Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Jun 2002 05:08:57 +0200
From:      Cyrille Lefevre <cyrille.lefevre@laposte.net>
To:        "J. Mallett" <jmallett@FreeBSD.org>
Cc:        standards@FreeBSD.org
Subject:   Re: cvs commit: www/en/projects/c99 index.sgml
Message-ID:  <20020611030857.GB14401@gits.dyndns.org>
In-Reply-To: <20020606194448.A23497@FreeBSD.ORG>
References:  <200206070217.g572HH584853@freefall.freebsd.org> <20020606194448.A23497@FreeBSD.ORG>

next in thread | previous in thread | raw e-mail | index | archive | help

--/NkBOFFp2J2Af1nK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Thu, Jun 06, 2002 at 07:44:49PM -0700, J. Mallett wrote:
> * From Mike Barcroft <mike@FreeBSD.org>
> > mike        2002/06/06 19:17:17 PDT
> > 
> >   Modified files:
> >     en/projects/c99      index.sgml 
> >   Log:
> >   J. Mallett will be coordinating changes to ps(1).
> 
> Which essentially means:  If you have patches for ps(1) wrt SUSv3 conformance,
> or want to discuss which options of ours should go in favor of SUSv3 ones that
> conflict, which should be optional, etc., speak up.

well, I'm a lot disapointed about your nomination while I ask for it last
week.  I suppose you get the maintainership of ps(1) because you are
a commiter ? whatever, here is, in attachment, the current version of
ps(1) I'm working on.

PS : I've tryed to subscribe to this list twince w/o success, any ideas ?

Cyrille.
-- 
Cyrille Lefevre                 mailto:cyrille.lefevre@laposte.net

--/NkBOFFp2J2Af1nK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=NOTES

ps compatible pre-BSD44, BSD44 and SUSV2

first of all, this code has been made last year and is based on
-stable version of ps(1). since then, I never posted it before
because it's conformance to SUSV2 (now SUSV3) needs to be checked.
this need always to be done and I will do it w/in the next days
(weeks?). in the meantime, I'll write a more detailled note about
differences between BSD and SUSV3 ps(1). also, the manual would
have to be updated to reflect the reallity (any volunteer ? :).

old compilation flags :

BACKWARD_COMPATIBILITY
	convert pre BSD44 options (w/o dash) to BSD44 ones.

LAZY_PS
	enable option -f to show command line and environment
	information about swapped out processes else, the -f
	option is implied.

new compilation flags :

COMPAT_BSD44
	be strictly compatible w/ BSD44 ps, else :
	* -p, -t and -U respectively accept a list of pids, ttys
	  or users instead of a single one.
	* -t accept ttyXX in addition to /dev/ttyXX and XX.
	* -U also accept uids in addition of user names.
	* output is formated more intelligently when combining
	  options such as -j, -l, -u and -v.  format strings are
	  combined instead of being concatenated.
	* -o keyword=header now works for aliased keywords, also,
	  -o keyword= don't print an empty line anymore, if any.

COMPAT_SUSV2
	be compatible w/ SUSV2 ps if the SUSV2 environment variable
	has a non-zero value or if called as ps5. this may be
	overriden using the new -B (BSD) or -V (SUSV2) options.
	SUSV2 is automagically disabled when using pre BSD44 options.
	SUSV2 options are, in fact, almost the SYSV ones.

	here is the usage string :

usage: ps [-AaBdefjl] [-C cmdlist] [-g pgrplist] [-G grouplist] [-o fmt]
          [-p pidlist] [-t ttylist] [-u userlist] [-U userlist]
	  [-m core] [-n system] [-w swap]

	here are the new -o keywords w/ their BSD44 counterpart,
	if any, in parentheses :

		addr (paddr), args (command), c, comm (command),
		etime, group, l (state), rgroup and stime.

	and the ones which are affected when SUSV2 is enable :

		pri and time.

NO_SWAP
	disable -W option since kvm(3) doesn't read swap for almost
	10 years.

also, single-linked tail queues have been converted to queue(3).

--/NkBOFFp2J2Af1nK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ps-stable.patch"

Index: Makefile
===================================================================
RCS file: /home/ncvs/src/bin/ps/Makefile,v
retrieving revision 1.13
diff -u -r1.13 Makefile
--- Makefile	17 Nov 1999 13:37:30 -0000	1.13
+++ Makefile	11 Jun 2002 03:02:38 -0000
@@ -9,7 +9,12 @@
 # keep ps from being an unnecessary load
 # on large systems.
 #
-CFLAGS+=-I${.CURDIR}/../../sys -DLAZY_PS
+CFLAGS= -g
+CFLAGS+= -I${.CURDIR}/../../sys
+CFLAGS+= -DBACKWARD_COMPATIBILITY
+CFLAGS+= -DLAZY_PS
+# CFLAGS+= -DCOMPAT_BSD44
+CFLAGS+= -DCOMPAT_SUSV2
 DPADD=	${LIBM} ${LIBKVM}
 LDADD=	-lm -lkvm
 #BINGRP=	kmem
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/bin/ps/extern.h,v
retrieving revision 1.9
diff -u -r1.9 extern.h
--- extern.h	27 Aug 1999 23:14:50 -0000	1.9
+++ extern.h	5 Jun 2001 01:16:06 -0000
@@ -34,45 +34,61 @@
  * $FreeBSD: src/bin/ps/extern.h,v 1.9 1999/08/27 23:14:50 peter Exp $
  */
 
-struct kinfo;
-struct nlist;
-struct var;
-struct varent;
-
 extern fixpt_t ccpu;
 extern int eval, fscale, mempages, nlistread, rawcpu, cflag;
 extern int sumrusage, termwidth, totwidth;
 extern VAR var[];
-extern VARENT *vhead;
+extern VARLIST varlist;
+
+#if defined(COMPAT_SUSV2)
+extern int susv2;
+#endif
 
 __BEGIN_DECLS
 void	 command __P((KINFO *, VARENT *));
 void	 cputime __P((KINFO *, VARENT *));
 int	 donlist __P((void));
+#if defined(COMPAT_SUSV2)
+void	 etime __P((KINFO *, VARENT *));
+#endif
 void	 evar __P((KINFO *, VARENT *));
 char	*fmt_argv __P((char **, char *, int));
 double	 getpcpu __P((KINFO *));
-double	 getpmem __P((KINFO *));
+#if defined(COMPAT_SUSV2)
+void	 gname __P((KINFO *, VARENT *));
+int	 s_gname __P((KINFO *));
+#endif
 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 *));
+#if defined(COMPAT_BSD44)
+void	 bsd_parsefmt __P((char *));
+#endif
+#if defined (COMPAT_SUSV2)
+void	 susv2_parsefmt __P((char *, char *));
+#endif
 void	 pcpu __P((KINFO *, VARENT *));
 void	 pmem __P((KINFO *, VARENT *));
 void	 pri __P((KINFO *, VARENT *));
-void	 rtprior __P((KINFO *, VARENT *));
 void	 printheader __P((void));
 void	 pvar __P((KINFO *, VARENT *));
+#if defined(COMPAT_SUSV2)
+void	 rgname __P((KINFO *, VARENT *));
+int	 s_rgname __P((KINFO *));
+#endif
 void	 rssize __P((KINFO *, VARENT *));
+void	 rtprior __P((KINFO *, VARENT *));
 void	 runame __P((KINFO *, VARENT *));
 int	 s_runame __P((KINFO *));
 void	 rvar __P((KINFO *, VARENT *));
 void	 showkey __P((void));
 void	 started __P((KINFO *, VARENT *));
+#if defined(COMPAT_SUSV2)
+void	 stime __P((KINFO *, VARENT *));
+#endif
 void	 state __P((KINFO *, VARENT *));
 void	 tdev __P((KINFO *, VARENT *));
 void	 tname __P((KINFO *, VARENT *));
Index: fmt.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/fmt.c,v
retrieving revision 1.14.2.1
diff -u -r1.14.2.1 fmt.c
--- fmt.c	16 Mar 2002 01:15:11 -0000	1.14.2.1
+++ fmt.c	25 May 2002 17:11:04 -0000
@@ -32,23 +32,23 @@
  */
 
 #ifndef lint
+#include <sys/cdefs.h>
 #if 0
-static char sccsid[] = "@(#)fmt.c	8.4 (Berkeley) 4/15/94";
+__RCSID("@(#)fmt.c	8.4 (Berkeley) 4/15/94");
 #endif
