diff options
Diffstat (limited to 'bin/ps')
| -rw-r--r-- | bin/ps/Makefile | 11 | ||||
| -rw-r--r-- | bin/ps/devname.c | 80 | ||||
| -rw-r--r-- | bin/ps/extern.h | 85 | ||||
| -rw-r--r-- | bin/ps/fmt.c | 115 | ||||
| -rw-r--r-- | bin/ps/keyword.c | 354 | ||||
| -rw-r--r-- | bin/ps/nlist.c | 136 | ||||
| -rw-r--r-- | bin/ps/print.c | 741 | ||||
| -rw-r--r-- | bin/ps/ps.1 | 502 | ||||
| -rw-r--r-- | bin/ps/ps.c | 504 | ||||
| -rw-r--r-- | bin/ps/ps.h | 88 | 
10 files changed, 2616 insertions, 0 deletions
| diff --git a/bin/ps/Makefile b/bin/ps/Makefile new file mode 100644 index 000000000000..b98abc29e204 --- /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 <bsd.prog.mk> diff --git a/bin/ps/devname.c b/bin/ps/devname.c new file mode 100644 index 000000000000..df94b9148162 --- /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 <sys/types.h> + +#include <db.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdio.h> +#include <string.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))) { +		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 000000000000..a23f3ec04dc5 --- /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 000000000000..3b6a1ec1c8b4 --- /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 <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <vis.h> +#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 000000000000..fb1133ba232b --- /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 <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/proc.h> + +#include <err.h> +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ps.h" + +#ifdef P_PPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#include <sys/ucred.h> +#include <sys/sysctl.h> +#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 000000000000..11199ca2d2a6 --- /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 <sys/param.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/resource.h> + +#include <err.h> +#include <errno.h> +#include <kvm.h> +#include <nlist.h> +#include <stdio.h> +#include <string.h> + +#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 000000000000..1208efa71ae9 --- /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 <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/proc.h> +#include <sys/stat.h> + +#ifdef P_PPWAIT +#define NEWVM +#endif + +#ifdef NEWVM +#include <sys/ucred.h> +#include <sys/sysctl.h> +#include <vm/vm.h> +#else +#include <machine/pte.h> +#include <sys/vmparam.h> +#include <sys/vm.h> +#endif + +#include <err.h> +#include <math.h> +#include <nlist.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <vis.h> +#include <tzfile.h> + +#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 000000000000..b0345f7fb6d2 --- /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 ``<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_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 000000000000..06d1d5f22a0b --- /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 <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/sysctl.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <kvm.h> +#include <nlist.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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 000000000000..fe2513e737b1 --- /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" | 
