xref: /titanic_50/usr/src/cmd/prstat/prstat.c (revision 4944376cd5de3dcd3b4feeaad9cbedbc024d1474)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5c6402783Sakolb  * Common Development and Distribution License (the "License").
6c6402783Sakolb  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21c6402783Sakolb 
227c478bd9Sstevel@tonic-gate /*
23*4944376cSJohn Levon  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/resource.h>
297c478bd9Sstevel@tonic-gate #include <sys/loadavg.h>
307c478bd9Sstevel@tonic-gate #include <sys/time.h>
317c478bd9Sstevel@tonic-gate #include <sys/pset.h>
320209230bSgjelinek #include <sys/vm_usage.h>
337c478bd9Sstevel@tonic-gate #include <zone.h>
347c478bd9Sstevel@tonic-gate #include <libzonecfg.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <unistd.h>
397c478bd9Sstevel@tonic-gate #include <dirent.h>
407c478bd9Sstevel@tonic-gate #include <string.h>
417c478bd9Sstevel@tonic-gate #include <errno.h>
427c478bd9Sstevel@tonic-gate #include <poll.h>
437c478bd9Sstevel@tonic-gate #include <ctype.h>
447c478bd9Sstevel@tonic-gate #include <fcntl.h>
457c478bd9Sstevel@tonic-gate #include <limits.h>
467c478bd9Sstevel@tonic-gate #include <signal.h>
477c478bd9Sstevel@tonic-gate #include <time.h>
487c478bd9Sstevel@tonic-gate #include <project.h>
497c478bd9Sstevel@tonic-gate 
50*4944376cSJohn Levon #include <langinfo.h>
517c478bd9Sstevel@tonic-gate #include <libintl.h>
527c478bd9Sstevel@tonic-gate #include <locale.h>
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #include "prstat.h"
557c478bd9Sstevel@tonic-gate #include "prutil.h"
567c478bd9Sstevel@tonic-gate #include "prtable.h"
577c478bd9Sstevel@tonic-gate #include "prsort.h"
587c478bd9Sstevel@tonic-gate #include "prfile.h"
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate  * x86 <sys/regs.h> ERR conflicts with <curses.h> ERR.  For the purposes
627c478bd9Sstevel@tonic-gate  * of this file, we care about the curses.h ERR so include that last.
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #if	defined(ERR)
667c478bd9Sstevel@tonic-gate #undef	ERR
677c478bd9Sstevel@tonic-gate #endif
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #ifndef	TEXT_DOMAIN			/* should be defined by cc -D */
707c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* use this only if it wasn't */
717c478bd9Sstevel@tonic-gate #endif
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #include <curses.h>
747c478bd9Sstevel@tonic-gate #include <term.h>
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #define	PSINFO_HEADER_PROC \
777c478bd9Sstevel@tonic-gate "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP       "
78c6402783Sakolb #define	PSINFO_HEADER_PROC_LGRP \
79c6402783Sakolb "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU LGRP PROCESS/NLWP  "
807c478bd9Sstevel@tonic-gate #define	PSINFO_HEADER_LWP \
817c478bd9Sstevel@tonic-gate "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/LWPID      "
82c6402783Sakolb #define	PSINFO_HEADER_LWP_LGRP \
83c6402783Sakolb "   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU LGRP PROCESS/LWPID "
847c478bd9Sstevel@tonic-gate #define	USAGE_HEADER_PROC \
857c478bd9Sstevel@tonic-gate "   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP  "
867c478bd9Sstevel@tonic-gate #define	USAGE_HEADER_LWP \
877c478bd9Sstevel@tonic-gate "   PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID "
887c478bd9Sstevel@tonic-gate #define	USER_HEADER_PROC \
890209230bSgjelinek " NPROC USERNAME  SWAP   RSS MEMORY      TIME  CPU                             "
907c478bd9Sstevel@tonic-gate #define	USER_HEADER_LWP \
910209230bSgjelinek "  NLWP USERNAME  SWAP   RSS MEMORY      TIME  CPU                             "
927c478bd9Sstevel@tonic-gate #define	TASK_HEADER_PROC \
930209230bSgjelinek "TASKID    NPROC  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
947c478bd9Sstevel@tonic-gate #define	TASK_HEADER_LWP \
950209230bSgjelinek "TASKID     NLWP  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
967c478bd9Sstevel@tonic-gate #define	PROJECT_HEADER_PROC \
970209230bSgjelinek "PROJID    NPROC  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
987c478bd9Sstevel@tonic-gate #define	PROJECT_HEADER_LWP \
990209230bSgjelinek "PROJID     NLWP  SWAP   RSS MEMORY      TIME  CPU PROJECT                     "
1007c478bd9Sstevel@tonic-gate #define	ZONE_HEADER_PROC \
1010209230bSgjelinek "ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE                        "
1027c478bd9Sstevel@tonic-gate #define	ZONE_HEADER_LWP \
1030209230bSgjelinek "ZONEID     NLWP  SWAP   RSS MEMORY      TIME  CPU ZONE                        "
1047c478bd9Sstevel@tonic-gate #define	PSINFO_LINE \
1057c478bd9Sstevel@tonic-gate "%6d %-8s %5s %5s %-6s %3s  %3s %9s %3.3s%% %-.16s/%d"
106c6402783Sakolb #define	PSINFO_LINE_LGRP \
107c6402783Sakolb "%6d %-8s %5s %5s %-6s %3s  %3s %9s %3.3s%% %4d %-.16s/%d"
1087c478bd9Sstevel@tonic-gate #define	USAGE_LINE \
1097c478bd9Sstevel@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 "\
1107c478bd9Sstevel@tonic-gate "%3.3s %-.12s/%d"
1117c478bd9Sstevel@tonic-gate #define	USER_LINE \
1127c478bd9Sstevel@tonic-gate "%6d %-8s %5.5s %5.5s   %3.3s%% %9s %3.3s%%"
1137c478bd9Sstevel@tonic-gate #define	TASK_LINE \
1147c478bd9Sstevel@tonic-gate "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
1157c478bd9Sstevel@tonic-gate #define	PROJECT_LINE \
1167c478bd9Sstevel@tonic-gate "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
1177c478bd9Sstevel@tonic-gate #define	ZONE_LINE \
1187c478bd9Sstevel@tonic-gate "%6d %8d %5s %5s   %3.3s%% %9s %3.3s%% %28s"
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate #define	TOTAL_LINE \
1217c478bd9Sstevel@tonic-gate "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f"
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /* global variables */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate static char	*t_ulon;			/* termcap: start underline */
1267c478bd9Sstevel@tonic-gate static char	*t_uloff;			/* termcap: end underline */
1277c478bd9Sstevel@tonic-gate static char	*t_up;				/* termcap: cursor 1 line up */
1287c478bd9Sstevel@tonic-gate static char	*t_eol;				/* termcap: clear end of line */
1297c478bd9Sstevel@tonic-gate static char	*t_smcup;			/* termcap: cursor mvcap on */
1307c478bd9Sstevel@tonic-gate static char	*t_rmcup;			/* termcap: cursor mvcap off */
1317c478bd9Sstevel@tonic-gate static char	*t_home;			/* termcap: move cursor home */
1327c478bd9Sstevel@tonic-gate static char	*movecur = NULL;		/* termcap: move up string */
1337c478bd9Sstevel@tonic-gate static char	*empty_string = "\0";		/* termcap: empty string */
1347c478bd9Sstevel@tonic-gate static uint_t	print_movecur = FALSE;		/* print movecur or not */
1357c478bd9Sstevel@tonic-gate static int	is_curses_on = FALSE;		/* current curses state */
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate static table_t	pid_tbl = {0, 0, NULL};		/* selected processes */
1387c478bd9Sstevel@tonic-gate static table_t	cpu_tbl = {0, 0, NULL};		/* selected processors */
1397c478bd9Sstevel@tonic-gate static table_t  set_tbl = {0, 0, NULL};		/* selected processor sets */
1407c478bd9Sstevel@tonic-gate static table_t	prj_tbl = {0, 0, NULL};		/* selected projects */
1417c478bd9Sstevel@tonic-gate static table_t	tsk_tbl = {0, 0, NULL};		/* selected tasks */
142c6402783Sakolb static table_t	lgr_tbl = {0, 0, NULL};		/* selected lgroups */
1437c478bd9Sstevel@tonic-gate static zonetbl_t zone_tbl = {0, 0, NULL};	/* selected zones */
1447c478bd9Sstevel@tonic-gate static nametbl_t euid_tbl = {0, 0, NULL}; 	/* selected effective users */
1457c478bd9Sstevel@tonic-gate static nametbl_t ruid_tbl = {0, 0, NULL}; 	/* selected real users */
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate static uint_t	total_procs;			/* total number of procs */
1487c478bd9Sstevel@tonic-gate static uint_t	total_lwps;			/* total number of lwps */
1497c478bd9Sstevel@tonic-gate static float	total_cpu;			/* total cpu usage */
1507c478bd9Sstevel@tonic-gate static float	total_mem;			/* total memory usage */
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate static list_t	lwps;				/* list of lwps/processes */
1537c478bd9Sstevel@tonic-gate static list_t	users;				/* list of users */
1547c478bd9Sstevel@tonic-gate static list_t	tasks;				/* list of tasks */
1557c478bd9Sstevel@tonic-gate static list_t	projects;			/* list of projects */
1567c478bd9Sstevel@tonic-gate static list_t	zones;				/* list of zones */
157c6402783Sakolb static list_t	lgroups;			/* list of lgroups */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate static volatile uint_t sigwinch = 0;
1607c478bd9Sstevel@tonic-gate static volatile uint_t sigtstp = 0;
1617c478bd9Sstevel@tonic-gate static volatile uint_t sigterm = 0;
1627c478bd9Sstevel@tonic-gate 
1630209230bSgjelinek static long pagesize;
1640209230bSgjelinek 
1657c478bd9Sstevel@tonic-gate /* default settings */
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate static optdesc_t opts = {
1687c478bd9Sstevel@tonic-gate 	5,			/* interval between updates, seconds */
1697c478bd9Sstevel@tonic-gate 	15,			/* number of lines in top part */
1707c478bd9Sstevel@tonic-gate 	5,			/* number of lines in bottom part */
1717c478bd9Sstevel@tonic-gate 	-1,			/* number of iterations; infinitely */
1727c478bd9Sstevel@tonic-gate 	OPT_PSINFO | OPT_FULLSCREEN | OPT_USEHOME | OPT_TERMCAP,
1737c478bd9Sstevel@tonic-gate 	-1			/* sort in decreasing order */
1747c478bd9Sstevel@tonic-gate };
1757c478bd9Sstevel@tonic-gate 
176*4944376cSJohn Levon /*
177*4944376cSJohn Levon  * Print timestamp as decimal reprentation of time_t value (-d u was specified)
178*4944376cSJohn Levon  * or the standard date format (-d d was specified).
179*4944376cSJohn Levon  */
180*4944376cSJohn Levon static void
181*4944376cSJohn Levon print_timestamp(void)
182*4944376cSJohn Levon {
183*4944376cSJohn Levon 	time_t t = time(NULL);
184*4944376cSJohn Levon 	static char *fmt = NULL;
185*4944376cSJohn Levon 
186*4944376cSJohn Levon 	/* We only need to retrieve this once per invocation */
187*4944376cSJohn Levon 	if (fmt == NULL)
188*4944376cSJohn Levon 		fmt = nl_langinfo(_DATE_FMT);
189*4944376cSJohn Levon 
190*4944376cSJohn Levon 	if (opts.o_outpmode & OPT_UDATE) {
191*4944376cSJohn Levon 		(void) printf("%ld", t);
192*4944376cSJohn Levon 	} else if (opts.o_outpmode & OPT_DDATE) {
193*4944376cSJohn Levon 		char dstr[64];
194*4944376cSJohn Levon 		int len;
195*4944376cSJohn Levon 
196*4944376cSJohn Levon 		len = strftime(dstr, sizeof (dstr), fmt, localtime(&t));
197*4944376cSJohn Levon 		if (len > 0)
198*4944376cSJohn Levon 			(void) printf("%s", dstr);
199*4944376cSJohn Levon 	}
200*4944376cSJohn Levon 	(void) putp(t_eol);
201*4944376cSJohn Levon 	(void) putchar('\n');
202*4944376cSJohn Levon }
203*4944376cSJohn Levon 
2047c478bd9Sstevel@tonic-gate static void
2057c478bd9Sstevel@tonic-gate psetloadavg(long psetid, void *ptr)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate 	double psetloadavg[3];
2087c478bd9Sstevel@tonic-gate 	double *loadavg = ptr;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	if (pset_getloadavg((psetid_t)psetid, psetloadavg, 3) != -1) {
2117c478bd9Sstevel@tonic-gate 		*loadavg++ += psetloadavg[0];
2127c478bd9Sstevel@tonic-gate 		*loadavg++ += psetloadavg[1];
2137c478bd9Sstevel@tonic-gate 		*loadavg += psetloadavg[2];
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate /*
2180209230bSgjelinek  * Queries the memory virtual and rss size for each member of a list.
2190209230bSgjelinek  * This will override the values computed by /proc aggregation.
2200209230bSgjelinek  */
2210209230bSgjelinek static void
2220209230bSgjelinek list_getsize(list_t *list)
2230209230bSgjelinek {
2240209230bSgjelinek 	id_info_t *id;
2250209230bSgjelinek 	vmusage_t *results, *next;
2260209230bSgjelinek 	vmusage_t *match;
2270209230bSgjelinek 	size_t nres = 0;
2280209230bSgjelinek 	size_t i;
2290209230bSgjelinek 	uint_t flags = 0;
2300209230bSgjelinek 	int ret;
2310209230bSgjelinek 	size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize;
2320209230bSgjelinek 
2330209230bSgjelinek 	/*
2340209230bSgjelinek 	 * Determine what swap/rss results to calculate.  getvmusage() will
2350209230bSgjelinek 	 * prune results returned to non-global zones automatically, so
2360209230bSgjelinek 	 * there is no need to pass different flags when calling from a
2370209230bSgjelinek 	 * non-global zone.
2380209230bSgjelinek 	 *
2390209230bSgjelinek 	 * Currently list_getsize() is only called with a single flag.  This
2400209230bSgjelinek 	 * is because -Z, -J, -T, and -a are mutually exclusive.  Regardless
2410209230bSgjelinek 	 * of this, we handle multiple flags.
2420209230bSgjelinek 	 */
2430209230bSgjelinek 	if (opts.o_outpmode & OPT_USERS) {
2440209230bSgjelinek 		/*
2450209230bSgjelinek 		 * Gather rss for all users in all zones.  Treat the same
2460209230bSgjelinek 		 * uid in different zones as the same user.
2470209230bSgjelinek 		 */
2480209230bSgjelinek 		flags |= VMUSAGE_COL_RUSERS;
2490209230bSgjelinek 
2500209230bSgjelinek 	} else if (opts.o_outpmode & OPT_TASKS) {
2510209230bSgjelinek 		/* Gather rss for all tasks in all zones */
2520209230bSgjelinek 		flags |= VMUSAGE_ALL_TASKS;
2530209230bSgjelinek 
2540209230bSgjelinek 	} else if (opts.o_outpmode & OPT_PROJECTS) {
2550209230bSgjelinek 		/*
2560209230bSgjelinek 		 * Gather rss for all projects in all zones.  Treat the same
2570209230bSgjelinek 		 * projid in diffrent zones as the same project.
2580209230bSgjelinek 		 */
2590209230bSgjelinek 		flags |= VMUSAGE_COL_PROJECTS;
2600209230bSgjelinek 
2610209230bSgjelinek 	} else if (opts.o_outpmode & OPT_ZONES) {
2620209230bSgjelinek 		/* Gather rss for all zones */
2630209230bSgjelinek 		flags |= VMUSAGE_ALL_ZONES;
2640209230bSgjelinek 
2650209230bSgjelinek 	} else {
2660209230bSgjelinek 		Die(gettext(
2670209230bSgjelinek 		    "Cannot determine rss flags for output options %x\n"),
2680209230bSgjelinek 		    opts.o_outpmode);
2690209230bSgjelinek 	}
2700209230bSgjelinek 
2710209230bSgjelinek 	/*
2720209230bSgjelinek 	 * getvmusage() returns an array of result structures.  One for
2730209230bSgjelinek 	 * each zone, project, task, or user on the system, depending on
2740209230bSgjelinek 	 * flags.
2750209230bSgjelinek 	 *
2760209230bSgjelinek 	 * If getvmusage() fails, prstat will use the size already gathered
2770209230bSgjelinek 	 * from psinfo
2780209230bSgjelinek 	 */
2790209230bSgjelinek 	if (getvmusage(flags, opts.o_interval, NULL, &nres) != 0)
2800209230bSgjelinek 		return;
2810209230bSgjelinek 
2820209230bSgjelinek 	results = (vmusage_t *)Malloc(sizeof (vmusage_t) * nres);
2830209230bSgjelinek 	for (;;) {
2840209230bSgjelinek 		ret = getvmusage(flags, opts.o_interval, results, &nres);
2850209230bSgjelinek 		if (ret == 0)
2860209230bSgjelinek 			break;
2870209230bSgjelinek 		if (errno == EOVERFLOW) {
2880209230bSgjelinek 			results = (vmusage_t *)Realloc(results,
2890209230bSgjelinek 			    sizeof (vmusage_t) * nres);
2900209230bSgjelinek 			continue;
2910209230bSgjelinek 		}
2920209230bSgjelinek 		/*
2930209230bSgjelinek 		 * Failure for some other reason.  Prstat will use the size
2940209230bSgjelinek 		 * already gathered from psinfo.
2950209230bSgjelinek 		 */
2960209230bSgjelinek 		return;
2970209230bSgjelinek 	}
2980209230bSgjelinek 	for (id = list->l_head; id != NULL; id = id->id_next) {
2990209230bSgjelinek 
3000209230bSgjelinek 		match = NULL;
3010209230bSgjelinek 		next = results;
3020209230bSgjelinek 		for (i = 0; i < nres; i++, next++) {
3030209230bSgjelinek 			switch (flags) {
3040209230bSgjelinek 			case VMUSAGE_COL_RUSERS:
3050209230bSgjelinek 				if (next->vmu_id == id->id_uid)
3060209230bSgjelinek 					match = next;
3070209230bSgjelinek 				break;
3080209230bSgjelinek 			case VMUSAGE_ALL_TASKS:
3090209230bSgjelinek 				if (next->vmu_id == id->id_taskid)
3100209230bSgjelinek 					match = next;
3110209230bSgjelinek 				break;
3120209230bSgjelinek 			case VMUSAGE_COL_PROJECTS:
3130209230bSgjelinek 				if (next->vmu_id == id->id_projid)
3140209230bSgjelinek 					match = next;
3150209230bSgjelinek 				break;
3160209230bSgjelinek 			case VMUSAGE_ALL_ZONES:
3170209230bSgjelinek 				if (next->vmu_id == id->id_zoneid)
3180209230bSgjelinek 					match = next;
3190209230bSgjelinek 				break;
3200209230bSgjelinek 			default:
3210209230bSgjelinek 				Die(gettext(
3220209230bSgjelinek 				    "Unknown vmusage flags %d\n"), flags);
3230209230bSgjelinek 			}
3240209230bSgjelinek 		}
3250209230bSgjelinek 		if (match != NULL) {
3260209230bSgjelinek 			id->id_size = match->vmu_swap_all / 1024;
3270209230bSgjelinek 			id->id_rssize = match->vmu_rss_all / 1024;
3280209230bSgjelinek 			id->id_pctmem = (100.0 * (float)match->vmu_rss_all) /
3290209230bSgjelinek 			    (float)physmem;
3300209230bSgjelinek 			/* Output using data from getvmusage() */
3310209230bSgjelinek 			id->id_sizematch = B_TRUE;
3320209230bSgjelinek 		}
3330209230bSgjelinek 		/*
3340209230bSgjelinek 		 * If no match is found, prstat will use the size already
3350209230bSgjelinek 		 * gathered from psinfo.
3360209230bSgjelinek 		 */
3370209230bSgjelinek 	}
3380209230bSgjelinek }
3390209230bSgjelinek 
3400209230bSgjelinek /*
3417c478bd9Sstevel@tonic-gate  * A routine to display the contents of the list on the screen
3427c478bd9Sstevel@tonic-gate  */
3437c478bd9Sstevel@tonic-gate static void
3447c478bd9Sstevel@tonic-gate list_print(list_t *list)
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	lwp_info_t *lwp;
3477c478bd9Sstevel@tonic-gate 	id_info_t *id;
3487c478bd9Sstevel@tonic-gate 	char usr[4], sys[4], trp[4], tfl[4];
3497c478bd9Sstevel@tonic-gate 	char dfl[4], lck[4], slp[4], lat[4];
3507c478bd9Sstevel@tonic-gate 	char vcx[4], icx[4], scl[4], sig[4];
3517c478bd9Sstevel@tonic-gate 	char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12];
3527c478bd9Sstevel@tonic-gate 	char pstate[7], pnice[4], ppri[4];
3537c478bd9Sstevel@tonic-gate 	char pname[LOGNAME_MAX+1];
3547c478bd9Sstevel@tonic-gate 	char projname[PROJNAME_MAX+1];
3557c478bd9Sstevel@tonic-gate 	char zonename[ZONENAME_MAX+1];
3567c478bd9Sstevel@tonic-gate 	float cpu, mem;
3577c478bd9Sstevel@tonic-gate 	double loadavg[3] = {0, 0, 0};
3587c478bd9Sstevel@tonic-gate 	int i, lwpid;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (foreach_element(&set_tbl, &loadavg, psetloadavg) == 0) {
3617c478bd9Sstevel@tonic-gate 		/*
3627c478bd9Sstevel@tonic-gate 		 * If processor sets aren't specified, we display system-wide
3637c478bd9Sstevel@tonic-gate 		 * load averages.
3647c478bd9Sstevel@tonic-gate 		 */
3657c478bd9Sstevel@tonic-gate 		(void) getloadavg(loadavg, 3);
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
368*4944376cSJohn Levon 	if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)) &&
369*4944376cSJohn Levon 	    ((list->l_type == LT_LWPS) || !(opts.o_outpmode & OPT_SPLIT)))
370*4944376cSJohn Levon 		print_timestamp();
3717c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
3727c478bd9Sstevel@tonic-gate 		(void) putchar('\r');
3737c478bd9Sstevel@tonic-gate 	(void) putp(t_ulon);
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	switch (list->l_type) {
3767c478bd9Sstevel@tonic-gate 	case LT_PROJECTS:
3777c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
3787c478bd9Sstevel@tonic-gate 			(void) printf(PROJECT_HEADER_LWP);
3797c478bd9Sstevel@tonic-gate 		else
3807c478bd9Sstevel@tonic-gate 			(void) printf(PROJECT_HEADER_PROC);
3817c478bd9Sstevel@tonic-gate 		break;
3827c478bd9Sstevel@tonic-gate 	case LT_TASKS:
3837c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
3847c478bd9Sstevel@tonic-gate 			(void) printf(TASK_HEADER_LWP);
3857c478bd9Sstevel@tonic-gate 		else
3867c478bd9Sstevel@tonic-gate 			(void) printf(TASK_HEADER_PROC);
3877c478bd9Sstevel@tonic-gate 		break;
3887c478bd9Sstevel@tonic-gate 	case LT_ZONES:
3897c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
3907c478bd9Sstevel@tonic-gate 			(void) printf(ZONE_HEADER_LWP);
3917c478bd9Sstevel@tonic-gate 		else
3927c478bd9Sstevel@tonic-gate 			(void) printf(ZONE_HEADER_PROC);
3937c478bd9Sstevel@tonic-gate 		break;
3947c478bd9Sstevel@tonic-gate 	case LT_USERS:
3957c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
3967c478bd9Sstevel@tonic-gate 			(void) printf(USER_HEADER_LWP);
3977c478bd9Sstevel@tonic-gate 		else
3987c478bd9Sstevel@tonic-gate 			(void) printf(USER_HEADER_PROC);
3997c478bd9Sstevel@tonic-gate 		break;
4007c478bd9Sstevel@tonic-gate 	case LT_LWPS:
4017c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS) {
402c6402783Sakolb 			if (opts.o_outpmode & OPT_PSINFO) {
403c6402783Sakolb 				if (opts.o_outpmode & OPT_LGRP)
404c6402783Sakolb 					(void) printf(PSINFO_HEADER_LWP_LGRP);
405c6402783Sakolb 				else
4067c478bd9Sstevel@tonic-gate 					(void) printf(PSINFO_HEADER_LWP);
407c6402783Sakolb 			}
4087c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_MSACCT)
4097c478bd9Sstevel@tonic-gate 				(void) printf(USAGE_HEADER_LWP);
4107c478bd9Sstevel@tonic-gate 		} else {
411c6402783Sakolb 			if (opts.o_outpmode & OPT_PSINFO) {
412c6402783Sakolb 				if (opts.o_outpmode & OPT_LGRP)
413c6402783Sakolb 					(void) printf(PSINFO_HEADER_PROC_LGRP);
414c6402783Sakolb 				else
4157c478bd9Sstevel@tonic-gate 					(void) printf(PSINFO_HEADER_PROC);
416c6402783Sakolb 			}
4177c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_MSACCT)
4187c478bd9Sstevel@tonic-gate 				(void) printf(USAGE_HEADER_PROC);
4197c478bd9Sstevel@tonic-gate 		}
4207c478bd9Sstevel@tonic-gate 		break;
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	(void) putp(t_uloff);
4247c478bd9Sstevel@tonic-gate 	(void) putp(t_eol);
4257c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	for (i = 0; i < list->l_used; i++) {
4287c478bd9Sstevel@tonic-gate 		switch (list->l_type) {
4297c478bd9Sstevel@tonic-gate 		case LT_PROJECTS:
4307c478bd9Sstevel@tonic-gate 		case LT_TASKS:
4317c478bd9Sstevel@tonic-gate 		case LT_USERS:
4327c478bd9Sstevel@tonic-gate 		case LT_ZONES:
4337c478bd9Sstevel@tonic-gate 			id = list->l_ptrs[i];
4347c478bd9Sstevel@tonic-gate 			/*
4357c478bd9Sstevel@tonic-gate 			 * CPU usage and memory usage normalization
4367c478bd9Sstevel@tonic-gate 			 */
4377c478bd9Sstevel@tonic-gate 			if (total_cpu >= 100)
4387c478bd9Sstevel@tonic-gate 				cpu = (100 * id->id_pctcpu) / total_cpu;
4397c478bd9Sstevel@tonic-gate 			else
4407c478bd9Sstevel@tonic-gate 				cpu = id->id_pctcpu;
4410209230bSgjelinek 			if (id->id_sizematch == B_FALSE && total_mem >= 100)
4427c478bd9Sstevel@tonic-gate 				mem = (100 * id->id_pctmem) / total_mem;
4437c478bd9Sstevel@tonic-gate 			else
4447c478bd9Sstevel@tonic-gate 				mem = id->id_pctmem;
4457c478bd9Sstevel@tonic-gate 			if (list->l_type == LT_USERS)
4467c478bd9Sstevel@tonic-gate 				pwd_getname(id->id_uid, pname, LOGNAME_MAX + 1);
4477c478bd9Sstevel@tonic-gate 			else if (list->l_type == LT_ZONES)
4487c478bd9Sstevel@tonic-gate 				getzonename(id->id_zoneid, zonename,
4497c478bd9Sstevel@tonic-gate 				    ZONENAME_MAX);
4507c478bd9Sstevel@tonic-gate 			else
4517c478bd9Sstevel@tonic-gate 				getprojname(id->id_projid, projname,
4527c478bd9Sstevel@tonic-gate 				    PROJNAME_MAX);
4537c478bd9Sstevel@tonic-gate 			Format_size(psize, id->id_size, 6);
4547c478bd9Sstevel@tonic-gate 			Format_size(prssize, id->id_rssize, 6);
4557c478bd9Sstevel@tonic-gate 			Format_pct(pmem, mem, 4);
4567c478bd9Sstevel@tonic-gate 			Format_pct(pcpu, cpu, 4);
4577c478bd9Sstevel@tonic-gate 			Format_time(ptime, id->id_time, 10);
4587c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_TTY)
4597c478bd9Sstevel@tonic-gate 				(void) putchar('\r');
4607c478bd9Sstevel@tonic-gate 			if (list->l_type == LT_PROJECTS)
4617c478bd9Sstevel@tonic-gate 				(void) printf(PROJECT_LINE, (int)id->id_projid,
4627c478bd9Sstevel@tonic-gate 				    id->id_nproc, psize, prssize, pmem, ptime,
4637c478bd9Sstevel@tonic-gate 				    pcpu, projname);
4647c478bd9Sstevel@tonic-gate 			else if (list->l_type == LT_TASKS)
4657c478bd9Sstevel@tonic-gate 				(void) printf(TASK_LINE, (int)id->id_taskid,
4667c478bd9Sstevel@tonic-gate 				    id->id_nproc, psize, prssize, pmem, ptime,
4677c478bd9Sstevel@tonic-gate 				    pcpu, projname);
4687c478bd9Sstevel@tonic-gate 			else if (list->l_type == LT_ZONES)
4697c478bd9Sstevel@tonic-gate 				(void) printf(ZONE_LINE, (int)id->id_zoneid,
4707c478bd9Sstevel@tonic-gate 				    id->id_nproc, psize, prssize, pmem, ptime,
4717c478bd9Sstevel@tonic-gate 				    pcpu, zonename);
4727c478bd9Sstevel@tonic-gate 			else
4737c478bd9Sstevel@tonic-gate 				(void) printf(USER_LINE, id->id_nproc, pname,
4747c478bd9Sstevel@tonic-gate 				    psize, prssize, pmem, ptime, pcpu);
4757c478bd9Sstevel@tonic-gate 			(void) putp(t_eol);
4767c478bd9Sstevel@tonic-gate 			(void) putchar('\n');
4777c478bd9Sstevel@tonic-gate 			break;
4787c478bd9Sstevel@tonic-gate 		case LT_LWPS:
4797c478bd9Sstevel@tonic-gate 			lwp = list->l_ptrs[i];
4807c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_LWPS)
4817c478bd9Sstevel@tonic-gate 				lwpid = lwp->li_info.pr_lwp.pr_lwpid;
4827c478bd9Sstevel@tonic-gate 			else
4837c478bd9Sstevel@tonic-gate 				lwpid = lwp->li_info.pr_nlwp +
4847c478bd9Sstevel@tonic-gate 				    lwp->li_info.pr_nzomb;
4857c478bd9Sstevel@tonic-gate 			pwd_getname(lwp->li_info.pr_uid, pname,
4867c478bd9Sstevel@tonic-gate 			    LOGNAME_MAX + 1);
4877c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_PSINFO) {
4887c478bd9Sstevel@tonic-gate 				Format_size(psize, lwp->li_info.pr_size, 6);
4897c478bd9Sstevel@tonic-gate 				Format_size(prssize, lwp->li_info.pr_rssize, 6);
4907c478bd9Sstevel@tonic-gate 				Format_state(pstate,
4917c478bd9Sstevel@tonic-gate 				    lwp->li_info.pr_lwp.pr_sname,
4927c478bd9Sstevel@tonic-gate 				    lwp->li_info.pr_lwp.pr_onpro, 7);
4937c478bd9Sstevel@tonic-gate 				if (strcmp(lwp->li_info.pr_lwp.pr_clname,
4947c478bd9Sstevel@tonic-gate 				    "RT") == 0 ||
4957c478bd9Sstevel@tonic-gate 				    strcmp(lwp->li_info.pr_lwp.pr_clname,
4967c478bd9Sstevel@tonic-gate 				    "SYS") == 0 ||
4977c478bd9Sstevel@tonic-gate 				    lwp->li_info.pr_lwp.pr_sname == 'Z')
4987c478bd9Sstevel@tonic-gate 					(void) strcpy(pnice, "  -");
4997c478bd9Sstevel@tonic-gate 				else
5007c478bd9Sstevel@tonic-gate 					Format_num(pnice,
5017c478bd9Sstevel@tonic-gate 					    lwp->li_info.pr_lwp.pr_nice - NZERO,
5027c478bd9Sstevel@tonic-gate 					    4);
5037c478bd9Sstevel@tonic-gate 				Format_num(ppri, lwp->li_info.pr_lwp.pr_pri, 4);
5047c478bd9Sstevel@tonic-gate 				Format_pct(pcpu,
5057c478bd9Sstevel@tonic-gate 				    FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu), 4);
5067c478bd9Sstevel@tonic-gate 				if (opts.o_outpmode & OPT_LWPS)
5077c478bd9Sstevel@tonic-gate 					Format_time(ptime,
5087c478bd9Sstevel@tonic-gate 					    lwp->li_info.pr_lwp.pr_time.tv_sec,
5097c478bd9Sstevel@tonic-gate 					    10);
5107c478bd9Sstevel@tonic-gate 				else
5117c478bd9Sstevel@tonic-gate 					Format_time(ptime,
5127c478bd9Sstevel@tonic-gate 					    lwp->li_info.pr_time.tv_sec, 10);
5137c478bd9Sstevel@tonic-gate 				if (opts.o_outpmode & OPT_TTY)
5147c478bd9Sstevel@tonic-gate 					(void) putchar('\r');
5157c478bd9Sstevel@tonic-gate 				stripfname(lwp->li_info.pr_fname);
516c6402783Sakolb 				if (opts.o_outpmode & OPT_LGRP) {
517c6402783Sakolb 					(void) printf(PSINFO_LINE_LGRP,
518c6402783Sakolb 					    (int)lwp->li_info.pr_pid, pname,
519c6402783Sakolb 					    psize, prssize, pstate, ppri, pnice,
520c6402783Sakolb 					    ptime, pcpu,
521c6402783Sakolb 					    (int)lwp->li_info.pr_lwp.pr_lgrp,
522c6402783Sakolb 					    lwp->li_info.pr_fname, lwpid);
523c6402783Sakolb 				} else {
5247c478bd9Sstevel@tonic-gate 					(void) printf(PSINFO_LINE,
5257c478bd9Sstevel@tonic-gate 					    (int)lwp->li_info.pr_pid, pname,
5267c478bd9Sstevel@tonic-gate 					    psize, prssize, pstate, ppri, pnice,
527c6402783Sakolb 					    ptime, pcpu,
528c6402783Sakolb 					    lwp->li_info.pr_fname, lwpid);
529c6402783Sakolb 				}
5307c478bd9Sstevel@tonic-gate 				(void) putp(t_eol);
5317c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
5327c478bd9Sstevel@tonic-gate 			}
5337c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_MSACCT) {
5347c478bd9Sstevel@tonic-gate 				Format_pct(usr, lwp->li_usr, 4);
5357c478bd9Sstevel@tonic-gate 				Format_pct(sys, lwp->li_sys, 4);
5367c478bd9Sstevel@tonic-gate 				Format_pct(slp, lwp->li_slp, 4);
5377c478bd9Sstevel@tonic-gate 				Format_num(vcx, lwp->li_vcx, 4);
5387c478bd9Sstevel@tonic-gate 				Format_num(icx, lwp->li_icx, 4);
5397c478bd9Sstevel@tonic-gate 				Format_num(scl, lwp->li_scl, 4);
5407c478bd9Sstevel@tonic-gate 				Format_num(sig, lwp->li_sig, 4);
5417c478bd9Sstevel@tonic-gate 				Format_pct(trp, lwp->li_trp, 4);
5427c478bd9Sstevel@tonic-gate 				Format_pct(tfl, lwp->li_tfl, 4);
5437c478bd9Sstevel@tonic-gate 				Format_pct(dfl, lwp->li_dfl, 4);
5447c478bd9Sstevel@tonic-gate 				Format_pct(lck, lwp->li_lck, 4);
5457c478bd9Sstevel@tonic-gate 				Format_pct(lat, lwp->li_lat, 4);
5467c478bd9Sstevel@tonic-gate 				if (opts.o_outpmode & OPT_TTY)
5477c478bd9Sstevel@tonic-gate 					(void) putchar('\r');
5487c478bd9Sstevel@tonic-gate 				stripfname(lwp->li_info.pr_fname);
5497c478bd9Sstevel@tonic-gate 				(void) printf(USAGE_LINE,
5507c478bd9Sstevel@tonic-gate 				    (int)lwp->li_info.pr_pid, pname,
5517c478bd9Sstevel@tonic-gate 				    usr, sys, trp, tfl, dfl, lck,
5527c478bd9Sstevel@tonic-gate 				    slp, lat, vcx, icx, scl, sig,
5537c478bd9Sstevel@tonic-gate 				    lwp->li_info.pr_fname, lwpid);
5547c478bd9Sstevel@tonic-gate 				(void) putp(t_eol);
5557c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
5567c478bd9Sstevel@tonic-gate 			}
5577c478bd9Sstevel@tonic-gate 			break;
5587c478bd9Sstevel@tonic-gate 		}
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
5627c478bd9Sstevel@tonic-gate 		(void) putchar('\r');
5637c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP) {
5647c478bd9Sstevel@tonic-gate 		switch (list->l_type) {
5657c478bd9Sstevel@tonic-gate 		case LT_PROJECTS:
5667c478bd9Sstevel@tonic-gate 		case LT_USERS:
5677c478bd9Sstevel@tonic-gate 		case LT_TASKS:
5687c478bd9Sstevel@tonic-gate 		case LT_ZONES:
5697c478bd9Sstevel@tonic-gate 			while (i++ < opts.o_nbottom) {
5707c478bd9Sstevel@tonic-gate 				(void) putp(t_eol);
5717c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
5727c478bd9Sstevel@tonic-gate 			}
5737c478bd9Sstevel@tonic-gate 			break;
5747c478bd9Sstevel@tonic-gate 		case LT_LWPS:
5757c478bd9Sstevel@tonic-gate 			while (i++ < opts.o_ntop) {
5767c478bd9Sstevel@tonic-gate 				(void) putp(t_eol);
5777c478bd9Sstevel@tonic-gate 				(void) putchar('\n');
5787c478bd9Sstevel@tonic-gate 			}
5797c478bd9Sstevel@tonic-gate 		}
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
5837c478bd9Sstevel@tonic-gate 		(void) putchar('\r');
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_SPLIT) && list->l_type == LT_LWPS)
5867c478bd9Sstevel@tonic-gate 		return;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	(void) printf(TOTAL_LINE, total_procs, total_lwps,
5897c478bd9Sstevel@tonic-gate 	    loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
5907c478bd9Sstevel@tonic-gate 	    loadavg[LOADAVG_15MIN]);
5917c478bd9Sstevel@tonic-gate 	(void) putp(t_eol);
5927c478bd9Sstevel@tonic-gate 	(void) putchar('\n');
5937c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
5947c478bd9Sstevel@tonic-gate 		(void) putchar('\r');
5957c478bd9Sstevel@tonic-gate 	(void) putp(t_eol);
5967c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate static lwp_info_t *
6007c478bd9Sstevel@tonic-gate list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate 	lwp_info_t *lwp;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	if (list->l_head == NULL) {
6057c478bd9Sstevel@tonic-gate 		list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
6067c478bd9Sstevel@tonic-gate 	} else {
6077c478bd9Sstevel@tonic-gate 		lwp = Zalloc(sizeof (lwp_info_t));
6087c478bd9Sstevel@tonic-gate 		lwp->li_prev = list->l_tail;
6097c478bd9Sstevel@tonic-gate 		((lwp_info_t *)list->l_tail)->li_next = lwp;
6107c478bd9Sstevel@tonic-gate 		list->l_tail = lwp;
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 	lwp->li_info.pr_pid = pid;
6137c478bd9Sstevel@tonic-gate 	lwp->li_info.pr_lwp.pr_lwpid = lwpid;
6147c478bd9Sstevel@tonic-gate 	lwpid_add(lwp, pid, lwpid);
6157c478bd9Sstevel@tonic-gate 	list->l_count++;
6167c478bd9Sstevel@tonic-gate 	return (lwp);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate static void
6207c478bd9Sstevel@tonic-gate list_remove_lwp(list_t *list, lwp_info_t *lwp)
6217c478bd9Sstevel@tonic-gate {
6227c478bd9Sstevel@tonic-gate 	if (lwp->li_prev)
6237c478bd9Sstevel@tonic-gate 		lwp->li_prev->li_next = lwp->li_next;
6247c478bd9Sstevel@tonic-gate 	else
6257c478bd9Sstevel@tonic-gate 		list->l_head = lwp->li_next;	/* removing the head */
6267c478bd9Sstevel@tonic-gate 	if (lwp->li_next)
6277c478bd9Sstevel@tonic-gate 		lwp->li_next->li_prev = lwp->li_prev;
6287c478bd9Sstevel@tonic-gate 	else
6297c478bd9Sstevel@tonic-gate 		list->l_tail = lwp->li_prev;	/* removing the tail */
6307c478bd9Sstevel@tonic-gate 	lwpid_del(lwp->li_info.pr_pid, lwp->li_info.pr_lwp.pr_lwpid);
6317c478bd9Sstevel@tonic-gate 	if (lwpid_pidcheck(lwp->li_info.pr_pid) == 0)
6327c478bd9Sstevel@tonic-gate 		fds_rm(lwp->li_info.pr_pid);
6337c478bd9Sstevel@tonic-gate 	list->l_count--;
6347c478bd9Sstevel@tonic-gate 	free(lwp);
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate static void
6387c478bd9Sstevel@tonic-gate list_clear(list_t *list)
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate 	if (list->l_type == LT_LWPS) {
6417c478bd9Sstevel@tonic-gate 		lwp_info_t	*lwp = list->l_tail;
6427c478bd9Sstevel@tonic-gate 		lwp_info_t	*lwp_tmp;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 		fd_closeall();
6457c478bd9Sstevel@tonic-gate 		while (lwp) {
6467c478bd9Sstevel@tonic-gate 			lwp_tmp = lwp;
6477c478bd9Sstevel@tonic-gate 			lwp = lwp->li_prev;
6487c478bd9Sstevel@tonic-gate 			list_remove_lwp(&lwps, lwp_tmp);
6497c478bd9Sstevel@tonic-gate 		}
6507c478bd9Sstevel@tonic-gate 	} else {
6517c478bd9Sstevel@tonic-gate 		id_info_t *id = list->l_head;
6527c478bd9Sstevel@tonic-gate 		id_info_t *nextid;
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 		while (id) {
6557c478bd9Sstevel@tonic-gate 			nextid = id->id_next;
6567c478bd9Sstevel@tonic-gate 			free(id);
6577c478bd9Sstevel@tonic-gate 			id = nextid;
6587c478bd9Sstevel@tonic-gate 		}
6597c478bd9Sstevel@tonic-gate 		list->l_count = 0;
6607c478bd9Sstevel@tonic-gate 		list->l_head = list->l_tail = NULL;
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate static void
6657c478bd9Sstevel@tonic-gate list_update(list_t *list, lwp_info_t *lwp)
6667c478bd9Sstevel@tonic-gate {
6677c478bd9Sstevel@tonic-gate 	id_info_t *id;
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	if (list->l_head == NULL) {			/* first element */
6707c478bd9Sstevel@tonic-gate 		list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
6717c478bd9Sstevel@tonic-gate 		goto update;
6727c478bd9Sstevel@tonic-gate 	}
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 	for (id = list->l_head; id; id = id->id_next) {
6757c478bd9Sstevel@tonic-gate 		if ((list->l_type == LT_USERS) &&
6767c478bd9Sstevel@tonic-gate 		    (id->id_uid != lwp->li_info.pr_uid))
6777c478bd9Sstevel@tonic-gate 			continue;
6787c478bd9Sstevel@tonic-gate 		if ((list->l_type == LT_TASKS) &&
6797c478bd9Sstevel@tonic-gate 		    (id->id_taskid != lwp->li_info.pr_taskid))
6807c478bd9Sstevel@tonic-gate 			continue;
6817c478bd9Sstevel@tonic-gate 		if ((list->l_type == LT_PROJECTS) &&
6827c478bd9Sstevel@tonic-gate 		    (id->id_projid != lwp->li_info.pr_projid))
6837c478bd9Sstevel@tonic-gate 			continue;
6847c478bd9Sstevel@tonic-gate 		if ((list->l_type == LT_ZONES) &&
6857c478bd9Sstevel@tonic-gate 		    (id->id_zoneid != lwp->li_info.pr_zoneid))
6867c478bd9Sstevel@tonic-gate 			continue;
687c6402783Sakolb 		if ((list->l_type == LT_LGRPS) &&
688c6402783Sakolb 		    (id->id_lgroup != lwp->li_info.pr_lwp.pr_lgrp))
689c6402783Sakolb 			continue;
6907c478bd9Sstevel@tonic-gate 		id->id_nproc++;
6917c478bd9Sstevel@tonic-gate 		id->id_taskid	= lwp->li_info.pr_taskid;
6927c478bd9Sstevel@tonic-gate 		id->id_projid	= lwp->li_info.pr_projid;
6937c478bd9Sstevel@tonic-gate 		id->id_zoneid	= lwp->li_info.pr_zoneid;
694c6402783Sakolb 		id->id_lgroup	= lwp->li_info.pr_lwp.pr_lgrp;
695c6402783Sakolb 
6967c478bd9Sstevel@tonic-gate 		if (lwp->li_flags & LWP_REPRESENT) {
6977c478bd9Sstevel@tonic-gate 			id->id_size	+= lwp->li_info.pr_size;
6987c478bd9Sstevel@tonic-gate 			id->id_rssize	+= lwp->li_info.pr_rssize;
6997c478bd9Sstevel@tonic-gate 		}
7007c478bd9Sstevel@tonic-gate 		id->id_pctcpu	+= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
7017c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_LWPS)
7027c478bd9Sstevel@tonic-gate 			id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time);
7037c478bd9Sstevel@tonic-gate 		else
7047c478bd9Sstevel@tonic-gate 			id->id_time += TIME2SEC(lwp->li_info.pr_time);
7057c478bd9Sstevel@tonic-gate 		id->id_pctmem	+= FRC2PCT(lwp->li_info.pr_pctmem);
7067c478bd9Sstevel@tonic-gate 		id->id_key	+= lwp->li_key;
7077c478bd9Sstevel@tonic-gate 		total_cpu	+= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
7087c478bd9Sstevel@tonic-gate 		total_mem	+= FRC2PCT(lwp->li_info.pr_pctmem);
7097c478bd9Sstevel@tonic-gate 		return;
7107c478bd9Sstevel@tonic-gate 	}
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	id = list->l_tail;
7137c478bd9Sstevel@tonic-gate 	id->id_next = Zalloc(sizeof (id_info_t));
7147c478bd9Sstevel@tonic-gate 	id->id_next->id_prev = list->l_tail;
7157c478bd9Sstevel@tonic-gate 	id->id_next->id_next = NULL;
7167c478bd9Sstevel@tonic-gate 	list->l_tail = id->id_next;
7177c478bd9Sstevel@tonic-gate 	id = list->l_tail;
7187c478bd9Sstevel@tonic-gate update:
7197c478bd9Sstevel@tonic-gate 	id->id_uid	= lwp->li_info.pr_uid;
7207c478bd9Sstevel@tonic-gate 	id->id_projid	= lwp->li_info.pr_projid;
7217c478bd9Sstevel@tonic-gate 	id->id_taskid	= lwp->li_info.pr_taskid;
7227c478bd9Sstevel@tonic-gate 	id->id_zoneid	= lwp->li_info.pr_zoneid;
723c6402783Sakolb 	id->id_lgroup	= lwp->li_info.pr_lwp.pr_lgrp;
7247c478bd9Sstevel@tonic-gate 	id->id_nproc++;
7250209230bSgjelinek 	id->id_sizematch = B_FALSE;
7267c478bd9Sstevel@tonic-gate 	if (lwp->li_flags & LWP_REPRESENT) {
7277c478bd9Sstevel@tonic-gate 		id->id_size	= lwp->li_info.pr_size;
7287c478bd9Sstevel@tonic-gate 		id->id_rssize	= lwp->li_info.pr_rssize;
7297c478bd9Sstevel@tonic-gate 	}
7307c478bd9Sstevel@tonic-gate 	id->id_pctcpu	= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
7317c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_LWPS)
7327c478bd9Sstevel@tonic-gate 		id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time);
7337c478bd9Sstevel@tonic-gate 	else
7347c478bd9Sstevel@tonic-gate 		id->id_time = TIME2SEC(lwp->li_info.pr_time);
7357c478bd9Sstevel@tonic-gate 	id->id_pctmem	= FRC2PCT(lwp->li_info.pr_pctmem);
7367c478bd9Sstevel@tonic-gate 	id->id_key	= lwp->li_key;
7377c478bd9Sstevel@tonic-gate 	total_cpu	+= id->id_pctcpu;
7387c478bd9Sstevel@tonic-gate 	total_mem	+= id->id_pctmem;
7397c478bd9Sstevel@tonic-gate 	list->l_count++;
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate static void
7437c478bd9Sstevel@tonic-gate lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage)
7447c478bd9Sstevel@tonic-gate {
7457c478bd9Sstevel@tonic-gate 	float period;
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	if (!lwpid_is_active(pid, lwpid)) {
7487c478bd9Sstevel@tonic-gate 		/*
7497c478bd9Sstevel@tonic-gate 		 * If we are reading cpu times for the first time then
7507c478bd9Sstevel@tonic-gate 		 * calculate average cpu times based on whole process
7517c478bd9Sstevel@tonic-gate 		 * execution time.
7527c478bd9Sstevel@tonic-gate 		 */
7537c478bd9Sstevel@tonic-gate 		(void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
7547c478bd9Sstevel@tonic-gate 		period = TIME2NSEC(usage->pr_rtime);
7557c478bd9Sstevel@tonic-gate 		period = period/(float)100;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 		if (period == 0) { /* zombie */
7587c478bd9Sstevel@tonic-gate 			period = 1;
7597c478bd9Sstevel@tonic-gate 			lwp->li_usr = 0;
7607c478bd9Sstevel@tonic-gate 			lwp->li_sys = 0;
7617c478bd9Sstevel@tonic-gate 			lwp->li_slp = 0;
7627c478bd9Sstevel@tonic-gate 		} else {
7637c478bd9Sstevel@tonic-gate 			lwp->li_usr = TIME2NSEC(usage->pr_utime)/period;
7647c478bd9Sstevel@tonic-gate 			lwp->li_sys = TIME2NSEC(usage->pr_stime)/period;
7657c478bd9Sstevel@tonic-gate 			lwp->li_slp = TIME2NSEC(usage->pr_slptime)/period;
7667c478bd9Sstevel@tonic-gate 		}
7677c478bd9Sstevel@tonic-gate 		lwp->li_trp = TIME2NSEC(usage->pr_ttime)/period;
7687c478bd9Sstevel@tonic-gate 		lwp->li_tfl = TIME2NSEC(usage->pr_tftime)/period;
7697c478bd9Sstevel@tonic-gate 		lwp->li_dfl = TIME2NSEC(usage->pr_dftime)/period;
7707c478bd9Sstevel@tonic-gate 		lwp->li_lck = TIME2NSEC(usage->pr_ltime)/period;
7717c478bd9Sstevel@tonic-gate 		lwp->li_lat = TIME2NSEC(usage->pr_wtime)/period;
7727c478bd9Sstevel@tonic-gate 		period = (period / NANOSEC)*(float)100; /* now in seconds */
7737c478bd9Sstevel@tonic-gate 		lwp->li_vcx = (ulong_t)
7747c478bd9Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_vctx/period));
7757c478bd9Sstevel@tonic-gate 		lwp->li_icx = (ulong_t)
7767c478bd9Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_ictx/period));
7777c478bd9Sstevel@tonic-gate 		lwp->li_scl = (ulong_t)
7787c478bd9Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_sysc/period));
7797c478bd9Sstevel@tonic-gate 		lwp->li_sig = (ulong_t)
7807c478bd9Sstevel@tonic-gate 		    (opts.o_interval * (usage->pr_sigs/period));
7817c478bd9Sstevel@tonic-gate 		(void) lwpid_set_active(pid, lwpid);
7827c478bd9Sstevel@tonic-gate 	} else {
7837c478bd9Sstevel@tonic-gate 		/*
7847c478bd9Sstevel@tonic-gate 		 * If this is not a first time we are reading a process's
7857c478bd9Sstevel@tonic-gate 		 * CPU times then recalculate CPU times based on fresh data
7867c478bd9Sstevel@tonic-gate 		 * obtained from procfs and previous CPU time usage values.
7877c478bd9Sstevel@tonic-gate 		 */
7887c478bd9Sstevel@tonic-gate 		period = TIME2NSEC(usage->pr_rtime)-
7897c478bd9Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_rtime);
7907c478bd9Sstevel@tonic-gate 		period = period/(float)100;
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 		if (period == 0) { /* zombie */
7937c478bd9Sstevel@tonic-gate 			period = 1;
7947c478bd9Sstevel@tonic-gate 			lwp->li_usr = 0;
7957c478bd9Sstevel@tonic-gate 			lwp->li_sys = 0;
7967c478bd9Sstevel@tonic-gate 			lwp->li_slp = 0;
7977c478bd9Sstevel@tonic-gate 		} else {
7987c478bd9Sstevel@tonic-gate 			lwp->li_usr = (TIME2NSEC(usage->pr_utime)-
7997c478bd9Sstevel@tonic-gate 			    TIME2NSEC(lwp->li_usage.pr_utime))/period;
8007c478bd9Sstevel@tonic-gate 			lwp->li_sys = (TIME2NSEC(usage->pr_stime) -
8017c478bd9Sstevel@tonic-gate 			    TIME2NSEC(lwp->li_usage.pr_stime))/period;
8027c478bd9Sstevel@tonic-gate 			lwp->li_slp = (TIME2NSEC(usage->pr_slptime) -
8037c478bd9Sstevel@tonic-gate 			    TIME2NSEC(lwp->li_usage.pr_slptime))/period;
8047c478bd9Sstevel@tonic-gate 		}
8057c478bd9Sstevel@tonic-gate 		lwp->li_trp = (TIME2NSEC(usage->pr_ttime) -
8067c478bd9Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_ttime))/period;
8077c478bd9Sstevel@tonic-gate 		lwp->li_tfl = (TIME2NSEC(usage->pr_tftime) -
8087c478bd9Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_tftime))/period;
8097c478bd9Sstevel@tonic-gate 		lwp->li_dfl = (TIME2NSEC(usage->pr_dftime) -
8107c478bd9Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_dftime))/period;
8117c478bd9Sstevel@tonic-gate 		lwp->li_lck = (TIME2NSEC(usage->pr_ltime) -
8127c478bd9Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_ltime))/period;
8137c478bd9Sstevel@tonic-gate 		lwp->li_lat = (TIME2NSEC(usage->pr_wtime) -
8147c478bd9Sstevel@tonic-gate 		    TIME2NSEC(lwp->li_usage.pr_wtime))/period;
8157c478bd9Sstevel@tonic-gate 		lwp->li_vcx = usage->pr_vctx - lwp->li_usage.pr_vctx;
8167c478bd9Sstevel@tonic-gate 		lwp->li_icx = usage->pr_ictx - lwp->li_usage.pr_ictx;
8177c478bd9Sstevel@tonic-gate 		lwp->li_scl = usage->pr_sysc - lwp->li_usage.pr_sysc;
8187c478bd9Sstevel@tonic-gate 		lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs;
8197c478bd9Sstevel@tonic-gate 		(void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
8207c478bd9Sstevel@tonic-gate 	}
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate static int
8247c478bd9Sstevel@tonic-gate read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize)
8257c478bd9Sstevel@tonic-gate {
8267c478bd9Sstevel@tonic-gate 	char procfile[MAX_PROCFS_PATH];
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	(void) snprintf(procfile, MAX_PROCFS_PATH,
8297c478bd9Sstevel@tonic-gate 	    "/proc/%s/%s", pidstr, file);
8307c478bd9Sstevel@tonic-gate 	if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL)
8317c478bd9Sstevel@tonic-gate 		return (1);
8327c478bd9Sstevel@tonic-gate 	if (pread(fd_getfd(*fd), buf, bufsize, 0) != bufsize) {
8337c478bd9Sstevel@tonic-gate 		fd_close(*fd);
8347c478bd9Sstevel@tonic-gate 		return (1);
8357c478bd9Sstevel@tonic-gate 	}
8367c478bd9Sstevel@tonic-gate 	return (0);
8377c478bd9Sstevel@tonic-gate }
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate static void
8407c478bd9Sstevel@tonic-gate add_proc(psinfo_t *psinfo)
8417c478bd9Sstevel@tonic-gate {
8427c478bd9Sstevel@tonic-gate 	lwp_info_t *lwp;
8437c478bd9Sstevel@tonic-gate 	id_t lwpid;
8447c478bd9Sstevel@tonic-gate 	pid_t pid = psinfo->pr_pid;
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	lwpid = psinfo->pr_lwp.pr_lwpid;
8477c478bd9Sstevel@tonic-gate 	if ((lwp = lwpid_get(pid, lwpid)) == NULL)
8487c478bd9Sstevel@tonic-gate 		lwp = list_add_lwp(&lwps, pid, lwpid);
8497c478bd9Sstevel@tonic-gate 	lwp->li_flags |= LWP_ALIVE | LWP_REPRESENT;
8507c478bd9Sstevel@tonic-gate 	(void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t));
8517c478bd9Sstevel@tonic-gate 	lwp->li_info.pr_lwp.pr_pctcpu = lwp->li_info.pr_pctcpu;
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate static void
8557c478bd9Sstevel@tonic-gate add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
8567c478bd9Sstevel@tonic-gate {
8577c478bd9Sstevel@tonic-gate 	lwp_info_t *lwp;
8587c478bd9Sstevel@tonic-gate 	pid_t pid = psinfo->pr_pid;
8597c478bd9Sstevel@tonic-gate 	id_t lwpid = lwpsinfo->pr_lwpid;
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	if ((lwp = lwpid_get(pid, lwpid)) == NULL)
8627c478bd9Sstevel@tonic-gate 		lwp = list_add_lwp(&lwps, pid, lwpid);
8637c478bd9Sstevel@tonic-gate 	lwp->li_flags &= ~LWP_REPRESENT;
8647c478bd9Sstevel@tonic-gate 	lwp->li_flags |= LWP_ALIVE;
8657c478bd9Sstevel@tonic-gate 	lwp->li_flags |= flags;
8667c478bd9Sstevel@tonic-gate 	(void) memcpy(&lwp->li_info, psinfo,
8677c478bd9Sstevel@tonic-gate 	    sizeof (psinfo_t) - sizeof (lwpsinfo_t));
8687c478bd9Sstevel@tonic-gate 	(void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t));
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate static void
8727c478bd9Sstevel@tonic-gate prstat_scandir(DIR *procdir)
8737c478bd9Sstevel@tonic-gate {
8747c478bd9Sstevel@tonic-gate 	char *pidstr;
8757c478bd9Sstevel@tonic-gate 	pid_t pid;
8767c478bd9Sstevel@tonic-gate 	id_t lwpid;
8777c478bd9Sstevel@tonic-gate 	size_t entsz;
8787c478bd9Sstevel@tonic-gate 	long nlwps, nent, i;
8797c478bd9Sstevel@tonic-gate 	char *buf, *ptr;
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	fds_t *fds;
8827c478bd9Sstevel@tonic-gate 	lwp_info_t *lwp;
8837c478bd9Sstevel@tonic-gate 	dirent_t *direntp;
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	prheader_t	header;
8867c478bd9Sstevel@tonic-gate 	psinfo_t	psinfo;
8877c478bd9Sstevel@tonic-gate 	prusage_t	usage;
8887c478bd9Sstevel@tonic-gate 	lwpsinfo_t	*lwpsinfo;
8897c478bd9Sstevel@tonic-gate 	prusage_t	*lwpusage;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	total_procs = 0;
8927c478bd9Sstevel@tonic-gate 	total_lwps = 0;
8937c478bd9Sstevel@tonic-gate 	total_cpu = 0;
8947c478bd9Sstevel@tonic-gate 	total_mem = 0;
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	convert_zone(&zone_tbl);
8977c478bd9Sstevel@tonic-gate 	for (rewinddir(procdir); (direntp = readdir(procdir)); ) {
8987c478bd9Sstevel@tonic-gate 		pidstr = direntp->d_name;
8997c478bd9Sstevel@tonic-gate 		if (pidstr[0] == '.')	/* skip "." and ".."  */
9007c478bd9Sstevel@tonic-gate 			continue;
9017c478bd9Sstevel@tonic-gate 		pid = atoi(pidstr);
9027c478bd9Sstevel@tonic-gate 		if (pid == 0 || pid == 2 || pid == 3)
9037c478bd9Sstevel@tonic-gate 			continue;	/* skip sched, pageout and fsflush */
9047c478bd9Sstevel@tonic-gate 		if (has_element(&pid_tbl, pid) == 0)
9057c478bd9Sstevel@tonic-gate 			continue;	/* check if we really want this pid */
9067c478bd9Sstevel@tonic-gate 		fds = fds_get(pid);	/* get ptr to file descriptors */
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 		if (read_procfile(&fds->fds_psinfo, pidstr,
9097c478bd9Sstevel@tonic-gate 		    "psinfo", &psinfo, sizeof (psinfo_t)) != 0)
9107c478bd9Sstevel@tonic-gate 			continue;
9117c478bd9Sstevel@tonic-gate 		if (!has_uid(&ruid_tbl, psinfo.pr_uid) ||
9127c478bd9Sstevel@tonic-gate 		    !has_uid(&euid_tbl, psinfo.pr_euid) ||
9137c478bd9Sstevel@tonic-gate 		    !has_element(&prj_tbl, psinfo.pr_projid) ||
9147c478bd9Sstevel@tonic-gate 		    !has_element(&tsk_tbl, psinfo.pr_taskid) ||
9157c478bd9Sstevel@tonic-gate 		    !has_zone(&zone_tbl, psinfo.pr_zoneid)) {
9167c478bd9Sstevel@tonic-gate 			fd_close(fds->fds_psinfo);
9177c478bd9Sstevel@tonic-gate 			continue;
9187c478bd9Sstevel@tonic-gate 		}
9197c478bd9Sstevel@tonic-gate 		nlwps = psinfo.pr_nlwp + psinfo.pr_nzomb;
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 		if (nlwps > 1 && (opts.o_outpmode & (OPT_LWPS | OPT_PSETS))) {
9227c478bd9Sstevel@tonic-gate 			int rep_lwp = 0;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 			if (read_procfile(&fds->fds_lpsinfo, pidstr, "lpsinfo",
9257c478bd9Sstevel@tonic-gate 			    &header, sizeof (prheader_t)) != 0) {
9267c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
9277c478bd9Sstevel@tonic-gate 				continue;
9287c478bd9Sstevel@tonic-gate 			}
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 			nent = header.pr_nent;
9317c478bd9Sstevel@tonic-gate 			entsz = header.pr_entsize * nent;
9327c478bd9Sstevel@tonic-gate 			ptr = buf = Malloc(entsz);
9337c478bd9Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lpsinfo), buf,
9347c478bd9Sstevel@tonic-gate 			    entsz, sizeof (struct prheader)) != entsz) {
9357c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
9367c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
9377c478bd9Sstevel@tonic-gate 				free(buf);
9387c478bd9Sstevel@tonic-gate 				continue;
9397c478bd9Sstevel@tonic-gate 			}
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 			nlwps = 0;
9427c478bd9Sstevel@tonic-gate 			for (i = 0; i < nent; i++, ptr += header.pr_entsize) {
9437c478bd9Sstevel@tonic-gate 				/*LINTED ALIGNMENT*/
9447c478bd9Sstevel@tonic-gate 				lwpsinfo = (lwpsinfo_t *)ptr;
9457c478bd9Sstevel@tonic-gate 				if (!has_element(&cpu_tbl,
9467c478bd9Sstevel@tonic-gate 				    lwpsinfo->pr_onpro) ||
9477c478bd9Sstevel@tonic-gate 				    !has_element(&set_tbl,
948c6402783Sakolb 				    lwpsinfo->pr_bindpset) ||
949*4944376cSJohn Levon 				    !has_element(&lgr_tbl, lwpsinfo->pr_lgrp))
9507c478bd9Sstevel@tonic-gate 					continue;
9517c478bd9Sstevel@tonic-gate 				nlwps++;
9527c478bd9Sstevel@tonic-gate 				if ((opts.o_outpmode & (OPT_PSETS | OPT_LWPS))
9537c478bd9Sstevel@tonic-gate 				    == OPT_PSETS) {
9547c478bd9Sstevel@tonic-gate 					/*
9557c478bd9Sstevel@tonic-gate 					 * If one of process's LWPs is bound
9567c478bd9Sstevel@tonic-gate 					 * to a given processor set, report the
9577c478bd9Sstevel@tonic-gate 					 * whole process.  We may be doing this
9587c478bd9Sstevel@tonic-gate 					 * a few times but we'll get an accurate
9597c478bd9Sstevel@tonic-gate 					 * lwp count in return.
9607c478bd9Sstevel@tonic-gate 					 */
9617c478bd9Sstevel@tonic-gate 					add_proc(&psinfo);
9627c478bd9Sstevel@tonic-gate 				} else {
9637c478bd9Sstevel@tonic-gate 					if (rep_lwp == 0) {
9647c478bd9Sstevel@tonic-gate 						rep_lwp = 1;
9657c478bd9Sstevel@tonic-gate 						add_lwp(&psinfo, lwpsinfo,
9667c478bd9Sstevel@tonic-gate 						    LWP_REPRESENT);
9677c478bd9Sstevel@tonic-gate 					} else {
9687c478bd9Sstevel@tonic-gate 						add_lwp(&psinfo, lwpsinfo, 0);
9697c478bd9Sstevel@tonic-gate 					}
9707c478bd9Sstevel@tonic-gate 				}
9717c478bd9Sstevel@tonic-gate 			}
9727c478bd9Sstevel@tonic-gate 			free(buf);
9737c478bd9Sstevel@tonic-gate 			if (nlwps == 0) {
9747c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
9757c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
9767c478bd9Sstevel@tonic-gate 				continue;
9777c478bd9Sstevel@tonic-gate 			}
9787c478bd9Sstevel@tonic-gate 		} else {
9797c478bd9Sstevel@tonic-gate 			if (!has_element(&cpu_tbl, psinfo.pr_lwp.pr_onpro) ||
980c6402783Sakolb 			    !has_element(&set_tbl, psinfo.pr_lwp.pr_bindpset) ||
981c6402783Sakolb 			    !has_element(&lgr_tbl, psinfo.pr_lwp.pr_lgrp)) {
9827c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
9837c478bd9Sstevel@tonic-gate 				continue;
9847c478bd9Sstevel@tonic-gate 			}
9857c478bd9Sstevel@tonic-gate 			add_proc(&psinfo);
9867c478bd9Sstevel@tonic-gate 		}
9877c478bd9Sstevel@tonic-gate 		if (!(opts.o_outpmode & OPT_MSACCT)) {
9887c478bd9Sstevel@tonic-gate 			total_procs++;
9897c478bd9Sstevel@tonic-gate 			total_lwps += nlwps;
9907c478bd9Sstevel@tonic-gate 			continue;
9917c478bd9Sstevel@tonic-gate 		}
9927c478bd9Sstevel@tonic-gate 		/*
9937c478bd9Sstevel@tonic-gate 		 * Get more information about processes from /proc/pid/usage.
9947c478bd9Sstevel@tonic-gate 		 * If process has more than one lwp, then we may have to
9957c478bd9Sstevel@tonic-gate 		 * also look at the /proc/pid/lusage file.
9967c478bd9Sstevel@tonic-gate 		 */
9977c478bd9Sstevel@tonic-gate 		if ((opts.o_outpmode & OPT_LWPS) && (nlwps > 1)) {
9987c478bd9Sstevel@tonic-gate 			if (read_procfile(&fds->fds_lusage, pidstr, "lusage",
9997c478bd9Sstevel@tonic-gate 			    &header, sizeof (prheader_t)) != 0) {
10007c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
10017c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
10027c478bd9Sstevel@tonic-gate 				continue;
10037c478bd9Sstevel@tonic-gate 			}
10047c478bd9Sstevel@tonic-gate 			nent = header.pr_nent;
10057c478bd9Sstevel@tonic-gate 			entsz = header.pr_entsize * nent;
10067c478bd9Sstevel@tonic-gate 			buf = Malloc(entsz);
10077c478bd9Sstevel@tonic-gate 			if (pread(fd_getfd(fds->fds_lusage), buf,
10087c478bd9Sstevel@tonic-gate 			    entsz, sizeof (struct prheader)) != entsz) {
10097c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_lusage);
10107c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
10117c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
10127c478bd9Sstevel@tonic-gate 				free(buf);
10137c478bd9Sstevel@tonic-gate 				continue;
10147c478bd9Sstevel@tonic-gate 			}
10157c478bd9Sstevel@tonic-gate 			for (i = 1, ptr = buf + header.pr_entsize; i < nent;
10167c478bd9Sstevel@tonic-gate 			    i++, ptr += header.pr_entsize) {
10177c478bd9Sstevel@tonic-gate 				/*LINTED ALIGNMENT*/
10187c478bd9Sstevel@tonic-gate 				lwpusage = (prusage_t *)ptr;
10197c478bd9Sstevel@tonic-gate 				lwpid = lwpusage->pr_lwpid;
10207c478bd9Sstevel@tonic-gate 				/*
10217c478bd9Sstevel@tonic-gate 				 * New LWPs created after we read lpsinfo
10227c478bd9Sstevel@tonic-gate 				 * will be ignored.  Don't want to do
10237c478bd9Sstevel@tonic-gate 				 * everything all over again.
10247c478bd9Sstevel@tonic-gate 				 */
10257c478bd9Sstevel@tonic-gate 				if ((lwp = lwpid_get(pid, lwpid)) == NULL)
10267c478bd9Sstevel@tonic-gate 					continue;
10277c478bd9Sstevel@tonic-gate 				lwp_update(lwp, pid, lwpid, lwpusage);
10287c478bd9Sstevel@tonic-gate 			}
10297c478bd9Sstevel@tonic-gate 			free(buf);
10307c478bd9Sstevel@tonic-gate 		} else {
10317c478bd9Sstevel@tonic-gate 			if (read_procfile(&fds->fds_usage, pidstr, "usage",
10327c478bd9Sstevel@tonic-gate 			    &usage, sizeof (prusage_t)) != 0) {
10337c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_lpsinfo);
10347c478bd9Sstevel@tonic-gate 				fd_close(fds->fds_psinfo);
10357c478bd9Sstevel@tonic-gate 				continue;
10367c478bd9Sstevel@tonic-gate 			}
10377c478bd9Sstevel@tonic-gate 			lwpid = psinfo.pr_lwp.pr_lwpid;
10387c478bd9Sstevel@tonic-gate 			if ((lwp = lwpid_get(pid, lwpid)) == NULL)
10397c478bd9Sstevel@tonic-gate 				continue;
10407c478bd9Sstevel@tonic-gate 			lwp_update(lwp, pid, lwpid, &usage);
10417c478bd9Sstevel@tonic-gate 		}
10427c478bd9Sstevel@tonic-gate 		total_procs++;
10437c478bd9Sstevel@tonic-gate 		total_lwps += nlwps;
10447c478bd9Sstevel@tonic-gate 	}
10457c478bd9Sstevel@tonic-gate 	fd_update();
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate /*
10497c478bd9Sstevel@tonic-gate  * This procedure removes all dead lwps from the linked list of all lwps.
10507c478bd9Sstevel@tonic-gate  * It also creates linked list of ids if necessary.
10517c478bd9Sstevel@tonic-gate  */
10527c478bd9Sstevel@tonic-gate static void
10537c478bd9Sstevel@tonic-gate list_refresh(list_t *list)
10547c478bd9Sstevel@tonic-gate {
10557c478bd9Sstevel@tonic-gate 	lwp_info_t *lwp, *lwp_next;
10567c478bd9Sstevel@tonic-gate 
10577c478bd9Sstevel@tonic-gate 	if (!(list->l_type & LT_LWPS))
10587c478bd9Sstevel@tonic-gate 		return;
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	for (lwp = list->l_head; lwp != NULL; ) {
10617c478bd9Sstevel@tonic-gate 		if (lwp->li_flags & LWP_ALIVE) {
10627c478bd9Sstevel@tonic-gate 			/*
10637c478bd9Sstevel@tonic-gate 			 * Process all live LWPs.
10647c478bd9Sstevel@tonic-gate 			 * When we're done, mark them as dead.
10657c478bd9Sstevel@tonic-gate 			 * They will be marked "alive" on the next
10667c478bd9Sstevel@tonic-gate 			 * /proc scan if they still exist.
10677c478bd9Sstevel@tonic-gate 			 */
10687c478bd9Sstevel@tonic-gate 			lwp->li_key = list_getkeyval(list, lwp);
10697c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_USERS)
10707c478bd9Sstevel@tonic-gate 				list_update(&users, lwp);
10717c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_TASKS)
10727c478bd9Sstevel@tonic-gate 				list_update(&tasks, lwp);
10737c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_PROJECTS)
10747c478bd9Sstevel@tonic-gate 				list_update(&projects, lwp);
10757c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_ZONES)
10767c478bd9Sstevel@tonic-gate 				list_update(&zones, lwp);
1077c6402783Sakolb 			if (opts.o_outpmode & OPT_LGRP)
1078c6402783Sakolb 				list_update(&lgroups, lwp);
10797c478bd9Sstevel@tonic-gate 			lwp->li_flags &= ~LWP_ALIVE;
10807c478bd9Sstevel@tonic-gate 			lwp = lwp->li_next;
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 		} else {
10837c478bd9Sstevel@tonic-gate 			lwp_next = lwp->li_next;
10847c478bd9Sstevel@tonic-gate 			list_remove_lwp(&lwps, lwp);
10857c478bd9Sstevel@tonic-gate 			lwp = lwp_next;
10867c478bd9Sstevel@tonic-gate 		}
10877c478bd9Sstevel@tonic-gate 	}
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate static void
10917c478bd9Sstevel@tonic-gate curses_on()
10927c478bd9Sstevel@tonic-gate {
10937c478bd9Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
10947c478bd9Sstevel@tonic-gate 		(void) initscr();
10957c478bd9Sstevel@tonic-gate 		(void) nonl();
10967c478bd9Sstevel@tonic-gate 		(void) putp(t_smcup);
10977c478bd9Sstevel@tonic-gate 		is_curses_on = TRUE;
10987c478bd9Sstevel@tonic-gate 	}
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate static void
11027c478bd9Sstevel@tonic-gate curses_off()
11037c478bd9Sstevel@tonic-gate {
11047c478bd9Sstevel@tonic-gate 	if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
11057c478bd9Sstevel@tonic-gate 		(void) putp(t_rmcup);
11067c478bd9Sstevel@tonic-gate 		(void) endwin();
11077c478bd9Sstevel@tonic-gate 		is_curses_on = FALSE;
11087c478bd9Sstevel@tonic-gate 	}
11097c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
11107c478bd9Sstevel@tonic-gate }
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate static int
11137c478bd9Sstevel@tonic-gate nlines()
11147c478bd9Sstevel@tonic-gate {
11157c478bd9Sstevel@tonic-gate 	struct winsize ws;
11167c478bd9Sstevel@tonic-gate 	char *envp;
11177c478bd9Sstevel@tonic-gate 	int n;
11187c478bd9Sstevel@tonic-gate 	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
11197c478bd9Sstevel@tonic-gate 		if (ws.ws_row > 0)
11207c478bd9Sstevel@tonic-gate 			return (ws.ws_row);
11217c478bd9Sstevel@tonic-gate 	}
11227c478bd9Sstevel@tonic-gate 	if (envp = getenv("LINES")) {
11237c478bd9Sstevel@tonic-gate 		if ((n = Atoi(envp)) > 0) {
11247c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_USEHOME;
11257c478bd9Sstevel@tonic-gate 			return (n);
11267c478bd9Sstevel@tonic-gate 		}
11277c478bd9Sstevel@tonic-gate 	}
11287c478bd9Sstevel@tonic-gate 	return (-1);
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate static void
11327c478bd9Sstevel@tonic-gate setmovecur()
11337c478bd9Sstevel@tonic-gate {
11347c478bd9Sstevel@tonic-gate 	int i, n;
11357c478bd9Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_FULLSCREEN) &&
11367c478bd9Sstevel@tonic-gate 	    (opts.o_outpmode & OPT_USEHOME)) {
11377c478bd9Sstevel@tonic-gate 		movecur = t_home;
11387c478bd9Sstevel@tonic-gate 		return;
11397c478bd9Sstevel@tonic-gate 	}
11407c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_SPLIT) {
11417c478bd9Sstevel@tonic-gate 		n = opts.o_ntop + opts.o_nbottom + 2;
11427c478bd9Sstevel@tonic-gate 	} else {
11437c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_USERS)
11447c478bd9Sstevel@tonic-gate 			n = opts.o_nbottom + 1;
11457c478bd9Sstevel@tonic-gate 		else
11467c478bd9Sstevel@tonic-gate 			n = opts.o_ntop + 1;
11477c478bd9Sstevel@tonic-gate 	}
1148*4944376cSJohn Levon 	if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)))
1149*4944376cSJohn Levon 		n++;
1150*4944376cSJohn Levon 
11517c478bd9Sstevel@tonic-gate 	if (movecur != NULL && movecur != empty_string && movecur != t_home)
11527c478bd9Sstevel@tonic-gate 		free(movecur);
11537c478bd9Sstevel@tonic-gate 	movecur = Zalloc(strlen(t_up) * (n + 5));
11547c478bd9Sstevel@tonic-gate 	for (i = 0; i <= n; i++)
11557c478bd9Sstevel@tonic-gate 		(void) strcat(movecur, t_up);
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate static int
11597c478bd9Sstevel@tonic-gate setsize()
11607c478bd9Sstevel@tonic-gate {
11617c478bd9Sstevel@tonic-gate 	static int oldn = 0;
11627c478bd9Sstevel@tonic-gate 	int n;
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_FULLSCREEN) {
11657c478bd9Sstevel@tonic-gate 		n = nlines();
11667c478bd9Sstevel@tonic-gate 		if (n == oldn)
11677c478bd9Sstevel@tonic-gate 			return (0);
11687c478bd9Sstevel@tonic-gate 		oldn = n;
11697c478bd9Sstevel@tonic-gate 		if (n == -1) {
11707c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_USEHOME;
11717c478bd9Sstevel@tonic-gate 			setmovecur();		/* set default window size */
11727c478bd9Sstevel@tonic-gate 			return (1);
11737c478bd9Sstevel@tonic-gate 		}
11747c478bd9Sstevel@tonic-gate 		n = n - 3;	/* minus header, total and cursor lines */
1175*4944376cSJohn Levon 		if ((opts.o_outpmode & OPT_UDATE) ||
1176*4944376cSJohn Levon 		    (opts.o_outpmode & OPT_DDATE))
1177*4944376cSJohn Levon 			n--;	/* minus timestamp */
11787c478bd9Sstevel@tonic-gate 		if (n < 1)
11797c478bd9Sstevel@tonic-gate 			Die(gettext("window is too small (try -n)\n"));
11807c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_SPLIT) {
11817c478bd9Sstevel@tonic-gate 			if (n < 8) {
11827c478bd9Sstevel@tonic-gate 				Die(gettext("window is too small (try -n)\n"));
11837c478bd9Sstevel@tonic-gate 			} else {
11847c478bd9Sstevel@tonic-gate 				opts.o_ntop = (n / 4) * 3;
11857c478bd9Sstevel@tonic-gate 				opts.o_nbottom = n - 1 - opts.o_ntop;
11867c478bd9Sstevel@tonic-gate 			}
11877c478bd9Sstevel@tonic-gate 		} else {
11887c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_USERS)
11897c478bd9Sstevel@tonic-gate 				opts.o_nbottom = n;
11907c478bd9Sstevel@tonic-gate 			else
11917c478bd9Sstevel@tonic-gate 				opts.o_ntop = n;
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 	}
11947c478bd9Sstevel@tonic-gate 	setmovecur();
11957c478bd9Sstevel@tonic-gate 	return (1);
11967c478bd9Sstevel@tonic-gate }
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate static void
11997c478bd9Sstevel@tonic-gate ldtermcap()
12007c478bd9Sstevel@tonic-gate {
12017c478bd9Sstevel@tonic-gate 	int err;
12027c478bd9Sstevel@tonic-gate 	if (setupterm(NULL, STDIN_FILENO, &err) == ERR) {
12037c478bd9Sstevel@tonic-gate 		switch (err) {
12047c478bd9Sstevel@tonic-gate 		case 0:
12057c478bd9Sstevel@tonic-gate 			Warn(gettext("failed to load terminal info, "
12067c478bd9Sstevel@tonic-gate 			    "defaulting to -c option\n"));
12077c478bd9Sstevel@tonic-gate 			break;
12087c478bd9Sstevel@tonic-gate 		case -1:
12097c478bd9Sstevel@tonic-gate 			Warn(gettext("terminfo database not found, "
12107c478bd9Sstevel@tonic-gate 			    "defaulting to -c option\n"));
12117c478bd9Sstevel@tonic-gate 			break;
12127c478bd9Sstevel@tonic-gate 		default:
12137c478bd9Sstevel@tonic-gate 			Warn(gettext("failed to initialize terminal, "
12147c478bd9Sstevel@tonic-gate 			    "defaulting to -c option\n"));
12157c478bd9Sstevel@tonic-gate 		}
12167c478bd9Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP;
12177c478bd9Sstevel@tonic-gate 		t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
12187c478bd9Sstevel@tonic-gate 		t_ulon = t_uloff = empty_string;
12197c478bd9Sstevel@tonic-gate 		return;
12207c478bd9Sstevel@tonic-gate 	}
12217c478bd9Sstevel@tonic-gate 	t_ulon	= tigetstr("smul");
12227c478bd9Sstevel@tonic-gate 	t_uloff	= tigetstr("rmul");
12237c478bd9Sstevel@tonic-gate 	t_up	= tigetstr("cuu1");
12247c478bd9Sstevel@tonic-gate 	t_eol	= tigetstr("el");
12257c478bd9Sstevel@tonic-gate 	t_smcup	= tigetstr("smcup");
12267c478bd9Sstevel@tonic-gate 	t_rmcup = tigetstr("rmcup");
12277c478bd9Sstevel@tonic-gate 	t_home  = tigetstr("home");
12287c478bd9Sstevel@tonic-gate 	if ((t_up == (char *)-1) || (t_eol == (char *)-1) ||
12297c478bd9Sstevel@tonic-gate 	    (t_smcup == (char *)-1) || (t_rmcup == (char *)-1)) {
12307c478bd9Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP;
12317c478bd9Sstevel@tonic-gate 		t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
12327c478bd9Sstevel@tonic-gate 		return;
12337c478bd9Sstevel@tonic-gate 	}
12347c478bd9Sstevel@tonic-gate 	if (t_up == NULL || t_eol == NULL) {
12357c478bd9Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP;
12367c478bd9Sstevel@tonic-gate 		t_eol = t_up = movecur = empty_string;
12377c478bd9Sstevel@tonic-gate 		return;
12387c478bd9Sstevel@tonic-gate 	}
12397c478bd9Sstevel@tonic-gate 	if (t_ulon == (char *)-1 || t_uloff == (char *)-1 ||
12407c478bd9Sstevel@tonic-gate 	    t_ulon == NULL || t_uloff == NULL) {
12417c478bd9Sstevel@tonic-gate 		t_ulon = t_uloff = empty_string;  /* can live without it */
12427c478bd9Sstevel@tonic-gate 	}
12437c478bd9Sstevel@tonic-gate 	if (t_smcup == NULL || t_rmcup == NULL)
12447c478bd9Sstevel@tonic-gate 		t_smcup = t_rmcup = empty_string;
12457c478bd9Sstevel@tonic-gate 	if (t_home == (char *)-1 || t_home == NULL) {
12467c478bd9Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_USEHOME;
12477c478bd9Sstevel@tonic-gate 		t_home = empty_string;
12487c478bd9Sstevel@tonic-gate 	}
12497c478bd9Sstevel@tonic-gate }
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate static void
12527c478bd9Sstevel@tonic-gate sig_handler(int sig)
12537c478bd9Sstevel@tonic-gate {
12547c478bd9Sstevel@tonic-gate 	switch (sig) {
12557c478bd9Sstevel@tonic-gate 	case SIGTSTP:	sigtstp = 1;
12567c478bd9Sstevel@tonic-gate 			break;
12577c478bd9Sstevel@tonic-gate 	case SIGWINCH:	sigwinch = 1;
12587c478bd9Sstevel@tonic-gate 			break;
12597c478bd9Sstevel@tonic-gate 	case SIGINT:
12607c478bd9Sstevel@tonic-gate 	case SIGTERM:	sigterm = 1;
12617c478bd9Sstevel@tonic-gate 			break;
12627c478bd9Sstevel@tonic-gate 	}
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate static void
12667c478bd9Sstevel@tonic-gate set_signals()
12677c478bd9Sstevel@tonic-gate {
12687c478bd9Sstevel@tonic-gate 	(void) signal(SIGTSTP, sig_handler);
12697c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, sig_handler);
12707c478bd9Sstevel@tonic-gate 	(void) signal(SIGTERM, sig_handler);
12717c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_FULLSCREEN)
12727c478bd9Sstevel@tonic-gate 		(void) signal(SIGWINCH, sig_handler);
12737c478bd9Sstevel@tonic-gate }
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate static void
1276a851ab35Svb160487 fill_table(table_t *table, char *arg, char option)
12777c478bd9Sstevel@tonic-gate {
12787c478bd9Sstevel@tonic-gate 	char *p = strtok(arg, ", ");
12797c478bd9Sstevel@tonic-gate 
1280a851ab35Svb160487 	if (p == NULL)
1281a851ab35Svb160487 		Die(gettext("invalid argument for -%c\n"), option);
1282a851ab35Svb160487 
1283a851ab35Svb160487 	add_element(table, (long)Atoi(p));
1284a851ab35Svb160487 	while (p = strtok(NULL, ", "))
1285a851ab35Svb160487 		add_element(table, (long)Atoi(p));
12867c478bd9Sstevel@tonic-gate }
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate static void
12897c478bd9Sstevel@tonic-gate fill_prj_table(char *arg)
12907c478bd9Sstevel@tonic-gate {
12917c478bd9Sstevel@tonic-gate 	projid_t projid;
12927c478bd9Sstevel@tonic-gate 	char *p = strtok(arg, ", ");
12937c478bd9Sstevel@tonic-gate 
1294a851ab35Svb160487 	if (p == NULL)
1295a851ab35Svb160487 		Die(gettext("invalid argument for -j\n"));
1296a851ab35Svb160487 
12977c478bd9Sstevel@tonic-gate 	if ((projid = getprojidbyname(p)) == -1)
12987c478bd9Sstevel@tonic-gate 		projid = Atoi(p);
12997c478bd9Sstevel@tonic-gate 	add_element(&prj_tbl, (long)projid);
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 	while (p = strtok(NULL, ", ")) {
13027c478bd9Sstevel@tonic-gate 		if ((projid = getprojidbyname(p)) == -1)
13037c478bd9Sstevel@tonic-gate 			projid = Atoi(p);
13047c478bd9Sstevel@tonic-gate 		add_element(&prj_tbl, (long)projid);
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate }
13077c478bd9Sstevel@tonic-gate 
13087c478bd9Sstevel@tonic-gate static void
13097c478bd9Sstevel@tonic-gate fill_set_table(char *arg)
13107c478bd9Sstevel@tonic-gate {
13117c478bd9Sstevel@tonic-gate 	char *p = strtok(arg, ", ");
13127c478bd9Sstevel@tonic-gate 	psetid_t id;
13137c478bd9Sstevel@tonic-gate 
1314a851ab35Svb160487 	if (p == NULL)
1315a851ab35Svb160487 		Die(gettext("invalid argument for -C\n"));
1316a851ab35Svb160487 
13177c478bd9Sstevel@tonic-gate 	if ((id = Atoi(p)) == 0)
13187c478bd9Sstevel@tonic-gate 		id = PS_NONE;
13197c478bd9Sstevel@tonic-gate 	add_element(&set_tbl, id);
13207c478bd9Sstevel@tonic-gate 	while (p = strtok(NULL, ", ")) {
13217c478bd9Sstevel@tonic-gate 		if ((id = Atoi(p)) == 0)
13227c478bd9Sstevel@tonic-gate 			id = PS_NONE;
13237c478bd9Sstevel@tonic-gate 		if (!has_element(&set_tbl, id))
13247c478bd9Sstevel@tonic-gate 			add_element(&set_tbl, id);
13257c478bd9Sstevel@tonic-gate 	}
13267c478bd9Sstevel@tonic-gate }
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate static void
13297c478bd9Sstevel@tonic-gate Exit()
13307c478bd9Sstevel@tonic-gate {
13317c478bd9Sstevel@tonic-gate 	curses_off();
13327c478bd9Sstevel@tonic-gate 	list_clear(&lwps);
13337c478bd9Sstevel@tonic-gate 	list_clear(&users);
13347c478bd9Sstevel@tonic-gate 	list_clear(&tasks);
13357c478bd9Sstevel@tonic-gate 	list_clear(&projects);
13367c478bd9Sstevel@tonic-gate 	list_clear(&zones);
13377c478bd9Sstevel@tonic-gate 	fd_exit();
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate 
13400209230bSgjelinek 
13417c478bd9Sstevel@tonic-gate int
13427c478bd9Sstevel@tonic-gate main(int argc, char **argv)
13437c478bd9Sstevel@tonic-gate {
13447c478bd9Sstevel@tonic-gate 	DIR *procdir;
13457c478bd9Sstevel@tonic-gate 	char *p;
13467c478bd9Sstevel@tonic-gate 	char *sortk = "cpu";	/* default sort key */
13477c478bd9Sstevel@tonic-gate 	int opt;
13487c478bd9Sstevel@tonic-gate 	int timeout;
13497c478bd9Sstevel@tonic-gate 	struct pollfd pollset;
13507c478bd9Sstevel@tonic-gate 	char key;
13517c478bd9Sstevel@tonic-gate 
13527c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
13537c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
13547c478bd9Sstevel@tonic-gate 	Progname(argv[0]);
13557c478bd9Sstevel@tonic-gate 	lwpid_init();
13567c478bd9Sstevel@tonic-gate 	fd_init(Setrlimit());
13577c478bd9Sstevel@tonic-gate 
13580209230bSgjelinek 	pagesize = sysconf(_SC_PAGESIZE);
13590209230bSgjelinek 
1360*4944376cSJohn Levon 	while ((opt = getopt(argc, argv,
1361*4944376cSJohn Levon 	    "vcd:HmaRLtu:U:n:p:C:P:h:s:S:j:k:TJz:Z")) != (int)EOF) {
13627c478bd9Sstevel@tonic-gate 		switch (opt) {
13637c478bd9Sstevel@tonic-gate 		case 'R':
13647c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_REALTIME;
13657c478bd9Sstevel@tonic-gate 			break;
13667c478bd9Sstevel@tonic-gate 		case 'c':
13677c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_TERMCAP;
13687c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_FULLSCREEN;
13697c478bd9Sstevel@tonic-gate 			break;
1370*4944376cSJohn Levon 		case 'd':
1371*4944376cSJohn Levon 			if (optarg) {
1372*4944376cSJohn Levon 				if (*optarg == 'u')
1373*4944376cSJohn Levon 					opts.o_outpmode |= OPT_UDATE;
1374*4944376cSJohn Levon 				else if (*optarg == 'd')
1375*4944376cSJohn Levon 					opts.o_outpmode |= OPT_DDATE;
1376*4944376cSJohn Levon 				else
1377*4944376cSJohn Levon 					Usage();
1378*4944376cSJohn Levon 			} else {
1379*4944376cSJohn Levon 				Usage();
1380*4944376cSJohn Levon 			}
1381*4944376cSJohn Levon 			break;
1382c6402783Sakolb 		case 'h':
1383c6402783Sakolb 			fill_table(&lgr_tbl, optarg, 'h');
1384c6402783Sakolb 			break;
1385c6402783Sakolb 		case 'H':
1386c6402783Sakolb 			opts.o_outpmode |= OPT_LGRP;
1387c6402783Sakolb 			break;
13887c478bd9Sstevel@tonic-gate 		case 'm':
13897c478bd9Sstevel@tonic-gate 		case 'v':
13907c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_PSINFO;
13917c478bd9Sstevel@tonic-gate 			opts.o_outpmode |=  OPT_MSACCT;
13927c478bd9Sstevel@tonic-gate 			break;
13937c478bd9Sstevel@tonic-gate 		case 't':
13947c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_PSINFO;
13957c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_USERS;
13967c478bd9Sstevel@tonic-gate 			break;
13977c478bd9Sstevel@tonic-gate 		case 'a':
13987c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_USERS;
13997c478bd9Sstevel@tonic-gate 			break;
14007c478bd9Sstevel@tonic-gate 		case 'T':
14017c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_TASKS;
14027c478bd9Sstevel@tonic-gate 			break;
14037c478bd9Sstevel@tonic-gate 		case 'J':
14047c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_PROJECTS;
14057c478bd9Sstevel@tonic-gate 			break;
14067c478bd9Sstevel@tonic-gate 		case 'n':
1407a851ab35Svb160487 			if ((p = strtok(optarg, ",")) == NULL)
1408a851ab35Svb160487 				Die(gettext("invalid argument for -n\n"));
14097c478bd9Sstevel@tonic-gate 			opts.o_ntop = Atoi(p);
14107c478bd9Sstevel@tonic-gate 			if (p = strtok(NULL, ","))
14117c478bd9Sstevel@tonic-gate 				opts.o_nbottom = Atoi(p);
14127c478bd9Sstevel@tonic-gate 			opts.o_outpmode &= ~OPT_FULLSCREEN;
14137c478bd9Sstevel@tonic-gate 			break;
14147c478bd9Sstevel@tonic-gate 		case 's':
14157c478bd9Sstevel@tonic-gate 			opts.o_sortorder = -1;
14167c478bd9Sstevel@tonic-gate 			sortk = optarg;
14177c478bd9Sstevel@tonic-gate 			break;
14187c478bd9Sstevel@tonic-gate 		case 'S':
14197c478bd9Sstevel@tonic-gate 			opts.o_sortorder = 1;
14207c478bd9Sstevel@tonic-gate 			sortk = optarg;
14217c478bd9Sstevel@tonic-gate 			break;
14227c478bd9Sstevel@tonic-gate 		case 'u':
1423a851ab35Svb160487 			if ((p = strtok(optarg, ", ")) == NULL)
1424a851ab35Svb160487 				Die(gettext("invalid argument for -u\n"));
14257c478bd9Sstevel@tonic-gate 			add_uid(&euid_tbl, p);
14267c478bd9Sstevel@tonic-gate 			while (p = strtok(NULL, ", "))
14277c478bd9Sstevel@tonic-gate 				add_uid(&euid_tbl, p);
14287c478bd9Sstevel@tonic-gate 			break;
14297c478bd9Sstevel@tonic-gate 		case 'U':
1430a851ab35Svb160487 			if ((p = strtok(optarg, ", ")) == NULL)
1431a851ab35Svb160487 				Die(gettext("invalid argument for -U\n"));
14327c478bd9Sstevel@tonic-gate 			add_uid(&ruid_tbl, p);
14337c478bd9Sstevel@tonic-gate 			while (p = strtok(NULL, ", "))
14347c478bd9Sstevel@tonic-gate 				add_uid(&ruid_tbl, p);
14357c478bd9Sstevel@tonic-gate 			break;
14367c478bd9Sstevel@tonic-gate 		case 'p':
1437a851ab35Svb160487 			fill_table(&pid_tbl, optarg, 'p');
14387c478bd9Sstevel@tonic-gate 			break;
14397c478bd9Sstevel@tonic-gate 		case 'C':
14407c478bd9Sstevel@tonic-gate 			fill_set_table(optarg);
14417c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_PSETS;
14427c478bd9Sstevel@tonic-gate 			break;
14437c478bd9Sstevel@tonic-gate 		case 'P':
1444a851ab35Svb160487 			fill_table(&cpu_tbl, optarg, 'P');
14457c478bd9Sstevel@tonic-gate 			break;
14467c478bd9Sstevel@tonic-gate 		case 'k':
1447a851ab35Svb160487 			fill_table(&tsk_tbl, optarg, 'k');
14487c478bd9Sstevel@tonic-gate 			break;
14497c478bd9Sstevel@tonic-gate 		case 'j':
14507c478bd9Sstevel@tonic-gate 			fill_prj_table(optarg);
14517c478bd9Sstevel@tonic-gate 			break;
14527c478bd9Sstevel@tonic-gate 		case 'L':
14537c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_LWPS;
14547c478bd9Sstevel@tonic-gate 			break;
14557c478bd9Sstevel@tonic-gate 		case 'z':
1456a851ab35Svb160487 			if ((p = strtok(optarg, ", ")) == NULL)
1457a851ab35Svb160487 				Die(gettext("invalid argument for -z\n"));
14587c478bd9Sstevel@tonic-gate 			add_zone(&zone_tbl, p);
14597c478bd9Sstevel@tonic-gate 			while (p = strtok(NULL, ", "))
14607c478bd9Sstevel@tonic-gate 				add_zone(&zone_tbl, p);
14617c478bd9Sstevel@tonic-gate 			break;
14627c478bd9Sstevel@tonic-gate 		case 'Z':
14637c478bd9Sstevel@tonic-gate 			opts.o_outpmode |= OPT_SPLIT | OPT_ZONES;
14647c478bd9Sstevel@tonic-gate 			break;
14657c478bd9Sstevel@tonic-gate 		default:
14667c478bd9Sstevel@tonic-gate 			Usage();
14677c478bd9Sstevel@tonic-gate 		}
14687c478bd9Sstevel@tonic-gate 	}
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 	(void) atexit(Exit);
14717c478bd9Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_USERS) &&
14727c478bd9Sstevel@tonic-gate 	    !(opts.o_outpmode & OPT_SPLIT))
14737c478bd9Sstevel@tonic-gate 		opts.o_nbottom = opts.o_ntop;
14747c478bd9Sstevel@tonic-gate 	if (opts.o_ntop == 0 || opts.o_nbottom == 0)
14757c478bd9Sstevel@tonic-gate 		Die(gettext("invalid argument for -n\n"));
14767c478bd9Sstevel@tonic-gate 	if (!(opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
14777c478bd9Sstevel@tonic-gate 	    ((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
14787c478bd9Sstevel@tonic-gate 		Die(gettext("-t option cannot be used with -v or -m\n"));
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode && OPT_USERS) &&
14817c478bd9Sstevel@tonic-gate 	    !((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
14827c478bd9Sstevel@tonic-gate 		Die(gettext("-t option cannot be used with "
14837c478bd9Sstevel@tonic-gate 		    "-a, -J, -T or -Z\n"));
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	if ((opts.o_outpmode & OPT_USERS) &&
1486*4944376cSJohn Levon 	    (opts.o_outpmode & (OPT_TASKS | OPT_PROJECTS | OPT_ZONES)))
14877c478bd9Sstevel@tonic-gate 		Die(gettext("-a option cannot be used with "
14887c478bd9Sstevel@tonic-gate 		    "-t, -J, -T or -Z\n"));
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	if (((opts.o_outpmode & OPT_TASKS) &&
14917c478bd9Sstevel@tonic-gate 	    (opts.o_outpmode & (OPT_PROJECTS|OPT_ZONES))) ||
14927c478bd9Sstevel@tonic-gate 	    ((opts.o_outpmode & OPT_PROJECTS) &&
14937c478bd9Sstevel@tonic-gate 	    (opts.o_outpmode & (OPT_TASKS|OPT_ZONES)))) {
1494c6402783Sakolb 		Die(gettext(
1495c6402783Sakolb 		    "-J, -T and -Z options are mutually exclusive\n"));
1496c6402783Sakolb 	}
1497c6402783Sakolb 
1498c6402783Sakolb 	/*
1499c6402783Sakolb 	 * There is not enough space to combine microstate information and
1500c6402783Sakolb 	 * lgroup information and still fit in 80-column output.
1501c6402783Sakolb 	 */
1502c6402783Sakolb 	if ((opts.o_outpmode & OPT_LGRP) && (opts.o_outpmode & OPT_MSACCT)) {
1503c6402783Sakolb 		Die(gettext("-H and -m options are mutually exclusive\n"));
15047c478bd9Sstevel@tonic-gate 	}
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 	if (argc > optind)
15077c478bd9Sstevel@tonic-gate 		opts.o_interval = Atoi(argv[optind++]);
15087c478bd9Sstevel@tonic-gate 	if (argc > optind)
15097c478bd9Sstevel@tonic-gate 		opts.o_count = Atoi(argv[optind++]);
15107c478bd9Sstevel@tonic-gate 	if (opts.o_count == 0)
15117c478bd9Sstevel@tonic-gate 		Die(gettext("invalid counter value\n"));
15127c478bd9Sstevel@tonic-gate 	if (argc > optind)
15137c478bd9Sstevel@tonic-gate 		Usage();
15147c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_REALTIME)
15157c478bd9Sstevel@tonic-gate 		Priocntl("RT");
15167c478bd9Sstevel@tonic-gate 	if (isatty(STDOUT_FILENO) == 1 && isatty(STDIN_FILENO))
15177c478bd9Sstevel@tonic-gate 		opts.o_outpmode |= OPT_TTY;	/* interactive */
15187c478bd9Sstevel@tonic-gate 	if (!(opts.o_outpmode & OPT_TTY)) {
15197c478bd9Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_TERMCAP; /* no termcap for pipes */
15207c478bd9Sstevel@tonic-gate 		opts.o_outpmode &= ~OPT_FULLSCREEN;
15217c478bd9Sstevel@tonic-gate 	}
15227c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP)
15237c478bd9Sstevel@tonic-gate 		ldtermcap();		/* can turn OPT_TERMCAP off */
15247c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP)
15257c478bd9Sstevel@tonic-gate 		(void) setsize();
15267c478bd9Sstevel@tonic-gate 	list_alloc(&lwps, opts.o_ntop);
15277c478bd9Sstevel@tonic-gate 	list_alloc(&users, opts.o_nbottom);
15287c478bd9Sstevel@tonic-gate 	list_alloc(&tasks, opts.o_nbottom);
15297c478bd9Sstevel@tonic-gate 	list_alloc(&projects, opts.o_nbottom);
15307c478bd9Sstevel@tonic-gate 	list_alloc(&zones, opts.o_nbottom);
1531c6402783Sakolb 	list_alloc(&lgroups, opts.o_nbottom);
15327c478bd9Sstevel@tonic-gate 	list_setkeyfunc(sortk, &opts, &lwps, LT_LWPS);
15337c478bd9Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &users, LT_USERS);
15347c478bd9Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &tasks, LT_TASKS);
15357c478bd9Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &projects, LT_PROJECTS);
15367c478bd9Sstevel@tonic-gate 	list_setkeyfunc(NULL, &opts, &zones, LT_ZONES);
1537c6402783Sakolb 	list_setkeyfunc(NULL, &opts, &lgroups, LT_LGRPS);
15387c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TERMCAP)
15397c478bd9Sstevel@tonic-gate 		curses_on();
15407c478bd9Sstevel@tonic-gate 	if ((procdir = opendir("/proc")) == NULL)
15417c478bd9Sstevel@tonic-gate 		Die(gettext("cannot open /proc directory\n"));
15427c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY) {
15437c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Please wait...\r"));
1544*4944376cSJohn Levon 		if (!(opts.o_outpmode & OPT_TERMCAP))
1545*4944376cSJohn Levon 			(void) putchar('\n');
15467c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
15477c478bd9Sstevel@tonic-gate 	}
15487c478bd9Sstevel@tonic-gate 	set_signals();
15497c478bd9Sstevel@tonic-gate 	pollset.fd = STDIN_FILENO;
15507c478bd9Sstevel@tonic-gate 	pollset.events = POLLIN;
15517c478bd9Sstevel@tonic-gate 	timeout = opts.o_interval * MILLISEC;
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	/*
15547c478bd9Sstevel@tonic-gate 	 * main program loop
15557c478bd9Sstevel@tonic-gate 	 */
15567c478bd9Sstevel@tonic-gate 	do {
15577c478bd9Sstevel@tonic-gate 		if (sigterm == 1)
15587c478bd9Sstevel@tonic-gate 			break;
15597c478bd9Sstevel@tonic-gate 		if (sigtstp == 1) {
15607c478bd9Sstevel@tonic-gate 			curses_off();
15617c478bd9Sstevel@tonic-gate 			(void) signal(SIGTSTP, SIG_DFL);
15627c478bd9Sstevel@tonic-gate 			(void) kill(0, SIGTSTP);
15637c478bd9Sstevel@tonic-gate 			/*
15647c478bd9Sstevel@tonic-gate 			 * prstat stops here until it receives SIGCONT signal.
15657c478bd9Sstevel@tonic-gate 			 */
15667c478bd9Sstevel@tonic-gate 			sigtstp = 0;
15677c478bd9Sstevel@tonic-gate 			(void) signal(SIGTSTP, sig_handler);
15687c478bd9Sstevel@tonic-gate 			curses_on();
15697c478bd9Sstevel@tonic-gate 			print_movecur = FALSE;
15707c478bd9Sstevel@tonic-gate 			if (opts.o_outpmode & OPT_FULLSCREEN)
15717c478bd9Sstevel@tonic-gate 				sigwinch = 1;
15727c478bd9Sstevel@tonic-gate 		}
15737c478bd9Sstevel@tonic-gate 		if (sigwinch == 1) {
15747c478bd9Sstevel@tonic-gate 			if (setsize() == 1) {
15757c478bd9Sstevel@tonic-gate 				list_free(&lwps);
15767c478bd9Sstevel@tonic-gate 				list_free(&users);
15777c478bd9Sstevel@tonic-gate 				list_free(&tasks);
15787c478bd9Sstevel@tonic-gate 				list_free(&projects);
15797c478bd9Sstevel@tonic-gate 				list_free(&zones);
15807c478bd9Sstevel@tonic-gate 				list_alloc(&lwps, opts.o_ntop);
15817c478bd9Sstevel@tonic-gate 				list_alloc(&users, opts.o_nbottom);
15827c478bd9Sstevel@tonic-gate 				list_alloc(&tasks, opts.o_nbottom);
15837c478bd9Sstevel@tonic-gate 				list_alloc(&projects, opts.o_nbottom);
15847c478bd9Sstevel@tonic-gate 				list_alloc(&zones, opts.o_nbottom);
15857c478bd9Sstevel@tonic-gate 			}
15867c478bd9Sstevel@tonic-gate 			sigwinch = 0;
15877c478bd9Sstevel@tonic-gate 			(void) signal(SIGWINCH, sig_handler);
15887c478bd9Sstevel@tonic-gate 		}
15897c478bd9Sstevel@tonic-gate 		prstat_scandir(procdir);
15907c478bd9Sstevel@tonic-gate 		list_refresh(&lwps);
15917c478bd9Sstevel@tonic-gate 		if (print_movecur)
15927c478bd9Sstevel@tonic-gate 			(void) putp(movecur);
15937c478bd9Sstevel@tonic-gate 		print_movecur = TRUE;
15947c478bd9Sstevel@tonic-gate 		if ((opts.o_outpmode & OPT_PSINFO) ||
15957c478bd9Sstevel@tonic-gate 		    (opts.o_outpmode & OPT_MSACCT)) {
15967c478bd9Sstevel@tonic-gate 			list_sort(&lwps);
15977c478bd9Sstevel@tonic-gate 			list_print(&lwps);
15987c478bd9Sstevel@tonic-gate 		}
15997c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_USERS) {
16000209230bSgjelinek 			list_getsize(&users);
16017c478bd9Sstevel@tonic-gate 			list_sort(&users);
16027c478bd9Sstevel@tonic-gate 			list_print(&users);
16037c478bd9Sstevel@tonic-gate 			list_clear(&users);
16047c478bd9Sstevel@tonic-gate 		}
16057c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_TASKS) {
16060209230bSgjelinek 			list_getsize(&tasks);
16077c478bd9Sstevel@tonic-gate 			list_sort(&tasks);
16087c478bd9Sstevel@tonic-gate 			list_print(&tasks);
16097c478bd9Sstevel@tonic-gate 			list_clear(&tasks);
16107c478bd9Sstevel@tonic-gate 		}
16117c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_PROJECTS) {
16120209230bSgjelinek 			list_getsize(&projects);
16137c478bd9Sstevel@tonic-gate 			list_sort(&projects);
16147c478bd9Sstevel@tonic-gate 			list_print(&projects);
16157c478bd9Sstevel@tonic-gate 			list_clear(&projects);
16167c478bd9Sstevel@tonic-gate 		}
16177c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_ZONES) {
16180209230bSgjelinek 			list_getsize(&zones);
16197c478bd9Sstevel@tonic-gate 			list_sort(&zones);
16207c478bd9Sstevel@tonic-gate 			list_print(&zones);
16217c478bd9Sstevel@tonic-gate 			list_clear(&zones);
16227c478bd9Sstevel@tonic-gate 		}
16237c478bd9Sstevel@tonic-gate 		if (opts.o_count == 1)
16247c478bd9Sstevel@tonic-gate 			break;
16257c478bd9Sstevel@tonic-gate 		/*
16267c478bd9Sstevel@tonic-gate 		 * If poll() returns -1 and sets errno to EINTR here because
16277c478bd9Sstevel@tonic-gate 		 * the process received a signal, it is Ok to abort this
16287c478bd9Sstevel@tonic-gate 		 * timeout and loop around because we check the signals at the
16297c478bd9Sstevel@tonic-gate 		 * top of the loop.
16307c478bd9Sstevel@tonic-gate 		 */
16317c478bd9Sstevel@tonic-gate 		if (opts.o_outpmode & OPT_TTY) {
16327c478bd9Sstevel@tonic-gate 			if (poll(&pollset, (nfds_t)1, timeout) > 0) {
16337c478bd9Sstevel@tonic-gate 				if (read(STDIN_FILENO, &key, 1) == 1) {
16347c478bd9Sstevel@tonic-gate 					if (tolower(key) == 'q')
16357c478bd9Sstevel@tonic-gate 						break;
16367c478bd9Sstevel@tonic-gate 				}
16377c478bd9Sstevel@tonic-gate 			}
16387c478bd9Sstevel@tonic-gate 		} else {
16397c478bd9Sstevel@tonic-gate 			(void) sleep(opts.o_interval);
16407c478bd9Sstevel@tonic-gate 		}
16417c478bd9Sstevel@tonic-gate 	} while (opts.o_count == (-1) || --opts.o_count);
16427c478bd9Sstevel@tonic-gate 
16437c478bd9Sstevel@tonic-gate 	if (opts.o_outpmode & OPT_TTY)
16447c478bd9Sstevel@tonic-gate 		(void) putchar('\r');
16457c478bd9Sstevel@tonic-gate 	return (0);
16467c478bd9Sstevel@tonic-gate }
1647