summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>2000-12-18 18:44:29 +0000
committerNiels Provos <provos@cvs.openbsd.org>2000-12-18 18:44:29 +0000
commit0171e311acfbf8b50971f7281bf2902ba1a41bcf (patch)
tree152f825c22ee1f7a3a8a1aab45ed4a029890faa6
parenta8b6aa5f5bccdf6c3cb36f5284aabe4c8ccad225 (diff)
calculate length and allocate buffer for status. work by deraadt@ and me
-rw-r--r--sys/miscfs/procfs/procfs_status.c145
1 files changed, 92 insertions, 53 deletions
diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c
index 9d2357cb4b5..5865eb0956f 100644
--- a/sys/miscfs/procfs/procfs_status.c
+++ b/sys/miscfs/procfs/procfs_status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: procfs_status.c,v 1.3 1997/12/30 01:33:14 deraadt Exp $ */
+/* $OpenBSD: procfs_status.c,v 1.4 2000/12/18 18:44:28 provos Exp $ */
/* $NetBSD: procfs_status.c,v 1.11 1996/03/16 23:52:50 christos Exp $ */
/*
@@ -44,6 +44,7 @@
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/ioctl.h>
@@ -52,26 +53,31 @@
#include <sys/resourcevar.h>
#include <miscfs/procfs/procfs.h>
+int procfs_stat_gen(struct proc *, char *s, int);
+
+#define COUNTORCAT(s, l, ps, n) do { \
+ if (s) \
+ strlcat(s, ps, l); \
+ else \
+ n += strlen(ps); \
+ } while (0)
+
+/* Generates:
+ * comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg uid gid groups
+ */
int
-procfs_dostatus(curp, p, pfs, uio)
- struct proc *curp;
+procfs_stat_gen(p, s, l)
struct proc *p;
- struct pfsnode *pfs;
- struct uio *uio;
+ char *s;
+ int l;
{
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);
+ struct timeval ut, st;
+ char ps[256], *sep;
+ int i, n;
pid = p->p_pid;
ppid = p->p_pptr ? p->p_pptr->p_pid : 0;
@@ -79,68 +85,101 @@ procfs_dostatus(curp, p, pfs, uio)
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 gid groups ... */
+ n = 0;
+ if (s)
+ bzero(s, l);
- ps = psbuf;
- bcopy(p->p_comm, ps, MAXCOMLEN);
+ bcopy(p->p_comm, ps, MAXCOMLEN-1);
ps[MAXCOMLEN] = '\0';
- ps += strlen(ps);
- ps += sprintf(ps, " %d %d %d %d ", pid, ppid, pgid, sid);
+ COUNTORCAT(s, l, ps, n);
+
+ (void) snprintf(ps, sizeof(ps), " %d %d %d %d ",
+ pid, ppid, pgid, sid);
+ COUNTORCAT(s, l, ps, n);
if ((p->p_flag&P_CONTROLT) && (tp = sess->s_ttyp))
- ps += sprintf(ps, "%d,%d ", major(tp->t_dev), minor(tp->t_dev));
+ snprintf(ps, sizeof(ps), "%d,%d ",
+ major(tp->t_dev), minor(tp->t_dev));
else
- ps += sprintf(ps, "%d,%d ", -1, -1);
+ snprintf(ps, sizeof(ps), "%d,%d ",
+ -1, -1);
+ COUNTORCAT(s, l, ps, n);
sep = "";
if (sess->s_ttyvp) {
- ps += sprintf(ps, "%sctty", sep);
+ snprintf(ps, sizeof(ps), "%sctty", sep);
sep = ",";
}
+ COUNTORCAT(s, l, ps, n);
+
if (SESS_LEADER(p)) {
- ps += sprintf(ps, "%ssldr", sep);
+ snprintf(ps, sizeof(ps), "%ssldr", sep);
sep = ",";
}
+ COUNTORCAT(s, l, ps, n);
+
if (*sep != ',')
- ps += sprintf(ps, "noflags");
+ snprintf(ps, sizeof(ps), "noflags");
+ COUNTORCAT(s, l, ps, n);
if (p->p_flag & P_INMEM)
- ps += sprintf(ps, " %ld,%ld",
- p->p_stats->p_start.tv_sec,
- p->p_stats->p_start.tv_usec);
+ snprintf(ps, sizeof(ps), " %ld,%ld",
+ 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, " %ld,%ld %ld,%ld",
- ut.tv_sec,
- ut.tv_usec,
- st.tv_sec,
- st.tv_usec);
- }
+ snprintf(ps, sizeof(ps), " -1,-1");
+ COUNTORCAT(s, l, ps, n);
+
+ calcru(p, &ut, &st, (void *) 0);
+ snprintf(ps, sizeof(ps), " %ld,%ld %ld,%ld",
+ ut.tv_sec, ut.tv_usec, st.tv_sec, st.tv_usec);
+ COUNTORCAT(s, l, ps, n);
- ps += sprintf(ps, " %s",
- (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "nochan");
+ snprintf(ps, sizeof(ps), " %s",
+ (p->p_wchan && p->p_wmesg) ? p->p_wmesg : "nochan");
+ COUNTORCAT(s, l, ps, n);
cr = p->p_ucred;
- ps += sprintf(ps, " %d", cr->cr_uid);
- ps += sprintf(ps, " %d", 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 = imin(xlen, uio->uio_resid);
- if (xlen <= 0)
+ snprintf(ps, sizeof(ps), " %u, %u", cr->cr_uid, cr->cr_gid);
+ COUNTORCAT(s, l, ps, n);
+ for (i = 0; i < cr->cr_ngroups; i++) {
+ snprintf(ps, sizeof(ps), ",%u", cr->cr_groups[i]);
+ COUNTORCAT(s, l, ps, n);
+ }
+
+ snprintf(ps, sizeof(ps), "\n");
+ COUNTORCAT(s, l, ps, n);
+
+ return (s != NULL ? strlen(s) + 1 : n + 1);
+}
+
+int
+procfs_dostatus(curp, p, pfs, uio)
+ struct proc *curp;
+ struct proc *p;
+ struct pfsnode *pfs;
+ struct uio *uio;
+{
+ char *ps;
+ int error, len;
+
+ if (uio->uio_rw != UIO_READ)
+ return (EOPNOTSUPP);
+
+ len = procfs_stat_gen(p, NULL, 0);
+ ps = malloc(len, M_TEMP, M_WAITOK);
+ if (!ps)
+ return (ENOMEM);
+ (void) procfs_stat_gen(p, ps, len);
+
+ len -= uio->uio_offset;
+ len = imin(len, uio->uio_resid);
+ if (len <= 0)
error = 0;
else
- error = uiomove(ps, xlen, uio);
+ error = uiomove(ps + uio->uio_offset, len, uio);
+ free(ps, M_TEMP);
return (error);
}
+