10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52685Sakolb * Common Development and Distribution License (the "License").
62685Sakolb * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
212685Sakolb
220Sstevel@tonic-gate /*
239123Sjohn.levon@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
25*9966SMenno.Lageman@Sun.COM *
26*9966SMenno.Lageman@Sun.COM * Portions Copyright 2009 Chad Mynhier
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/resource.h>
310Sstevel@tonic-gate #include <sys/loadavg.h>
320Sstevel@tonic-gate #include <sys/time.h>
330Sstevel@tonic-gate #include <sys/pset.h>
343247Sgjelinek #include <sys/vm_usage.h>
350Sstevel@tonic-gate #include <zone.h>
360Sstevel@tonic-gate #include <libzonecfg.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <stdio.h>
390Sstevel@tonic-gate #include <stdlib.h>
400Sstevel@tonic-gate #include <unistd.h>
410Sstevel@tonic-gate #include <dirent.h>
420Sstevel@tonic-gate #include <string.h>
430Sstevel@tonic-gate #include <errno.h>
440Sstevel@tonic-gate #include <poll.h>
450Sstevel@tonic-gate #include <ctype.h>
460Sstevel@tonic-gate #include <fcntl.h>
470Sstevel@tonic-gate #include <limits.h>
480Sstevel@tonic-gate #include <signal.h>
490Sstevel@tonic-gate #include <time.h>
500Sstevel@tonic-gate #include <project.h>
510Sstevel@tonic-gate
529123Sjohn.levon@sun.com #include <langinfo.h>
530Sstevel@tonic-gate #include <libintl.h>
540Sstevel@tonic-gate #include <locale.h>
550Sstevel@tonic-gate
560Sstevel@tonic-gate #include "prstat.h"
570Sstevel@tonic-gate #include "prutil.h"
580Sstevel@tonic-gate #include "prtable.h"
590Sstevel@tonic-gate #include "prsort.h"
600Sstevel@tonic-gate #include "prfile.h"
610Sstevel@tonic-gate
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate * x86 <sys/regs.h> ERR conflicts with <curses.h> ERR. For the purposes
640Sstevel@tonic-gate * of this file, we care about the curses.h ERR so include that last.
650Sstevel@tonic-gate */
660Sstevel@tonic-gate
670Sstevel@tonic-gate #if defined(ERR)
680Sstevel@tonic-gate #undef ERR
690Sstevel@tonic-gate #endif
700Sstevel@tonic-gate
710Sstevel@tonic-gate #ifndef TEXT_DOMAIN /* should be defined by cc -D */
720Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* use this only if it wasn't */
730Sstevel@tonic-gate #endif
740Sstevel@tonic-gate
750Sstevel@tonic-gate #include <curses.h>
760Sstevel@tonic-gate #include <term.h>
770Sstevel@tonic-gate
780Sstevel@tonic-gate #define PSINFO_HEADER_PROC \
790Sstevel@tonic-gate " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP "
802685Sakolb #define PSINFO_HEADER_PROC_LGRP \
812685Sakolb " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/NLWP "
820Sstevel@tonic-gate #define PSINFO_HEADER_LWP \
830Sstevel@tonic-gate " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID "
842685Sakolb #define PSINFO_HEADER_LWP_LGRP \
852685Sakolb " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/LWPID "
860Sstevel@tonic-gate #define USAGE_HEADER_PROC \
870Sstevel@tonic-gate " PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP "
880Sstevel@tonic-gate #define USAGE_HEADER_LWP \
890Sstevel@tonic-gate " PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID "
900Sstevel@tonic-gate #define USER_HEADER_PROC \
913247Sgjelinek " NPROC USERNAME SWAP RSS MEMORY TIME CPU "
920Sstevel@tonic-gate #define USER_HEADER_LWP \
933247Sgjelinek " NLWP USERNAME SWAP RSS MEMORY TIME CPU "
940Sstevel@tonic-gate #define TASK_HEADER_PROC \
953247Sgjelinek "TASKID NPROC SWAP RSS MEMORY TIME CPU PROJECT "
960Sstevel@tonic-gate #define TASK_HEADER_LWP \
973247Sgjelinek "TASKID NLWP SWAP RSS MEMORY TIME CPU PROJECT "
980Sstevel@tonic-gate #define PROJECT_HEADER_PROC \
993247Sgjelinek "PROJID NPROC SWAP RSS MEMORY TIME CPU PROJECT "
1000Sstevel@tonic-gate #define PROJECT_HEADER_LWP \
1013247Sgjelinek "PROJID NLWP SWAP RSS MEMORY TIME CPU PROJECT "
1020Sstevel@tonic-gate #define ZONE_HEADER_PROC \
1033247Sgjelinek "ZONEID NPROC SWAP RSS MEMORY TIME CPU ZONE "
1040Sstevel@tonic-gate #define ZONE_HEADER_LWP \
1053247Sgjelinek "ZONEID NLWP SWAP RSS MEMORY TIME CPU ZONE "
1060Sstevel@tonic-gate #define PSINFO_LINE \
1070Sstevel@tonic-gate "%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %-.16s/%d"
1082685Sakolb #define PSINFO_LINE_LGRP \
1092685Sakolb "%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %4d %-.16s/%d"
1100Sstevel@tonic-gate #define USAGE_LINE \
1110Sstevel@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 "\
1120Sstevel@tonic-gate "%3.3s %-.12s/%d"
1130Sstevel@tonic-gate #define USER_LINE \
1140Sstevel@tonic-gate "%6d %-8s %5.5s %5.5s %3.3s%% %9s %3.3s%%"
1150Sstevel@tonic-gate #define TASK_LINE \
1160Sstevel@tonic-gate "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s"
1170Sstevel@tonic-gate #define PROJECT_LINE \
1180Sstevel@tonic-gate "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s"
1190Sstevel@tonic-gate #define ZONE_LINE \
1200Sstevel@tonic-gate "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s"
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate #define TOTAL_LINE \
1230Sstevel@tonic-gate "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f"
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /* global variables */
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate static char *t_ulon; /* termcap: start underline */
1280Sstevel@tonic-gate static char *t_uloff; /* termcap: end underline */
1290Sstevel@tonic-gate static char *t_up; /* termcap: cursor 1 line up */
1300Sstevel@tonic-gate static char *t_eol; /* termcap: clear end of line */
1310Sstevel@tonic-gate static char *t_smcup; /* termcap: cursor mvcap on */
1320Sstevel@tonic-gate static char *t_rmcup; /* termcap: cursor mvcap off */
1330Sstevel@tonic-gate static char *t_home; /* termcap: move cursor home */
1340Sstevel@tonic-gate static char *movecur = NULL; /* termcap: move up string */
1350Sstevel@tonic-gate static char *empty_string = "\0"; /* termcap: empty string */
1360Sstevel@tonic-gate static uint_t print_movecur = FALSE; /* print movecur or not */
1370Sstevel@tonic-gate static int is_curses_on = FALSE; /* current curses state */
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate static table_t pid_tbl = {0, 0, NULL}; /* selected processes */
1400Sstevel@tonic-gate static table_t cpu_tbl = {0, 0, NULL}; /* selected processors */
1410Sstevel@tonic-gate static table_t set_tbl = {0, 0, NULL}; /* selected processor sets */
1420Sstevel@tonic-gate static table_t prj_tbl = {0, 0, NULL}; /* selected projects */
1430Sstevel@tonic-gate static table_t tsk_tbl = {0, 0, NULL}; /* selected tasks */
1442685Sakolb static table_t lgr_tbl = {0, 0, NULL}; /* selected lgroups */
1450Sstevel@tonic-gate static zonetbl_t zone_tbl = {0, 0, NULL}; /* selected zones */
146*9966SMenno.Lageman@Sun.COM static uidtbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */
147*9966SMenno.Lageman@Sun.COM static uidtbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate static uint_t total_procs; /* total number of procs */
1500Sstevel@tonic-gate static uint_t total_lwps; /* total number of lwps */
1510Sstevel@tonic-gate static float total_cpu; /* total cpu usage */
1520Sstevel@tonic-gate static float total_mem; /* total memory usage */
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate static list_t lwps; /* list of lwps/processes */
1550Sstevel@tonic-gate static list_t users; /* list of users */
1560Sstevel@tonic-gate static list_t tasks; /* list of tasks */
1570Sstevel@tonic-gate static list_t projects; /* list of projects */
1580Sstevel@tonic-gate static list_t zones; /* list of zones */
1592685Sakolb static list_t lgroups; /* list of lgroups */
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate static volatile uint_t sigwinch = 0;
1620Sstevel@tonic-gate static volatile uint_t sigtstp = 0;
1630Sstevel@tonic-gate static volatile uint_t sigterm = 0;
1640Sstevel@tonic-gate
1653247Sgjelinek static long pagesize;
1663247Sgjelinek
1670Sstevel@tonic-gate /* default settings */
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate static optdesc_t opts = {
1700Sstevel@tonic-gate 5, /* interval between updates, seconds */
1710Sstevel@tonic-gate 15, /* number of lines in top part */
1720Sstevel@tonic-gate 5, /* number of lines in bottom part */
1730Sstevel@tonic-gate -1, /* number of iterations; infinitely */
1740Sstevel@tonic-gate OPT_PSINFO | OPT_FULLSCREEN | OPT_USEHOME | OPT_TERMCAP,
1750Sstevel@tonic-gate -1 /* sort in decreasing order */
1760Sstevel@tonic-gate };
1770Sstevel@tonic-gate
1789123Sjohn.levon@sun.com /*
1799123Sjohn.levon@sun.com * Print timestamp as decimal reprentation of time_t value (-d u was specified)
1809123Sjohn.levon@sun.com * or the standard date format (-d d was specified).
1819123Sjohn.levon@sun.com */
1829123Sjohn.levon@sun.com static void
print_timestamp(void)1839123Sjohn.levon@sun.com print_timestamp(void)
1849123Sjohn.levon@sun.com {
1859123Sjohn.levon@sun.com time_t t = time(NULL);
1869123Sjohn.levon@sun.com static char *fmt = NULL;
1879123Sjohn.levon@sun.com
1889123Sjohn.levon@sun.com /* We only need to retrieve this once per invocation */
1899123Sjohn.levon@sun.com if (fmt == NULL)
1909123Sjohn.levon@sun.com fmt = nl_langinfo(_DATE_FMT);
1919123Sjohn.levon@sun.com
1929123Sjohn.levon@sun.com if (opts.o_outpmode & OPT_UDATE) {
1939123Sjohn.levon@sun.com (void) printf("%ld", t);
1949123Sjohn.levon@sun.com } else if (opts.o_outpmode & OPT_DDATE) {
1959123Sjohn.levon@sun.com char dstr[64];
1969123Sjohn.levon@sun.com int len;
1979123Sjohn.levon@sun.com
1989123Sjohn.levon@sun.com len = strftime(dstr, sizeof (dstr), fmt, localtime(&t));
1999123Sjohn.levon@sun.com if (len > 0)
2009123Sjohn.levon@sun.com (void) printf("%s", dstr);
2019123Sjohn.levon@sun.com }
2029123Sjohn.levon@sun.com (void) putp(t_eol);
2039123Sjohn.levon@sun.com (void) putchar('\n');
2049123Sjohn.levon@sun.com }
2059123Sjohn.levon@sun.com
2060Sstevel@tonic-gate static void
psetloadavg(long psetid,void * ptr)2070Sstevel@tonic-gate psetloadavg(long psetid, void *ptr)
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate double psetloadavg[3];
2100Sstevel@tonic-gate double *loadavg = ptr;
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate if (pset_getloadavg((psetid_t)psetid, psetloadavg, 3) != -1) {
2130Sstevel@tonic-gate *loadavg++ += psetloadavg[0];
2140Sstevel@tonic-gate *loadavg++ += psetloadavg[1];
2150Sstevel@tonic-gate *loadavg += psetloadavg[2];
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate /*
2203247Sgjelinek * Queries the memory virtual and rss size for each member of a list.
2213247Sgjelinek * This will override the values computed by /proc aggregation.
2223247Sgjelinek */
2233247Sgjelinek static void
list_getsize(list_t * list)2243247Sgjelinek list_getsize(list_t *list)
2253247Sgjelinek {
2263247Sgjelinek id_info_t *id;
2273247Sgjelinek vmusage_t *results, *next;
2283247Sgjelinek vmusage_t *match;
2293247Sgjelinek size_t nres = 0;
2303247Sgjelinek size_t i;
2313247Sgjelinek uint_t flags = 0;
2323247Sgjelinek int ret;
2333247Sgjelinek size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize;
2343247Sgjelinek
2353247Sgjelinek /*
2363247Sgjelinek * Determine what swap/rss results to calculate. getvmusage() will
2373247Sgjelinek * prune results returned to non-global zones automatically, so
2383247Sgjelinek * there is no need to pass different flags when calling from a
2393247Sgjelinek * non-global zone.
2403247Sgjelinek *
2413247Sgjelinek * Currently list_getsize() is only called with a single flag. This
2423247Sgjelinek * is because -Z, -J, -T, and -a are mutually exclusive. Regardless
2433247Sgjelinek * of this, we handle multiple flags.
2443247Sgjelinek */
2453247Sgjelinek if (opts.o_outpmode & OPT_USERS) {
2463247Sgjelinek /*
2473247Sgjelinek * Gather rss for all users in all zones. Treat the same
2483247Sgjelinek * uid in different zones as the same user.
2493247Sgjelinek */
2503247Sgjelinek flags |= VMUSAGE_COL_RUSERS;
2513247Sgjelinek
2523247Sgjelinek } else if (opts.o_outpmode & OPT_TASKS) {
2533247Sgjelinek /* Gather rss for all tasks in all zones */
2543247Sgjelinek flags |= VMUSAGE_ALL_TASKS;
2553247Sgjelinek
2563247Sgjelinek } else if (opts.o_outpmode & OPT_PROJECTS) {
2573247Sgjelinek /*
2583247Sgjelinek * Gather rss for all projects in all zones. Treat the same
2593247Sgjelinek * projid in diffrent zones as the same project.
2603247Sgjelinek */
2613247Sgjelinek flags |= VMUSAGE_COL_PROJECTS;
2623247Sgjelinek
2633247Sgjelinek } else if (opts.o_outpmode & OPT_ZONES) {
2643247Sgjelinek /* Gather rss for all zones */
2653247Sgjelinek flags |= VMUSAGE_ALL_ZONES;
2663247Sgjelinek
2673247Sgjelinek } else {
2683247Sgjelinek Die(gettext(
2693247Sgjelinek "Cannot determine rss flags for output options %x\n"),
2703247Sgjelinek opts.o_outpmode);
2713247Sgjelinek }
2723247Sgjelinek
2733247Sgjelinek /*
2743247Sgjelinek * getvmusage() returns an array of result structures. One for
2753247Sgjelinek * each zone, project, task, or user on the system, depending on
2763247Sgjelinek * flags.
2773247Sgjelinek *
2783247Sgjelinek * If getvmusage() fails, prstat will use the size already gathered
2793247Sgjelinek * from psinfo
2803247Sgjelinek */
2813247Sgjelinek if (getvmusage(flags, opts.o_interval, NULL, &nres) != 0)
2823247Sgjelinek return;
2833247Sgjelinek
2843247Sgjelinek results = (vmusage_t *)Malloc(sizeof (vmusage_t) * nres);
2853247Sgjelinek for (;;) {
2863247Sgjelinek ret = getvmusage(flags, opts.o_interval, results, &nres);
2873247Sgjelinek if (ret == 0)
2883247Sgjelinek break;
2893247Sgjelinek if (errno == EOVERFLOW) {
2903247Sgjelinek results = (vmusage_t *)Realloc(results,
2913247Sgjelinek sizeof (vmusage_t) * nres);
2923247Sgjelinek continue;
2933247Sgjelinek }
2943247Sgjelinek /*
2953247Sgjelinek * Failure for some other reason. Prstat will use the size
2963247Sgjelinek * already gathered from psinfo.
2973247Sgjelinek */
2989524Sgerald.jelinek@sun.com free(results);
2993247Sgjelinek return;
3003247Sgjelinek }
3013247Sgjelinek for (id = list->l_head; id != NULL; id = id->id_next) {
3023247Sgjelinek
3033247Sgjelinek match = NULL;
3043247Sgjelinek next = results;
3053247Sgjelinek for (i = 0; i < nres; i++, next++) {
3063247Sgjelinek switch (flags) {
3073247Sgjelinek case VMUSAGE_COL_RUSERS:
3083247Sgjelinek if (next->vmu_id == id->id_uid)
3093247Sgjelinek match = next;
3103247Sgjelinek break;
3113247Sgjelinek case VMUSAGE_ALL_TASKS:
3123247Sgjelinek if (next->vmu_id == id->id_taskid)
3133247Sgjelinek match = next;
3143247Sgjelinek break;
3153247Sgjelinek case VMUSAGE_COL_PROJECTS:
3163247Sgjelinek if (next->vmu_id == id->id_projid)
3173247Sgjelinek match = next;
3183247Sgjelinek break;
3193247Sgjelinek case VMUSAGE_ALL_ZONES:
3203247Sgjelinek if (next->vmu_id == id->id_zoneid)
3213247Sgjelinek match = next;
3223247Sgjelinek break;
3233247Sgjelinek default:
3243247Sgjelinek Die(gettext(
3253247Sgjelinek "Unknown vmusage flags %d\n"), flags);
3263247Sgjelinek }
3273247Sgjelinek }
3283247Sgjelinek if (match != NULL) {
3293247Sgjelinek id->id_size = match->vmu_swap_all / 1024;
3303247Sgjelinek id->id_rssize = match->vmu_rss_all / 1024;
3313247Sgjelinek id->id_pctmem = (100.0 * (float)match->vmu_rss_all) /
3323247Sgjelinek (float)physmem;
3333247Sgjelinek /* Output using data from getvmusage() */
3343247Sgjelinek id->id_sizematch = B_TRUE;
3353247Sgjelinek }
3363247Sgjelinek /*
3373247Sgjelinek * If no match is found, prstat will use the size already
3383247Sgjelinek * gathered from psinfo.
3393247Sgjelinek */
3403247Sgjelinek }
3419524Sgerald.jelinek@sun.com free(results);
3423247Sgjelinek }
3433247Sgjelinek
3443247Sgjelinek /*
3450Sstevel@tonic-gate * A routine to display the contents of the list on the screen
3460Sstevel@tonic-gate */
3470Sstevel@tonic-gate static void
list_print(list_t * list)3480Sstevel@tonic-gate list_print(list_t *list)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate lwp_info_t *lwp;
3510Sstevel@tonic-gate id_info_t *id;
3520Sstevel@tonic-gate char usr[4], sys[4], trp[4], tfl[4];
3530Sstevel@tonic-gate char dfl[4], lck[4], slp[4], lat[4];
3540Sstevel@tonic-gate char vcx[4], icx[4], scl[4], sig[4];
3550Sstevel@tonic-gate char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12];
3560Sstevel@tonic-gate char pstate[7], pnice[4], ppri[4];
3570Sstevel@tonic-gate char pname[LOGNAME_MAX+1];
3580Sstevel@tonic-gate char projname[PROJNAME_MAX+1];
3590Sstevel@tonic-gate char zonename[ZONENAME_MAX+1];
3600Sstevel@tonic-gate float cpu, mem;
3610Sstevel@tonic-gate double loadavg[3] = {0, 0, 0};
3620Sstevel@tonic-gate int i, lwpid;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate if (foreach_element(&set_tbl, &loadavg, psetloadavg) == 0) {
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate * If processor sets aren't specified, we display system-wide
3670Sstevel@tonic-gate * load averages.
3680Sstevel@tonic-gate */
3690Sstevel@tonic-gate (void) getloadavg(loadavg, 3);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3729123Sjohn.levon@sun.com if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)) &&
3739123Sjohn.levon@sun.com ((list->l_type == LT_LWPS) || !(opts.o_outpmode & OPT_SPLIT)))
3749123Sjohn.levon@sun.com print_timestamp();
3750Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
3760Sstevel@tonic-gate (void) putchar('\r');
3770Sstevel@tonic-gate (void) putp(t_ulon);
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate switch (list->l_type) {
3800Sstevel@tonic-gate case LT_PROJECTS:
3810Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
3820Sstevel@tonic-gate (void) printf(PROJECT_HEADER_LWP);
3830Sstevel@tonic-gate else
3840Sstevel@tonic-gate (void) printf(PROJECT_HEADER_PROC);
3850Sstevel@tonic-gate break;
3860Sstevel@tonic-gate case LT_TASKS:
3870Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
3880Sstevel@tonic-gate (void) printf(TASK_HEADER_LWP);
3890Sstevel@tonic-gate else
3900Sstevel@tonic-gate (void) printf(TASK_HEADER_PROC);
3910Sstevel@tonic-gate break;
3920Sstevel@tonic-gate case LT_ZONES:
3930Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
3940Sstevel@tonic-gate (void) printf(ZONE_HEADER_LWP);
3950Sstevel@tonic-gate else
3960Sstevel@tonic-gate (void) printf(ZONE_HEADER_PROC);
3970Sstevel@tonic-gate break;
3980Sstevel@tonic-gate case LT_USERS:
3990Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
4000Sstevel@tonic-gate (void) printf(USER_HEADER_LWP);
4010Sstevel@tonic-gate else
4020Sstevel@tonic-gate (void) printf(USER_HEADER_PROC);
4030Sstevel@tonic-gate break;
4040Sstevel@tonic-gate case LT_LWPS:
4050Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) {
4062685Sakolb if (opts.o_outpmode & OPT_PSINFO) {
4072685Sakolb if (opts.o_outpmode & OPT_LGRP)
4082685Sakolb (void) printf(PSINFO_HEADER_LWP_LGRP);
4092685Sakolb else
4102685Sakolb (void) printf(PSINFO_HEADER_LWP);
4112685Sakolb }
4120Sstevel@tonic-gate if (opts.o_outpmode & OPT_MSACCT)
4130Sstevel@tonic-gate (void) printf(USAGE_HEADER_LWP);
4140Sstevel@tonic-gate } else {
4152685Sakolb if (opts.o_outpmode & OPT_PSINFO) {
4162685Sakolb if (opts.o_outpmode & OPT_LGRP)
4172685Sakolb (void) printf(PSINFO_HEADER_PROC_LGRP);
4182685Sakolb else
4192685Sakolb (void) printf(PSINFO_HEADER_PROC);
4202685Sakolb }
4210Sstevel@tonic-gate if (opts.o_outpmode & OPT_MSACCT)
4220Sstevel@tonic-gate (void) printf(USAGE_HEADER_PROC);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate break;
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate (void) putp(t_uloff);
4280Sstevel@tonic-gate (void) putp(t_eol);
4290Sstevel@tonic-gate (void) putchar('\n');
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate for (i = 0; i < list->l_used; i++) {
4320Sstevel@tonic-gate switch (list->l_type) {
4330Sstevel@tonic-gate case LT_PROJECTS:
4340Sstevel@tonic-gate case LT_TASKS:
4350Sstevel@tonic-gate case LT_USERS:
4360Sstevel@tonic-gate case LT_ZONES:
4370Sstevel@tonic-gate id = list->l_ptrs[i];
4380Sstevel@tonic-gate /*
4390Sstevel@tonic-gate * CPU usage and memory usage normalization
4400Sstevel@tonic-gate */
4410Sstevel@tonic-gate if (total_cpu >= 100)
4420Sstevel@tonic-gate cpu = (100 * id->id_pctcpu) / total_cpu;
4430Sstevel@tonic-gate else
4440Sstevel@tonic-gate cpu = id->id_pctcpu;
4453247Sgjelinek if (id->id_sizematch == B_FALSE && total_mem >= 100)
4460Sstevel@tonic-gate mem = (100 * id->id_pctmem) / total_mem;
4470Sstevel@tonic-gate else
4480Sstevel@tonic-gate mem = id->id_pctmem;
4490Sstevel@tonic-gate if (list->l_type == LT_USERS)
450*9966SMenno.Lageman@Sun.COM pwd_getname(id->id_uid, pname, LOGNAME_MAX + 1,
451*9966SMenno.Lageman@Sun.COM opts.o_outpmode & OPT_NORESOLVE);
4520Sstevel@tonic-gate else if (list->l_type == LT_ZONES)
4530Sstevel@tonic-gate getzonename(id->id_zoneid, zonename,
4540Sstevel@tonic-gate ZONENAME_MAX);
4550Sstevel@tonic-gate else
4560Sstevel@tonic-gate getprojname(id->id_projid, projname,
457*9966SMenno.Lageman@Sun.COM PROJNAME_MAX,
458*9966SMenno.Lageman@Sun.COM opts.o_outpmode & OPT_NORESOLVE);
4590Sstevel@tonic-gate Format_size(psize, id->id_size, 6);
4600Sstevel@tonic-gate Format_size(prssize, id->id_rssize, 6);
4610Sstevel@tonic-gate Format_pct(pmem, mem, 4);
4620Sstevel@tonic-gate Format_pct(pcpu, cpu, 4);
4630Sstevel@tonic-gate Format_time(ptime, id->id_time, 10);
4640Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
4650Sstevel@tonic-gate (void) putchar('\r');
4660Sstevel@tonic-gate if (list->l_type == LT_PROJECTS)
4670Sstevel@tonic-gate (void) printf(PROJECT_LINE, (int)id->id_projid,
4680Sstevel@tonic-gate id->id_nproc, psize, prssize, pmem, ptime,
4690Sstevel@tonic-gate pcpu, projname);
4700Sstevel@tonic-gate else if (list->l_type == LT_TASKS)
4710Sstevel@tonic-gate (void) printf(TASK_LINE, (int)id->id_taskid,
4720Sstevel@tonic-gate id->id_nproc, psize, prssize, pmem, ptime,
4730Sstevel@tonic-gate pcpu, projname);
4740Sstevel@tonic-gate else if (list->l_type == LT_ZONES)
4750Sstevel@tonic-gate (void) printf(ZONE_LINE, (int)id->id_zoneid,
4760Sstevel@tonic-gate id->id_nproc, psize, prssize, pmem, ptime,
4770Sstevel@tonic-gate pcpu, zonename);
4780Sstevel@tonic-gate else
4790Sstevel@tonic-gate (void) printf(USER_LINE, id->id_nproc, pname,
4800Sstevel@tonic-gate psize, prssize, pmem, ptime, pcpu);
4810Sstevel@tonic-gate (void) putp(t_eol);
4820Sstevel@tonic-gate (void) putchar('\n');
4830Sstevel@tonic-gate break;
4840Sstevel@tonic-gate case LT_LWPS:
4850Sstevel@tonic-gate lwp = list->l_ptrs[i];
4860Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
4870Sstevel@tonic-gate lwpid = lwp->li_info.pr_lwp.pr_lwpid;
4880Sstevel@tonic-gate else
4890Sstevel@tonic-gate lwpid = lwp->li_info.pr_nlwp +
4900Sstevel@tonic-gate lwp->li_info.pr_nzomb;
491*9966SMenno.Lageman@Sun.COM pwd_getname(lwp->li_info.pr_uid, pname, LOGNAME_MAX + 1,
492*9966SMenno.Lageman@Sun.COM opts.o_outpmode & OPT_NORESOLVE);
4930Sstevel@tonic-gate if (opts.o_outpmode & OPT_PSINFO) {
4940Sstevel@tonic-gate Format_size(psize, lwp->li_info.pr_size, 6);
4950Sstevel@tonic-gate Format_size(prssize, lwp->li_info.pr_rssize, 6);
4960Sstevel@tonic-gate Format_state(pstate,
4970Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_sname,
4980Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_onpro, 7);
4990Sstevel@tonic-gate if (strcmp(lwp->li_info.pr_lwp.pr_clname,
5000Sstevel@tonic-gate "RT") == 0 ||
5010Sstevel@tonic-gate strcmp(lwp->li_info.pr_lwp.pr_clname,
5020Sstevel@tonic-gate "SYS") == 0 ||
5030Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_sname == 'Z')
5040Sstevel@tonic-gate (void) strcpy(pnice, " -");
5050Sstevel@tonic-gate else
5060Sstevel@tonic-gate Format_num(pnice,
5070Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_nice - NZERO,
5080Sstevel@tonic-gate 4);
5090Sstevel@tonic-gate Format_num(ppri, lwp->li_info.pr_lwp.pr_pri, 4);
5100Sstevel@tonic-gate Format_pct(pcpu,
5110Sstevel@tonic-gate FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu), 4);
5120Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
5130Sstevel@tonic-gate Format_time(ptime,
5140Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_time.tv_sec,
5150Sstevel@tonic-gate 10);
5160Sstevel@tonic-gate else
5170Sstevel@tonic-gate Format_time(ptime,
5180Sstevel@tonic-gate lwp->li_info.pr_time.tv_sec, 10);
5190Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
5200Sstevel@tonic-gate (void) putchar('\r');
5210Sstevel@tonic-gate stripfname(lwp->li_info.pr_fname);
5222685Sakolb if (opts.o_outpmode & OPT_LGRP) {
5232685Sakolb (void) printf(PSINFO_LINE_LGRP,
5242685Sakolb (int)lwp->li_info.pr_pid, pname,
5252685Sakolb psize, prssize, pstate, ppri, pnice,
5262685Sakolb ptime, pcpu,
5272685Sakolb (int)lwp->li_info.pr_lwp.pr_lgrp,
5282685Sakolb lwp->li_info.pr_fname, lwpid);
5292685Sakolb } else {
5302685Sakolb (void) printf(PSINFO_LINE,
5312685Sakolb (int)lwp->li_info.pr_pid, pname,
5322685Sakolb psize, prssize, pstate, ppri, pnice,
5332685Sakolb ptime, pcpu,
5342685Sakolb lwp->li_info.pr_fname, lwpid);
5352685Sakolb }
5360Sstevel@tonic-gate (void) putp(t_eol);
5370Sstevel@tonic-gate (void) putchar('\n');
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate if (opts.o_outpmode & OPT_MSACCT) {
5400Sstevel@tonic-gate Format_pct(usr, lwp->li_usr, 4);
5410Sstevel@tonic-gate Format_pct(sys, lwp->li_sys, 4);
5420Sstevel@tonic-gate Format_pct(slp, lwp->li_slp, 4);
5430Sstevel@tonic-gate Format_num(vcx, lwp->li_vcx, 4);
5440Sstevel@tonic-gate Format_num(icx, lwp->li_icx, 4);
5450Sstevel@tonic-gate Format_num(scl, lwp->li_scl, 4);
5460Sstevel@tonic-gate Format_num(sig, lwp->li_sig, 4);
5470Sstevel@tonic-gate Format_pct(trp, lwp->li_trp, 4);
5480Sstevel@tonic-gate Format_pct(tfl, lwp->li_tfl, 4);
5490Sstevel@tonic-gate Format_pct(dfl, lwp->li_dfl, 4);
5500Sstevel@tonic-gate Format_pct(lck, lwp->li_lck, 4);
5510Sstevel@tonic-gate Format_pct(lat, lwp->li_lat, 4);
5520Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
5530Sstevel@tonic-gate (void) putchar('\r');
5540Sstevel@tonic-gate stripfname(lwp->li_info.pr_fname);
5550Sstevel@tonic-gate (void) printf(USAGE_LINE,
5560Sstevel@tonic-gate (int)lwp->li_info.pr_pid, pname,
5570Sstevel@tonic-gate usr, sys, trp, tfl, dfl, lck,
5580Sstevel@tonic-gate slp, lat, vcx, icx, scl, sig,
5590Sstevel@tonic-gate lwp->li_info.pr_fname, lwpid);
5600Sstevel@tonic-gate (void) putp(t_eol);
5610Sstevel@tonic-gate (void) putchar('\n');
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate break;
5640Sstevel@tonic-gate }
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
5680Sstevel@tonic-gate (void) putchar('\r');
5690Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP) {
5700Sstevel@tonic-gate switch (list->l_type) {
5710Sstevel@tonic-gate case LT_PROJECTS:
5720Sstevel@tonic-gate case LT_USERS:
5730Sstevel@tonic-gate case LT_TASKS:
5740Sstevel@tonic-gate case LT_ZONES:
5750Sstevel@tonic-gate while (i++ < opts.o_nbottom) {
5760Sstevel@tonic-gate (void) putp(t_eol);
5770Sstevel@tonic-gate (void) putchar('\n');
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate break;
5800Sstevel@tonic-gate case LT_LWPS:
5810Sstevel@tonic-gate while (i++ < opts.o_ntop) {
5820Sstevel@tonic-gate (void) putp(t_eol);
5830Sstevel@tonic-gate (void) putchar('\n');
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
5890Sstevel@tonic-gate (void) putchar('\r');
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate if ((opts.o_outpmode & OPT_SPLIT) && list->l_type == LT_LWPS)
5920Sstevel@tonic-gate return;
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate (void) printf(TOTAL_LINE, total_procs, total_lwps,
5950Sstevel@tonic-gate loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN],
5960Sstevel@tonic-gate loadavg[LOADAVG_15MIN]);
5970Sstevel@tonic-gate (void) putp(t_eol);
5980Sstevel@tonic-gate (void) putchar('\n');
5990Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
6000Sstevel@tonic-gate (void) putchar('\r');
6010Sstevel@tonic-gate (void) putp(t_eol);
6020Sstevel@tonic-gate (void) fflush(stdout);
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate static lwp_info_t *
list_add_lwp(list_t * list,pid_t pid,id_t lwpid)6060Sstevel@tonic-gate list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
6070Sstevel@tonic-gate {
6080Sstevel@tonic-gate lwp_info_t *lwp;
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate if (list->l_head == NULL) {
6110Sstevel@tonic-gate list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
6120Sstevel@tonic-gate } else {
6130Sstevel@tonic-gate lwp = Zalloc(sizeof (lwp_info_t));
6140Sstevel@tonic-gate lwp->li_prev = list->l_tail;
6150Sstevel@tonic-gate ((lwp_info_t *)list->l_tail)->li_next = lwp;
6160Sstevel@tonic-gate list->l_tail = lwp;
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate lwp->li_info.pr_pid = pid;
6190Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_lwpid = lwpid;
6200Sstevel@tonic-gate lwpid_add(lwp, pid, lwpid);
6210Sstevel@tonic-gate list->l_count++;
6220Sstevel@tonic-gate return (lwp);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate static void
list_remove_lwp(list_t * list,lwp_info_t * lwp)6260Sstevel@tonic-gate list_remove_lwp(list_t *list, lwp_info_t *lwp)
6270Sstevel@tonic-gate {
6280Sstevel@tonic-gate if (lwp->li_prev)
6290Sstevel@tonic-gate lwp->li_prev->li_next = lwp->li_next;
6300Sstevel@tonic-gate else
6310Sstevel@tonic-gate list->l_head = lwp->li_next; /* removing the head */
6320Sstevel@tonic-gate if (lwp->li_next)
6330Sstevel@tonic-gate lwp->li_next->li_prev = lwp->li_prev;
6340Sstevel@tonic-gate else
6350Sstevel@tonic-gate list->l_tail = lwp->li_prev; /* removing the tail */
6360Sstevel@tonic-gate lwpid_del(lwp->li_info.pr_pid, lwp->li_info.pr_lwp.pr_lwpid);
6370Sstevel@tonic-gate if (lwpid_pidcheck(lwp->li_info.pr_pid) == 0)
6380Sstevel@tonic-gate fds_rm(lwp->li_info.pr_pid);
6390Sstevel@tonic-gate list->l_count--;
6400Sstevel@tonic-gate free(lwp);
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate static void
list_clear(list_t * list)6440Sstevel@tonic-gate list_clear(list_t *list)
6450Sstevel@tonic-gate {
6460Sstevel@tonic-gate if (list->l_type == LT_LWPS) {
6470Sstevel@tonic-gate lwp_info_t *lwp = list->l_tail;
6480Sstevel@tonic-gate lwp_info_t *lwp_tmp;
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate fd_closeall();
6510Sstevel@tonic-gate while (lwp) {
6520Sstevel@tonic-gate lwp_tmp = lwp;
6530Sstevel@tonic-gate lwp = lwp->li_prev;
6540Sstevel@tonic-gate list_remove_lwp(&lwps, lwp_tmp);
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate } else {
6570Sstevel@tonic-gate id_info_t *id = list->l_head;
6580Sstevel@tonic-gate id_info_t *nextid;
6590Sstevel@tonic-gate
6600Sstevel@tonic-gate while (id) {
6610Sstevel@tonic-gate nextid = id->id_next;
6620Sstevel@tonic-gate free(id);
6630Sstevel@tonic-gate id = nextid;
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate list->l_count = 0;
6660Sstevel@tonic-gate list->l_head = list->l_tail = NULL;
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate static void
list_update(list_t * list,lwp_info_t * lwp)6710Sstevel@tonic-gate list_update(list_t *list, lwp_info_t *lwp)
6720Sstevel@tonic-gate {
6730Sstevel@tonic-gate id_info_t *id;
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate if (list->l_head == NULL) { /* first element */
6760Sstevel@tonic-gate list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
6770Sstevel@tonic-gate goto update;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate for (id = list->l_head; id; id = id->id_next) {
6810Sstevel@tonic-gate if ((list->l_type == LT_USERS) &&
6820Sstevel@tonic-gate (id->id_uid != lwp->li_info.pr_uid))
6830Sstevel@tonic-gate continue;
6840Sstevel@tonic-gate if ((list->l_type == LT_TASKS) &&
6850Sstevel@tonic-gate (id->id_taskid != lwp->li_info.pr_taskid))
6860Sstevel@tonic-gate continue;
6870Sstevel@tonic-gate if ((list->l_type == LT_PROJECTS) &&
6880Sstevel@tonic-gate (id->id_projid != lwp->li_info.pr_projid))
6890Sstevel@tonic-gate continue;
6900Sstevel@tonic-gate if ((list->l_type == LT_ZONES) &&
6910Sstevel@tonic-gate (id->id_zoneid != lwp->li_info.pr_zoneid))
6920Sstevel@tonic-gate continue;
6932685Sakolb if ((list->l_type == LT_LGRPS) &&
6942685Sakolb (id->id_lgroup != lwp->li_info.pr_lwp.pr_lgrp))
6952685Sakolb continue;
6960Sstevel@tonic-gate id->id_nproc++;
6970Sstevel@tonic-gate id->id_taskid = lwp->li_info.pr_taskid;
6980Sstevel@tonic-gate id->id_projid = lwp->li_info.pr_projid;
6990Sstevel@tonic-gate id->id_zoneid = lwp->li_info.pr_zoneid;
7002685Sakolb id->id_lgroup = lwp->li_info.pr_lwp.pr_lgrp;
7012685Sakolb
7020Sstevel@tonic-gate if (lwp->li_flags & LWP_REPRESENT) {
7030Sstevel@tonic-gate id->id_size += lwp->li_info.pr_size;
7040Sstevel@tonic-gate id->id_rssize += lwp->li_info.pr_rssize;
7050Sstevel@tonic-gate }
7060Sstevel@tonic-gate id->id_pctcpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
7070Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
7080Sstevel@tonic-gate id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time);
7090Sstevel@tonic-gate else
7100Sstevel@tonic-gate id->id_time += TIME2SEC(lwp->li_info.pr_time);
7110Sstevel@tonic-gate id->id_pctmem += FRC2PCT(lwp->li_info.pr_pctmem);
7120Sstevel@tonic-gate id->id_key += lwp->li_key;
7130Sstevel@tonic-gate total_cpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
7140Sstevel@tonic-gate total_mem += FRC2PCT(lwp->li_info.pr_pctmem);
7150Sstevel@tonic-gate return;
7160Sstevel@tonic-gate }
7170Sstevel@tonic-gate
7180Sstevel@tonic-gate id = list->l_tail;
7190Sstevel@tonic-gate id->id_next = Zalloc(sizeof (id_info_t));
7200Sstevel@tonic-gate id->id_next->id_prev = list->l_tail;
7210Sstevel@tonic-gate id->id_next->id_next = NULL;
7220Sstevel@tonic-gate list->l_tail = id->id_next;
7230Sstevel@tonic-gate id = list->l_tail;
7240Sstevel@tonic-gate update:
7250Sstevel@tonic-gate id->id_uid = lwp->li_info.pr_uid;
7260Sstevel@tonic-gate id->id_projid = lwp->li_info.pr_projid;
7270Sstevel@tonic-gate id->id_taskid = lwp->li_info.pr_taskid;
7280Sstevel@tonic-gate id->id_zoneid = lwp->li_info.pr_zoneid;
7292685Sakolb id->id_lgroup = lwp->li_info.pr_lwp.pr_lgrp;
7300Sstevel@tonic-gate id->id_nproc++;
7313247Sgjelinek id->id_sizematch = B_FALSE;
7320Sstevel@tonic-gate if (lwp->li_flags & LWP_REPRESENT) {
7330Sstevel@tonic-gate id->id_size = lwp->li_info.pr_size;
7340Sstevel@tonic-gate id->id_rssize = lwp->li_info.pr_rssize;
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate id->id_pctcpu = FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
7370Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS)
7380Sstevel@tonic-gate id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time);
7390Sstevel@tonic-gate else
7400Sstevel@tonic-gate id->id_time = TIME2SEC(lwp->li_info.pr_time);
7410Sstevel@tonic-gate id->id_pctmem = FRC2PCT(lwp->li_info.pr_pctmem);
7420Sstevel@tonic-gate id->id_key = lwp->li_key;
7430Sstevel@tonic-gate total_cpu += id->id_pctcpu;
7440Sstevel@tonic-gate total_mem += id->id_pctmem;
7450Sstevel@tonic-gate list->l_count++;
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate static void
lwp_update(lwp_info_t * lwp,pid_t pid,id_t lwpid,struct prusage * usage)7490Sstevel@tonic-gate lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage)
7500Sstevel@tonic-gate {
7510Sstevel@tonic-gate float period;
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate if (!lwpid_is_active(pid, lwpid)) {
7540Sstevel@tonic-gate /*
7550Sstevel@tonic-gate * If we are reading cpu times for the first time then
7560Sstevel@tonic-gate * calculate average cpu times based on whole process
7570Sstevel@tonic-gate * execution time.
7580Sstevel@tonic-gate */
7590Sstevel@tonic-gate (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
7600Sstevel@tonic-gate period = TIME2NSEC(usage->pr_rtime);
7610Sstevel@tonic-gate period = period/(float)100;
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate if (period == 0) { /* zombie */
7640Sstevel@tonic-gate period = 1;
7650Sstevel@tonic-gate lwp->li_usr = 0;
7660Sstevel@tonic-gate lwp->li_sys = 0;
7670Sstevel@tonic-gate lwp->li_slp = 0;
7680Sstevel@tonic-gate } else {
7690Sstevel@tonic-gate lwp->li_usr = TIME2NSEC(usage->pr_utime)/period;
7700Sstevel@tonic-gate lwp->li_sys = TIME2NSEC(usage->pr_stime)/period;
7710Sstevel@tonic-gate lwp->li_slp = TIME2NSEC(usage->pr_slptime)/period;
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate lwp->li_trp = TIME2NSEC(usage->pr_ttime)/period;
7740Sstevel@tonic-gate lwp->li_tfl = TIME2NSEC(usage->pr_tftime)/period;
7750Sstevel@tonic-gate lwp->li_dfl = TIME2NSEC(usage->pr_dftime)/period;
7760Sstevel@tonic-gate lwp->li_lck = TIME2NSEC(usage->pr_ltime)/period;
7770Sstevel@tonic-gate lwp->li_lat = TIME2NSEC(usage->pr_wtime)/period;
7780Sstevel@tonic-gate period = (period / NANOSEC)*(float)100; /* now in seconds */
7790Sstevel@tonic-gate lwp->li_vcx = (ulong_t)
7800Sstevel@tonic-gate (opts.o_interval * (usage->pr_vctx/period));
7810Sstevel@tonic-gate lwp->li_icx = (ulong_t)
7820Sstevel@tonic-gate (opts.o_interval * (usage->pr_ictx/period));
7830Sstevel@tonic-gate lwp->li_scl = (ulong_t)
7840Sstevel@tonic-gate (opts.o_interval * (usage->pr_sysc/period));
7850Sstevel@tonic-gate lwp->li_sig = (ulong_t)
7860Sstevel@tonic-gate (opts.o_interval * (usage->pr_sigs/period));
7870Sstevel@tonic-gate (void) lwpid_set_active(pid, lwpid);
7880Sstevel@tonic-gate } else {
7890Sstevel@tonic-gate /*
7900Sstevel@tonic-gate * If this is not a first time we are reading a process's
7910Sstevel@tonic-gate * CPU times then recalculate CPU times based on fresh data
7920Sstevel@tonic-gate * obtained from procfs and previous CPU time usage values.
7930Sstevel@tonic-gate */
7940Sstevel@tonic-gate period = TIME2NSEC(usage->pr_rtime)-
7950Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_rtime);
7960Sstevel@tonic-gate period = period/(float)100;
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate if (period == 0) { /* zombie */
7990Sstevel@tonic-gate period = 1;
8000Sstevel@tonic-gate lwp->li_usr = 0;
8010Sstevel@tonic-gate lwp->li_sys = 0;
8020Sstevel@tonic-gate lwp->li_slp = 0;
8030Sstevel@tonic-gate } else {
8040Sstevel@tonic-gate lwp->li_usr = (TIME2NSEC(usage->pr_utime)-
8050Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_utime))/period;
8060Sstevel@tonic-gate lwp->li_sys = (TIME2NSEC(usage->pr_stime) -
8070Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_stime))/period;
8080Sstevel@tonic-gate lwp->li_slp = (TIME2NSEC(usage->pr_slptime) -
8090Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_slptime))/period;
8100Sstevel@tonic-gate }
8110Sstevel@tonic-gate lwp->li_trp = (TIME2NSEC(usage->pr_ttime) -
8120Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_ttime))/period;
8130Sstevel@tonic-gate lwp->li_tfl = (TIME2NSEC(usage->pr_tftime) -
8140Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_tftime))/period;
8150Sstevel@tonic-gate lwp->li_dfl = (TIME2NSEC(usage->pr_dftime) -
8160Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_dftime))/period;
8170Sstevel@tonic-gate lwp->li_lck = (TIME2NSEC(usage->pr_ltime) -
8180Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_ltime))/period;
8190Sstevel@tonic-gate lwp->li_lat = (TIME2NSEC(usage->pr_wtime) -
8200Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_wtime))/period;
8210Sstevel@tonic-gate lwp->li_vcx = usage->pr_vctx - lwp->li_usage.pr_vctx;
8220Sstevel@tonic-gate lwp->li_icx = usage->pr_ictx - lwp->li_usage.pr_ictx;
8230Sstevel@tonic-gate lwp->li_scl = usage->pr_sysc - lwp->li_usage.pr_sysc;
8240Sstevel@tonic-gate lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs;
8250Sstevel@tonic-gate (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t));
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate
8290Sstevel@tonic-gate static int
read_procfile(fd_t ** fd,char * pidstr,char * file,void * buf,size_t bufsize)8300Sstevel@tonic-gate read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize)
8310Sstevel@tonic-gate {
8320Sstevel@tonic-gate char procfile[MAX_PROCFS_PATH];
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate (void) snprintf(procfile, MAX_PROCFS_PATH,
8350Sstevel@tonic-gate "/proc/%s/%s", pidstr, file);
8360Sstevel@tonic-gate if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL)
8370Sstevel@tonic-gate return (1);
8380Sstevel@tonic-gate if (pread(fd_getfd(*fd), buf, bufsize, 0) != bufsize) {
8390Sstevel@tonic-gate fd_close(*fd);
8400Sstevel@tonic-gate return (1);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate return (0);
8430Sstevel@tonic-gate }
8440Sstevel@tonic-gate
8450Sstevel@tonic-gate static void
add_proc(psinfo_t * psinfo)8460Sstevel@tonic-gate add_proc(psinfo_t *psinfo)
8470Sstevel@tonic-gate {
8480Sstevel@tonic-gate lwp_info_t *lwp;
8490Sstevel@tonic-gate id_t lwpid;
8500Sstevel@tonic-gate pid_t pid = psinfo->pr_pid;
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate lwpid = psinfo->pr_lwp.pr_lwpid;
8530Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL)
8540Sstevel@tonic-gate lwp = list_add_lwp(&lwps, pid, lwpid);
8550Sstevel@tonic-gate lwp->li_flags |= LWP_ALIVE | LWP_REPRESENT;
8560Sstevel@tonic-gate (void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t));
8570Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_pctcpu = lwp->li_info.pr_pctcpu;
8580Sstevel@tonic-gate }
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate static void
add_lwp(psinfo_t * psinfo,lwpsinfo_t * lwpsinfo,int flags)8610Sstevel@tonic-gate add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags)
8620Sstevel@tonic-gate {
8630Sstevel@tonic-gate lwp_info_t *lwp;
8640Sstevel@tonic-gate pid_t pid = psinfo->pr_pid;
8650Sstevel@tonic-gate id_t lwpid = lwpsinfo->pr_lwpid;
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL)
8680Sstevel@tonic-gate lwp = list_add_lwp(&lwps, pid, lwpid);
8690Sstevel@tonic-gate lwp->li_flags &= ~LWP_REPRESENT;
8700Sstevel@tonic-gate lwp->li_flags |= LWP_ALIVE;
8710Sstevel@tonic-gate lwp->li_flags |= flags;
8720Sstevel@tonic-gate (void) memcpy(&lwp->li_info, psinfo,
8730Sstevel@tonic-gate sizeof (psinfo_t) - sizeof (lwpsinfo_t));
8740Sstevel@tonic-gate (void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t));
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate static void
prstat_scandir(DIR * procdir)8780Sstevel@tonic-gate prstat_scandir(DIR *procdir)
8790Sstevel@tonic-gate {
8800Sstevel@tonic-gate char *pidstr;
8810Sstevel@tonic-gate pid_t pid;
8820Sstevel@tonic-gate id_t lwpid;
8830Sstevel@tonic-gate size_t entsz;
8840Sstevel@tonic-gate long nlwps, nent, i;
8850Sstevel@tonic-gate char *buf, *ptr;
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate fds_t *fds;
8880Sstevel@tonic-gate lwp_info_t *lwp;
8890Sstevel@tonic-gate dirent_t *direntp;
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate prheader_t header;
8920Sstevel@tonic-gate psinfo_t psinfo;
8930Sstevel@tonic-gate prusage_t usage;
8940Sstevel@tonic-gate lwpsinfo_t *lwpsinfo;
8950Sstevel@tonic-gate prusage_t *lwpusage;
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate total_procs = 0;
8980Sstevel@tonic-gate total_lwps = 0;
8990Sstevel@tonic-gate total_cpu = 0;
9000Sstevel@tonic-gate total_mem = 0;
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate convert_zone(&zone_tbl);
9030Sstevel@tonic-gate for (rewinddir(procdir); (direntp = readdir(procdir)); ) {
9040Sstevel@tonic-gate pidstr = direntp->d_name;
9050Sstevel@tonic-gate if (pidstr[0] == '.') /* skip "." and ".." */
9060Sstevel@tonic-gate continue;
9070Sstevel@tonic-gate pid = atoi(pidstr);
9080Sstevel@tonic-gate if (pid == 0 || pid == 2 || pid == 3)
9090Sstevel@tonic-gate continue; /* skip sched, pageout and fsflush */
9100Sstevel@tonic-gate if (has_element(&pid_tbl, pid) == 0)
9110Sstevel@tonic-gate continue; /* check if we really want this pid */
9120Sstevel@tonic-gate fds = fds_get(pid); /* get ptr to file descriptors */
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate if (read_procfile(&fds->fds_psinfo, pidstr,
9150Sstevel@tonic-gate "psinfo", &psinfo, sizeof (psinfo_t)) != 0)
9160Sstevel@tonic-gate continue;
9170Sstevel@tonic-gate if (!has_uid(&ruid_tbl, psinfo.pr_uid) ||
9180Sstevel@tonic-gate !has_uid(&euid_tbl, psinfo.pr_euid) ||
9190Sstevel@tonic-gate !has_element(&prj_tbl, psinfo.pr_projid) ||
9200Sstevel@tonic-gate !has_element(&tsk_tbl, psinfo.pr_taskid) ||
9210Sstevel@tonic-gate !has_zone(&zone_tbl, psinfo.pr_zoneid)) {
9220Sstevel@tonic-gate fd_close(fds->fds_psinfo);
9230Sstevel@tonic-gate continue;
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate nlwps = psinfo.pr_nlwp + psinfo.pr_nzomb;
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate if (nlwps > 1 && (opts.o_outpmode & (OPT_LWPS | OPT_PSETS))) {
9280Sstevel@tonic-gate int rep_lwp = 0;
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate if (read_procfile(&fds->fds_lpsinfo, pidstr, "lpsinfo",
9310Sstevel@tonic-gate &header, sizeof (prheader_t)) != 0) {
9320Sstevel@tonic-gate fd_close(fds->fds_psinfo);
9330Sstevel@tonic-gate continue;
9340Sstevel@tonic-gate }
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate nent = header.pr_nent;
9370Sstevel@tonic-gate entsz = header.pr_entsize * nent;
9380Sstevel@tonic-gate ptr = buf = Malloc(entsz);
9390Sstevel@tonic-gate if (pread(fd_getfd(fds->fds_lpsinfo), buf,
9400Sstevel@tonic-gate entsz, sizeof (struct prheader)) != entsz) {
9410Sstevel@tonic-gate fd_close(fds->fds_lpsinfo);
9420Sstevel@tonic-gate fd_close(fds->fds_psinfo);
9430Sstevel@tonic-gate free(buf);
9440Sstevel@tonic-gate continue;
9450Sstevel@tonic-gate }
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate nlwps = 0;
9480Sstevel@tonic-gate for (i = 0; i < nent; i++, ptr += header.pr_entsize) {
9490Sstevel@tonic-gate /*LINTED ALIGNMENT*/
9500Sstevel@tonic-gate lwpsinfo = (lwpsinfo_t *)ptr;
9510Sstevel@tonic-gate if (!has_element(&cpu_tbl,
9520Sstevel@tonic-gate lwpsinfo->pr_onpro) ||
9530Sstevel@tonic-gate !has_element(&set_tbl,
9542685Sakolb lwpsinfo->pr_bindpset) ||
9559123Sjohn.levon@sun.com !has_element(&lgr_tbl, lwpsinfo->pr_lgrp))
9560Sstevel@tonic-gate continue;
9570Sstevel@tonic-gate nlwps++;
9580Sstevel@tonic-gate if ((opts.o_outpmode & (OPT_PSETS | OPT_LWPS))
9590Sstevel@tonic-gate == OPT_PSETS) {
9600Sstevel@tonic-gate /*
9610Sstevel@tonic-gate * If one of process's LWPs is bound
9620Sstevel@tonic-gate * to a given processor set, report the
9630Sstevel@tonic-gate * whole process. We may be doing this
9640Sstevel@tonic-gate * a few times but we'll get an accurate
9650Sstevel@tonic-gate * lwp count in return.
9660Sstevel@tonic-gate */
9670Sstevel@tonic-gate add_proc(&psinfo);
9680Sstevel@tonic-gate } else {
9690Sstevel@tonic-gate if (rep_lwp == 0) {
9700Sstevel@tonic-gate rep_lwp = 1;
9710Sstevel@tonic-gate add_lwp(&psinfo, lwpsinfo,
9720Sstevel@tonic-gate LWP_REPRESENT);
9730Sstevel@tonic-gate } else {
9740Sstevel@tonic-gate add_lwp(&psinfo, lwpsinfo, 0);
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate }
9780Sstevel@tonic-gate free(buf);
9790Sstevel@tonic-gate if (nlwps == 0) {
9800Sstevel@tonic-gate fd_close(fds->fds_lpsinfo);
9810Sstevel@tonic-gate fd_close(fds->fds_psinfo);
9820Sstevel@tonic-gate continue;
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate } else {
9850Sstevel@tonic-gate if (!has_element(&cpu_tbl, psinfo.pr_lwp.pr_onpro) ||
9862685Sakolb !has_element(&set_tbl, psinfo.pr_lwp.pr_bindpset) ||
9872685Sakolb !has_element(&lgr_tbl, psinfo.pr_lwp.pr_lgrp)) {
9880Sstevel@tonic-gate fd_close(fds->fds_psinfo);
9890Sstevel@tonic-gate continue;
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate add_proc(&psinfo);
9920Sstevel@tonic-gate }
9930Sstevel@tonic-gate if (!(opts.o_outpmode & OPT_MSACCT)) {
9940Sstevel@tonic-gate total_procs++;
9950Sstevel@tonic-gate total_lwps += nlwps;
9960Sstevel@tonic-gate continue;
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate /*
9990Sstevel@tonic-gate * Get more information about processes from /proc/pid/usage.
10000Sstevel@tonic-gate * If process has more than one lwp, then we may have to
10010Sstevel@tonic-gate * also look at the /proc/pid/lusage file.
10020Sstevel@tonic-gate */
10030Sstevel@tonic-gate if ((opts.o_outpmode & OPT_LWPS) && (nlwps > 1)) {
10040Sstevel@tonic-gate if (read_procfile(&fds->fds_lusage, pidstr, "lusage",
10050Sstevel@tonic-gate &header, sizeof (prheader_t)) != 0) {
10060Sstevel@tonic-gate fd_close(fds->fds_lpsinfo);
10070Sstevel@tonic-gate fd_close(fds->fds_psinfo);
10080Sstevel@tonic-gate continue;
10090Sstevel@tonic-gate }
10100Sstevel@tonic-gate nent = header.pr_nent;
10110Sstevel@tonic-gate entsz = header.pr_entsize * nent;
10120Sstevel@tonic-gate buf = Malloc(entsz);
10130Sstevel@tonic-gate if (pread(fd_getfd(fds->fds_lusage), buf,
10140Sstevel@tonic-gate entsz, sizeof (struct prheader)) != entsz) {
10150Sstevel@tonic-gate fd_close(fds->fds_lusage);
10160Sstevel@tonic-gate fd_close(fds->fds_lpsinfo);
10170Sstevel@tonic-gate fd_close(fds->fds_psinfo);
10180Sstevel@tonic-gate free(buf);
10190Sstevel@tonic-gate continue;
10200Sstevel@tonic-gate }
10210Sstevel@tonic-gate for (i = 1, ptr = buf + header.pr_entsize; i < nent;
10220Sstevel@tonic-gate i++, ptr += header.pr_entsize) {
10230Sstevel@tonic-gate /*LINTED ALIGNMENT*/
10240Sstevel@tonic-gate lwpusage = (prusage_t *)ptr;
10250Sstevel@tonic-gate lwpid = lwpusage->pr_lwpid;
10260Sstevel@tonic-gate /*
10270Sstevel@tonic-gate * New LWPs created after we read lpsinfo
10280Sstevel@tonic-gate * will be ignored. Don't want to do
10290Sstevel@tonic-gate * everything all over again.
10300Sstevel@tonic-gate */
10310Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL)
10320Sstevel@tonic-gate continue;
10330Sstevel@tonic-gate lwp_update(lwp, pid, lwpid, lwpusage);
10340Sstevel@tonic-gate }
10350Sstevel@tonic-gate free(buf);
10360Sstevel@tonic-gate } else {
10370Sstevel@tonic-gate if (read_procfile(&fds->fds_usage, pidstr, "usage",
10380Sstevel@tonic-gate &usage, sizeof (prusage_t)) != 0) {
10390Sstevel@tonic-gate fd_close(fds->fds_lpsinfo);
10400Sstevel@tonic-gate fd_close(fds->fds_psinfo);
10410Sstevel@tonic-gate continue;
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate lwpid = psinfo.pr_lwp.pr_lwpid;
10440Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL)
10450Sstevel@tonic-gate continue;
10460Sstevel@tonic-gate lwp_update(lwp, pid, lwpid, &usage);
10470Sstevel@tonic-gate }
10480Sstevel@tonic-gate total_procs++;
10490Sstevel@tonic-gate total_lwps += nlwps;
10500Sstevel@tonic-gate }
10510Sstevel@tonic-gate fd_update();
10520Sstevel@tonic-gate }
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /*
10550Sstevel@tonic-gate * This procedure removes all dead lwps from the linked list of all lwps.
10560Sstevel@tonic-gate * It also creates linked list of ids if necessary.
10570Sstevel@tonic-gate */
10580Sstevel@tonic-gate static void
list_refresh(list_t * list)10590Sstevel@tonic-gate list_refresh(list_t *list)
10600Sstevel@tonic-gate {
10610Sstevel@tonic-gate lwp_info_t *lwp, *lwp_next;
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate if (!(list->l_type & LT_LWPS))
10640Sstevel@tonic-gate return;
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate for (lwp = list->l_head; lwp != NULL; ) {
10670Sstevel@tonic-gate if (lwp->li_flags & LWP_ALIVE) {
10680Sstevel@tonic-gate /*
10690Sstevel@tonic-gate * Process all live LWPs.
10700Sstevel@tonic-gate * When we're done, mark them as dead.
10710Sstevel@tonic-gate * They will be marked "alive" on the next
10720Sstevel@tonic-gate * /proc scan if they still exist.
10730Sstevel@tonic-gate */
10740Sstevel@tonic-gate lwp->li_key = list_getkeyval(list, lwp);
10750Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS)
10760Sstevel@tonic-gate list_update(&users, lwp);
10770Sstevel@tonic-gate if (opts.o_outpmode & OPT_TASKS)
10780Sstevel@tonic-gate list_update(&tasks, lwp);
10790Sstevel@tonic-gate if (opts.o_outpmode & OPT_PROJECTS)
10800Sstevel@tonic-gate list_update(&projects, lwp);
10810Sstevel@tonic-gate if (opts.o_outpmode & OPT_ZONES)
10820Sstevel@tonic-gate list_update(&zones, lwp);
10832685Sakolb if (opts.o_outpmode & OPT_LGRP)
10842685Sakolb list_update(&lgroups, lwp);
10850Sstevel@tonic-gate lwp->li_flags &= ~LWP_ALIVE;
10860Sstevel@tonic-gate lwp = lwp->li_next;
10870Sstevel@tonic-gate
10880Sstevel@tonic-gate } else {
10890Sstevel@tonic-gate lwp_next = lwp->li_next;
10900Sstevel@tonic-gate list_remove_lwp(&lwps, lwp);
10910Sstevel@tonic-gate lwp = lwp_next;
10920Sstevel@tonic-gate }
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate static void
curses_on()10970Sstevel@tonic-gate curses_on()
10980Sstevel@tonic-gate {
10990Sstevel@tonic-gate if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) {
11000Sstevel@tonic-gate (void) initscr();
11010Sstevel@tonic-gate (void) nonl();
11020Sstevel@tonic-gate (void) putp(t_smcup);
11030Sstevel@tonic-gate is_curses_on = TRUE;
11040Sstevel@tonic-gate }
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate static void
curses_off()11080Sstevel@tonic-gate curses_off()
11090Sstevel@tonic-gate {
11100Sstevel@tonic-gate if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) {
11110Sstevel@tonic-gate (void) putp(t_rmcup);
11120Sstevel@tonic-gate (void) endwin();
11130Sstevel@tonic-gate is_curses_on = FALSE;
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate (void) fflush(stdout);
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate
11180Sstevel@tonic-gate static int
nlines()11190Sstevel@tonic-gate nlines()
11200Sstevel@tonic-gate {
11210Sstevel@tonic-gate struct winsize ws;
11220Sstevel@tonic-gate char *envp;
11230Sstevel@tonic-gate int n;
11240Sstevel@tonic-gate if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
11250Sstevel@tonic-gate if (ws.ws_row > 0)
11260Sstevel@tonic-gate return (ws.ws_row);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate if (envp = getenv("LINES")) {
11290Sstevel@tonic-gate if ((n = Atoi(envp)) > 0) {
11300Sstevel@tonic-gate opts.o_outpmode &= ~OPT_USEHOME;
11310Sstevel@tonic-gate return (n);
11320Sstevel@tonic-gate }
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate return (-1);
11350Sstevel@tonic-gate }
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate static void
setmovecur()11380Sstevel@tonic-gate setmovecur()
11390Sstevel@tonic-gate {
11400Sstevel@tonic-gate int i, n;
11410Sstevel@tonic-gate if ((opts.o_outpmode & OPT_FULLSCREEN) &&
11420Sstevel@tonic-gate (opts.o_outpmode & OPT_USEHOME)) {
11430Sstevel@tonic-gate movecur = t_home;
11440Sstevel@tonic-gate return;
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate if (opts.o_outpmode & OPT_SPLIT) {
11470Sstevel@tonic-gate n = opts.o_ntop + opts.o_nbottom + 2;
11480Sstevel@tonic-gate } else {
11490Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS)
11500Sstevel@tonic-gate n = opts.o_nbottom + 1;
11510Sstevel@tonic-gate else
11520Sstevel@tonic-gate n = opts.o_ntop + 1;
11530Sstevel@tonic-gate }
11549123Sjohn.levon@sun.com if (((opts.o_outpmode & OPT_UDATE) || (opts.o_outpmode & OPT_DDATE)))
11559123Sjohn.levon@sun.com n++;
11569123Sjohn.levon@sun.com
11570Sstevel@tonic-gate if (movecur != NULL && movecur != empty_string && movecur != t_home)
11580Sstevel@tonic-gate free(movecur);
11590Sstevel@tonic-gate movecur = Zalloc(strlen(t_up) * (n + 5));
11600Sstevel@tonic-gate for (i = 0; i <= n; i++)
11610Sstevel@tonic-gate (void) strcat(movecur, t_up);
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate static int
setsize()11650Sstevel@tonic-gate setsize()
11660Sstevel@tonic-gate {
11670Sstevel@tonic-gate static int oldn = 0;
11680Sstevel@tonic-gate int n;
11690Sstevel@tonic-gate
11700Sstevel@tonic-gate if (opts.o_outpmode & OPT_FULLSCREEN) {
11710Sstevel@tonic-gate n = nlines();
11720Sstevel@tonic-gate if (n == oldn)
11730Sstevel@tonic-gate return (0);
11740Sstevel@tonic-gate oldn = n;
11750Sstevel@tonic-gate if (n == -1) {
11760Sstevel@tonic-gate opts.o_outpmode &= ~OPT_USEHOME;
11770Sstevel@tonic-gate setmovecur(); /* set default window size */
11780Sstevel@tonic-gate return (1);
11790Sstevel@tonic-gate }
11800Sstevel@tonic-gate n = n - 3; /* minus header, total and cursor lines */
11819123Sjohn.levon@sun.com if ((opts.o_outpmode & OPT_UDATE) ||
11829123Sjohn.levon@sun.com (opts.o_outpmode & OPT_DDATE))
11839123Sjohn.levon@sun.com n--; /* minus timestamp */
11840Sstevel@tonic-gate if (n < 1)
11850Sstevel@tonic-gate Die(gettext("window is too small (try -n)\n"));
11860Sstevel@tonic-gate if (opts.o_outpmode & OPT_SPLIT) {
11870Sstevel@tonic-gate if (n < 8) {
11880Sstevel@tonic-gate Die(gettext("window is too small (try -n)\n"));
11890Sstevel@tonic-gate } else {
11900Sstevel@tonic-gate opts.o_ntop = (n / 4) * 3;
11910Sstevel@tonic-gate opts.o_nbottom = n - 1 - opts.o_ntop;
11920Sstevel@tonic-gate }
11930Sstevel@tonic-gate } else {
11940Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS)
11950Sstevel@tonic-gate opts.o_nbottom = n;
11960Sstevel@tonic-gate else
11970Sstevel@tonic-gate opts.o_ntop = n;
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate }
12000Sstevel@tonic-gate setmovecur();
12010Sstevel@tonic-gate return (1);
12020Sstevel@tonic-gate }
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate static void
ldtermcap()12050Sstevel@tonic-gate ldtermcap()
12060Sstevel@tonic-gate {
12070Sstevel@tonic-gate int err;
12080Sstevel@tonic-gate if (setupterm(NULL, STDIN_FILENO, &err) == ERR) {
12090Sstevel@tonic-gate switch (err) {
12100Sstevel@tonic-gate case 0:
12110Sstevel@tonic-gate Warn(gettext("failed to load terminal info, "
12120Sstevel@tonic-gate "defaulting to -c option\n"));
12130Sstevel@tonic-gate break;
12140Sstevel@tonic-gate case -1:
12150Sstevel@tonic-gate Warn(gettext("terminfo database not found, "
12160Sstevel@tonic-gate "defaulting to -c option\n"));
12170Sstevel@tonic-gate break;
12180Sstevel@tonic-gate default:
12190Sstevel@tonic-gate Warn(gettext("failed to initialize terminal, "
12200Sstevel@tonic-gate "defaulting to -c option\n"));
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP;
12230Sstevel@tonic-gate t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
12240Sstevel@tonic-gate t_ulon = t_uloff = empty_string;
12250Sstevel@tonic-gate return;
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate t_ulon = tigetstr("smul");
12280Sstevel@tonic-gate t_uloff = tigetstr("rmul");
12290Sstevel@tonic-gate t_up = tigetstr("cuu1");
12300Sstevel@tonic-gate t_eol = tigetstr("el");
12310Sstevel@tonic-gate t_smcup = tigetstr("smcup");
12320Sstevel@tonic-gate t_rmcup = tigetstr("rmcup");
12330Sstevel@tonic-gate t_home = tigetstr("home");
12340Sstevel@tonic-gate if ((t_up == (char *)-1) || (t_eol == (char *)-1) ||
12350Sstevel@tonic-gate (t_smcup == (char *)-1) || (t_rmcup == (char *)-1)) {
12360Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP;
12370Sstevel@tonic-gate t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string;
12380Sstevel@tonic-gate return;
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate if (t_up == NULL || t_eol == NULL) {
12410Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP;
12420Sstevel@tonic-gate t_eol = t_up = movecur = empty_string;
12430Sstevel@tonic-gate return;
12440Sstevel@tonic-gate }
12450Sstevel@tonic-gate if (t_ulon == (char *)-1 || t_uloff == (char *)-1 ||
12460Sstevel@tonic-gate t_ulon == NULL || t_uloff == NULL) {
12470Sstevel@tonic-gate t_ulon = t_uloff = empty_string; /* can live without it */
12480Sstevel@tonic-gate }
12490Sstevel@tonic-gate if (t_smcup == NULL || t_rmcup == NULL)
12500Sstevel@tonic-gate t_smcup = t_rmcup = empty_string;
12510Sstevel@tonic-gate if (t_home == (char *)-1 || t_home == NULL) {
12520Sstevel@tonic-gate opts.o_outpmode &= ~OPT_USEHOME;
12530Sstevel@tonic-gate t_home = empty_string;
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate static void
sig_handler(int sig)12580Sstevel@tonic-gate sig_handler(int sig)
12590Sstevel@tonic-gate {
12600Sstevel@tonic-gate switch (sig) {
12610Sstevel@tonic-gate case SIGTSTP: sigtstp = 1;
12620Sstevel@tonic-gate break;
12630Sstevel@tonic-gate case SIGWINCH: sigwinch = 1;
12640Sstevel@tonic-gate break;
12650Sstevel@tonic-gate case SIGINT:
12660Sstevel@tonic-gate case SIGTERM: sigterm = 1;
12670Sstevel@tonic-gate break;
12680Sstevel@tonic-gate }
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate
12710Sstevel@tonic-gate static void
set_signals()12720Sstevel@tonic-gate set_signals()
12730Sstevel@tonic-gate {
12740Sstevel@tonic-gate (void) signal(SIGTSTP, sig_handler);
12750Sstevel@tonic-gate (void) signal(SIGINT, sig_handler);
12760Sstevel@tonic-gate (void) signal(SIGTERM, sig_handler);
12770Sstevel@tonic-gate if (opts.o_outpmode & OPT_FULLSCREEN)
12780Sstevel@tonic-gate (void) signal(SIGWINCH, sig_handler);
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate static void
fill_table(table_t * table,char * arg,char option)1282586Svb160487 fill_table(table_t *table, char *arg, char option)
12830Sstevel@tonic-gate {
12840Sstevel@tonic-gate char *p = strtok(arg, ", ");
1285586Svb160487
1286586Svb160487 if (p == NULL)
1287586Svb160487 Die(gettext("invalid argument for -%c\n"), option);
12880Sstevel@tonic-gate
1289586Svb160487 add_element(table, (long)Atoi(p));
1290586Svb160487 while (p = strtok(NULL, ", "))
1291586Svb160487 add_element(table, (long)Atoi(p));
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate static void
fill_prj_table(char * arg)12950Sstevel@tonic-gate fill_prj_table(char *arg)
12960Sstevel@tonic-gate {
12970Sstevel@tonic-gate projid_t projid;
12980Sstevel@tonic-gate char *p = strtok(arg, ", ");
12990Sstevel@tonic-gate
1300586Svb160487 if (p == NULL)
1301586Svb160487 Die(gettext("invalid argument for -j\n"));
1302586Svb160487
13030Sstevel@tonic-gate if ((projid = getprojidbyname(p)) == -1)
13040Sstevel@tonic-gate projid = Atoi(p);
13050Sstevel@tonic-gate add_element(&prj_tbl, (long)projid);
13060Sstevel@tonic-gate
13070Sstevel@tonic-gate while (p = strtok(NULL, ", ")) {
13080Sstevel@tonic-gate if ((projid = getprojidbyname(p)) == -1)
13090Sstevel@tonic-gate projid = Atoi(p);
13100Sstevel@tonic-gate add_element(&prj_tbl, (long)projid);
13110Sstevel@tonic-gate }
13120Sstevel@tonic-gate }
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate static void
fill_set_table(char * arg)13150Sstevel@tonic-gate fill_set_table(char *arg)
13160Sstevel@tonic-gate {
13170Sstevel@tonic-gate char *p = strtok(arg, ", ");
13180Sstevel@tonic-gate psetid_t id;
13190Sstevel@tonic-gate
1320586Svb160487 if (p == NULL)
1321586Svb160487 Die(gettext("invalid argument for -C\n"));
1322586Svb160487
13230Sstevel@tonic-gate if ((id = Atoi(p)) == 0)
13240Sstevel@tonic-gate id = PS_NONE;
13250Sstevel@tonic-gate add_element(&set_tbl, id);
13260Sstevel@tonic-gate while (p = strtok(NULL, ", ")) {
13270Sstevel@tonic-gate if ((id = Atoi(p)) == 0)
13280Sstevel@tonic-gate id = PS_NONE;
13290Sstevel@tonic-gate if (!has_element(&set_tbl, id))
13300Sstevel@tonic-gate add_element(&set_tbl, id);
13310Sstevel@tonic-gate }
13320Sstevel@tonic-gate }
13330Sstevel@tonic-gate
13340Sstevel@tonic-gate static void
Exit()13350Sstevel@tonic-gate Exit()
13360Sstevel@tonic-gate {
13370Sstevel@tonic-gate curses_off();
13380Sstevel@tonic-gate list_clear(&lwps);
13390Sstevel@tonic-gate list_clear(&users);
13400Sstevel@tonic-gate list_clear(&tasks);
13410Sstevel@tonic-gate list_clear(&projects);
13420Sstevel@tonic-gate list_clear(&zones);
13430Sstevel@tonic-gate fd_exit();
13440Sstevel@tonic-gate }
13450Sstevel@tonic-gate
13463247Sgjelinek
13470Sstevel@tonic-gate int
main(int argc,char ** argv)13480Sstevel@tonic-gate main(int argc, char **argv)
13490Sstevel@tonic-gate {
13500Sstevel@tonic-gate DIR *procdir;
13510Sstevel@tonic-gate char *p;
13520Sstevel@tonic-gate char *sortk = "cpu"; /* default sort key */
13530Sstevel@tonic-gate int opt;
13540Sstevel@tonic-gate int timeout;
13550Sstevel@tonic-gate struct pollfd pollset;
13560Sstevel@tonic-gate char key;
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
13590Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
13600Sstevel@tonic-gate Progname(argv[0]);
13610Sstevel@tonic-gate lwpid_init();
13620Sstevel@tonic-gate fd_init(Setrlimit());
13630Sstevel@tonic-gate
13643247Sgjelinek pagesize = sysconf(_SC_PAGESIZE);
13653247Sgjelinek
13669123Sjohn.levon@sun.com while ((opt = getopt(argc, argv,
1367*9966SMenno.Lageman@Sun.COM "vcd:HmarRLtu:U:n:p:C:P:h:s:S:j:k:TJz:Z")) != (int)EOF) {
13680Sstevel@tonic-gate switch (opt) {
1369*9966SMenno.Lageman@Sun.COM case 'r':
1370*9966SMenno.Lageman@Sun.COM opts.o_outpmode |= OPT_NORESOLVE;
1371*9966SMenno.Lageman@Sun.COM break;
13720Sstevel@tonic-gate case 'R':
13730Sstevel@tonic-gate opts.o_outpmode |= OPT_REALTIME;
13740Sstevel@tonic-gate break;
13750Sstevel@tonic-gate case 'c':
13760Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP;
13770Sstevel@tonic-gate opts.o_outpmode &= ~OPT_FULLSCREEN;
13780Sstevel@tonic-gate break;
13799123Sjohn.levon@sun.com case 'd':
13809123Sjohn.levon@sun.com if (optarg) {
13819123Sjohn.levon@sun.com if (*optarg == 'u')
13829123Sjohn.levon@sun.com opts.o_outpmode |= OPT_UDATE;
13839123Sjohn.levon@sun.com else if (*optarg == 'd')
13849123Sjohn.levon@sun.com opts.o_outpmode |= OPT_DDATE;
13859123Sjohn.levon@sun.com else
13869123Sjohn.levon@sun.com Usage();
13879123Sjohn.levon@sun.com } else {
13889123Sjohn.levon@sun.com Usage();
13899123Sjohn.levon@sun.com }
13909123Sjohn.levon@sun.com break;
13912685Sakolb case 'h':
13922685Sakolb fill_table(&lgr_tbl, optarg, 'h');
13932685Sakolb break;
13942685Sakolb case 'H':
13952685Sakolb opts.o_outpmode |= OPT_LGRP;
13962685Sakolb break;
13970Sstevel@tonic-gate case 'm':
13980Sstevel@tonic-gate case 'v':
13990Sstevel@tonic-gate opts.o_outpmode &= ~OPT_PSINFO;
14000Sstevel@tonic-gate opts.o_outpmode |= OPT_MSACCT;
14010Sstevel@tonic-gate break;
14020Sstevel@tonic-gate case 't':
14030Sstevel@tonic-gate opts.o_outpmode &= ~OPT_PSINFO;
14040Sstevel@tonic-gate opts.o_outpmode |= OPT_USERS;
14050Sstevel@tonic-gate break;
14060Sstevel@tonic-gate case 'a':
14070Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_USERS;
14080Sstevel@tonic-gate break;
14090Sstevel@tonic-gate case 'T':
14100Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_TASKS;
14110Sstevel@tonic-gate break;
14120Sstevel@tonic-gate case 'J':
14130Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_PROJECTS;
14140Sstevel@tonic-gate break;
14150Sstevel@tonic-gate case 'n':
1416586Svb160487 if ((p = strtok(optarg, ",")) == NULL)
1417586Svb160487 Die(gettext("invalid argument for -n\n"));
14180Sstevel@tonic-gate opts.o_ntop = Atoi(p);
14190Sstevel@tonic-gate if (p = strtok(NULL, ","))
14200Sstevel@tonic-gate opts.o_nbottom = Atoi(p);
14210Sstevel@tonic-gate opts.o_outpmode &= ~OPT_FULLSCREEN;
14220Sstevel@tonic-gate break;
14230Sstevel@tonic-gate case 's':
14240Sstevel@tonic-gate opts.o_sortorder = -1;
14250Sstevel@tonic-gate sortk = optarg;
14260Sstevel@tonic-gate break;
14270Sstevel@tonic-gate case 'S':
14280Sstevel@tonic-gate opts.o_sortorder = 1;
14290Sstevel@tonic-gate sortk = optarg;
14300Sstevel@tonic-gate break;
14310Sstevel@tonic-gate case 'u':
1432586Svb160487 if ((p = strtok(optarg, ", ")) == NULL)
1433586Svb160487 Die(gettext("invalid argument for -u\n"));
14340Sstevel@tonic-gate add_uid(&euid_tbl, p);
14350Sstevel@tonic-gate while (p = strtok(NULL, ", "))
14360Sstevel@tonic-gate add_uid(&euid_tbl, p);
14370Sstevel@tonic-gate break;
14380Sstevel@tonic-gate case 'U':
1439586Svb160487 if ((p = strtok(optarg, ", ")) == NULL)
1440586Svb160487 Die(gettext("invalid argument for -U\n"));
14410Sstevel@tonic-gate add_uid(&ruid_tbl, p);
14420Sstevel@tonic-gate while (p = strtok(NULL, ", "))
14430Sstevel@tonic-gate add_uid(&ruid_tbl, p);
14440Sstevel@tonic-gate break;
14450Sstevel@tonic-gate case 'p':
1446586Svb160487 fill_table(&pid_tbl, optarg, 'p');
14470Sstevel@tonic-gate break;
14480Sstevel@tonic-gate case 'C':
14490Sstevel@tonic-gate fill_set_table(optarg);
14500Sstevel@tonic-gate opts.o_outpmode |= OPT_PSETS;
14510Sstevel@tonic-gate break;
14520Sstevel@tonic-gate case 'P':
1453586Svb160487 fill_table(&cpu_tbl, optarg, 'P');
14540Sstevel@tonic-gate break;
14550Sstevel@tonic-gate case 'k':
1456586Svb160487 fill_table(&tsk_tbl, optarg, 'k');
14570Sstevel@tonic-gate break;
14580Sstevel@tonic-gate case 'j':
14590Sstevel@tonic-gate fill_prj_table(optarg);
14600Sstevel@tonic-gate break;
14610Sstevel@tonic-gate case 'L':
14620Sstevel@tonic-gate opts.o_outpmode |= OPT_LWPS;
14630Sstevel@tonic-gate break;
14640Sstevel@tonic-gate case 'z':
1465586Svb160487 if ((p = strtok(optarg, ", ")) == NULL)
1466586Svb160487 Die(gettext("invalid argument for -z\n"));
14670Sstevel@tonic-gate add_zone(&zone_tbl, p);
14680Sstevel@tonic-gate while (p = strtok(NULL, ", "))
14690Sstevel@tonic-gate add_zone(&zone_tbl, p);
14700Sstevel@tonic-gate break;
14710Sstevel@tonic-gate case 'Z':
14720Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_ZONES;
14730Sstevel@tonic-gate break;
14740Sstevel@tonic-gate default:
14750Sstevel@tonic-gate Usage();
14760Sstevel@tonic-gate }
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate (void) atexit(Exit);
14800Sstevel@tonic-gate if ((opts.o_outpmode & OPT_USERS) &&
14810Sstevel@tonic-gate !(opts.o_outpmode & OPT_SPLIT))
14820Sstevel@tonic-gate opts.o_nbottom = opts.o_ntop;
14830Sstevel@tonic-gate if (opts.o_ntop == 0 || opts.o_nbottom == 0)
14840Sstevel@tonic-gate Die(gettext("invalid argument for -n\n"));
14850Sstevel@tonic-gate if (!(opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) &&
14860Sstevel@tonic-gate ((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
14870Sstevel@tonic-gate Die(gettext("-t option cannot be used with -v or -m\n"));
14880Sstevel@tonic-gate
14890Sstevel@tonic-gate if ((opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode && OPT_USERS) &&
14900Sstevel@tonic-gate !((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT))))
14910Sstevel@tonic-gate Die(gettext("-t option cannot be used with "
14920Sstevel@tonic-gate "-a, -J, -T or -Z\n"));
14930Sstevel@tonic-gate
14940Sstevel@tonic-gate if ((opts.o_outpmode & OPT_USERS) &&
14959123Sjohn.levon@sun.com (opts.o_outpmode & (OPT_TASKS | OPT_PROJECTS | OPT_ZONES)))
14960Sstevel@tonic-gate Die(gettext("-a option cannot be used with "
14970Sstevel@tonic-gate "-t, -J, -T or -Z\n"));
14980Sstevel@tonic-gate
14990Sstevel@tonic-gate if (((opts.o_outpmode & OPT_TASKS) &&
15000Sstevel@tonic-gate (opts.o_outpmode & (OPT_PROJECTS|OPT_ZONES))) ||
15010Sstevel@tonic-gate ((opts.o_outpmode & OPT_PROJECTS) &&
15029123Sjohn.levon@sun.com (opts.o_outpmode & (OPT_TASKS|OPT_ZONES)))) {
15032685Sakolb Die(gettext(
15042685Sakolb "-J, -T and -Z options are mutually exclusive\n"));
15052685Sakolb }
15062685Sakolb
15072685Sakolb /*
15082685Sakolb * There is not enough space to combine microstate information and
15092685Sakolb * lgroup information and still fit in 80-column output.
15102685Sakolb */
15112685Sakolb if ((opts.o_outpmode & OPT_LGRP) && (opts.o_outpmode & OPT_MSACCT)) {
15122685Sakolb Die(gettext("-H and -m options are mutually exclusive\n"));
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate if (argc > optind)
15160Sstevel@tonic-gate opts.o_interval = Atoi(argv[optind++]);
15170Sstevel@tonic-gate if (argc > optind)
15180Sstevel@tonic-gate opts.o_count = Atoi(argv[optind++]);
15190Sstevel@tonic-gate if (opts.o_count == 0)
15200Sstevel@tonic-gate Die(gettext("invalid counter value\n"));
15210Sstevel@tonic-gate if (argc > optind)
15220Sstevel@tonic-gate Usage();
15230Sstevel@tonic-gate if (opts.o_outpmode & OPT_REALTIME)
15240Sstevel@tonic-gate Priocntl("RT");
15250Sstevel@tonic-gate if (isatty(STDOUT_FILENO) == 1 && isatty(STDIN_FILENO))
15260Sstevel@tonic-gate opts.o_outpmode |= OPT_TTY; /* interactive */
15270Sstevel@tonic-gate if (!(opts.o_outpmode & OPT_TTY)) {
15280Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP; /* no termcap for pipes */
15290Sstevel@tonic-gate opts.o_outpmode &= ~OPT_FULLSCREEN;
15300Sstevel@tonic-gate }
15310Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP)
15320Sstevel@tonic-gate ldtermcap(); /* can turn OPT_TERMCAP off */
15330Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP)
15340Sstevel@tonic-gate (void) setsize();
15350Sstevel@tonic-gate list_alloc(&lwps, opts.o_ntop);
15360Sstevel@tonic-gate list_alloc(&users, opts.o_nbottom);
15370Sstevel@tonic-gate list_alloc(&tasks, opts.o_nbottom);
15380Sstevel@tonic-gate list_alloc(&projects, opts.o_nbottom);
15390Sstevel@tonic-gate list_alloc(&zones, opts.o_nbottom);
15402685Sakolb list_alloc(&lgroups, opts.o_nbottom);
15410Sstevel@tonic-gate list_setkeyfunc(sortk, &opts, &lwps, LT_LWPS);
15420Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &users, LT_USERS);
15430Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &tasks, LT_TASKS);
15440Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &projects, LT_PROJECTS);
15450Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &zones, LT_ZONES);
15462685Sakolb list_setkeyfunc(NULL, &opts, &lgroups, LT_LGRPS);
15470Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP)
15480Sstevel@tonic-gate curses_on();
15490Sstevel@tonic-gate if ((procdir = opendir("/proc")) == NULL)
15500Sstevel@tonic-gate Die(gettext("cannot open /proc directory\n"));
15510Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) {
15520Sstevel@tonic-gate (void) printf(gettext("Please wait...\r"));
15539123Sjohn.levon@sun.com if (!(opts.o_outpmode & OPT_TERMCAP))
15549123Sjohn.levon@sun.com (void) putchar('\n');
15550Sstevel@tonic-gate (void) fflush(stdout);
15560Sstevel@tonic-gate }
15570Sstevel@tonic-gate set_signals();
15580Sstevel@tonic-gate pollset.fd = STDIN_FILENO;
15590Sstevel@tonic-gate pollset.events = POLLIN;
15600Sstevel@tonic-gate timeout = opts.o_interval * MILLISEC;
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate /*
15630Sstevel@tonic-gate * main program loop
15640Sstevel@tonic-gate */
15650Sstevel@tonic-gate do {
15660Sstevel@tonic-gate if (sigterm == 1)
15670Sstevel@tonic-gate break;
15680Sstevel@tonic-gate if (sigtstp == 1) {
15690Sstevel@tonic-gate curses_off();
15700Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL);
15710Sstevel@tonic-gate (void) kill(0, SIGTSTP);
15720Sstevel@tonic-gate /*
15730Sstevel@tonic-gate * prstat stops here until it receives SIGCONT signal.
15740Sstevel@tonic-gate */
15750Sstevel@tonic-gate sigtstp = 0;
15760Sstevel@tonic-gate (void) signal(SIGTSTP, sig_handler);
15770Sstevel@tonic-gate curses_on();
15780Sstevel@tonic-gate print_movecur = FALSE;
15790Sstevel@tonic-gate if (opts.o_outpmode & OPT_FULLSCREEN)
15800Sstevel@tonic-gate sigwinch = 1;
15810Sstevel@tonic-gate }
15820Sstevel@tonic-gate if (sigwinch == 1) {
15830Sstevel@tonic-gate if (setsize() == 1) {
15840Sstevel@tonic-gate list_free(&lwps);
15850Sstevel@tonic-gate list_free(&users);
15860Sstevel@tonic-gate list_free(&tasks);
15870Sstevel@tonic-gate list_free(&projects);
15880Sstevel@tonic-gate list_free(&zones);
15890Sstevel@tonic-gate list_alloc(&lwps, opts.o_ntop);
15900Sstevel@tonic-gate list_alloc(&users, opts.o_nbottom);
15910Sstevel@tonic-gate list_alloc(&tasks, opts.o_nbottom);
15920Sstevel@tonic-gate list_alloc(&projects, opts.o_nbottom);
15930Sstevel@tonic-gate list_alloc(&zones, opts.o_nbottom);
15940Sstevel@tonic-gate }
15950Sstevel@tonic-gate sigwinch = 0;
15960Sstevel@tonic-gate (void) signal(SIGWINCH, sig_handler);
15970Sstevel@tonic-gate }
15980Sstevel@tonic-gate prstat_scandir(procdir);
15990Sstevel@tonic-gate list_refresh(&lwps);
16000Sstevel@tonic-gate if (print_movecur)
16010Sstevel@tonic-gate (void) putp(movecur);
16020Sstevel@tonic-gate print_movecur = TRUE;
16030Sstevel@tonic-gate if ((opts.o_outpmode & OPT_PSINFO) ||
16040Sstevel@tonic-gate (opts.o_outpmode & OPT_MSACCT)) {
16050Sstevel@tonic-gate list_sort(&lwps);
16060Sstevel@tonic-gate list_print(&lwps);
16070Sstevel@tonic-gate }
16080Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS) {
16093247Sgjelinek list_getsize(&users);
16100Sstevel@tonic-gate list_sort(&users);
16110Sstevel@tonic-gate list_print(&users);
16120Sstevel@tonic-gate list_clear(&users);
16130Sstevel@tonic-gate }
16140Sstevel@tonic-gate if (opts.o_outpmode & OPT_TASKS) {
16153247Sgjelinek list_getsize(&tasks);
16160Sstevel@tonic-gate list_sort(&tasks);
16170Sstevel@tonic-gate list_print(&tasks);
16180Sstevel@tonic-gate list_clear(&tasks);
16190Sstevel@tonic-gate }
16200Sstevel@tonic-gate if (opts.o_outpmode & OPT_PROJECTS) {
16213247Sgjelinek list_getsize(&projects);
16220Sstevel@tonic-gate list_sort(&projects);
16230Sstevel@tonic-gate list_print(&projects);
16240Sstevel@tonic-gate list_clear(&projects);
16250Sstevel@tonic-gate }
16260Sstevel@tonic-gate if (opts.o_outpmode & OPT_ZONES) {
16273247Sgjelinek list_getsize(&zones);
16280Sstevel@tonic-gate list_sort(&zones);
16290Sstevel@tonic-gate list_print(&zones);
16300Sstevel@tonic-gate list_clear(&zones);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate if (opts.o_count == 1)
16330Sstevel@tonic-gate break;
16340Sstevel@tonic-gate /*
16350Sstevel@tonic-gate * If poll() returns -1 and sets errno to EINTR here because
16360Sstevel@tonic-gate * the process received a signal, it is Ok to abort this
16370Sstevel@tonic-gate * timeout and loop around because we check the signals at the
16380Sstevel@tonic-gate * top of the loop.
16390Sstevel@tonic-gate */
16400Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) {
16410Sstevel@tonic-gate if (poll(&pollset, (nfds_t)1, timeout) > 0) {
16420Sstevel@tonic-gate if (read(STDIN_FILENO, &key, 1) == 1) {
16430Sstevel@tonic-gate if (tolower(key) == 'q')
16440Sstevel@tonic-gate break;
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate }
16470Sstevel@tonic-gate } else {
16480Sstevel@tonic-gate (void) sleep(opts.o_interval);
16490Sstevel@tonic-gate }
16500Sstevel@tonic-gate } while (opts.o_count == (-1) || --opts.o_count);
16510Sstevel@tonic-gate
16520Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY)
16530Sstevel@tonic-gate (void) putchar('\r');
16540Sstevel@tonic-gate return (0);
16550Sstevel@tonic-gate }
1656