Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/ps When using the procfs for extracting process informat...



details:   https://anonhg.NetBSD.org/src/rev/696a8b396fb5
branches:  trunk
changeset: 477213:696a8b396fb5
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Fri Oct 15 19:31:24 1999 +0000

description:
When using the procfs for extracting process information, extract
also process start time, process arguments and session leadership status.

The procfs fallback is also used when kvm_openfiles() completely fails
(e.g. when /dev/mem is not readable).

Solves PR 7772, though the final implementation is different.

diffstat:

 bin/ps/extern.h     |    5 +-
 bin/ps/print.c      |   25 ++++++++---
 bin/ps/procfs_ops.c |  115 ++++++++++++++++++++++++++++++++++++++++++++++-----
 bin/ps/ps.c         |   59 ++++++++++++++++++-------
 4 files changed, 166 insertions(+), 38 deletions(-)

diffs (truncated from 451 to 300 lines):

diff -r 4633ef5d3bf9 -r 696a8b396fb5 bin/ps/extern.h
--- a/bin/ps/extern.h   Fri Oct 15 17:17:07 1999 +0000
+++ b/bin/ps/extern.h   Fri Oct 15 19:31:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: extern.h,v 1.13 1999/03/26 22:36:02 bgrayson Exp $     */
+/*     $NetBSD: extern.h,v 1.14 1999/10/15 19:31:24 jdolecek Exp $     */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -68,7 +68,8 @@
 void    pnice __P((KINFO *, VARENT *));
 void    pri __P((KINFO *, VARENT *));
 void    printheader __P((void));
-struct kinfo_proc *     procfs_getprocs __P((int, int, int*));
+KINFO  *getkinfo_procfs __P((int, int, int*));
+char   **procfs_getargv __P((const struct kinfo_proc *, int));
 void    pvar __P((KINFO *, VARENT *));
 void    rssize __P((KINFO *, VARENT *));
 void    runame __P((KINFO *, VARENT *));
diff -r 4633ef5d3bf9 -r 696a8b396fb5 bin/ps/print.c
--- a/bin/ps/print.c    Fri Oct 15 17:17:07 1999 +0000
+++ b/bin/ps/print.c    Fri Oct 15 19:31:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: print.c,v 1.44 1999/10/11 09:18:09 mrg Exp $   */
+/*     $NetBSD: print.c,v 1.45 1999/10/15 19:31:24 jdolecek Exp $      */
 
 /*-
  * Copyright (c) 1990, 1993, 1994
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)print.c    8.6 (Berkeley) 4/16/94";
 #else
-__RCSID("$NetBSD: print.c,v 1.44 1999/10/11 09:18:09 mrg Exp $");
+__RCSID("$NetBSD: print.c,v 1.45 1999/10/15 19:31:24 jdolecek Exp $");
 #endif
 #endif /* not lint */
 
@@ -68,7 +68,7 @@
 #include "ps.h"
 
 extern kvm_t *kd;
-extern int needenv, needcomm, commandonly;
+extern int needenv, needcomm, commandonly, dontuseprocfs;
 
 static char *cmdpart __P((char *));
 static void  printval __P((char *, VAR *));
@@ -144,6 +144,7 @@
 {
        VAR *v;
        int left;
+       static int use_procfs=0;
        char **argv, **p, *name;
 
        v = ve->var;
@@ -156,7 +157,7 @@
                        left = v->width;
        } else
                left = -1;