-static const char rcsid[] =
-  "$FreeBSD: src/bin/ps/fmt.c,v 1.14.2.1 2002/03/16 01:15:11 mikeh Exp $";
+__FBSDID("$FreeBSD: src/bin/ps/fmt.c,v 1.14.2.1 2002/03/16 01:15:11 mikeh Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <vis.h>
-#include "ps.h"
 
 static char *cmdpart __P((char *));
 static char *shquote __P((char **));
Index: keyword.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/keyword.c,v
retrieving revision 1.24.2.2
diff -u -r1.24.2.2 keyword.c
--- keyword.c	21 Sep 2001 04:49:23 -0000	1.24.2.2
+++ keyword.c	25 May 2002 17:15:04 -0000
@@ -32,11 +32,11 @@
  */
 
 #ifndef lint
+#include <sys/cdefs.h>
 #if 0
-static char sccsid[] = "@(#)keyword.c	8.5 (Berkeley) 4/2/94";
+__RCSID("@(#)keyword.c	8.5 (Berkeley) 4/2/94");
 #else
-static const char rcsid[] =
-  "$FreeBSD: src/bin/ps/keyword.c,v 1.24.2.2 2001/09/21 04:49:23 peter Exp $";
+__FBSDID("$FreeBSD: src/bin/ps/keyword.c,v 1.24.2.2 2001/09/21 04:49:23 peter Exp $");
 #endif
 #endif /* not lint */
 
@@ -47,6 +47,7 @@
 #include <sys/sysctl.h>
 #include <sys/ucred.h>
 #include <sys/user.h>
+#include <sys/queue.h>
 
 #include <err.h>
 #include <errno.h>
@@ -58,8 +59,16 @@
 
 #include "ps.h"
 
-static VAR *findvar __P((char *));
-static int  vcmp __P((const void *, const void *));
+#define	FMTSEP	", \t\n"
+
+#if defined(COMPAT_BSD44)
+static void	bsd_parsefmt1 __P((char *, char *));
+#endif
+#if defined(COMPAT_SUSV2)
+static void	susv2_parsefmt1 __P((char *, char *, char *));
+#endif
+static VAR     *findvar __P((char *, char *));
+static int	vcmp __P((const void *, const void *));
 
 #ifdef NOTINUSE
 int	utime(), stime(), ixrss(), idrss(), isrss();
@@ -83,113 +92,156 @@
 #define USERLEN UT_NAMESIZE
 
 VAR var[] = {
-	{"%cpu", "%CPU", NULL, 0, pcpu, NULL, 4},
-	{"%mem", "%MEM", NULL, 0, pmem, NULL, 4},
-	{"acflag", "ACFLG",
-		NULL, 0, pvar, NULL, 3, POFF(p_acflag), USHORT, "x"},
-	{"acflg", "", "acflag"},
-	{"blocked", "", "sigmask"},
-	{"caught", "", "sigcatch"},
-	{"command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16},
-	{"cpu", "CPU", NULL, 0, pvar, NULL, 3, POFF(p_estcpu), UINT, "d"},
-	{"cputime", "", "time"},
-	{"f", "F", NULL, 0, pvar, NULL, 7, POFF(p_flag), INT, "x"},
-	{"flags", "", "f"},
-	{"ignored", "", "sigignore"},
-	{"inblk", "INBLK",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_inblock), LONG, "ld"},
-	{"inblock", "", "inblk"},
-	{"jobc", "JOBC", NULL, 0, evar, NULL, 4, EOFF(e_jobc), SHORT, "d"},
-	{"ktrace", "KTRACE",
-		NULL, 0, pvar, NULL, 8, POFF(p_traceflag), INT, "x"},
-	{"ktracep", "KTRACEP",
-		NULL, 0, pvar, NULL, 8, POFF(p_tracep), LONG, "lx"},
-	{"lim", "LIM", NULL, 0, maxrss, NULL, 5},
-	{"login", "LOGIN", NULL, LJUST, logname, NULL, MAXLOGNAME-1},
-	{"logname", "", "login"},
-	{"lstart", "STARTED", NULL, LJUST|USER, lstarted, NULL, 28},
-	{"majflt", "MAJFLT",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_majflt), LONG, "ld"},
-	{"minflt", "MINFLT",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_minflt), LONG, "ld"},
-	{"msgrcv", "MSGRCV",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_msgrcv), LONG, "ld"},
-	{"msgsnd", "MSGSND",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_msgsnd), LONG, "ld"},
-	{"ni", "", "nice"},
-	{"nice", "NI", NULL, 0, pvar, NULL, 2, POFF(p_nice), CHAR, "d"},
-	{"nivcsw", "NIVCSW",
-		NULL, USER, rvar, NULL, 5, ROFF(ru_nivcsw), LONG, "ld"},
-	{"nsignals", "", "nsigs"},
-	{"nsigs", "NSIGS",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_nsignals), LONG, "ld"},
-	{"nswap", "NSWAP",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_nswap), LONG, "ld"},
-	{"nvcsw", "NVCSW",
-		NULL, USER, rvar, NULL, 5, ROFF(ru_nvcsw), LONG, "ld"},
-	{"nwchan", "WCHAN", NULL, 0, pvar, NULL, 8, POFF(p_wchan), KPTR, "lx"},
-	{"oublk", "OUBLK",
-		NULL, USER, rvar, NULL, 4, ROFF(ru_oublock), LONG, "ld"},
-	{"oublock", "", "oublk"},
-	{"p_ru", "P_RU", NULL, 0, pvar, NULL, 6, POFF(p_ru), KPTR, "lx"},
-	{"paddr", "PADDR", NULL, 0, evar, NULL, 8, EOFF(e_paddr), KPTR, "lx"},
-	{"pagein", "PAGEIN", NULL, USER, pagein, NULL, 6},
-	{"pcpu", "", "%cpu"},
-	{"pending", "", "sig"},
-	{"pgid", "PGID",
-		NULL, 0, evar, NULL, PIDLEN, EOFF(e_pgid), UINT, PIDFMT},
-	{"pid", "PID", NULL, 0, pvar, NULL, PIDLEN, POFF(p_pid), UINT, PIDFMT},
-	{"pmem", "", "%mem"},
-	{"ppid", "PPID",
-		NULL, 0, evar, NULL, PIDLEN, EOFF(e_ppid), UINT, PIDFMT},
-	{"pri", "PRI", NULL, 0, pri, NULL, 3},
-	{"re", "RE", NULL, 0, pvar, NULL, 3, POFF(p_swtime), UINT, "d"},
-	{"rgid", "RGID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_pcred.p_rgid),
-		UINT, UIDFMT},
-	{"rlink", "RLINK",
-		NULL, 0, pvar, NULL, 8, POFF(p_procq.tqe_prev), KPTR, "lx"},
-	{"rss", "RSS", NULL, 0, p_rssize, NULL, 4},
-	{"rssize", "", "rsz"},
-	{"rsz", "RSZ", NULL, 0, rssize, NULL, 4},
-	{"rtprio", "RTPRIO", NULL, 0, rtprior, NULL, 7, POFF(p_rtprio)},
-	{"ruid", "RUID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_pcred.p_ruid),
-		UINT, UIDFMT},
-	{"ruser", "RUSER", NULL, LJUST|DSIZ, runame, s_runame, USERLEN},
-	{"sess", "SESS", NULL, 0, evar, NULL, 6, EOFF(e_sess), KPTR, "lx"},
-	{"sig", "PENDING", NULL, 0, pvar, NULL, 8, POFF(p_siglist), INT, "x"},
-	{"sigcatch", "CAUGHT",
-		NULL, 0, evar, NULL, 8, EOFF(e_procsig.ps_sigcatch), UINT, "x"},
-	{"sigignore", "IGNORED",
-		NULL, 0, evar, NULL, 8, EOFF(e_procsig.ps_sigignore), UINT, "x"},
-	{"sigmask", "BLOCKED",
-		NULL, 0, pvar, NULL, 8, POFF(p_sigmask), UINT, "x"},
-	{"sl", "SL", NULL, 0, pvar, NULL, 3, POFF(p_slptime), UINT, "d"},
-	{"start", "STARTED", NULL, LJUST|USER, started, NULL, 7},
-	{"stat", "", "state"},
-	{"state", "STAT", NULL, 0, state, NULL, 4},
-	{"svgid", "SVGID", NULL, 0,
-		evar, NULL, UIDLEN, EOFF(e_pcred.p_svgid), UINT, UIDFMT},
-	{"svuid", "SVUID", NULL, 0,
-		evar, NULL, UIDLEN, EOFF(e_pcred.p_svuid), UINT, UIDFMT},
-	{"tdev", "TDEV", NULL, 0, tdev, NULL, 4},
-	{"time", "TIME", NULL, USER, cputime, NULL, 9},
-	{"tpgid", "TPGID",
-		NULL, 0, evar, NULL, 4, EOFF(e_tpgid), UINT, PIDFMT},
-	{"tsess", "TSESS", NULL, 0, evar, NULL, 6, EOFF(e_tsess), KPTR, "lx"},
-	{"tsiz", "TSIZ", NULL, 0, tsize, NULL, 4},
-	{"tt", "TT ", NULL, 0, tname, NULL, 4},
-	{"tty", "TTY", NULL, LJUST, longtname, NULL, 8},
-	{"ucomm", "UCOMM", NULL, LJUST, ucomm, NULL, MAXCOMLEN},
-	{"uid", "UID", NULL, 0, evar, NULL, UIDLEN, EOFF(e_ucred.cr_uid),
-		UINT, UIDFMT},
-	{"upr", "UPR", NULL, 0, pvar, NULL, 3, POFF(p_usrpri), CHAR, "d"},
-	{"user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN},
-	{"usrpri", "", "upr"},
-	{"vsize", "", "vsz"},
-	{"vsz", "VSZ", NULL, 0, vsize, NULL, 5},
-	{"wchan", "WCHAN", NULL, LJUST, wchan, NULL, 6},
-	{"xstat", "XSTAT", NULL, 0, pvar, NULL, 4, POFF(p_xstat), USHORT, "x"},
-	{""},
+	{ "%cpu", "%CPU", NULL, 0, pcpu, NULL, 4 },
+	{ "%mem", "%MEM", NULL, 0, pmem, NULL, 4 },
+	{ "acflag", "ACFLG", NULL,
+		  0, pvar, NULL, 3, POFF(p_acflag), USHORT, "x" },
+	{ "acflg", NULL, "acflag" },
+#if defined(COMPAT_SUSV2)
+	{ "addr", "ADDR", "paddr" },
+	{ "args", NULL, "command" },
+#endif
+	{ "blocked", NULL, "sigmask" },
+#if defined(COMPAT_SUSV2)
+	{ "c", "C", NULL, 0, pvar, NULL, 1, POFF(p_oncpu), UCHAR, "d" },
+#endif
+	{ "caught", NULL, "sigcatch" },
+#if defined(COMPAT_SUSV2)
+	{ "comm", "COMMAND", "ucomm" },
+#endif
+	{ "command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16 },
+	{ "cpu", "CPU", NULL, 0, pvar, NULL, 3, POFF(p_estcpu), UINT, "d" },
+	{ "cputime", NULL, "time" },
+#if defined(COMPAT_SUSV2)
+	{ "etime", "ELAPSED", NULL, USER, etime, NULL, 11 },
+#endif
+	{ "f", "F", NULL, 0, pvar, NULL, 7, POFF(p_flag), INT, "x" },
+	{ "flags", NULL, "f" },
+#if defined(COMPAT_SUSV2)
+	{ "group", "GROUP", NULL, LJUST|DSIZ, gname, s_gname, USERLEN },
+#endif
+	{ "ignored", NULL, "sigignore" },
+	{ "inblk", "INBLK", NULL,
+		  USER, rvar, NULL, 4, ROFF(ru_inblock), LONG, "ld" },
+	{ "inblock", NULL, "inblk" },
+	{ "jobc", "JOBC", NULL, 0, evar, NULL, 4, EOFF(e_jobc), SHORT, "d" },
+	{ "ktrace", "KTRACE", NULL,
+		  0, pvar, NULL, 8, POFF(p_traceflag), INT, "x" },
+	{ "ktracep", "KTRACEP", NULL,
+		  0, pvar, NULL, 8, POFF(p_tracep), LONG, "lx" },
+#if defined(COMPAT_SUSV2)
+	{ "l", "L", "state" },
+#endif
+	{ "lim", "LIM", NULL, 0, maxrss, NULL, 5 },
+	{ "login", "LOGIN", NULL, LJUST, logname, NULL, MAXLOGNAME-1 },
+	{ "logname", NULL, "login" },
+	{ "lstart", "STARTED", NULL, LJUST|USER, lstarted, NULL, 28 },
+	{ "majflt", "MAJFLT", NULL,
+		  USER, rvar, NULL, 7, ROFF(ru_majflt), LONG, "ld" },
+	{ "minflt", "MINFLT", NULL,
+		  USER, rvar, NULL, 7, ROFF(ru_minflt), LONG, "ld" },
+	{ "msgrcv", "MSGRCV", NULL,
+		  USER, rvar, NULL, 7, ROFF(ru_msgrcv), LONG, "ld" },
+	{ "msgsnd", "MSGSND", NULL,
+		  USER, rvar, NULL, 7, ROFF(ru_msgsnd), LONG, "ld" },
+	{ "ni", NULL, "nice" },
+/* SUSV2 */
+	{ "nice", "NI", NULL, 0, pvar, NULL, 3, POFF(p_nice), CHAR, "d" },
+	{ "nivcsw", "NIVCSW", NULL,
+		  USER, rvar, NULL, 5, ROFF(ru_nivcsw), LONG, "ld" },
+	{ "nsignals", NULL, "nsigs" },
+	{ "nsigs", "NSIGS", NULL,
+		  USER, rvar, NULL, 4, ROFF(ru_nsignals), LONG, "ld" },
+	{ "nswap", "NSWAP", NULL,
+		  USER, rvar, NULL, 4, ROFF(ru_nswap), LONG, "ld" },
+	{ "nvcsw", "NVCSW", NULL,
+		  USER, rvar, NULL, 5, ROFF(ru_nvcsw), LONG, "ld" },
+	{ "nwchan", "WCHAN", NULL,
+		  0, pvar, NULL, 8, POFF(p_wchan), KPTR, "lx" },
+	{ "oublk", "OUBLK", NULL,
+		  USER, rvar, NULL, 6, ROFF(ru_oublock), LONG, "ld" },
+	{ "oublock", NULL, "oublk" },
+	{ "p_ru", "P_RU", NULL, 0, pvar, NULL, 6, POFF(p_ru), KPTR, "lx" },
+	{ "paddr", "PADDR", NULL,
+		  0, evar, NULL, 8, EOFF(e_paddr), KPTR, "lx" },
+	{ "pagein", "PAGEIN", NULL, USER, pagein, NULL, 6 },
+/* SUSV2 */
+	{ "pcpu", NULL, "%cpu" },
+	{ "pending", NULL, "sig" },
+/* SUSV2 */
+	{ "pgid", "PGID", NULL,
+		  0, evar, NULL, PIDLEN, EOFF(e_pgid), UINT, PIDFMT },
+/* SUSV2 */
+	{ "pid", "PID", NULL,
+		  0, pvar, NULL, PIDLEN, POFF(p_pid), UINT, PIDFMT },
+	{ "pmem", NULL, "%mem" },
+/* SUSV2 */
+	{ "ppid", "PPID", NULL,
+		  0, evar, NULL, PIDLEN, EOFF(e_ppid), UINT, PIDFMT },
+	{ "pri", "PRI", NULL, 0, pri, NULL, 3 },
+	{ "re", "RE", NULL, 0, pvar, NULL, 6, POFF(p_swtime), UINT, "d" },
+	{ "rgid", "RGID", NULL,
+		  0, evar, NULL, UIDLEN, EOFF(e_pcred.p_rgid), UINT, UIDFMT },
+#if defined(COMPAT_SUSV2)
+	{ "rgroup", "RGROUP", NULL, LJUST|DSIZ, rgname, s_rgname, USERLEN },
+#endif
+	{ "rlink", "RLINK", NULL,
+		  0, pvar, NULL, 8, POFF(p_procq.tqe_prev), KPTR, "lx" },
+	{ "rss", "RSS", NULL, 0, p_rssize, NULL, 5 },
+	{ "rssize", NULL, "rsz" },
+	{ "rsz", "RSZ", NULL, 0, rssize, NULL, 5 },
+	{ "rtprio", "RTPRIO", NULL, 0, rtprior, NULL, 7, POFF(p_rtprio) },
+	{ "ruid", "RUID", NULL,
+		  0, evar, NULL, UIDLEN, EOFF(e_pcred.p_ruid), UINT, UIDFMT },
+/* SUSV2 */
+	{ "ruser", "RUSER", NULL, LJUST|DSIZ, runame, s_runame, USERLEN },
+	{ "s", "S", "state" },
+	{ "sess", "SESS", NULL, 0, evar, NULL, 7, EOFF(e_sess), KPTR, "lx" },
+/* SVR4 { "sid", "SID", "sess" }, */
+	{ "sig", "PENDING", NULL,
+		  0, pvar, NULL, 8, POFF(p_siglist), INT, "x" },
+	{ "sigcatch", "CAUGHT", NULL,
+		  0, evar, NULL, 8, EOFF(e_procsig.ps_sigcatch), UINT, "x" },
+	{ "sigignore", "IGNORED", NULL,
+		  0, evar, NULL, 8, EOFF(e_procsig.ps_sigignore), UINT, "x" },
+	{ "sigmask", "BLOCKED", NULL,
+		  0, pvar, NULL, 8, POFF(p_sigmask), UINT, "x" },
+	{ "sl", "SL", NULL, 0, pvar, NULL, 6, POFF(p_slptime), UINT, "d" },
+	{ "start", "STARTED", NULL, LJUST|USER, started, NULL, 7 },
+	{ "stat", NULL, "state" },
+	{ "state", "STAT", NULL, 0, state, NULL, 4 },
+#if defined(COMPAT_SUSV2)
+	{ "stime", "STIME", NULL, USER, stime, NULL, 8 },
+#endif
+	{ "svgid", "SVGID", NULL,
+		  0, evar, NULL, UIDLEN, EOFF(e_pcred.p_svgid), UINT, UIDFMT },
+	{ "svuid", "SVUID", NULL,
+		  0, evar, NULL, UIDLEN, EOFF(e_pcred.p_svuid), UINT, UIDFMT },
+	{ "tdev", "TDEV", NULL, 0, tdev, NULL, 4 },
+/* SUSV2 */
+	{ "time", "TIME", NULL, USER, cputime, NULL, 9 },
+	{ "tpgid", "TPGID", NULL,
+		  0, evar, NULL, 6, EOFF(e_tpgid), UINT, PIDFMT },
+	{ "tsess", "TSESS", NULL,
+		  0, evar, NULL, 7, EOFF(e_tsess), KPTR, "lx" },
+	{ "tsiz", "TSIZ", NULL, 0, tsize, NULL, 5 },
+	{ "tt", "TT ", NULL, 0, tname, NULL, 4 },
+/* SUSV2 */
+	{ "tty", "TTY", NULL, LJUST, longtname, NULL, 8 },
+	{ "ucomm", "UCOMM", NULL, LJUST, ucomm, NULL, MAXCOMLEN },
+	{ "uid", "UID", NULL,
+		  0, evar, NULL, UIDLEN, EOFF(e_ucred.cr_uid), UINT, UIDFMT },
+	{ "upr", "UPR", NULL, 0, pvar, NULL, 3, POFF(p_usrpri), CHAR, "d" },
+/* SUSV2 */
+	{ "user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN },
+	{ "usrpri", NULL, "upr" },
+	{ "vsize", NULL, "vsz" },
+/* SUSV2 */
+	{ "vsz", "VSZ", NULL, 0, vsize, NULL, 5 },
+	{ "wchan", "WCHAN", NULL, LJUST, wchan, NULL, 7 },
+	{ "xstat", "XSTAT", NULL,
+		  0, pvar, NULL, 4, POFF(p_xstat), USHORT, "x" },
+	{ "" },
 };
 
 void
@@ -213,65 +265,128 @@
 	(void) printf("\n");
 }
 
+#if defined(COMPAT_BSD44)
 void
-parsefmt(p)
+bsd_parsefmt(p)
 	char *p;
 {
-	static struct varent *vtail;
+	bsd_parsefmt1(p, NULL);
+}
 
-#define	FMTSEP	" \t,\n"
-	while (p && *p) {
-		char *cp;
-		VAR *v;
-		struct varent *vent;
+static void
+bsd_parsefmt1(p, h)
+	char *p, *h;
+{
+	char *cp, *hp;
+	VAR *v;
+	VARENT *vent;
 
+	while (p && *p) {
 		while ((cp = strsep(&p, FMTSEP)) != NULL && *cp == '\0')
 			/* void */;
-		if (cp == NULL || !(v = findvar(cp)))
+		if ((hp = strchr(cp, '=')) != NULL)
+			*hp++ = '\0';
+		if (cp == NULL || !(v = findvar(cp, hp ? hp : h)))
 			continue;
-		if ((vent = malloc(sizeof(struct varent))) == NULL)
+		if ((vent = malloc(sizeof(VARENT))) == NULL)
 			err(1, NULL);
 		vent->var = v;
-		vent->next = NULL;
-		if (vhead == NULL)
-			vhead = vtail = vent;
-		else {
-			vtail->next = vent;
-			vtail = vent;
+		STAILQ_INSERT_TAIL(&varlist, vent, list);
+	}
+	if (STAILQ_EMPTY(&varlist))
+		errx(1, "no valid keywords");
+}
+#endif
+
+#if defined(COMPAT_SUSV2)
+void
+susv2_parsefmt(p, f)
+	char *p, *f;
+{
+	susv2_parsefmt1(p, f, NULL);
+}
+
+static void
+susv2_parsefmt1(p, f, h)
+	char *p, *f, *h;
+{
+	char *cp, *hp;
+	VAR *v;
+	VARENT *vent;
+loop:
+	while (p && *p) {
+		while ((cp = strsep(&p, FMTSEP)) != NULL && *cp == '\0')
+			/* void */;
+		if (cp == NULL)
+			continue;
+		if ((hp = strpbrk(cp, "[=")) != NULL) {
+			switch (*hp) {
+			case '[':
+				if (!f || !*f || strpbrk(hp, f))
+					*hp++ = '\0';
+				else
+					continue;
+				if (!(hp = strchr(hp, '=')))
+					break;
+				/* FALLTHROUGH */
+			case '=':
+				*hp++ = '\0';
+			}
 		}
+		if (!(v = findvar(cp, hp ? hp : h)))
+			continue;
+		STAILQ_FOREACH(vent, &varlist, list)
+			if (!strcmp(v->name, vent->var->name)) {
+				free(v);
+				goto loop;
+			}
+		if ((vent = malloc(sizeof(VARENT))) == NULL)
+			err(1, NULL);
+		vent->var = v;
+		STAILQ_INSERT_TAIL(&varlist, vent, list);
 	}
-	if (!vhead)
+	if (STAILQ_EMPTY(&varlist))
 		errx(1, "no valid keywords");
 }
+#endif
 
 static VAR *
-findvar(p)
-	char *p;
+findvar(p, h)
+	char *p, *h;
 {
 	VAR *v, key;
-	char *hp;
-	int vcmp();
-
-	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) {
+#if defined(COMPAT_BSD44)
+		if (h) {
+			h = NULL;
 			warnx("%s: illegal keyword specification", p);
 			eval = 1;
 		}
-		parsefmt(v->alias);
+#endif
+#if defined(COMPAT_SUSV2)
+		susv2_parsefmt1(v->alias, NULL, h ? h : v->header);
+#else
+		bsd_parsefmt1(v->alias, h ? h : v->header);
+#endif
 		return ((VAR *)NULL);
 	}
 	if (!v) {
 		warnx("%s: keyword not found", p);
 		eval = 1;
-	} else if (hp)
-		v->header = hp;
+	} else if (h) {
+		VAR *vp;
+
+		if ((vp = malloc(sizeof(VAR))) == NULL)
+			err(1, NULL);
+		memcpy(vp, v, sizeof(VAR));
+		v = vp;
+		if ((v->header = strdup(h)) == NULL)
+			err(1, NULL);
+	}
 	return (v);
 }
 
Index: nlist.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/nlist.c,v
retrieving revision 1.12.6.2
diff -u -r1.12.6.2 nlist.c
--- nlist.c	1 Aug 2001 05:04:48 -0000	1.12.6.2
+++ nlist.c	25 May 2002 17:12:30 -0000
@@ -32,11 +32,11 @@
  */
 
 #ifndef lint
+#include <sys/cdefs.h>
 #if 0
-static char sccsid[] = "@(#)nlist.c	8.4 (Berkeley) 4/2/94";
+__RCSID("@(#)nlist.c	8.4 (Berkeley) 4/2/94");
 #endif
-static const char rcsid[] =
-  "$FreeBSD: src/bin/ps/nlist.c,v 1.12.6.2 2001/08/01 05:04:48 obrien Exp $";
+__FBSDID("$FreeBSD: src/bin/ps/nlist.c,v 1.12.6.2 2001/08/01 05:04:48 obrien Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
Index: print.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/print.c,v
retrieving revision 1.36.2.3
diff -u -r1.36.2.3 print.c
--- print.c	12 Mar 2002 18:12:57 -0000	1.36.2.3
+++ print.c	25 May 2002 17:18:09 -0000
@@ -32,11 +32,11 @@
  */
 
 #ifndef lint
+#include <sys/cdefs.h>
 #if 0
-static char sccsid[] = "@(#)print.c	8.6 (Berkeley) 4/16/94";
+__RCSID("@(#)print.c	8.6 (Berkeley) 4/16/94");
 #endif
-static const char rcsid[] =
-  "$FreeBSD: src/bin/ps/print.c,v 1.36.2.3 2002/03/12 18:12:57 phantom Exp $";
+__FBSDID("$FreeBSD: src/bin/ps/print.c,v 1.36.2.3 2002/03/12 18:12:57 phantom Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -44,10 +44,10 @@
 #include <sys/resource.h>
 #include <sys/proc.h>
 #include <sys/stat.h>
-
 #include <sys/ucred.h>
 #include <sys/user.h>
 #include <sys/sysctl.h>
+#include <sys/queue.h>
 #include <vm/vm.h>
 
 #include <err.h>
@@ -64,22 +64,44 @@
 
 #include "ps.h"
 
+#define FMTLEN	64
+#define BUFLEN	128
+
+static const char	sfmt[] = "%s";
+static const char	wsfmt[] = "%*s";
+static const char	wwsfmt[] = "%*.*s";
+static const char	lwsfmt[] = "%-*s";
+static const char	lwwsfmt[] = "%-*.*s";
+static const char	wdfmt[] = "%*d";
+static const char	wldfmt[] = "%*ld";
+static const char	wlufmt[] = "%*lu";
+static const char	wffmt[] = "%*.1f";
+
+static void	gettime __P((time_t *, struct timeval *));
+static double	getpmem __P((KINFO *));
+static void	printval __P((char *, VAR *v));
+
 void
 printheader()
 {
 	VAR *v;
-	struct varent *vent;
+	VARENT *vent;
 
-	for (vent = vhead; vent; vent = vent->next) {
+	STAILQ_FOREACH(vent, &varlist, list)
+		if (*vent->var->header)
+			break;
+	if (!vent)
+		return;
+	STAILQ_FOREACH(vent, &varlist, list) {
 		v = vent->var;
 		if (v->flag & LJUST) {
-			if (vent->next == NULL)	/* last one */
-				(void)printf("%s", v->header);
+			if (STAILQ_NEXT(vent, list) == NULL)	/* last one */
+				(void)printf(sfmt, v->header);
 			else
-				(void)printf("%-*s", v->width, v->header);
+				(void)printf(lwsfmt, v->width, v->header);
 		} else
-			(void)printf("%*s", v->width, v->header);
-		if (vent->next != NULL)
+			(void)printf(wsfmt, v->width, v->header);
+		if (STAILQ_NEXT(vent, list) != NULL)
 			(void)putchar(' ');
 	}
 	(void)putchar('\n');
@@ -97,10 +119,10 @@
 	v = ve->var;
 
 	if (cflag) {
-		if (ve->next == NULL)	/* last field, don't pad */
-			(void)printf("%s", KI_PROC(k)->p_comm);
+		if (STAILQ_NEXT(ve, list) == NULL) /* last field, don't pad */
+			(void)printf(sfmt, KI_PROC(k)->p_comm);
 		else
-			(void)printf("%-*s", v->width, KI_PROC(k)->p_comm);
+			(void)printf(lwsfmt, v->width, KI_PROC(k)->p_comm);
 		return;
 	}
 
@@ -114,12 +136,13 @@
 	} else
 		vis_env = NULL;
 
-	if (ve->next == NULL) {
-		/* last field */
+	if (STAILQ_NEXT(ve, list) == NULL) { /* last field */
 		if (termwidth == UNLIMITED) {
-			if (vis_env)
-				(void)printf("%s ", vis_env);
-			(void)printf("%s", vis_args);
+			if (vis_env) {
+				(void)printf(sfmt, vis_env);
+				(void)putchar(' ');
+			}
+			(void)printf(sfmt, vis_args);
 		} else {
 			left = termwidth - (totwidth - v->width);
 			if (left < 1) /* already wrapped, just use std width */
@@ -128,14 +151,14 @@
 				while (--left >= 0 && *cp)
 					(void)putchar(*cp++);
 				if (--left >= 0)
-					putchar(' ');
+					(void)putchar(' ');
 			}
 			for (cp = vis_args; --left >= 0 && *cp != '\0';)
 				(void)putchar(*cp++);
 		}
 	} else
 		/* XXX env? */
-		(void)printf("%-*.*s", v->width, v->width, vis_args);
+		(void)printf(lwwsfmt, v->width, v->width, vis_args);
 	free(vis_args);
 	if (vis_env != NULL)
 		free(vis_env);
@@ -149,7 +172,7 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%-*s", v->width, KI_PROC(k)->p_comm);
+	(void)printf(lwsfmt, v->width, KI_PROC(k)->p_comm);
 }
 
 void
@@ -161,7 +184,8 @@
 	char *s;
 
 	v = ve->var;
-	(void)printf("%-*s", v->width, (s = KI_EPROC(k)->e_login, *s) ? s : "-");
+	(void)printf(lwsfmt, v->width,
+	    (s = KI_EPROC(k)->e_login, *s) ? s : "-");
 }
 
 void
@@ -173,7 +197,7 @@
 	int flag;
 	char *cp;
 	VAR *v;
-	char buf[16];
+	char buf[BUFLEN];
 
 	v = ve->var;
 	p = KI_PROC(k);
@@ -183,29 +207,28 @@
 	switch (p->p_stat) {
 
 	case SSTOP:
-		*cp = 'T';
+		*cp++ = 'T';
 		break;
 
 	case SSLEEP:
 		if (flag & P_SINTR)	/* interruptable (long) */
-			*cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
+			*cp++ = p->p_slptime >= MAXSLP ? 'I' : 'S';
 		else
-			*cp = 'D';
+			*cp++ = 'D';
 		break;
 
 	case SRUN:
 	case SIDL:
-		*cp = 'R';
+		*cp++ = 'R';
 		break;
 
 	case SZOMB:
-		*cp = 'Z';
+		*cp++ = 'Z';
 		break;
 
 	default:
-		*cp = '?';
+		*cp++ = '?';
 	}
-	cp++;
 	if (!(flag & P_INMEM))
 		*cp++ = 'W';
 	if (p->p_nice < NZERO)
@@ -222,12 +245,13 @@
 		*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)
+	if ((flag & P_CONTROLT) &&
+	    KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid)
 		*cp++ = '+';
 	if (flag & P_JAILED)
 		*cp++ = 'J';
 	*cp = '\0';
-	(void)printf("%-*s", v->width, buf);
+	(void)printf(lwsfmt, v->width, buf);
 }
 
 void
