xref: /onnv-gate/usr/src/cmd/prstat/prstat.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/resource.h>
31*0Sstevel@tonic-gate #include <sys/loadavg.h>
32*0Sstevel@tonic-gate #include <sys/time.h>
33*0Sstevel@tonic-gate #include <sys/pset.h>
34*0Sstevel@tonic-gate #include <zone.h>
35*0Sstevel@tonic-gate #include <libzonecfg.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <stdio.h>
38*0Sstevel@tonic-gate #include <stdlib.h>
39*0Sstevel@tonic-gate #include <unistd.h>
40*0Sstevel@tonic-gate #include <dirent.h>
41*0Sstevel@tonic-gate #include <string.h>
42*0Sstevel@tonic-gate #include <errno.h>
43*0Sstevel@tonic-gate #include <poll.h>
44*0Sstevel@tonic-gate #include <ctype.h>
45*0Sstevel@tonic-gate #include <fcntl.h>
46*0Sstevel@tonic-gate #include <limits.h>
47*0Sstevel@tonic-gate #include <signal.h>
48*0Sstevel@tonic-gate #include <time.h>
49*0Sstevel@tonic-gate #include <project.h>
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #include <libintl.h>
52*0Sstevel@tonic-gate #include <locale.h>
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate #include "prstat.h"
55*0Sstevel@tonic-gate #include "prutil.h"
56*0Sstevel@tonic-gate #include "prtable.h"
57*0Sstevel@tonic-gate #include "prsort.h"
58*0Sstevel@tonic-gate #include "prfile.h"
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate /*
61*0Sstevel@tonic-gate  * x86 <sys/regs.h> ERR conflicts with <curses.h> ERR.  For the purposes
62*0Sstevel@tonic-gate  * of this file, we care about the curses.h ERR so include that last.
63*0Sstevel@tonic-gate  */
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate #if	defined(ERR)
66*0Sstevel@tonic-gate #undef	ERR
67*0Sstevel@tonic-gate #endif
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate #ifndef	TEXT_DOMAIN			/* should be defined by cc -D */
70*0Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* use this only if it wasn't */
71*0Sstevel@tonic-gate #endif
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate #include <curses.h>
74*0Sstevel@tonic-gate #include <term.h>
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate #define	PSINFO_HEADER_PROC \
77*0Sstevel@tonic-gate "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP       "
78*0Sstevel@tonic-gate #define	PSINFO_HEADER_LWP \
79*0Sstevel@tonic-gate "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/LWPID      "
80*0Sstevel@tonic-gate #define	USAGE_HEADER_PROC \
81*0Sstevel@tonic-gate "   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP  "
82*0Sstevel@tonic-gate #define	USAGE_HEADER_LWP \
83*0Sstevel@tonic-gate "   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID "
84*0Sstevel@tonic-gate #define	USER_HEADER_PROC \
85*0Sstevel@tonic-gate " NPROC USERNAME  SIZE   RSS MEMORY      TIME  CPU                             "
86*0Sstevel@tonic-gate #define	USER_HEADER_LWP \
87*0Sstevel@tonic-gate "  NLWP USERNAME  SIZE   RSS MEMORY      TIME  CPU                             "
88*0Sstevel@tonic-gate #define	TASK_HEADER_PROC \
89*0Sstevel@tonic-gate "TASKID    NPROC  SIZE   RSS MEMORY      TIME  CPU PROJECT                     "
90*0Sstevel@tonic-gate #define	TASK_HEADER_LWP \
91*0Sstevel@tonic-gate "TASKID     NLWP  SIZE   RSS MEMORY      TIME  CPU PROJECT                     "
92*0Sstevel@tonic-gate #define	PROJECT_HEADER_PROC \
93*0Sstevel@tonic-gate "PROJID    NPROC  SIZE   RSS MEMORY      TIME  CPU PROJECT                     "
94*0Sstevel@tonic-gate #define	PROJECT_HEADER_LWP \
95*0Sstevel@tonic-gate "PROJID     NLWP  SIZE   RSS MEMORY      TIME  CPU PROJECT                     "
96*0Sstevel@tonic-gate #define	ZONE_HEADER_PROC \
97*0Sstevel@tonic-gate "ZONEID    NPROC  SIZE   RSS MEMORY      TIME  CPU ZONE                        "
98*0Sstevel@tonic-gate #define	ZONE_HEADER_LWP \
99*0Sstevel@tonic-gate "ZONEID     NLWP  SIZE   RSS MEMORY      TIME  CPU ZONE                        "
100*0Sstevel@tonic-gate #define	PSINFO_LINE \
101*0Sstevel@tonic-gate "%6d %-8s %5s %5s %-6s %3s  %3s %9s %3.3s%% %-.16s/%d"
102*0Sstevel@tonic-gate #define	USAGE_LINE \
103*0Sstevel@tonic-gate "%6d %-8s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s %3.3s "\
104*0Sstevel@tonic-gate "%3.3s %-.12s/%d"
105*0Sstevel@tonic-gate #define	USER_LINE \
106*0Sstevel@tonic-gate "%6d %-8s %5.5s %5.5s   %3.3s%% %9s %3.3s%%"
107*0Sstevel@tonic-gate #define	TASK_LINE \
108*0Sstevel@tonic-gate "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
109*0Sstevel@tonic-gate #define	PROJECT_LINE \
110*0Sstevel@tonic-gate "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
111*0Sstevel@tonic-gate #define	ZONE_LINE \
112*0Sstevel@tonic-gate "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate #define	TOTAL_LINE \
115*0Sstevel@tonic-gate "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f"
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate /* global variables */
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate static char	*t_ulon;			/* termcap: start underline */
120*0Sstevel@tonic-gate static char	*t_uloff;			/* termcap: end underline */
121*0Sstevel@tonic-gate static char	*t_up;				/* termcap: cursor 1 line up */
122*0Sstevel@tonic-gate static char	*t_eol;				/* termcap: clear end of line */
123*0Sstevel@tonic-gate static char	*t_smcup;			/* termcap: cursor mvcap on */
124*0Sstevel@tonic-gate static char	*t_rmcup;			/* termcap: cursor mvcap off */
125*0Sstevel@tonic-gate static char	*t_home;			/* termcap: move cursor home */
126*0Sstevel@tonic-gate static char	*movecur = NULL;		/* termcap: move up string */
127*0Sstevel@tonic-gate static char	*empty_string = "\0";		/* termcap: empty string */
128*0Sstevel@tonic-gate static uint_t	print_movecur = FALSE;		/* print movecur or not */
129*0Sstevel@tonic-gate static int	is_curses_on = FALSE;		/* current curses state */
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate static table_t	pid_tbl = {0, 0, NULL};		/* selected processes */
132*0Sstevel@tonic-gate static table_t	cpu_tbl = {0, 0, NULL};		/* selected processors */
133*0Sstevel@tonic-gate static table_t  set_tbl = {0, 0, NULL};		/* selected processor sets */
134*0Sstevel@tonic-gate static table_t	prj_tbl = {0, 0, NULL};		/* selected projects */
135*0Sstevel@tonic-gate static table_t	tsk_tbl = {0, 0, NULL};		/* selected tasks */
136*0Sstevel@tonic-gate static zonetbl_t zone_tbl = {0, 0, NULL};	/* selected zones */
137*0Sstevel@tonic-gate static nametbl_t euid_tbl = {0, 0, NULL}; 	/* selected effective users */
138*0Sstevel@tonic-gate static nametbl_t ruid_tbl = {0, 0, NULL}; 	/* selected real users */
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate static uint_t	total_procs;			/* total number of procs */
141*0Sstevel@tonic-gate static uint_t	total_lwps;			/* total number of lwps */
142*0Sstevel@tonic-gate static float	total_cpu;			/* total cpu usage */
143*0Sstevel@tonic-gate static float	total_mem;			/* total memory usage */
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate static list_t	lwps;				/* list of lwps/processes */
146*0Sstevel@tonic-gate static list_t	users;				/* list of users */
147*0Sstevel@tonic-gate static list_t	tasks;				/* list of tasks */
148*0Sstevel@tonic-gate static list_t	projects;			/* list of projects */
149*0Sstevel@tonic-gate static list_t	zones;				/* list of zones */
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate static volatile uint_t sigwinch = 0;
152*0Sstevel@tonic-gate static volatile uint_t sigtstp = 0;
153*0Sstevel@tonic-gate static volatile uint_t sigterm = 0;
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate /* default settings */
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate static optdesc_t opts = {
158*0Sstevel@tonic-gate 	5,			/* interval between updates, seconds */
159*0Sstevel@tonic-gate 	15,			/* number of lines in top part */
160*0Sstevel@tonic-gate 	5,			/* number of lines in bottom part */
161*0Sstevel@tonic-gate 	-1,			/* number of iterations; infinitely */
162*0Sstevel@tonic-gate 	OPT_PSINFO | OPT_FULLSCREEN | OPT_USEHOME | OPT_TERMCAP,
163*0Sstevel@tonic-gate 	-1			/* sort in decreasing order */
164*0Sstevel@tonic-gate };
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate static void
167*0Sstevel@tonic-gate psetloadavg(long psetid, void *ptr)
168*0Sstevel@tonic-gate {
169*0Sstevel@tonic-gate 	double psetloadavg[3];
170*0Sstevel@tonic-gate 	double *loadavg = ptr;
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	if (pset_getloadavg((psetid_t)psetid, psetloadavg, 3) != -1) {
173*0Sstevel@tonic-gate 		*loadavg++ += psetloadavg[0];
174*0Sstevel@tonic-gate 		*loadavg++ += psetloadavg[1];
175*0Sstevel@tonic-gate 		*loadavg += psetloadavg[2];
176*0Sstevel@tonic-gate 	}
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate /*
180*0Sstevel@tonic-gate  * A routine to display the contents of the list on the screen
181*0Sstevel@tonic-gate  */
182*0Sstevel@tonic-gate static void
183*0Sstevel@tonic-gate list_print(list_t *list)
184*0Sstevel@tonic-gate {
185*0Sstevel@tonic-gate 	lwp_info_t *lwp;
186*0Sstevel@tonic-gate 	id_info_t *id;
187*0Sstevel@tonic-gate 	char usr[4], sys[4], trp[4], tfl[4];
188*0Sstevel@tonic-gate 	char dfl[4], lck[4], slp[4], lat[4];
189*0Sstevel@tonic-gate 	char vcx[4], icx[4], scl[4], sig[4];
190*0Sstevel@tonic-gate 	char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12];
191*0Sstevel@tonic-gate 	char pstate[7], pnice[4], ppri[4];
192*0Sstevel@tonic-gate 	char pname[LOGNAME_MAX+1];
193*0Sstevel@tonic-gate 	char projname[PROJNAME_MAX+1];
194*0Sstevel@tonic-gate 	char zonename[ZONENAME_MAX+1];
195*0Sstevel@tonic-gate 	float cpu, mem;
196*0Sstevel@tonic-gate 	double loadavg[3] = {0, 0, 0};
197*0Sstevel@tonic-gate 	int i, lwpid;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	if (foreach_element(&set_tbl, &loadavg, psetloadavg) == 0) {
200*0Sstevel@tonic-gate 		/*
201*0Sstevel@tonic-gate 		 * If processor sets aren't specified, we display system-wide
202*0Sstevel@tonic-gate 		 * load averages.
203*0Sstevel@tonic-gate 		 */
204*0Sstevel@tonic-gate 		(void) getloadavg(loadavg, 3);
205*0Sstevel@tonic-gate 	}
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
208*0Sstevel@tonic-gate 		(void) putchar('\r');
209*0Sstevel@tonic-gate 	(void) putp(t_ulon);
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	switch (list->l_type) {
212*0Sstevel@tonic-gate 	case LT_PROJECTS:
213*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
214*0Sstevel@tonic-gate 			(void) printf(PROJECT_HEADER_LWP);
215*0Sstevel@tonic-gate 		else
216*0Sstevel@tonic-gate 			(void) printf(PROJECT_HEADER_PROC);
217*0Sstevel@tonic-gate 		break;
218*0Sstevel@tonic-gate 	case LT_TASKS:
219*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
220*0Sstevel@tonic-gate 			(void) printf(TASK_HEADER_LWP);
221*0Sstevel@tonic-gate 		else
222*0Sstevel@tonic-gate 			(void) printf(TASK_HEADER_PROC);
223*0Sstevel@tonic-gate 		break;
224*0Sstevel@tonic-gate 	case LT_ZONES:
225*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
226*0Sstevel@tonic-gate 			(void) printf(ZONE_HEADER_LWP);
227*0Sstevel@tonic-gate 		else
228*0Sstevel@tonic-gate 			(void) printf(ZONE_HEADER_PROC);
229*0Sstevel@tonic-gate 		break;
230*0Sstevel@tonic-gate 	case LT_USERS:
231*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
232*0Sstevel@tonic-gate 			(void) printf(USER_HEADER_LWP);
233*0Sstevel@tonic-gate 		else
234*0Sstevel@tonic-gate 			(void) printf(USER_HEADER_PROC);
235*0Sstevel@tonic-gate 		break;
236*0Sstevel@tonic-gate 	case LT_LWPS:
237*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS) {
238*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_PSINFO)
239*0Sstevel@tonic-gate 				(void) printf(PSINFO_HEADER_LWP);
240*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_MSACCT)
241*0Sstevel@tonic-gate 				(void) printf(USAGE_HEADER_LWP);
242*0Sstevel@tonic-gate 		} else {
243*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_PSINFO)
244*0Sstevel@tonic-gate 				(void) printf(PSINFO_HEADER_PROC);
245*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_MSACCT)
246*0Sstevel@tonic-gate 				(void) printf(USAGE_HEADER_PROC);
247*0Sstevel@tonic-gate 		}
248*0Sstevel@tonic-gate 		break;
249*0Sstevel@tonic-gate 	}
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 	(void) putp(t_uloff);
252*0Sstevel@tonic-gate 	(void) putp(t_eol);
253*0Sstevel@tonic-gate 	(void) putchar('\n');
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	for (i = 0; i < list->l_used; i++) {
256*0Sstevel@tonic-gate 		switch (list->l_type) {
257*0Sstevel@tonic-gate 		case LT_PROJECTS:
258*0Sstevel@tonic-gate 		case LT_TASKS:
259*0Sstevel@tonic-gate 		case LT_USERS:
260*0Sstevel@tonic-gate 		case LT_ZONES:
261*0Sstevel@tonic-gate 			id = list->l_ptrs[i];
262*0Sstevel@tonic-gate 			/*
263*0Sstevel@tonic-gate 			 * CPU usage and memory usage normalization
264*0Sstevel@tonic-gate 			 */
265*0Sstevel@tonic-gate 			if (total_cpu >= 100)
266*0Sstevel@tonic-gate 				cpu = (100 * id->id_pctcpu) / total_cpu;
267*0Sstevel@tonic-gate 			else
268*0Sstevel@tonic-gate 				cpu = id->id_pctcpu;
269*0Sstevel@tonic-gate 			if (total_mem >= 100)
270*0Sstevel@tonic-gate 				mem = (100 * id->id_pctmem) / total_mem;
271*0Sstevel@tonic-gate 			else
272*0Sstevel@tonic-gate 				mem = id->id_pctmem;
273*0Sstevel@tonic-gate 			if (list->l_type == LT_USERS)
274*0Sstevel@tonic-gate 				pwd_getname(id->id_uid, pname, LOGNAME_MAX + 1);
275*0Sstevel@tonic-gate 			else if (list->l_type == LT_ZONES)
276*0Sstevel@tonic-gate 				getzonename(id->id_zoneid, zonename,
277*0Sstevel@tonic-gate 				    ZONENAME_MAX);
278*0Sstevel@tonic-gate 			else
279*0Sstevel@tonic-gate 				getprojname(id->id_projid, projname,
280*0Sstevel@tonic-gate 				    PROJNAME_MAX);
281*0Sstevel@tonic-gate 			Format_size(psize, id->id_size, 6);
282*0Sstevel@tonic-gate 			Format_size(prssize, id->id_rssize, 6);
283*0Sstevel@tonic-gate 			Format_pct(pmem, mem, 4);
284*0Sstevel@tonic-gate 			Format_pct(pcpu, cpu, 4);
285*0Sstevel@tonic-gate 			Format_time(ptime, id->id_time, 10);
286*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_TTY)
287*0Sstevel@tonic-gate 				(void) putchar('\r');
288*0Sstevel@tonic-gate 			if (list->l_type == LT_PROJECTS)
289*0Sstevel@tonic-gate 				(void) printf(PROJECT_LINE, (int)id->id_projid,
290*0Sstevel@tonic-gate 				    id->id_nproc, psize, prssize, pmem, ptime,
291*0Sstevel@tonic-gate 				    pcpu, projname);
292*0Sstevel@tonic-gate 			else if (list->l_type == LT_TASKS)
293*0Sstevel@tonic-gate 				(void) printf(TASK_LINE, (int)id->id_taskid,
294*0Sstevel@tonic-gate 				    id->id_nproc, psize, prssize, pmem, ptime,
295*0Sstevel@tonic-gate 				    pcpu, projname);
296*0Sstevel@tonic-gate 			else if (list->l_type == LT_ZONES)
297*0Sstevel@tonic-gate 				(void) printf(ZONE_LINE, (int)id->id_zoneid,
298*0Sstevel@tonic-gate 				    id->id_nproc, psize, prssize, pmem, ptime,
299*0Sstevel@tonic-gate 				    pcpu, zonename);
300*0Sstevel@tonic-gate 			else
301*0Sstevel@tonic-gate 				(void) printf(USER_LINE, id->id_nproc, pname,
302*0Sstevel@tonic-gate 				    psize, prssize, pmem, ptime, pcpu);
303*0Sstevel@tonic-gate 			(void) putp(t_eol);
304*0Sstevel@tonic-gate 			(void) putchar('\n');
305*0Sstevel@tonic-gate 			break;
306*0Sstevel@tonic-gate 		case LT_LWPS:
307*0Sstevel@tonic-gate 			lwp = list->l_ptrs[i];
308*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_LWPS)
309*0Sstevel@tonic-gate 				lwpid = lwp->li_info.pr_lwp.pr_lwpid;
310*0Sstevel@tonic-gate 			else
311*0Sstevel@tonic-gate 				lwpid = lwp->li_info.pr_nlwp +
312*0Sstevel@tonic-gate 				    lwp->li_info.pr_nzomb;
313*0Sstevel@tonic-gate 			pwd_getname(lwp->li_info.pr_uid, pname,
314*0Sstevel@tonic-gate 			    LOGNAME_MAX + 1);
315*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_PSINFO) {
316*0Sstevel@tonic-gate 				Format_size(psize, lwp->li_info.pr_size, 6);
317*0Sstevel@tonic-gate 				Format_size(prssize, lwp->li_info.pr_rssize, 6);
318*0Sstevel@tonic-gate 				Format_state(pstate,
319*0Sstevel@tonic-gate 				    lwp->li_info.pr_lwp.pr_sname,
320*0Sstevel@tonic-gate 				    lwp->li_info.pr_lwp.pr_onpro, 7);
321*0Sstevel@tonic-gate 				if (strcmp(lwp->li_info.pr_lwp.pr_clname,
322*0Sstevel@tonic-gate 				    "RT") == 0 ||
323*0Sstevel@tonic-gate 				    strcmp(lwp->li_info.pr_lwp.pr_clname,
324*0Sstevel@tonic-gate 				    "SYS") == 0 ||
325*0Sstevel@tonic-gate 				    lwp->li_info.pr_lwp.pr_sname == 'Z')
326*0Sstevel@tonic-gate 					(void) strcpy(pnice, "  -");
327*0Sstevel@tonic-gate 				else
328*0Sstevel@tonic-gate 					Format_num(pnice,
329*0Sstevel@tonic-gate 					    lwp->li_info.pr_lwp.pr_nice - NZERO,
330*0Sstevel@tonic-gate 					    4);
331*0Sstevel@tonic-gate 				Format_num(ppri, lwp->li_info.pr_lwp.pr_pri, 4);
332*0Sstevel@tonic-gate 				Format_pct(pcpu,
333*0Sstevel@tonic-gate 				    FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu), 4);
334*0Sstevel@tonic-gate 				if (opts.o_outpmode & OPT_LWPS)
335*0Sstevel@tonic-gate 					Format_time(ptime,
336*0Sstevel@tonic-gate 					    lwp->li_info.pr_lwp.pr_time.tv_sec,
337*0Sstevel@tonic-gate 					    10);
338*0Sstevel@tonic-gate 				else
339*0Sstevel@tonic-gate 					Format_time(ptime,
340*0Sstevel@tonic-gate 					    lwp->li_info.pr_time.tv_sec, 10);
341*0Sstevel@tonic-gate 				if (opts.o_outpmode & OPT_TTY)
342*0Sstevel@tonic-gate 					(void) putchar('\r');
343*0Sstevel@tonic-gate 				stripfname(lwp->li_info.pr_fname);
344*0Sstevel@tonic-gate 				(void) printf(PSINFO_LINE,
345*0Sstevel@tonic-gate 				    (int)lwp->li_info.pr_pid, pname,
346*0Sstevel@tonic-gate 				    psize, prssize, pstate, ppri, pnice,
347*0Sstevel@tonic-gate 				    ptime, pcpu, lwp->li_info.pr_fname, lwpid);
348*0Sstevel@tonic-gate 				(void) putp(t_eol);
349*0Sstevel@tonic-gate 				(void) putchar('\n');
350*0Sstevel@tonic-gate 			}
351*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_MSACCT) {
352*0Sstevel@tonic-gate 				Format_pct(usr, lwp->li_usr, 4);
353*0Sstevel@tonic-gate 				Format_pct(sys, lwp->li_sys, 4);
354*0Sstevel@tonic-gate 				Format_pct(slp, lwp->li_slp, 4);
355*0Sstevel@tonic-gate 				Format_num(vcx, lwp->li_vcx, 4);
356*0Sstevel@tonic-gate 				Format_num(icx, lwp->li_icx, 4);
357*0Sstevel@tonic-gate 				Format_num(scl, lwp->li_scl, 4);
358*0Sstevel@tonic-gate 				Format_num(sig, lwp->li_sig, 4);
359*0Sstevel@tonic-gate 				Format_pct(trp, lwp->li_trp, 4);
360*0Sstevel@tonic-gate 				Format_pct(tfl, lwp->li_tfl, 4);
361*0Sstevel@tonic-gate 				Format_pct(dfl, lwp->li_dfl, 4);
362*0Sstevel@tonic-gate 				Format_pct(lck, lwp->li_lck, 4);
363*0Sstevel@tonic-gate 				Format_pct(lat, lwp->li_lat, 4);
364*0Sstevel@tonic-gate 				if (opts.o_outpmode & OPT_TTY)
365*0Sstevel@tonic-gate 					(void) putchar('\r');
366*0Sstevel@tonic-gate 				stripfname(lwp->li_info.pr_fname);
367*0Sstevel@tonic-gate 				(void) printf(USAGE_LINE,
368*0Sstevel@tonic-gate 				    (int)lwp->li_info.pr_pid, pname,
369*0Sstevel@tonic-gate 				    usr, sys, trp, tfl, dfl, lck,
370*0Sstevel@tonic-gate 				    slp, lat, vcx, icx, scl, sig,
371*0Sstevel@tonic-gate 				    lwp->li_info.pr_fname, lwpid);
372*0Sstevel@tonic-gate 				(void) putp(t_eol);
373*0Sstevel@tonic-gate 				(void) putchar('\n');
374*0Sstevel@tonic-gate 			}
375*0Sstevel@tonic-gate 			break;
376*0Sstevel@tonic-gate 		}
377*0Sstevel@tonic-gate 	}
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
380*0Sstevel@tonic-gate 		(void) putchar('\r');
381*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP) {
382*0Sstevel@tonic-gate 		switch (list->l_type) {
383*0Sstevel@tonic-gate 		case LT_PROJECTS:
384*0Sstevel@tonic-gate 		case LT_USERS:
385*0Sstevel@tonic-gate 		case LT_TASKS:
386*0Sstevel@tonic-gate 		case LT_ZONES:
387*0Sstevel@tonic-gate 			while (i++ < opts.o_nbottom) {
388*0Sstevel@tonic-gate 				(void) putp(t_eol);
389*0Sstevel@tonic-gate 				(void) putchar('\n');
390*0Sstevel@tonic-gate 			}
391*0Sstevel@tonic-gate 			break;
392*0Sstevel@tonic-gate 		case LT_LWPS:
393*0Sstevel@tonic-gate 			while (i++ < opts.o_ntop) {
394*0Sstevel@tonic-gate 				(void) putp(t_eol);
395*0Sstevel@tonic-gate 				(void) putchar('\n');
396*0Sstevel@tonic-gate 			}
397*0Sstevel@tonic-gate 		}
398*0Sstevel@tonic-gate 	}
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
401*0Sstevel@tonic-gate 		(void) putchar('\r');
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_SPLIT) && list->l_type == LT_LWPS)
404*0Sstevel@tonic-gate 		return;
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 	(void) printf(TOTAL_LINE, total_procs, total_lwps,
407*0Sstevel@tonic-gate 	    loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
408*0Sstevel@tonic-gate 	    loadavg[LOADAVG_15MIN]);
409*0Sstevel@tonic-gate 	(void) putp(t_eol);
410*0Sstevel@tonic-gate 	(void) putchar('\n');
411*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
412*0Sstevel@tonic-gate 		(void) putchar('\r');
413*0Sstevel@tonic-gate 	(void) putp(t_eol);
414*0Sstevel@tonic-gate 	(void) fflush(stdout);
415*0Sstevel@tonic-gate }
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate static lwp_info_t *
418*0Sstevel@tonic-gate list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
419*0Sstevel@tonic-gate {
420*0Sstevel@tonic-gate 	lwp_info_t *lwp;
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate 	if (list->l_head == NULL) {
423*0Sstevel@tonic-gate 		list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
424*0Sstevel@tonic-gate 	} else {
425*0Sstevel@tonic-gate 		lwp = Zalloc(sizeof (lwp_info_t));
426*0Sstevel@tonic-gate 		lwp->li_prev = list->l_tail;
427*0Sstevel@tonic-gate 		((lwp_info_t *)list->l_tail)->li_next = lwp;
428*0Sstevel@tonic-gate 		list->l_tail = lwp;
429*0Sstevel@tonic-gate 	}
430*0Sstevel@tonic-gate 	lwp->li_info.pr_pid = pid;
431*0Sstevel@tonic-gate 	lwp->li_info.pr_lwp.pr_lwpid = lwpid;
432*0Sstevel@tonic-gate 	lwpid_add(lwp, pid, lwpid);
433*0Sstevel@tonic-gate 	list->l_count++;
434*0Sstevel@tonic-gate 	return (lwp);
435*0Sstevel@tonic-gate }
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate static void
438*0Sstevel@tonic-gate list_remove_lwp(list_t *list, lwp_info_t *lwp)
439*0Sstevel@tonic-gate {
440*0Sstevel@tonic-gate 	if (lwp->li_prev)
441*0Sstevel@tonic-gate 		lwp->li_prev->li_next = lwp->li_next;
442*0Sstevel@tonic-gate 	else
443*0Sstevel@tonic-gate 		list->l_head = lwp->li_next;	/* removing the head */
444*0Sstevel@tonic-gate 	if (lwp->li_next)
445*0Sstevel@tonic-gate 		lwp->li_next->li_prev = lwp->li_prev;
446*0Sstevel@tonic-gate 	else
447*0Sstevel@tonic-gate 		list->l_tail = lwp->li_prev;	/* removing the tail */
448*0Sstevel@tonic-gate 	lwpid_del(lwp->li_info.pr_pid, lwp->li_info.pr_lwp.pr_lwpid);
449*0Sstevel@tonic-gate 	if (lwpid_pidcheck(lwp->li_info.pr_pid) == 0)
450*0Sstevel@tonic-gate 		fds_rm(lwp->li_info.pr_pid);
451*0Sstevel@tonic-gate 	list->l_count--;
452*0Sstevel@tonic-gate 	free(lwp);
453*0Sstevel@tonic-gate }
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate static void
456*0Sstevel@tonic-gate list_clear(list_t *list)
457*0Sstevel@tonic-gate {
458*0Sstevel@tonic-gate 	if (list->l_type == LT_LWPS) {
459*0Sstevel@tonic-gate 		lwp_info_t	*lwp = list->l_tail;
460*0Sstevel@tonic-gate 		lwp_info_t	*lwp_tmp;
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate 		fd_closeall();
463*0Sstevel@tonic-gate 		while (lwp) {
464*0Sstevel@tonic-gate 			lwp_tmp = lwp;
465*0Sstevel@tonic-gate 			lwp = lwp->li_prev;
466*0Sstevel@tonic-gate 			list_remove_lwp(&lwps, lwp_tmp);
467*0Sstevel@tonic-gate 		}
468*0Sstevel@tonic-gate 	} else {
469*0Sstevel@tonic-gate 		id_info_t *id = list->l_head;
470*0Sstevel@tonic-gate 		id_info_t *nextid;
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 		while (id) {
473*0Sstevel@tonic-gate 			nextid = id->id_next;
474*0Sstevel@tonic-gate 			free(id);
475*0Sstevel@tonic-gate 			id = nextid;
476*0Sstevel@tonic-gate 		}
477*0Sstevel@tonic-gate 		list->l_count = 0;
478*0Sstevel@tonic-gate 		list->l_head = list->l_tail = NULL;
479*0Sstevel@tonic-gate 	}
480*0Sstevel@tonic-gate }
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate static void
483*0Sstevel@tonic-gate list_update(list_t *list, lwp_info_t *lwp)
484*0Sstevel@tonic-gate {
485*0Sstevel@tonic-gate 	id_info_t *id;
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate 	if (list->l_head == NULL) {			/* first element */
488*0Sstevel@tonic-gate 		list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
489*0Sstevel@tonic-gate 		goto update;
490*0Sstevel@tonic-gate 	}
491*0Sstevel@tonic-gate 
492*0Sstevel@tonic-gate 	for (id = list->l_head; id; id = id->id_next) {
493*0Sstevel@tonic-gate 		if ((list->l_type == LT_USERS) &&
494*0Sstevel@tonic-gate 		    (id->id_uid != lwp->li_info.pr_uid))
495*0Sstevel@tonic-gate 			continue;
496*0Sstevel@tonic-gate 		if ((list->l_type == LT_TASKS) &&
497*0Sstevel@tonic-gate 		    (id->id_taskid != lwp->li_info.pr_taskid))
498*0Sstevel@tonic-gate 			continue;
499*0Sstevel@tonic-gate 		if ((list->l_type == LT_PROJECTS) &&
500*0Sstevel@tonic-gate 		    (id->id_projid != lwp->li_info.pr_projid))
501*0Sstevel@tonic-gate 			continue;
502*0Sstevel@tonic-gate 		if ((list->l_type == LT_ZONES) &&
503*0Sstevel@tonic-gate 		    (id->id_zoneid != lwp->li_info.pr_zoneid))
504*0Sstevel@tonic-gate 			continue;
505*0Sstevel@tonic-gate 		id->id_nproc++;
506*0Sstevel@tonic-gate 		id->id_taskid	= lwp->li_info.pr_taskid;
507*0Sstevel@tonic-gate 		id->id_projid	= lwp->li_info.pr_projid;
508*0Sstevel@tonic-gate 		id->id_zoneid	= lwp->li_info.pr_zoneid;
509*0Sstevel@tonic-gate 		if (lwp->li_flags & LWP_REPRESENT) {
510*0Sstevel@tonic-gate 			id->id_size	+= lwp->li_info.pr_size;
511*0Sstevel@tonic-gate 			id->id_rssize	+= lwp->li_info.pr_rssize;
512*0Sstevel@tonic-gate 		}
513*0Sstevel@tonic-gate 		id->id_pctcpu	+= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
514*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
515*0Sstevel@tonic-gate 			id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time);
516*0Sstevel@tonic-gate 		else
517*0Sstevel@tonic-gate 			id->id_time += TIME2SEC(lwp->li_info.pr_time);
518*0Sstevel@tonic-gate 		id->id_pctmem	+= FRC2PCT(lwp->li_info.pr_pctmem);
519*0Sstevel@tonic-gate 		id->id_key	+= lwp->li_key;
520*0Sstevel@tonic-gate 		total_cpu	+= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
521*0Sstevel@tonic-gate 		total_mem	+= FRC2PCT(lwp->li_info.pr_pctmem);
522*0Sstevel@tonic-gate 		return;
523*0Sstevel@tonic-gate 	}
524*0Sstevel@tonic-gate 
525*0Sstevel@tonic-gate 	id = list->l_tail;
526*0Sstevel@tonic-gate 	id->id_next = Zalloc(sizeof (id_info_t));
527*0Sstevel@tonic-gate 	id->id_next->id_prev = list->l_tail;
528*0Sstevel@tonic-gate 	id->id_next->id_next = NULL;
529*0Sstevel@tonic-gate 	list->l_tail = id->id_next;
530*0Sstevel@tonic-gate 	id = list->l_tail;
531*0Sstevel@tonic-gate update:
532*0Sstevel@tonic-gate 	id->id_uid	= lwp->li_info.pr_uid;
533*0Sstevel@tonic-gate 	id->id_projid	= lwp->li_info.pr_projid;
534*0Sstevel@tonic-gate 	id->id_taskid	= lwp->li_info.pr_taskid;
535*0Sstevel@tonic-gate 	id->id_zoneid	= lwp->li_info.pr_zoneid;
536*0Sstevel@tonic-gate 	id->id_nproc++;
537*0Sstevel@tonic-gate 	if (lwp->li_flags & LWP_REPRESENT) {
538*0Sstevel@tonic-gate 		id->id_size	= lwp->li_info.pr_size;
539*0Sstevel@tonic-gate 		id->id_rssize	= lwp->li_info.pr_rssize;
540*0Sstevel@tonic-gate 	}
541*0Sstevel@tonic-gate 	id->id_pctcpu	= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
542*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_LWPS)
543*0Sstevel@tonic-gate 		id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time);
544*0Sstevel@tonic-gate 	else
545*0Sstevel@tonic-gate 		id->id_time = TIME2SEC(lwp->li_info.pr_time);
546*0Sstevel@tonic-gate 	id->id_pctmem	= FRC2PCT(lwp->li_info.pr_pctmem);
547*0Sstevel@tonic-gate 	id->id_key	= lwp->li_key;
548*0Sstevel@tonic-gate 	total_cpu	+= id->id_pctcpu;
549*0Sstevel@tonic-gate 	total_mem	+= id->id_pctmem;
550*0Sstevel@tonic-gate 	list->l_count++;
551*0Sstevel@tonic-gate }
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate static void
554*0Sstevel@tonic-gate lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage)
555*0Sstevel@tonic-gate {
556*0Sstevel@tonic-gate 	float period;
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate 	if (!lwpid_is_active(pid, lwpid)) {
559*0Sstevel@tonic-gate 		/*
560*0Sstevel@tonic-gate 		 * If we are reading cpu times for the first time then
561*0Sstevel@tonic-gate 		 * calculate average cpu times based on whole process
562*0Sstevel@tonic-gate 		 * execution time.
563*0Sstevel@tonic-gate 		 */
564*0Sstevel@tonic-gate 		(void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
565*0Sstevel@tonic-gate 		period = TIME2NSEC(usage->pr_rtime);
566*0Sstevel@tonic-gate 		period = period/(float)100;
567*0Sstevel@tonic-gate 
568*0Sstevel@tonic-gate 		if (period == 0) { /* zombie */
569*0Sstevel@tonic-gate 			period = 1;
570*0Sstevel@tonic-gate 			lwp->li_usr = 0;
571*0Sstevel@tonic-gate 			lwp->li_sys = 0;
572*0Sstevel@tonic-gate 			lwp->li_slp = 0;
573*0Sstevel@tonic-gate 		} else {
574*0Sstevel@tonic-gate 			lwp->li_usr = TIME2NSEC(usage->pr_utime)/period;
575*0Sstevel@tonic-gate 			lwp->li_sys = TIME2NSEC(usage->pr_stime)/period;
576*0Sstevel@tonic-gate 			lwp->li_slp = TIME2NSEC(usage->pr_slptime)/period;
577*0Sstevel@tonic-gate 		}
578*0Sstevel@tonic-gate 		lwp->li_trp = TIME2NSEC(usage->pr_ttime)/period;
579*0Sstevel@tonic-gate 		lwp->li_tfl = TIME2NSEC(usage->pr_tftime)/period;
580*0Sstevel@tonic-gate 		lwp->li_dfl = TIME2NSEC(usage->pr_dftime)/period;
581*0Sstevel@tonic-gate 		lwp->li_lck = TIME2NSEC(usage->pr_ltime)/period;
582*0Sstevel@tonic-gate 		lwp->li_lat = TIME2NSEC(usage->pr_wtime)/period;
583*0Sstevel@tonic-gate 		period = (period / NANOSEC)*(float)100; /* now in seconds */
584*0Sstevel@tonic-gate 		lwp->li_vcx = (ulong_t)
585*0Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_vctx/period));
586*0Sstevel@tonic-gate 		lwp->li_icx = (ulong_t)
587*0Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_ictx/period));
588*0Sstevel@tonic-gate 		lwp->li_scl = (ulong_t)
589*0Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_sysc/period));
590*0Sstevel@tonic-gate 		lwp->li_sig = (ulong_t)
591*0Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_sigs/period));
592*0Sstevel@tonic-gate 		(void) lwpid_set_active(pid, lwpid);
593*0Sstevel@tonic-gate 	} else {
594*0Sstevel@tonic-gate 		/*
595*0Sstevel@tonic-gate 		 * If this is not a first time we are reading a process's
596*0Sstevel@tonic-gate 		 * CPU times then recalculate CPU times based on fresh data
597*0Sstevel@tonic-gate 		 * obtained from procfs and previous CPU time usage values.
598*0Sstevel@tonic-gate 		 */
599*0Sstevel@tonic-gate 		period = TIME2NSEC(usage->pr_rtime)-
600*0Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_rtime);
601*0Sstevel@tonic-gate 		period = period/(float)100;
602*0Sstevel@tonic-gate 
603*0Sstevel@tonic-gate 		if (period == 0) { /* zombie */
604*0Sstevel@tonic-gate 			period = 1;
605*0Sstevel@tonic-gate 			lwp->li_usr = 0;
606*0Sstevel@tonic-gate 			lwp->li_sys = 0;
607*0Sstevel@tonic-gate 			lwp->li_slp = 0;
608*0Sstevel@tonic-gate 		} else {
609*0Sstevel@tonic-gate 			lwp->li_usr = (TIME2NSEC(usage->pr_utime)-
610*0Sstevel@tonic-gate 			    TIME2NSEC(lwp->li_usage.pr_utime))/period;
611*0Sstevel@tonic-gate 			lwp->li_sys = (TIME2NSEC(usage->pr_stime) -
612*0Sstevel@tonic-gate 			    TIME2NSEC(lwp->li_usage.pr_stime))/period;
613*0Sstevel@tonic-gate 			lwp->li_slp = (TIME2NSEC(usage->pr_slptime) -
614*0Sstevel@tonic-gate 			    TIME2NSEC(lwp->li_usage.pr_slptime))/period;
615*0Sstevel@tonic-gate 		}
616*0Sstevel@tonic-gate 		lwp->li_trp = (TIME2NSEC(usage->pr_ttime) -
617*0Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_ttime))/period;
618*0Sstevel@tonic-gate 		lwp->li_tfl = (TIME2NSEC(usage->pr_tftime) -
619*0Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_tftime))/period;
620*0Sstevel@tonic-gate 		lwp->li_dfl = (TIME2NSEC(usage->pr_dftime) -
621*0Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_dftime))/period;
622*0Sstevel@tonic-gate 		lwp->li_lck = (TIME2NSEC(usage->pr_ltime) -
623*0Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_ltime))/period;
624*0Sstevel@tonic-gate 		lwp->li_lat = (TIME2NSEC(usage->pr_wtime) -
625*0Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_wtime))/period;
626*0Sstevel@tonic-gate 		lwp->li_vcx = usage->pr_vctx - lwp->li_usage.pr_vctx;
627*0Sstevel@tonic-gate 		lwp->li_icx = usage->pr_ictx - lwp->li_usage.pr_ictx;
628*0Sstevel@tonic-gate 		lwp->li_scl = usage->pr_sysc - lwp->li_usage.pr_sysc;
629*0Sstevel@tonic-gate 		lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs;
630*0Sstevel@tonic-gate 		(void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
631*0Sstevel@tonic-gate 	}
632*0Sstevel@tonic-gate }
633*0Sstevel@tonic-gate 
634*0Sstevel@tonic-gate static int
635*0Sstevel@tonic-gate read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize)
636*0Sstevel@tonic-gate {
637*0Sstevel@tonic-gate 	char procfile[MAX_PROCFS_PATH];
638*0Sstevel@tonic-gate 
639*0Sstevel@tonic-gate 	(void) snprintf(procfile, MAX_PROCFS_PATH,
640*0Sstevel@tonic-gate 	    "/proc/%s/%s", pidstr, file);
641*0Sstevel@tonic-gate 	if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL)
642*0Sstevel@tonic-gate 		return (1);
643*0Sstevel@tonic-gate 	if (pread(fd_getfd(*fd), buf, bufsize, 0) != bufsize) {
644*0Sstevel@tonic-gate 		fd_close(*fd);
645*0Sstevel@tonic-gate 		return (1);
646*0Sstevel@tonic-gate 	}
647*0Sstevel@tonic-gate 	return (0);
648*0Sstevel@tonic-gate }
649*0Sstevel@tonic-gate 
650*0Sstevel@tonic-gate static void
651*0Sstevel@tonic-gate add_proc(psinfo_t *psinfo)
652*0Sstevel@tonic-gate {
653*0Sstevel@tonic-gate 	lwp_info_t *lwp;
654*0Sstevel@tonic-gate 	id_t lwpid;
655*0Sstevel@tonic-gate 	pid_t pid = psinfo->pr_pid;
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 	lwpid = psinfo->pr_lwp.pr_lwpid;
658*0Sstevel@tonic-gate 	if ((lwp = lwpid_get(pid, lwpid)) == NULL)
659*0Sstevel@tonic-gate 		lwp = list_add_lwp(&lwps, pid, lwpid);
660*0Sstevel@tonic-gate 	lwp->li_flags |= LWP_ALIVE | LWP_REPRESENT;
661*0Sstevel@tonic-gate 	(void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t));
662*0Sstevel@tonic-gate 	lwp->li_info.pr_lwp.pr_pctcpu = lwp->li_info.pr_pctcpu;
663*0Sstevel@tonic-gate }
664*0Sstevel@tonic-gate 
665*0Sstevel@tonic-gate static void
666*0Sstevel@tonic-gate add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
667*0Sstevel@tonic-gate {
668*0Sstevel@tonic-gate 	lwp_info_t *lwp;
669*0Sstevel@tonic-gate 	pid_t pid = psinfo->pr_pid;
670*0Sstevel@tonic-gate 	id_t lwpid = lwpsinfo->pr_lwpid;
671*0Sstevel@tonic-gate 
672*0Sstevel@tonic-gate 	if ((lwp = lwpid_get(pid, lwpid)) == NULL)
673*0Sstevel@tonic-gate 		lwp = list_add_lwp(&lwps, pid, lwpid);
674*0Sstevel@tonic-gate 	lwp->li_flags &= ~LWP_REPRESENT;
675*0Sstevel@tonic-gate 	lwp->li_flags |= LWP_ALIVE;
676*0Sstevel@tonic-gate 	lwp->li_flags |= flags;
677*0Sstevel@tonic-gate 	(void) memcpy(&lwp->li_info, psinfo,
678*0Sstevel@tonic-gate 	    sizeof (psinfo_t) - sizeof (lwpsinfo_t));
679*0Sstevel@tonic-gate 	(void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t));
680*0Sstevel@tonic-gate }
681*0Sstevel@tonic-gate 
682*0Sstevel@tonic-gate static void
683*0Sstevel@tonic-gate prstat_scandir(DIR *procdir)
684*0Sstevel@tonic-gate {
685*0Sstevel@tonic-gate 	char *pidstr;
686*0Sstevel@tonic-gate 	pid_t pid;
687*0Sstevel@tonic-gate 	id_t lwpid;
688*0Sstevel@tonic-gate 	size_t entsz;
689*0Sstevel@tonic-gate 	long nlwps, nent, i;
690*0Sstevel@tonic-gate 	char *buf, *ptr;
691*0Sstevel@tonic-gate 
692*0Sstevel@tonic-gate 	fds_t *fds;
693*0Sstevel@tonic-gate 	lwp_info_t *lwp;
694*0Sstevel@tonic-gate 	dirent_t *direntp;
695*0Sstevel@tonic-gate 
696*0Sstevel@tonic-gate 	prheader_t	header;
697*0Sstevel@tonic-gate 	psinfo_t	psinfo;
698*0Sstevel@tonic-gate 	prusage_t	usage;
699*0Sstevel@tonic-gate 	lwpsinfo_t	*lwpsinfo;
700*0Sstevel@tonic-gate 	prusage_t	*lwpusage;
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate 	total_procs = 0;
703*0Sstevel@tonic-gate 	total_lwps = 0;
704*0Sstevel@tonic-gate 	total_cpu = 0;
705*0Sstevel@tonic-gate 	total_mem = 0;
706*0Sstevel@tonic-gate 
707*0Sstevel@tonic-gate 	convert_zone(&zone_tbl);
708*0Sstevel@tonic-gate 	for (rewinddir(procdir); (direntp = readdir(procdir)); ) {
709*0Sstevel@tonic-gate 		pidstr = direntp->d_name;
710*0Sstevel@tonic-gate 		if (pidstr[0] == '.')	/* skip "." and ".."  */
711*0Sstevel@tonic-gate 			continue;
712*0Sstevel@tonic-gate 		pid = atoi(pidstr);
713*0Sstevel@tonic-gate 		if (pid == 0 || pid == 2 || pid == 3)
714*0Sstevel@tonic-gate 			continue;	/* skip sched, pageout and fsflush */
715*0Sstevel@tonic-gate 		if (has_element(&pid_tbl, pid) == 0)
716*0Sstevel@tonic-gate 			continue;	/* check if we really want this pid */
717*0Sstevel@tonic-gate 		fds = fds_get(pid);	/* get ptr to file descriptors */
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 		if (read_procfile(&fds->fds_psinfo, pidstr,
720*0Sstevel@tonic-gate 		    "psinfo", &psinfo, sizeof (psinfo_t)) != 0)
721*0Sstevel@tonic-gate 			continue;
722*0Sstevel@tonic-gate 		if (!has_uid(&ruid_tbl, psinfo.pr_uid) ||
723*0Sstevel@tonic-gate 		    !has_uid(&euid_tbl, psinfo.pr_euid) ||
724*0Sstevel@tonic-gate 		    !has_element(&prj_tbl, psinfo.pr_projid) ||
725*0Sstevel@tonic-gate 		    !has_element(&tsk_tbl, psinfo.pr_taskid) ||
726*0Sstevel@tonic-gate 		    !has_zone(&zone_tbl, psinfo.pr_zoneid)) {
727*0Sstevel@tonic-gate 			fd_close(fds->fds_psinfo);
728*0Sstevel@tonic-gate 			continue;
729*0Sstevel@tonic-gate 		}
730*0Sstevel@tonic-gate 		nlwps = psinfo.pr_nlwp + psinfo.pr_nzomb;
731*0Sstevel@tonic-gate 
732*0Sstevel@tonic-gate 		if (nlwps > 1 && (opts.o_outpmode & (OPT_LWPS | OPT_PSETS))) {
733*0Sstevel@tonic-gate 			int rep_lwp = 0;
734*0Sstevel@tonic-gate 
735*0Sstevel@tonic-gate 			if (read_procfile(&fds->fds_lpsinfo, pidstr, "lpsinfo",
736*0Sstevel@tonic-gate 			    &header, sizeof (prheader_t)) != 0) {
737*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
738*0Sstevel@tonic-gate 				continue;
739*0Sstevel@tonic-gate 			}
740*0Sstevel@tonic-gate 
741*0Sstevel@tonic-gate 			nent = header.pr_nent;
742*0Sstevel@tonic-gate 			entsz = header.pr_entsize * nent;
743*0Sstevel@tonic-gate 			ptr = buf = Malloc(entsz);
744*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lpsinfo), buf,
745*0Sstevel@tonic-gate 			    entsz, sizeof (struct prheader)) != entsz) {
746*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
747*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
748*0Sstevel@tonic-gate 				free(buf);
749*0Sstevel@tonic-gate 				continue;
750*0Sstevel@tonic-gate 			}
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 			nlwps = 0;
753*0Sstevel@tonic-gate 			for (i = 0; i < nent; i++, ptr += header.pr_entsize) {
754*0Sstevel@tonic-gate 				/*LINTED ALIGNMENT*/
755*0Sstevel@tonic-gate 				lwpsinfo = (lwpsinfo_t *)ptr;
756*0Sstevel@tonic-gate 				if (!has_element(&cpu_tbl,
757*0Sstevel@tonic-gate 				    lwpsinfo->pr_onpro) ||
758*0Sstevel@tonic-gate 				    !has_element(&set_tbl,
759*0Sstevel@tonic-gate 				    lwpsinfo->pr_bindpset))
760*0Sstevel@tonic-gate 					continue;
761*0Sstevel@tonic-gate 				nlwps++;
762*0Sstevel@tonic-gate 				if ((opts.o_outpmode & (OPT_PSETS | OPT_LWPS))
763*0Sstevel@tonic-gate 				    == OPT_PSETS) {
764*0Sstevel@tonic-gate 					/*
765*0Sstevel@tonic-gate 					 * If one of process's LWPs is bound
766*0Sstevel@tonic-gate 					 * to a given processor set, report the
767*0Sstevel@tonic-gate 					 * whole process.  We may be doing this
768*0Sstevel@tonic-gate 					 * a few times but we'll get an accurate
769*0Sstevel@tonic-gate 					 * lwp count in return.
770*0Sstevel@tonic-gate 					 */
771*0Sstevel@tonic-gate 					add_proc(&psinfo);
772*0Sstevel@tonic-gate 				} else {
773*0Sstevel@tonic-gate 					if (rep_lwp == 0) {
774*0Sstevel@tonic-gate 						rep_lwp = 1;
775*0Sstevel@tonic-gate 						add_lwp(&psinfo, lwpsinfo,
776*0Sstevel@tonic-gate 						    LWP_REPRESENT);
777*0Sstevel@tonic-gate 					} else {
778*0Sstevel@tonic-gate 						add_lwp(&psinfo, lwpsinfo, 0);
779*0Sstevel@tonic-gate 					}
780*0Sstevel@tonic-gate 				}
781*0Sstevel@tonic-gate 			}
782*0Sstevel@tonic-gate 			free(buf);
783*0Sstevel@tonic-gate 			if (nlwps == 0) {
784*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
785*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
786*0Sstevel@tonic-gate 				continue;
787*0Sstevel@tonic-gate 			}
788*0Sstevel@tonic-gate 		} else {
789*0Sstevel@tonic-gate 			if (!has_element(&cpu_tbl, psinfo.pr_lwp.pr_onpro) ||
790*0Sstevel@tonic-gate 			    !has_element(&set_tbl, psinfo.pr_lwp.pr_bindpset)) {
791*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
792*0Sstevel@tonic-gate 				continue;
793*0Sstevel@tonic-gate 			}
794*0Sstevel@tonic-gate 			add_proc(&psinfo);
795*0Sstevel@tonic-gate 		}
796*0Sstevel@tonic-gate 		if (!(opts.o_outpmode & OPT_MSACCT)) {
797*0Sstevel@tonic-gate 			total_procs++;
798*0Sstevel@tonic-gate 			total_lwps += nlwps;
799*0Sstevel@tonic-gate 			continue;
800*0Sstevel@tonic-gate 		}
801*0Sstevel@tonic-gate 		/*
802*0Sstevel@tonic-gate 		 * Get more information about processes from /proc/pid/usage.
803*0Sstevel@tonic-gate 		 * If process has more than one lwp, then we may have to
804*0Sstevel@tonic-gate 		 * also look at the /proc/pid/lusage file.
805*0Sstevel@tonic-gate 		 */
806*0Sstevel@tonic-gate 		if ((opts.o_outpmode & OPT_LWPS) && (nlwps > 1)) {
807*0Sstevel@tonic-gate 			if (read_procfile(&fds->fds_lusage, pidstr, "lusage",
808*0Sstevel@tonic-gate 			    &header, sizeof (prheader_t)) != 0) {
809*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
810*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
811*0Sstevel@tonic-gate 				continue;
812*0Sstevel@tonic-gate 			}
813*0Sstevel@tonic-gate 			nent = header.pr_nent;
814*0Sstevel@tonic-gate 			entsz = header.pr_entsize * nent;
815*0Sstevel@tonic-gate 			buf = Malloc(entsz);
816*0Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lusage), buf,
817*0Sstevel@tonic-gate 			    entsz, sizeof (struct prheader)) != entsz) {
818*0Sstevel@tonic-gate 				fd_close(fds->fds_lusage);
819*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
820*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
821*0Sstevel@tonic-gate 				free(buf);
822*0Sstevel@tonic-gate 				continue;
823*0Sstevel@tonic-gate 			}
824*0Sstevel@tonic-gate 			for (i = 1, ptr = buf + header.pr_entsize; i < nent;
825*0Sstevel@tonic-gate 			    i++, ptr += header.pr_entsize) {
826*0Sstevel@tonic-gate 				/*LINTED ALIGNMENT*/
827*0Sstevel@tonic-gate 				lwpusage = (prusage_t *)ptr;
828*0Sstevel@tonic-gate 				lwpid = lwpusage->pr_lwpid;
829*0Sstevel@tonic-gate 				/*
830*0Sstevel@tonic-gate 				 * New LWPs created after we read lpsinfo
831*0Sstevel@tonic-gate 				 * will be ignored.  Don't want to do
832*0Sstevel@tonic-gate 				 * everything all over again.
833*0Sstevel@tonic-gate 				 */
834*0Sstevel@tonic-gate 				if ((lwp = lwpid_get(pid, lwpid)) == NULL)
835*0Sstevel@tonic-gate 					continue;
836*0Sstevel@tonic-gate 				lwp_update(lwp, pid, lwpid, lwpusage);
837*0Sstevel@tonic-gate 			}
838*0Sstevel@tonic-gate 			free(buf);
839*0Sstevel@tonic-gate 		} else {
840*0Sstevel@tonic-gate 			if (read_procfile(&fds->fds_usage, pidstr, "usage",
841*0Sstevel@tonic-gate 			    &usage, sizeof (prusage_t)) != 0) {
842*0Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
843*0Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
844*0Sstevel@tonic-gate 				continue;
845*0Sstevel@tonic-gate 			}
846*0Sstevel@tonic-gate 			lwpid = psinfo.pr_lwp.pr_lwpid;
847*0Sstevel@tonic-gate 			if ((lwp = lwpid_get(pid, lwpid)) == NULL)
848*0Sstevel@tonic-gate 				continue;
849*0Sstevel@tonic-gate 			lwp_update(lwp, pid, lwpid, &usage);
850*0Sstevel@tonic-gate 		}
851*0Sstevel@tonic-gate 		total_procs++;
852*0Sstevel@tonic-gate 		total_lwps += nlwps;
853*0Sstevel@tonic-gate 	}
854*0Sstevel@tonic-gate 	fd_update();
855*0Sstevel@tonic-gate }
856*0Sstevel@tonic-gate 
857*0Sstevel@tonic-gate /*
858*0Sstevel@tonic-gate  * This procedure removes all dead lwps from the linked list of all lwps.
859*0Sstevel@tonic-gate  * It also creates linked list of ids if necessary.
860*0Sstevel@tonic-gate  */
861*0Sstevel@tonic-gate static void
862*0Sstevel@tonic-gate list_refresh(list_t *list)
863*0Sstevel@tonic-gate {
864*0Sstevel@tonic-gate 	lwp_info_t *lwp, *lwp_next;
865*0Sstevel@tonic-gate 
866*0Sstevel@tonic-gate 	if (!(list->l_type & LT_LWPS))
867*0Sstevel@tonic-gate 		return;
868*0Sstevel@tonic-gate 
869*0Sstevel@tonic-gate 	for (lwp = list->l_head; lwp != NULL; ) {
870*0Sstevel@tonic-gate 		if (lwp->li_flags & LWP_ALIVE) {
871*0Sstevel@tonic-gate 			/*
872*0Sstevel@tonic-gate 			 * Process all live LWPs.
873*0Sstevel@tonic-gate 			 * When we're done, mark them as dead.
874*0Sstevel@tonic-gate 			 * They will be marked "alive" on the next
875*0Sstevel@tonic-gate 			 * /proc scan if they still exist.
876*0Sstevel@tonic-gate 			 */
877*0Sstevel@tonic-gate 			lwp->li_key = list_getkeyval(list, lwp);
878*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_USERS)
879*0Sstevel@tonic-gate 				list_update(&users, lwp);
880*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_TASKS)
881*0Sstevel@tonic-gate 				list_update(&tasks, lwp);
882*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_PROJECTS)
883*0Sstevel@tonic-gate 				list_update(&projects, lwp);
884*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_ZONES)
885*0Sstevel@tonic-gate 				list_update(&zones, lwp);
886*0Sstevel@tonic-gate 			lwp->li_flags &= ~LWP_ALIVE;
887*0Sstevel@tonic-gate 			lwp = lwp->li_next;
888*0Sstevel@tonic-gate 
889*0Sstevel@tonic-gate 		} else {
890*0Sstevel@tonic-gate 			lwp_next = lwp->li_next;
891*0Sstevel@tonic-gate 			list_remove_lwp(&lwps, lwp);
892*0Sstevel@tonic-gate 			lwp = lwp_next;
893*0Sstevel@tonic-gate 		}
894*0Sstevel@tonic-gate 	}
895*0Sstevel@tonic-gate }
896*0Sstevel@tonic-gate 
897*0Sstevel@tonic-gate static void
898*0Sstevel@tonic-gate curses_on()
899*0Sstevel@tonic-gate {
900*0Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
901*0Sstevel@tonic-gate 		(void) initscr();
902*0Sstevel@tonic-gate 		(void) nonl();
903*0Sstevel@tonic-gate 		(void) putp(t_smcup);
904*0Sstevel@tonic-gate 		is_curses_on = TRUE;
905*0Sstevel@tonic-gate 	}
906*0Sstevel@tonic-gate }
907*0Sstevel@tonic-gate 
908*0Sstevel@tonic-gate static void
909*0Sstevel@tonic-gate curses_off()
910*0Sstevel@tonic-gate {
911*0Sstevel@tonic-gate 	if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
912*0Sstevel@tonic-gate 		(void) putp(t_rmcup);
913*0Sstevel@tonic-gate 		(void) endwin();
914*0Sstevel@tonic-gate 		is_curses_on = FALSE;
915*0Sstevel@tonic-gate 	}
916*0Sstevel@tonic-gate 	(void) fflush(stdout);
917*0Sstevel@tonic-gate }
918*0Sstevel@tonic-gate 
919*0Sstevel@tonic-gate static int
920*0Sstevel@tonic-gate nlines()
921*0Sstevel@tonic-gate {
922*0Sstevel@tonic-gate 	struct winsize ws;
923*0Sstevel@tonic-gate 	char *envp;
924*0Sstevel@tonic-gate 	int n;
925*0Sstevel@tonic-gate 	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
926*0Sstevel@tonic-gate 		if (ws.ws_row > 0)
927*0Sstevel@tonic-gate 			return (ws.ws_row);
928*0Sstevel@tonic-gate 	}
929*0Sstevel@tonic-gate 	if (envp = getenv("LINES")) {
930*0Sstevel@tonic-gate 		if ((n = Atoi(envp)) > 0) {
931*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_USEHOME;
932*0Sstevel@tonic-gate 			return (n);
933*0Sstevel@tonic-gate 		}
934*0Sstevel@tonic-gate 	}
935*0Sstevel@tonic-gate 	return (-1);
936*0Sstevel@tonic-gate }
937*0Sstevel@tonic-gate 
938*0Sstevel@tonic-gate static void
939*0Sstevel@tonic-gate setmovecur()
940*0Sstevel@tonic-gate {
941*0Sstevel@tonic-gate 	int i, n;
942*0Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_FULLSCREEN) &&
943*0Sstevel@tonic-gate 	    (opts.o_outpmode & OPT_USEHOME)) {
944*0Sstevel@tonic-gate 		movecur = t_home;
945*0Sstevel@tonic-gate 		return;
946*0Sstevel@tonic-gate 	}
947*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_SPLIT) {
948*0Sstevel@tonic-gate 		n = opts.o_ntop + opts.o_nbottom + 2;
949*0Sstevel@tonic-gate 	} else {
950*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_USERS)
951*0Sstevel@tonic-gate 			n = opts.o_nbottom + 1;
952*0Sstevel@tonic-gate 		else
953*0Sstevel@tonic-gate 			n = opts.o_ntop + 1;
954*0Sstevel@tonic-gate 	}
955*0Sstevel@tonic-gate 	if (movecur != NULL && movecur != empty_string && movecur != t_home)
956*0Sstevel@tonic-gate 		free(movecur);
957*0Sstevel@tonic-gate 	movecur = Zalloc(strlen(t_up) * (n + 5));
958*0Sstevel@tonic-gate 	for (i = 0; i <= n; i++)
959*0Sstevel@tonic-gate 		(void) strcat(movecur, t_up);
960*0Sstevel@tonic-gate }
961*0Sstevel@tonic-gate 
962*0Sstevel@tonic-gate static int
963*0Sstevel@tonic-gate setsize()
964*0Sstevel@tonic-gate {
965*0Sstevel@tonic-gate 	static int oldn = 0;
966*0Sstevel@tonic-gate 	int n;
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_FULLSCREEN) {
969*0Sstevel@tonic-gate 		n = nlines();
970*0Sstevel@tonic-gate 		if (n == oldn)
971*0Sstevel@tonic-gate 			return (0);
972*0Sstevel@tonic-gate 		oldn = n;
973*0Sstevel@tonic-gate 		if (n == -1) {
974*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_USEHOME;
975*0Sstevel@tonic-gate 			setmovecur();		/* set default window size */
976*0Sstevel@tonic-gate 			return (1);
977*0Sstevel@tonic-gate 		}
978*0Sstevel@tonic-gate 		n = n - 3;	/* minus header, total and cursor lines */
979*0Sstevel@tonic-gate 		if (n < 1)
980*0Sstevel@tonic-gate 			Die(gettext("window is too small (try -n)\n"));
981*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_SPLIT) {
982*0Sstevel@tonic-gate 			if (n < 8) {
983*0Sstevel@tonic-gate 				Die(gettext("window is too small (try -n)\n"));
984*0Sstevel@tonic-gate 			} else {
985*0Sstevel@tonic-gate 				opts.o_ntop = (n / 4) * 3;
986*0Sstevel@tonic-gate 				opts.o_nbottom = n - 1 - opts.o_ntop;
987*0Sstevel@tonic-gate 			}
988*0Sstevel@tonic-gate 		} else {
989*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_USERS)
990*0Sstevel@tonic-gate 				opts.o_nbottom = n;
991*0Sstevel@tonic-gate 			else
992*0Sstevel@tonic-gate 				opts.o_ntop = n;
993*0Sstevel@tonic-gate 		}
994*0Sstevel@tonic-gate 	}
995*0Sstevel@tonic-gate 	setmovecur();
996*0Sstevel@tonic-gate 	return (1);
997*0Sstevel@tonic-gate }
998*0Sstevel@tonic-gate 
999*0Sstevel@tonic-gate static void
1000*0Sstevel@tonic-gate ldtermcap()
1001*0Sstevel@tonic-gate {
1002*0Sstevel@tonic-gate 	int err;
1003*0Sstevel@tonic-gate 	if (setupterm(NULL, STDIN_FILENO, &err) == ERR) {
1004*0Sstevel@tonic-gate 		switch (err) {
1005*0Sstevel@tonic-gate 		case 0:
1006*0Sstevel@tonic-gate 			Warn(gettext("failed to load terminal info, "
1007*0Sstevel@tonic-gate 			    "defaulting to -c option\n"));
1008*0Sstevel@tonic-gate 			break;
1009*0Sstevel@tonic-gate 		case -1:
1010*0Sstevel@tonic-gate 			Warn(gettext("terminfo database not found, "
1011*0Sstevel@tonic-gate 			    "defaulting to -c option\n"));
1012*0Sstevel@tonic-gate 			break;
1013*0Sstevel@tonic-gate 		default:
1014*0Sstevel@tonic-gate 			Warn(gettext("failed to initialize terminal, "
1015*0Sstevel@tonic-gate 			    "defaulting to -c option\n"));
1016*0Sstevel@tonic-gate 		}
1017*0Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP;
1018*0Sstevel@tonic-gate 		t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
1019*0Sstevel@tonic-gate 		t_ulon = t_uloff = empty_string;
1020*0Sstevel@tonic-gate 		return;
1021*0Sstevel@tonic-gate 	}
1022*0Sstevel@tonic-gate 	t_ulon	= tigetstr("smul");
1023*0Sstevel@tonic-gate 	t_uloff	= tigetstr("rmul");
1024*0Sstevel@tonic-gate 	t_up	= tigetstr("cuu1");
1025*0Sstevel@tonic-gate 	t_eol	= tigetstr("el");
1026*0Sstevel@tonic-gate 	t_smcup	= tigetstr("smcup");
1027*0Sstevel@tonic-gate 	t_rmcup = tigetstr("rmcup");
1028*0Sstevel@tonic-gate 	t_home  = tigetstr("home");
1029*0Sstevel@tonic-gate 	if ((t_up == (char *)-1) || (t_eol == (char *)-1) ||
1030*0Sstevel@tonic-gate 	    (t_smcup == (char *)-1) || (t_rmcup == (char *)-1)) {
1031*0Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP;
1032*0Sstevel@tonic-gate 		t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
1033*0Sstevel@tonic-gate 		return;
1034*0Sstevel@tonic-gate 	}
1035*0Sstevel@tonic-gate 	if (t_up == NULL || t_eol == NULL) {
1036*0Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP;
1037*0Sstevel@tonic-gate 		t_eol = t_up = movecur = empty_string;
1038*0Sstevel@tonic-gate 		return;
1039*0Sstevel@tonic-gate 	}
1040*0Sstevel@tonic-gate 	if (t_ulon == (char *)-1 || t_uloff == (char *)-1 ||
1041*0Sstevel@tonic-gate 	    t_ulon == NULL || t_uloff == NULL) {
1042*0Sstevel@tonic-gate 		t_ulon = t_uloff = empty_string;  /* can live without it */
1043*0Sstevel@tonic-gate 	}
1044*0Sstevel@tonic-gate 	if (t_smcup == NULL || t_rmcup == NULL)
1045*0Sstevel@tonic-gate 		t_smcup = t_rmcup = empty_string;
1046*0Sstevel@tonic-gate 	if (t_home == (char *)-1 || t_home == NULL) {
1047*0Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_USEHOME;
1048*0Sstevel@tonic-gate 		t_home = empty_string;
1049*0Sstevel@tonic-gate 	}
1050*0Sstevel@tonic-gate }
1051*0Sstevel@tonic-gate 
1052*0Sstevel@tonic-gate static void
1053*0Sstevel@tonic-gate sig_handler(int sig)
1054*0Sstevel@tonic-gate {
1055*0Sstevel@tonic-gate 	switch (sig) {
1056*0Sstevel@tonic-gate 	case SIGTSTP:	sigtstp = 1;
1057*0Sstevel@tonic-gate 			break;
1058*0Sstevel@tonic-gate 	case SIGWINCH:	sigwinch = 1;
1059*0Sstevel@tonic-gate 			break;
1060*0Sstevel@tonic-gate 	case SIGINT:
1061*0Sstevel@tonic-gate 	case SIGTERM:	sigterm = 1;
1062*0Sstevel@tonic-gate 			break;
1063*0Sstevel@tonic-gate 	}
1064*0Sstevel@tonic-gate }
1065*0Sstevel@tonic-gate 
1066*0Sstevel@tonic-gate static void
1067*0Sstevel@tonic-gate set_signals()
1068*0Sstevel@tonic-gate {
1069*0Sstevel@tonic-gate 	(void) signal(SIGTSTP, sig_handler);
1070*0Sstevel@tonic-gate 	(void) signal(SIGINT, sig_handler);
1071*0Sstevel@tonic-gate 	(void) signal(SIGTERM, sig_handler);
1072*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_FULLSCREEN)
1073*0Sstevel@tonic-gate 		(void) signal(SIGWINCH, sig_handler);
1074*0Sstevel@tonic-gate }
1075*0Sstevel@tonic-gate 
1076*0Sstevel@tonic-gate static void
1077*0Sstevel@tonic-gate fill_table(table_t *table, char *arg)
1078*0Sstevel@tonic-gate {
1079*0Sstevel@tonic-gate 	char *p = strtok(arg, ", ");
1080*0Sstevel@tonic-gate 	long l = Atoi(p);
1081*0Sstevel@tonic-gate 
1082*0Sstevel@tonic-gate 	add_element(table, l);
1083*0Sstevel@tonic-gate 	while (p = strtok(NULL, ", ")) {
1084*0Sstevel@tonic-gate 		l = Atoi(p);
1085*0Sstevel@tonic-gate 		add_element(table, l);
1086*0Sstevel@tonic-gate 	}
1087*0Sstevel@tonic-gate }
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate static void
1090*0Sstevel@tonic-gate fill_prj_table(char *arg)
1091*0Sstevel@tonic-gate {
1092*0Sstevel@tonic-gate 	projid_t projid;
1093*0Sstevel@tonic-gate 	char *p = strtok(arg, ", ");
1094*0Sstevel@tonic-gate 
1095*0Sstevel@tonic-gate 	if ((projid = getprojidbyname(p)) == -1)
1096*0Sstevel@tonic-gate 		projid = Atoi(p);
1097*0Sstevel@tonic-gate 	add_element(&prj_tbl, (long)projid);
1098*0Sstevel@tonic-gate 
1099*0Sstevel@tonic-gate 	while (p = strtok(NULL, ", ")) {
1100*0Sstevel@tonic-gate 		if ((projid = getprojidbyname(p)) == -1)
1101*0Sstevel@tonic-gate 			projid = Atoi(p);
1102*0Sstevel@tonic-gate 		add_element(&prj_tbl, (long)projid);
1103*0Sstevel@tonic-gate 	}
1104*0Sstevel@tonic-gate }
1105*0Sstevel@tonic-gate 
1106*0Sstevel@tonic-gate static void
1107*0Sstevel@tonic-gate fill_set_table(char *arg)
1108*0Sstevel@tonic-gate {
1109*0Sstevel@tonic-gate 	char *p = strtok(arg, ", ");
1110*0Sstevel@tonic-gate 	psetid_t id;
1111*0Sstevel@tonic-gate 
1112*0Sstevel@tonic-gate 	if ((id = Atoi(p)) == 0)
1113*0Sstevel@tonic-gate 		id = PS_NONE;
1114*0Sstevel@tonic-gate 	add_element(&set_tbl, id);
1115*0Sstevel@tonic-gate 	while (p = strtok(NULL, ", ")) {
1116*0Sstevel@tonic-gate 		if ((id = Atoi(p)) == 0)
1117*0Sstevel@tonic-gate 			id = PS_NONE;
1118*0Sstevel@tonic-gate 		if (!has_element(&set_tbl, id))
1119*0Sstevel@tonic-gate 			add_element(&set_tbl, id);
1120*0Sstevel@tonic-gate 	}
1121*0Sstevel@tonic-gate }
1122*0Sstevel@tonic-gate 
1123*0Sstevel@tonic-gate static void
1124*0Sstevel@tonic-gate Exit()
1125*0Sstevel@tonic-gate {
1126*0Sstevel@tonic-gate 	curses_off();
1127*0Sstevel@tonic-gate 	list_clear(&lwps);
1128*0Sstevel@tonic-gate 	list_clear(&users);
1129*0Sstevel@tonic-gate 	list_clear(&tasks);
1130*0Sstevel@tonic-gate 	list_clear(&projects);
1131*0Sstevel@tonic-gate 	list_clear(&zones);
1132*0Sstevel@tonic-gate 	fd_exit();
1133*0Sstevel@tonic-gate }
1134*0Sstevel@tonic-gate 
1135*0Sstevel@tonic-gate int
1136*0Sstevel@tonic-gate main(int argc, char **argv)
1137*0Sstevel@tonic-gate {
1138*0Sstevel@tonic-gate 	DIR *procdir;
1139*0Sstevel@tonic-gate 	char *p;
1140*0Sstevel@tonic-gate 	char *sortk = "cpu";	/* default sort key */
1141*0Sstevel@tonic-gate 	int opt;
1142*0Sstevel@tonic-gate 	int timeout;
1143*0Sstevel@tonic-gate 	struct pollfd pollset;
1144*0Sstevel@tonic-gate 	char key;
1145*0Sstevel@tonic-gate 
1146*0Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1147*0Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1148*0Sstevel@tonic-gate 	Progname(argv[0]);
1149*0Sstevel@tonic-gate 	lwpid_init();
1150*0Sstevel@tonic-gate 	fd_init(Setrlimit());
1151*0Sstevel@tonic-gate 
1152*0Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "vcmaRLtu:U:n:p:C:P:s:S:j:k:TJz:Z"))
1153*0Sstevel@tonic-gate 	    != (int)EOF) {
1154*0Sstevel@tonic-gate 		switch (opt) {
1155*0Sstevel@tonic-gate 		case 'R':
1156*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_REALTIME;
1157*0Sstevel@tonic-gate 			break;
1158*0Sstevel@tonic-gate 		case 'c':
1159*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_TERMCAP;
1160*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_FULLSCREEN;
1161*0Sstevel@tonic-gate 			break;
1162*0Sstevel@tonic-gate 		case 'm':
1163*0Sstevel@tonic-gate 		case 'v':
1164*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_PSINFO;
1165*0Sstevel@tonic-gate 			opts.o_outpmode |=  OPT_MSACCT;
1166*0Sstevel@tonic-gate 			break;
1167*0Sstevel@tonic-gate 		case 't':
1168*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_PSINFO;
1169*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_USERS;
1170*0Sstevel@tonic-gate 			break;
1171*0Sstevel@tonic-gate 		case 'a':
1172*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_USERS;
1173*0Sstevel@tonic-gate 			break;
1174*0Sstevel@tonic-gate 		case 'T':
1175*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_TASKS;
1176*0Sstevel@tonic-gate 			break;
1177*0Sstevel@tonic-gate 		case 'J':
1178*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_PROJECTS;
1179*0Sstevel@tonic-gate 			break;
1180*0Sstevel@tonic-gate 		case 'n':
1181*0Sstevel@tonic-gate 			p = strtok(optarg, ",");
1182*0Sstevel@tonic-gate 			opts.o_ntop = Atoi(p);
1183*0Sstevel@tonic-gate 			if (p = strtok(NULL, ","))
1184*0Sstevel@tonic-gate 				opts.o_nbottom = Atoi(p);
1185*0Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_FULLSCREEN;
1186*0Sstevel@tonic-gate 			break;
1187*0Sstevel@tonic-gate 		case 's':
1188*0Sstevel@tonic-gate 			opts.o_sortorder = -1;
1189*0Sstevel@tonic-gate 			sortk = optarg;
1190*0Sstevel@tonic-gate 			break;
1191*0Sstevel@tonic-gate 		case 'S':
1192*0Sstevel@tonic-gate 			opts.o_sortorder = 1;
1193*0Sstevel@tonic-gate 			sortk = optarg;
1194*0Sstevel@tonic-gate 			break;
1195*0Sstevel@tonic-gate 		case 'u':
1196*0Sstevel@tonic-gate 			p = strtok(optarg, ", ");
1197*0Sstevel@tonic-gate 			add_uid(&euid_tbl, p);
1198*0Sstevel@tonic-gate 			while (p = strtok(NULL, ", "))
1199*0Sstevel@tonic-gate 				add_uid(&euid_tbl, p);
1200*0Sstevel@tonic-gate 			break;
1201*0Sstevel@tonic-gate 		case 'U':
1202*0Sstevel@tonic-gate 			p = strtok(optarg, ", ");
1203*0Sstevel@tonic-gate 			add_uid(&ruid_tbl, p);
1204*0Sstevel@tonic-gate 			while (p = strtok(NULL, ", "))
1205*0Sstevel@tonic-gate 				add_uid(&ruid_tbl, p);
1206*0Sstevel@tonic-gate 			break;
1207*0Sstevel@tonic-gate 		case 'p':
1208*0Sstevel@tonic-gate 			fill_table(&pid_tbl, optarg);
1209*0Sstevel@tonic-gate 			break;
1210*0Sstevel@tonic-gate 		case 'C':
1211*0Sstevel@tonic-gate 			fill_set_table(optarg);
1212*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_PSETS;
1213*0Sstevel@tonic-gate 			break;
1214*0Sstevel@tonic-gate 		case 'P':
1215*0Sstevel@tonic-gate 			fill_table(&cpu_tbl, optarg);
1216*0Sstevel@tonic-gate 			break;
1217*0Sstevel@tonic-gate 		case 'k':
1218*0Sstevel@tonic-gate 			fill_table(&tsk_tbl, optarg);
1219*0Sstevel@tonic-gate 			break;
1220*0Sstevel@tonic-gate 		case 'j':
1221*0Sstevel@tonic-gate 			fill_prj_table(optarg);
1222*0Sstevel@tonic-gate 			break;
1223*0Sstevel@tonic-gate 		case 'L':
1224*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_LWPS;
1225*0Sstevel@tonic-gate 			break;
1226*0Sstevel@tonic-gate 		case 'z':
1227*0Sstevel@tonic-gate 			p = strtok(optarg, ", ");
1228*0Sstevel@tonic-gate 			add_zone(&zone_tbl, p);
1229*0Sstevel@tonic-gate 			while (p = strtok(NULL, ", "))
1230*0Sstevel@tonic-gate 				add_zone(&zone_tbl, p);
1231*0Sstevel@tonic-gate 			break;
1232*0Sstevel@tonic-gate 		case 'Z':
1233*0Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_ZONES;
1234*0Sstevel@tonic-gate 			break;
1235*0Sstevel@tonic-gate 		default:
1236*0Sstevel@tonic-gate 			Usage();
1237*0Sstevel@tonic-gate 		}
1238*0Sstevel@tonic-gate 	}
1239*0Sstevel@tonic-gate 
1240*0Sstevel@tonic-gate 	(void) atexit(Exit);
1241*0Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_USERS) &&
1242*0Sstevel@tonic-gate 	    !(opts.o_outpmode & OPT_SPLIT))
1243*0Sstevel@tonic-gate 		opts.o_nbottom = opts.o_ntop;
1244*0Sstevel@tonic-gate 	if (opts.o_ntop == 0 || opts.o_nbottom == 0)
1245*0Sstevel@tonic-gate 		Die(gettext("invalid argument for -n\n"));
1246*0Sstevel@tonic-gate 	if (!(opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
1247*0Sstevel@tonic-gate 	    ((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
1248*0Sstevel@tonic-gate 		Die(gettext("-t option cannot be used with -v or -m\n"));
1249*0Sstevel@tonic-gate 
1250*0Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode && OPT_USERS) &&
1251*0Sstevel@tonic-gate 	    !((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
1252*0Sstevel@tonic-gate 		Die(gettext("-t option cannot be used with "
1253*0Sstevel@tonic-gate 		    "-a, -J, -T or -Z\n"));
1254*0Sstevel@tonic-gate 
1255*0Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_USERS) &&
1256*0Sstevel@tonic-gate 	    (opts.o_outpmode & (OPT_TASKS | OPT_PROJECTS | OPT_ZONES)))
1257*0Sstevel@tonic-gate 		Die(gettext("-a option cannot be used with "
1258*0Sstevel@tonic-gate 		    "-t, -J, -T or -Z\n"));
1259*0Sstevel@tonic-gate 
1260*0Sstevel@tonic-gate 	if (((opts.o_outpmode & OPT_TASKS) &&
1261*0Sstevel@tonic-gate 	    (opts.o_outpmode & (OPT_PROJECTS|OPT_ZONES))) ||
1262*0Sstevel@tonic-gate 	    ((opts.o_outpmode & OPT_PROJECTS) &&
1263*0Sstevel@tonic-gate 	    (opts.o_outpmode & (OPT_TASKS|OPT_ZONES)))) {
1264*0Sstevel@tonic-gate 		Die(gettext("-J, -T and -Z options are mutually exclusive\n"));
1265*0Sstevel@tonic-gate 	}
1266*0Sstevel@tonic-gate 
1267*0Sstevel@tonic-gate 	if (argc > optind)
1268*0Sstevel@tonic-gate 		opts.o_interval = Atoi(argv[optind++]);
1269*0Sstevel@tonic-gate 	if (argc > optind)
1270*0Sstevel@tonic-gate 		opts.o_count = Atoi(argv[optind++]);
1271*0Sstevel@tonic-gate 	if (opts.o_count == 0)
1272*0Sstevel@tonic-gate 		Die(gettext("invalid counter value\n"));
1273*0Sstevel@tonic-gate 	if (argc > optind)
1274*0Sstevel@tonic-gate 		Usage();
1275*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_REALTIME)
1276*0Sstevel@tonic-gate 		Priocntl("RT");
1277*0Sstevel@tonic-gate 	if (isatty(STDOUT_FILENO) == 1 && isatty(STDIN_FILENO))
1278*0Sstevel@tonic-gate 		opts.o_outpmode |= OPT_TTY;	/* interactive */
1279*0Sstevel@tonic-gate 	if (!(opts.o_outpmode & OPT_TTY)) {
1280*0Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP; /* no termcap for pipes */
1281*0Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_FULLSCREEN;
1282*0Sstevel@tonic-gate 	}
1283*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP)
1284*0Sstevel@tonic-gate 		ldtermcap();		/* can turn OPT_TERMCAP off */
1285*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP)
1286*0Sstevel@tonic-gate 		(void) setsize();
1287*0Sstevel@tonic-gate 	list_alloc(&lwps, opts.o_ntop);
1288*0Sstevel@tonic-gate 	list_alloc(&users, opts.o_nbottom);
1289*0Sstevel@tonic-gate 	list_alloc(&tasks, opts.o_nbottom);
1290*0Sstevel@tonic-gate 	list_alloc(&projects, opts.o_nbottom);
1291*0Sstevel@tonic-gate 	list_alloc(&zones, opts.o_nbottom);
1292*0Sstevel@tonic-gate 	list_setkeyfunc(sortk, &opts, &lwps, LT_LWPS);
1293*0Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &users, LT_USERS);
1294*0Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &tasks, LT_TASKS);
1295*0Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &projects, LT_PROJECTS);
1296*0Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &zones, LT_ZONES);
1297*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP)
1298*0Sstevel@tonic-gate 		curses_on();
1299*0Sstevel@tonic-gate 	if ((procdir = opendir("/proc")) == NULL)
1300*0Sstevel@tonic-gate 		Die(gettext("cannot open /proc directory\n"));
1301*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY) {
1302*0Sstevel@tonic-gate 		(void) printf(gettext("Please wait...\r"));
1303*0Sstevel@tonic-gate 		(void) fflush(stdout);
1304*0Sstevel@tonic-gate 	}
1305*0Sstevel@tonic-gate 	set_signals();
1306*0Sstevel@tonic-gate 	pollset.fd = STDIN_FILENO;
1307*0Sstevel@tonic-gate 	pollset.events = POLLIN;
1308*0Sstevel@tonic-gate 	timeout = opts.o_interval * MILLISEC;
1309*0Sstevel@tonic-gate 
1310*0Sstevel@tonic-gate 	/*
1311*0Sstevel@tonic-gate 	 * main program loop
1312*0Sstevel@tonic-gate 	 */
1313*0Sstevel@tonic-gate 	do {
1314*0Sstevel@tonic-gate 		if (sigterm == 1)
1315*0Sstevel@tonic-gate 			break;
1316*0Sstevel@tonic-gate 		if (sigtstp == 1) {
1317*0Sstevel@tonic-gate 			curses_off();
1318*0Sstevel@tonic-gate 			(void) signal(SIGTSTP, SIG_DFL);
1319*0Sstevel@tonic-gate 			(void) kill(0, SIGTSTP);
1320*0Sstevel@tonic-gate 			/*
1321*0Sstevel@tonic-gate 			 * prstat stops here until it receives SIGCONT signal.
1322*0Sstevel@tonic-gate 			 */
1323*0Sstevel@tonic-gate 			sigtstp = 0;
1324*0Sstevel@tonic-gate 			(void) signal(SIGTSTP, sig_handler);
1325*0Sstevel@tonic-gate 			curses_on();
1326*0Sstevel@tonic-gate 			print_movecur = FALSE;
1327*0Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_FULLSCREEN)
1328*0Sstevel@tonic-gate 				sigwinch = 1;
1329*0Sstevel@tonic-gate 		}
1330*0Sstevel@tonic-gate 		if (sigwinch == 1) {
1331*0Sstevel@tonic-gate 			if (setsize() == 1) {
1332*0Sstevel@tonic-gate 				list_free(&lwps);
1333*0Sstevel@tonic-gate 				list_free(&users);
1334*0Sstevel@tonic-gate 				list_free(&tasks);
1335*0Sstevel@tonic-gate 				list_free(&projects);
1336*0Sstevel@tonic-gate 				list_free(&zones);
1337*0Sstevel@tonic-gate 				list_alloc(&lwps, opts.o_ntop);
1338*0Sstevel@tonic-gate 				list_alloc(&users, opts.o_nbottom);
1339*0Sstevel@tonic-gate 				list_alloc(&tasks, opts.o_nbottom);
1340*0Sstevel@tonic-gate 				list_alloc(&projects, opts.o_nbottom);
1341*0Sstevel@tonic-gate 				list_alloc(&zones, opts.o_nbottom);
1342*0Sstevel@tonic-gate 			}
1343*0Sstevel@tonic-gate 			sigwinch = 0;
1344*0Sstevel@tonic-gate 			(void) signal(SIGWINCH, sig_handler);
1345*0Sstevel@tonic-gate 		}
1346*0Sstevel@tonic-gate 		prstat_scandir(procdir);
1347*0Sstevel@tonic-gate 		list_refresh(&lwps);
1348*0Sstevel@tonic-gate 		if (print_movecur)
1349*0Sstevel@tonic-gate 			(void) putp(movecur);
1350*0Sstevel@tonic-gate 		print_movecur = TRUE;
1351*0Sstevel@tonic-gate 		if ((opts.o_outpmode & OPT_PSINFO) ||
1352*0Sstevel@tonic-gate 		    (opts.o_outpmode & OPT_MSACCT)) {
1353*0Sstevel@tonic-gate 			list_sort(&lwps);
1354*0Sstevel@tonic-gate 			list_print(&lwps);
1355*0Sstevel@tonic-gate 		}
1356*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_USERS) {
1357*0Sstevel@tonic-gate 			list_sort(&users);
1358*0Sstevel@tonic-gate 			list_print(&users);
1359*0Sstevel@tonic-gate 			list_clear(&users);
1360*0Sstevel@tonic-gate 		}
1361*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_TASKS) {
1362*0Sstevel@tonic-gate 			list_sort(&tasks);
1363*0Sstevel@tonic-gate 			list_print(&tasks);
1364*0Sstevel@tonic-gate 			list_clear(&tasks);
1365*0Sstevel@tonic-gate 		}
1366*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_PROJECTS) {
1367*0Sstevel@tonic-gate 			list_sort(&projects);
1368*0Sstevel@tonic-gate 			list_print(&projects);
1369*0Sstevel@tonic-gate 			list_clear(&projects);
1370*0Sstevel@tonic-gate 		}
1371*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_ZONES) {
1372*0Sstevel@tonic-gate 			list_sort(&zones);
1373*0Sstevel@tonic-gate 			list_print(&zones);
1374*0Sstevel@tonic-gate 			list_clear(&zones);
1375*0Sstevel@tonic-gate 		}
1376*0Sstevel@tonic-gate 		if (opts.o_count == 1)
1377*0Sstevel@tonic-gate 			break;
1378*0Sstevel@tonic-gate 		/*
1379*0Sstevel@tonic-gate 		 * If poll() returns -1 and sets errno to EINTR here because
1380*0Sstevel@tonic-gate 		 * the process received a signal, it is Ok to abort this
1381*0Sstevel@tonic-gate 		 * timeout and loop around because we check the signals at the
1382*0Sstevel@tonic-gate 		 * top of the loop.
1383*0Sstevel@tonic-gate 		 */
1384*0Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_TTY) {
1385*0Sstevel@tonic-gate 			if (poll(&pollset, (nfds_t)1, timeout) > 0) {
1386*0Sstevel@tonic-gate 				if (read(STDIN_FILENO, &key, 1) == 1) {
1387*0Sstevel@tonic-gate 					if (tolower(key) == 'q')
1388*0Sstevel@tonic-gate 						break;
1389*0Sstevel@tonic-gate 				}
1390*0Sstevel@tonic-gate 			}
1391*0Sstevel@tonic-gate 		} else {
1392*0Sstevel@tonic-gate 			(void) sleep(opts.o_interval);
1393*0Sstevel@tonic-gate 		}
1394*0Sstevel@tonic-gate 	} while (opts.o_count == (-1) || --opts.o_count);
1395*0Sstevel@tonic-gate 
1396*0Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
1397*0Sstevel@tonic-gate 		(void) putchar('\r');
1398*0Sstevel@tonic-gate 	return (0);
1399*0Sstevel@tonic-gate }
1400