diff options
Diffstat (limited to 'bin/ps')
| -rw-r--r-- | bin/ps/Makefile | 11 | ||||
| -rw-r--r-- | bin/ps/devname.c | 75 | ||||
| -rw-r--r-- | bin/ps/extern.h | 43 | ||||
| -rw-r--r-- | bin/ps/keyword.c | 357 | ||||
| -rw-r--r-- | bin/ps/nlist.c | 135 | ||||
| -rw-r--r-- | bin/ps/print.c | 600 | ||||
| -rw-r--r-- | bin/ps/ps.1 | 503 | ||||
| -rw-r--r-- | bin/ps/ps.c | 499 | ||||
| -rw-r--r-- | bin/ps/ps.h | 85 |
9 files changed, 2308 insertions, 0 deletions
diff --git a/bin/ps/Makefile b/bin/ps/Makefile new file mode 100644 index 000000000000..82a9c3a7a020 --- /dev/null +++ b/bin/ps/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 5.5 (Berkeley) 4/23/91 + +PROG= ps +SRCS= devname.c keyword.c nlist.c print.c ps.c +CFLAGS+=-I/sys +DPADD= ${LIBMATH} ${LIBUTIL} +LDADD= -lm -lutil +BINGRP= kmem +BINMODE=2555 + +.include <bsd.prog.mk> diff --git a/bin/ps/devname.c b/bin/ps/devname.c new file mode 100644 index 000000000000..5f2815d30b8f --- /dev/null +++ b/bin/ps/devname.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)devname.c 5.14 (Berkeley) 5/6/91"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <fcntl.h> +#include <db.h> +#include <stdio.h> +#include <paths.h> + +char * +devname(dev, type) + dev_t dev; + mode_t type; +{ + struct { + mode_t type; + dev_t dev; + } bkey; + static DB *db; + static int failure; + DBT data, key; + + if (!db && !failure && + !(db = dbopen(_PATH_DEVDB, O_RDONLY, 0, DB_HASH, NULL))) { + (void)fprintf(stderr, + "warning: no device database %s\n", _PATH_DEVDB); + failure = 1; + } + if (failure) + return("??"); + + /* + * Keys are a mode_t followed by a dev_t. The former is the type of + * the file (mode & S_IFMT), the latter is the st_rdev field. + */ + bkey.dev = dev; + bkey.type = type; + key.data = &bkey; + key.size = sizeof(bkey); + return((db->get)(db, &key, &data, 0L) ? "??" : (char *)data.data); +} diff --git a/bin/ps/extern.h b/bin/ps/extern.h new file mode 100644 index 000000000000..a6de5c909b0a --- /dev/null +++ b/bin/ps/extern.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 5.2 (Berkeley) 6/3/91 + */ + +#include <sys/cdefs.h> + +extern VAR var[]; +extern struct varent *vhead; + +__BEGIN_DECLS +void err __P((const char *, ...)); +__END_DECLS diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c new file mode 100644 index 000000000000..5776137c9c3d --- /dev/null +++ b/bin/ps/keyword.c @@ -0,0 +1,357 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)keyword.c 5.9 (Berkeley) 6/3/91"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/proc.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include "ps.h" + +#ifdef SPPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#include <sys/ucred.h> +#include <sys/kinfo_proc.h> +#endif + +int command(), cputime(), evar(), logname(), longtname(), lstarted(), + maxrss(), p_rssize(), pagein(), pcpu(), pmem(), pri(), pvar(), + rssize(), runame(), rvar(), started(), state(), tdev(), tname(), + tsize(), ucomm(), uname(), uvar(), vsize(), wchan(); +#ifndef NEWVM +int trss(); +#endif + +#ifdef NOTINUSE +int utime(), stime(), ixrss(), idrss(), isrss(); + {{"utime"}, "UTIME", USER, utime, 4}, + {{"stime"}, "STIME", USER, stime, 4}, + {{"ixrss"}, "IXRSS", USER, ixrss, 4}, + {{"idrss"}, "IDRSS", USER, idrss, 4}, + {{"isrss"}, "ISRSS", USER, isrss, 4}, +#endif + +/* Compute offset in common structures. */ +#define POFF(x) offsetof(struct proc, x) +#define EOFF(x) offsetof(struct eproc, x) +#define UOFF(x) offsetof(struct usave, x) +#define ROFF(x) offsetof(struct rusage, x) + +#define UIDFMT "u" +#define UIDLEN 5 +#define PIDFMT "d" +#define PIDLEN 5 +#define USERLEN 8 + +VAR var[] = { +#ifdef NEWVM + {"%cpu", "%CPU", NULL, 0, pcpu, 4}, + {"%mem", "%MEM", NULL, 0, pmem, 4}, + {"acflag", "ACFLG", NULL, 0, pvar, 3, POFF(p_acflag), SHORT, "x"}, + {"acflg", "", "acflag"}, + {"blocked", "", "sigmask"}, + {"caught", "", "sigcatch"}, + {"command", "COMMAND", NULL, COMM|LJUST, command, 16}, + {"cpu", "CPU", NULL, 0, pvar, 3, POFF(p_cpu), UCHAR, "d"}, + {"cputime", "", "time"}, + {"f", "F", NULL, 0, pvar, 7, POFF(p_flag), LONG, "x"}, + {"flags", "", "f"}, + {"ignored", "", "sigignore"}, + {"inblk", "INBLK", NULL, USER, rvar, 4, ROFF(ru_inblock), LONG, "d"}, + {"inblock", "", "inblk"}, + {"jobc", "JOBC", NULL, 0, evar, 4, EOFF(e_jobc), SHORT, "d"}, + {"ktrace", "KTRACE", NULL, 0, pvar, 8, POFF(p_traceflag), LONG, "x"}, + {"ktracep", "KTRACEP", NULL, 0, pvar, 8, POFF(p_tracep), LONG, "x"}, + {"lim", "LIM", NULL, 0, maxrss, 5}, + {"login", "LOGIN", NULL, LJUST, logname, MAXLOGNAME}, + {"logname", "", "login"}, + {"lstart", "STARTED", NULL, LJUST|USER, lstarted, 28}, + {"majflt", "MAJFLT", NULL, USER, rvar, 4, ROFF(ru_majflt), LONG, "d"}, + {"minflt", "MINFLT", NULL, USER, rvar, 4, ROFF(ru_minflt), LONG, "d"}, + {"msgrcv", "MSGRCV", NULL, USER, rvar, 4, ROFF(ru_msgrcv), LONG, "d"}, + {"msgsnd", "MSGSND", NULL, USER, rvar, 4, ROFF(ru_msgsnd), LONG, "d"}, + {"ni", "", "nice"}, + {"nice", "NI", NULL, 0, pvar, 3, POFF(p_nice), CHAR, "d"}, + {"nivcsw", "NIVCSW", NULL, USER, rvar, 5, ROFF(ru_nivcsw), LONG, "d"}, + {"nsignals", "", "nsigs"}, + {"nsigs", "NSIGS", NULL, USER, rvar, 4, ROFF(ru_nsignals), LONG, "d"}, + {"nswap", "NSWAP", NULL, USER, rvar, 4, ROFF(ru_nswap), LONG, "d"}, + {"nvcsw", "NVCSW", NULL, USER, rvar, 5, ROFF(ru_nvcsw), LONG, "d"}, + {"nwchan", "WCHAN", NULL, 0, pvar, 6, POFF(p_wchan), KPTR, "x"}, + {"oublk", "OUBLK", NULL, USER, rvar, 4, ROFF(ru_oublock), LONG, "d"}, + {"oublock", "", "oublk"}, + {"p_ru", "P_RU", NULL, 0, pvar, 6, POFF(p_ru), KPTR, "x"}, + {"paddr", "PADDR", NULL, 0, evar, 6, EOFF(e_paddr), KPTR, "x"}, + {"pagein", "PAGEIN", NULL, USER, pagein, 6}, + {"pcpu", "", "%cpu"}, + {"pending", "", "sig"}, + {"pgid", "PGID", NULL, 0, evar, PIDLEN, EOFF(e_pgid), USHORT, PIDFMT}, + {"pid", "PID", NULL, 0, pvar, PIDLEN, POFF(p_pid),SHORT, PIDFMT}, + {"pmem", "", "%mem"}, + {"ppid", "PPID", NULL, 0, evar, PIDLEN, EOFF(e_ppid), SHORT, PIDFMT}, + {"pri", "PRI", NULL, 0, pri, 3}, + {"re", "RE", NULL, 0, pvar, 3, POFF(p_time), CHAR, "d"}, + {"rgid", "RGID", NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_rgid), + USHORT, UIDFMT}, + {"rlink", "RLINK", NULL, 0, pvar, 8, POFF(p_rlink), KPTR, "x"}, + {"rss", "RSS", NULL, 0, p_rssize, 4}, + {"rssize", "", "rsz"}, + {"rsz", "RSZ", NULL, 0, rssize, 4}, + {"ruid", "RUID", NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_ruid), + USHORT, UIDFMT}, + {"ruser", "RUSER", NULL, LJUST, runame, USERLEN}, + {"sess", "SESS", NULL, 0, evar, 6, EOFF(e_sess), KPTR, "x"}, + {"sig", "PENDING", NULL, 0, pvar, 8, POFF(p_sig), LONG, "x"}, + {"sigcatch", "CAUGHT", NULL, 0, pvar, 8, POFF(p_sigcatch), LONG, "x"}, + {"sigignore", "IGNORED", + NULL, 0, pvar, 8, POFF(p_sigignore), LONG, "x"}, + {"sigmask", "BLOCKED", NULL, 0, pvar, 8, POFF(p_sigmask), LONG, "x"}, + {"sl", "SL", NULL, 0, pvar, 3, POFF(p_slptime), CHAR, "d"}, + {"start", "STARTED", NULL, LJUST|USER, started, 8}, + {"stat", "", "state"}, + {"state", "STAT", NULL, 0, state, 4}, + {"svgid", "SVGID", + NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_svgid), USHORT, UIDFMT}, + {"svuid", "SVUID", + NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_svuid), USHORT, UIDFMT}, + {"tdev", "TDEV", NULL, 0, tdev, 4}, + {"time", "TIME", NULL, USER, cputime, 9}, + {"tpgid", "TPGID", NULL, 0, evar, 4, EOFF(e_tpgid), USHORT, PIDFMT}, + {"tsess", "TSESS", NULL, 0, evar, 6, EOFF(e_tsess), KPTR, "x"}, + {"tsiz", "TSIZ", NULL, 0, tsize, 4}, + {"tt", "TT", NULL, LJUST, tname, 3}, + {"tty", "TTY", NULL, LJUST, longtname, 8}, + {"ucomm", "UCOMM", NULL, LJUST, ucomm, MAXCOMLEN}, + {"uid", "UID", NULL, 0, evar, UIDLEN, EOFF(e_ucred.cr_uid), + USHORT, UIDFMT}, + {"upr", "UPR", NULL, 0, pvar, 3, POFF(p_usrpri), CHAR, "d"}, + {"user", "USER", NULL, LJUST, uname, USERLEN}, + {"usrpri", "", "upr"}, + {"vsize", "", "vsz"}, + {"vsz", "VSZ", NULL, 0, vsize, 5}, + {"wchan", "WCHAN", NULL, LJUST, wchan, 6}, + {"xstat", "XSTAT", NULL, 0, pvar, 4, POFF(p_xstat), USHORT, "x"}, +#else + {"%cpu", "%CPU", NULL, 0, pcpu, 4}, + {"%mem", "%MEM", NULL, 0, pmem, 4}, + {"acflag", "ACFLG", NULL, USER, uvar, 3, UOFF(u_acflag), SHORT, "x"}, + {"acflg", "", "acflag"}, + {"blocked", "", "sigmask"}, + {"caught", "", "sigcatch"}, + {"command", "COMMAND", NULL, COMM|LJUST|USER, command, 16}, + {"cpu", "CPU", NULL, 0, pvar, 3, POFF(p_cpu), UCHAR, "d"}, + {"cputime", "", "time"}, + {"f", "F", NULL, 0, pvar, 7, POFF(p_flag), LONG, "x"}, + {"flags", "", "f"}, + {"ignored", "", "sigignore"}, + {"inblk", "INBLK", NULL, USER, rvar, 4, ROFF(ru_inblock), LONG, "d"}, + {"inblock", "", "inblk"}, + {"jobc", "JOBC", NULL, 0, evar, 4, EOFF(e_jobc), SHORT, "d"}, + {"ktrace", "KTRACE", NULL, 0, pvar, 8, POFF(p_traceflag), LONG, "x"}, + {"ktracep", "KTRACEP", NULL, 0, pvar, 8, POFF(p_tracep), LONG, "x"}, + {"lim", "LIM", NULL, 0, maxrss, 5}, + {"logname", "LOGNAME", NULL, LJUST, logname, MAXLOGNAME}, + {"lstart", "STARTED", NULL, LJUST|USER, lstarted, 28}, + {"majflt", "MAJFLT", NULL, USER, rvar, 4, ROFF(ru_majflt), LONG, "d"}, + {"minflt", "MINFLT", NULL, USER, rvar, 4, ROFF(ru_minflt), LONG, "d"}, + {"msgrcv", "MSGRCV", NULL, USER, rvar, 4, ROFF(ru_msgrcv), LONG, "d"}, + {"msgsnd", "MSGSND", NULL, USER, rvar, 4, ROFF(ru_msgsnd), LONG, "d"}, + {"ni", "", "nice"}, + {"nice", "NI", NULL, 0, pvar, 2, POFF(p_nice), CHAR, "d"}, + {"nivcsw", "NIVCSW", NULL, USER, rvar, 5, ROFF(ru_nivcsw), LONG, "d"}, + {"nsignals", "", "nsigs"}, + {"nsigs", "NSIGS", NULL, USER, rvar, 4, ROFF(ru_nsignals), LONG, "d"}, + {"nswap", "NSWAP", NULL, USER, rvar, 4, ROFF(ru_nswap), LONG, "d"}, + {"nvcsw", "NVCSW", NULL, USER, rvar, 5, ROFF(ru_nvcsw), LONG, "d"}, + {"nwchan", "WCHAN", NULL, 0, pvar, 6, POFF(p_wchan), KPTR, "x"}, + {"oublk", "OUBLK", NULL, USER, rvar, 4, ROFF(ru_oublock), LONG, "d"}, + {"oublock", "", "oublk"}, + {"p_ru", "P_RU", NULL, 0, pvar, 6, POFF(p_ru), KPTR, "x"}, + {"paddr", "PADDR", NULL, 0, evar, 6, EOFF(e_paddr), KPTR, "x"}, + {"pagein", "PAGEIN", NULL, USER, pagein, 6}, + {"pcpu", "", "%cpu"}, + {"pending", "", "sig"}, + {"pgid", "PGID", NULL, 0, evar, PIDLEN, EOFF(e_pgid), USHORT, PIDFMT}, + {"pid", "PID", NULL, 0, pvar, PIDLEN, POFF(p_pid),SHORT, PIDFMT}, + {"pmem", "", "%mem"}, + {"poip", "POIP", NULL, 0, pvar, 4, POFF(p_poip), SHORT, "d"}, + {"ppid", "PPID", NULL, 0, pvar, PIDLEN, POFF(p_ppid), SHORT, PIDFMT}, + {"pri", "PRI", NULL, 0, pri, 3}, + {"re", "RE", NULL, 0, pvar, 3, POFF(p_time), CHAR, "d"}, + {"rgid", "RGID", NULL, 0, pvar, UIDLEN, POFF(p_rgid), USHORT, UIDFMT}, + {"rlink", "RLINK", NULL, 0, pvar, 8, POFF(p_rlink), KPTR, "x"}, + {"rss", "RSS", NULL, 0, p_rssize, 4}, + {"rssize", "", "rsz"}, + {"rsz", "RSZ", NULL, 0, rssize, 4}, + {"ruid", "RUID", NULL, 0, pvar, UIDLEN, POFF(p_ruid), USHORT, UIDFMT}, + {"ruser", "RUSER", NULL, LJUST, runame, USERLEN}, + {"sess", "SESS", NULL, 0, evar, 6, EOFF(e_sess), KPTR, "x"}, + {"sig", "PENDING", NULL, 0, pvar, 8, POFF(p_sig), LONG, "x"}, + {"sigcatch", "CAUGHT", NULL, 0, pvar, 8, POFF(p_sigcatch), LONG, "x"}, + {"sigignore", "IGNORED", + NULL, 0, pvar, 8, POFF(p_sigignore), LONG, "x"}, + {"sigmask", "BLOCKED", NULL, 0, pvar, 8, POFF(p_sigmask), LONG, "x"}, + {"sl", "SL", NULL, 0, pvar, 3, POFF(p_slptime), CHAR, "d"}, + {"start", "STARTED", NULL, LJUST|USER, started, 8}, + {"stat", "", "state"}, + {"state", "STAT", NULL, 0, state, 4}, + {"svgid", "SVGID", + NULL, 0, pvar, UIDLEN, POFF(p_svgid), USHORT, UIDFMT}, + {"svuid", "SVUID", + NULL, 0, pvar, UIDLEN, POFF(p_svuid), USHORT, UIDFMT}, + {"tdev", "TDEV", NULL, 0, tdev, 4}, + {"time", "TIME", NULL, USER, cputime, 9}, + {"tpgid", "TPGID", NULL, 0, evar, 4, EOFF(e_tpgid), USHORT, PIDFMT}, + {"trs", "TRS", NULL, 0, trss, 3}, + {"tsess", "TSESS", NULL, 0, evar, 6, EOFF(e_tsess), KPTR, "x"}, + {"tsiz", "TSIZ", NULL, 0, tsize, 4}, + {"tt", "TT", NULL, LJUST, tname, 3}, + {"tty", "TTY", NULL, LJUST, longtname, 8}, + {"ucomm", "UCOMM", NULL, LJUST, ucomm, MAXCOMLEN}, + {"uid", "UID", NULL, 0, pvar, UIDLEN, POFF(p_uid),USHORT, UIDFMT}, + {"upr", "UPR", NULL, 0, pvar, 3, POFF(p_usrpri), CHAR, "d"}, + {"uprocp", "UPROCP", NULL, USER, uvar, 6, UOFF(u_procp), KPTR, "x"}, + {"user", "USER", NULL, LJUST, uname, USERLEN}, + {"usrpri", "", "upr"}, + {"vsize", "", "vsz"}, + {"vsz", "VSZ", NULL, 0, vsize, 5}, + {"wchan", "WCHAN", NULL, LJUST, wchan, 6}, + {"xstat", "XSTAT", NULL, 0, pvar, 4, POFF(p_xstat), USHORT, "x"}, +#endif + {""}, +}; + +showkey() +{ + extern int termwidth; + register VAR *v; + register int i, len; + register char *p, *sep; + + i = 0; + sep = ""; + for (v = var; *(p = v->name); ++v) { + len = strlen(p); + if (termwidth && (i += len + 1) > termwidth) { + i = len; + sep = "\n"; + } + (void) printf("%s%s", sep, p); + sep = " "; + } + (void) printf("\n"); +} + +parsefmt(p) + char *p; +{ + static struct varent *vtail; + register VAR *v; + register char *cp; + register struct varent *vent; + static VAR *findvar(); + +#define FMTSEP " \t,\n" + while (p && *p) { + while ((cp = strsep(&p, FMTSEP)) != NULL && *cp == '\0') + /* void */; + if (!(v = findvar(cp))) + continue; + if ((vent = malloc(sizeof(struct varent))) == NULL) + err("%s", strerror(errno)); + vent->var = v; + vent->next = NULL; + if (vhead == NULL) + vhead = vtail = vent; + else { + vtail->next = vent; + vtail = vent; + } + } + if (!vhead) + err("no valid keywords\n"); +} + +static VAR * +findvar(p) + char *p; +{ + extern int eval; + VAR *v, key; + char *hp; + int vcmp(); + + key.name = p; + + hp = index(p, '='); + if (hp) + *hp++ = '\0'; + + key.name = p; + v = (VAR *)bsearch(&key, var, + sizeof(var)/sizeof(VAR), sizeof(VAR), vcmp); + + if (v && v->alias) { + if (hp) { + (void)fprintf(stderr, + "ps: %s: illegal keyword specification\n", p); + eval = 1; + } + parsefmt(v->alias); + return((VAR *)NULL); + } + if (!v) { + (void)fprintf(stderr, "ps: keyword %s not found\n", p); + eval = 1; + } + if (hp) + v->header = hp; + return(v); +} + +vcmp(a, b) + VAR *a, *b; +{ + return(strcmp(a->name, b->name)); +} diff --git a/bin/ps/nlist.c b/bin/ps/nlist.c new file mode 100644 index 000000000000..f9373d498dca --- /dev/null +++ b/bin/ps/nlist.c @@ -0,0 +1,135 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00051 + * -------------------- ----- ---------------------- + * + * 14 Aug 92 David Greenman Fixed NEWVM mempages calculation + */ + +#ifndef lint +static char sccsid[] = "@(#)nlist.c 5.5 (Berkeley) 7/1/91"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <nlist.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#ifdef SPPWAIT +#define NEWVM +#endif + +struct nlist psnl[] = { + {"_fscale"}, +#define X_FSCALE 0 + {"_ccpu"}, +#define X_CCPU 1 +#ifdef NEWVM + {"_avail_start"}, +#define X_AVAILSTART 2 + {"_avail_end"}, +#define X_AVAILEND 3 +#else + {"_ecmx"}, +#define X_ECMX 2 +#endif + {NULL} +}; + +fixpt_t ccpu; /* kernel _ccpu variable */ +int nlistread; /* if nlist already read. */ +int mempages; /* number of pages of phys. memory */ +int fscale; /* kernel _fscale variable */ + +#define kread(x, v) \ + kvm_read(psnl[x].n_value, (char *)&v, sizeof v) != sizeof(v) + +donlist() +{ + extern int eval; + int rval; +#ifdef NEWVM + int tmp; +#endif + + rval = 0; + nlistread = 1; + if (kvm_nlist(psnl)) { + nlisterr(psnl); + eval = 1; + return(1); + } + if (kread(X_FSCALE, fscale)) { + (void)fprintf(stderr, "ps: fscale: %s\n", kvm_geterr()); + eval = rval = 1; + } +#ifdef NEWVM + if (kread(X_AVAILEND, mempages)) { + (void)fprintf(stderr, "ps: avail_start: %s\n", kvm_geterr()); + eval = rval = 1; + } + if (kread(X_AVAILSTART, tmp)) { + (void)fprintf(stderr, "ps: avail_end: %s\n", kvm_geterr()); + eval = rval = 1; + } + mempages -= tmp; + mempages = mempages / NBPG; /* 14 Aug 92*/ +#else + if (kread(X_ECMX, mempages)) { + (void)fprintf(stderr, "ps: ecmx: %s\n", kvm_geterr()); + eval = rval = 1; + } +#endif + if (kread(X_CCPU, ccpu)) { + (void)fprintf(stderr, "ps: ccpu: %s\n", kvm_geterr()); + eval = rval = 1; + } + return(rval); +} + +nlisterr(nl) + struct nlist nl[]; +{ + int i; + + fprintf(stderr, "ps: nlist: can't find following symbols:"); + for (i = 0; nl[i].n_name != NULL; i++) + if (nl[i].n_value == 0) + fprintf(stderr, " %s", nl[i].n_name); + fprintf(stderr, "\n"); +} diff --git a/bin/ps/print.c b/bin/ps/print.c new file mode 100644 index 000000000000..ce4be52cbd7b --- /dev/null +++ b/bin/ps/print.c @@ -0,0 +1,600 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)print.c 5.9 (Berkeley) 7/1/91"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <math.h> +#include <tzfile.h> +#include <stddef.h> +#include <string.h> +#include "ps.h" + +#ifdef SPPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#include <vm/vm.h> +#include <sys/ucred.h> +#include <sys/kinfo_proc.h> +#else +#include <machine/pte.h> +#include <sys/vmparam.h> +#include <sys/vm.h> +#endif + +printheader() +{ + register VAR *v; + register struct varent *vent; + + for (vent = vhead; vent; vent = vent->next) { + v = vent->var; + if (v->flag & LJUST) { + if (vent->next == NULL) /* last one */ + (void) printf("%s", v->header); + else + (void) printf("%-*s", v->width, v->header); + } else + (void) printf("%*s", v->width, v->header); + if (vent->next != NULL) + (void) putchar(' '); + } + (void) putchar('\n'); +} + +command(k, v, next) + KINFO *k; + VAR *v; +{ + extern int termwidth, totwidth; + + if (next == NULL) { + /* last field */ + if (termwidth == UNLIMITED) + (void) printf("%s", k->ki_args); + else { + register int left = termwidth - (totwidth - v->width); + register char *cp = k->ki_args; + + if (left < 1) /* already wrapped, just use std width */ + left = v->width; + while (--left >= 0 && *cp) + (void) putchar(*cp++); + } + } else + (void) printf("%-*.*s", v->width, v->width, k->ki_args); + +} + +ucomm(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%-*s", v->width, k->ki_p->p_comm); +} + +logname(k, v) + KINFO *k; + VAR *v; +{ +#ifndef NEWVM + (void) printf("%-*s", v->width, k->ki_p->p_logname); +#else /* NEWVM */ + (void) printf("%-*s", v->width, k->ki_e->e_login); +#endif /* NEWVM */ +} + +state(k, v) + KINFO *k; + VAR *v; +{ + char buf[16]; + register char *cp = buf; + register struct proc *p = k->ki_p; + register flag = p->p_flag; + + switch (p->p_stat) { + + case SSTOP: + *cp = 'T'; + break; + + case SSLEEP: + if (flag & SSINTR) /* interuptable (long) */ + *cp = p->p_slptime >= MAXSLP ? 'I' : 'S'; + else + *cp = (flag & SPAGE) ? 'P' : 'D'; + break; + + case SRUN: + case SIDL: + *cp = 'R'; + break; + + case SZOMB: + *cp = 'Z'; + break; + + default: + *cp = '?'; + } + cp++; + if (flag & SLOAD) { +#ifndef NEWVM + if (p->p_rssize > p->p_maxrss) + *cp++ = '>'; +#endif + } else + *cp++ = 'W'; + if (p->p_nice < NZERO) + *cp++ = '<'; + else if (p->p_nice > NZERO) + *cp++ = 'N'; +#ifndef NEWVM + if (flag & SUANOM) + *cp++ = 'A'; + else if (flag & SSEQL) + *cp++ = 'S'; +#endif + if (flag & STRC) + *cp++ = 'X'; + if (flag & SWEXIT && p->p_stat != SZOMB) + *cp++ = 'E'; +#ifdef NEWVM + if (flag & SPPWAIT) +#else + if (flag & SVFORK) +#endif + *cp++ = 'V'; +#ifdef NEWVM + if (flag & (SSYS|SLOCK|SKEEP|SPHYSIO)) +#else + if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO)) +#endif + *cp++ = 'L'; + if (k->ki_e->e_flag & EPROC_SLEADER) + *cp++ = 's'; + if ((flag & SCTTY) && k->ki_e->e_pgid == k->ki_e->e_tpgid) + *cp++ = '+'; + *cp = '\0'; + (void) printf("%-*s", v->width, buf); +} + +pri(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%*d", v->width, k->ki_p->p_pri - PZERO); +} + +uname(k, v) + KINFO *k; + VAR *v; +{ +#ifndef NEWVM + (void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_uid, 0)); +#else /* NEWVM */ + (void) printf("%-*s", v->width, + user_from_uid(k->ki_e->e_ucred.cr_uid, 0)); +#endif /* NEWVM */ +} + +runame(k, v) + KINFO *k; + VAR *v; +{ +#ifndef NEWVM + (void) printf("%-*s", v->width, user_from_uid(k->ki_p->p_ruid, 0)); +#else /* NEWVM */ + (void) printf("%-*s", v->width, + user_from_uid(k->ki_e->e_pcred.p_ruid, 0)); +#endif /* NEWVM */ +} + +tdev(k, v) + KINFO *k; + VAR *v; +{ + dev_t dev = k->ki_e->e_tdev; + + if (dev == NODEV) + (void) printf("%*s", v->width, "??"); + else { + char buff[16]; + + (void) sprintf(buff, "%d/%d", major(dev), minor(dev)); + (void) printf("%*s", v->width, buff); + } +} + +tname(k, v) + KINFO *k; + VAR *v; +{ + dev_t dev; + char *ttname, *devname(); + + dev = k->ki_e->e_tdev; + if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) + (void) printf("%-*s", v->width, "??"); + else { + if (strncmp(ttname, "tty", 3) == 0) + ttname += 3; + (void) printf("%*.*s%c", v->width-1, v->width-1, ttname, + k->ki_e->e_flag & EPROC_CTTY ? ' ' : '-'); + } +} + +longtname(k, v) + KINFO *k; + VAR *v; +{ + dev_t dev; + char *ttname, *devname(); + + dev = k->ki_e->e_tdev; + if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) + (void) printf("%-*s", v->width, "??"); + else + (void) printf("%-*s", v->width, ttname); +} + +started(k, v) + KINFO *k; + VAR *v; +{ + static time_t now; + struct tm *tp; + char buf[100]; + + if (!k->ki_u) { + (void) printf("%-*s", v->width, "-"); + return; + } + + tp = localtime(&k->ki_u->u_start.tv_sec); + if (!now) + (void)time(&now); + if (now - k->ki_u->u_start.tv_sec < 24 * SECSPERHOUR) { + static char fmt[] = "%l:@M%p"; + fmt[3] = '%'; /* I *hate* SCCS... */ + (void) strftime(buf, sizeof(buf) - 1, fmt, tp); + } else if (now - k->ki_u->u_start.tv_sec < 7 * SECSPERDAY) { + static char fmt[] = "%a@I%p"; + fmt[2] = '%'; /* I *hate* SCCS... */ + (void) strftime(buf, sizeof(buf) - 1, fmt, tp); + } else + (void) strftime(buf, sizeof(buf) - 1, "%e%b%y", tp); + (void) printf("%-*s", v->width, buf); +} + +lstarted(k, v) + KINFO *k; + VAR *v; +{ + char buf[100]; + + if (!k->ki_u) { + (void) printf("%-*s", v->width, "-"); + return; + } + (void) strftime(buf, sizeof(buf) -1, "%C", + localtime(&k->ki_u->u_start.tv_sec)); + (void) printf("%-*s", v->width, buf); +} + +wchan(k, v) + KINFO *k; + VAR *v; +{ + if (k->ki_p->p_wchan) { + if (k->ki_p->p_wmesg) + (void) printf("%-*.*s", v->width, v->width, k->ki_e->e_wmesg); + else + (void) printf("%-*x", v->width, + (int)k->ki_p->p_wchan &~ KERNBASE); + } else + (void) printf("%-*s", v->width, "-"); +} + +#define pgtok(a) (((a)*NBPG)/1024) + +vsize(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%*d", v->width, +#ifndef NEWVM + pgtok(k->ki_p->p_dsize + k->ki_p->p_ssize + k->ki_e->e_xsize)); +#else /* NEWVM */ + pgtok(k->ki_e->e_vm.vm_dsize + k->ki_e->e_vm.vm_ssize + + k->ki_e->e_vm.vm_tsize)); +#endif /* NEWVM */ +} + +rssize(k, v) + KINFO *k; + VAR *v; +{ +#ifndef NEWVM + (void) printf("%*d", v->width, + pgtok(k->ki_p->p_rssize + (k->ki_e->e_xccount ? + (k->ki_e->e_xrssize / k->ki_e->e_xccount) : 0))); +#else /* NEWVM */ + /* XXX don't have info about shared */ + (void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_rssize)); +#endif /* NEWVM */ +} + +p_rssize(k, v) /* doesn't account for text */ + KINFO *k; + VAR *v; +{ +#ifndef NEWVM + (void) printf("%*d", v->width, pgtok(k->ki_p->p_rssize)); +#else /* NEWVM */ + (void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_rssize)); +#endif /* NEWVM */ +} + +cputime(k, v) + KINFO *k; + VAR *v; +{ + extern int sumrusage; + long secs; + long psecs; /* "parts" of a second. first micro, then centi */ + char obuff[128]; + + if (k->ki_p->p_stat == SZOMB || k->ki_u == NULL) { + secs = 0; + psecs = 0; + } else { + secs = k->ki_p->p_utime.tv_sec + + k->ki_p->p_stime.tv_sec; + psecs = k->ki_p->p_utime.tv_usec + + k->ki_p->p_stime.tv_usec; + if (sumrusage) { + secs += k->ki_u->u_cru.ru_utime.tv_sec + + k->ki_u->u_cru.ru_stime.tv_sec; + psecs += k->ki_u->u_cru.ru_utime.tv_usec + + k->ki_u->u_cru.ru_stime.tv_usec; + } + /* + * round and scale to 100's + */ + psecs = (psecs + 5000) / 10000; + secs += psecs / 100; + psecs = psecs % 100; + } + (void) sprintf(obuff, "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); + (void) printf("%*s", v->width, obuff); +} + +double +getpcpu(k) + KINFO *k; +{ + extern fixpt_t ccpu; + extern int fscale, nlistread, rawcpu; + struct proc *p; + static int failure; + + if (!nlistread) + failure = donlist(); + if (failure) + return (0.0); + + p = k->ki_p; +#define fxtofl(fixpt) ((double)(fixpt) / fscale) + + /* XXX - I don't like this */ + if (p->p_time == 0 || (p->p_flag & SLOAD) == 0) + return (0.0); + if (rawcpu) + return (100.0 * fxtofl(p->p_pctcpu)); + return (100.0 * fxtofl(p->p_pctcpu) / + (1.0 - exp(p->p_time * log(fxtofl(ccpu))))); +} + +pcpu(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%*.1f", v->width, getpcpu(k)); +} + +double +getpmem(k) + KINFO *k; +{ + extern int mempages, nlistread; + static int failure; + struct proc *p; + struct eproc *e; + double fracmem; + int szptudot; + + if (!nlistread) + failure = donlist(); + if (failure) + return (0.0); + + p = k->ki_p; + e = k->ki_e; + if ((p->p_flag & SLOAD) == 0) + return (0.0); +#ifndef NEWVM + szptudot = UPAGES + clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize)); + fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages; + if (p->p_textp && e->e_xccount) + fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages; +#else /* NEWVM */ + /* XXX want pmap ptpages, segtab, etc. (per architecture) */ + szptudot = UPAGES; + /* XXX don't have info about shared */ + fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages; +#endif /* NEWVM */ + return (100.0 * fracmem); +} + +pmem(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%*.1f", v->width, getpmem(k)); +} + +pagein(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%*d", v->width, k->ki_u ? k->ki_u->u_ru.ru_majflt : 0); +} + +maxrss(k, v) + KINFO *k; + VAR *v; +{ +#ifndef NEWVM /* not yet */ + if (k->ki_p->p_maxrss != (RLIM_INFINITY/NBPG)) + (void) printf("%*d", v->width, pgtok(k->ki_p->p_maxrss)); + else +#endif /* NEWVM */ + (void) printf("%*s", v->width, "-"); +} + +tsize(k, v) + KINFO *k; + VAR *v; +{ +#ifndef NEWVM + (void) printf("%*d", v->width, pgtok(k->ki_e->e_xsize)); +#else /* NEWVM */ + (void) printf("%*d", v->width, pgtok(k->ki_e->e_vm.vm_tsize)); +#endif /* NEWVM */ +} + +#ifndef NEWVM +trss(k, v) + KINFO *k; + VAR *v; +{ + (void) printf("%*d", v->width, pgtok(k->ki_e->e_xrssize)); +} +#endif /* NEWVM */ + +/* + * Generic output routines. Print fields from various prototype + * structures. + */ +pvar(k, v) + KINFO *k; + VAR *v; +{ + printval((char *)((char *)k->ki_p + v->off), v); +} + +evar(k, v) + KINFO *k; + VAR *v; +{ + printval((char *)((char *)k->ki_e + v->off), v); +} + +uvar(k, v) + KINFO *k; + VAR *v; +{ + if (k->ki_u) + printval((char *)((char *)k->ki_u + v->off), v); + else + (void) printf("%*s", v->width, "-"); +} + +rvar(k, v) + KINFO *k; + VAR *v; +{ + if (k->ki_u) + printval((char *)((char *)(&k->ki_u->u_ru) + v->off), v); + else + (void) printf("%*s", v->width, "-"); +} + +printval(bp, v) + char *bp; + VAR *v; +{ + static char ofmt[32] = "%"; + register char *cp = ofmt+1, *fcp = v->fmt; + + if (v->flag & LJUST) + *cp++ = '-'; + *cp++ = '*'; + while (*cp++ = *fcp++); + + switch (v->type) { + case CHAR: + (void) printf(ofmt, v->width, *(char *)bp); + break; + case UCHAR: + (void) printf(ofmt, v->width, *(u_char *)bp); + break; + case SHORT: + (void) printf(ofmt, v->width, *(short *)bp); + break; + case USHORT: + (void) printf(ofmt, v->width, *(u_short *)bp); + break; + case LONG: + (void) printf(ofmt, v->width, *(long *)bp); + break; + case ULONG: + (void) printf(ofmt, v->width, *(u_long *)bp); + break; + case KPTR: + (void) printf(ofmt, v->width, *(u_long *)bp &~ KERNBASE); + break; + default: + err("unknown type %d", v->type); + } +} diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 new file mode 100644 index 000000000000..bfb3fe5312bc --- /dev/null +++ b/bin/ps/ps.1 @@ -0,0 +1,503 @@ +.\" Copyright (c) 1980, 1990, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ps.1 6.17 (Berkeley) 6/20/91 +.\" +.Dd June 20, 1991 +.Dt PS 1 +.Os BSD 4 +.Sh NAME +.Nm ps +.Nd process status +.Sh SYNOPSIS +.Nm ps +.Op Fl aChjlmrSTuvwx +.Op Fl M Ar core +.Op Fl N Ar system +.Op Fl O Ar fmt +.Op Fl o Ar fmt +.Op Fl p Ar pid +.Op Fl t Ar tty +.Op Fl W Ar swap +.Nm ps +.Op Fl L +.Sh DESCRIPTION +.Nm Ps +displays a header line followed by lines containing information about your +processes that have controlling terminals. +This information is sorted by process +.Tn ID . +.Pp +The information displayed is selected based on a set of keywords (see the +.Fl L +.Fl O +and +.Fl o +options). +The default output format includes, for each process, the process' +.Tn ID , +controlling terminal, cpu time (including both user and system time), +state, and associated command. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl a +Display information about other users' processes as well as your own. +.It Fl C +Change the way the cpu percentage is calculated by using a ``raw'' +cpu calculation that ignores ``resident'' time (this normally has +no effect). +.It Fl h +Repeat the information header as often as necessary to guarantee one +header per page of information. +.It Fl j +Print information associated with the following keywords: +user, pid, ppid, pgid, sess, jobc, state, tt, time and command. +.It Fl L +List the set of available keywords. +.It Fl l +Display information associated with the following keywords: +uid, pid, ppid, cpu, pri, nice, vsz, rss, wchan, state, tt, time +and command. +.It Fl M +Extract values associated with the name list from the specified core +instead of the default +.Dq Pa /dev/kmem . +.It Fl m +Sort by memory usage, instead of by process +.Tn ID . +.It Fl N +Extract the name list from the specified system instead of the default +.Dq Pa /386bsd . +.It Fl O +Add the information associated with the space or comma separated list +of keywords specifed, after the process +.Tn ID , +in the default information +display. +Keywords may be appended with an equals (``='') sign and a string. +This causes the printed header to use the specified string instead of +the standard header. +.It Fl o +Display information associated with the space or comma separated list +of keywords specifed. +Keywords may be appended with an equals (``='') sign and a string. +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 . +.It Fl r +Sort by current cpu usage, instead of by process +.Tn ID . +.It Fl S +Change the way the process time is calculated by summing all exited +children to their parent process. +.It Fl T +Display information about processes attached to the device associated +with the standard input. +.It Fl t +Display information about processes attached to the specified terminal +device. +.It Fl u +Display information associated with the following keywords: +user, pid, %cpu, %mem, vsz, rss, tt, state, start, time and command. +The +.Fl u +option implies the +.Fl r +option. +.It Fl v +Display information associated with the following keywords: +pid, state, time, sl, re, pagein, vsz, rss, lim, tsiz, trss, +%cpu, %mem and command. +The +.Fl v +option implies the +.Fl m +option. +.It Fl W +Extract swap information from the specified file instead of the +default +.Dq Pa /dev/swap . +.It Fl w +Use 132 columns to display information, instead of the default which +is your window size. +If the +.Fl w +option is specified more than once, +.Nm ps +will use as many columns as necessary without regard for your window size. +.It Fl x +Display information about processes without controlling terminals. +.El +.Pp +A complete list of the available keywords are listed below. +Some of these keywords are further specifed as follows: +.Bl -tag -width indent +.It %cpu +The cpu utilization of the process; this is a decaying average over up to +a minute of previous (real) time. +Since the time base over which this is computed varies (since processes may +be very young) it is possible for the sum of all +.Tn \&%CPU +fields to exceed 100%. +.It %mem +The percentage of real memory used by this process. +.It flags +The flags (in hexadecimal) associated with the process as in +the include file +.Aq Pa sys/proc.h : +.Bl -column SNOCLDSTOP SNOCLDSTOP +.It Dv "SLOAD" Ta No "0x0000001 in core" +.It Dv "SSYS" Ta No "0x0000002 swapper or pager process" +.It Dv "SLOCK" Ta No "0x0000004 process being swapped out" +.It Dv "SSWAP" Ta No "0x0000008 save area flag" +.It Dv "STRC" Ta No "0x0000010 process is being traced" +.It Dv "SWTED" Ta No "0x0000020 another tracing flag" +.It Dv "SSINTR" Ta No "0x0000040 sleep is interruptible" +.It Dv "SPAGE" Ta No "0x0000080 process in page wait state" +.It Dv "SKEEP" Ta No "0x0000100 another flag to prevent swap out" +.It Dv "SOMASK" Ta No "0x0000200 restore old mask after taking signal" +.It Dv "SWEXIT" Ta No "0x0000400 working on exiting" +.It Dv "SPHYSIO" Ta No "0x0000800 doing physical" +.Tn I/O +.It Dv "SVFORK" Ta No "0x0001000 process resulted from" +.Xr vfork 2 +.It Dv "SVFDONE" Ta No "0x0002000 another" +.Xr vfork +flag +.It Dv "SNOVM" Ta No "0x0004000 no vm, parent in a" +.Xr vfork +.It Dv "SPAGV" Ta No "0x0008000 init data space on demand, from vnode" +.It Dv "SSEQL" Ta No "0x0010000 user warned of sequential vm behavior" +.It Dv "SUANOM" Ta No "0x0020000 user warned of random vm behavior" +.It Dv "STIMO" Ta No "0x0040000 timing out during sleep" +.It Dv "SNOCLDSTOP" Ta No "0x0080000 no" +.Dv SIGCHLD +when children stop +.It Dv "SCTTY" Ta No "0x0100000 has a controlling terminal" +.It Dv "SOWEUPC" Ta No "0x0200000 owe process an addupc() call at next ast" +.\" the routine addupc is not documented in the man pages +.It Dv "SSEL" Ta No "0x0400000 selecting; wakeup/waiting danger" +.It Dv "SEXEC" Ta No "0x0800000 process called" +.Xr exec 2 +.It Dv "SHPUX" Ta No "0x1000000 \\*(tNHP-UX\\*(sP process +.Pq Dv HPUXCOMPAT +.It Dv "SULOCK" Ta No "0x2000000 locked in core after swap error" +.It Dv "SPTECHG" Ta No "0x4000000 pte's for process have changed" +.El +.It lim +The soft limit on memory used, specified via a call to +.Xr setrlimit 2 . +.It lstart +The exact time the command started, using the ``%C'' format described in +.Xr strftime 3 . +.It nice +The process scheduling increment (see +.Xr setpriority 2 ) . +.It rss +the real memory (resident set) size of the process (in 1024 byte units). +.It start +The time the command started. +If the command started less than 24 hours ago, the start time is +displayed using the ``%l:ps.1p'' format described in +.Xr strftime 3 . +If the command started less than 7 days ago, the start time is +displayed using the ``%a6.15p'' format. +Otherwise, the start time is displayed using the ``%e%b%y'' format. +.It state +The state is given by a sequence of letters, for example, +.Dq Tn RWNA . +The first letter indicates the run state of the process: +.Pp +.Bl -tag -width indent -compact +.It D +Marks a process in disk (or other short term, uninterruptable) wait. +.It I +Marks a process that is idle (sleeping for longer than about 20 seconds). +.It P +Marks a process in page wait. +.It R +Marks a runnable process. +.It S +Marks a process that is sleeping for less than about 20 seconds. +.It T +Marks a stopped process. +.It Z +Marks a dead process (a ``zombie''). +.El +.Pp +Additional characters after these, if any, indicate additional state +information: +.Pp +.Bl -tag -width indent -compact +.It + +The process is in the foreground process group of its control terminal. +.It < +The process has raised +.Tn CPU +scheduling priority. +.It > +The process has specified a soft limit on memory requirements and is +currently exceeding that limit; such a process is (necessarily) not +swapped. +.It A +the process has asked for random page replacement +.Pf ( Dv VA_ANOM , +from +.Xr vadvise 2 , +for example, +.Xr lisp 1 +in a garbage collect). +.It E +The process is trying to exit. +.It L +The process has pages locked in core (for example, for raw +.Tn I/O ) . +.It N +The process has reduced +.Tn CPU +scheduling priority (see +.Xr setpriority 2 ) . +.It S +The process has asked for +.Tn FIFO +page replacement +.Pf ( Dv VA_SEQL , +from +.Xr vadvise 2 , +for example, a large image processing program using virtual memory to +sequentially address voluminous data). +.It s +The process is a session leader. +.It V +The process is suspended during a +.Xr vfork . +.It W +The process is swapped out. +.It X +The process is being traced or debugged. +.El +.It tt +An abbreviation for the pathname of the controlling terminal, if any. +The abbreviation consists of the two letters following +.Dq Pa /dev/tty , +or, for the console, ``co''. +This is followed by a ``-'' if the process can no longer reach that +controlling terminal (i.e., it has been revoked). +.It wchan +The event (an address in the system) on which a process waits. +When printed numerically, the initial part of the address is +trimmed off and the result is printed in hex, for example, 0x80324000 prints +as 324000. +.El +.Pp +When printing using the command keyword, a process that has exited and +has a parent that has not yet waited for the process (in other words, a zombie) +is listed as ``<defunct>'', and a process which is blocked while trying +to exit is listed as ``<exiting>''. +.Nm Ps +makes an educated guess as to the file name and arguments given when the +process was created by examining memory or the swap area. +The method is inherently somewhat unreliable and in any event a process +is entitled to destroy this information, so the names cannot be depended +on too much. +The ucomm (accounting) keyword can, however, be depended on. +.Sh KEYWORDS +The following is a complete list of the available keywords and their +meanings. +Several of them have aliases (keywords which are synonyms). +.Pp +.Bl -tag -width sigignore -compact +.It %cpu +percentage cpu usage (alias pcpu) +.It %mem +percentage memory usage (alias pmem) +.It acflag +accounting flag (alias acflg) +.It command +command and arguments +.It cpu +short-term cpu usage factor (for scheduling) +.It flags +the process flags, in hexadecimal (alias f) +.It inblk +total blocks read (alias inblock) +.It jobc +job control count +.It ktrace +tracing flags +.It ktracep +tracing vnode +.It lim +memoryuse limit +.It logname +login name of user who started the process +.It lstart +time started +.It majflt +total page faults +.It minflt +total page reclaims +.It msgrcv +total messages received (reads from pipes/sockets) +.It msgsnd +total messages sent (writes on pipes/sockets) +.It nice +nice value (alias ni) +.It nivcsw +total involuntary context switches +.It nsigs +total signals taken (alias nsignals) +.It nswap +total swaps in/out +.It nvcsw +total voluntary context switches +.It nwchan +wait channel (as an address) +.It oublk +total blocks written (alias oublock) +.It p_ru +resource usage (valid only for zombie) +.It paddr +swap address +.It pagein +pageins (same as majflt) +.It pgid +process group number +.It pid +process +.Tn ID +.It poip +pageouts in progress +.It ppid +parent process +.Tn ID +.It pri +scheduling priority +.It re +core residency time (in seconds; 127 = infinity) +.It rgid +real group +.Tn ID +.It rlink +reverse link on run queue, or 0 +.It rss +resident set size +.It rsz +resident set size + (text size / text use count) (alias rssize) +.It ruid +real user +.Tn ID +.It ruser +user name (from ruid) +.It sess +session pointer +.It sig +pending signals (alias pending) +.It sigcatch +caught signals (alias caught) +.It sigignore +ignored signals (alias ignored) +.It sigmask +blocked signals (alias blocked) +.It sl +sleep time (in seconds; 127 = infinity) +.It start +time started +.It state +symbolic process state (alias stat) +.It svgid +saved gid from a setgid executable +.It svuid +saved uid from a setuid executable +.It tdev +control terminal device number +.It time +accumulated cpu time, user + system (alias cputime) +.It tpgid +control terminal process group +.Tn ID +.It trss +text resident set size (in Kbytes) +.It tsess +control terminal session pointer +.It tsiz +text size (in Kbytes) +.It tt +control terminal name (two letter abbreviation) +.It tty +full name of control terminal +.It uprocp +process pointer +.It ucomm +name to be used for accounting +.It uid +effective user +.Tn ID +.It upr +scheduling priority on return from system call (alias usrpri) +.It user +user name (from uid) +.It vsz +virtual size in Kbytes (alias vsize) +.It wchan +wait channel (as a symbolic name) +.It xstat +exit or stop status (valid only for stopped or zombie process) +.El +.Sh FILES +.Bl -tag -width /var/run/kvm_386bsd.db -compact +.It Pa /dev +special files and device names +.It Pa /dev/drum +default swap device +.It Pa /dev/kmem +default kernel memory +.It Pa /var/run/dev.db +/dev name database +.It Pa /var/run/kvm_386bsd.db +system namelist database +.It Pa /386bsd +default system namelist +.El +.Sh SEE ALSO +.Xr kill 1 , +.Xr w 1 , +.Xr kvm 3 , +.Xr strftime 3 , +.Xr pstat 8 +.Sh BUGS +Since +.Nm ps +cannot run faster than the system and is run as any other scheduled +process, the information it displays can never be exact. diff --git a/bin/ps/ps.c b/bin/ps/ps.c new file mode 100644 index 000000000000..15fcf3ffda7a --- /dev/null +++ b/bin/ps/ps.c @@ -0,0 +1,499 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00036 + * -------------------- ----- ---------------------- + * + * 14 Sep 92 Goran Hammarback Fixed ps exception due to gcc bug + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1990 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ps.c 5.43 (Berkeley) 7/1/91"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/kinfo.h> +#include <nlist.h> +#include <kvm.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <paths.h> +#include "ps.h" + +#ifdef SPPWAIT +#define NEWVM +#endif + +KINFO *kinfo; +struct varent *vhead, *vtail; + +int eval; /* exit value */ +int rawcpu; /* -C */ +int sumrusage; /* -S */ +int termwidth; /* width of screen (0 == infinity) */ +int totwidth; /* calculated width of requested variables */ + +static int needuser, needcomm; + +enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; + +uid_t getuid(); +char *ttyname(); +double getpcpu(); /* 14 Sep 92*/ + +char dfmt[] = "pid tt state time command"; +char jfmt[] = "user pid ppid pgid sess jobc state tt time command"; +char lfmt[] = "uid pid ppid cpu pri nice vsz rss wchan state tt time command"; +char o1[] = "pid"; +char o2[] = "tt state time command"; +char ufmt[] = "user pid %cpu %mem vsz rss tt state start time command"; +char vfmt[] = + "pid state time sl re pagein vsz rss lim tsiz trs %cpu %mem command"; + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + register struct proc *p; + register size_t nentries; + register struct varent *vent; + register int i; + struct winsize ws; + dev_t ttydev; + int all, ch, flag, fmt, lineno, pid, prtheader, uid, what, xflg; + int pscomp(); + char *nlistf, *memf, *swapf; + char *kludge_oldps_options(); + + if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && + ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && + ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&ws) == -1) || + ws.ws_col == 0) + termwidth = 79; + else + termwidth = ws.ws_col - 1; + + if (argc > 1) + argv[1] = kludge_oldps_options(argv[1]); + + fmt = 0; + all = xflg = 0; + pid = uid = -1; + ttydev = NODEV; + memf = nlistf = swapf = NULL; + while ((ch = getopt(argc, argv, + "aCghjLlM:mN:O:o:p:rSTt:uvW:wx")) != EOF) + switch((char)ch) { + case 'a': + all = 1; + break; + case 'C': + rawcpu = 1; + break; + case 'g': + break; /* no-op */ + case 'h': + prtheader = ws.ws_row > 5 ? ws.ws_row : 22; + break; + case 'j': + parsefmt(jfmt); + fmt = 1; + jfmt[0] = '\0'; + break; + case 'L': + showkey(); + exit(0); + case 'l': + parsefmt(lfmt); + fmt = 1; + lfmt[0] = '\0'; + break; + case 'M': + memf = optarg; + break; + case 'm': + sortby = SORTMEM; + break; + case 'N': + nlistf = optarg; + break; + case 'O': + parsefmt(o1); + parsefmt(optarg); + parsefmt(o2); + o1[0] = o2[0] = '\0'; + fmt = 1; + break; + case 'o': + parsefmt(optarg); + fmt = 1; + break; + case 'p': + pid = atoi(optarg); + xflg = 1; + break; + case 'r': + sortby = SORTCPU; + break; + case 'S': + sumrusage = 1; + break; + case 'T': + if ((optarg = ttyname(STDIN_FILENO)) == NULL) + err("stdin: not a terminal"); + /* FALLTHROUGH */ + case 't': { + char *ttypath; + struct stat stbuf; + char pathbuf[MAXPATHLEN]; + + if (strcmp(optarg, "co") == 0) + ttypath = _PATH_CONSOLE; + else if (*optarg != '/') + (void) sprintf(ttypath = pathbuf, "%s%s", + _PATH_TTY, optarg); + else + ttypath = optarg; + if (stat(ttypath, &stbuf) == -1) + err("%s: %s", ttypath, strerror(errno)); + if (!S_ISCHR(stbuf.st_mode)) + err("%s: not a terminal", ttypath); + ttydev = stbuf.st_rdev; + break; + } + case 'u': + parsefmt(ufmt); + sortby = SORTCPU; + fmt = 1; + ufmt[0] = '\0'; + break; + case 'v': + parsefmt(vfmt); + sortby = SORTMEM; + fmt = 1; + vfmt[0] = '\0'; + break; + case 'W': + swapf = optarg; + break; + case 'w': + if (termwidth < 131) + termwidth = 131; + else + termwidth = UNLIMITED; + break; + case 'x': + xflg = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + +#define BACKWARD_COMPATIBILITY +#ifdef BACKWARD_COMPATIBILITY + if (*argv) { + + nlistf = *argv; + if (*++argv) { + memf = *argv; + if (*++argv) + swapf = *argv; + } + } +#endif + if (kvm_openfiles(nlistf, memf, swapf) == -1) + err("kvm_openfiles: %s", kvm_geterr()); + + if (!fmt) + parsefmt(dfmt); + + if (!all && ttydev == NODEV && pid == -1) /* XXX - should be cleaner */ + uid = getuid(); + + /* + * scan requested variables, noting what structures are needed, + * and adjusting header widths as appropiate. + */ + scanvars(); + /* + * get proc list + */ + if (uid != -1) { + what = KINFO_PROC_UID; + flag = uid; + } else if (ttydev != NODEV) { + what = KINFO_PROC_TTY; + flag = ttydev; + } else if (pid != -1) { + what = KINFO_PROC_PID; + flag = pid; + } else + what = KINFO_PROC_ALL; + /* + * select procs + */ + if ((nentries = kvm_getprocs(what, flag)) == -1) + err("%s", kvm_geterr()); + kinfo = malloc(nentries * sizeof(KINFO)); + if (kinfo == NULL) + err("%s", strerror(errno)); + for (nentries = 0; p = kvm_nextproc(); ++nentries) { + kinfo[nentries].ki_p = p; + kinfo[nentries].ki_e = kvm_geteproc(p); + if (needuser || needcomm) + saveuser(&kinfo[nentries]); + } + /* + * print header + */ + printheader(); + if (nentries == 0) + exit(0); + /* + * sort proc list + */ + qsort((void *)kinfo, nentries, sizeof(KINFO), pscomp); + /* + * for each proc, call each variable output function. + */ + for (i = lineno = 0; i < nentries; i++) { + if (xflg == 0 && (kinfo[i].ki_e->e_tdev == NODEV || + (kinfo[i].ki_p->p_flag & SCTTY ) == 0)) + continue; + for (vent = vhead; vent; vent = vent->next) { + (*vent->var->oproc)(&kinfo[i], vent->var, vent->next); + if (vent->next != NULL) + (void) putchar(' '); + } + (void) putchar('\n'); + if (prtheader && lineno++ == prtheader-4) { + (void) putchar('\n'); + printheader(); + lineno = 0; + } + } + exit(eval); +} + +scanvars() +{ + register struct varent *vent; + register VAR *v; + register int i; + + for (vent = vhead; vent; vent = vent->next) { + v = vent->var; + i = strlen(v->header); + if (v->width < i) + v->width = i; + totwidth += v->width + 1; /* +1 for space */ + if (v->flag & USER) + needuser = 1; + if (v->flag & COMM) + needcomm = 1; + } + totwidth--; +} + + +/* XXX - redo */ +saveuser(ki) + KINFO *ki; +{ + register struct usave *usp; + register struct user *up; + + if ((usp = calloc(1, sizeof(struct usave))) == NULL) + err("%s", strerror(errno)); + up = kvm_getu(ki->ki_p); + /* + * save arguments if needed + */ + ki->ki_args = needcomm ? strdup(kvm_getargs(ki->ki_p, up)) : NULL; + if (up != NULL) { + ki->ki_u = usp; + /* + * save important fields + */ +#ifdef NEWVM + usp->u_start = up->u_stats.p_start; + usp->u_ru = up->u_stats.p_ru; + usp->u_cru = up->u_stats.p_cru; +#else + usp->u_procp = up->u_procp; + usp->u_start = up->u_start; + usp->u_ru = up->u_ru; + usp->u_cru = up->u_cru; + usp->u_acflag = up->u_acflag; +#endif + } else + free(usp); +} + +pscomp(k1, k2) + KINFO *k1, *k2; +{ + int i; +#ifdef NEWVM +#define VSIZE(k) ((k)->ki_e->e_vm.vm_dsize + (k)->ki_e->e_vm.vm_ssize + \ + (k)->ki_e->e_vm.vm_tsize) +#else +#define VSIZE(k) ((k)->ki_p->p_dsize + (k)->ki_p->p_ssize + (k)->ki_e->e_xsize) +#endif + + if (sortby == SORTCPU) + return (getpcpu(k2) - getpcpu(k1)); + if (sortby == SORTMEM) + return (VSIZE(k2) - VSIZE(k1)); + i = k1->ki_e->e_tdev - k2->ki_e->e_tdev; + if (i == 0) + i = k1->ki_p->p_pid - k2->ki_p->p_pid; + return (i); +} + +/* + * ICK (all for getopt), would rather hide the ugliness + * here than taint the main code. + * + * ps foo -> ps -foo + * ps 34 -> ps -p34 + * + * The old convention that 't' with no trailing tty arg means the users + * tty, is only supported if argv[1] doesn't begin with a '-'. This same + * feature is available with the option 'T', which takes no argument. + */ +char * +kludge_oldps_options(s) + char *s; +{ + size_t len; + char *newopts, *ns, *cp; + + len = strlen(s); + if ((newopts = ns = malloc(len + 2)) == NULL) + err("%s", strerror(errno)); + /* + * options begin with '-' + */ + if (*s != '-') + *ns++ = '-'; /* add option flag */ + /* + * gaze to end of argv[1] + */ + cp = s + len - 1; + /* + * if last letter is a 't' flag with no argument (in the context + * of the oldps options -- option string NOT starting with a '-' -- + * then convert to 'T' (meaning *this* terminal, i.e. ttyname(0)). + */ + if (*cp == 't' && *s != '-') + *cp = 'T'; + else { + /* + * otherwise check for trailing number, which *may* be a + * pid. + */ + while (cp >= s && isdigit(*cp)) + --cp; + } + cp++; + bcopy(s, ns, (size_t)(cp - s)); /* copy up to trailing number */ + ns += cp - s; + /* + * if there's a trailing number, and not a preceding 'p' (pid) or + * 't' (tty) flag, then assume it's a pid and insert a 'p' flag. + */ + if (isdigit(*cp) && (cp == s || cp[-1] != 't' && cp[-1] != 'p' && + (cp - 1 == s || cp[-2] != 't'))) + *ns++ = 'p'; + (void) strcpy(ns, cp); /* and append the number */ + + return (newopts); +} + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "ps: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(1); + /* NOTREACHED */ +} + +usage() +{ + (void) fprintf(stderr, +"usage: ps [-aChjlmrSTuvwx] [-O|o fmt] [-p pid] [-t tty]\n\t [-M core] [-N system] [-W swap]\n ps [-L]\n"); + exit(1); +} diff --git a/bin/ps/ps.h b/bin/ps/ps.h new file mode 100644 index 000000000000..0fdf835475aa --- /dev/null +++ b/bin/ps/ps.h @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ps.h 5.3 (Berkeley) 6/3/91 + */ + +#define UNLIMITED 0 /* unlimited terminal width */ +enum type { CHAR, UCHAR, SHORT, USHORT, LONG, ULONG, KPTR }; + +struct usave { + struct proc *u_procp; + struct timeval u_start; + struct rusage u_ru; + struct rusage u_cru; + char u_acflag; +}; + +typedef struct _kinfo { + struct proc *ki_p; /* proc structure */ + struct eproc *ki_e; /* extra stuff */ + struct usave *ki_u; /* interesting parts of user */ + char *ki_args; /* exec args (should be char **) */ + char *ki_env; /* environment (should be char **) */ +} KINFO; + +/* Variables. */ +typedef struct _var { + char *name; /* name(s) of variable */ + char *header; /* default header */ + char *alias; /* aliases */ +#define COMM 0x01 /* needs exec arguments and environment (XXX) */ +#define LJUST 0x02 /* left adjust on output (trailing blanks) */ +#define USER 0x04 /* needs user structure */ + u_int flag; + int (*oproc)(); /* output routine */ + short width; /* printing width */ + /* + * The following (optional) elements are hooks for passing information + * to the generic output routines: pvar, evar, uvar (those which print + * simple elements from well known structures: proc, eproc, usave) + */ + int off; /* offset in structure */ + enum type type; /* type of element */ + char *fmt; /* printf format */ + char *time; /* time format */ + /* + * glue to link selected fields together + */ +} VAR; + +struct varent { + VAR *var; + struct varent *next; +}; + +#include "extern.h" |