@@ -238,7 +262,12 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*d", v->width, KI_PROC(k)->p_priority - PZERO);
+#if defined(COMPAT_SUSV2)
+	if (susv2)
+		(void)printf(wdfmt, v->width, KI_PROC(k)->p_priority);
+	else
+#endif
+		(void)printf(wdfmt, v->width, KI_PROC(k)->p_priority - PZERO);
 }
 
 void
@@ -249,8 +278,8 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%-*s",
-	    (int)v->width, user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0));
+	(void)printf(lwsfmt, v->width,
+	    user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0));
 }
 
 int
@@ -268,17 +297,57 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%-*s",
-	    (int)v->width, user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0));
+	(void)printf(lwsfmt, v->width,
+	    user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0));
 }
 
 int
 s_runame(k)
 	KINFO *k;
 {
-	    return (strlen(user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0)));
+	return (strlen(user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0)));
 }
 
+#if defined(COMPAT_SUSV2)
+void
+gname(k, ve)
+	KINFO *k;
+	VARENT *ve;
+{
+	VAR *v;
+
+	v = ve->var;
+	(void)printf(lwsfmt, v->width,
+	    group_from_gid(KI_EPROC(k)->e_ucred.cr_gid, 0));
+}
+
+int
+s_gname(k)
+	KINFO *k;
+{
+	return (strlen(group_from_gid(KI_EPROC(k)->e_ucred.cr_gid, 0)));
+}
+
+void
+rgname(k, ve)
+	KINFO *k;
+	VARENT *ve;
+{
+	VAR *v;
+
+	v = ve->var;
+	(void)printf(lwsfmt, v->width,
+	    group_from_gid(KI_EPROC(k)->e_pcred.p_rgid, 0));
+}
+
+int
+s_rgname(k)
+	KINFO *k;
+{
+	return (strlen(group_from_gid(KI_EPROC(k)->e_pcred.p_rgid, 0)));
+}
+#endif
+
 void
 tdev(k, ve)
 	KINFO *k;
