diff options
author | gad <gad@FreeBSD.org> | 2004-03-17 22:46:58 +0000 |
---|---|---|
committer | gad <gad@FreeBSD.org> | 2004-03-17 22:46:58 +0000 |
commit | 5091cee4e6b00274b99c80c60ca89b1bd7f41e08 (patch) | |
tree | fb9de08362c8eb0e7bc9290227abffba878261f2 /bin/ps | |
parent | 436fe9bbc1dd12e4651d30356928ac1a8d427448 (diff) | |
download | FreeBSD-src-5091cee4e6b00274b99c80c60ca89b1bd7f41e08.zip FreeBSD-src-5091cee4e6b00274b99c80c60ca89b1bd7f41e08.tar.gz |
Improvements to 'ps -p <x>'. If <x> is a process id that does not exist, then
just print the header (if any) and exit, thus matching the behavior on -stable
and other OS's.
Also adds support for <x> being a comma-separated list of processes, and does
a much better checking for invalid-values of <x>, such as 'ps -p someword'.
Reviewed by: mentioned on freebsd-current
MFC after: 10 days
Diffstat (limited to 'bin/ps')
-rw-r--r-- | bin/ps/ps.1 | 7 | ||||
-rw-r--r-- | bin/ps/ps.c | 118 |
2 files changed, 104 insertions, 21 deletions
diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 8b552cc..a6bd751 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -45,7 +45,10 @@ .Op Fl N Ar system .Op Fl O Ar fmt .Op Fl o Ar fmt -.Op Fl p Ar pid +.Oo Fl p Ar pid Ns Xo +.Op , Ns Ar pid Ns No ... +.Xc +.Oc .Op Fl t Ar tty .Oo Fl U Ar username Ns Xo .Op , Ns Ar username Ns No ... @@ -146,7 +149,7 @@ This causes the printed header to use the specified string instead of the standard header. .It Fl p Display information associated with the specified process -.Tn ID . +.Tn ID(s) . .It Fl r Sort by current cpu usage, instead of by process .Tn ID . diff --git a/bin/ps/ps.c b/bin/ps/ps.c index 0bf39c0..d458d46 100644 --- a/bin/ps/ps.c +++ b/bin/ps/ps.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <ctype.h> #include <err.h> +#include <errno.h> #include <fcntl.h> #include <kvm.h> #include <limits.h> @@ -99,6 +100,7 @@ static void scanvars(void); static void dynsizevars(KINFO *); static void sizevars(void); static void usage(void); +static pid_t *getpids(const char *, int *); static uid_t *getuids(const char *, int *); static char dfmt[] = "pid,tt,state,time,command"; @@ -125,10 +127,10 @@ main(int argc, char *argv[]) struct varent *vent; struct winsize ws; dev_t ttydev; - pid_t pid; + pid_t *pids; uid_t *uids; int all, ch, flag, i, _fmt, lineno, nentries, nocludge, dropgid; - int prtheader, wflag, what, xflg, uid, nuids, showthreads; + int prtheader, wflag, what, xflg, pid, uid, npids, nuids, showthreads; char *cols; char errbuf[_POSIX2_LINE_MAX]; const char *cp, *nlistf, *memf; @@ -168,9 +170,8 @@ main(int argc, char *argv[]) } all = _fmt = prtheader = wflag = xflg = 0; - pid = -1; - nuids = 0; - uids = NULL; + npids = nuids = 0; + pids = uids = NULL; ttydev = NODEV; dropgid = 0; memf = nlistf = _PATH_DEVNULL; @@ -239,7 +240,7 @@ main(int argc, char *argv[]) break; #endif case 'p': - pid = atol(optarg); + pids = getpids(optarg, &npids); xflg = 1; break; case 'r': @@ -333,7 +334,7 @@ main(int argc, char *argv[]) parsefmt(dfmt, 0); /* XXX - should be cleaner */ - if (!all && ttydev == NODEV && pid == -1 && !nuids) { + if (!all && ttydev == NODEV && !npids && !nuids) { if ((uids = malloc(sizeof (*uids))) == NULL) errx(1, "malloc failed"); nuids = 1; @@ -354,9 +355,9 @@ main(int argc, char *argv[]) } else if (ttydev != NODEV) { what = KERN_PROC_TTY | showthreads; flag = ttydev; - } else if (pid != -1) { + } else if (npids == 1) { what = KERN_PROC_PID | showthreads; - flag = pid; + flag = *pids; } else { what = showthreads != 0 ? KERN_PROC_ALL : KERN_PROC_PROC; flag = 0; @@ -365,15 +366,18 @@ main(int argc, char *argv[]) /* * select procs */ - if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0 || nentries < 0) + kp = kvm_getprocs(kd, what, flag, &nentries); + if ((kp == 0 && nentries != 0) || nentries < 0) errx(1, "%s", kvm_geterr(kd)); - if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) - errx(1, "malloc failed"); - for (i = nentries; --i >= 0; ++kp) { - kinfo[i].ki_p = kp; - if (needuser) - saveuser(&kinfo[i]); - dynsizevars(&kinfo[i]); + if (nentries > 0) { + if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) + errx(1, "malloc failed"); + for (i = nentries; --i >= 0; ++kp) { + kinfo[i].ki_p = kp; + if (needuser) + saveuser(&kinfo[i]); + dynsizevars(&kinfo[i]); + } } sizevars(); @@ -395,6 +399,13 @@ main(int argc, char *argv[]) if (xflg == 0 && ((&kinfo[i])->ki_p->ki_tdev == NODEV || ((&kinfo[i])->ki_p->ki_flag & P_CONTROLT ) == 0)) continue; + if (npids > 1) { + for (pid = 0; pid < npids; pid++) + if ((&kinfo[i])->ki_p->ki_pid == pids[pid]) + break; + if (pid == npids) + continue; + } if (nuids > 1) { for (uid = 0; uid < nuids; uid++) if ((&kinfo[i])->ki_p->ki_uid == uids[uid]) @@ -419,6 +430,75 @@ main(int argc, char *argv[]) exit(eval); } +#define BSD_PID_MAX 99999 /* Copy of PID_MAX from sys/proc.h */ +pid_t * +getpids(const char *arg, int *npids) +{ + char copyarg[32]; + char *copyp, *endp; + pid_t *pids, *morepids; + int alloc; + long tempid; + + alloc = 0; + *npids = 0; + pids = NULL; + while (*arg != '\0') { + while (*arg != '\0' && strchr(SEP, *arg) != NULL) + arg++; + if (*arg == '\0' || strchr(SEP, *arg) != NULL) + tempid = 0; + else { + copyp = copyarg; + endp = copyarg + sizeof(copyarg) - 1; + while (*arg != '\0' && strchr(SEP, *arg) == NULL && + copyp <= endp) + *copyp++ = *arg++; + if (copyp > endp) { + *endp = '\0'; + tempid = -1; + while (*arg != '\0' && + strchr(SEP, *arg) == NULL) + arg++; + } else { + *copyp = '\0'; + errno = 0; + tempid = strtol(copyarg, &endp, 10); + } + /* + * Write warning messages for any values which + * would never be a valid process number. + */ + if (*endp != '\0' || tempid < 0 || copyarg == endp) { + warnx("invalid process number: %s", copyarg); + errno = ERANGE; + } else if (errno != 0 || tempid > BSD_PID_MAX) { + warnx("process number too large: %s", copyarg); + errno = ERANGE; + } + if (errno == ERANGE) { + /* Ignore this value from the given list. */ + continue; + } + } + if (*npids >= alloc) { + alloc = (alloc + 1) << 1; + morepids = realloc(pids, alloc * sizeof (*pids)); + if (morepids == NULL) { + free(pids); + errx(1, "realloc failed"); + } + pids = morepids; + } + pids[(*npids)++] = tempid; + } + + if (!*npids) + errx(1, "No valid process numbers specified"); + + return (pids); +} + uid_t * getuids(const char *arg, int *nuids) { @@ -669,8 +749,8 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n%s\n", - "usage: ps [-aCHhjlmrSTuvwxZ] [-O|o fmt] [-p pid] [-t tty] [-U user]", - " [-M core] [-N system]", + "usage: ps [-aCHhjlmrSTuvwxZ] [-O|o fmt] [-p pid[,pid]] [-t tty]", + " [-U user[,user]] [-M core] [-N system]", " ps [-L]"); exit(1); } |