xref: /titanic_51/usr/src/cmd/ps/ps.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate  * ps -- print things about processes.
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate #include <stdio.h>
37*7c478bd9Sstevel@tonic-gate #include <ctype.h>
38*7c478bd9Sstevel@tonic-gate #include <string.h>
39*7c478bd9Sstevel@tonic-gate #include <errno.h>
40*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
41*7c478bd9Sstevel@tonic-gate #include <pwd.h>
42*7c478bd9Sstevel@tonic-gate #include <grp.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
46*7c478bd9Sstevel@tonic-gate #include <unistd.h>
47*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
48*7c478bd9Sstevel@tonic-gate #include <limits.h>
49*7c478bd9Sstevel@tonic-gate #include <dirent.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/fault.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
54*7c478bd9Sstevel@tonic-gate #include <procfs.h>
55*7c478bd9Sstevel@tonic-gate #include <locale.h>
56*7c478bd9Sstevel@tonic-gate #include <wctype.h>
57*7c478bd9Sstevel@tonic-gate #include <wchar.h>
58*7c478bd9Sstevel@tonic-gate #include <libw.h>
59*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/pset.h>
62*7c478bd9Sstevel@tonic-gate #include <project.h>
63*7c478bd9Sstevel@tonic-gate #include <zone.h>
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	min(a, b)	((a) > (b) ? (b) : (a))
66*7c478bd9Sstevel@tonic-gate #define	max(a, b)	((a) < (b) ? (b) : (a))
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate #define	NTTYS	20	/* initial size of table for -t option  */
69*7c478bd9Sstevel@tonic-gate #define	SIZ	30	/* initial size of tables for -p, -s, -g, and -z */
70*7c478bd9Sstevel@tonic-gate #define	ARGSIZ	30	/* size of buffer holding args for -t, -p, -u options */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define	MAXUGNAME 10	/* max chars in a user/group name or printed u/g id */
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /* Structure for storing user or group info */
75*7c478bd9Sstevel@tonic-gate struct ugdata {
76*7c478bd9Sstevel@tonic-gate 	id_t	id;			/* numeric user-id or group-id */
77*7c478bd9Sstevel@tonic-gate 	char	name[MAXUGNAME+1];	/* user/group name, null terminated */
78*7c478bd9Sstevel@tonic-gate };
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate struct ughead {
81*7c478bd9Sstevel@tonic-gate 	size_t	size;		/* number of ugdata structs allocated */
82*7c478bd9Sstevel@tonic-gate 	size_t	nent;		/* number of active entries */
83*7c478bd9Sstevel@tonic-gate 	struct ugdata *ent;	/* pointer to array of actual entries */
84*7c478bd9Sstevel@tonic-gate };
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate enum fname {	/* enumeration of field names */
87*7c478bd9Sstevel@tonic-gate 	F_USER,		/* effective user of the process */
88*7c478bd9Sstevel@tonic-gate 	F_RUSER,	/* real user of the process */
89*7c478bd9Sstevel@tonic-gate 	F_GROUP,	/* effective group of the process */
90*7c478bd9Sstevel@tonic-gate 	F_RGROUP,	/* real group of the process */
91*7c478bd9Sstevel@tonic-gate 	F_UID,		/* numeric effective uid of the process */
92*7c478bd9Sstevel@tonic-gate 	F_RUID,		/* numeric real uid of the process */
93*7c478bd9Sstevel@tonic-gate 	F_GID,		/* numeric effective gid of the process */
94*7c478bd9Sstevel@tonic-gate 	F_RGID,		/* numeric real gid of the process */
95*7c478bd9Sstevel@tonic-gate 	F_PID,		/* process id */
96*7c478bd9Sstevel@tonic-gate 	F_PPID,		/* parent process id */
97*7c478bd9Sstevel@tonic-gate 	F_PGID,		/* process group id */
98*7c478bd9Sstevel@tonic-gate 	F_SID,		/* session id */
99*7c478bd9Sstevel@tonic-gate 	F_PSR,		/* bound processor */
100*7c478bd9Sstevel@tonic-gate 	F_LWP,		/* lwp-id */
101*7c478bd9Sstevel@tonic-gate 	F_NLWP,		/* number of lwps */
102*7c478bd9Sstevel@tonic-gate 	F_OPRI,		/* old priority (obsolete) */
103*7c478bd9Sstevel@tonic-gate 	F_PRI,		/* new priority */
104*7c478bd9Sstevel@tonic-gate 	F_F,		/* process flags */
105*7c478bd9Sstevel@tonic-gate 	F_S,		/* letter indicating the state */
106*7c478bd9Sstevel@tonic-gate 	F_C,		/* processor utilization (obsolete) */
107*7c478bd9Sstevel@tonic-gate 	F_PCPU,		/* percent of recently used cpu time */
108*7c478bd9Sstevel@tonic-gate 	F_PMEM,		/* percent of physical memory used (rss) */
109*7c478bd9Sstevel@tonic-gate 	F_OSZ,		/* virtual size of the process in pages */
110*7c478bd9Sstevel@tonic-gate 	F_VSZ,		/* virtual size of the process in kilobytes */
111*7c478bd9Sstevel@tonic-gate 	F_RSS,		/* resident set size of the process in kilobytes */
112*7c478bd9Sstevel@tonic-gate 	F_NICE,		/* "nice" value of the process */
113*7c478bd9Sstevel@tonic-gate 	F_CLASS,	/* scheduler class */
114*7c478bd9Sstevel@tonic-gate 	F_STIME,	/* start time of the process, hh:mm:ss or Month Day */
115*7c478bd9Sstevel@tonic-gate 	F_ETIME,	/* elapsed time of the process, [[dd-]hh:]mm:ss */
116*7c478bd9Sstevel@tonic-gate 	F_TIME,		/* cpu time of the process, [[dd-]hh:]mm:ss */
117*7c478bd9Sstevel@tonic-gate 	F_TTY,		/* name of the controlling terminal */
118*7c478bd9Sstevel@tonic-gate 	F_ADDR,		/* address of the process (obsolete) */
119*7c478bd9Sstevel@tonic-gate 	F_WCHAN,	/* wait channel (sleep condition variable) */
120*7c478bd9Sstevel@tonic-gate 	F_FNAME,	/* file name of command */
121*7c478bd9Sstevel@tonic-gate 	F_COMM,		/* name of command (argv[0] value) */
122*7c478bd9Sstevel@tonic-gate 	F_ARGS,		/* name of command plus all its arguments */
123*7c478bd9Sstevel@tonic-gate 	F_TASKID,	/* task id */
124*7c478bd9Sstevel@tonic-gate 	F_PROJID,	/* project id */
125*7c478bd9Sstevel@tonic-gate 	F_PROJECT,	/* project name of the process */
126*7c478bd9Sstevel@tonic-gate 	F_PSET,		/* bound processor set */
127*7c478bd9Sstevel@tonic-gate 	F_ZONE,		/* zone name */
128*7c478bd9Sstevel@tonic-gate 	F_ZONEID,	/* zone id */
129*7c478bd9Sstevel@tonic-gate 	F_CTID		/* process contract id */
130*7c478bd9Sstevel@tonic-gate };
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate struct field {
133*7c478bd9Sstevel@tonic-gate 	struct field	*next;		/* linked list */
134*7c478bd9Sstevel@tonic-gate 	int		fname;		/* field index */
135*7c478bd9Sstevel@tonic-gate 	const char	*header;	/* header to use */
136*7c478bd9Sstevel@tonic-gate 	int		width;		/* width of field */
137*7c478bd9Sstevel@tonic-gate };
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate static	struct field *fields = NULL;	/* fields selected via -o */
140*7c478bd9Sstevel@tonic-gate static	struct field *last_field = NULL;
141*7c478bd9Sstevel@tonic-gate static	int do_header = 0;
142*7c478bd9Sstevel@tonic-gate static	struct timeval now;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /* array of defined fields, in fname order */
145*7c478bd9Sstevel@tonic-gate struct def_field {
146*7c478bd9Sstevel@tonic-gate 	const char *fname;
147*7c478bd9Sstevel@tonic-gate 	const char *header;
148*7c478bd9Sstevel@tonic-gate 	int width;
149*7c478bd9Sstevel@tonic-gate 	int minwidth;
150*7c478bd9Sstevel@tonic-gate };
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate static struct def_field fname[] = {
153*7c478bd9Sstevel@tonic-gate 	/* fname	header		width	minwidth */
154*7c478bd9Sstevel@tonic-gate 	{ "user",	"USER",		8,	8	},
155*7c478bd9Sstevel@tonic-gate 	{ "ruser",	"RUSER",	8,	8	},
156*7c478bd9Sstevel@tonic-gate 	{ "group",	"GROUP",	8,	8	},
157*7c478bd9Sstevel@tonic-gate 	{ "rgroup",	"RGROUP",	8,	8	},
158*7c478bd9Sstevel@tonic-gate 	{ "uid",	"UID",		5,	5	},
159*7c478bd9Sstevel@tonic-gate 	{ "ruid",	"RUID",		5,	5	},
160*7c478bd9Sstevel@tonic-gate 	{ "gid",	"GID",		5,	5	},
161*7c478bd9Sstevel@tonic-gate 	{ "rgid",	"RGID",		5,	5	},
162*7c478bd9Sstevel@tonic-gate 	{ "pid",	"PID",		5,	5	},
163*7c478bd9Sstevel@tonic-gate 	{ "ppid",	"PPID",		5,	5	},
164*7c478bd9Sstevel@tonic-gate 	{ "pgid",	"PGID",		5,	5	},
165*7c478bd9Sstevel@tonic-gate 	{ "sid",	"SID",		5,	5	},
166*7c478bd9Sstevel@tonic-gate 	{ "psr",	"PSR",		3,	2	},
167*7c478bd9Sstevel@tonic-gate 	{ "lwp",	"LWP",		6,	2	},
168*7c478bd9Sstevel@tonic-gate 	{ "nlwp",	"NLWP",		4,	2	},
169*7c478bd9Sstevel@tonic-gate 	{ "opri",	"PRI",		3,	2	},
170*7c478bd9Sstevel@tonic-gate 	{ "pri",	"PRI",		3,	2	},
171*7c478bd9Sstevel@tonic-gate 	{ "f",		"F",		2,	2	},
172*7c478bd9Sstevel@tonic-gate 	{ "s",		"S",		1,	1	},
173*7c478bd9Sstevel@tonic-gate 	{ "c",		"C",		2,	2	},
174*7c478bd9Sstevel@tonic-gate 	{ "pcpu",	"%CPU",		4,	4	},
175*7c478bd9Sstevel@tonic-gate 	{ "pmem",	"%MEM",		4,	4	},
176*7c478bd9Sstevel@tonic-gate 	{ "osz",	"SZ",		4,	4	},
177*7c478bd9Sstevel@tonic-gate 	{ "vsz",	"VSZ",		4,	4	},
178*7c478bd9Sstevel@tonic-gate 	{ "rss",	"RSS",		4,	4	},
179*7c478bd9Sstevel@tonic-gate 	{ "nice",	"NI",		2,	2	},
180*7c478bd9Sstevel@tonic-gate 	{ "class",	"CLS",		4,	2	},
181*7c478bd9Sstevel@tonic-gate 	{ "stime",	"STIME",	8,	8	},
182*7c478bd9Sstevel@tonic-gate 	{ "etime",	"ELAPSED",	11,	7	},
183*7c478bd9Sstevel@tonic-gate 	{ "time",	"TIME",		11,	5	},
184*7c478bd9Sstevel@tonic-gate 	{ "tty",	"TT",		7,	7	},
185*7c478bd9Sstevel@tonic-gate #ifdef _LP64
186*7c478bd9Sstevel@tonic-gate 	{ "addr",	"ADDR",		16,	8	},
187*7c478bd9Sstevel@tonic-gate 	{ "wchan",	"WCHAN",	16,	8	},
188*7c478bd9Sstevel@tonic-gate #else
189*7c478bd9Sstevel@tonic-gate 	{ "addr",	"ADDR",		8,	8	},
190*7c478bd9Sstevel@tonic-gate 	{ "wchan",	"WCHAN",	8,	8	},
191*7c478bd9Sstevel@tonic-gate #endif
192*7c478bd9Sstevel@tonic-gate 	{ "fname",	"COMMAND",	8,	8	},
193*7c478bd9Sstevel@tonic-gate 	{ "comm",	"COMMAND",	80,	8	},
194*7c478bd9Sstevel@tonic-gate 	{ "args",	"COMMAND",	80,	80	},
195*7c478bd9Sstevel@tonic-gate 	{ "taskid",	"TASKID",	5,	5	},
196*7c478bd9Sstevel@tonic-gate 	{ "projid",	"PROJID",	5,	5	},
197*7c478bd9Sstevel@tonic-gate 	{ "project",	"PROJECT",	8,	8	},
198*7c478bd9Sstevel@tonic-gate 	{ "pset",	"PSET",		3,	3	},
199*7c478bd9Sstevel@tonic-gate 	{ "zone",	"ZONE",		8,	8	},
200*7c478bd9Sstevel@tonic-gate 	{ "zoneid",	"ZONEID",	5,	5	},
201*7c478bd9Sstevel@tonic-gate 	{ "ctid",	"CTID",		5,	5	},
202*7c478bd9Sstevel@tonic-gate };
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate #define	NFIELDS	(sizeof (fname) / sizeof (fname[0]))
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate static	int	retcode = 1;
207*7c478bd9Sstevel@tonic-gate static	int	lflg;
208*7c478bd9Sstevel@tonic-gate static	int	Aflg;
209*7c478bd9Sstevel@tonic-gate static	int	uflg;
210*7c478bd9Sstevel@tonic-gate static	int	Uflg;
211*7c478bd9Sstevel@tonic-gate static	int	Gflg;
212*7c478bd9Sstevel@tonic-gate static	int	aflg;
213*7c478bd9Sstevel@tonic-gate static	int	dflg;
214*7c478bd9Sstevel@tonic-gate static	int	Lflg;
215*7c478bd9Sstevel@tonic-gate static	int	Pflg;
216*7c478bd9Sstevel@tonic-gate static	int	yflg;
217*7c478bd9Sstevel@tonic-gate static	int	pflg;
218*7c478bd9Sstevel@tonic-gate static	int	fflg;
219*7c478bd9Sstevel@tonic-gate static	int	cflg;
220*7c478bd9Sstevel@tonic-gate static	int	jflg;
221*7c478bd9Sstevel@tonic-gate static	int	gflg;
222*7c478bd9Sstevel@tonic-gate static	int	sflg;
223*7c478bd9Sstevel@tonic-gate static	int	tflg;
224*7c478bd9Sstevel@tonic-gate static	int	zflg;
225*7c478bd9Sstevel@tonic-gate static	int	Zflg;
226*7c478bd9Sstevel@tonic-gate static	uid_t	tuid = -1;
227*7c478bd9Sstevel@tonic-gate static	int	errflg;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate static	int	ndev;		/* number of devices */
230*7c478bd9Sstevel@tonic-gate static	int	maxdev;		/* number of devl structures allocated */
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate #define	DNINCR	100
233*7c478bd9Sstevel@tonic-gate #define	DNSIZE	14
234*7c478bd9Sstevel@tonic-gate static struct devl {		/* device list   */
235*7c478bd9Sstevel@tonic-gate 	char	dname[DNSIZE];	/* device name   */
236*7c478bd9Sstevel@tonic-gate 	dev_t	ddev;		/* device number */
237*7c478bd9Sstevel@tonic-gate } *devl;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate static	struct tty {
240*7c478bd9Sstevel@tonic-gate 	char *tname;
241*7c478bd9Sstevel@tonic-gate 	dev_t tdev;
242*7c478bd9Sstevel@tonic-gate } *tty = NULL;			/* for t option */
243*7c478bd9Sstevel@tonic-gate static	size_t	ttysz = 0;
244*7c478bd9Sstevel@tonic-gate static	int	ntty = 0;
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate static	pid_t	*pid = NULL;	/* for p option */
247*7c478bd9Sstevel@tonic-gate static	size_t	pidsz = 0;
248*7c478bd9Sstevel@tonic-gate static	size_t	npid = 0;
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate static	pid_t	*grpid = NULL;	/* for g option */
251*7c478bd9Sstevel@tonic-gate static	size_t	grpidsz = 0;
252*7c478bd9Sstevel@tonic-gate static	int	ngrpid = 0;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate static	pid_t	*sessid = NULL;	/* for s option */
255*7c478bd9Sstevel@tonic-gate static	size_t	sessidsz = 0;
256*7c478bd9Sstevel@tonic-gate static	int	nsessid = 0;
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate static	zoneid_t *zoneid = NULL; /* for z option */
259*7c478bd9Sstevel@tonic-gate static	size_t	zoneidsz = 0;
260*7c478bd9Sstevel@tonic-gate static	int	nzoneid = 0;
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate static	int	kbytes_per_page;
263*7c478bd9Sstevel@tonic-gate static	int	pidwidth;
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate static	char	*procdir = "/proc";	/* standard /proc directory */
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate static struct ughead	euid_tbl;	/* table to store selected euid's */
268*7c478bd9Sstevel@tonic-gate static struct ughead	ruid_tbl;	/* table to store selected real uid's */
269*7c478bd9Sstevel@tonic-gate static struct ughead	egid_tbl;	/* table to store selected egid's */
270*7c478bd9Sstevel@tonic-gate static struct ughead	rgid_tbl;	/* table to store selected real gid's */
271*7c478bd9Sstevel@tonic-gate static prheader_t *lpsinfobuf;		/* buffer to contain lpsinfo */
272*7c478bd9Sstevel@tonic-gate static size_t	lpbufsize;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  * This constant defines the sentinal number of process IDs below which we
276*7c478bd9Sstevel@tonic-gate  * only examine individual entries in /proc rather than scanning through
277*7c478bd9Sstevel@tonic-gate  * /proc. This optimization is a huge win in the common case.
278*7c478bd9Sstevel@tonic-gate  */
279*7c478bd9Sstevel@tonic-gate #define	PTHRESHOLD	40
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate static	void	usage(void);
282*7c478bd9Sstevel@tonic-gate static	char	*getarg(char **);
283*7c478bd9Sstevel@tonic-gate static	char	*parse_format(char *);
284*7c478bd9Sstevel@tonic-gate static	char	*gettty(psinfo_t *);
285*7c478bd9Sstevel@tonic-gate static	int	prfind(int, psinfo_t *, char **);
286*7c478bd9Sstevel@tonic-gate static	void	prcom(psinfo_t *, char *);
287*7c478bd9Sstevel@tonic-gate static	void	prtpct(ushort_t, int);
288*7c478bd9Sstevel@tonic-gate static	void	print_time(time_t, int);
289*7c478bd9Sstevel@tonic-gate static	void	print_field(psinfo_t *, struct field *, const char *);
290*7c478bd9Sstevel@tonic-gate static	void	print_zombie_field(psinfo_t *, struct field *, const char *);
291*7c478bd9Sstevel@tonic-gate static	void	pr_fields(psinfo_t *, const char *,
292*7c478bd9Sstevel@tonic-gate 		void (*print_fld)(psinfo_t *, struct field *, const char *));
293*7c478bd9Sstevel@tonic-gate static	int	search(pid_t *, int, pid_t);
294*7c478bd9Sstevel@tonic-gate static	void	add_ugentry(struct ughead *, char *);
295*7c478bd9Sstevel@tonic-gate static	int	uconv(struct ughead *);
296*7c478bd9Sstevel@tonic-gate static	int	gconv(struct ughead *);
297*7c478bd9Sstevel@tonic-gate static	int	ugfind(uid_t, struct ughead *);
298*7c478bd9Sstevel@tonic-gate static	void	prtime(timestruc_t, int, int);
299*7c478bd9Sstevel@tonic-gate static	void	przom(psinfo_t *);
300*7c478bd9Sstevel@tonic-gate static	int	namencnt(char *, int, int);
301*7c478bd9Sstevel@tonic-gate static	char	*err_string(int);
302*7c478bd9Sstevel@tonic-gate static	int	print_proc(char *pname);
303*7c478bd9Sstevel@tonic-gate static	time_t	delta_secs(const timestruc_t *);
304*7c478bd9Sstevel@tonic-gate static	int	str2id(const char *, pid_t *, long, long);
305*7c478bd9Sstevel@tonic-gate static	void	*Realloc(void *, size_t);
306*7c478bd9Sstevel@tonic-gate static	int	pidcmp(const void *p1, const void *p2);
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate int
309*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
310*7c478bd9Sstevel@tonic-gate {
311*7c478bd9Sstevel@tonic-gate 	char	*p;
312*7c478bd9Sstevel@tonic-gate 	char	*p1;
313*7c478bd9Sstevel@tonic-gate 	char	*parg;
314*7c478bd9Sstevel@tonic-gate 	int	c;
315*7c478bd9Sstevel@tonic-gate 	int	i;
316*7c478bd9Sstevel@tonic-gate 	int	pgerrflg = 0;	/* err flg: non-numeric arg w/p & g options */
317*7c478bd9Sstevel@tonic-gate 	size_t	size;
318*7c478bd9Sstevel@tonic-gate 	DIR	*dirp;
319*7c478bd9Sstevel@tonic-gate 	struct dirent *dentp;
320*7c478bd9Sstevel@tonic-gate 	pid_t	maxpid;
321*7c478bd9Sstevel@tonic-gate 	pid_t	id;
322*7c478bd9Sstevel@tonic-gate 	int	ret;
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
325*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
326*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
327*7c478bd9Sstevel@tonic-gate #endif
328*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	(void) memset(&euid_tbl, 0, sizeof (euid_tbl));
331*7c478bd9Sstevel@tonic-gate 	(void) memset(&ruid_tbl, 0, sizeof (ruid_tbl));
332*7c478bd9Sstevel@tonic-gate 	(void) memset(&egid_tbl, 0, sizeof (egid_tbl));
333*7c478bd9Sstevel@tonic-gate 	(void) memset(&rgid_tbl, 0, sizeof (rgid_tbl));
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	kbytes_per_page = sysconf(_SC_PAGESIZE) / 1024;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&now, NULL);
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	/*
340*7c478bd9Sstevel@tonic-gate 	 * calculate width of pid fields based on configured MAXPID
341*7c478bd9Sstevel@tonic-gate 	 * (must be at least 5 to retain output format compatibility)
342*7c478bd9Sstevel@tonic-gate 	 */
343*7c478bd9Sstevel@tonic-gate 	id = maxpid = (pid_t)sysconf(_SC_MAXPID);
344*7c478bd9Sstevel@tonic-gate 	pidwidth = 1;
345*7c478bd9Sstevel@tonic-gate 	while ((id /= 10) > 0)
346*7c478bd9Sstevel@tonic-gate 		++pidwidth;
347*7c478bd9Sstevel@tonic-gate 	pidwidth = pidwidth < 5 ? 5 : pidwidth;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 	fname[F_PID].width = fname[F_PPID].width = pidwidth;
350*7c478bd9Sstevel@tonic-gate 	fname[F_PGID].width = fname[F_SID].width = pidwidth;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "jlfceAadLPyZt:p:g:u:U:G:n:s:o:z:")) !=
353*7c478bd9Sstevel@tonic-gate 	    EOF)
354*7c478bd9Sstevel@tonic-gate 		switch (c) {
355*7c478bd9Sstevel@tonic-gate 		case 'l':		/* long listing */
356*7c478bd9Sstevel@tonic-gate 			lflg++;
357*7c478bd9Sstevel@tonic-gate 			break;
358*7c478bd9Sstevel@tonic-gate 		case 'f':		/* full listing */
359*7c478bd9Sstevel@tonic-gate 			fflg++;
360*7c478bd9Sstevel@tonic-gate 			break;
361*7c478bd9Sstevel@tonic-gate 		case 'j':
362*7c478bd9Sstevel@tonic-gate 			jflg++;
363*7c478bd9Sstevel@tonic-gate 			break;
364*7c478bd9Sstevel@tonic-gate 		case 'c':
365*7c478bd9Sstevel@tonic-gate 			/*
366*7c478bd9Sstevel@tonic-gate 			 * Format output to reflect scheduler changes:
367*7c478bd9Sstevel@tonic-gate 			 * high numbers for high priorities and don't
368*7c478bd9Sstevel@tonic-gate 			 * print nice or p_cpu values.  'c' option only
369*7c478bd9Sstevel@tonic-gate 			 * effective when used with 'l' or 'f' options.
370*7c478bd9Sstevel@tonic-gate 			 */
371*7c478bd9Sstevel@tonic-gate 			cflg++;
372*7c478bd9Sstevel@tonic-gate 			break;
373*7c478bd9Sstevel@tonic-gate 		case 'A':		/* list every process */
374*7c478bd9Sstevel@tonic-gate 		case 'e':		/* (obsolete) list every process */
375*7c478bd9Sstevel@tonic-gate 			Aflg++;
376*7c478bd9Sstevel@tonic-gate 			tflg = Gflg = Uflg = uflg = pflg = gflg = sflg = 0;
377*7c478bd9Sstevel@tonic-gate 			zflg = 0;
378*7c478bd9Sstevel@tonic-gate 			break;
379*7c478bd9Sstevel@tonic-gate 		case 'a':
380*7c478bd9Sstevel@tonic-gate 			/*
381*7c478bd9Sstevel@tonic-gate 			 * Same as 'e' except no session group leaders
382*7c478bd9Sstevel@tonic-gate 			 * and no non-terminal processes.
383*7c478bd9Sstevel@tonic-gate 			 */
384*7c478bd9Sstevel@tonic-gate 			aflg++;
385*7c478bd9Sstevel@tonic-gate 			break;
386*7c478bd9Sstevel@tonic-gate 		case 'd':	/* same as e except no session leaders */
387*7c478bd9Sstevel@tonic-gate 			dflg++;
388*7c478bd9Sstevel@tonic-gate 			break;
389*7c478bd9Sstevel@tonic-gate 		case 'L':	/* show lwps */
390*7c478bd9Sstevel@tonic-gate 			Lflg++;
391*7c478bd9Sstevel@tonic-gate 			break;
392*7c478bd9Sstevel@tonic-gate 		case 'P':	/* show bound processor */
393*7c478bd9Sstevel@tonic-gate 			Pflg++;
394*7c478bd9Sstevel@tonic-gate 			break;
395*7c478bd9Sstevel@tonic-gate 		case 'y':	/* omit F & ADDR, report RSS & SZ in Kby */
396*7c478bd9Sstevel@tonic-gate 			yflg++;
397*7c478bd9Sstevel@tonic-gate 			break;
398*7c478bd9Sstevel@tonic-gate 		case 'n':	/* no longer needed; retain as no-op */
399*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
400*7c478bd9Sstevel@tonic-gate 			    gettext("ps: warning: -n option ignored\n"));
401*7c478bd9Sstevel@tonic-gate 			break;
402*7c478bd9Sstevel@tonic-gate 		case 't':		/* terminals */
403*7c478bd9Sstevel@tonic-gate #define	TSZ	30
404*7c478bd9Sstevel@tonic-gate 			tflg++;
405*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
406*7c478bd9Sstevel@tonic-gate 			do {
407*7c478bd9Sstevel@tonic-gate 				char nambuf[TSZ+6];	/* for "/dev/" + '\0' */
408*7c478bd9Sstevel@tonic-gate 				struct stat64 s;
409*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
410*7c478bd9Sstevel@tonic-gate 				p = Realloc(NULL, TSZ+1);	/* for '\0' */
411*7c478bd9Sstevel@tonic-gate 				/* zero the buffer before using it */
412*7c478bd9Sstevel@tonic-gate 				p[0] = '\0';
413*7c478bd9Sstevel@tonic-gate 				size = TSZ;
414*7c478bd9Sstevel@tonic-gate 				if (isdigit(*parg)) {
415*7c478bd9Sstevel@tonic-gate 					(void) strcpy(p, "tty");
416*7c478bd9Sstevel@tonic-gate 					size -= 3;
417*7c478bd9Sstevel@tonic-gate 				}
418*7c478bd9Sstevel@tonic-gate 				(void) strncat(p, parg, size);
419*7c478bd9Sstevel@tonic-gate 				if (ntty == ttysz) {
420*7c478bd9Sstevel@tonic-gate 					if ((ttysz *= 2) == 0)
421*7c478bd9Sstevel@tonic-gate 						ttysz = NTTYS;
422*7c478bd9Sstevel@tonic-gate 					tty = Realloc(tty,
423*7c478bd9Sstevel@tonic-gate 					    (ttysz + 1) * sizeof (struct tty));
424*7c478bd9Sstevel@tonic-gate 				}
425*7c478bd9Sstevel@tonic-gate 				tty[ntty].tdev = PRNODEV;
426*7c478bd9Sstevel@tonic-gate 				(void) strcpy(nambuf, "/dev/");
427*7c478bd9Sstevel@tonic-gate 				(void) strcat(nambuf, p);
428*7c478bd9Sstevel@tonic-gate 				if (stat64(nambuf, &s) == 0)
429*7c478bd9Sstevel@tonic-gate 					tty[ntty].tdev = s.st_rdev;
430*7c478bd9Sstevel@tonic-gate 				tty[ntty++].tname = p;
431*7c478bd9Sstevel@tonic-gate 			} while (*p1);
432*7c478bd9Sstevel@tonic-gate 			break;
433*7c478bd9Sstevel@tonic-gate 		case 'p':		/* proc ids */
434*7c478bd9Sstevel@tonic-gate 			pflg++;
435*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
436*7c478bd9Sstevel@tonic-gate 			do {
437*7c478bd9Sstevel@tonic-gate 				pid_t id;
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
440*7c478bd9Sstevel@tonic-gate 				if ((ret = str2id(parg, &id, 0, maxpid)) != 0) {
441*7c478bd9Sstevel@tonic-gate 					pgerrflg++;
442*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
443*7c478bd9Sstevel@tonic-gate 					    gettext("ps: %s "), parg);
444*7c478bd9Sstevel@tonic-gate 					if (ret == EINVAL)
445*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
446*7c478bd9Sstevel@tonic-gate 						    gettext("is an invalid "
447*7c478bd9Sstevel@tonic-gate 						    "non-numeric argument"));
448*7c478bd9Sstevel@tonic-gate 					else
449*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
450*7c478bd9Sstevel@tonic-gate 						    gettext("exceeds valid "
451*7c478bd9Sstevel@tonic-gate 						    "range"));
452*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
453*7c478bd9Sstevel@tonic-gate 					    gettext(" for -p option\n"));
454*7c478bd9Sstevel@tonic-gate 					continue;
455*7c478bd9Sstevel@tonic-gate 				}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 				if (npid == pidsz) {
458*7c478bd9Sstevel@tonic-gate 					if ((pidsz *= 2) == 0)
459*7c478bd9Sstevel@tonic-gate 						pidsz = SIZ;
460*7c478bd9Sstevel@tonic-gate 					pid = Realloc(pid,
461*7c478bd9Sstevel@tonic-gate 					    pidsz * sizeof (pid_t));
462*7c478bd9Sstevel@tonic-gate 				}
463*7c478bd9Sstevel@tonic-gate 				pid[npid++] = id;
464*7c478bd9Sstevel@tonic-gate 			} while (*p1);
465*7c478bd9Sstevel@tonic-gate 			break;
466*7c478bd9Sstevel@tonic-gate 		case 's':		/* session */
467*7c478bd9Sstevel@tonic-gate 			sflg++;
468*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
469*7c478bd9Sstevel@tonic-gate 			do {
470*7c478bd9Sstevel@tonic-gate 				pid_t id;
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
473*7c478bd9Sstevel@tonic-gate 				if ((ret = str2id(parg, &id, 0, maxpid)) != 0) {
474*7c478bd9Sstevel@tonic-gate 					pgerrflg++;
475*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
476*7c478bd9Sstevel@tonic-gate 					    gettext("ps: %s "), parg);
477*7c478bd9Sstevel@tonic-gate 					if (ret == EINVAL)
478*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
479*7c478bd9Sstevel@tonic-gate 						    gettext("is an invalid "
480*7c478bd9Sstevel@tonic-gate 						    "non-numeric argument"));
481*7c478bd9Sstevel@tonic-gate 					else
482*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
483*7c478bd9Sstevel@tonic-gate 						    gettext("exceeds valid "
484*7c478bd9Sstevel@tonic-gate 						    "range"));
485*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
486*7c478bd9Sstevel@tonic-gate 					    gettext(" for -s option\n"));
487*7c478bd9Sstevel@tonic-gate 					continue;
488*7c478bd9Sstevel@tonic-gate 				}
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 				if (nsessid == sessidsz) {
491*7c478bd9Sstevel@tonic-gate 					if ((sessidsz *= 2) == 0)
492*7c478bd9Sstevel@tonic-gate 						sessidsz = SIZ;
493*7c478bd9Sstevel@tonic-gate 					sessid = Realloc(sessid,
494*7c478bd9Sstevel@tonic-gate 					    sessidsz * sizeof (pid_t));
495*7c478bd9Sstevel@tonic-gate 				}
496*7c478bd9Sstevel@tonic-gate 				sessid[nsessid++] = id;
497*7c478bd9Sstevel@tonic-gate 			} while (*p1);
498*7c478bd9Sstevel@tonic-gate 			break;
499*7c478bd9Sstevel@tonic-gate 		case 'g':		/* proc group */
500*7c478bd9Sstevel@tonic-gate 			gflg++;
501*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
502*7c478bd9Sstevel@tonic-gate 			do {
503*7c478bd9Sstevel@tonic-gate 				pid_t id;
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
506*7c478bd9Sstevel@tonic-gate 				if ((ret = str2id(parg, &id, 0, maxpid)) != 0) {
507*7c478bd9Sstevel@tonic-gate 					pgerrflg++;
508*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
509*7c478bd9Sstevel@tonic-gate 					    gettext("ps: %s "), parg);
510*7c478bd9Sstevel@tonic-gate 					if (ret == EINVAL)
511*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
512*7c478bd9Sstevel@tonic-gate 						    gettext("is an invalid "
513*7c478bd9Sstevel@tonic-gate 						    "non-numeric argument"));
514*7c478bd9Sstevel@tonic-gate 					else
515*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
516*7c478bd9Sstevel@tonic-gate 						    gettext("exceeds valid "
517*7c478bd9Sstevel@tonic-gate 						    "range"));
518*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
519*7c478bd9Sstevel@tonic-gate 					    gettext(" for -g option\n"));
520*7c478bd9Sstevel@tonic-gate 					continue;
521*7c478bd9Sstevel@tonic-gate 				}
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 				if (ngrpid == grpidsz) {
524*7c478bd9Sstevel@tonic-gate 					if ((grpidsz *= 2) == 0)
525*7c478bd9Sstevel@tonic-gate 						grpidsz = SIZ;
526*7c478bd9Sstevel@tonic-gate 					grpid = Realloc(grpid,
527*7c478bd9Sstevel@tonic-gate 					    grpidsz * sizeof (pid_t));
528*7c478bd9Sstevel@tonic-gate 				}
529*7c478bd9Sstevel@tonic-gate 				grpid[ngrpid++] = id;
530*7c478bd9Sstevel@tonic-gate 			} while (*p1);
531*7c478bd9Sstevel@tonic-gate 			break;
532*7c478bd9Sstevel@tonic-gate 		case 'u':		/* effective user name or number */
533*7c478bd9Sstevel@tonic-gate 			uflg++;
534*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
535*7c478bd9Sstevel@tonic-gate 			do {
536*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
537*7c478bd9Sstevel@tonic-gate 				add_ugentry(&euid_tbl, parg);
538*7c478bd9Sstevel@tonic-gate 			} while (*p1);
539*7c478bd9Sstevel@tonic-gate 			break;
540*7c478bd9Sstevel@tonic-gate 		case 'U':		/* real user name or number */
541*7c478bd9Sstevel@tonic-gate 			Uflg++;
542*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
543*7c478bd9Sstevel@tonic-gate 			do {
544*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
545*7c478bd9Sstevel@tonic-gate 				add_ugentry(&ruid_tbl, parg);
546*7c478bd9Sstevel@tonic-gate 			} while (*p1);
547*7c478bd9Sstevel@tonic-gate 			break;
548*7c478bd9Sstevel@tonic-gate 		case 'G':		/* real group name or number */
549*7c478bd9Sstevel@tonic-gate 			Gflg++;
550*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
551*7c478bd9Sstevel@tonic-gate 			do {
552*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
553*7c478bd9Sstevel@tonic-gate 				add_ugentry(&rgid_tbl, parg);
554*7c478bd9Sstevel@tonic-gate 			} while (*p1);
555*7c478bd9Sstevel@tonic-gate 			break;
556*7c478bd9Sstevel@tonic-gate 		case 'o':		/* output format */
557*7c478bd9Sstevel@tonic-gate 			p = optarg;
558*7c478bd9Sstevel@tonic-gate 			while ((p = parse_format(p)) != NULL)
559*7c478bd9Sstevel@tonic-gate 				;
560*7c478bd9Sstevel@tonic-gate 			break;
561*7c478bd9Sstevel@tonic-gate 		case 'z':		/* zone name or number */
562*7c478bd9Sstevel@tonic-gate 			zflg++;
563*7c478bd9Sstevel@tonic-gate 			p1 = optarg;
564*7c478bd9Sstevel@tonic-gate 			do {
565*7c478bd9Sstevel@tonic-gate 				zoneid_t id;
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 				parg = getarg(&p1);
568*7c478bd9Sstevel@tonic-gate 				if (zone_get_id(parg, &id) != 0) {
569*7c478bd9Sstevel@tonic-gate 					pgerrflg++;
570*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
571*7c478bd9Sstevel@tonic-gate 					    gettext("ps: unknown zone %s\n"),
572*7c478bd9Sstevel@tonic-gate 					    parg);
573*7c478bd9Sstevel@tonic-gate 					continue;
574*7c478bd9Sstevel@tonic-gate 				}
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 				if (nzoneid == zoneidsz) {
577*7c478bd9Sstevel@tonic-gate 					if ((zoneidsz *= 2) == 0)
578*7c478bd9Sstevel@tonic-gate 						zoneidsz = SIZ;
579*7c478bd9Sstevel@tonic-gate 					zoneid = Realloc(zoneid,
580*7c478bd9Sstevel@tonic-gate 					    zoneidsz * sizeof (zoneid_t));
581*7c478bd9Sstevel@tonic-gate 				}
582*7c478bd9Sstevel@tonic-gate 				zoneid[nzoneid++] = id;
583*7c478bd9Sstevel@tonic-gate 			} while (*p1);
584*7c478bd9Sstevel@tonic-gate 			break;
585*7c478bd9Sstevel@tonic-gate 		case 'Z':		/* show zone name */
586*7c478bd9Sstevel@tonic-gate 			Zflg++;
587*7c478bd9Sstevel@tonic-gate 			break;
588*7c478bd9Sstevel@tonic-gate 		default:			/* error on ? */
589*7c478bd9Sstevel@tonic-gate 			errflg++;
590*7c478bd9Sstevel@tonic-gate 			break;
591*7c478bd9Sstevel@tonic-gate 		}
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	if (errflg || optind < argc || pgerrflg)
594*7c478bd9Sstevel@tonic-gate 		usage();
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	if (tflg)
597*7c478bd9Sstevel@tonic-gate 		tty[ntty].tname = NULL;
598*7c478bd9Sstevel@tonic-gate 	/*
599*7c478bd9Sstevel@tonic-gate 	 * If an appropriate option has not been specified, use the
600*7c478bd9Sstevel@tonic-gate 	 * current terminal and effective uid as the default.
601*7c478bd9Sstevel@tonic-gate 	 */
602*7c478bd9Sstevel@tonic-gate 	if (!(aflg|Aflg|dflg|Gflg|Uflg|uflg|tflg|pflg|gflg|sflg|zflg)) {
603*7c478bd9Sstevel@tonic-gate 		psinfo_t info;
604*7c478bd9Sstevel@tonic-gate 		int procfd;
605*7c478bd9Sstevel@tonic-gate 		char *name;
606*7c478bd9Sstevel@tonic-gate 		char pname[100];
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		/* get our own controlling tty name using /proc */
609*7c478bd9Sstevel@tonic-gate 		(void) snprintf(pname, sizeof (pname),
610*7c478bd9Sstevel@tonic-gate 		    "%s/self/psinfo", procdir);
611*7c478bd9Sstevel@tonic-gate 		if ((procfd = open(pname, O_RDONLY)) < 0 ||
612*7c478bd9Sstevel@tonic-gate 		    read(procfd, (char *)&info, sizeof (info)) < 0 ||
613*7c478bd9Sstevel@tonic-gate 		    info.pr_ttydev == PRNODEV) {
614*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
615*7c478bd9Sstevel@tonic-gate 			    gettext("ps: no controlling terminal\n"));
616*7c478bd9Sstevel@tonic-gate 			exit(1);
617*7c478bd9Sstevel@tonic-gate 		}
618*7c478bd9Sstevel@tonic-gate 		(void) close(procfd);
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 		i = 0;
621*7c478bd9Sstevel@tonic-gate 		name = gettty(&info);
622*7c478bd9Sstevel@tonic-gate 		if (*name == '?') {
623*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
624*7c478bd9Sstevel@tonic-gate 			    gettext("ps: can't find controlling terminal\n"));
625*7c478bd9Sstevel@tonic-gate 			exit(1);
626*7c478bd9Sstevel@tonic-gate 		}
627*7c478bd9Sstevel@tonic-gate 		if (ntty == ttysz) {
628*7c478bd9Sstevel@tonic-gate 			if ((ttysz *= 2) == 0)
629*7c478bd9Sstevel@tonic-gate 				ttysz = NTTYS;
630*7c478bd9Sstevel@tonic-gate 			tty = Realloc(tty, (ttysz + 1) * sizeof (struct tty));
631*7c478bd9Sstevel@tonic-gate 		}
632*7c478bd9Sstevel@tonic-gate 		tty[ntty].tdev = info.pr_ttydev;
633*7c478bd9Sstevel@tonic-gate 		tty[ntty++].tname = name;
634*7c478bd9Sstevel@tonic-gate 		tty[ntty].tname = NULL;
635*7c478bd9Sstevel@tonic-gate 		tflg++;
636*7c478bd9Sstevel@tonic-gate 		tuid = getuid();
637*7c478bd9Sstevel@tonic-gate 	}
638*7c478bd9Sstevel@tonic-gate 	if (Aflg) {
639*7c478bd9Sstevel@tonic-gate 		Gflg = Uflg = uflg = pflg = sflg = gflg = aflg = dflg = 0;
640*7c478bd9Sstevel@tonic-gate 		zflg = 0;
641*7c478bd9Sstevel@tonic-gate 	}
642*7c478bd9Sstevel@tonic-gate 	if (Aflg | aflg | dflg)
643*7c478bd9Sstevel@tonic-gate 		tflg = 0;
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	i = 0;		/* prepare to exit on name lookup errors */
646*7c478bd9Sstevel@tonic-gate 	i += uconv(&euid_tbl);
647*7c478bd9Sstevel@tonic-gate 	i += uconv(&ruid_tbl);
648*7c478bd9Sstevel@tonic-gate 	i += gconv(&egid_tbl);
649*7c478bd9Sstevel@tonic-gate 	i += gconv(&rgid_tbl);
650*7c478bd9Sstevel@tonic-gate 	if (i)
651*7c478bd9Sstevel@tonic-gate 		exit(1);
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	/* allocate a buffer for lwpsinfo structures */
654*7c478bd9Sstevel@tonic-gate 	lpbufsize = 4096;
655*7c478bd9Sstevel@tonic-gate 	if (Lflg && (lpsinfobuf = malloc(lpbufsize)) == NULL) {
656*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
657*7c478bd9Sstevel@tonic-gate 		    gettext("ps: no memory\n"));
658*7c478bd9Sstevel@tonic-gate 		exit(1);
659*7c478bd9Sstevel@tonic-gate 	}
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	if (fields) {	/* print user-specified header */
662*7c478bd9Sstevel@tonic-gate 		if (do_header) {
663*7c478bd9Sstevel@tonic-gate 			struct field *f;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 			for (f = fields; f != NULL; f = f->next) {
666*7c478bd9Sstevel@tonic-gate 				if (f != fields)
667*7c478bd9Sstevel@tonic-gate 					(void) printf(" ");
668*7c478bd9Sstevel@tonic-gate 				switch (f->fname) {
669*7c478bd9Sstevel@tonic-gate 				case F_TTY:
670*7c478bd9Sstevel@tonic-gate 					(void) printf("%-*s",
671*7c478bd9Sstevel@tonic-gate 					    f->width, f->header);
672*7c478bd9Sstevel@tonic-gate 					break;
673*7c478bd9Sstevel@tonic-gate 				case F_FNAME:
674*7c478bd9Sstevel@tonic-gate 				case F_COMM:
675*7c478bd9Sstevel@tonic-gate 				case F_ARGS:
676*7c478bd9Sstevel@tonic-gate 					/*
677*7c478bd9Sstevel@tonic-gate 					 * Print these headers full width
678*7c478bd9Sstevel@tonic-gate 					 * unless they appear at the end.
679*7c478bd9Sstevel@tonic-gate 					 */
680*7c478bd9Sstevel@tonic-gate 					if (f->next != NULL) {
681*7c478bd9Sstevel@tonic-gate 						(void) printf("%-*s",
682*7c478bd9Sstevel@tonic-gate 						    f->width, f->header);
683*7c478bd9Sstevel@tonic-gate 					} else {
684*7c478bd9Sstevel@tonic-gate 						(void) printf("%s",
685*7c478bd9Sstevel@tonic-gate 						    f->header);
686*7c478bd9Sstevel@tonic-gate 					}
687*7c478bd9Sstevel@tonic-gate 					break;
688*7c478bd9Sstevel@tonic-gate 				default:
689*7c478bd9Sstevel@tonic-gate 					(void) printf("%*s",
690*7c478bd9Sstevel@tonic-gate 					    f->width, f->header);
691*7c478bd9Sstevel@tonic-gate 					break;
692*7c478bd9Sstevel@tonic-gate 				}
693*7c478bd9Sstevel@tonic-gate 			}
694*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
695*7c478bd9Sstevel@tonic-gate 		}
696*7c478bd9Sstevel@tonic-gate 	} else {	/* print standard header */
697*7c478bd9Sstevel@tonic-gate 		if (lflg) {
698*7c478bd9Sstevel@tonic-gate 			if (yflg)
699*7c478bd9Sstevel@tonic-gate 				(void) printf(" S");
700*7c478bd9Sstevel@tonic-gate 			else
701*7c478bd9Sstevel@tonic-gate 				(void) printf(" F S");
702*7c478bd9Sstevel@tonic-gate 		}
703*7c478bd9Sstevel@tonic-gate 		if (Zflg)
704*7c478bd9Sstevel@tonic-gate 			(void) printf("    ZONE");
705*7c478bd9Sstevel@tonic-gate 		if (fflg) {
706*7c478bd9Sstevel@tonic-gate 			if (lflg)
707*7c478bd9Sstevel@tonic-gate 				(void) printf(" ");
708*7c478bd9Sstevel@tonic-gate 			(void) printf("     UID");
709*7c478bd9Sstevel@tonic-gate 		} else if (lflg)
710*7c478bd9Sstevel@tonic-gate 			(void) printf("    UID");
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*s", pidwidth,  "PID");
713*7c478bd9Sstevel@tonic-gate 		if (lflg || fflg)
714*7c478bd9Sstevel@tonic-gate 			(void) printf(" %*s", pidwidth, "PPID");
715*7c478bd9Sstevel@tonic-gate 		if (jflg)
716*7c478bd9Sstevel@tonic-gate 			(void) printf(" %*s %*s", pidwidth, "PGID",
717*7c478bd9Sstevel@tonic-gate 			    pidwidth, "SID");
718*7c478bd9Sstevel@tonic-gate 		if (Lflg)
719*7c478bd9Sstevel@tonic-gate 			(void) printf("   LWP");
720*7c478bd9Sstevel@tonic-gate 		if (Pflg)
721*7c478bd9Sstevel@tonic-gate 			(void) printf(" PSR");
722*7c478bd9Sstevel@tonic-gate 		if (Lflg && fflg)
723*7c478bd9Sstevel@tonic-gate 			(void) printf("  NLWP");
724*7c478bd9Sstevel@tonic-gate 		if (cflg)
725*7c478bd9Sstevel@tonic-gate 			(void) printf("  CLS PRI");
726*7c478bd9Sstevel@tonic-gate 		else if (lflg || fflg) {
727*7c478bd9Sstevel@tonic-gate 			(void) printf("   C");
728*7c478bd9Sstevel@tonic-gate 			if (lflg)
729*7c478bd9Sstevel@tonic-gate 				(void) printf(" PRI NI");
730*7c478bd9Sstevel@tonic-gate 		}
731*7c478bd9Sstevel@tonic-gate 		if (lflg) {
732*7c478bd9Sstevel@tonic-gate 			if (yflg)
733*7c478bd9Sstevel@tonic-gate 				(void) printf("   RSS     SZ    WCHAN");
734*7c478bd9Sstevel@tonic-gate 			else
735*7c478bd9Sstevel@tonic-gate 				(void) printf("     ADDR     SZ    WCHAN");
736*7c478bd9Sstevel@tonic-gate 		}
737*7c478bd9Sstevel@tonic-gate 		if (fflg)
738*7c478bd9Sstevel@tonic-gate 			(void) printf("    STIME");
739*7c478bd9Sstevel@tonic-gate 		if (Lflg)
740*7c478bd9Sstevel@tonic-gate 			(void) printf(" TTY        LTIME CMD\n");
741*7c478bd9Sstevel@tonic-gate 		else
742*7c478bd9Sstevel@tonic-gate 			(void) printf(" TTY         TIME CMD\n");
743*7c478bd9Sstevel@tonic-gate 	}
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 	if (pflg && !(aflg|Aflg|dflg|Gflg|Uflg|uflg|tflg|gflg|sflg|zflg) &&
747*7c478bd9Sstevel@tonic-gate 	    npid <= PTHRESHOLD) {
748*7c478bd9Sstevel@tonic-gate 		/*
749*7c478bd9Sstevel@tonic-gate 		 * If we are looking at specific processes go straight
750*7c478bd9Sstevel@tonic-gate 		 * to their /proc entries and don't scan /proc.
751*7c478bd9Sstevel@tonic-gate 		 */
752*7c478bd9Sstevel@tonic-gate 		int i;
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 		(void) qsort(pid, npid, sizeof (pid_t), pidcmp);
755*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < npid; i++) {
756*7c478bd9Sstevel@tonic-gate 			char pname[12];
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate 			if (i >= 1 && pid[i] == pid[i - 1])
759*7c478bd9Sstevel@tonic-gate 				continue;
760*7c478bd9Sstevel@tonic-gate 			(void) sprintf(pname, "%d", (int)pid[i]);
761*7c478bd9Sstevel@tonic-gate 			if (print_proc(pname) == 0)
762*7c478bd9Sstevel@tonic-gate 				retcode = 0;
763*7c478bd9Sstevel@tonic-gate 		}
764*7c478bd9Sstevel@tonic-gate 	} else {
765*7c478bd9Sstevel@tonic-gate 		/*
766*7c478bd9Sstevel@tonic-gate 		 * Determine which processes to print info about by searching
767*7c478bd9Sstevel@tonic-gate 		 * the /proc directory and looking at each process.
768*7c478bd9Sstevel@tonic-gate 		 */
769*7c478bd9Sstevel@tonic-gate 		if ((dirp = opendir(procdir)) == NULL) {
770*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
771*7c478bd9Sstevel@tonic-gate 			    gettext("ps: cannot open PROC directory %s\n"),
772*7c478bd9Sstevel@tonic-gate 			    procdir);
773*7c478bd9Sstevel@tonic-gate 			exit(1);
774*7c478bd9Sstevel@tonic-gate 		}
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 		/* for each active process --- */
777*7c478bd9Sstevel@tonic-gate 		while (dentp = readdir(dirp)) {
778*7c478bd9Sstevel@tonic-gate 			if (dentp->d_name[0] == '.')    /* skip . and .. */
779*7c478bd9Sstevel@tonic-gate 				continue;
780*7c478bd9Sstevel@tonic-gate 			if (print_proc(dentp->d_name) == 0)
781*7c478bd9Sstevel@tonic-gate 				retcode = 0;
782*7c478bd9Sstevel@tonic-gate 		}
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 		(void) closedir(dirp);
785*7c478bd9Sstevel@tonic-gate 	}
786*7c478bd9Sstevel@tonic-gate 	return (retcode);
787*7c478bd9Sstevel@tonic-gate }
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate int
791*7c478bd9Sstevel@tonic-gate print_proc(char *pid_name)
792*7c478bd9Sstevel@tonic-gate {
793*7c478bd9Sstevel@tonic-gate 	char	pname[PATH_MAX];
794*7c478bd9Sstevel@tonic-gate 	int	pdlen;
795*7c478bd9Sstevel@tonic-gate 	int	found;
796*7c478bd9Sstevel@tonic-gate 	int	procfd; /* filedescriptor for /proc/nnnnn/psinfo */
797*7c478bd9Sstevel@tonic-gate 	char	*tp;    /* ptr to ttyname,  if any */
798*7c478bd9Sstevel@tonic-gate 	psinfo_t info;  /* process information from /proc */
799*7c478bd9Sstevel@tonic-gate 	lwpsinfo_t *lwpsinfo;   /* array of lwpsinfo structs */
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate 	pdlen = snprintf(pname, sizeof (pname), "%s/%s/", procdir, pid_name);
802*7c478bd9Sstevel@tonic-gate 	if (pdlen >= sizeof (pname) - 10)
803*7c478bd9Sstevel@tonic-gate 		return (1);
804*7c478bd9Sstevel@tonic-gate retry:
805*7c478bd9Sstevel@tonic-gate 	(void) strcpy(&pname[pdlen], "psinfo");
806*7c478bd9Sstevel@tonic-gate 	if ((procfd = open(pname, O_RDONLY)) == -1) {
807*7c478bd9Sstevel@tonic-gate 		/* Process may have exited meanwhile. */
808*7c478bd9Sstevel@tonic-gate 		return (1);
809*7c478bd9Sstevel@tonic-gate 	}
810*7c478bd9Sstevel@tonic-gate 	/*
811*7c478bd9Sstevel@tonic-gate 	 * Get the info structure for the process and close quickly.
812*7c478bd9Sstevel@tonic-gate 	 */
813*7c478bd9Sstevel@tonic-gate 	if (read(procfd, (char *)&info, sizeof (info)) < 0) {
814*7c478bd9Sstevel@tonic-gate 		int	saverr = errno;
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 		(void) close(procfd);
817*7c478bd9Sstevel@tonic-gate 		if (saverr == EAGAIN)
818*7c478bd9Sstevel@tonic-gate 			goto retry;
819*7c478bd9Sstevel@tonic-gate 		if (saverr != ENOENT)
820*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
821*7c478bd9Sstevel@tonic-gate 			    gettext("ps: read() on %s: %s\n"),
822*7c478bd9Sstevel@tonic-gate 			    pname, err_string(saverr));
823*7c478bd9Sstevel@tonic-gate 		return (1);
824*7c478bd9Sstevel@tonic-gate 	}
825*7c478bd9Sstevel@tonic-gate 	(void) close(procfd);
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	found = 0;
828*7c478bd9Sstevel@tonic-gate 	if (info.pr_lwp.pr_state == 0)	/* can't happen? */
829*7c478bd9Sstevel@tonic-gate 		return (1);
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate 	/*
832*7c478bd9Sstevel@tonic-gate 	 * Omit session group leaders for 'a' and 'd' options.
833*7c478bd9Sstevel@tonic-gate 	 */
834*7c478bd9Sstevel@tonic-gate 	if ((info.pr_pid == info.pr_sid) && (dflg || aflg))
835*7c478bd9Sstevel@tonic-gate 		return (1);
836*7c478bd9Sstevel@tonic-gate 	if (Aflg || dflg)
837*7c478bd9Sstevel@tonic-gate 		found++;
838*7c478bd9Sstevel@tonic-gate 	else if (pflg && search(pid, npid, info.pr_pid))
839*7c478bd9Sstevel@tonic-gate 		found++;	/* ppid in p option arg list */
840*7c478bd9Sstevel@tonic-gate 	else if (uflg && ugfind(info.pr_euid, &euid_tbl))
841*7c478bd9Sstevel@tonic-gate 		found++;	/* puid in u option arg list */
842*7c478bd9Sstevel@tonic-gate 	else if (Uflg && ugfind(info.pr_uid, &ruid_tbl))
843*7c478bd9Sstevel@tonic-gate 		found++;	/* puid in U option arg list */
844*7c478bd9Sstevel@tonic-gate #ifdef NOT_YET
845*7c478bd9Sstevel@tonic-gate 	else if (gflg && ugfind(info.pr_egid, &egid_tbl))
846*7c478bd9Sstevel@tonic-gate 		found++;	/* pgid in g option arg list */
847*7c478bd9Sstevel@tonic-gate #endif	/* NOT_YET */
848*7c478bd9Sstevel@tonic-gate 	else if (Gflg && ugfind(info.pr_gid, &rgid_tbl))
849*7c478bd9Sstevel@tonic-gate 		found++;	/* pgid in G option arg list */
850*7c478bd9Sstevel@tonic-gate 	else if (gflg && search(grpid, ngrpid, info.pr_pgid))
851*7c478bd9Sstevel@tonic-gate 		found++;	/* grpid in g option arg list */
852*7c478bd9Sstevel@tonic-gate 	else if (sflg && search(sessid, nsessid, info.pr_sid))
853*7c478bd9Sstevel@tonic-gate 		found++;	/* sessid in s option arg list */
854*7c478bd9Sstevel@tonic-gate 	else if (zflg && search(zoneid, nzoneid, info.pr_zoneid))
855*7c478bd9Sstevel@tonic-gate 		found++;	/* zoneid in z option arg list */
856*7c478bd9Sstevel@tonic-gate 	if (!found && !tflg && !aflg)
857*7c478bd9Sstevel@tonic-gate 		return (1);
858*7c478bd9Sstevel@tonic-gate 	if (!prfind(found, &info, &tp))
859*7c478bd9Sstevel@tonic-gate 		return (1);
860*7c478bd9Sstevel@tonic-gate 	if (Lflg && (info.pr_nlwp + info.pr_nzomb) > 1) {
861*7c478bd9Sstevel@tonic-gate 		ssize_t prsz;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 		(void) strcpy(&pname[pdlen], "lpsinfo");
864*7c478bd9Sstevel@tonic-gate 		if ((procfd = open(pname, O_RDONLY)) == -1)
865*7c478bd9Sstevel@tonic-gate 			return (1);
866*7c478bd9Sstevel@tonic-gate 		/*
867*7c478bd9Sstevel@tonic-gate 		 * Get the info structures for the lwps.
868*7c478bd9Sstevel@tonic-gate 		 */
869*7c478bd9Sstevel@tonic-gate 		prsz = read(procfd, lpsinfobuf, lpbufsize);
870*7c478bd9Sstevel@tonic-gate 		if (prsz == -1) {
871*7c478bd9Sstevel@tonic-gate 			int	saverr = errno;
872*7c478bd9Sstevel@tonic-gate 
873*7c478bd9Sstevel@tonic-gate 			(void) close(procfd);
874*7c478bd9Sstevel@tonic-gate 			if (saverr == EAGAIN)
875*7c478bd9Sstevel@tonic-gate 				goto retry;
876*7c478bd9Sstevel@tonic-gate 			if (saverr != ENOENT)
877*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
878*7c478bd9Sstevel@tonic-gate 				    gettext("ps: read() on %s: %s\n"),
879*7c478bd9Sstevel@tonic-gate 				    pname, err_string(saverr));
880*7c478bd9Sstevel@tonic-gate 			return (1);
881*7c478bd9Sstevel@tonic-gate 		}
882*7c478bd9Sstevel@tonic-gate 		(void) close(procfd);
883*7c478bd9Sstevel@tonic-gate 		if (prsz == lpbufsize) {
884*7c478bd9Sstevel@tonic-gate 			/*
885*7c478bd9Sstevel@tonic-gate 			 * buffer overflow. Realloc new buffer.
886*7c478bd9Sstevel@tonic-gate 			 * Error handling is done in Realloc().
887*7c478bd9Sstevel@tonic-gate 			 */
888*7c478bd9Sstevel@tonic-gate 			lpbufsize *= 2;
889*7c478bd9Sstevel@tonic-gate 			lpsinfobuf = Realloc(lpsinfobuf, lpbufsize);
890*7c478bd9Sstevel@tonic-gate 			goto retry;
891*7c478bd9Sstevel@tonic-gate 		}
892*7c478bd9Sstevel@tonic-gate 		if (lpsinfobuf->pr_nent != (info.pr_nlwp + info.pr_nzomb))
893*7c478bd9Sstevel@tonic-gate 			goto retry;
894*7c478bd9Sstevel@tonic-gate 		lwpsinfo = (lwpsinfo_t *)(lpsinfobuf + 1);
895*7c478bd9Sstevel@tonic-gate 	}
896*7c478bd9Sstevel@tonic-gate 	if (!Lflg || (info.pr_nlwp + info.pr_nzomb) <= 1) {
897*7c478bd9Sstevel@tonic-gate 		prcom(&info, tp);
898*7c478bd9Sstevel@tonic-gate 	} else {
899*7c478bd9Sstevel@tonic-gate 		int nlwp = 0;
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate 		do {
902*7c478bd9Sstevel@tonic-gate 			info.pr_lwp = *lwpsinfo;
903*7c478bd9Sstevel@tonic-gate 			prcom(&info, tp);
904*7c478bd9Sstevel@tonic-gate 			/* LINTED improper alignment */
905*7c478bd9Sstevel@tonic-gate 			lwpsinfo = (lwpsinfo_t *)((char *)lwpsinfo +
906*7c478bd9Sstevel@tonic-gate 				lpsinfobuf->pr_entsize);
907*7c478bd9Sstevel@tonic-gate 		} while (++nlwp < lpsinfobuf->pr_nent);
908*7c478bd9Sstevel@tonic-gate 	}
909*7c478bd9Sstevel@tonic-gate 	return (0);
910*7c478bd9Sstevel@tonic-gate }
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate static void
914*7c478bd9Sstevel@tonic-gate usage(void)		/* print usage message and quit */
915*7c478bd9Sstevel@tonic-gate {
916*7c478bd9Sstevel@tonic-gate 	static char usage1[] =
917*7c478bd9Sstevel@tonic-gate 	    "ps [ -aAdeflcjLPyZ ] [ -o format ] [ -t termlist ]";
918*7c478bd9Sstevel@tonic-gate 	static char usage2[] =
919*7c478bd9Sstevel@tonic-gate 	    "\t[ -u userlist ] [ -U userlist ] [ -G grouplist ]";
920*7c478bd9Sstevel@tonic-gate 	static char usage3[] =
921*7c478bd9Sstevel@tonic-gate 	    "\t[ -p proclist ] [ -g pgrplist ] [ -s sidlist ] [ -z zonelist ]";
922*7c478bd9Sstevel@tonic-gate 	static char usage4[] =
923*7c478bd9Sstevel@tonic-gate 	    "  'format' is one or more of:";
924*7c478bd9Sstevel@tonic-gate 	static char usage5[] =
925*7c478bd9Sstevel@tonic-gate 	    "\tuser ruser group rgroup uid ruid gid rgid pid ppid pgid "
926*7c478bd9Sstevel@tonic-gate 	    "sid taskid ctid";
927*7c478bd9Sstevel@tonic-gate 	static char usage6[] =
928*7c478bd9Sstevel@tonic-gate 	    "\tpri opri pcpu pmem vsz rss osz nice class time etime stime zone "
929*7c478bd9Sstevel@tonic-gate 	    "zoneid";
930*7c478bd9Sstevel@tonic-gate 	static char usage7[] =
931*7c478bd9Sstevel@tonic-gate 	    "\tf s c lwp nlwp psr tty addr wchan fname comm args "
932*7c478bd9Sstevel@tonic-gate 	    "projid project pset";
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
935*7c478bd9Sstevel@tonic-gate 	    gettext("usage: %s\n%s\n%s\n%s\n%s\n%s\n%s\n"),
936*7c478bd9Sstevel@tonic-gate 	    gettext(usage1), gettext(usage2), gettext(usage3),
937*7c478bd9Sstevel@tonic-gate 	    gettext(usage4), gettext(usage5), gettext(usage6), gettext(usage7));
938*7c478bd9Sstevel@tonic-gate 	exit(1);
939*7c478bd9Sstevel@tonic-gate }
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate /*
942*7c478bd9Sstevel@tonic-gate  * getarg() finds the next argument in list and copies arg into argbuf.
943*7c478bd9Sstevel@tonic-gate  * p1 first pts to arg passed back from getopt routine.  p1 is then
944*7c478bd9Sstevel@tonic-gate  * bumped to next character that is not a comma or blank -- p1 NULL
945*7c478bd9Sstevel@tonic-gate  * indicates end of list.
946*7c478bd9Sstevel@tonic-gate  */
947*7c478bd9Sstevel@tonic-gate static char *
948*7c478bd9Sstevel@tonic-gate getarg(char **pp1)
949*7c478bd9Sstevel@tonic-gate {
950*7c478bd9Sstevel@tonic-gate 	static char argbuf[ARGSIZ];
951*7c478bd9Sstevel@tonic-gate 	char *p1 = *pp1;
952*7c478bd9Sstevel@tonic-gate 	char *parga = argbuf;
953*7c478bd9Sstevel@tonic-gate 	int c;
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate 	while ((c = *p1) != '\0' && (c == ',' || isspace(c)))
956*7c478bd9Sstevel@tonic-gate 		p1++;
957*7c478bd9Sstevel@tonic-gate 
958*7c478bd9Sstevel@tonic-gate 	while ((c = *p1) != '\0' && c != ',' && !isspace(c)) {
959*7c478bd9Sstevel@tonic-gate 		if (parga < argbuf + ARGSIZ - 1)
960*7c478bd9Sstevel@tonic-gate 			*parga++ = c;
961*7c478bd9Sstevel@tonic-gate 		p1++;
962*7c478bd9Sstevel@tonic-gate 	}
963*7c478bd9Sstevel@tonic-gate 	*parga = '\0';
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	while ((c = *p1) != '\0' && (c == ',' || isspace(c)))
966*7c478bd9Sstevel@tonic-gate 		p1++;
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	*pp1 = p1;
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 	return (argbuf);
971*7c478bd9Sstevel@tonic-gate }
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate /*
974*7c478bd9Sstevel@tonic-gate  * parse_format() takes the argument to the -o option,
975*7c478bd9Sstevel@tonic-gate  * sets up the next output field structure, and returns
976*7c478bd9Sstevel@tonic-gate  * a pointer to any further output field specifier(s).
977*7c478bd9Sstevel@tonic-gate  * As a side-effect, it increments errflg if encounters a format error.
978*7c478bd9Sstevel@tonic-gate  */
979*7c478bd9Sstevel@tonic-gate static char *
980*7c478bd9Sstevel@tonic-gate parse_format(char *arg)
981*7c478bd9Sstevel@tonic-gate {
982*7c478bd9Sstevel@tonic-gate 	int c;
983*7c478bd9Sstevel@tonic-gate 	char *name;
984*7c478bd9Sstevel@tonic-gate 	char *header = NULL;
985*7c478bd9Sstevel@tonic-gate 	int width = 0;
986*7c478bd9Sstevel@tonic-gate 	struct def_field *df;
987*7c478bd9Sstevel@tonic-gate 	struct field *f;
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 	while ((c = *arg) != '\0' && (c == ',' || isspace(c)))
990*7c478bd9Sstevel@tonic-gate 		arg++;
991*7c478bd9Sstevel@tonic-gate 	if (c == '\0')
992*7c478bd9Sstevel@tonic-gate 		return (NULL);
993*7c478bd9Sstevel@tonic-gate 	name = arg;
994*7c478bd9Sstevel@tonic-gate 	arg = strpbrk(arg, " \t\r\v\f\n,=");
995*7c478bd9Sstevel@tonic-gate 	if (arg != NULL) {
996*7c478bd9Sstevel@tonic-gate 		c = *arg;
997*7c478bd9Sstevel@tonic-gate 		*arg++ = '\0';
998*7c478bd9Sstevel@tonic-gate 		if (c == '=') {
999*7c478bd9Sstevel@tonic-gate 			char *s;
1000*7c478bd9Sstevel@tonic-gate 
1001*7c478bd9Sstevel@tonic-gate 			header = arg;
1002*7c478bd9Sstevel@tonic-gate 			arg = NULL;
1003*7c478bd9Sstevel@tonic-gate 			width = strlen(header);
1004*7c478bd9Sstevel@tonic-gate 			s = header + width;
1005*7c478bd9Sstevel@tonic-gate 			while (s > header && isspace(*--s))
1006*7c478bd9Sstevel@tonic-gate 				*s = '\0';
1007*7c478bd9Sstevel@tonic-gate 			while (isspace(*header))
1008*7c478bd9Sstevel@tonic-gate 				header++;
1009*7c478bd9Sstevel@tonic-gate 		}
1010*7c478bd9Sstevel@tonic-gate 	}
1011*7c478bd9Sstevel@tonic-gate 	for (df = &fname[0]; df < &fname[NFIELDS]; df++)
1012*7c478bd9Sstevel@tonic-gate 		if (strcmp(name, df->fname) == 0) {
1013*7c478bd9Sstevel@tonic-gate 			if (strcmp(name, "lwp") == 0)
1014*7c478bd9Sstevel@tonic-gate 				Lflg++;
1015*7c478bd9Sstevel@tonic-gate 			break;
1016*7c478bd9Sstevel@tonic-gate 		}
1017*7c478bd9Sstevel@tonic-gate 	if (df >= &fname[NFIELDS]) {
1018*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1019*7c478bd9Sstevel@tonic-gate 			gettext("ps: unknown output format: -o %s\n"),
1020*7c478bd9Sstevel@tonic-gate 			name);
1021*7c478bd9Sstevel@tonic-gate 		errflg++;
1022*7c478bd9Sstevel@tonic-gate 		return (arg);
1023*7c478bd9Sstevel@tonic-gate 	}
1024*7c478bd9Sstevel@tonic-gate 	if ((f = malloc(sizeof (*f))) == NULL) {
1025*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1026*7c478bd9Sstevel@tonic-gate 		    gettext("ps: malloc() for output format failed, %s\n"),
1027*7c478bd9Sstevel@tonic-gate 		    err_string(errno));
1028*7c478bd9Sstevel@tonic-gate 		exit(1);
1029*7c478bd9Sstevel@tonic-gate 	}
1030*7c478bd9Sstevel@tonic-gate 	f->next = NULL;
1031*7c478bd9Sstevel@tonic-gate 	f->fname = df - &fname[0];
1032*7c478bd9Sstevel@tonic-gate 	f->header = header? header : df->header;
1033*7c478bd9Sstevel@tonic-gate 	if (width == 0)
1034*7c478bd9Sstevel@tonic-gate 		width = df->width;
1035*7c478bd9Sstevel@tonic-gate 	if (*f->header != '\0')
1036*7c478bd9Sstevel@tonic-gate 		do_header = 1;
1037*7c478bd9Sstevel@tonic-gate 	f->width = max(width, df->minwidth);
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate 	if (fields == NULL)
1040*7c478bd9Sstevel@tonic-gate 		fields = last_field = f;
1041*7c478bd9Sstevel@tonic-gate 	else {
1042*7c478bd9Sstevel@tonic-gate 		last_field->next = f;
1043*7c478bd9Sstevel@tonic-gate 		last_field = f;
1044*7c478bd9Sstevel@tonic-gate 	}
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate 	return (arg);
1047*7c478bd9Sstevel@tonic-gate }
1048*7c478bd9Sstevel@tonic-gate 
1049*7c478bd9Sstevel@tonic-gate static char *
1050*7c478bd9Sstevel@tonic-gate devlookup(dev_t ddev)
1051*7c478bd9Sstevel@tonic-gate {
1052*7c478bd9Sstevel@tonic-gate 	struct devl *dp;
1053*7c478bd9Sstevel@tonic-gate 	int i;
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 	for (dp = devl, i = 0; i < ndev; dp++, i++) {
1056*7c478bd9Sstevel@tonic-gate 		if (dp->ddev == ddev)
1057*7c478bd9Sstevel@tonic-gate 			return (dp->dname);
1058*7c478bd9Sstevel@tonic-gate 	}
1059*7c478bd9Sstevel@tonic-gate 	return (NULL);
1060*7c478bd9Sstevel@tonic-gate }
1061*7c478bd9Sstevel@tonic-gate 
1062*7c478bd9Sstevel@tonic-gate static char *
1063*7c478bd9Sstevel@tonic-gate devadd(char *name, dev_t ddev)
1064*7c478bd9Sstevel@tonic-gate {
1065*7c478bd9Sstevel@tonic-gate 	struct devl *dp;
1066*7c478bd9Sstevel@tonic-gate 	int leng, start, i;
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate 	if (ndev == maxdev) {
1069*7c478bd9Sstevel@tonic-gate 		maxdev += DNINCR;
1070*7c478bd9Sstevel@tonic-gate 		devl = Realloc(devl, maxdev * sizeof (struct devl));
1071*7c478bd9Sstevel@tonic-gate 	}
1072*7c478bd9Sstevel@tonic-gate 	dp = &devl[ndev++];
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 	dp->ddev = ddev;
1075*7c478bd9Sstevel@tonic-gate 	if (name == NULL) {
1076*7c478bd9Sstevel@tonic-gate 		(void) strcpy(dp->dname, "??");
1077*7c478bd9Sstevel@tonic-gate 		return (dp->dname);
1078*7c478bd9Sstevel@tonic-gate 	}
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate 	leng = strlen(name);
1081*7c478bd9Sstevel@tonic-gate 	/* Strip off /dev/ */
1082*7c478bd9Sstevel@tonic-gate 	if (leng < DNSIZE + 4)
1083*7c478bd9Sstevel@tonic-gate 		(void) strcpy(dp->dname, &name[5]);
1084*7c478bd9Sstevel@tonic-gate 	else {
1085*7c478bd9Sstevel@tonic-gate 		start = leng - DNSIZE - 1;
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 		for (i = start; i < leng && name[i] != '/'; i++)
1088*7c478bd9Sstevel@tonic-gate 				;
1089*7c478bd9Sstevel@tonic-gate 		if (i == leng)
1090*7c478bd9Sstevel@tonic-gate 			(void) strncpy(dp->dname, &name[start], DNSIZE);
1091*7c478bd9Sstevel@tonic-gate 		else
1092*7c478bd9Sstevel@tonic-gate 			(void) strncpy(dp->dname, &name[i+1], DNSIZE);
1093*7c478bd9Sstevel@tonic-gate 	}
1094*7c478bd9Sstevel@tonic-gate 	return (dp->dname);
1095*7c478bd9Sstevel@tonic-gate }
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate /*
1098*7c478bd9Sstevel@tonic-gate  * gettty returns the user's tty number or ? if none.
1099*7c478bd9Sstevel@tonic-gate  */
1100*7c478bd9Sstevel@tonic-gate static char *
1101*7c478bd9Sstevel@tonic-gate gettty(psinfo_t *psinfo)
1102*7c478bd9Sstevel@tonic-gate {
1103*7c478bd9Sstevel@tonic-gate 	extern char *_ttyname_dev(dev_t, char *, size_t);
1104*7c478bd9Sstevel@tonic-gate 	char devname[TTYNAME_MAX];
1105*7c478bd9Sstevel@tonic-gate 	char *retval;
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate 	if (psinfo->pr_ttydev == PRNODEV)
1108*7c478bd9Sstevel@tonic-gate 		return ("?");
1109*7c478bd9Sstevel@tonic-gate 
1110*7c478bd9Sstevel@tonic-gate 	if ((retval = devlookup(psinfo->pr_ttydev)) != NULL)
1111*7c478bd9Sstevel@tonic-gate 		return (retval);
1112*7c478bd9Sstevel@tonic-gate 
1113*7c478bd9Sstevel@tonic-gate 	retval = _ttyname_dev(psinfo->pr_ttydev, devname, sizeof (devname));
1114*7c478bd9Sstevel@tonic-gate 
1115*7c478bd9Sstevel@tonic-gate 	return (devadd(retval, psinfo->pr_ttydev));
1116*7c478bd9Sstevel@tonic-gate }
1117*7c478bd9Sstevel@tonic-gate 
1118*7c478bd9Sstevel@tonic-gate /*
1119*7c478bd9Sstevel@tonic-gate  * Find the process's tty and return 1 if process is to be printed.
1120*7c478bd9Sstevel@tonic-gate  */
1121*7c478bd9Sstevel@tonic-gate static int
1122*7c478bd9Sstevel@tonic-gate prfind(int found, psinfo_t *psinfo, char **tpp)
1123*7c478bd9Sstevel@tonic-gate {
1124*7c478bd9Sstevel@tonic-gate 	char	*tp;
1125*7c478bd9Sstevel@tonic-gate 	struct tty *ttyp;
1126*7c478bd9Sstevel@tonic-gate 
1127*7c478bd9Sstevel@tonic-gate 	if (psinfo->pr_nlwp == 0) {
1128*7c478bd9Sstevel@tonic-gate 		/* process is a zombie */
1129*7c478bd9Sstevel@tonic-gate 		*tpp = "?";
1130*7c478bd9Sstevel@tonic-gate 		if (tflg && !found)
1131*7c478bd9Sstevel@tonic-gate 			return (0);
1132*7c478bd9Sstevel@tonic-gate 		return (1);
1133*7c478bd9Sstevel@tonic-gate 	}
1134*7c478bd9Sstevel@tonic-gate 
1135*7c478bd9Sstevel@tonic-gate 	/*
1136*7c478bd9Sstevel@tonic-gate 	 * Get current terminal.  If none ("?") and 'a' is set, don't print
1137*7c478bd9Sstevel@tonic-gate 	 * info.  If 't' is set, check if term is in list of desired terminals
1138*7c478bd9Sstevel@tonic-gate 	 * and print it if it is.
1139*7c478bd9Sstevel@tonic-gate 	 */
1140*7c478bd9Sstevel@tonic-gate 	tp = gettty(psinfo);
1141*7c478bd9Sstevel@tonic-gate 	if (aflg && *tp == '?') {
1142*7c478bd9Sstevel@tonic-gate 		*tpp = tp;
1143*7c478bd9Sstevel@tonic-gate 		return (0);
1144*7c478bd9Sstevel@tonic-gate 	}
1145*7c478bd9Sstevel@tonic-gate 	if (tflg && !found) {
1146*7c478bd9Sstevel@tonic-gate 		int match = 0;
1147*7c478bd9Sstevel@tonic-gate 		char *other = NULL;
1148*7c478bd9Sstevel@tonic-gate 		for (ttyp = tty; ttyp->tname != NULL; ttyp++) {
1149*7c478bd9Sstevel@tonic-gate 			/*
1150*7c478bd9Sstevel@tonic-gate 			 * Look for a name match
1151*7c478bd9Sstevel@tonic-gate 			 */
1152*7c478bd9Sstevel@tonic-gate 			if (strcmp(tp, ttyp->tname) == 0) {
1153*7c478bd9Sstevel@tonic-gate 				match = 1;
1154*7c478bd9Sstevel@tonic-gate 				break;
1155*7c478bd9Sstevel@tonic-gate 			}
1156*7c478bd9Sstevel@tonic-gate 			/*
1157*7c478bd9Sstevel@tonic-gate 			 * Look for same device under different names.
1158*7c478bd9Sstevel@tonic-gate 			 */
1159*7c478bd9Sstevel@tonic-gate 			if ((other == NULL) &&
1160*7c478bd9Sstevel@tonic-gate 			    (ttyp->tdev != PRNODEV) &&
1161*7c478bd9Sstevel@tonic-gate 			    (psinfo->pr_ttydev == ttyp->tdev))
1162*7c478bd9Sstevel@tonic-gate 				other = ttyp->tname;
1163*7c478bd9Sstevel@tonic-gate 		}
1164*7c478bd9Sstevel@tonic-gate 		if (!match && (other != NULL)) {
1165*7c478bd9Sstevel@tonic-gate 			/*
1166*7c478bd9Sstevel@tonic-gate 			 * found under a different name
1167*7c478bd9Sstevel@tonic-gate 			 */
1168*7c478bd9Sstevel@tonic-gate 			match = 1;
1169*7c478bd9Sstevel@tonic-gate 			tp = other;
1170*7c478bd9Sstevel@tonic-gate 		}
1171*7c478bd9Sstevel@tonic-gate 		if (!match || (tuid != -1 && tuid != psinfo->pr_euid)) {
1172*7c478bd9Sstevel@tonic-gate 			/*
1173*7c478bd9Sstevel@tonic-gate 			 * not found OR not matching euid
1174*7c478bd9Sstevel@tonic-gate 			 */
1175*7c478bd9Sstevel@tonic-gate 			*tpp = tp;
1176*7c478bd9Sstevel@tonic-gate 			return (0);
1177*7c478bd9Sstevel@tonic-gate 		}
1178*7c478bd9Sstevel@tonic-gate 	}
1179*7c478bd9Sstevel@tonic-gate 	*tpp = tp;
1180*7c478bd9Sstevel@tonic-gate 	return (1);
1181*7c478bd9Sstevel@tonic-gate }
1182*7c478bd9Sstevel@tonic-gate 
1183*7c478bd9Sstevel@tonic-gate /*
1184*7c478bd9Sstevel@tonic-gate  * Print info about the process.
1185*7c478bd9Sstevel@tonic-gate  */
1186*7c478bd9Sstevel@tonic-gate static void
1187*7c478bd9Sstevel@tonic-gate prcom(psinfo_t *psinfo, char *ttyp)
1188*7c478bd9Sstevel@tonic-gate {
1189*7c478bd9Sstevel@tonic-gate 	char	*cp;
1190*7c478bd9Sstevel@tonic-gate 	long	tm;
1191*7c478bd9Sstevel@tonic-gate 	int	bytesleft;
1192*7c478bd9Sstevel@tonic-gate 	int	wcnt, length;
1193*7c478bd9Sstevel@tonic-gate 	wchar_t	wchar;
1194*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
1195*7c478bd9Sstevel@tonic-gate 	int	zombie_lwp;
1196*7c478bd9Sstevel@tonic-gate 	char	zonename[ZONENAME_MAX];
1197*7c478bd9Sstevel@tonic-gate 
1198*7c478bd9Sstevel@tonic-gate 	/*
1199*7c478bd9Sstevel@tonic-gate 	 * If process is zombie, call zombie print routine and return.
1200*7c478bd9Sstevel@tonic-gate 	 */
1201*7c478bd9Sstevel@tonic-gate 	if (psinfo->pr_nlwp == 0) {
1202*7c478bd9Sstevel@tonic-gate 		if (fields != NULL)
1203*7c478bd9Sstevel@tonic-gate 			pr_fields(psinfo, ttyp, print_zombie_field);
1204*7c478bd9Sstevel@tonic-gate 		else
1205*7c478bd9Sstevel@tonic-gate 			przom(psinfo);
1206*7c478bd9Sstevel@tonic-gate 		return;
1207*7c478bd9Sstevel@tonic-gate 	}
1208*7c478bd9Sstevel@tonic-gate 
1209*7c478bd9Sstevel@tonic-gate 	zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z');
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate 	/*
1212*7c478bd9Sstevel@tonic-gate 	 * If user specified '-o format', print requested fields and return.
1213*7c478bd9Sstevel@tonic-gate 	 */
1214*7c478bd9Sstevel@tonic-gate 	if (fields != NULL) {
1215*7c478bd9Sstevel@tonic-gate 		pr_fields(psinfo, ttyp, print_field);
1216*7c478bd9Sstevel@tonic-gate 		return;
1217*7c478bd9Sstevel@tonic-gate 	}
1218*7c478bd9Sstevel@tonic-gate 
1219*7c478bd9Sstevel@tonic-gate 	/*
1220*7c478bd9Sstevel@tonic-gate 	 * All fields before 'PID' are printed with a trailing space as a
1221*7c478bd9Sstevel@tonic-gate 	 * spearator, rather than keeping track of which column is first.  All
1222*7c478bd9Sstevel@tonic-gate 	 * other fields are printed with a leading space.
1223*7c478bd9Sstevel@tonic-gate 	 */
1224*7c478bd9Sstevel@tonic-gate 	if (lflg) {
1225*7c478bd9Sstevel@tonic-gate 		if (!yflg)
1226*7c478bd9Sstevel@tonic-gate 			(void) printf("%2x ", psinfo->pr_flag & 0377); /* F */
1227*7c478bd9Sstevel@tonic-gate 		(void) printf("%c ", psinfo->pr_lwp.pr_sname);	/* S */
1228*7c478bd9Sstevel@tonic-gate 	}
1229*7c478bd9Sstevel@tonic-gate 
1230*7c478bd9Sstevel@tonic-gate 	if (Zflg) {						/* ZONE */
1231*7c478bd9Sstevel@tonic-gate 		if (getzonenamebyid(psinfo->pr_zoneid, zonename,
1232*7c478bd9Sstevel@tonic-gate 		    sizeof (zonename)) < 0) {
1233*7c478bd9Sstevel@tonic-gate 			(void) printf("%7.7d ", ((int)psinfo->pr_zoneid));
1234*7c478bd9Sstevel@tonic-gate 		} else {
1235*7c478bd9Sstevel@tonic-gate 			(void) printf("%8.8s ", zonename);
1236*7c478bd9Sstevel@tonic-gate 		}
1237*7c478bd9Sstevel@tonic-gate 	}
1238*7c478bd9Sstevel@tonic-gate 
1239*7c478bd9Sstevel@tonic-gate 	if (fflg) {						/* UID */
1240*7c478bd9Sstevel@tonic-gate 		if ((pwd = getpwuid(psinfo->pr_euid)) != NULL)
1241*7c478bd9Sstevel@tonic-gate 			(void) printf("%8.8s ", pwd->pw_name);
1242*7c478bd9Sstevel@tonic-gate 		else
1243*7c478bd9Sstevel@tonic-gate 			(void) printf("%7.7d ", (int)psinfo->pr_euid);
1244*7c478bd9Sstevel@tonic-gate 	} else if (lflg) {
1245*7c478bd9Sstevel@tonic-gate 		(void) printf("%6d ", (int)psinfo->pr_euid);
1246*7c478bd9Sstevel@tonic-gate 	}
1247*7c478bd9Sstevel@tonic-gate 	(void) printf("%*d", pidwidth, (int)psinfo->pr_pid); /* PID */
1248*7c478bd9Sstevel@tonic-gate 	if (lflg || fflg)
1249*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*d", pidwidth,
1250*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_ppid); /* PPID */
1251*7c478bd9Sstevel@tonic-gate 	if (jflg) {
1252*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*d", pidwidth,
1253*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_pgid);	/* PGID */
1254*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*d", pidwidth,
1255*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_sid);	/* SID  */
1256*7c478bd9Sstevel@tonic-gate 	}
1257*7c478bd9Sstevel@tonic-gate 	if (Lflg)
1258*7c478bd9Sstevel@tonic-gate 		(void) printf(" %5d", (int)psinfo->pr_lwp.pr_lwpid); /* LWP */
1259*7c478bd9Sstevel@tonic-gate 	if (Pflg) {
1260*7c478bd9Sstevel@tonic-gate 		if (psinfo->pr_lwp.pr_bindpro == PBIND_NONE)	/* PSR */
1261*7c478bd9Sstevel@tonic-gate 			(void) printf("   -");
1262*7c478bd9Sstevel@tonic-gate 		else
1263*7c478bd9Sstevel@tonic-gate 			(void) printf(" %3d", psinfo->pr_lwp.pr_bindpro);
1264*7c478bd9Sstevel@tonic-gate 	}
1265*7c478bd9Sstevel@tonic-gate 	if (Lflg && fflg)					/* NLWP */
1266*7c478bd9Sstevel@tonic-gate 		(void) printf(" %5d", psinfo->pr_nlwp + psinfo->pr_nzomb);
1267*7c478bd9Sstevel@tonic-gate 	if (cflg) {
1268*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)					/* CLS */
1269*7c478bd9Sstevel@tonic-gate 			(void) printf("     ");
1270*7c478bd9Sstevel@tonic-gate 		else
1271*7c478bd9Sstevel@tonic-gate 			(void) printf(" %4s", psinfo->pr_lwp.pr_clname);
1272*7c478bd9Sstevel@tonic-gate 		(void) printf(" %3d", psinfo->pr_lwp.pr_pri);	/* PRI */
1273*7c478bd9Sstevel@tonic-gate 	} else if (lflg || fflg) {
1274*7c478bd9Sstevel@tonic-gate 		(void) printf(" %3d", psinfo->pr_lwp.pr_cpu & 0377); /* C   */
1275*7c478bd9Sstevel@tonic-gate 		if (lflg) {					    /* PRI NI */
1276*7c478bd9Sstevel@tonic-gate 			/*
1277*7c478bd9Sstevel@tonic-gate 			 * Print priorities the old way (lower numbers
1278*7c478bd9Sstevel@tonic-gate 			 * mean higher priority) and print nice value
1279*7c478bd9Sstevel@tonic-gate 			 * for time sharing procs.
1280*7c478bd9Sstevel@tonic-gate 			 */
1281*7c478bd9Sstevel@tonic-gate 			(void) printf(" %3d", psinfo->pr_lwp.pr_oldpri);
1282*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_lwp.pr_oldpri != 0)
1283*7c478bd9Sstevel@tonic-gate 				(void) printf(" %2d", psinfo->pr_lwp.pr_nice);
1284*7c478bd9Sstevel@tonic-gate 			else
1285*7c478bd9Sstevel@tonic-gate 				(void) printf(" %2.2s",
1286*7c478bd9Sstevel@tonic-gate 				    psinfo->pr_lwp.pr_clname);
1287*7c478bd9Sstevel@tonic-gate 		}
1288*7c478bd9Sstevel@tonic-gate 	}
1289*7c478bd9Sstevel@tonic-gate 	if (lflg) {
1290*7c478bd9Sstevel@tonic-gate 		if (yflg) {
1291*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_flag & SSYS)		/* RSS */
1292*7c478bd9Sstevel@tonic-gate 				(void) printf("     0");
1293*7c478bd9Sstevel@tonic-gate 			else if (psinfo->pr_rssize)
1294*7c478bd9Sstevel@tonic-gate 				(void) printf(" %5lu",
1295*7c478bd9Sstevel@tonic-gate 					(ulong_t)psinfo->pr_rssize);
1296*7c478bd9Sstevel@tonic-gate 			else
1297*7c478bd9Sstevel@tonic-gate 				(void) printf("     ?");
1298*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_flag & SSYS)		/* SZ */
1299*7c478bd9Sstevel@tonic-gate 				(void) printf("      0");
1300*7c478bd9Sstevel@tonic-gate 			else if (psinfo->pr_size)
1301*7c478bd9Sstevel@tonic-gate 				(void) printf(" %6lu",
1302*7c478bd9Sstevel@tonic-gate 					(ulong_t)psinfo->pr_size);
1303*7c478bd9Sstevel@tonic-gate 			else
1304*7c478bd9Sstevel@tonic-gate 				(void) printf("      ?");
1305*7c478bd9Sstevel@tonic-gate 		} else {
1306*7c478bd9Sstevel@tonic-gate #ifndef _LP64
1307*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_addr)			/* ADDR */
1308*7c478bd9Sstevel@tonic-gate 				(void) printf(" %8lx",
1309*7c478bd9Sstevel@tonic-gate 					(ulong_t)psinfo->pr_addr);
1310*7c478bd9Sstevel@tonic-gate 			else
1311*7c478bd9Sstevel@tonic-gate #endif
1312*7c478bd9Sstevel@tonic-gate 				(void) printf("        ?");
1313*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_flag & SSYS)		/* SZ */
1314*7c478bd9Sstevel@tonic-gate 				(void) printf("      0");
1315*7c478bd9Sstevel@tonic-gate 			else if (psinfo->pr_size)
1316*7c478bd9Sstevel@tonic-gate 				(void) printf(" %6lu",
1317*7c478bd9Sstevel@tonic-gate 				    (ulong_t)psinfo->pr_size / kbytes_per_page);
1318*7c478bd9Sstevel@tonic-gate 			else
1319*7c478bd9Sstevel@tonic-gate 				(void) printf("      ?");
1320*7c478bd9Sstevel@tonic-gate 		}
1321*7c478bd9Sstevel@tonic-gate 		if (psinfo->pr_lwp.pr_sname != 'S')		/* WCHAN */
1322*7c478bd9Sstevel@tonic-gate 			(void) printf("         ");
1323*7c478bd9Sstevel@tonic-gate #ifndef _LP64
1324*7c478bd9Sstevel@tonic-gate 		else if (psinfo->pr_lwp.pr_wchan)
1325*7c478bd9Sstevel@tonic-gate 			(void) printf(" %8lx",
1326*7c478bd9Sstevel@tonic-gate 				(ulong_t)psinfo->pr_lwp.pr_wchan);
1327*7c478bd9Sstevel@tonic-gate #endif
1328*7c478bd9Sstevel@tonic-gate 		else
1329*7c478bd9Sstevel@tonic-gate 			(void) printf("        ?");
1330*7c478bd9Sstevel@tonic-gate 	}
1331*7c478bd9Sstevel@tonic-gate 	if (fflg) {						/* STIME */
1332*7c478bd9Sstevel@tonic-gate 		if (Lflg)
1333*7c478bd9Sstevel@tonic-gate 			prtime(psinfo->pr_lwp.pr_start, 9, 1);
1334*7c478bd9Sstevel@tonic-gate 		else
1335*7c478bd9Sstevel@tonic-gate 			prtime(psinfo->pr_start, 9, 1);
1336*7c478bd9Sstevel@tonic-gate 	}
1337*7c478bd9Sstevel@tonic-gate 	(void) printf(" %-8.14s", ttyp);			/* TTY */
1338*7c478bd9Sstevel@tonic-gate 	if (Lflg) {
1339*7c478bd9Sstevel@tonic-gate 		tm = psinfo->pr_lwp.pr_time.tv_sec;
1340*7c478bd9Sstevel@tonic-gate 		if (psinfo->pr_lwp.pr_time.tv_nsec > 500000000)
1341*7c478bd9Sstevel@tonic-gate 			tm++;
1342*7c478bd9Sstevel@tonic-gate 	} else {
1343*7c478bd9Sstevel@tonic-gate 		tm = psinfo->pr_time.tv_sec;
1344*7c478bd9Sstevel@tonic-gate 		if (psinfo->pr_time.tv_nsec > 500000000)
1345*7c478bd9Sstevel@tonic-gate 			tm++;
1346*7c478bd9Sstevel@tonic-gate 	}
1347*7c478bd9Sstevel@tonic-gate 	(void) printf(" %4ld:%.2ld", tm / 60, tm % 60);		/* [L]TIME */
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 	if (zombie_lwp) {
1350*7c478bd9Sstevel@tonic-gate 		(void) printf(" <defunct>\n");
1351*7c478bd9Sstevel@tonic-gate 		return;
1352*7c478bd9Sstevel@tonic-gate 	}
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 	if (!fflg) {						/* CMD */
1355*7c478bd9Sstevel@tonic-gate 		wcnt = namencnt(psinfo->pr_fname, 16, 8);
1356*7c478bd9Sstevel@tonic-gate 		(void) printf(" %.*s\n", wcnt, psinfo->pr_fname);
1357*7c478bd9Sstevel@tonic-gate 		return;
1358*7c478bd9Sstevel@tonic-gate 	}
1359*7c478bd9Sstevel@tonic-gate 
1360*7c478bd9Sstevel@tonic-gate 	/*
1361*7c478bd9Sstevel@tonic-gate 	 * PRARGSZ == length of cmd arg string.
1362*7c478bd9Sstevel@tonic-gate 	 */
1363*7c478bd9Sstevel@tonic-gate 	psinfo->pr_psargs[PRARGSZ-1] = '\0';
1364*7c478bd9Sstevel@tonic-gate 	bytesleft = PRARGSZ;
1365*7c478bd9Sstevel@tonic-gate 	for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) {
1366*7c478bd9Sstevel@tonic-gate 		length = mbtowc(&wchar, cp, MB_LEN_MAX);
1367*7c478bd9Sstevel@tonic-gate 		if (length == 0)
1368*7c478bd9Sstevel@tonic-gate 			break;
1369*7c478bd9Sstevel@tonic-gate 		if (length < 0 || !iswprint(wchar)) {
1370*7c478bd9Sstevel@tonic-gate 			if (length < 0)
1371*7c478bd9Sstevel@tonic-gate 				length = 1;
1372*7c478bd9Sstevel@tonic-gate 			if (bytesleft <= length) {
1373*7c478bd9Sstevel@tonic-gate 				*cp = '\0';
1374*7c478bd9Sstevel@tonic-gate 				break;
1375*7c478bd9Sstevel@tonic-gate 			}
1376*7c478bd9Sstevel@tonic-gate 			/* omit the unprintable character */
1377*7c478bd9Sstevel@tonic-gate 			(void) memmove(cp, cp+length, bytesleft-length);
1378*7c478bd9Sstevel@tonic-gate 			length = 0;
1379*7c478bd9Sstevel@tonic-gate 		}
1380*7c478bd9Sstevel@tonic-gate 		bytesleft -= length;
1381*7c478bd9Sstevel@tonic-gate 	}
1382*7c478bd9Sstevel@tonic-gate 	wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, lflg ? 35 : PRARGSZ);
1383*7c478bd9Sstevel@tonic-gate 	(void) printf(" %.*s\n", wcnt, psinfo->pr_psargs);
1384*7c478bd9Sstevel@tonic-gate }
1385*7c478bd9Sstevel@tonic-gate 
1386*7c478bd9Sstevel@tonic-gate /*
1387*7c478bd9Sstevel@tonic-gate  * Print percent from 16-bit binary fraction [0 .. 1]
1388*7c478bd9Sstevel@tonic-gate  * Round up .01 to .1 to indicate some small percentage (the 0x7000 below).
1389*7c478bd9Sstevel@tonic-gate  */
1390*7c478bd9Sstevel@tonic-gate static void
1391*7c478bd9Sstevel@tonic-gate prtpct(ushort_t pct, int width)
1392*7c478bd9Sstevel@tonic-gate {
1393*7c478bd9Sstevel@tonic-gate 	uint_t value = pct;	/* need 32 bits to compute with */
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 	value = ((value * 1000) + 0x7000) >> 15;	/* [0 .. 1000] */
1396*7c478bd9Sstevel@tonic-gate 	if (value >= 1000)
1397*7c478bd9Sstevel@tonic-gate 		value = 999;
1398*7c478bd9Sstevel@tonic-gate 	if ((width -= 2) < 2)
1399*7c478bd9Sstevel@tonic-gate 		width = 2;
1400*7c478bd9Sstevel@tonic-gate 	(void) printf("%*u.%u", width, value / 10, value % 10);
1401*7c478bd9Sstevel@tonic-gate }
1402*7c478bd9Sstevel@tonic-gate 
1403*7c478bd9Sstevel@tonic-gate static void
1404*7c478bd9Sstevel@tonic-gate print_time(time_t tim, int width)
1405*7c478bd9Sstevel@tonic-gate {
1406*7c478bd9Sstevel@tonic-gate 	char buf[30];
1407*7c478bd9Sstevel@tonic-gate 	time_t seconds;
1408*7c478bd9Sstevel@tonic-gate 	time_t minutes;
1409*7c478bd9Sstevel@tonic-gate 	time_t hours;
1410*7c478bd9Sstevel@tonic-gate 	time_t days;
1411*7c478bd9Sstevel@tonic-gate 
1412*7c478bd9Sstevel@tonic-gate 	if (tim < 0) {
1413*7c478bd9Sstevel@tonic-gate 		(void) printf("%*s", width, "-");
1414*7c478bd9Sstevel@tonic-gate 		return;
1415*7c478bd9Sstevel@tonic-gate 	}
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 	seconds = tim % 60;
1418*7c478bd9Sstevel@tonic-gate 	tim /= 60;
1419*7c478bd9Sstevel@tonic-gate 	minutes = tim % 60;
1420*7c478bd9Sstevel@tonic-gate 	tim /= 60;
1421*7c478bd9Sstevel@tonic-gate 	hours = tim % 24;
1422*7c478bd9Sstevel@tonic-gate 	days = tim / 24;
1423*7c478bd9Sstevel@tonic-gate 
1424*7c478bd9Sstevel@tonic-gate 	if (days > 0) {
1425*7c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf), "%ld-%2.2ld:%2.2ld:%2.2ld",
1426*7c478bd9Sstevel@tonic-gate 		    days, hours, minutes, seconds);
1427*7c478bd9Sstevel@tonic-gate 	} else if (hours > 0) {
1428*7c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf), "%2.2ld:%2.2ld:%2.2ld",
1429*7c478bd9Sstevel@tonic-gate 		    hours, minutes, seconds);
1430*7c478bd9Sstevel@tonic-gate 	} else {
1431*7c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf), "%2.2ld:%2.2ld",
1432*7c478bd9Sstevel@tonic-gate 		    minutes, seconds);
1433*7c478bd9Sstevel@tonic-gate 	}
1434*7c478bd9Sstevel@tonic-gate 
1435*7c478bd9Sstevel@tonic-gate 	(void) printf("%*s", width, buf);
1436*7c478bd9Sstevel@tonic-gate }
1437*7c478bd9Sstevel@tonic-gate 
1438*7c478bd9Sstevel@tonic-gate static void
1439*7c478bd9Sstevel@tonic-gate print_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
1440*7c478bd9Sstevel@tonic-gate {
1441*7c478bd9Sstevel@tonic-gate 	int width = f->width;
1442*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
1443*7c478bd9Sstevel@tonic-gate 	struct group *grp;
1444*7c478bd9Sstevel@tonic-gate 	time_t cputime;
1445*7c478bd9Sstevel@tonic-gate 	int bytesleft;
1446*7c478bd9Sstevel@tonic-gate 	int wcnt;
1447*7c478bd9Sstevel@tonic-gate 	wchar_t	wchar;
1448*7c478bd9Sstevel@tonic-gate 	char *cp;
1449*7c478bd9Sstevel@tonic-gate 	int length;
1450*7c478bd9Sstevel@tonic-gate 	ulong_t mask;
1451*7c478bd9Sstevel@tonic-gate 	char c, *csave;
1452*7c478bd9Sstevel@tonic-gate 	int zombie_lwp;
1453*7c478bd9Sstevel@tonic-gate 
1454*7c478bd9Sstevel@tonic-gate 	zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z');
1455*7c478bd9Sstevel@tonic-gate 
1456*7c478bd9Sstevel@tonic-gate 	switch (f->fname) {
1457*7c478bd9Sstevel@tonic-gate 	case F_RUSER:
1458*7c478bd9Sstevel@tonic-gate 		if ((pwd = getpwuid(psinfo->pr_uid)) != NULL)
1459*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, pwd->pw_name);
1460*7c478bd9Sstevel@tonic-gate 		else
1461*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, (int)psinfo->pr_uid);
1462*7c478bd9Sstevel@tonic-gate 		break;
1463*7c478bd9Sstevel@tonic-gate 	case F_USER:
1464*7c478bd9Sstevel@tonic-gate 		if ((pwd = getpwuid(psinfo->pr_euid)) != NULL)
1465*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, pwd->pw_name);
1466*7c478bd9Sstevel@tonic-gate 		else
1467*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, (int)psinfo->pr_euid);
1468*7c478bd9Sstevel@tonic-gate 		break;
1469*7c478bd9Sstevel@tonic-gate 	case F_RGROUP:
1470*7c478bd9Sstevel@tonic-gate 		if ((grp = getgrgid(psinfo->pr_gid)) != NULL)
1471*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, grp->gr_name);
1472*7c478bd9Sstevel@tonic-gate 		else
1473*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, (int)psinfo->pr_gid);
1474*7c478bd9Sstevel@tonic-gate 		break;
1475*7c478bd9Sstevel@tonic-gate 	case F_GROUP:
1476*7c478bd9Sstevel@tonic-gate 		if ((grp = getgrgid(psinfo->pr_egid)) != NULL)
1477*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, grp->gr_name);
1478*7c478bd9Sstevel@tonic-gate 		else
1479*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, (int)psinfo->pr_egid);
1480*7c478bd9Sstevel@tonic-gate 		break;
1481*7c478bd9Sstevel@tonic-gate 	case F_RUID:
1482*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_uid);
1483*7c478bd9Sstevel@tonic-gate 		break;
1484*7c478bd9Sstevel@tonic-gate 	case F_UID:
1485*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_euid);
1486*7c478bd9Sstevel@tonic-gate 		break;
1487*7c478bd9Sstevel@tonic-gate 	case F_RGID:
1488*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_gid);
1489*7c478bd9Sstevel@tonic-gate 		break;
1490*7c478bd9Sstevel@tonic-gate 	case F_GID:
1491*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_egid);
1492*7c478bd9Sstevel@tonic-gate 		break;
1493*7c478bd9Sstevel@tonic-gate 	case F_PID:
1494*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_pid);
1495*7c478bd9Sstevel@tonic-gate 		break;
1496*7c478bd9Sstevel@tonic-gate 	case F_PPID:
1497*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_ppid);
1498*7c478bd9Sstevel@tonic-gate 		break;
1499*7c478bd9Sstevel@tonic-gate 	case F_PGID:
1500*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_pgid);
1501*7c478bd9Sstevel@tonic-gate 		break;
1502*7c478bd9Sstevel@tonic-gate 	case F_SID:
1503*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_sid);
1504*7c478bd9Sstevel@tonic-gate 		break;
1505*7c478bd9Sstevel@tonic-gate 	case F_PSR:
1506*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp || psinfo->pr_lwp.pr_bindpro == PBIND_NONE)
1507*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1508*7c478bd9Sstevel@tonic-gate 		else
1509*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, psinfo->pr_lwp.pr_bindpro);
1510*7c478bd9Sstevel@tonic-gate 		break;
1511*7c478bd9Sstevel@tonic-gate 	case F_LWP:
1512*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid);
1513*7c478bd9Sstevel@tonic-gate 		break;
1514*7c478bd9Sstevel@tonic-gate 	case F_NLWP:
1515*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, psinfo->pr_nlwp + psinfo->pr_nzomb);
1516*7c478bd9Sstevel@tonic-gate 		break;
1517*7c478bd9Sstevel@tonic-gate 	case F_OPRI:
1518*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1519*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1520*7c478bd9Sstevel@tonic-gate 		else
1521*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, psinfo->pr_lwp.pr_oldpri);
1522*7c478bd9Sstevel@tonic-gate 		break;
1523*7c478bd9Sstevel@tonic-gate 	case F_PRI:
1524*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1525*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1526*7c478bd9Sstevel@tonic-gate 		else
1527*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, psinfo->pr_lwp.pr_pri);
1528*7c478bd9Sstevel@tonic-gate 		break;
1529*7c478bd9Sstevel@tonic-gate 	case F_F:
1530*7c478bd9Sstevel@tonic-gate 		mask = 0xffffffffUL;
1531*7c478bd9Sstevel@tonic-gate 		if (width < 8)
1532*7c478bd9Sstevel@tonic-gate 			mask >>= (8 - width) * 4;
1533*7c478bd9Sstevel@tonic-gate 		(void) printf("%*lx", width, psinfo->pr_flag & mask);
1534*7c478bd9Sstevel@tonic-gate 		break;
1535*7c478bd9Sstevel@tonic-gate 	case F_S:
1536*7c478bd9Sstevel@tonic-gate 		(void) printf("%*c", width, psinfo->pr_lwp.pr_sname);
1537*7c478bd9Sstevel@tonic-gate 		break;
1538*7c478bd9Sstevel@tonic-gate 	case F_C:
1539*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1540*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1541*7c478bd9Sstevel@tonic-gate 		else
1542*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, psinfo->pr_lwp.pr_cpu);
1543*7c478bd9Sstevel@tonic-gate 		break;
1544*7c478bd9Sstevel@tonic-gate 	case F_PCPU:
1545*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1546*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1547*7c478bd9Sstevel@tonic-gate 		else if (Lflg)
1548*7c478bd9Sstevel@tonic-gate 			prtpct(psinfo->pr_lwp.pr_pctcpu, width);
1549*7c478bd9Sstevel@tonic-gate 		else
1550*7c478bd9Sstevel@tonic-gate 			prtpct(psinfo->pr_pctcpu, width);
1551*7c478bd9Sstevel@tonic-gate 		break;
1552*7c478bd9Sstevel@tonic-gate 	case F_PMEM:
1553*7c478bd9Sstevel@tonic-gate 		prtpct(psinfo->pr_pctmem, width);
1554*7c478bd9Sstevel@tonic-gate 		break;
1555*7c478bd9Sstevel@tonic-gate 	case F_OSZ:
1556*7c478bd9Sstevel@tonic-gate 		(void) printf("%*lu", width,
1557*7c478bd9Sstevel@tonic-gate 			(ulong_t)psinfo->pr_size / kbytes_per_page);
1558*7c478bd9Sstevel@tonic-gate 		break;
1559*7c478bd9Sstevel@tonic-gate 	case F_VSZ:
1560*7c478bd9Sstevel@tonic-gate 		(void) printf("%*lu", width, (ulong_t)psinfo->pr_size);
1561*7c478bd9Sstevel@tonic-gate 		break;
1562*7c478bd9Sstevel@tonic-gate 	case F_RSS:
1563*7c478bd9Sstevel@tonic-gate 		(void) printf("%*lu", width, (ulong_t)psinfo->pr_rssize);
1564*7c478bd9Sstevel@tonic-gate 		break;
1565*7c478bd9Sstevel@tonic-gate 	case F_NICE:
1566*7c478bd9Sstevel@tonic-gate 		/* if pr_oldpri is zero, then this class has no nice */
1567*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1568*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1569*7c478bd9Sstevel@tonic-gate 		else if (psinfo->pr_lwp.pr_oldpri != 0)
1570*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, psinfo->pr_lwp.pr_nice);
1571*7c478bd9Sstevel@tonic-gate 		else
1572*7c478bd9Sstevel@tonic-gate 			(void) printf("%*.*s", width, width,
1573*7c478bd9Sstevel@tonic-gate 				psinfo->pr_lwp.pr_clname);
1574*7c478bd9Sstevel@tonic-gate 		break;
1575*7c478bd9Sstevel@tonic-gate 	case F_CLASS:
1576*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1577*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1578*7c478bd9Sstevel@tonic-gate 		else
1579*7c478bd9Sstevel@tonic-gate 			(void) printf("%*.*s", width, width,
1580*7c478bd9Sstevel@tonic-gate 				psinfo->pr_lwp.pr_clname);
1581*7c478bd9Sstevel@tonic-gate 		break;
1582*7c478bd9Sstevel@tonic-gate 	case F_STIME:
1583*7c478bd9Sstevel@tonic-gate 		if (Lflg)
1584*7c478bd9Sstevel@tonic-gate 			prtime(psinfo->pr_lwp.pr_start, width, 0);
1585*7c478bd9Sstevel@tonic-gate 		else
1586*7c478bd9Sstevel@tonic-gate 			prtime(psinfo->pr_start, width, 0);
1587*7c478bd9Sstevel@tonic-gate 		break;
1588*7c478bd9Sstevel@tonic-gate 	case F_ETIME:
1589*7c478bd9Sstevel@tonic-gate 		if (Lflg)
1590*7c478bd9Sstevel@tonic-gate 			print_time(delta_secs(&psinfo->pr_lwp.pr_start),
1591*7c478bd9Sstevel@tonic-gate 				width);
1592*7c478bd9Sstevel@tonic-gate 		else
1593*7c478bd9Sstevel@tonic-gate 			print_time(delta_secs(&psinfo->pr_start), width);
1594*7c478bd9Sstevel@tonic-gate 		break;
1595*7c478bd9Sstevel@tonic-gate 	case F_TIME:
1596*7c478bd9Sstevel@tonic-gate 		if (Lflg) {
1597*7c478bd9Sstevel@tonic-gate 			cputime = psinfo->pr_lwp.pr_time.tv_sec;
1598*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_lwp.pr_time.tv_nsec > 500000000)
1599*7c478bd9Sstevel@tonic-gate 				cputime++;
1600*7c478bd9Sstevel@tonic-gate 		} else {
1601*7c478bd9Sstevel@tonic-gate 			cputime = psinfo->pr_time.tv_sec;
1602*7c478bd9Sstevel@tonic-gate 			if (psinfo->pr_time.tv_nsec > 500000000)
1603*7c478bd9Sstevel@tonic-gate 				cputime++;
1604*7c478bd9Sstevel@tonic-gate 		}
1605*7c478bd9Sstevel@tonic-gate 		print_time(cputime, width);
1606*7c478bd9Sstevel@tonic-gate 		break;
1607*7c478bd9Sstevel@tonic-gate 	case F_TTY:
1608*7c478bd9Sstevel@tonic-gate 		(void) printf("%-*s", width, ttyp);
1609*7c478bd9Sstevel@tonic-gate 		break;
1610*7c478bd9Sstevel@tonic-gate 	case F_ADDR:
1611*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp)
1612*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1613*7c478bd9Sstevel@tonic-gate 		else if (Lflg)
1614*7c478bd9Sstevel@tonic-gate 			(void) printf("%*lx", width,
1615*7c478bd9Sstevel@tonic-gate 				(long)psinfo->pr_lwp.pr_addr);
1616*7c478bd9Sstevel@tonic-gate 		else
1617*7c478bd9Sstevel@tonic-gate 			(void) printf("%*lx", width, (long)psinfo->pr_addr);
1618*7c478bd9Sstevel@tonic-gate 		break;
1619*7c478bd9Sstevel@tonic-gate 	case F_WCHAN:
1620*7c478bd9Sstevel@tonic-gate 		if (!zombie_lwp && psinfo->pr_lwp.pr_wchan)
1621*7c478bd9Sstevel@tonic-gate 			(void) printf("%*lx", width,
1622*7c478bd9Sstevel@tonic-gate 				(long)psinfo->pr_lwp.pr_wchan);
1623*7c478bd9Sstevel@tonic-gate 		else
1624*7c478bd9Sstevel@tonic-gate 			(void) printf("%*.*s", width, width, "-");
1625*7c478bd9Sstevel@tonic-gate 		break;
1626*7c478bd9Sstevel@tonic-gate 	case F_FNAME:
1627*7c478bd9Sstevel@tonic-gate 		/*
1628*7c478bd9Sstevel@tonic-gate 		 * Print full width unless this is the last output format.
1629*7c478bd9Sstevel@tonic-gate 		 */
1630*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp) {
1631*7c478bd9Sstevel@tonic-gate 			if (f->next != NULL)
1632*7c478bd9Sstevel@tonic-gate 				(void) printf("%-*s", width, "<defunct>");
1633*7c478bd9Sstevel@tonic-gate 			else
1634*7c478bd9Sstevel@tonic-gate 				(void) printf("%s", "<defunct>");
1635*7c478bd9Sstevel@tonic-gate 			break;
1636*7c478bd9Sstevel@tonic-gate 		}
1637*7c478bd9Sstevel@tonic-gate 		wcnt = namencnt(psinfo->pr_fname, 16, width);
1638*7c478bd9Sstevel@tonic-gate 		if (f->next != NULL)
1639*7c478bd9Sstevel@tonic-gate 			(void) printf("%-*.*s", width, wcnt, psinfo->pr_fname);
1640*7c478bd9Sstevel@tonic-gate 		else
1641*7c478bd9Sstevel@tonic-gate 			(void) printf("%-.*s", wcnt, psinfo->pr_fname);
1642*7c478bd9Sstevel@tonic-gate 		break;
1643*7c478bd9Sstevel@tonic-gate 	case F_COMM:
1644*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp) {
1645*7c478bd9Sstevel@tonic-gate 			if (f->next != NULL)
1646*7c478bd9Sstevel@tonic-gate 				(void) printf("%-*s", width, "<defunct>");
1647*7c478bd9Sstevel@tonic-gate 			else
1648*7c478bd9Sstevel@tonic-gate 				(void) printf("%s", "<defunct>");
1649*7c478bd9Sstevel@tonic-gate 			break;
1650*7c478bd9Sstevel@tonic-gate 		}
1651*7c478bd9Sstevel@tonic-gate 		csave = strpbrk(psinfo->pr_psargs, " \t\r\v\f\n");
1652*7c478bd9Sstevel@tonic-gate 		if (csave) {
1653*7c478bd9Sstevel@tonic-gate 			c = *csave;
1654*7c478bd9Sstevel@tonic-gate 			*csave = '\0';
1655*7c478bd9Sstevel@tonic-gate 		}
1656*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
1657*7c478bd9Sstevel@tonic-gate 	case F_ARGS:
1658*7c478bd9Sstevel@tonic-gate 		/*
1659*7c478bd9Sstevel@tonic-gate 		 * PRARGSZ == length of cmd arg string.
1660*7c478bd9Sstevel@tonic-gate 		 */
1661*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp) {
1662*7c478bd9Sstevel@tonic-gate 			(void) printf("%-*s", width, "<defunct>");
1663*7c478bd9Sstevel@tonic-gate 			break;
1664*7c478bd9Sstevel@tonic-gate 		}
1665*7c478bd9Sstevel@tonic-gate 		psinfo->pr_psargs[PRARGSZ-1] = '\0';
1666*7c478bd9Sstevel@tonic-gate 		bytesleft = PRARGSZ;
1667*7c478bd9Sstevel@tonic-gate 		for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) {
1668*7c478bd9Sstevel@tonic-gate 			length = mbtowc(&wchar, cp, MB_LEN_MAX);
1669*7c478bd9Sstevel@tonic-gate 			if (length == 0)
1670*7c478bd9Sstevel@tonic-gate 				break;
1671*7c478bd9Sstevel@tonic-gate 			if (length < 0 || !iswprint(wchar)) {
1672*7c478bd9Sstevel@tonic-gate 				if (length < 0)
1673*7c478bd9Sstevel@tonic-gate 					length = 1;
1674*7c478bd9Sstevel@tonic-gate 				if (bytesleft <= length) {
1675*7c478bd9Sstevel@tonic-gate 					*cp = '\0';
1676*7c478bd9Sstevel@tonic-gate 					break;
1677*7c478bd9Sstevel@tonic-gate 				}
1678*7c478bd9Sstevel@tonic-gate 				/* omit the unprintable character */
1679*7c478bd9Sstevel@tonic-gate 				(void) memmove(cp, cp+length, bytesleft-length);
1680*7c478bd9Sstevel@tonic-gate 				length = 0;
1681*7c478bd9Sstevel@tonic-gate 			}
1682*7c478bd9Sstevel@tonic-gate 			bytesleft -= length;
1683*7c478bd9Sstevel@tonic-gate 		}
1684*7c478bd9Sstevel@tonic-gate 		wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, width);
1685*7c478bd9Sstevel@tonic-gate 		/*
1686*7c478bd9Sstevel@tonic-gate 		 * Print full width unless this is the last format.
1687*7c478bd9Sstevel@tonic-gate 		 */
1688*7c478bd9Sstevel@tonic-gate 		if (f->next != NULL)
1689*7c478bd9Sstevel@tonic-gate 			(void) printf("%-*.*s", width, wcnt,
1690*7c478bd9Sstevel@tonic-gate 			    psinfo->pr_psargs);
1691*7c478bd9Sstevel@tonic-gate 		else
1692*7c478bd9Sstevel@tonic-gate 			(void) printf("%-.*s", wcnt,
1693*7c478bd9Sstevel@tonic-gate 			    psinfo->pr_psargs);
1694*7c478bd9Sstevel@tonic-gate 		if (f->fname == F_COMM && csave)
1695*7c478bd9Sstevel@tonic-gate 			*csave = c;
1696*7c478bd9Sstevel@tonic-gate 		break;
1697*7c478bd9Sstevel@tonic-gate 	case F_TASKID:
1698*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_taskid);
1699*7c478bd9Sstevel@tonic-gate 		break;
1700*7c478bd9Sstevel@tonic-gate 	case F_PROJID:
1701*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_projid);
1702*7c478bd9Sstevel@tonic-gate 		break;
1703*7c478bd9Sstevel@tonic-gate 	case F_PROJECT:
1704*7c478bd9Sstevel@tonic-gate 		{
1705*7c478bd9Sstevel@tonic-gate 			struct project cproj;
1706*7c478bd9Sstevel@tonic-gate 			char proj_buf[PROJECT_BUFSZ];
1707*7c478bd9Sstevel@tonic-gate 
1708*7c478bd9Sstevel@tonic-gate 			if ((getprojbyid(psinfo->pr_projid, &cproj,
1709*7c478bd9Sstevel@tonic-gate 			    (void *)&proj_buf, PROJECT_BUFSZ)) == NULL)
1710*7c478bd9Sstevel@tonic-gate 				(void) printf("%*d", width,
1711*7c478bd9Sstevel@tonic-gate 				    (int)psinfo->pr_projid);
1712*7c478bd9Sstevel@tonic-gate 			else
1713*7c478bd9Sstevel@tonic-gate 				(void) printf("%*s", width,
1714*7c478bd9Sstevel@tonic-gate 				    (cproj.pj_name != NULL) ?
1715*7c478bd9Sstevel@tonic-gate 				    cproj.pj_name : "---");
1716*7c478bd9Sstevel@tonic-gate 		}
1717*7c478bd9Sstevel@tonic-gate 		break;
1718*7c478bd9Sstevel@tonic-gate 	case F_PSET:
1719*7c478bd9Sstevel@tonic-gate 		if (zombie_lwp || psinfo->pr_lwp.pr_bindpset == PS_NONE)
1720*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1721*7c478bd9Sstevel@tonic-gate 		else
1722*7c478bd9Sstevel@tonic-gate 			(void) printf("%*d", width, psinfo->pr_lwp.pr_bindpset);
1723*7c478bd9Sstevel@tonic-gate 		break;
1724*7c478bd9Sstevel@tonic-gate 	case F_ZONEID:
1725*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, (int)psinfo->pr_zoneid);
1726*7c478bd9Sstevel@tonic-gate 		break;
1727*7c478bd9Sstevel@tonic-gate 	case F_ZONE:
1728*7c478bd9Sstevel@tonic-gate 		{
1729*7c478bd9Sstevel@tonic-gate 			char zonename[ZONENAME_MAX];
1730*7c478bd9Sstevel@tonic-gate 
1731*7c478bd9Sstevel@tonic-gate 			if (getzonenamebyid(psinfo->pr_zoneid, zonename,
1732*7c478bd9Sstevel@tonic-gate 			    sizeof (zonename)) < 0) {
1733*7c478bd9Sstevel@tonic-gate 				(void) printf("%*d", width,
1734*7c478bd9Sstevel@tonic-gate 				    ((int)psinfo->pr_zoneid));
1735*7c478bd9Sstevel@tonic-gate 			} else {
1736*7c478bd9Sstevel@tonic-gate 				(void) printf("%*s", width, zonename);
1737*7c478bd9Sstevel@tonic-gate 			}
1738*7c478bd9Sstevel@tonic-gate 		}
1739*7c478bd9Sstevel@tonic-gate 		break;
1740*7c478bd9Sstevel@tonic-gate 	case F_CTID:
1741*7c478bd9Sstevel@tonic-gate 		if (psinfo->pr_contract == -1)
1742*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s", width, "-");
1743*7c478bd9Sstevel@tonic-gate 		else
1744*7c478bd9Sstevel@tonic-gate 			(void) printf("%*ld", width, (long)psinfo->pr_contract);
1745*7c478bd9Sstevel@tonic-gate 		break;
1746*7c478bd9Sstevel@tonic-gate 	}
1747*7c478bd9Sstevel@tonic-gate }
1748*7c478bd9Sstevel@tonic-gate 
1749*7c478bd9Sstevel@tonic-gate static void
1750*7c478bd9Sstevel@tonic-gate print_zombie_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
1751*7c478bd9Sstevel@tonic-gate {
1752*7c478bd9Sstevel@tonic-gate 	int wcnt;
1753*7c478bd9Sstevel@tonic-gate 	int width = f->width;
1754*7c478bd9Sstevel@tonic-gate 
1755*7c478bd9Sstevel@tonic-gate 	switch (f->fname) {
1756*7c478bd9Sstevel@tonic-gate 	case F_FNAME:
1757*7c478bd9Sstevel@tonic-gate 	case F_COMM:
1758*7c478bd9Sstevel@tonic-gate 	case F_ARGS:
1759*7c478bd9Sstevel@tonic-gate 		/*
1760*7c478bd9Sstevel@tonic-gate 		 * Print full width unless this is the last output format.
1761*7c478bd9Sstevel@tonic-gate 		 */
1762*7c478bd9Sstevel@tonic-gate 		wcnt = min(width, sizeof ("<defunct>"));
1763*7c478bd9Sstevel@tonic-gate 		if (f->next != NULL)
1764*7c478bd9Sstevel@tonic-gate 			(void) printf("%-*.*s", width, wcnt, "<defunct>");
1765*7c478bd9Sstevel@tonic-gate 		else
1766*7c478bd9Sstevel@tonic-gate 			(void) printf("%-.*s", wcnt, "<defunct>");
1767*7c478bd9Sstevel@tonic-gate 		break;
1768*7c478bd9Sstevel@tonic-gate 
1769*7c478bd9Sstevel@tonic-gate 	case F_PSR:
1770*7c478bd9Sstevel@tonic-gate 	case F_PCPU:
1771*7c478bd9Sstevel@tonic-gate 	case F_PMEM:
1772*7c478bd9Sstevel@tonic-gate 	case F_NICE:
1773*7c478bd9Sstevel@tonic-gate 	case F_CLASS:
1774*7c478bd9Sstevel@tonic-gate 	case F_STIME:
1775*7c478bd9Sstevel@tonic-gate 	case F_ETIME:
1776*7c478bd9Sstevel@tonic-gate 	case F_WCHAN:
1777*7c478bd9Sstevel@tonic-gate 	case F_PSET:
1778*7c478bd9Sstevel@tonic-gate 		(void) printf("%*s", width, "-");
1779*7c478bd9Sstevel@tonic-gate 		break;
1780*7c478bd9Sstevel@tonic-gate 
1781*7c478bd9Sstevel@tonic-gate 	case F_OPRI:
1782*7c478bd9Sstevel@tonic-gate 	case F_PRI:
1783*7c478bd9Sstevel@tonic-gate 	case F_OSZ:
1784*7c478bd9Sstevel@tonic-gate 	case F_VSZ:
1785*7c478bd9Sstevel@tonic-gate 	case F_RSS:
1786*7c478bd9Sstevel@tonic-gate 		(void) printf("%*d", width, 0);
1787*7c478bd9Sstevel@tonic-gate 		break;
1788*7c478bd9Sstevel@tonic-gate 
1789*7c478bd9Sstevel@tonic-gate 	default:
1790*7c478bd9Sstevel@tonic-gate 		print_field(psinfo, f, ttyp);
1791*7c478bd9Sstevel@tonic-gate 		break;
1792*7c478bd9Sstevel@tonic-gate 	}
1793*7c478bd9Sstevel@tonic-gate }
1794*7c478bd9Sstevel@tonic-gate 
1795*7c478bd9Sstevel@tonic-gate static void
1796*7c478bd9Sstevel@tonic-gate pr_fields(psinfo_t *psinfo, const char *ttyp,
1797*7c478bd9Sstevel@tonic-gate 	void (*print_fld)(psinfo_t *, struct field *, const char *))
1798*7c478bd9Sstevel@tonic-gate {
1799*7c478bd9Sstevel@tonic-gate 	struct field *f;
1800*7c478bd9Sstevel@tonic-gate 
1801*7c478bd9Sstevel@tonic-gate 	for (f = fields; f != NULL; f = f->next) {
1802*7c478bd9Sstevel@tonic-gate 		print_fld(psinfo, f, ttyp);
1803*7c478bd9Sstevel@tonic-gate 		if (f->next != NULL)
1804*7c478bd9Sstevel@tonic-gate 			(void) printf(" ");
1805*7c478bd9Sstevel@tonic-gate 	}
1806*7c478bd9Sstevel@tonic-gate 	(void) printf("\n");
1807*7c478bd9Sstevel@tonic-gate }
1808*7c478bd9Sstevel@tonic-gate 
1809*7c478bd9Sstevel@tonic-gate /*
1810*7c478bd9Sstevel@tonic-gate  * Returns 1 if arg is found in array arr, of length num; 0 otherwise.
1811*7c478bd9Sstevel@tonic-gate  */
1812*7c478bd9Sstevel@tonic-gate static int
1813*7c478bd9Sstevel@tonic-gate search(pid_t *arr, int number, pid_t arg)
1814*7c478bd9Sstevel@tonic-gate {
1815*7c478bd9Sstevel@tonic-gate 	int i;
1816*7c478bd9Sstevel@tonic-gate 
1817*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < number; i++)
1818*7c478bd9Sstevel@tonic-gate 		if (arg == arr[i])
1819*7c478bd9Sstevel@tonic-gate 			return (1);
1820*7c478bd9Sstevel@tonic-gate 	return (0);
1821*7c478bd9Sstevel@tonic-gate }
1822*7c478bd9Sstevel@tonic-gate 
1823*7c478bd9Sstevel@tonic-gate /*
1824*7c478bd9Sstevel@tonic-gate  * Add an entry (user, group) to the specified table.
1825*7c478bd9Sstevel@tonic-gate  */
1826*7c478bd9Sstevel@tonic-gate static void
1827*7c478bd9Sstevel@tonic-gate add_ugentry(struct ughead *tbl, char *name)
1828*7c478bd9Sstevel@tonic-gate {
1829*7c478bd9Sstevel@tonic-gate 	struct ugdata *entp;
1830*7c478bd9Sstevel@tonic-gate 
1831*7c478bd9Sstevel@tonic-gate 	if (tbl->size == tbl->nent) {	/* reallocate the table entries */
1832*7c478bd9Sstevel@tonic-gate 		if ((tbl->size *= 2) == 0)
1833*7c478bd9Sstevel@tonic-gate 			tbl->size = 32;		/* first time */
1834*7c478bd9Sstevel@tonic-gate 		tbl->ent = Realloc(tbl->ent, tbl->size*sizeof (struct ugdata));
1835*7c478bd9Sstevel@tonic-gate 	}
1836*7c478bd9Sstevel@tonic-gate 	entp = &tbl->ent[tbl->nent++];
1837*7c478bd9Sstevel@tonic-gate 	entp->id = 0;
1838*7c478bd9Sstevel@tonic-gate 	(void) strncpy(entp->name, name, MAXUGNAME);
1839*7c478bd9Sstevel@tonic-gate 	entp->name[MAXUGNAME] = '\0';
1840*7c478bd9Sstevel@tonic-gate }
1841*7c478bd9Sstevel@tonic-gate 
1842*7c478bd9Sstevel@tonic-gate static int
1843*7c478bd9Sstevel@tonic-gate uconv(struct ughead *uhead)
1844*7c478bd9Sstevel@tonic-gate {
1845*7c478bd9Sstevel@tonic-gate 	struct ugdata *utbl = uhead->ent;
1846*7c478bd9Sstevel@tonic-gate 	int n = uhead->nent;
1847*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
1848*7c478bd9Sstevel@tonic-gate 	int i;
1849*7c478bd9Sstevel@tonic-gate 	int fnd = 0;
1850*7c478bd9Sstevel@tonic-gate 	uid_t uid;
1851*7c478bd9Sstevel@tonic-gate 
1852*7c478bd9Sstevel@tonic-gate 	/*
1853*7c478bd9Sstevel@tonic-gate 	 * Ask the name service for names.
1854*7c478bd9Sstevel@tonic-gate 	 */
1855*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1856*7c478bd9Sstevel@tonic-gate 		/*
1857*7c478bd9Sstevel@tonic-gate 		 * If name is numeric, ask for numeric id
1858*7c478bd9Sstevel@tonic-gate 		 */
1859*7c478bd9Sstevel@tonic-gate 		if (str2id(utbl[i].name, &uid, 0, UID_MAX) == 0)
1860*7c478bd9Sstevel@tonic-gate 			pwd = getpwuid(uid);
1861*7c478bd9Sstevel@tonic-gate 		else
1862*7c478bd9Sstevel@tonic-gate 			pwd = getpwnam(utbl[i].name);
1863*7c478bd9Sstevel@tonic-gate 
1864*7c478bd9Sstevel@tonic-gate 		/*
1865*7c478bd9Sstevel@tonic-gate 		 * If found, enter found index into tbl array.
1866*7c478bd9Sstevel@tonic-gate 		 */
1867*7c478bd9Sstevel@tonic-gate 		if (pwd == NULL) {
1868*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1869*7c478bd9Sstevel@tonic-gate 			    gettext("ps: unknown user %s\n"), utbl[i].name);
1870*7c478bd9Sstevel@tonic-gate 			continue;
1871*7c478bd9Sstevel@tonic-gate 		}
1872*7c478bd9Sstevel@tonic-gate 
1873*7c478bd9Sstevel@tonic-gate 		utbl[fnd].id = pwd->pw_uid;
1874*7c478bd9Sstevel@tonic-gate 		(void) strncpy(utbl[fnd].name, pwd->pw_name, MAXUGNAME);
1875*7c478bd9Sstevel@tonic-gate 		fnd++;
1876*7c478bd9Sstevel@tonic-gate 	}
1877*7c478bd9Sstevel@tonic-gate 
1878*7c478bd9Sstevel@tonic-gate 	uhead->nent = fnd;	/* in case it changed */
1879*7c478bd9Sstevel@tonic-gate 	return (n - fnd);
1880*7c478bd9Sstevel@tonic-gate }
1881*7c478bd9Sstevel@tonic-gate 
1882*7c478bd9Sstevel@tonic-gate static int
1883*7c478bd9Sstevel@tonic-gate gconv(struct ughead *ghead)
1884*7c478bd9Sstevel@tonic-gate {
1885*7c478bd9Sstevel@tonic-gate 	struct ugdata *gtbl = ghead->ent;
1886*7c478bd9Sstevel@tonic-gate 	int n = ghead->nent;
1887*7c478bd9Sstevel@tonic-gate 	struct group *grp;
1888*7c478bd9Sstevel@tonic-gate 	gid_t gid;
1889*7c478bd9Sstevel@tonic-gate 	int i;
1890*7c478bd9Sstevel@tonic-gate 	int fnd = 0;
1891*7c478bd9Sstevel@tonic-gate 
1892*7c478bd9Sstevel@tonic-gate 	/*
1893*7c478bd9Sstevel@tonic-gate 	 * Ask the name service for names.
1894*7c478bd9Sstevel@tonic-gate 	 */
1895*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1896*7c478bd9Sstevel@tonic-gate 		/*
1897*7c478bd9Sstevel@tonic-gate 		 * If name is numeric, ask for numeric id
1898*7c478bd9Sstevel@tonic-gate 		 */
1899*7c478bd9Sstevel@tonic-gate 		if (str2id(gtbl[i].name, &gid, 0, UID_MAX) == 0)
1900*7c478bd9Sstevel@tonic-gate 			grp = getgrgid(gid);
1901*7c478bd9Sstevel@tonic-gate 		else
1902*7c478bd9Sstevel@tonic-gate 			grp = getgrnam(gtbl[i].name);
1903*7c478bd9Sstevel@tonic-gate 		/*
1904*7c478bd9Sstevel@tonic-gate 		 * If found, enter found index into tbl array.
1905*7c478bd9Sstevel@tonic-gate 		 */
1906*7c478bd9Sstevel@tonic-gate 		if (grp == NULL) {
1907*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1908*7c478bd9Sstevel@tonic-gate 			    gettext("ps: unknown group %s\n"), gtbl[i].name);
1909*7c478bd9Sstevel@tonic-gate 			continue;
1910*7c478bd9Sstevel@tonic-gate 		}
1911*7c478bd9Sstevel@tonic-gate 
1912*7c478bd9Sstevel@tonic-gate 		gtbl[fnd].id = grp->gr_gid;
1913*7c478bd9Sstevel@tonic-gate 		(void) strncpy(gtbl[fnd].name, grp->gr_name, MAXUGNAME);
1914*7c478bd9Sstevel@tonic-gate 		fnd++;
1915*7c478bd9Sstevel@tonic-gate 	}
1916*7c478bd9Sstevel@tonic-gate 
1917*7c478bd9Sstevel@tonic-gate 	ghead->nent = fnd;	/* in case it changed */
1918*7c478bd9Sstevel@tonic-gate 	return (n - fnd);
1919*7c478bd9Sstevel@tonic-gate }
1920*7c478bd9Sstevel@tonic-gate 
1921*7c478bd9Sstevel@tonic-gate /*
1922*7c478bd9Sstevel@tonic-gate  * Return 1 if puid is in table, otherwise 0.
1923*7c478bd9Sstevel@tonic-gate  */
1924*7c478bd9Sstevel@tonic-gate static int
1925*7c478bd9Sstevel@tonic-gate ugfind(id_t id, struct ughead *ughead)
1926*7c478bd9Sstevel@tonic-gate {
1927*7c478bd9Sstevel@tonic-gate 	struct ugdata *utbl = ughead->ent;
1928*7c478bd9Sstevel@tonic-gate 	int n = ughead->nent;
1929*7c478bd9Sstevel@tonic-gate 	int i;
1930*7c478bd9Sstevel@tonic-gate 
1931*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++)
1932*7c478bd9Sstevel@tonic-gate 		if (utbl[i].id == id)
1933*7c478bd9Sstevel@tonic-gate 			return (1);
1934*7c478bd9Sstevel@tonic-gate 	return (0);
1935*7c478bd9Sstevel@tonic-gate }
1936*7c478bd9Sstevel@tonic-gate 
1937*7c478bd9Sstevel@tonic-gate /*
1938*7c478bd9Sstevel@tonic-gate  * Print starting time of process unless process started more than 24 hours
1939*7c478bd9Sstevel@tonic-gate  * ago, in which case the date is printed.  The date is printed in the form
1940*7c478bd9Sstevel@tonic-gate  * "MMM dd" if old format, else the blank is replaced with an '_' so
1941*7c478bd9Sstevel@tonic-gate  * it appears as a single word (for parseability).
1942*7c478bd9Sstevel@tonic-gate  */
1943*7c478bd9Sstevel@tonic-gate static void
1944*7c478bd9Sstevel@tonic-gate prtime(timestruc_t st, int width, int old)
1945*7c478bd9Sstevel@tonic-gate {
1946*7c478bd9Sstevel@tonic-gate 	char sttim[26];
1947*7c478bd9Sstevel@tonic-gate 	time_t starttime;
1948*7c478bd9Sstevel@tonic-gate 
1949*7c478bd9Sstevel@tonic-gate 	starttime = st.tv_sec;
1950*7c478bd9Sstevel@tonic-gate 	if (st.tv_nsec > 500000000)
1951*7c478bd9Sstevel@tonic-gate 		starttime++;
1952*7c478bd9Sstevel@tonic-gate 	if ((now.tv_sec - starttime) >= 24*60*60) {
1953*7c478bd9Sstevel@tonic-gate 		(void) strftime(sttim, sizeof (sttim), old? \
1954*7c478bd9Sstevel@tonic-gate 		    "%b %d" : "%b_%d", localtime(&starttime));
1955*7c478bd9Sstevel@tonic-gate 		sttim[7] = '\0';
1956*7c478bd9Sstevel@tonic-gate 	} else {
1957*7c478bd9Sstevel@tonic-gate 		(void) strftime(sttim, sizeof (sttim), \
1958*7c478bd9Sstevel@tonic-gate 		    "%H:%M:%S", localtime(&starttime));
1959*7c478bd9Sstevel@tonic-gate 		sttim[8] = '\0';
1960*7c478bd9Sstevel@tonic-gate 	}
1961*7c478bd9Sstevel@tonic-gate 	(void) printf("%*.*s", width, width, sttim);
1962*7c478bd9Sstevel@tonic-gate }
1963*7c478bd9Sstevel@tonic-gate 
1964*7c478bd9Sstevel@tonic-gate static void
1965*7c478bd9Sstevel@tonic-gate przom(psinfo_t *psinfo)
1966*7c478bd9Sstevel@tonic-gate {
1967*7c478bd9Sstevel@tonic-gate 	long	tm;
1968*7c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
1969*7c478bd9Sstevel@tonic-gate 	char zonename[ZONENAME_MAX];
1970*7c478bd9Sstevel@tonic-gate 
1971*7c478bd9Sstevel@tonic-gate 	/*
1972*7c478bd9Sstevel@tonic-gate 	 * All fields before 'PID' are printed with a trailing space as a
1973*7c478bd9Sstevel@tonic-gate 	 * spearator, rather than keeping track of which column is first.  All
1974*7c478bd9Sstevel@tonic-gate 	 * other fields are printed with a leading space.
1975*7c478bd9Sstevel@tonic-gate 	 */
1976*7c478bd9Sstevel@tonic-gate 	if (lflg) {	/* F S */
1977*7c478bd9Sstevel@tonic-gate 		if (!yflg)
1978*7c478bd9Sstevel@tonic-gate 			(void) printf("%2x ", psinfo->pr_flag & 0377); /* F */
1979*7c478bd9Sstevel@tonic-gate 		(void) printf("%c ", psinfo->pr_lwp.pr_sname);	/* S */
1980*7c478bd9Sstevel@tonic-gate 	}
1981*7c478bd9Sstevel@tonic-gate 	if (Zflg) {
1982*7c478bd9Sstevel@tonic-gate 		if (getzonenamebyid(psinfo->pr_zoneid, zonename,
1983*7c478bd9Sstevel@tonic-gate 		    sizeof (zonename)) < 0) {
1984*7c478bd9Sstevel@tonic-gate 			(void) printf("%7.7d ", ((int)psinfo->pr_zoneid));
1985*7c478bd9Sstevel@tonic-gate 		} else {
1986*7c478bd9Sstevel@tonic-gate 			(void) printf("%8.8s ", zonename);
1987*7c478bd9Sstevel@tonic-gate 		}
1988*7c478bd9Sstevel@tonic-gate 	}
1989*7c478bd9Sstevel@tonic-gate 	if (fflg) {
1990*7c478bd9Sstevel@tonic-gate 		if ((pwd = getpwuid(psinfo->pr_euid)) != NULL)
1991*7c478bd9Sstevel@tonic-gate 			(void) printf("%8.8s ", pwd->pw_name);
1992*7c478bd9Sstevel@tonic-gate 		else
1993*7c478bd9Sstevel@tonic-gate 			(void) printf("%7.7d ", (int)psinfo->pr_euid);
1994*7c478bd9Sstevel@tonic-gate 	} else if (lflg)
1995*7c478bd9Sstevel@tonic-gate 		(void) printf("%6d ", (int)psinfo->pr_euid);
1996*7c478bd9Sstevel@tonic-gate 
1997*7c478bd9Sstevel@tonic-gate 	(void) printf("%*d", pidwidth, (int)psinfo->pr_pid);	/* PID */
1998*7c478bd9Sstevel@tonic-gate 	if (lflg || fflg)
1999*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*d", pidwidth,
2000*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_ppid);			/* PPID */
2001*7c478bd9Sstevel@tonic-gate 
2002*7c478bd9Sstevel@tonic-gate 	if (jflg) {
2003*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*d", pidwidth,
2004*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_pgid);			/* PGID */
2005*7c478bd9Sstevel@tonic-gate 		(void) printf(" %*d", pidwidth,
2006*7c478bd9Sstevel@tonic-gate 		    (int)psinfo->pr_sid);			/* SID  */
2007*7c478bd9Sstevel@tonic-gate 	}
2008*7c478bd9Sstevel@tonic-gate 
2009*7c478bd9Sstevel@tonic-gate 	if (Lflg)
2010*7c478bd9Sstevel@tonic-gate 		(void) printf(" %5d", 0);			/* LWP */
2011*7c478bd9Sstevel@tonic-gate 	if (Pflg)
2012*7c478bd9Sstevel@tonic-gate 		(void) printf("   -");				/* PSR */
2013*7c478bd9Sstevel@tonic-gate 	if (Lflg && fflg)
2014*7c478bd9Sstevel@tonic-gate 		(void) printf(" %5d", 0);			/* NLWP */
2015*7c478bd9Sstevel@tonic-gate 
2016*7c478bd9Sstevel@tonic-gate 	if (cflg) {
2017*7c478bd9Sstevel@tonic-gate 		(void) printf(" %4s", "-");	/* zombies have no class */
2018*7c478bd9Sstevel@tonic-gate 		(void) printf(" %3d", psinfo->pr_lwp.pr_pri);	/* PRI	*/
2019*7c478bd9Sstevel@tonic-gate 	} else if (lflg || fflg) {
2020*7c478bd9Sstevel@tonic-gate 		(void) printf(" %3d", psinfo->pr_lwp.pr_cpu & 0377); /* C   */
2021*7c478bd9Sstevel@tonic-gate 		if (lflg)
2022*7c478bd9Sstevel@tonic-gate 			(void) printf(" %3d %2s",
2023*7c478bd9Sstevel@tonic-gate 			    psinfo->pr_lwp.pr_oldpri, "-");	/* PRI NI */
2024*7c478bd9Sstevel@tonic-gate 	}
2025*7c478bd9Sstevel@tonic-gate 	if (lflg) {
2026*7c478bd9Sstevel@tonic-gate 		if (yflg)				/* RSS SZ WCHAN */
2027*7c478bd9Sstevel@tonic-gate 			(void) printf(" %5d %6d %8s", 0, 0, "-");
2028*7c478bd9Sstevel@tonic-gate 		else					/* ADDR SZ WCHAN */
2029*7c478bd9Sstevel@tonic-gate 			(void) printf(" %8s %6d %8s", "-", 0, "-");
2030*7c478bd9Sstevel@tonic-gate 	}
2031*7c478bd9Sstevel@tonic-gate 	if (fflg)
2032*7c478bd9Sstevel@tonic-gate 		(void) printf(" %8.8s", "-");			/* STIME */
2033*7c478bd9Sstevel@tonic-gate 	(void) printf(" %-8.14s", "?");				/* TTY */
2034*7c478bd9Sstevel@tonic-gate 
2035*7c478bd9Sstevel@tonic-gate 	tm = psinfo->pr_time.tv_sec;
2036*7c478bd9Sstevel@tonic-gate 	if (psinfo->pr_time.tv_nsec > 500000000)
2037*7c478bd9Sstevel@tonic-gate 		tm++;
2038*7c478bd9Sstevel@tonic-gate 	(void) printf(" %4ld:%.2ld", tm / 60, tm % 60);	/* TIME */
2039*7c478bd9Sstevel@tonic-gate 	(void) printf(" <defunct>\n");
2040*7c478bd9Sstevel@tonic-gate }
2041*7c478bd9Sstevel@tonic-gate 
2042*7c478bd9Sstevel@tonic-gate /*
2043*7c478bd9Sstevel@tonic-gate  * Function to compute the number of printable bytes in a multibyte
2044*7c478bd9Sstevel@tonic-gate  * command string ("internationalization").
2045*7c478bd9Sstevel@tonic-gate  */
2046*7c478bd9Sstevel@tonic-gate static int
2047*7c478bd9Sstevel@tonic-gate namencnt(char *cmd, int csisize, int scrsize)
2048*7c478bd9Sstevel@tonic-gate {
2049*7c478bd9Sstevel@tonic-gate 	int csiwcnt = 0, scrwcnt = 0;
2050*7c478bd9Sstevel@tonic-gate 	int ncsisz, nscrsz;
2051*7c478bd9Sstevel@tonic-gate 	wchar_t  wchar;
2052*7c478bd9Sstevel@tonic-gate 	int	 len;
2053*7c478bd9Sstevel@tonic-gate 
2054*7c478bd9Sstevel@tonic-gate 	while (*cmd != '\0') {
2055*7c478bd9Sstevel@tonic-gate 		if ((len = csisize - csiwcnt) > (int)MB_CUR_MAX)
2056*7c478bd9Sstevel@tonic-gate 			len = MB_CUR_MAX;
2057*7c478bd9Sstevel@tonic-gate 		if ((ncsisz = mbtowc(&wchar, cmd, len)) < 0)
2058*7c478bd9Sstevel@tonic-gate 			return (8); /* default to use for illegal chars */
2059*7c478bd9Sstevel@tonic-gate 		if ((nscrsz = wcwidth(wchar)) <= 0)
2060*7c478bd9Sstevel@tonic-gate 			return (8);
2061*7c478bd9Sstevel@tonic-gate 		if (csiwcnt + ncsisz > csisize || scrwcnt + nscrsz > scrsize)
2062*7c478bd9Sstevel@tonic-gate 			break;
2063*7c478bd9Sstevel@tonic-gate 		csiwcnt += ncsisz;
2064*7c478bd9Sstevel@tonic-gate 		scrwcnt += nscrsz;
2065*7c478bd9Sstevel@tonic-gate 		cmd += ncsisz;
2066*7c478bd9Sstevel@tonic-gate 	}
2067*7c478bd9Sstevel@tonic-gate 	return (csiwcnt);
2068*7c478bd9Sstevel@tonic-gate }
2069*7c478bd9Sstevel@tonic-gate 
2070*7c478bd9Sstevel@tonic-gate static char *
2071*7c478bd9Sstevel@tonic-gate err_string(int err)
2072*7c478bd9Sstevel@tonic-gate {
2073*7c478bd9Sstevel@tonic-gate 	static char buf[32];
2074*7c478bd9Sstevel@tonic-gate 	char *str = strerror(err);
2075*7c478bd9Sstevel@tonic-gate 
2076*7c478bd9Sstevel@tonic-gate 	if (str == NULL)
2077*7c478bd9Sstevel@tonic-gate 		(void) snprintf(str = buf, sizeof (buf), "Errno #%d", err);
2078*7c478bd9Sstevel@tonic-gate 
2079*7c478bd9Sstevel@tonic-gate 	return (str);
2080*7c478bd9Sstevel@tonic-gate }
2081*7c478bd9Sstevel@tonic-gate 
2082*7c478bd9Sstevel@tonic-gate /* If allocation fails, die */
2083*7c478bd9Sstevel@tonic-gate static void *
2084*7c478bd9Sstevel@tonic-gate Realloc(void *ptr, size_t size)
2085*7c478bd9Sstevel@tonic-gate {
2086*7c478bd9Sstevel@tonic-gate 	ptr = realloc(ptr, size);
2087*7c478bd9Sstevel@tonic-gate 	if (ptr == NULL) {
2088*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("ps: no memory\n"));
2089*7c478bd9Sstevel@tonic-gate 		exit(1);
2090*7c478bd9Sstevel@tonic-gate 	}
2091*7c478bd9Sstevel@tonic-gate 	return (ptr);
2092*7c478bd9Sstevel@tonic-gate }
2093*7c478bd9Sstevel@tonic-gate 
2094*7c478bd9Sstevel@tonic-gate static time_t
2095*7c478bd9Sstevel@tonic-gate delta_secs(const timestruc_t *start)
2096*7c478bd9Sstevel@tonic-gate {
2097*7c478bd9Sstevel@tonic-gate 	time_t seconds = now.tv_sec - start->tv_sec;
2098*7c478bd9Sstevel@tonic-gate 	long nanosecs = now.tv_usec * 1000 - start->tv_nsec;
2099*7c478bd9Sstevel@tonic-gate 
2100*7c478bd9Sstevel@tonic-gate 	if (nanosecs >= (NANOSEC / 2))
2101*7c478bd9Sstevel@tonic-gate 		seconds++;
2102*7c478bd9Sstevel@tonic-gate 	else if (nanosecs < -(NANOSEC / 2))
2103*7c478bd9Sstevel@tonic-gate 		seconds--;
2104*7c478bd9Sstevel@tonic-gate 
2105*7c478bd9Sstevel@tonic-gate 	return (seconds);
2106*7c478bd9Sstevel@tonic-gate }
2107*7c478bd9Sstevel@tonic-gate 
2108*7c478bd9Sstevel@tonic-gate /*
2109*7c478bd9Sstevel@tonic-gate  * Returns the following:
2110*7c478bd9Sstevel@tonic-gate  *
2111*7c478bd9Sstevel@tonic-gate  * 	0	No error
2112*7c478bd9Sstevel@tonic-gate  * 	EINVAL	Invalid number
2113*7c478bd9Sstevel@tonic-gate  * 	ERANGE	Value exceeds (min, max) range
2114*7c478bd9Sstevel@tonic-gate  */
2115*7c478bd9Sstevel@tonic-gate static int
2116*7c478bd9Sstevel@tonic-gate str2id(const char *p, pid_t *val, long min, long max)
2117*7c478bd9Sstevel@tonic-gate {
2118*7c478bd9Sstevel@tonic-gate 	char *q;
2119*7c478bd9Sstevel@tonic-gate 	long number;
2120*7c478bd9Sstevel@tonic-gate 	int error;
2121*7c478bd9Sstevel@tonic-gate 
2122*7c478bd9Sstevel@tonic-gate 	errno = 0;
2123*7c478bd9Sstevel@tonic-gate 	number = strtol(p, &q, 10);
2124*7c478bd9Sstevel@tonic-gate 
2125*7c478bd9Sstevel@tonic-gate 	if (errno != 0 || q == p || *q != '\0') {
2126*7c478bd9Sstevel@tonic-gate 		if ((error = errno) == 0) {
2127*7c478bd9Sstevel@tonic-gate 			/*
2128*7c478bd9Sstevel@tonic-gate 			 * strtol() can fail without setting errno, or it can
2129*7c478bd9Sstevel@tonic-gate 			 * set it to EINVAL or ERANGE.  In the case errno is
2130*7c478bd9Sstevel@tonic-gate 			 * still zero, return EINVAL.
2131*7c478bd9Sstevel@tonic-gate 			 */
2132*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
2133*7c478bd9Sstevel@tonic-gate 		}
2134*7c478bd9Sstevel@tonic-gate 	} else if (number < min || number > max) {
2135*7c478bd9Sstevel@tonic-gate 		error = ERANGE;
2136*7c478bd9Sstevel@tonic-gate 	} else {
2137*7c478bd9Sstevel@tonic-gate 		error = 0;
2138*7c478bd9Sstevel@tonic-gate 	}
2139*7c478bd9Sstevel@tonic-gate 
2140*7c478bd9Sstevel@tonic-gate 	*val = number;
2141*7c478bd9Sstevel@tonic-gate 
2142*7c478bd9Sstevel@tonic-gate 	return (error);
2143*7c478bd9Sstevel@tonic-gate }
2144*7c478bd9Sstevel@tonic-gate 
2145*7c478bd9Sstevel@tonic-gate static int
2146*7c478bd9Sstevel@tonic-gate pidcmp(const void *p1, const void *p2)
2147*7c478bd9Sstevel@tonic-gate {
2148*7c478bd9Sstevel@tonic-gate 	pid_t i = *((pid_t *)p1);
2149*7c478bd9Sstevel@tonic-gate 	pid_t j = *((pid_t *)p2);
2150*7c478bd9Sstevel@tonic-gate 
2151*7c478bd9Sstevel@tonic-gate 	return (i - j);
2152*7c478bd9Sstevel@tonic-gate }
2153