@@ -286,16 +355,16 @@
 {
 	VAR *v;
 	dev_t dev;
-	char buff[16];
+	char buf[BUFLEN];
 
 	v = ve->var;
 	dev = KI_EPROC(k)->e_tdev;
 	if (dev == NODEV)
-		(void)printf("%*s", v->width, "??");
+		(void)printf(wsfmt, v->width, "??");
 	else {
-		(void)snprintf(buff, sizeof(buff),
+		(void)snprintf(buf, sizeof(buf),
 		    "%d/%d", major(dev), minor(dev));
-		(void)printf("%*s", v->width, buff);
+		(void)printf(wsfmt, v->width, buf);
 	}
 }
 
@@ -311,13 +380,13 @@
 	v = ve->var;
 	dev = KI_EPROC(k)->e_tdev;
 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
-		(void)printf("%*s ", v->width-1, "??");
+		(void)printf(wsfmt, v->width, "?? ");
 	else {
 		if (strncmp(ttname, "tty", 3) == 0 ||
 		    strncmp(ttname, "cua", 3) == 0)
 			ttname += 3;
-		(void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
-			KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-');
+		(void)printf(wwsfmt, v->width-1, v->width-1, ttname);
+		(void)putchar(KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-');
 	}
 }
 
@@ -333,9 +402,27 @@
 	v = ve->var;
 	dev = KI_EPROC(k)->e_tdev;
 	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
-		(void)printf("%-*s", v->width, "??");
+		(void)printf(lwsfmt, v->width, "??");
 	else
-		(void)printf("%-*s", v->width, ttname);
+		(void)printf(lwsfmt, v->width, ttname);
+}
+
+static void
+gettime(tp, tvp)
+	time_t *tp;
+	struct timeval *tvp;
+{
+	static time_t	t;
+	static struct timeval	tv;
+
+	if (!t) {
+		(void)time(&t);
+		(void)gettimeofday(&tv, NULL);
+	}
+	if (tp)
+		*tp = t;
+	if (tvp)
+		*tvp = tv;
 }
 
 void
@@ -344,15 +431,15 @@
 	VARENT *ve;
 {
 	VAR *v;
-	static time_t now;
+	time_t now;
 	time_t then;
 	struct tm *tp;
-	char buf[100];
+	char buf[BUFLEN];
 	static int  use_ampm = -1;
 
 	v = ve->var;
 	if (!k->ki_u.u_valid) {
-		(void)printf("%-*s", v->width, "-");
+		(void)printf(lwsfmt, v->width, "-");
 		return;
 	}
 
@@ -361,18 +448,48 @@
 
 	then = k->ki_u.u_start.tv_sec;
 	tp = localtime(&then);
-	if (!now)
-		(void)time(&now);
+	gettime(&now, NULL);
 	if (now - k->ki_u.u_start.tv_sec < 24 * 3600) {
 		(void)strftime(buf, sizeof(buf) - 1,
 		use_ampm ? "%l:%M%p" : "%k:%M  ", tp);
 	} else if (now - k->ki_u.u_start.tv_sec < 7 * 86400) {
 		(void)strftime(buf, sizeof(buf) - 1,
 		use_ampm ? "%a%I%p" : "%a%H  ", tp);
-	} else
-		(void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
-	(void)printf("%-*s", v->width, buf);
+	} else {
+		static const char fmt[] = "%e%b%y"; /* avoid gcc warning */
+		(void)strftime(buf, sizeof(buf) - 1, fmt, tp);
+	}
+	(void)printf(lwsfmt, v->width, buf);
+}
+
+#if defined(COMPAT_SUSV2)
+void
+stime(k, ve)
+	KINFO *k;
+	VARENT *ve;
+{
+	VAR *v;
+	time_t now;
+	time_t then;
+	struct tm *tp;
+	char buf[BUFLEN];
+
+	v = ve->var;
+	if (!k->ki_u.u_valid) {
+		(void)printf(lwsfmt, v->width, "-");
+		return;
+	}
+
+	then = k->ki_u.u_start.tv_sec;
+	tp = localtime(&then);
+	gettime(&now, NULL);
+	if (now - k->ki_u.u_start.tv_sec < 24 * 3600)
+		(void)strftime(buf, sizeof(buf) - 1, "%T", tp);
+	else
+		(void)strftime(buf, sizeof(buf) - 1, "%b %d", tp);
+	(void)printf(wsfmt, v->width, buf);
 }
+#endif
 
 void
 lstarted(k, ve)
@@ -381,16 +498,17 @@
 {
 	VAR *v;
 	time_t then;
-	char buf[100];
+	char buf[BUFLEN];
+	static const char fmt[] = "%c"; /* avoid gcc warning */
 
 	v = ve->var;
 	if (!k->ki_u.u_valid) {
-		(void)printf("%-*s", v->width, "-");
+		(void)printf(lwsfmt, v->width, "-");
 		return;
 	}
 	then = k->ki_u.u_start.tv_sec;
-	(void)strftime(buf, sizeof(buf) -1, "%c", localtime(&then));
-	(void)printf("%-*s", v->width, buf);
+	(void)strftime(buf, sizeof(buf) -1, fmt, localtime(&then));
+	(void)printf(lwsfmt, v->width, buf);
 }
 
 void
@@ -403,13 +521,13 @@
 	v = ve->var;
 	if (KI_PROC(k)->p_wchan) {
 		if (KI_PROC(k)->p_wmesg)
-			(void)printf("%-*.*s", v->width, v->width,
+			(void)printf(lwwsfmt, v->width, v->width,
 				      KI_EPROC(k)->e_wmesg);
 		else
 			(void)printf("%-*lx", v->width,
 			    (long)KI_PROC(k)->p_wchan);
 	} else
-		(void)printf("%-*s", v->width, "-");
+		(void)printf(lwsfmt, v->width, "-");
 }
 
 #ifndef pgtok
@@ -424,7 +542,7 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*d", v->width,
+	(void)printf(wdfmt, v->width,
 	    (KI_EPROC(k)->e_vm.vm_map.size/1024));
 }
 
@@ -437,7 +555,7 @@
 
 	v = ve->var;
 	/* XXX don't have info about shared */
-	(void)printf("%*lu", v->width,
+	(void)printf(wlufmt, v->width,
 	    (u_long)pgtok(KI_EPROC(k)->e_vm.vm_rssize));
 }
 
