From e3cfc8ce61f788739c66445d903f8beacb40c93d Mon Sep 17 00:00:00 2001 From: rgrimes Date: Thu, 26 May 1994 06:18:55 +0000 Subject: BSD 4.4 Lite bin Sources --- bin/ps/Makefile | 11 + bin/ps/devname.c | 80 ++++++ bin/ps/extern.h | 85 +++++++ bin/ps/fmt.c | 115 +++++++++ bin/ps/keyword.c | 354 ++++++++++++++++++++++++++ bin/ps/nlist.c | 136 ++++++++++ bin/ps/print.c | 741 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/ps/ps.1 | 502 +++++++++++++++++++++++++++++++++++++ bin/ps/ps.c | 504 +++++++++++++++++++++++++++++++++++++ bin/ps/ps.h | 88 +++++++ 10 files changed, 2616 insertions(+) create mode 100644 bin/ps/Makefile create mode 100644 bin/ps/devname.c create mode 100644 bin/ps/extern.h create mode 100644 bin/ps/fmt.c create mode 100644 bin/ps/keyword.c create mode 100644 bin/ps/nlist.c create mode 100644 bin/ps/print.c create mode 100644 bin/ps/ps.1 create mode 100644 bin/ps/ps.c create mode 100644 bin/ps/ps.h (limited to 'bin/ps') diff --git a/bin/ps/Makefile b/bin/ps/Makefile new file mode 100644 index 0000000..b98abc2 --- /dev/null +++ b/bin/ps/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 8.1 (Berkeley) 6/2/93 + +PROG= ps +SRCS= fmt.c keyword.c nlist.c print.c ps.c +CFLAGS+=-I/sys +DPADD= ${LIBMATH} ${LIBKVM} +LDADD= -lm -lkvm +BINGRP= kmem +BINMODE=2555 + +.include diff --git a/bin/ps/devname.c b/bin/ps/devname.c new file mode 100644 index 0000000..df94b91 --- /dev/null +++ b/bin/ps/devname.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1989, 1993 + * 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 8.1 (Berkeley) 5/31/93"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +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))) { + warn("warning: %s", _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. Be + * sure to clear any padding that may be found in bkey. + */ + memset(&bkey, 0, sizeof(bkey)); + bkey.dev = dev; + bkey.type = type; + key.data = &bkey; + key.size = sizeof(bkey); + return ((db->get)(db, &key, &data, 0) ? "??" : (char *)data.data); +} diff --git a/bin/ps/extern.h b/bin/ps/extern.h new file mode 100644 index 0000000..a23f3ec --- /dev/null +++ b/bin/ps/extern.h @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * 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 8.3 (Berkeley) 4/2/94 + */ + +struct kinfo; +struct nlist; +struct var; +struct varent; + +extern fixpt_t ccpu; +extern int eval, fscale, mempages, nlistread, rawcpu; +extern int sumrusage, termwidth, totwidth; +extern VAR var[]; +extern VARENT *vhead; + +__BEGIN_DECLS +void command __P((KINFO *, VARENT *)); +void cputime __P((KINFO *, VARENT *)); +int donlist __P((void)); +void evar __P((KINFO *, VARENT *)); +char *fmt_argv __P((char **, char *, int)); +double getpcpu __P((KINFO *)); +double getpmem __P((KINFO *)); +void logname __P((KINFO *, VARENT *)); +void longtname __P((KINFO *, VARENT *)); +void lstarted __P((KINFO *, VARENT *)); +void maxrss __P((KINFO *, VARENT *)); +void nlisterr __P((struct nlist *)); +void p_rssize __P((KINFO *, VARENT *)); +void pagein __P((KINFO *, VARENT *)); +void parsefmt __P((char *)); +void pcpu __P((KINFO *, VARENT *)); +void pmem __P((KINFO *, VARENT *)); +void pri __P((KINFO *, VARENT *)); +void printheader __P((void)); +void pvar __P((KINFO *, VARENT *)); +void rssize __P((KINFO *, VARENT *)); +void runame __P((KINFO *, VARENT *)); +void rvar __P((KINFO *, VARENT *)); +void showkey __P((void)); +void started __P((KINFO *, VARENT *)); +void state __P((KINFO *, VARENT *)); +void tdev __P((KINFO *, VARENT *)); +void tname __P((KINFO *, VARENT *)); +#ifndef NEWVM +void trss __P((KINFO *, VARENT *)); +#endif +void tsize __P((KINFO *, VARENT *)); +void ucomm __P((KINFO *, VARENT *)); +void uname __P((KINFO *, VARENT *)); +void uvar __P((KINFO *, VARENT *)); +void vsize __P((KINFO *, VARENT *)); +void wchan __P((KINFO *, VARENT *)); +__END_DECLS diff --git a/bin/ps/fmt.c b/bin/ps/fmt.c new file mode 100644 index 0000000..3b6a1ec --- /dev/null +++ b/bin/ps/fmt.c @@ -0,0 +1,115 @@ +/*- + * Copyright (c) 1992, 1993, 1994 + * 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[] = "@(#)fmt.c 8.4 (Berkeley) 4/15/94"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ps.h" + +static char *cmdpart __P((char *)); +static char *shquote __P((char **)); + +/* + * XXX + * This is a stub until marc does the real one. + */ +static char * +shquote(argv) + char **argv; +{ + char **p, *dst, *src; + static char buf[4096]; /* XXX */ + + if (*argv == 0) { + buf[0] = 0; + return (buf); + } + dst = buf; + for (p = argv; (src = *p++) != 0; ) { + if (*src == 0) + continue; + strvis(dst, src, VIS_NL | VIS_CSTYLE); + while (*dst) + dst++; + *dst++ = ' '; + } + *dst = '\0'; + return (buf); +} + +static char * +cmdpart(arg0) + char *arg0; +{ + char *cp; + + return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0); +} + +char * +fmt_argv(argv, cmd, maxlen) + char **argv; + char *cmd; + int maxlen; +{ + int len; + char *ap, *cp; + + if (argv == 0 || argv[0] == 0) { + if (cmd == NULL) + return (""); + ap = NULL; + len = maxlen + 3; + } else { + ap = shquote(argv); + len = strlen(ap) + maxlen + 4; + } + if ((cp = malloc(len)) == NULL) + return (NULL); + if (ap == NULL) + sprintf(cp, "(%.*s)", maxlen, cmd); + else if (strncmp(cmdpart(argv[0]), cmd, maxlen) != 0) + sprintf(cp, "%s (%.*s)", ap, maxlen, cmd); + else + (void) strcpy(cp, ap); + return (cp); +} diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c new file mode 100644 index 0000000..fb1133b --- /dev/null +++ b/bin/ps/keyword.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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 8.5 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +#ifdef P_PPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#include +#include +#endif + +static VAR *findvar __P((char *)); +static int vcmp __P((const void *, const void *)); + +#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), USHORT, "x"}, + {"acflg", "", "acflag"}, + {"blocked", "", "sigmask"}, + {"caught", "", "sigcatch"}, + {"command", "COMMAND", NULL, COMM|LJUST|USER, command, 16}, + {"cpu", "CPU", NULL, 0, pvar, 3, POFF(p_estcpu), ULONG, "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, 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), ULONG, PIDFMT}, + {"pid", "PID", NULL, 0, pvar, PIDLEN, POFF(p_pid), LONG, PIDFMT}, + {"pmem", "", "%mem"}, + {"ppid", "PPID", NULL, 0, evar, PIDLEN, EOFF(e_ppid), LONG, PIDFMT}, + {"pri", "PRI", NULL, 0, pri, 3}, + {"re", "RE", NULL, 0, pvar, 3, POFF(p_swtime), ULONG, "d"}, + {"rgid", "RGID", NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_rgid), + ULONG, UIDFMT}, + {"rlink", "RLINK", NULL, 0, pvar, 8, POFF(p_back), 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), + ULONG, 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_siglist), 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), ULONG, "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), ULONG, UIDFMT}, + {"svuid", "SVUID", + NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_svuid), ULONG, UIDFMT}, + {"tdev", "TDEV", NULL, 0, tdev, 4}, + {"time", "TIME", NULL, USER, cputime, 9}, + {"tpgid", "TPGID", NULL, 0, evar, 4, EOFF(e_tpgid), ULONG, 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), + ULONG, 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), ULONG, "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), ULONG, PIDFMT}, + {"pid", "PID", NULL, 0, pvar, PIDLEN, POFF(p_pid), LONG, PIDFMT}, + {"pmem", "", "%mem"}, + {"poip", "POIP", NULL, 0, pvar, 4, POFF(p_poip), SHORT, "d"}, + {"ppid", "PPID", NULL, 0, pvar, PIDLEN, POFF(p_ppid), LONG, PIDFMT}, + {"pri", "PRI", NULL, 0, pri, 3}, + {"re", "RE", NULL, 0, pvar, 3, POFF(p_swtime), ULONG, "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), ULONG, "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), ULONG, 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 + {""}, +}; + +void +showkey() +{ + VAR *v; + int i; + char *p, *sep; + + i = 0; + sep = ""; + for (v = var; *(p = v->name); ++v) { + int len = strlen(p); + if (termwidth && (i += len + 1) > termwidth) { + i = len; + sep = "\n"; + } + (void) printf("%s%s", sep, p); + sep = " "; + } + (void) printf("\n"); +} + +void +parsefmt(p) + char *p; +{ + static struct varent *vtail; + +#define FMTSEP " \t,\n" + while (p && *p) { + char *cp; + VAR *v; + struct varent *vent; + + while ((cp = strsep(&p, FMTSEP)) != NULL && *cp == '\0') + /* void */; + if (!(v = findvar(cp))) + continue; + if ((vent = malloc(sizeof(struct varent))) == NULL) + err(1, NULL); + vent->var = v; + vent->next = NULL; + if (vhead == NULL) + vhead = vtail = vent; + else { + vtail->next = vent; + vtail = vent; + } + } + if (!vhead) + errx(1, "no valid keywords"); +} + +static VAR * +findvar(p) + char *p; +{ + VAR *v, key; + char *hp; + int vcmp(); + + key.name = p; + + hp = strchr(p, '='); + if (hp) + *hp++ = '\0'; + + key.name = p; + v = bsearch(&key, var, sizeof(var)/sizeof(VAR) - 1, sizeof(VAR), vcmp); + + if (v && v->alias) { + if (hp) { + warnx("%s: illegal keyword specification", p); + eval = 1; + } + parsefmt(v->alias); + return ((VAR *)NULL); + } + if (!v) { + warnx("%s: keyword not found", p); + eval = 1; + } + if (hp) + v->header = hp; + return (v); +} + +static int +vcmp(a, b) + const void *a, *b; +{ + return (strcmp(((VAR *)a)->name, ((VAR *)b)->name)); +} diff --git a/bin/ps/nlist.c b/bin/ps/nlist.c new file mode 100644 index 0000000..11199ca --- /dev/null +++ b/bin/ps/nlist.c @@ -0,0 +1,136 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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[] = "@(#)nlist.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +#ifdef P_PPWAIT +#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 */ + +extern kvm_t *kd; + +#define kread(x, v) \ + kvm_read(kd, psnl[x].n_value, (char *)&v, sizeof v) != sizeof(v) + +int +donlist() +{ + int rval; +#ifdef NEWVM + int tmp; +#endif + + rval = 0; + nlistread = 1; + if (kvm_nlist(kd, psnl)) { + nlisterr(psnl); + eval = 1; + return (1); + } + if (kread(X_FSCALE, fscale)) { + warnx("fscale: %s", kvm_geterr(kd)); + eval = rval = 1; + } +#ifdef NEWVM + if (kread(X_AVAILEND, mempages)) { + warnx("avail_start: %s", kvm_geterr(kd)); + eval = rval = 1; + } + if (kread(X_AVAILSTART, tmp)) { + warnx("avail_end: %s", kvm_geterr(kd)); + eval = rval = 1; + } + mempages -= tmp; +#else + if (kread(X_ECMX, mempages)) { + warnx("ecmx: %s", kvm_geterr(kd)); + eval = rval = 1; + } +#endif + if (kread(X_CCPU, ccpu)) { + warnx("ccpu: %s", kvm_geterr(kd)); + eval = rval = 1; + } + return (rval); +} + +void +nlisterr(nl) + struct nlist nl[]; +{ + int i; + + (void)fprintf(stderr, "ps: nlist: can't find following symbols:"); + for (i = 0; nl[i].n_name != NULL; i++) + if (nl[i].n_value == 0) + (void)fprintf(stderr, " %s", nl[i].n_name); + (void)fprintf(stderr, "\n"); +} diff --git a/bin/ps/print.c b/bin/ps/print.c new file mode 100644 index 0000000..1208efa --- /dev/null +++ b/bin/ps/print.c @@ -0,0 +1,741 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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 8.6 (Berkeley) 4/16/94"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#ifdef P_PPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#include +#include +#include +#else +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +void +printheader() +{ + VAR *v; + 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'); +} + +void +command(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + int left; + char *cp, *vis_env, *vis_args; + + if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL) + err(1, NULL); + strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH); + if (k->ki_env) { + if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1)) == NULL) + err(1, NULL); + strvis(vis_env, k->ki_env, VIS_TAB | VIS_NL | VIS_NOSLASH); + } else + vis_env = NULL; + + v = ve->var; + if (ve->next == NULL) { + /* last field */ + if (termwidth == UNLIMITED) { + if (vis_env) + (void)printf("%s ", vis_env); + (void)printf("%s", vis_args); + } else { + left = termwidth - (totwidth - v->width); + if (left < 1) /* already wrapped, just use std width */ + left = v->width; + if ((cp = vis_env) != NULL) { + while (--left >= 0 && *cp) + (void)putchar(*cp++); + if (--left >= 0) + putchar(' '); + } + for (cp = vis_args; --left >= 0 && *cp != '\0';) + (void)putchar(*cp++); + } + } else + /* XXX env? */ + (void)printf("%-*.*s", v->width, v->width, vis_args); + free(vis_args); + if (vis_env != NULL) + free(vis_env); +} + +void +ucomm(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%-*s", v->width, KI_PROC(k)->p_comm); +} + +void +logname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM + (void)printf("%-*s", v->width, KI_PROC(k)->p_logname); +#else + (void)printf("%-*s", v->width, KI_EPROC(k)->e_login); +#endif +} + +void +state(k, ve) + KINFO *k; + VARENT *ve; +{ + struct proc *p; + int flag; + char *cp; + VAR *v; + char buf[16]; + + v = ve->var; + p = KI_PROC(k); + flag = p->p_flag; + cp = buf; + + switch (p->p_stat) { + + case SSTOP: + *cp = 'T'; + break; + + case SSLEEP: + if (flag & P_SINTR) /* interuptable (long) */ + *cp = p->p_slptime >= MAXSLP ? 'I' : 'S'; + else + *cp = 'D'; + break; + + case SRUN: + case SIDL: + *cp = 'R'; + break; + + case SZOMB: + *cp = 'Z'; + break; + + default: + *cp = '?'; + } + cp++; + if (flag & P_INMEM) { +#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 & P_TRACED) + *cp++ = 'X'; + if (flag & P_WEXIT && p->p_stat != SZOMB) + *cp++ = 'E'; +#ifdef NEWVM + if (flag & P_PPWAIT) +#else + if (flag & SVFORK) +#endif + *cp++ = 'V'; +#ifdef NEWVM + if (flag & (P_SYSTEM | P_NOSWAP | P_PHYSIO)) +#else + if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO)) +#endif + *cp++ = 'L'; + if (KI_EPROC(k)->e_flag & EPROC_SLEADER) + *cp++ = 's'; + if ((flag & P_CONTROLT) && KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid) + *cp++ = '+'; + *cp = '\0'; + (void)printf("%-*s", v->width, buf); +} + +void +pri(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*d", v->width, KI_PROC(k)->p_priority - PZERO); +} + +void +uname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM + (void)printf("%-*s", + (int)v->width, user_from_uid(KI_PROC(k)->p_uid, 0)); +#else + (void)printf("%-*s", + (int)v->width, user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0)); +#endif +} + +void +runame(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM + (void)printf("%-*s", + (int)v->width, user_from_uid(KI_PROC(k)->p_ruid, 0)); +#else + (void)printf("%-*s", + (int)v->width, user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0)); +#endif +} + +void +tdev(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + dev_t dev; + char buff[16]; + + v = ve->var; + dev = KI_EPROC(k)->e_tdev; + if (dev == NODEV) + (void)printf("%*s", v->width, "??"); + else { + (void)snprintf(buff, sizeof(buff), + "%d/%d", major(dev), minor(dev)); + (void)printf("%*s", v->width, buff); + } +} + +void +tname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + dev_t dev; + char *ttname; + + v = ve->var; + dev = KI_EPROC(k)->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, + KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-'); + } +} + +void +longtname(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + dev_t dev; + char *ttname; + + v = ve->var; + dev = KI_EPROC(k)->e_tdev; + if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) + (void)printf("%-*s", v->width, "??"); + else + (void)printf("%-*s", v->width, ttname); +} + +void +started(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + static time_t now; + struct tm *tp; + char buf[100]; + + v = ve->var; + if (!k->ki_u.u_valid) { + (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) { + /* I *hate* SCCS... */ + static char fmt[] = __CONCAT("%l:%", "M%p"); + (void)strftime(buf, sizeof(buf) - 1, fmt, tp); + } else if (now - k->ki_u.u_start.tv_sec < 7 * SECSPERDAY) { + /* I *hate* SCCS... */ + static char fmt[] = __CONCAT("%a%", "I%p"); + (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); +} + +void +lstarted(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + char buf[100]; + + v = ve->var; + if (!k->ki_u.u_valid) { + (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); +} + +void +wchan(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if (KI_PROC(k)->p_wchan) { + if (KI_PROC(k)->p_wmesg) + (void)printf("%-*.*s", v->width, v->width, + KI_EPROC(k)->e_wmesg); + else + (void)printf("%-*x", v->width, + (int)KI_PROC(k)->p_wchan &~ KERNBASE); + } else + (void)printf("%-*s", v->width, "-"); +} + +#define pgtok(a) (((a)*NBPG)/1024) + +void +vsize(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*d", v->width, +#ifndef NEWVM + pgtok(KI_PROC(k)->p_dsize + + KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize)); +#else + pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + + KI_EPROC(k)->e_vm.vm_tsize)); +#endif +} + +void +rssize(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM + (void)printf("%*d", v->width, + pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ? + (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0))); +#else + /* XXX don't have info about shared */ + (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); +#endif +} + +void +p_rssize(k, ve) /* doesn't account for text */ + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM + (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize)); +#else + (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize)); +#endif +} + +void +cputime(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + long secs; + long psecs; /* "parts" of a second. first micro, then centi */ + char obuff[128]; + + v = ve->var; + if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) { + secs = 0; + psecs = 0; + } else { + /* + * This counts time spent handling interrupts. We could + * fix this, but it is not 100% trivial (and interrupt + * time fractions only work on the sparc anyway). XXX + */ + secs = KI_PROC(k)->p_rtime.tv_sec; + psecs = KI_PROC(k)->p_rtime.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)snprintf(obuff, sizeof(obuff), + "%3ld:%02ld.%02ld", secs/60, secs%60, psecs); + (void)printf("%*s", v->width, obuff); +} + +double +getpcpu(k) + KINFO *k; +{ + struct proc *p; + static int failure; + + if (!nlistread) + failure = donlist(); + if (failure) + return (0.0); + + p = KI_PROC(k); +#define fxtofl(fixpt) ((double)(fixpt) / fscale) + + /* XXX - I don't like this */ + if (p->p_swtime == 0 || (p->p_flag & P_INMEM) == 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_swtime * log(fxtofl(ccpu))))); +} + +void +pcpu(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*.1f", v->width, getpcpu(k)); +} + +double +getpmem(k) + KINFO *k; +{ + static int failure; + struct proc *p; + struct eproc *e; + double fracmem; + int szptudot; + + if (!nlistread) + failure = donlist(); + if (failure) + return (0.0); + + p = KI_PROC(k); + e = KI_EPROC(k); + if ((p->p_flag & P_INMEM) == 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 + /* 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 + return (100.0 * fracmem); +} + +void +pmem(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*.1f", v->width, getpmem(k)); +} + +void +pagein(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*d", v->width, + k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0); +} + +void +maxrss(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM /* not yet */ + if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/NBPG)) + (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss)); + else +#endif + (void)printf("%*s", v->width, "-"); +} + +void +tsize(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; +#ifndef NEWVM + (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize)); +#else + (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize)); +#endif +} + +#ifndef NEWVM +void +trss(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize)); +} +#endif + +/* + * Generic output routines. Print fields from various prototype + * structures. + */ +static void +printval(bp, v) + char *bp; + VAR *v; +{ + static char ofmt[32] = "%"; + char *fcp, *cp; + + 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: + errx(1, "unknown type %d", v->type); + } +} + +void +pvar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + printval((char *)((char *)KI_PROC(k) + v->off), v); +} + +void +evar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + printval((char *)((char *)KI_EPROC(k) + v->off), v); +} + +void +uvar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if (k->ki_u.u_valid) + printval((char *)((char *)&k->ki_u + v->off), v); + else + (void)printf("%*s", v->width, "-"); +} + +void +rvar(k, ve) + KINFO *k; + VARENT *ve; +{ + VAR *v; + + v = ve->var; + if (k->ki_u.u_valid) + printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v); + else + (void)printf("%*s", v->width, "-"); +} diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 new file mode 100644 index 0000000..b0345f7 --- /dev/null +++ b/bin/ps/ps.1 @@ -0,0 +1,502 @@ +.\" Copyright (c) 1980, 1990, 1991, 1993, 1994 +.\" 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 8.3 (Berkeley) 4/18/94 +.\" +.Dd April 18, 1994 +.Dt PS 1 +.Os BSD 4 +.Sh NAME +.Nm \&ps +.Nd process status +.Sh SYNOPSIS +.Nm \&ps +.Op Fl aCehjlmrSTuvwx +.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 e +Display the environment as well. +.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 /vmunix . +.It Fl O +Add the information associated with the space or comma separated list +of keywords specified, 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 specified. +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, +%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 specified 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 "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, uninterruptible) wait. +.It I +Marks a process that is idle (sleeping for longer than about 20 seconds). +.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 ``'', and a process which is blocked while trying +to exit is listed as ``''. +.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_vmunix.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_vmunix.db +system namelist database +.It Pa /vmunix +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 0000000..06d1d5f --- /dev/null +++ b/bin/ps/ps.c @@ -0,0 +1,504 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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 copyright[] = +"@(#) Copyright (c) 1990, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ps.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps.h" + +#ifdef P_PPWAIT +#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, needenv; + +enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; + +static char *fmt __P((char **(*)(kvm_t *, const struct kinfo_proc *, int), + KINFO *, char *, int)); +static char *kludge_oldps_options __P((char *)); +static int pscomp __P((const void *, const void *)); +static void saveuser __P((KINFO *)); +static void scanvars __P((void)); +static void usage __P((void)); + +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 %cpu %mem command"; + +kvm_t *kd; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct kinfo_proc *kp; + struct varent *vent; + struct winsize ws; + dev_t ttydev; + pid_t pid; + uid_t uid; + int all, ch, flag, i, fmt, lineno, nentries; + int prtheader, wflag, what, xflg; + char *nlistf, *memf, *swapf, errbuf[256]; + + 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]); + + all = fmt = prtheader = wflag = xflg = 0; + pid = -1; + uid = (uid_t) -1; + ttydev = NODEV; + memf = nlistf = swapf = NULL; + while ((ch = getopt(argc, argv, + "aCeghjLlM:mN:O:o:p:rSTt:uvW:wx")) != EOF) + switch((char)ch) { + case 'a': + all = 1; + break; + case 'e': /* XXX set ufmt */ + needenv = 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 = atol(optarg); + xflg = 1; + break; + case 'r': + sortby = SORTCPU; + break; + case 'S': + sumrusage = 1; + break; + case 'T': + if ((optarg = ttyname(STDIN_FILENO)) == NULL) + errx(1, "stdin: not a terminal"); + /* FALLTHROUGH */ + case 't': { + struct stat sb; + char *ttypath, pathbuf[MAXPATHLEN]; + + if (strcmp(optarg, "co") == 0) + ttypath = _PATH_CONSOLE; + else if (*optarg != '/') + (void)snprintf(ttypath = pathbuf, + sizeof(pathbuf), "%s%s", _PATH_TTY, optarg); + else + ttypath = optarg; + if (stat(ttypath, &sb) == -1) + err(1, "%s", ttypath); + if (!S_ISCHR(sb.st_mode)) + errx(1, "%s: not a terminal", ttypath); + ttydev = sb.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 (wflag) + termwidth = UNLIMITED; + else if (termwidth < 131) + termwidth = 131; + wflag++; + 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 + /* + * Discard setgid privileges if not the running kernel so that bad + * guys can't print interesting stuff from kernel memory. + */ + if (nlistf != NULL || memf != NULL || swapf != NULL) + setgid(getgid()); + + kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf); + if (kd == 0) + errx(1, "%s", errbuf); + + 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 != (uid_t) -1) { + what = KERN_PROC_UID; + flag = uid; + } else if (ttydev != NODEV) { + what = KERN_PROC_TTY; + flag = ttydev; + } else if (pid != -1) { + what = KERN_PROC_PID; + flag = pid; + } else { + what = KERN_PROC_ALL; + flag = 0; + } + /* + * select procs + */ + if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0) + errx(1, "%s", kvm_geterr(kd)); + if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) + err(1, NULL); + for (i = nentries; --i >= 0; ++kp) { + kinfo[i].ki_p = kp; + if (needuser) + saveuser(&kinfo[i]); + } + /* + * print header + */ + printheader(); + if (nentries == 0) + exit(0); + /* + * sort proc list + */ + qsort(kinfo, nentries, sizeof(KINFO), pscomp); + /* + * for each proc, call each variable output function. + */ + for (i = lineno = 0; i < nentries; i++) { + if (xflg == 0 && (KI_EPROC(&kinfo[i])->e_tdev == NODEV || + (KI_PROC(&kinfo[i])->p_flag & P_CONTROLT ) == 0)) + continue; + for (vent = vhead; vent; vent = vent->next) { + (vent->var->oproc)(&kinfo[i], vent); + if (vent->next != NULL) + (void)putchar(' '); + } + (void)putchar('\n'); + if (prtheader && lineno++ == prtheader - 4) { + (void)putchar('\n'); + printheader(); + lineno = 0; + } + } + exit(eval); +} + +static void +scanvars() +{ + struct varent *vent; + VAR *v; + 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--; +} + +static char * +fmt(fn, ki, comm, maxlen) + char **(*fn) __P((kvm_t *, const struct kinfo_proc *, int)); + KINFO *ki; + char *comm; + int maxlen; +{ + char *s; + + if ((s = + fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm, maxlen)) == NULL) + err(1, NULL); + return (s); +} + +static void +saveuser(ki) + KINFO *ki; +{ + struct pstats pstats; + struct usave *usp; + + usp = &ki->ki_u; + if (kvm_read(kd, (u_long)&KI_PROC(ki)->p_addr->u_stats, + (char *)&pstats, sizeof(pstats)) == sizeof(pstats)) { + /* + * The u-area might be swapped out, and we can't get + * at it because we have a crashdump and no swap. + * If it's here fill in these fields, otherwise, just + * leave them 0. + */ + usp->u_start = pstats.p_start; + usp->u_ru = pstats.p_ru; + usp->u_cru = pstats.p_cru; + usp->u_valid = 1; + } else + usp->u_valid = 0; + /* + * save arguments if needed + */ + if (needcomm) + ki->ki_args = fmt(kvm_getargv, ki, KI_PROC(ki)->p_comm, + MAXCOMLEN); + else + ki->ki_args = NULL; + if (needenv) + ki->ki_env = fmt(kvm_getenvv, ki, (char *)NULL, 0); + else + ki->ki_env = NULL; +} + +static int +pscomp(a, b) + const void *a, *b; +{ + int i; +#ifdef NEWVM +#define VSIZE(k) (KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + \ + KI_EPROC(k)->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((KINFO *)b) - getpcpu((KINFO *)a)); + if (sortby == SORTMEM) + return (VSIZE((KINFO *)b) - VSIZE((KINFO *)a)); + i = KI_EPROC((KINFO *)a)->e_tdev - KI_EPROC((KINFO *)b)->e_tdev; + if (i == 0) + i = KI_PROC((KINFO *)a)->p_pid - KI_PROC((KINFO *)b)->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. + */ +static 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(1, NULL); + /* + * 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++; + memmove(ns, s, (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); +} + +static void +usage() +{ + + (void)fprintf(stderr, + "usage:\t%s\n\t %s\n\t%s\n", + "ps [-aChjlmrSTuvwx] [-O|o fmt] [-p pid] [-t tty]", + "[-M core] [-N system] [-W swap]", + "ps [-L]"); + exit(1); +} diff --git a/bin/ps/ps.h b/bin/ps/ps.h new file mode 100644 index 0000000..fe2513e --- /dev/null +++ b/bin/ps/ps.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1990, 1993 + * 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 8.1 (Berkeley) 5/31/93 + */ + +#define UNLIMITED 0 /* unlimited terminal width */ +enum type { CHAR, UCHAR, SHORT, USHORT, LONG, ULONG, KPTR }; + +struct usave { + struct timeval u_start; + struct rusage u_ru; + struct rusage u_cru; + char u_acflag; + char u_valid; +}; + +#define KI_PROC(ki) (&(ki)->ki_p->kp_proc) +#define KI_EPROC(ki) (&(ki)->ki_p->kp_eproc) + +typedef struct kinfo { + struct kinfo_proc *ki_p; /* proc structure */ + struct usave ki_u; /* interesting parts of user */ + char *ki_args; /* exec args */ + char *ki_env; /* environment */ +} KINFO; + +/* Variables. */ +typedef struct varent { + struct varent *next; + struct var *var; +} VARENT; + +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; + /* output routine */ + void (*oproc) __P((struct kinfo *, struct varent *)); + 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; + +#include "extern.h" -- cgit v1.1