date and time created 94/01/05 12:34:11 by pendry
authorJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Thu, 6 Jan 1994 04:34:11 +0000 (20:34 -0800)
committerJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Thu, 6 Jan 1994 04:34:11 +0000 (20:34 -0800)
SCCS-vsn: sys/miscfs/procfs/procfs_regs.c 8.1
SCCS-vsn: sys/miscfs/procfs/procfs_status.c 8.1
SCCS-vsn: sys/miscfs/procfs/procfs_subr.c 8.1

usr/src/sys/miscfs/procfs/procfs_regs.c [new file with mode: 0644]
usr/src/sys/miscfs/procfs/procfs_status.c [new file with mode: 0644]
usr/src/sys/miscfs/procfs/procfs_subr.c [new file with mode: 0644]

diff --git a/usr/src/sys/miscfs/procfs/procfs_regs.c b/usr/src/sys/miscfs/procfs/procfs_regs.c
new file mode 100644 (file)
index 0000000..eecb01f
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)procfs_regs.c       8.1 (Berkeley) %G%
+ *
+ * From:
+ *     $Id: procfs_regs.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <machine/reg.h>
+#include <miscfs/procfs/procfs.h>
+
+int
+procfs_doregs(curp, p, pfs, uio)
+       struct proc *curp;
+       struct proc *p;
+       struct pfsnode *pfs;
+       struct uio *uio;
+{
+       int error;
+       struct reg r;
+       char *kv;
+       int kl;
+
+       kl = sizeof(r);
+       kv = (char *) &r;
+
+       kv += uio->uio_offset;
+       kl -= uio->uio_offset;
+       if (kl > uio->uio_resid)
+               kl = uio->uio_resid;
+
+       if (kl < 0)
+               error = EINVAL;
+       else
+               error = procfs_read_regs(p, &r);
+       if (error == 0)
+               error = uiomove(kv, kl, uio);
+       if (error == 0 && uio->uio_rw == UIO_WRITE) {
+               if (p->p_stat != SSTOP)
+                       error = EBUSY;
+               else
+                       error = procfs_write_regs(p, &r);
+       }
+
+       uio->uio_offset = 0;
+       return (error);
+}
diff --git a/usr/src/sys/miscfs/procfs/procfs_status.c b/usr/src/sys/miscfs/procfs/procfs_status.c
new file mode 100644 (file)
index 0000000..2db5664
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)procfs_status.c     8.1 (Berkeley) %G%
+ *
+ * From:
+ *     $Id: procfs_status.c,v 3.1 1993/12/15 09:40:17 jsp Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <miscfs/procfs/procfs.h>
+
+int
+procfs_dostatus(curp, p, pfs, uio)
+       struct proc *curp;
+       struct proc *p;
+       struct pfsnode *pfs;
+       struct uio *uio;
+{
+       struct session *sess;
+       struct tty *tp;
+       struct ucred *cr;
+       char *ps;
+       char *sep;
+       int pid, ppid, pgid, sid;
+       int i;
+       int xlen;
+       int error;
+       char psbuf[256];                /* XXX - conservative */
+
+       if (uio->uio_rw != UIO_READ)
+               return (EOPNOTSUPP);
+
+       pid = p->p_pid;
+       ppid = p->p_pptr ? p->p_pptr->p_pid : 0,
+       pgid = p->p_pgrp->pg_id;
+       sess = p->p_pgrp->pg_session;
+       sid = sess->s_leader ? sess->s_leader->p_pid : 0;
+
+/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg uid groups ... */
+
+       ps = psbuf;
+       bcopy(p->p_comm, ps, MAXCOMLEN);
+       ps[MAXCOMLEN] = '\0';
+       ps += strlen(ps);
+       ps += sprintf(ps, " %d %d %d %d ", pid, ppid, pgid, sid);
+
+       if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
+               ps += sprintf(ps, "%d,%d ", major(tp->t_dev), minor(tp->t_dev));
+       else
+               ps += sprintf(ps, "%d,%d ", -1, -1);
+
+       sep = "";
+       if (sess->s_ttyvp) {
+               ps += sprintf(ps, "%sctty", sep);
+               sep = ",";
+       }
+       if (SESS_LEADER(p)) {
+               ps += sprintf(ps, "%ssldr", sep);
+               sep = ",";
+       }
+       if (*sep != ',')
+               ps += sprintf(ps, "noflags");
+
+       if (p->p_flag & P_INMEM)
+               ps += sprintf(ps, " %d %d",
+                       p->p_stats->p_start.tv_sec,
+                       p->p_stats->p_start.tv_usec);
+       else
+               ps += sprintf(ps, " -1 -1");
+       
+       {
+               struct timeval ut, st;
+
+               calcru(p, &ut, &st, (void *) 0);
+               ps += sprintf(ps, " %d %d %d %d",
+                       ut.tv_sec,
+                       ut.tv_usec,
+                       st.tv_sec,
+                       st.tv_usec);
+       }
+
+       ps += sprintf(ps, " %s",
+               (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "nochan");
+
+       cr = p->p_ucred;
+
+       ps += sprintf(ps, " %d %d", cr->cr_uid, cr->cr_gid);
+       for (i = 0; i < cr->cr_ngroups; i++)
+               ps += sprintf(ps, " %d", cr->cr_groups[i]);
+       ps += sprintf(ps, "\n");
+
+       xlen = ps - psbuf;
+       xlen -= uio->uio_offset;
+       ps = psbuf + uio->uio_offset;
+       xlen = min(xlen, uio->uio_resid);
+       if (xlen <= 0)
+               error = 0;
+       else
+               error = uiomove(ps, xlen, uio);
+
+       return (error);
+}
diff --git a/usr/src/sys/miscfs/procfs/procfs_subr.c b/usr/src/sys/miscfs/procfs/procfs_subr.c
new file mode 100644 (file)
index 0000000..5b1a2f4
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)procfs_subr.c       8.1 (Berkeley) %G%
+ *
+ * From:
+ *     $Id: procfs_subr.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <miscfs/procfs/procfs.h>
+
+static struct pfsnode *pfshead;
+static int pfsvplock;
+
+/*
+ * allocate a pfsnode/vnode pair.  the vnode is
+ * referenced, but not locked.
+ *
+ * the pid, pfs_type, and mount point uniquely
+ * identify a pfsnode.  the mount point is needed
+ * because someone might mount this filesystem
+ * twice.
+ *
+ * all pfsnodes are maintained on a singly-linked
+ * list.  new nodes are only allocated when they cannot
+ * be found on this list.  entries on the list are
+ * removed when the vfs reclaim entry is called.
+ *
+ * a single lock is kept for the entire list.  this is
+ * needed because the getnewvnode() function can block
+ * waiting for a vnode to become free, in which case there
+ * may be more than one process trying to get the same
+ * vnode.  this lock is only taken if we are going to
+ * call getnewvnode, since the kernel itself is single-threaded.
+ *
+ * if an entry is found on the list, then call vget() to
+ * take a reference.  this is done because there may be
+ * zero references to it and so it needs to removed from
+ * the vnode free list.
+ */
+int
+procfs_allocvp(mp, vpp, pid, pfs_type)
+       struct mount *mp;
+       struct vnode **vpp;
+       long pid;
+       pfstype pfs_type;
+{
+       int error;
+       struct pfsnode *pfs;
+       struct pfsnode **pp;
+
+loop:
+       for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) {
+               if (pfs->pfs_pid == pid &&
+                   pfs->pfs_type == pfs_type &&
+                   PFSTOV(pfs)->v_mount == mp) {
+                       if (vget(pfs->pfs_vnode, 1))
+                               goto loop;
+                       VOP_UNLOCK(pfs->pfs_vnode);
+                       *vpp = pfs->pfs_vnode;
+                       return (0);
+               }
+       }
+
+       /*
+        * otherwise lock the vp list while we call getnewvnode
+        * since that can block.
+        */ 
+       if (pfsvplock & PROCFS_LOCKED) {
+               pfsvplock |= PROCFS_WANT;
+               sleep((caddr_t) &pfsvplock, PINOD);
+               goto loop;
+       }
+       pfsvplock |= PROCFS_LOCKED;
+
+       error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp);
+       if (error)
+               goto out;
+
+       MALLOC((*vpp)->v_data, void *, sizeof(struct pfsnode),
+               M_TEMP, M_WAITOK);
+
+       pfs = VTOPFS(*vpp);
+       pfs->pfs_next = 0;
+       pfs->pfs_pid = (pid_t) pid;
+       pfs->pfs_type = pfs_type;
+       pfs->pfs_vnode = *vpp;
+       pfs->pfs_flags = 0;
+       pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type);
+
+       switch (pfs_type) {
+       case Proot:     /* /proc = dr-xr-xr-x */
+               pfs->pfs_mode = (VREAD|VEXEC) |
+                               (VREAD|VEXEC) >> 3 |
+                               (VREAD|VEXEC) >> 6;
+               break;
+
+       case Pproc:
+               pfs->pfs_mode = (VREAD|VEXEC) |
+                               (VREAD|VEXEC) >> 3 |
+                               (VREAD|VEXEC) >> 6;
+               break;
+
+       case Pfile:
+               pfs->pfs_mode = (VREAD|VWRITE);
+               break;
+
+       case Pmem:
+               pfs->pfs_mode = (VREAD|VWRITE);
+               break;
+
+       case Pregs:
+               pfs->pfs_mode = (VREAD|VWRITE);
+               break;
+
+       case Pctl:
+               pfs->pfs_mode = (VWRITE);
+               break;
+
+       case Pstatus:
+               pfs->pfs_mode = (VREAD) |
+                               (VREAD >> 3) |
+                               (VREAD >> 6);
+               break;
+
+       case Pnote:
+               pfs->pfs_mode = (VWRITE);
+               break;
+
+       case Pnotepg:
+               pfs->pfs_mode = (VWRITE);
+               break;
+
+       default:
+               panic("procfs_allocvp");
+       }
+
+       /* add to procfs vnode list */
+       for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next)
+               continue;
+       *pp = pfs;
+
+out:
+       pfsvplock &= ~PROCFS_LOCKED;
+
+       if (pfsvplock & PROCFS_WANT) {
+               pfsvplock &= ~PROCFS_WANT;
+               wakeup((caddr_t) &pfsvplock);
+       }
+
+       return (error);
+}
+
+int
+procfs_freevp(vp)
+       struct vnode *vp;
+{
+       struct pfsnode **pfspp;
+       struct pfsnode *pfs = VTOPFS(vp);
+
+       for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) {
+               if (*pfspp == pfs) {
+                       *pfspp = pfs->pfs_next;
+                       break;
+               }
+       }
+
+       FREE(vp->v_data, M_TEMP);
+       vp->v_data = 0;
+       return (0);
+}
+
+int
+procfs_rw(ap)
+       struct vop_read_args *ap;
+{
+       struct vnode *vp = ap->a_vp;
+       struct uio *uio = ap->a_uio;
+       struct proc *curp = uio->uio_procp;
+       struct pfsnode *pfs = VTOPFS(vp);
+       struct proc *p;
+
+       p = PFIND(pfs->pfs_pid);
+       if (p == 0)
+               return (EINVAL);
+
+       switch (pfs->pfs_type) {
+       case Pnote:
+       case Pnotepg:
+               return (procfs_donote(curp, p, pfs, uio));
+
+       case Pregs:
+               return (procfs_doregs(curp, p, pfs, uio));
+
+       case Pctl:
+               return (procfs_doctl(curp, p, pfs, uio));
+
+       case Pstatus:
+               return (procfs_dostatus(curp, p, pfs, uio));
+
+       case Pmem:
+               return (procfs_domem(curp, p, pfs, uio));
+
+       default:
+               return (EOPNOTSUPP);
+       }
+}
+
+/*
+ * Get a string from userland into (buf).  Strip a trailing
+ * nl character (to allow easy access from the shell).
+ * The buffer should be *buflenp + 1 chars long.  vfs_getuserstr
+ * will automatically add a nul char at the end.
+ *
+ * Returns 0 on success or the following errors
+ *
+ * EINVAL:    file offset is non-zero.
+ * EMSGSIZE:  message is longer than kernel buffer
+ * EFAULT:    user i/o buffer is not addressable
+ */
+int
+vfs_getuserstr(uio, buf, buflenp)
+       struct uio *uio;
+       char *buf;
+       int *buflenp;
+{
+       int xlen;
+       int error;
+
+       if (uio->uio_offset != 0)
+               return (EINVAL);
+
+       xlen = *buflenp;
+
+       /* must be able to read the whole string in one go */
+       if (xlen < uio->uio_resid)
+               return (EMSGSIZE);
+       xlen = uio->uio_resid;
+
+       error = uiomove(buf, xlen, uio);
+       if (error)
+               return (error);
+
+       /* allow multiple writes without seeks */
+       uio->uio_offset = 0;
+
+       /* cleanup string and remove trailing newline */
+       buf[xlen] = '\0';
+       xlen = strlen(buf);
+       if (xlen > 0 && buf[xlen-1] == '\n')
+               buf[--xlen] = '\0';
+       *buflenp = xlen;
+
+       return (0);
+}
+
+vfs_namemap_t *
+vfs_findname(nm, buf, buflen)
+       vfs_namemap_t *nm;
+       char *buf;
+       int buflen;
+{
+       for (; nm->nm_name; nm++)
+               if (bcmp(buf, (char *) nm->nm_name, buflen+1) == 0)
+                       return (nm);
+
+       return (0);
+}