@@ -449,7 +567,8 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*ld", v->width, (long)pgtok(KI_EPROC(k)->e_vm.vm_rssize));
+	(void)printf(wldfmt, v->width,
+	    (long)pgtok(KI_EPROC(k)->e_vm.vm_rssize));
 }
 
 void
@@ -460,11 +579,14 @@
 	VAR *v;
 	long secs;
 	long psecs;	/* "parts" of a second. first micro, then centi */
-	char obuff[128];
+	long mins, hours, days;
+	char fmt[FMTLEN];
+	char buf[BUFLEN];
 	static char decimal_point = 0;
 
 	if (!decimal_point)
 		decimal_point = localeconv()->decimal_point[0];
+
 	v = ve->var;
 	if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) {
 		secs = 0;
@@ -481,7 +603,7 @@
 			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;
+				 k->ki_u.u_cru.ru_stime.tv_usec;
 		}
 		/*
 		 * round and scale to 100's
@@ -490,10 +612,75 @@
 		secs += psecs / 100;
 		psecs = psecs % 100;
 	}
-	(void)snprintf(obuff, sizeof(obuff),
-	    "%3ld:%02ld%c%02ld", secs/60, secs%60, decimal_point, psecs);
-	(void)printf("%*s", v->width, obuff);
+	mins = secs / 60;
+	*fmt = '\0';
+#if defined(COMPAT_SUSV2)
+	if (susv2) {
+		hours = mins / 60;
+		days = hours / 24;
+		hours %= 24;
+		mins %= 60;
+		if (days)
+			strcat(fmt, "%6$02ld-");
+		strcat(fmt, "%5$02ld:%1$02ld:%2$02ld");
+	} else
+#endif
+	{
+		hours = days = 0;
+		strcat(fmt, "%3ld:%02ld%c%02ld");
+	}
+	secs %= 60;
+	(void)snprintf(buf, sizeof(buf), fmt,
+	mins, secs, decimal_point, psecs, hours, days);
+	(void)printf(wsfmt, v->width, buf);
+}
+
+#if defined(COMPAT_SUSV2)
+void
+etime
+(k, ve)
+	KINFO *k;
+	VARENT *ve;
+{
+	VAR *v;
+	struct timeval now;
+	long psecs, secs, mins, hours, days;
+	char fmt[FMTLEN];
+	char buf[BUFLEN];
+
+        v = ve->var;
+        if (!k->ki_u.u_valid) {
+                (void)printf(wsfmt, v->width, "-");
+                return;
+        }
+	gettime(NULL, &now);
+	secs = now.tv_sec - k->ki_u.u_start.tv_sec;
+	psecs = now.tv_usec - k->ki_u.u_start.tv_usec;
+	if (psecs < 0)
+		secs--, psecs += 1000000;
+	mins = secs / 60;
+	*fmt = '\0';
+#if defined(COMPAT_SUSV2)
+	if (susv2) {
+		hours = mins / 60;
+		days = hours / 24;
+		hours %= 24;
+		mins %= 60;
+		if (days)
+			strcat(fmt, "%5$02ld-");
+		if (hours)
+			strcat(fmt, "%4$02ld:");
+		strcat(fmt, "%1$02ld:%2$02ld");
+	} else
+#endif
+		strcat(fmt, "%3ld:%02ld.%02ld");
+	secs %= 60;
+	(void)snprintf(buf, sizeof(buf), fmt, mins, secs, psecs, hours, days);
+	(void)printf(wsfmt, v->width, buf);
 }
+#endif
+
+#define	fxtofl(fixpt)	((double)(fixpt) / fscale)
 
 double
 getpcpu(k)
@@ -508,7 +695,6 @@
 		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)
@@ -527,10 +713,10 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*.1f", v->width, getpcpu(k));
+	(void)printf(wffmt, v->width, getpcpu(k));
 }
 
-double
+static double
 getpmem(k)
 	KINFO *k;
 {
@@ -564,7 +750,7 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*.1f", v->width, getpmem(k));
+	(void)printf(wffmt, v->width, getpmem(k));
 }
 
 void
@@ -575,7 +761,7 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*ld", v->width,
+	(void)printf(wldfmt, v->width,
 	    k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0);
 }
 
@@ -588,7 +774,7 @@
 
 	v = ve->var;
 	/* XXX not yet */
-	(void)printf("%*s", v->width, "-");
+	(void)printf(wsfmt, v->width, "-");
 }
 
 void
@@ -599,7 +785,8 @@
 	VAR *v;
 
 	v = ve->var;
-	(void)printf("%*ld", v->width, (long)pgtok(KI_EPROC(k)->e_vm.vm_tsize));
+	(void)printf(wldfmt, v->width, 
+	    (long)pgtok(KI_EPROC(k)->e_vm.vm_tsize));
 }
 
 void
@@ -609,7 +796,7 @@
 {
 	VAR *v;
 	struct rtprio *prtp;
-	char str[8];
+	char buf[BUFLEN];
 	unsigned prio, type;
  
 	v = ve->var;
@@ -618,20 +805,20 @@
 	type = prtp->type;
 	switch (type) {
 	case RTP_PRIO_REALTIME:
-		snprintf(str, sizeof(str), "real:%u", prio);
+		snprintf(buf, sizeof(buf), "real:%u", prio);
 		break;
 	case RTP_PRIO_NORMAL:
-		strncpy(str, "normal", sizeof(str));
+		strncpy(buf, "normal", sizeof(buf));
 		break;
 	case RTP_PRIO_IDLE:
-		snprintf(str, sizeof(str), "idle:%u", prio);
+		snprintf(buf, sizeof(buf), "idle:%u", prio);
 		break;
 	default:
-		snprintf(str, sizeof(str), "%u:%u", type, prio);
+		snprintf(buf, sizeof(buf), "%u:%u", type, prio);
 		break;
 	}
-	str[sizeof(str) - 1] = '\0';
-	(void)printf("%*s", v->width, str);
+	buf[sizeof(buf) - 1] = '\0';
+	(void)printf(wsfmt, v->width, buf);
 }
 
 /*
@@ -643,7 +830,7 @@
 	char *bp;
 	VAR *v;
 {
-	static char ofmt[32] = "%";
+	static char ofmt[FMTLEN] = "%";
 	char *fcp, *cp;
 
 	cp = ofmt + 1;
@@ -719,7 +906,7 @@
 	if (k->ki_u.u_valid)
 		printval((char *)((char *)&k->ki_u + v->off), v);
 	else
-		(void)printf("%*s", v->width, "-");
+		(void)printf(wsfmt, v->width, "-");
 }
 
 void
@@ -733,5 +920,5 @@
 	if (k->ki_u.u_valid)
 		printval((char *)((char *)(&k->ki_u.u_ru) + v->off), v);
 	else
-		(void)printf("%*s", v->width, "-");
+		(void)printf(wsfmt, v->width, "-");
 }
Index: ps.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/ps.c,v
retrieving revision 1.30.2.5
diff -u -r1.30.2.5 ps.c
--- ps.c	1 Feb 2002 14:09:30 -0000	1.30.2.5
+++ ps.c	11 Jun 2002 02:30:49 -0000
@@ -32,17 +32,13 @@
  */
 
 #ifndef lint
-static char const copyright[] =
-"@(#) Copyright (c) 1990, 1993, 1994\n\
-	The Regents of the University of California.  All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
+#include <sys/cdefs.h>
+__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\\n\
+	The Regents of the University of California.  All rights reserved.\\n");
 #if 0
-static char sccsid[] = "@(#)ps.c	8.4 (Berkeley) 4/2/94";
+__RCSID("@(#)ps.c	8.4 (Berkeley) 4/2/94");
 #endif
