summaryrefslogtreecommitdiffstats
path: root/bin/ps
diff options
context:
space:
mode:
authorgad <gad@FreeBSD.org>2004-03-17 22:46:58 +0000
committergad <gad@FreeBSD.org>2004-03-17 22:46:58 +0000
commit5091cee4e6b00274b99c80c60ca89b1bd7f41e08 (patch)
treefb9de08362c8eb0e7bc9290227abffba878261f2 /bin/ps
parent436fe9bbc1dd12e4651d30356928ac1a8d427448 (diff)
downloadFreeBSD-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.17
-rw-r--r--bin/ps/ps.c118
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);
}
OpenPOWER on IntegriCloud