-       if (needenv) {
+       if (needenv && kd) {
                argv = kvm_getenvv(kd, ki->ki_p, termwidth);
                if ((p = argv) != NULL) {
                        while (*p) {
@@ -169,7 +170,13 @@
        if (needcomm) {
                name = KI_PROC(ki)->p_comm;
                if (!commandonly) {
-                       argv = kvm_getargv(kd, ki->ki_p, termwidth);
+                       argv = NULL;
+                       if (kd && !use_procfs)
+                               argv = kvm_getargv(kd, ki->ki_p, termwidth);
+                       if (argv == NULL && !dontuseprocfs) {
+                               argv = procfs_getargv(ki->ki_p, termwidth);
+                               use_procfs = 1;
+                       }
                        if ((p = argv) != NULL) {
                                while (*p) {
                                        fmt_puts(*p, &left);
@@ -182,6 +189,10 @@
                                fmt_puts(name, &left);
                                fmt_putc(')', &left);
                        }
+                       if (use_procfs) {
+                               free(argv[0]);
+                               free(argv);
+                       }
                } else {
                        fmt_puts(name, &left);
                }
@@ -549,7 +560,7 @@
        static int failure;
 
        if (!nlistread)
-               failure = donlist();
+               failure = (kd) ? donlist() : 1;
        if (failure)
                return (0.0);
 
@@ -588,7 +599,7 @@
        int szptudot;
 
        if (!nlistread)
-               failure = donlist();
+               failure = (kd) ? donlist() : 1;
        if (failure)
                return (0.0);
 
diff -r 4633ef5d3bf9 -r 696a8b396fb5 bin/ps/procfs_ops.c
--- a/bin/ps/procfs_ops.c       Fri Oct 15 17:17:07 1999 +0000
+++ b/bin/ps/procfs_ops.c       Fri Oct 15 19:31:24 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: procfs_ops.c,v 1.5 1999/05/09 19:23:38 thorpej Exp $   */
+/*     $NetBSD: procfs_ops.c,v 1.6 1999/10/15 19:31:25 jdolecek Exp $  */
 
 /*
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -42,6 +42,7 @@
 #include <sys/sysctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/resource.h> /* for rusage */
 
 #include <fcntl.h>
 #include <dirent.h>
@@ -52,6 +53,8 @@
 #include <err.h>
 #include <kvm.h>
 
+#include "ps.h"
+
 /* Assume that no process status file will ever be larger than this. */
 #define STATUS_SIZE    8192
 
@@ -70,8 +73,7 @@
 }
 
 static int verify_procfs_fd __P((int, const char *));
-static int parsekinfo __P((const char *, struct kinfo_proc *));
-struct kinfo_proc *procfs_getprocs __P((int, int, int *));
+static int parsekinfo __P((const char *, KINFO *));
 
 static int
 verify_procfs_fd(fd, path)
@@ -97,15 +99,16 @@
 }
 
 static int
-parsekinfo(path, kp)
+parsekinfo(path, ki)
        const char *path;
-       struct kinfo_proc *kp;
+       KINFO *ki;
 {
        char    fullpath[MAXPATHLEN];
        int     dirfd, fd, nbytes, devmajor, devminor;
        struct timeval usertime, systime, starttime;
        char    buff[STATUS_SIZE];
        char    flagstr[256];
+       struct kinfo_proc *kp = ki->ki_p;
 
        /*
         * Verify that /proc/<pid> is a procfs file (and that no one has
@@ -131,7 +134,6 @@
                 * Don't print warning, as the process may have died since our
                 * scan of the directory entries.
                 */
-               close(fd);
                return -1;      /* Process may no longer exist. */
        }
 
@@ -174,6 +176,14 @@
        kp->kp_proc.p_rtime.tv_sec = usertime.tv_sec + systime.tv_sec;
        kp->kp_proc.p_rtime.tv_usec = usertime.tv_usec + systime.tv_usec;
 
+       /* if starttime.[u]sec is != -1, it's in-memory process */
+       if (starttime.tv_sec != -1 && starttime.tv_usec != -1) {
+               kp->kp_proc.p_flag |= P_INMEM;
+               ki->ki_u.u_valid = 1;
+               ki->ki_u.u_start.tv_sec = starttime.tv_sec;
+               ki->ki_u.u_start.tv_usec = starttime.tv_usec;
+       }
+
        /*
         * CPU time isn't shown unless the ki_u.u_valid flag is set.
         * Unfortunately, we don't have access to that here.
@@ -183,11 +193,15 @@
        if (strstr(flagstr, "ctty"))
                kp->kp_proc.p_flag |= P_CONTROLT;
 
+       /* Set the flag for whether or not this process is session leader */
+       if (strstr(flagstr, "sldr"))
+               kp->kp_eproc.e_flag |= EPROC_SLEADER;
+
        return 0;
 }
 
-struct kinfo_proc *
-procfs_getprocs(op, arg, cnt)
+KINFO *
+getkinfo_procfs(op, arg, cnt)
        int     op, arg;
        int    *cnt;
 {
@@ -195,6 +209,7 @@
        int     procdirfd, nbytes, knum = 0, maxknum = 0;
        char   *direntbuff;
        struct kinfo_proc *kp;
+       KINFO   *ki;
        int     mib[4];
        size_t  len;
        struct statfs procfsstat;
@@ -250,8 +265,8 @@
                err(1, "sysctl to fetch maxproc");
        maxknum *= 2;           /* Double it, to be really paranoid.  */
 
-       kp = (struct kinfo_proc *) malloc(sizeof(struct kinfo_proc) * maxknum);
-       memset(kp, 0, sizeof(struct kinfo_proc) * maxknum);
+       kp = (struct kinfo_proc *) calloc(sizeof(struct kinfo_proc)*maxknum, 1);
+       ki = (KINFO *) calloc(sizeof(KINFO)*maxknum, 1);
 
        /* Read in a batch of entries at a time.  */
        while ((knum < maxknum) &&
@@ -268,7 +283,8 @@
                                continue;
                        if (strcmp(dp->d_name, "curproc") == 0)
                                continue;
-                       if (parsekinfo(dp->d_name, &kp[knum]) != 0)
+                       ki[knum].ki_p = &kp[knum];
+                       if (parsekinfo(dp->d_name, &ki[knum]) != 0)
                                continue;
                        /*
                         * Now check some of the flags.  If the newest entry
@@ -323,5 +339,80 @@
 
        *cnt = knum;
        close(procdirfd);
-       return kp;
+       /* free unused memory */
+       if (knum < maxknum) {
+               kp = realloc(kp, sizeof(*kp) * knum);
+               ki = realloc(ki, sizeof(*ki) * knum);
+               for(; knum >= 0; knum--)
+                       ki[knum].ki_p = &kp[knum];
+       }
+       return ki;
 }
+
+/*
+ * return process arguments, possibly ones used when exec()ing
+ * the process; return the array as two element array, first is
+ * argv[0], second element is all the other args separated by spaces
+ */
+char **
+procfs_getargv(kp, nchr)
+       const struct kinfo_proc *kp;
+       int nchr;
+{
+       char    fullpath[MAXPATHLEN], *buf, *name, *args, **argv;
+       int fd, num;
+       ssize_t len;
+       size_t idx;
+
+       /* Open /proc/<pid>/cmdline, and parse it into the argv array */
+       snprintf(fullpath, MAXPATHLEN, "/proc/%d/cmdline", kp->kp_proc.p_pid);
+       fd = open(fullpath, O_RDONLY, 0);
+       if (fd == -1 || verify_procfs_fd(fd, fullpath)) {
+               /*
+                * Don't print warning, as the process may have died since our
+                * scan of the directory entries.
+                */
+               return NULL;    /* Process may no longer exist. */
+       }
+
+       buf = (char *)malloc(nchr+1);
+       len = read(fd, buf, nchr);
+       close(fd);
+       if (len == -1) {
+               warnx("procfs_getargv");
+               return NULL;
+       }
+       
+       num = 1;
+       args = NULL;
+       name = buf;
+       /* substitute any \0's with space */
+       for(idx=0; idx < len; idx++) {
+               if (buf[idx] == '\0') {
+                       if (!args)
+                               args = &buf[idx+1];
+                       else
+                               buf[idx] = ' ';
+                       num++;
+               }
+       }
+       buf[len] = '\0'; /* end the string */
+
+       /* if the name is the same as the p_comm, just enclosed
+        * in parentheses, remove the parentheses */
+       if (num == 1 && name[0] == '(' && name[len-1] == ')'
+               && strncmp(name+1, kp->kp_proc.p_comm, len-2) == 0)



Home | Main Index | Thread Index | Old Index