-static const char rcsid[] =
-  "$FreeBSD: src/bin/ps/ps.c,v 1.30.2.5 2002/02/01 14:09:30 ru Exp $";
+__FBSDID("$FreeBSD: src/bin/ps/ps.c,v 1.30.2.5 2002/02/01 14:09:30 ru Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -52,6 +48,7 @@
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/sysctl.h>
+#include <sys/queue.h>
 
 #include <ctype.h>
 #include <err.h>
@@ -66,67 +63,125 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#if defined(COMPAT_SUSV2)
+#include <grp.h>
+#endif
 #include <pwd.h>
 #include <utmp.h>
 
 #include "ps.h"
 
-#define SEP ", \t"		/* username separators */
+#define SEP		", \t"		/* username separators */
+#define BUCKETS		32		/* power of 2 */
+#define SUSV2ENV	"SUSV2"		/* getenv() */
+#define OPTLEN		64
+#define UIDLEN		32
+
+enum entry {
+	DEV, UID, PID
+#if defined(COMPAT_SUSV2)
+	, FMT, GID, PGID, CMD
+#endif
+};
+
+enum sort {
+	DEFAULT, SORTMEM, SORTCPU
+};
+
+/*
+ * Global variables
+ */
 
 KINFO *kinfo;
-struct varent *vhead, *vtail;
+VARLIST varlist = STAILQ_HEAD_INITIALIZER(varlist);
 
-int	eval;			/* exit value */
-int	cflag;			/* -c */
-int	rawcpu;			/* -C */
-int	sumrusage;		/* -S */
-int	termwidth;		/* width of screen (0 == infinity) */
+int	eval;				/* exit value */
+int	rawcpu;				/* -C */
+int	cflag;				/* -c */
+int	sumrusage;			/* -S */
+int	termwidth;		/* -w : width of screen (0 == infinity) */
 int	totwidth;		/* calculated width of requested variables */
 
-static int needuser, needcomm, needenv;
+#if defined(COMPAT_SUSV2)
+int	susv2;				/* atoi(getenv("SUSV2")) != 0 */
+#endif
+
+/*
+ * Local variables
+ */
+
+					/* bsd options | susv2 options */
+static int	all;			/* -a | -a, -d, or -e */
+#if defined(COMPAT_SUSV2)
+static char   **cmds;			/* nop | -C */
+static int	ncmds;			/* ditto */
+#endif
+static int	needenv;		/* -e */
 #if defined(LAZY_PS)
-static int forceuread=0;
+static int	forceuread;		/* -f | nop */
 #else
-static int forceuread=1;
+static int	forceuread = 1;		/* ditto */
 #endif
+#if defined(COMPAT_SUSV2)
+static pid_t   *pgids;			/* nop | -g */
+static int	npgids;			/* ditto */
+#endif
+static int	prtheader;		/* -h */
+static char    *memf = _PATH_DEVNULL;	/* -M | -m */
+static enum sort sortby = DEFAULT;	/* -m | -r */
+static char    *nlistf = _PATH_DEVNULL;	/* -N | -n */
+static pid_t   *pids;			/* -p | -p */
+static int	npids;			/* ditto */
+static dev_t   *devs;			/* -T or -t | -t */
+static int	ndevs;			/* ditto */
+static uid_t   *uids;			/* -U | -u */
+static int	nuids;			/* ditto */
+#if defined(COMPAT_SUSV2)
+static uid_t   *ruids;			/* nop | -U */
+static int	nruids;			/* ditto */
+static gid_t   *gids;			/* nop | -G */
+static int	ngids;			/* ditto */
+#endif
+static char    *swapf = _PATH_DEVNULL;	/* -W | -w */
+static int	dropgid;		/* ditto */
+static int	xflag;			/* -x | -A or -e */
 
-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	 dynsizevars __P((KINFO *));
-static void	 sizevars __P((void));
-static void	 usage __P((void));
-static uid_t	*getuids(const char *, int *);
-
-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";
+static struct winsize ws;
+static int needuser, needcomm;		/* scanvars() */
 
-kvm_t *kd;
+/*
+ * Local functions
+ */
+static void	addentry __P((char *, void **, int *, enum entry));
+static void	dynsizevars __P((KINFO *));
+static char    *fmt __P((kvm_t *,
+			    char **(*)(kvm_t *, const struct kinfo_proc *, int),
+			    KINFO *, char *, int));
+static char    *kludge_oldps_options __P((char *));
+static void	bsd_parseopts __P((int, char *const *));
+#if defined(COMPAT_SUSV2)
+static void	susv2_parseopts __P((int, char *const *));
+#endif
+static int	pscomp __P((const void *, const void *));
+static void	saveuser __P((kvm_t *, KINFO *));
+static void	scanvars __P((void));
+static void	sizevars __P((void));
+static void	usage __P((void));
 
 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 *uids;
-	int all, ch, flag, i, fmt, lineno, nentries, dropgid;
-	int prtheader, wflag, what, xflg, uid, nuids;
-	char *nlistf, *memf, errbuf[_POSIX2_LINE_MAX];
+	kvm_t *kd;			/* kvm file descriptor */
+	struct kinfo_proc *kp;		/* kvm_getprocs() */
+	VARENT *vent;
+	int i, j, lineno;		/* indices */
+	int what, flag, nentries;	/* kvm_getprocs() */
+	char errbuf[_POSIX2_LINE_MAX];	/* kvm_openfiles() */
+#if defined(COMPAT_SUSV2)
+	char *cp;
+#endif
 
 	(void) setlocale(LC_ALL, "");
 
@@ -138,52 +193,340 @@
 	else
 		termwidth = ws.ws_col - 1;
 
+#if defined(COMPAT_SUSV2)
+	if ((cp = strrchr(argv[0], '/')) != NULL)
+		cp++;
+	else
+		cp = argv[0];
+	susv2 = strchr(cp, '5') != NULL;
+	if ((cp = getenv(SUSV2ENV)) != NULL)
+		susv2 = atoi(cp);	/* XXX ERANGE */
+#endif
+
 	if (argc > 1)
 		argv[1] = kludge_oldps_options(argv[1]);
 
-	all = fmt = prtheader = wflag = xflg = 0;
-	pid = -1;
-	nuids = 0;
-	uids = NULL;
-	ttydev = NODEV;
-	dropgid = 0;
-	memf = nlistf = _PATH_DEVNULL;
-	while ((ch = getopt(argc, argv,
+#if defined(COMPAT_SUSV2)
+	if (susv2)
+		susv2_parseopts(argc, argv);
+	else
+#endif
+		bsd_parseopts(argc, argv);
+
+	argc -= optind;
+	argv += optind;
+
+#ifdef	BACKWARD_COMPATIBILITY
+#if defined(COMPAT_SUSV2)
+	if (!susv2)
+#endif
+		if (*argv) {
+			nlistf = *argv;
+			if (*++argv) {
+				memf = *argv;
+#if defined(NO_SWAP)
+				if (*++argv)
+					swapf = *argv;
+#endif
+			}
+		}
+#endif
+	/*
+	 * Discard setgid privileges if not the running kernel so that bad
+	 * guys can't print interesting stuff from kernel memory.
+	 */
+	if (dropgid) {
+		setgid(getgid());
+		setuid(getuid());
+	}
+
+	kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf);
+	if (kd == 0)
+		errx(1, "%s", errbuf);
+
+	/* XXX - should be cleaner */
+	if (!all
+	    && !(nuids + npids + ndevs)
+#if defined(COMPAT_SUSV2)
+	    && !(ngids + npgids + nruids + ncmds)
+#endif
+	    ) {
+		char buf[UIDLEN];
+ 
+		snprintf(buf, sizeof(buf), "%d", getuid());
+		addentry(buf, (void **)&uids, &nuids, UID);
+	}
+
+	/*
+	 * scan requested variables, noting what structures are needed,
+	 * and adjusting header widths as appropriate.
+	 */
+	scanvars();
+
+	/*
+	 * get proc list
+	 */
+	if (nuids == 1) {
+		what = KERN_PROC_UID;
+		flag = *uids;
+	} else if (npids == 1) {
+		what = KERN_PROC_PID;
+		flag = *pids;
+	} else if (ndevs == 1) {
+		what = KERN_PROC_TTY;
+		flag = *devs;
+	}
+#if defined(COMPAT_SUSV2)
+	else if (npgids == 1) {
+		what = KERN_PROC_PGRP;
+		flag = *pgids;
+	} else if (nruids == 1) {
+		what = KERN_PROC_RUID;
+		flag = *ruids;
+	}
+#endif
+	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, "malloc");
+	for (i = nentries; --i >= 0; ++kp) {
+		kinfo[i].ki_p = kp;
+		if (needuser)
+			saveuser(kd, &kinfo[i]);
+		dynsizevars(&kinfo[i]);
+	}
+
+	sizevars();
+
+	/*
+	 * print header
+	 */
+	printheader();
+
+	/*
+	 * oops! no proc, goodbye.
+	 */
+	if (nentries == 0)
+		exit(1);
+
+	/*
+	 * 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 (xflag == 0 && (KI_EPROC(&kinfo[i])->e_tdev == NODEV ||
+		    (KI_PROC(&kinfo[i])->p_flag & P_CONTROLT) == 0))
+			continue;
+		if (nuids > 1) {
+			for (j = 0; j < nuids; j++)
+				if (KI_EPROC(&kinfo[i])->e_ucred.cr_uid ==
+				    uids[j])
+					break;
+			if (j == nuids)
+				continue;
+		}
+#if defined(COMPAT_SUSV2)
+		if (npids > 1) {
+			for (j = 0; j < npids; j++)
+				if (KI_PROC(&kinfo[i])->p_pid == pids[j])
+					break;
+			if (j == npids)
+				continue;
+		}
+		if (ndevs > 1) {
+			for (j = 0; j < ndevs; j++)
+				if (KI_EPROC(&kinfo[i])->e_tdev == devs[j])
+					break;
+			if (j == ndevs)
+				continue;
+		}
+		if (ngids > 0) {
+			for (j = 0; j < ngids; j++)
+				if (KI_EPROC(&kinfo[i])->e_ucred.cr_gid ==
+				    gids[j])
+					break;
+			if (j == ngids)
+				continue;
+		}
+		if (npgids > 1) {
+			for (j = 0; j < npgids; j++)
+				if (KI_EPROC(&kinfo[i])->e_pgid == pgids[j])
+					break;
+			if (j == npgids)
+				continue;
+		}
+		if (nruids > 1) {
+			for (j = 0; j < nruids; j++)
+				if (KI_EPROC(&kinfo[i])->e_pcred.p_ruid ==
+				    ruids[j])
+					break;
+			if (j == nruids)
+				continue;
+		}
+		if (ncmds > 0) {
+			for (j = 0; j < ncmds; j++)
+				if (!strncmp(KI_PROC(&kinfo[i])->p_comm,
+					    cmds[j],
+					    MIN(MAXCOMLEN, strlen(cmds[j]))))
+					break;
+			if (j == ncmds)
+				continue;
+		}
+#endif
+		STAILQ_FOREACH(vent, &varlist, list) {
+			(vent->var->oproc)(&kinfo[i], vent);
+			if (STAILQ_NEXT(vent, list) != NULL)
+				(void)putchar(' ');
+		}
+		(void)putchar('\n');
+		if (prtheader && lineno++ == prtheader - 4) {
+			(void)putchar('\n');
+			printheader();
+			lineno = 0;
+		}
+	}
+	/* XXX needed ? */
+	free(uids);
+#if defined(COMPAT_SUSV2)
+	free(devs);
+	free(gids);
+	free(pids);
+	free(pgids);
+	free(ruids);
+#endif
+
+	exit(eval);
+}
+
+static void
+bsd_parseopts(int argc, char *const *argv)
+{
+	static char	optstr[OPTLEN];
+	static char	optfmt[] = "%s%s%s%s%s";
+	static char    *opts = "aCceghjLlM:mN:O:o:p:rSTt:U:uvwx";
 #if defined(LAZY_PS)
-	    "aCcefghjLlM:mN:O:o:p:rSTt:U:uvwx")) != -1)
+	static char	optf[] = "f";
+#else
+	static char	optf[] = "";
+#endif
+#if defined(COMPAT_SUSV2)
+	static char	optb[] = "B";
+	static char	optv[] = "V";
 #else
-	    "aCceghjLlM:mN:O:o:p:rSTt:U:uvwx")) != -1)
+	static char	optb[] = "";
+	static char	optv[] = "";
 #endif
-		switch((char)ch) {
+#if defined(NO_SWAP)
+	static char	optw[] = "";
+#else
+	static char	optw[] = "W:";
+#endif
+	static char	o1fmt[] = "pid";
+	static char	o2fmt[] = "tt state time command";
+#if defined(COMPAT_BSD44)
+	static char	dfmt[] = "pid tt state time command";
+	static char	jfmt[] = "\
+user pid ppid pgid sess jobc state tt time command";
+	static char	lfmt[] = "\
+uid pid ppid cpu pri nice vsz rss wchan state tt time command";
+	static char	ufmt[] = "\
+user pid %cpu %mem vsz rss tt state start time command";
+	static char	vfmt[] = "\
+pid state time sl re pagein vsz rss lim tsiz %cpu %mem command";
+#else
+	static char	fmt[] = "\
+user[ju] uid[l] pid[djl1uv] ppid[jl] pgid[j] sess[j] jobc[j] cpu[l] \
+pri[l] nice[l] %cpu[u] %mem[u] vsz[lu] rss[lu] wchan[l] tt[d2u] \
+state[djl2uv] tt[jl] start[u] time[djl2uv] sl[v] re[v] pagein[v] \
+vsz[v] rss[v] lim[v] tsiz[v] %cpu[v] %mem[v] command[djl2uv]";
+#endif
+
+	int	ch;
+#if defined(COMPAT_BSD44)
+	int	fmt;
+#else
+	int	jflag;			/* -j */
+	int	lflag;			/* -l */
+	int	uflag;			/* -u */
+	int	vflag;			/* -v */
+	int	oflag;			/* -O or -o */
+	char   *ufmt;			/* ditto */
+	int	nufmt;
+#endif
+	int	wflag;			/* -w */
+
+#if defined(COMPAT_BSD44)
+	fmt = 0;
+#else
+	jflag = lflag = oflag = uflag = vflag = nufmt = 0;
+	ufmt = NULL;
+#endif
+	wflag = 0;
+
+	(void)snprintf(optstr, sizeof(optstr), optfmt,
+			opts, optb, optf, optv, optw);
+
+	while ((ch = getopt(argc, argv, optstr)) != -1)
+		switch(ch) {
 		case 'a':
 			all = 1;
 			break;
+#if defined(COMPAT_SUSV2)
+		case 'B':		/* no-op */
+			break;
+#endif
 		case 'C':
 			rawcpu = 1;
 			break;
 		case 'c':
 			cflag = 1;
 			break;
-		case 'e':			/* XXX set ufmt */
+		case 'e':		/* XXX set ufmt */
 			needenv = 1;
 			break;
-		case 'g':
-			break;			/* no-op */
+#if defined(LAZY_PS)
+		case 'f':
+			if (getuid() == 0 || getgid() == 0)
+			    forceuread = 1;
+			break;
+#endif
+		case 'g':		/* no-op */
+			break;
 		case 'h':
 			prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
 			break;
 		case 'j':
-			parsefmt(jfmt);
-			fmt = 1;
+#if defined(COMPAT_BSD44)
+			bsd_parsefmt(jfmt);
 			jfmt[0] = '\0';
+			fmt = 1;
+#else
+			jflag = 1;
+#endif
 			break;
 		case 'L':
 			showkey();
 			exit(0);
 		case 'l':
-			parsefmt(lfmt);
-			fmt = 1;
+#if defined(COMPAT_BSD44)
+			bsd_parsefmt(lfmt);
 			lfmt[0] = '\0';
+			fmt = 1;
+#else
+			lflag = 1;
+#endif
 			break;
 		case 'M':
 			memf = optarg;
@@ -197,25 +540,37 @@
 			dropgid = 1;
 			break;
 		case 'O':
-			parsefmt(o1);
-			parsefmt(optarg);
-			parsefmt(o2);
-			o1[0] = o2[0] = '\0';
+#if defined(COMPAT_BSD44)
+			bsd_parsefmt(o1fmt);
+			bsd_parsefmt(optarg);
+			bsd_parsefmt(o2fmt);
+			o1fmt[0] = o2fmt[0] = '\0';
 			fmt = 1;
+#else
+			/* XXX quick and dirty hack, need to be rewritten */
+			if (o1fmt[0]) {
+				addentry(o1fmt, (void **)&ufmt, &nufmt, FMT);
+				o1fmt[0] = '\0';
+			}
+			addentry(optarg, (void **)&ufmt, &nufmt, FMT);
+			oflag = 1;
+#endif
 			break;
 		case 'o':
-			parsefmt(optarg);
+#if defined(COMPAT_BSD44)
+			bsd_parsefmt(optarg);
 			fmt = 1;
-			break;
-#if defined(LAZY_PS)
-		case 'f':
-			if (getuid() == 0 || getgid() == 0)
-			    forceuread = 1;
-			break;
+#else
+			addentry(optarg, (void **)&ufmt, &nufmt, FMT);
+			oflag = 1;
 #endif
+			break;
 		case 'p':
-			pid = atol(optarg);
-			xflg = 1;
+#if defined(COMPAT_BSD44)
+			npids = 0;
+#endif
+			addentry(optarg, (void **)&pids, &npids, PID);
+			xflag = 1;
 			break;
 		case 'r':
 			sortby = SORTCPU;
@@ -228,217 +583,465 @@
 				errx(1, "stdin: not a terminal");
 			/* FALLTHROUGH */
 		case 't': {
-			struct stat sb;
-			char *ttypath, pathbuf[PATH_MAX];
-
-			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;
+#if defined(COMPAT_BSD44)
+			ndevs = 0;
+#endif
+			addentry(optarg, (void **)&devs, &ndevs, DEV);
 			break;
 		}
 		case 'U':
-			uids = getuids(optarg, &nuids);
-			xflg++;		/* XXX: intuitive? */
+#if defined(COMPAT_BSD44)
+			nuids = 0;
+#endif
+			addentry(optarg, (void **)&uids, &nuids, UID);
+			xflag = 1;	/* XXX intuitive? */
 			break;
 		case 'u':
-			parsefmt(ufmt);
 			sortby = SORTCPU;
-			fmt = 1;
+#if defined(COMPAT_BSD44)
+			bsd_parsefmt(ufmt);
 			ufmt[0] = '\0';
+			fmt = 1;
+#else
+			uflag = 1;
+#endif
 			break;
+#if defined(COMPAT_SUSV2)
+		case 'V':
+			susv2 = 1;
+			susv2_parseopts(argc, argv);
+			return;
+#endif
 		case 'v':
-			parsefmt(vfmt);
 			sortby = SORTMEM;
-			fmt = 1;
+#if defined(COMPAT_BSD44)
+			bsd_parsefmt(vfmt);
 			vfmt[0] = '\0';
+			fmt = 1;
+#else
+			vflag = 1;
+#endif
 			break;
+#if defined(NO_SWAP)
+		case 'W':
+			swapf = optarg;
+			dropgid = 1;
+			break;
+#endif
 		case 'w':
 			if (wflag)
 				termwidth = UNLIMITED;
 			else if (termwidth < 131)
 				termwidth = 131;
-			wflag++;
+			wflag = 1;
 			break;
 		case 'x':
-			xflg = 1;
+			xflag = 1;
 			break;
 		case '?':
 		default:
 			usage();
 		}
-	argc -= optind;
-	argv += optind;
 
-#define	BACKWARD_COMPATIBILITY
-#ifdef	BACKWARD_COMPATIBILITY
-	if (*argv) {
-		nlistf = *argv;
-		if (*++argv) {
-			memf = *argv;
+#if defined(COMPAT_BSD44)
+	if (!fmt)
+		bsd_parsefmt(dfmt);
+#else
+	if (oflag) {
+		if (!o1fmt[0]) {
+			addentry(o2fmt, (void **)&ufmt, &nufmt, FMT);
+			o2fmt[0] = '\0';
 		}
+		susv2_parsefmt(ufmt, NULL);
+		free(ufmt);		/* XXX needed? */
+	} else {
+		char	flags[5];	/* jluv\0 | d\0 */
+		char   *cp;
+
+		cp = flags;
+		if (jflag)
+			*cp++ = 'j';
+		if (lflag)
+			*cp++ = 'l';
+		if (uflag)
+			*cp++ = 'u';
+		if (vflag)
+			*cp++ = 'v';
+		if (cp == flags)
+			*cp++ = 'd';
+		*cp = '\0';
+		susv2_parsefmt(fmt, flags);
 	}
 #endif
-	/*
-	 * Discard setgid privileges if not the running kernel so that bad
-	 * guys can't print interesting stuff from kernel memory.
-	 */
-	if (dropgid) {
-		setgid(getgid());
-		setuid(getuid());
-	}
+}
 
-	kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
-	if (kd == 0)
-		errx(1, "%s", errbuf);
+#if defined(COMPAT_SUSV2)
+static void
+susv2_parseopts(int argc, char *const *argv)
+{
+	static char    *opts = "AaBC:defg:G:jLlm:n:o:p:t:u:U:Vw:";
+	static char	fmt[] = "\
+f[lx] s[lx] user[fx] uid[l] pid[dfjlx] ppid[flx] pgid[j] sid[j] \
+c[flx] pri[lx] nice[lx] addr[lx] vsz[lx] wchan[lx] stime[fx] \
+tt[dfjlx] time[dfjlx] comm[djl] args[fx]"; /* x means both f and l */
+
+	int	ch;
+	int	fflag = 0;		/* -f */
+	int	jflag = 0;		/* -j */
+	int	lflag = 0;		/* -l */
+	int	oflag = 0;		/* -o */
+	char   *ufmt;			/* ditto */
+	int	nufmt;
+
+	fflag = jflag = lflag = oflag = nufmt = 0;
+	ufmt = NULL;
+
+	while ((ch = getopt(argc, argv, opts)) != -1)
+		switch(ch) {
+		case 'A':
+			xflag = 1;
+			break;
+		case 'a':
+			all = 1;
+			break;
+		case 'B':
+			susv2 = 0;
+			bsd_parseopts(argc, argv);
+			return;
+		case 'C':
+			addentry(optarg, (void **)&cmds, &ncmds, CMD);
+			all = xflag = 1;
+			break;
+#if 0
+		case 'c':		/* not yet */
+			break;
+#endif
+		case 'd':
+			all = 1;
+			break;
+		case 'e':
+			all = xflag = 1;
+			break;
+		case 'f':
+			fflag = 1;
+			termwidth = UNLIMITED;
+			break;
+		case 'g':
+			addentry(optarg, (void **)&pgids, &npgids, PGID);
+			all = xflag = 1;
+			break;
+		case 'G':
+			addentry(optarg, (void **)&gids, &ngids, GID);
+			break;
+		case 'j':
+			jflag = 1;
+			break;
+		case 'L':
+			showkey();
+			exit(0);
+		case 'l':
+			lflag = 1;
+			break;
+		case 'm':
+			memf = optarg;
+			dropgid = 1;
+			break;
+		case 'n':
+			nlistf = optarg;
+			dropgid = 1;
+			break;
+		case 'o':
+			addentry(optarg, (void **)&ufmt, &nufmt, FMT);
+			oflag = 1;
+			break;
+		case 'p':
+			addentry(optarg, (void **)&pids, &npids, PID);
+			break;
+		case 't':
+			addentry(optarg, (void **)&devs, &ndevs, DEV);
+			break;
+		case 'u':
+			addentry(optarg, (void **)&uids, &nuids, UID);
+			break;
+		case 'U':
+			addentry(optarg, (void **)&ruids, &nruids, UID);
+			break;
+		case 'V':		/* no-op */
+			break;
+		case 'w':
+			swapf = optarg;
+			dropgid = 1;
+			break;
+#if 0
+		case 'y':		/* not yet */
+			break;
+#endif
+		case '?':
+		default:
+			usage();
+		}
 
-	if (!fmt)
-		parsefmt(dfmt);
+	if (oflag) {
+		susv2_parsefmt(ufmt, NULL);
+		free(ufmt);		/* XXX needed? */
+	} else {
+		char flags[3];		/* d\0 | jx\0 */
+		char *cp;
 
-	/* XXX - should be cleaner */
-	if (!all && ttydev == NODEV && pid == -1 && !nuids) {
-		if ((uids = malloc(sizeof (*uids))) == NULL)
-			errx(1, "malloc: %s", strerror(errno));
-		nuids = 1;
-		*uids = getuid();
+		cp = flags;
+		if (fflag && lflag)
+			*cp++ = 'x';
+		else if (fflag)
+			*cp++ = 'f';
+		else if (lflag)
+			*cp++ = 'l';
+		if (jflag)
+			*cp++ = 'j';
+		if (cp == flags)
+			*cp++ = 'd';
+		*cp = '\0';
+		susv2_parsefmt(fmt, flags);
 	}
+}
+#endif
 
-	/*
-	 * scan requested variables, noting what structures are needed,
-	 * and adjusting header widths as appropriate.
-	 */
-	scanvars();
-	/*
-	 * get proc list
-	 */
-	if (nuids == 1) {
-		what = KERN_PROC_UID;
-		flag = *uids;
-	} 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]);
-		dynsizevars(&kinfo[i]);
-	}
+static void
+addentry(char *arg, void **entries, int *nentries, enum entry what)
+{
+	dev_t dev;
+#if defined(COMPAT_SUSV2)
+	char *fmt;
+	gid_t gid;
+	pid_t pgid;
+	char *cmd;
+#endif
+	uid_t uid;
+	pid_t pid;
+	size_t len, lo, hi, have, need, size;
+	struct stat sb;
+	struct passwd *pwd;
+#if defined(COMPAT_SUSV2)
+	struct group *grp;
+#endif
+	char buf[MAX(UT_NAMESIZE + 1, PATH_MAX)];
+	char *ttypath, pathbuf[PATH_MAX];
 
-	sizevars();
+	dev = 0; uid = 0; pid = 0; size = 0; /* make gcc happy */
+#if defined(COMPAT_SUSV2)
+	gid = 0; pgid = 0; fmt = 0;	/* ditto */
+#endif
 
-	/*
-	 * print header
-	 */
-	printheader();
-	if (nentries == 0)
-		exit(1);
-	/*
-	 * 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;
-		if (nuids > 1) {
-			for (uid = 0; uid < nuids; uid++)
-				if (KI_EPROC(&kinfo[i])->e_ucred.cr_uid ==
-				    uids[uid])
-					break;
-			if (uid == nuids)
+	for (; (len = strcspn(arg, SEP)) > 0;
+	     arg += len + strspn(arg + len, SEP)) {
+		have = *nentries;
+		need = 1;
+
+		switch (what) {
+		case DEV:
+			if ((len + (strlen(_PATH_TTY) * *arg != '/'))
+			    >= sizeof(buf)) {
+				warnx("%.*s: path name too long",
+				    (int)len, arg);
 				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;
-		}
-	}
-	free(uids);
+			}
+			strncpy(buf, arg, len);
+			buf[len] = '\0';
 
-	exit(eval);
-}
+			if (strcmp(buf, "co") == 0)
+				ttypath = _PATH_CONSOLE;
+			else if (*buf != '/')
+				(void)snprintf(ttypath = pathbuf,
+				    sizeof(buf), "%s%s",
+#if !defined(COMPAT_BSD44)
+				    !strncmp(buf, "tty", 3) ? _PATH_DEV :
+#endif
+				    _PATH_TTY, buf);
+			else
+				ttypath = buf;
+			if (stat(ttypath, &sb) == -1)
+				err(1, "%s", ttypath);
+			if (!S_ISCHR(sb.st_mode))
+				errx(1, "%s: not a terminal", ttypath);
+			dev = sb.st_rdev;
+			size = sizeof(dev_t);
+			break;
+#if defined(COMPAT_SUSV2)
+		case FMT:
+			fmt = arg;
+			size = sizeof(char);
+			need += len + 1;
+			break;
+		case GID:
+			if (len >= sizeof(buf)) {
+				warnx("%.*s: group name too long",
+				    (int)len, arg);
+				continue;
+			}
+			strncpy(buf, arg, len);
+			buf[len] = '\0';
+#if !defined(COMPAT_BSD44)
+			gid = (gid_t)strtoul(buf, NULL, 10); /* XXX ERANGE */
+#endif
 
-uid_t *
-getuids(const char *arg, int *nuids)
-{
-	char name[UT_NAMESIZE + 1];
-	struct passwd *pwd;
-	uid_t *uids, *moreuids;
-	int l, alloc;
+			if ((grp = getgrnam(buf)) == NULL
+#if !defined(COMPAT_BSD44)
+#if defined(COMPAT_SUSV2)
+			    /* && susv2 */
+#endif
+			    && (grp = getgrgid(gid)) == NULL
+#endif
+				) {
+				warnx("%s: no such group", buf);
+				continue;
+			}
+			gid = grp->gr_gid;
+			size = sizeof(gid);
+			break;
+		case PGID:
+			if (len >= sizeof(buf)) {
+				warnx("%.*s: process group id too big",
+				    (int)len, arg);
+				continue;
+			}
+			strncpy(buf, arg, len);
+			buf[len] = '\0';
+
+			pgid = (pid_t)strtoul(buf, NULL, 10); /* XXX ERANGE */
+			size = sizeof(pid_t);
+			break;
+		case CMD:
+			cmd = arg;
+			size = sizeof(char *);
+			arg [len++] = '\0';
+			break;
+#endif
+		case UID:
+			if (len >= sizeof(buf)) {
+				warnx("%.*s: login name too long",
+				    (int)len, arg);
+				continue;
+			}
+			strncpy(buf, arg, len);
+			buf[len] = '\0';
+#if !defined(COMPAT_BSD44)
+			uid = (uid_t)strtoul(buf, NULL, 10); /* XXX ERANGE */
+#endif
 
+			if ((pwd = getpwnam(buf)) == NULL
+#if !defined(COMPAT_BSD44)
+#if defined(COMPAT_SUSV2)
+			    /* && susv2 */
+#endif
+			    && (pwd = getpwuid(uid)) == NULL
+#endif
+			    ) {
+				warnx("%s: no such user", buf);
+				continue;
+			}
+			uid = pwd->pw_uid;
+			size = sizeof(uid);
+			break;
+		case PID:
+			if (len >= sizeof(buf)) {
+				warnx("%.*s: process id too big",
+				    (int)len, arg);
+				continue;
+			}
+			strncpy(buf, arg, len);
+			buf[len] = '\0';
 
-	alloc = 0;
-	*nuids = 0;
-	uids = NULL;
-	for (; (l = strcspn(arg, SEP)) > 0; arg += l + strspn(arg + l, SEP)) {
-		if (l >= sizeof name) {
-			warnx("%.*s: name too long", l, arg);
-			continue;
+			pid = (pid_t)strtoul(buf, NULL, 10); /* XXX ERANGE */
+			size = sizeof(pid_t);
+			break;
 		}
-		strncpy(name, arg, l);
-		name[l] = '\0';
-		if ((pwd = getpwnam(name)) == NULL) {
-			warnx("%s: no such user", name);
-			continue;
+
+		lo = rounddown(have + need, BUCKETS);
+		hi = roundup2(have, BUCKETS);
+		if (lo >= hi) {
+			int n = roundup2(have + need, BUCKETS);
+			if ((*entries = realloc(*entries, n * size)) == NULL)
+				err(1, "realloc");
 		}
-		if (*nuids >= alloc) {
-			alloc = (alloc + 1) << 1;
-			moreuids = realloc(uids, alloc * sizeof (*uids));
-			if (moreuids == NULL) {
-				free(uids);
-				errx(1, "realloc: %s", strerror(errno));
-			}
-			uids = moreuids;
+
+		switch (what) {
+		case DEV:
+			*((dev_t **)entries)[(*nentries)++] = dev;
+			break;
+#if defined(COMPAT_SUSV2)
+		case FMT:
+			(*((char **)entries))[(*nentries)++] = ' ';
+			strncpy((*((char **)entries))+*nentries, fmt, len);
+			*nentries += len;
+			(*((char **)entries))[*nentries] = '\0';
+			break;
+		case GID:
+			(*((gid_t **)entries))[(*nentries)++] = gid;
+			break;
+		case PGID:
+			(*((pid_t **)entries))[(*nentries)++] = pgid;
+			break;
+		case CMD:
+			(*((char ***)entries))[(*nentries)++] = cmd;
+			break;
+#endif
+		case UID:
+			(*((uid_t **)entries))[(*nentries)++] = uid;
+			break;
+		case PID:
+			(*((pid_t **)entries))[(*nentries)++] = pid;
+			break;
 		}
-		uids[(*nuids)++] = pwd->pw_uid;
 	}
-	endpwent();
 
-	if (!*nuids)
-		errx(1, "No users specified");
+	switch (what) {
+	case UID:
+		endpwent();
+		break;
+#if defined(COMPAT_SUSV2)
+	case GID:
+		endgrent();
+		break;
+	default:		/* avoid gcc warnings */
+	}
+#endif
 
-	return uids;
+	if (!*nentries) {
+		switch (what) {
+		case DEV:
+			arg = "terminal";
+			break;
+#if defined(COMPAT_SUSV2)
+		case FMT:
+			arg = "format";
+			break;
+		case GID:
+			arg = "group";
+			break;
+		case PGID:
+			arg = "process group id";
+			break;
+		case CMD:
+			arg = "process name";
+			break;
+#endif
+		case UID:
+			arg = "user";
+			break;
+		case PID:
+			arg = "process id";
+			break;
+		}
+		errx(1, "no %s specified", arg);
+	}
 }
 
 static void
 scanvars()
 {
-	struct varent *vent;
+	VARENT *vent;
 	VAR *v;
 
-	for (vent = vhead; vent; vent = vent->next) {
+	STAILQ_FOREACH(vent, &varlist, list) {
 		v = vent->var;
 		if (v->flag & DSIZ) {
 			v->dwidth = v->width;
@@ -455,11 +1058,11 @@
 dynsizevars(ki)
 	KINFO *ki;
 {
-	struct varent *vent;
+	VARENT *vent;
 	VAR *v;
 	int i;
 
-	for (vent = vhead; vent; vent = vent->next) {
+	STAILQ_FOREACH(vent, &varlist, list) {
 		v = vent->var;
 		if (!(v->flag & DSIZ))
 			continue;
@@ -474,11 +1077,11 @@
 static void
 sizevars()
 {
-	struct varent *vent;
+	VARENT *vent;
 	VAR *v;
 	int i;
 
-	for (vent = vhead; vent; vent = vent->next) {
+	STAILQ_FOREACH(vent, &varlist, list) {
 		v = vent->var;
 		i = strlen(v->header);
 		if (v->width < i)
@@ -489,7 +1092,8 @@
 }
 
 static char *
-fmt(fn, ki, comm, maxlen)
+fmt(kd, fn, ki, comm, maxlen)
+	kvm_t *kd;
 	char **(*fn) __P((kvm_t *, const struct kinfo_proc *, int));
 	KINFO *ki;
 	char *comm;
@@ -497,8 +1101,8 @@
 {
 	char *s;
 
-	if ((s =
-	    fmt_argv((*fn)(kd, ki->ki_p, termwidth), comm, maxlen)) == NULL)
+	if ((s = fmt_argv((*fn)(kd, ki->ki_p, termwidth),
+				comm, maxlen)) == NULL)
 		err(1, NULL);
 	return (s);
 }
@@ -506,7 +1110,8 @@
 #define UREADOK(ki)	(forceuread || (KI_PROC(ki)->p_flag & P_INMEM))
 
 static void
-saveuser(ki)
+saveuser(kd, ki)
+	kvm_t *kd;
 	KINFO *ki;
 {
 	struct usave *usp;
@@ -530,7 +1135,7 @@
 	 * save arguments if needed
 	 */
 	if (needcomm && (UREADOK(ki) || (KI_PROC(ki)->p_args != NULL))) {
-		ki->ki_args = fmt(kvm_getargv, ki, KI_PROC(ki)->p_comm,
+		ki->ki_args = fmt(kd, kvm_getargv, ki, KI_PROC(ki)->p_comm,
 		    MAXCOMLEN);
 	} else if (needcomm) {
 		ki->ki_args = malloc(strlen(KI_PROC(ki)->p_comm) + 3);
@@ -539,7 +1144,7 @@
 		ki->ki_args = NULL;
 	}
 	if (needenv && UREADOK(ki)) {
-		ki->ki_env = fmt(kvm_getenvv, ki, (char *)NULL, 0);
+		ki->ki_env = fmt(kd, kvm_getenvv, ki, (char *)NULL, 0);
 	} else if (needenv) {
 		ki->ki_env = malloc(3);
 		strcpy(ki->ki_env, "()");
@@ -548,13 +1153,14 @@
 	}
 }
 
+#define VSIZE(k) (KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + \
+		  KI_EPROC(k)->e_vm.vm_tsize)
+
 static int
 pscomp(a, b)
 	const void *a, *b;
 {
 	int i;
-#define VSIZE(k) (KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + \
-		  KI_EPROC(k)->e_vm.vm_tsize)
 
 	if (sortby == SORTCPU)
 		return (getpcpu((KINFO *)b) - getpcpu((KINFO *)a));
@@ -586,12 +1192,16 @@
 
 	len = strlen(s);
 	if ((newopts = ns = malloc(len + 2)) == NULL)
-		err(1, NULL);
+		err(1, "malloc");
 	/*
 	 * options begin with '-'
 	 */
-	if (*s != '-')
+	if (*s != '-') {
+#if defined(COMPAT_SUSV2)
+		susv2 = 0;
+#endif
 		*ns++ = '-';	/* add option flag */
+	}
 	/*
 	 * gaze to end of argv[1]
 	 */
@@ -634,10 +1244,42 @@
 static void
 usage()
 {
+#if defined(LAZY_PS)
+	static char	optf[] = "f";
+#else
+	static char	optf[] = "";
+#endif
+#if defined(COMPAT_BSD44)
+	static char	list[] = "";
+#else
+	static char	list[] = "list";
+#endif
+#if defined(COMPAT_SUSV2)
+	static char	optb[] = "B";
+	static char	optv[] = "V";
+#else
+	static char	optb[] = "";
+	static char	optv[] = "";
+#endif
+#if defined(NO_SWAP)
+	static char	optw[] = "";
+#else
+	static char	optw[] = " [-W swap]";
+#endif
 
-	(void)fprintf(stderr, "%s\n%s\n%s\n",
-	    "usage: ps [-aChjlmrSTuvwx] [-O|o fmt] [-p pid] [-t tty] [-U user]",
-	    "          [-M core] [-N system]",
-	    "       ps [-L]");
+#if defined(COMPAT_SUSV2)
+	if (susv2)
+		(void)fprintf(stderr, "\
+usage: ps [-AaBdefjl] [-C cmdlist] [-g pgrplist] [-G grouplist] [-o fmt]\n\
+          [-p pidlist] [-t ttylist] [-u userlist] [-U userlist]\n\
+          [-m core] [-n system] [-w swap]\n\
+");
+	else
+#endif
+		(void)fprintf(stderr, "\
+usage: ps [-a%sC%shjlmrSTuv%swx] [-O|-o fmt] [-p pid%s] [-t tty%s]\n\
+          [-U user%s] [-M core] [-N system]%s\n\
+       ps [-L]\n\
+", optb, optf, optv, list, list, list, optw);
 	exit(1);
 }
Index: ps.h
===================================================================
RCS file: /home/ncvs/src/bin/ps/ps.h,v
retrieving revision 1.7
diff -u -r1.7 ps.h
--- ps.h	27 Aug 1999 23:14:52 -0000	1.7
+++ ps.h	3 Jun 2001 20:10:12 -0000
@@ -34,6 +34,10 @@
  * $FreeBSD: src/bin/ps/ps.h,v 1.7 1999/08/27 23:14:52 peter Exp $
  */
 
+#if !defined(COMPAT_BSD44) && !defined(COMPAT_SUSV2)
+#define COMPAT_BSD44
+#endif
+
 #define	UNLIMITED	0	/* unlimited terminal width */
 enum type { CHAR, UCHAR, SHORT, USHORT, INT, UINT, LONG, ULONG, KPTR };
 
@@ -56,8 +60,10 @@
 } KINFO;
 
 /* Variables. */
+typedef STAILQ_HEAD(varlist, varent) VARLIST;
+
 typedef struct varent {
-	struct varent *next;
+	STAILQ_ENTRY(varent) list;
 	struct var *var;
 } VARENT;
 

--/NkBOFFp2J2Af1nK--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-standards" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020611030857.GB14401>