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 /* 232685Sakolb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 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> 34*3247Sgjelinek #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 520Sstevel@tonic-gate #include <libintl.h> 530Sstevel@tonic-gate #include <locale.h> 540Sstevel@tonic-gate 550Sstevel@tonic-gate #include "prstat.h" 560Sstevel@tonic-gate #include "prutil.h" 570Sstevel@tonic-gate #include "prtable.h" 580Sstevel@tonic-gate #include "prsort.h" 590Sstevel@tonic-gate #include "prfile.h" 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* 620Sstevel@tonic-gate * x86 <sys/regs.h> ERR conflicts with <curses.h> ERR. For the purposes 630Sstevel@tonic-gate * of this file, we care about the curses.h ERR so include that last. 640Sstevel@tonic-gate */ 650Sstevel@tonic-gate 660Sstevel@tonic-gate #if defined(ERR) 670Sstevel@tonic-gate #undef ERR 680Sstevel@tonic-gate #endif 690Sstevel@tonic-gate 700Sstevel@tonic-gate #ifndef TEXT_DOMAIN /* should be defined by cc -D */ 710Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* use this only if it wasn't */ 720Sstevel@tonic-gate #endif 730Sstevel@tonic-gate 740Sstevel@tonic-gate #include <curses.h> 750Sstevel@tonic-gate #include <term.h> 760Sstevel@tonic-gate 770Sstevel@tonic-gate #define PSINFO_HEADER_PROC \ 780Sstevel@tonic-gate " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/NLWP " 792685Sakolb #define PSINFO_HEADER_PROC_LGRP \ 802685Sakolb " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/NLWP " 810Sstevel@tonic-gate #define PSINFO_HEADER_LWP \ 820Sstevel@tonic-gate " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID " 832685Sakolb #define PSINFO_HEADER_LWP_LGRP \ 842685Sakolb " PID USERNAME SIZE RSS STATE PRI NICE TIME CPU LGRP PROCESS/LWPID " 850Sstevel@tonic-gate #define USAGE_HEADER_PROC \ 860Sstevel@tonic-gate " PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/NLWP " 870Sstevel@tonic-gate #define USAGE_HEADER_LWP \ 880Sstevel@tonic-gate " PID USERNAME USR SYS TRP TFL DFL LCK SLP LAT VCX ICX SCL SIG PROCESS/LWPID " 890Sstevel@tonic-gate #define USER_HEADER_PROC \ 90*3247Sgjelinek " NPROC USERNAME SWAP RSS MEMORY TIME CPU " 910Sstevel@tonic-gate #define USER_HEADER_LWP \ 92*3247Sgjelinek " NLWP USERNAME SWAP RSS MEMORY TIME CPU " 930Sstevel@tonic-gate #define TASK_HEADER_PROC \ 94*3247Sgjelinek "TASKID NPROC SWAP RSS MEMORY TIME CPU PROJECT " 950Sstevel@tonic-gate #define TASK_HEADER_LWP \ 96*3247Sgjelinek "TASKID NLWP SWAP RSS MEMORY TIME CPU PROJECT " 970Sstevel@tonic-gate #define PROJECT_HEADER_PROC \ 98*3247Sgjelinek "PROJID NPROC SWAP RSS MEMORY TIME CPU PROJECT " 990Sstevel@tonic-gate #define PROJECT_HEADER_LWP \ 100*3247Sgjelinek "PROJID NLWP SWAP RSS MEMORY TIME CPU PROJECT " 1010Sstevel@tonic-gate #define ZONE_HEADER_PROC \ 102*3247Sgjelinek "ZONEID NPROC SWAP RSS MEMORY TIME CPU ZONE " 1030Sstevel@tonic-gate #define ZONE_HEADER_LWP \ 104*3247Sgjelinek "ZONEID NLWP SWAP RSS MEMORY TIME CPU ZONE " 1050Sstevel@tonic-gate #define PSINFO_LINE \ 1060Sstevel@tonic-gate "%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %-.16s/%d" 1072685Sakolb #define PSINFO_LINE_LGRP \ 1082685Sakolb "%6d %-8s %5s %5s %-6s %3s %3s %9s %3.3s%% %4d %-.16s/%d" 1090Sstevel@tonic-gate #define USAGE_LINE \ 1100Sstevel@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 "\ 1110Sstevel@tonic-gate "%3.3s %-.12s/%d" 1120Sstevel@tonic-gate #define USER_LINE \ 1130Sstevel@tonic-gate "%6d %-8s %5.5s %5.5s %3.3s%% %9s %3.3s%%" 1140Sstevel@tonic-gate #define TASK_LINE \ 1150Sstevel@tonic-gate "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s" 1160Sstevel@tonic-gate #define PROJECT_LINE \ 1170Sstevel@tonic-gate "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s" 1180Sstevel@tonic-gate #define ZONE_LINE \ 1190Sstevel@tonic-gate "%6d %8d %5s %5s %3.3s%% %9s %3.3s%% %28s" 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate #define TOTAL_LINE \ 1220Sstevel@tonic-gate "Total: %d processes, %d lwps, load averages: %3.2f, %3.2f, %3.2f" 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate /* global variables */ 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate static char *t_ulon; /* termcap: start underline */ 1270Sstevel@tonic-gate static char *t_uloff; /* termcap: end underline */ 1280Sstevel@tonic-gate static char *t_up; /* termcap: cursor 1 line up */ 1290Sstevel@tonic-gate static char *t_eol; /* termcap: clear end of line */ 1300Sstevel@tonic-gate static char *t_smcup; /* termcap: cursor mvcap on */ 1310Sstevel@tonic-gate static char *t_rmcup; /* termcap: cursor mvcap off */ 1320Sstevel@tonic-gate static char *t_home; /* termcap: move cursor home */ 1330Sstevel@tonic-gate static char *movecur = NULL; /* termcap: move up string */ 1340Sstevel@tonic-gate static char *empty_string = "\0"; /* termcap: empty string */ 1350Sstevel@tonic-gate static uint_t print_movecur = FALSE; /* print movecur or not */ 1360Sstevel@tonic-gate static int is_curses_on = FALSE; /* current curses state */ 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate static table_t pid_tbl = {0, 0, NULL}; /* selected processes */ 1390Sstevel@tonic-gate static table_t cpu_tbl = {0, 0, NULL}; /* selected processors */ 1400Sstevel@tonic-gate static table_t set_tbl = {0, 0, NULL}; /* selected processor sets */ 1410Sstevel@tonic-gate static table_t prj_tbl = {0, 0, NULL}; /* selected projects */ 1420Sstevel@tonic-gate static table_t tsk_tbl = {0, 0, NULL}; /* selected tasks */ 1432685Sakolb static table_t lgr_tbl = {0, 0, NULL}; /* selected lgroups */ 1440Sstevel@tonic-gate static zonetbl_t zone_tbl = {0, 0, NULL}; /* selected zones */ 1450Sstevel@tonic-gate static nametbl_t euid_tbl = {0, 0, NULL}; /* selected effective users */ 1460Sstevel@tonic-gate static nametbl_t ruid_tbl = {0, 0, NULL}; /* selected real users */ 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate static uint_t total_procs; /* total number of procs */ 1490Sstevel@tonic-gate static uint_t total_lwps; /* total number of lwps */ 1500Sstevel@tonic-gate static float total_cpu; /* total cpu usage */ 1510Sstevel@tonic-gate static float total_mem; /* total memory usage */ 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate static list_t lwps; /* list of lwps/processes */ 1540Sstevel@tonic-gate static list_t users; /* list of users */ 1550Sstevel@tonic-gate static list_t tasks; /* list of tasks */ 1560Sstevel@tonic-gate static list_t projects; /* list of projects */ 1570Sstevel@tonic-gate static list_t zones; /* list of zones */ 1582685Sakolb static list_t lgroups; /* list of lgroups */ 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate static volatile uint_t sigwinch = 0; 1610Sstevel@tonic-gate static volatile uint_t sigtstp = 0; 1620Sstevel@tonic-gate static volatile uint_t sigterm = 0; 1630Sstevel@tonic-gate 164*3247Sgjelinek static long pagesize; 165*3247Sgjelinek 1660Sstevel@tonic-gate /* default settings */ 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate static optdesc_t opts = { 1690Sstevel@tonic-gate 5, /* interval between updates, seconds */ 1700Sstevel@tonic-gate 15, /* number of lines in top part */ 1710Sstevel@tonic-gate 5, /* number of lines in bottom part */ 1720Sstevel@tonic-gate -1, /* number of iterations; infinitely */ 1730Sstevel@tonic-gate OPT_PSINFO | OPT_FULLSCREEN | OPT_USEHOME | OPT_TERMCAP, 1740Sstevel@tonic-gate -1 /* sort in decreasing order */ 1750Sstevel@tonic-gate }; 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate static void 1780Sstevel@tonic-gate psetloadavg(long psetid, void *ptr) 1790Sstevel@tonic-gate { 1800Sstevel@tonic-gate double psetloadavg[3]; 1810Sstevel@tonic-gate double *loadavg = ptr; 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate if (pset_getloadavg((psetid_t)psetid, psetloadavg, 3) != -1) { 1840Sstevel@tonic-gate *loadavg++ += psetloadavg[0]; 1850Sstevel@tonic-gate *loadavg++ += psetloadavg[1]; 1860Sstevel@tonic-gate *loadavg += psetloadavg[2]; 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* 191*3247Sgjelinek * Queries the memory virtual and rss size for each member of a list. 192*3247Sgjelinek * This will override the values computed by /proc aggregation. 193*3247Sgjelinek */ 194*3247Sgjelinek static void 195*3247Sgjelinek list_getsize(list_t *list) 196*3247Sgjelinek { 197*3247Sgjelinek id_info_t *id; 198*3247Sgjelinek vmusage_t *results, *next; 199*3247Sgjelinek vmusage_t *match; 200*3247Sgjelinek size_t nres = 0; 201*3247Sgjelinek size_t i; 202*3247Sgjelinek uint_t flags = 0; 203*3247Sgjelinek int ret; 204*3247Sgjelinek size_t physmem = sysconf(_SC_PHYS_PAGES) * pagesize; 205*3247Sgjelinek 206*3247Sgjelinek /* 207*3247Sgjelinek * Determine what swap/rss results to calculate. getvmusage() will 208*3247Sgjelinek * prune results returned to non-global zones automatically, so 209*3247Sgjelinek * there is no need to pass different flags when calling from a 210*3247Sgjelinek * non-global zone. 211*3247Sgjelinek * 212*3247Sgjelinek * Currently list_getsize() is only called with a single flag. This 213*3247Sgjelinek * is because -Z, -J, -T, and -a are mutually exclusive. Regardless 214*3247Sgjelinek * of this, we handle multiple flags. 215*3247Sgjelinek */ 216*3247Sgjelinek if (opts.o_outpmode & OPT_USERS) { 217*3247Sgjelinek /* 218*3247Sgjelinek * Gather rss for all users in all zones. Treat the same 219*3247Sgjelinek * uid in different zones as the same user. 220*3247Sgjelinek */ 221*3247Sgjelinek flags |= VMUSAGE_COL_RUSERS; 222*3247Sgjelinek 223*3247Sgjelinek } else if (opts.o_outpmode & OPT_TASKS) { 224*3247Sgjelinek /* Gather rss for all tasks in all zones */ 225*3247Sgjelinek flags |= VMUSAGE_ALL_TASKS; 226*3247Sgjelinek 227*3247Sgjelinek } else if (opts.o_outpmode & OPT_PROJECTS) { 228*3247Sgjelinek /* 229*3247Sgjelinek * Gather rss for all projects in all zones. Treat the same 230*3247Sgjelinek * projid in diffrent zones as the same project. 231*3247Sgjelinek */ 232*3247Sgjelinek flags |= VMUSAGE_COL_PROJECTS; 233*3247Sgjelinek 234*3247Sgjelinek } else if (opts.o_outpmode & OPT_ZONES) { 235*3247Sgjelinek /* Gather rss for all zones */ 236*3247Sgjelinek flags |= VMUSAGE_ALL_ZONES; 237*3247Sgjelinek 238*3247Sgjelinek } else { 239*3247Sgjelinek Die(gettext( 240*3247Sgjelinek "Cannot determine rss flags for output options %x\n"), 241*3247Sgjelinek opts.o_outpmode); 242*3247Sgjelinek } 243*3247Sgjelinek 244*3247Sgjelinek /* 245*3247Sgjelinek * getvmusage() returns an array of result structures. One for 246*3247Sgjelinek * each zone, project, task, or user on the system, depending on 247*3247Sgjelinek * flags. 248*3247Sgjelinek * 249*3247Sgjelinek * If getvmusage() fails, prstat will use the size already gathered 250*3247Sgjelinek * from psinfo 251*3247Sgjelinek */ 252*3247Sgjelinek if (getvmusage(flags, opts.o_interval, NULL, &nres) != 0) 253*3247Sgjelinek return; 254*3247Sgjelinek 255*3247Sgjelinek results = (vmusage_t *)Malloc(sizeof (vmusage_t) * nres); 256*3247Sgjelinek for (;;) { 257*3247Sgjelinek ret = getvmusage(flags, opts.o_interval, results, &nres); 258*3247Sgjelinek if (ret == 0) 259*3247Sgjelinek break; 260*3247Sgjelinek if (errno == EOVERFLOW) { 261*3247Sgjelinek results = (vmusage_t *)Realloc(results, 262*3247Sgjelinek sizeof (vmusage_t) * nres); 263*3247Sgjelinek continue; 264*3247Sgjelinek } 265*3247Sgjelinek /* 266*3247Sgjelinek * Failure for some other reason. Prstat will use the size 267*3247Sgjelinek * already gathered from psinfo. 268*3247Sgjelinek */ 269*3247Sgjelinek return; 270*3247Sgjelinek } 271*3247Sgjelinek for (id = list->l_head; id != NULL; id = id->id_next) { 272*3247Sgjelinek 273*3247Sgjelinek match = NULL; 274*3247Sgjelinek next = results; 275*3247Sgjelinek for (i = 0; i < nres; i++, next++) { 276*3247Sgjelinek switch (flags) { 277*3247Sgjelinek case VMUSAGE_COL_RUSERS: 278*3247Sgjelinek if (next->vmu_id == id->id_uid) 279*3247Sgjelinek match = next; 280*3247Sgjelinek break; 281*3247Sgjelinek case VMUSAGE_ALL_TASKS: 282*3247Sgjelinek if (next->vmu_id == id->id_taskid) 283*3247Sgjelinek match = next; 284*3247Sgjelinek break; 285*3247Sgjelinek case VMUSAGE_COL_PROJECTS: 286*3247Sgjelinek if (next->vmu_id == id->id_projid) 287*3247Sgjelinek match = next; 288*3247Sgjelinek break; 289*3247Sgjelinek case VMUSAGE_ALL_ZONES: 290*3247Sgjelinek if (next->vmu_id == id->id_zoneid) 291*3247Sgjelinek match = next; 292*3247Sgjelinek break; 293*3247Sgjelinek default: 294*3247Sgjelinek Die(gettext( 295*3247Sgjelinek "Unknown vmusage flags %d\n"), flags); 296*3247Sgjelinek } 297*3247Sgjelinek } 298*3247Sgjelinek if (match != NULL) { 299*3247Sgjelinek id->id_size = match->vmu_swap_all / 1024; 300*3247Sgjelinek id->id_rssize = match->vmu_rss_all / 1024; 301*3247Sgjelinek id->id_pctmem = (100.0 * (float)match->vmu_rss_all) / 302*3247Sgjelinek (float)physmem; 303*3247Sgjelinek /* Output using data from getvmusage() */ 304*3247Sgjelinek id->id_sizematch = B_TRUE; 305*3247Sgjelinek } 306*3247Sgjelinek /* 307*3247Sgjelinek * If no match is found, prstat will use the size already 308*3247Sgjelinek * gathered from psinfo. 309*3247Sgjelinek */ 310*3247Sgjelinek } 311*3247Sgjelinek } 312*3247Sgjelinek 313*3247Sgjelinek /* 3140Sstevel@tonic-gate * A routine to display the contents of the list on the screen 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate static void 3170Sstevel@tonic-gate list_print(list_t *list) 3180Sstevel@tonic-gate { 3190Sstevel@tonic-gate lwp_info_t *lwp; 3200Sstevel@tonic-gate id_info_t *id; 3210Sstevel@tonic-gate char usr[4], sys[4], trp[4], tfl[4]; 3220Sstevel@tonic-gate char dfl[4], lck[4], slp[4], lat[4]; 3230Sstevel@tonic-gate char vcx[4], icx[4], scl[4], sig[4]; 3240Sstevel@tonic-gate char psize[6], prssize[6], pmem[6], pcpu[6], ptime[12]; 3250Sstevel@tonic-gate char pstate[7], pnice[4], ppri[4]; 3260Sstevel@tonic-gate char pname[LOGNAME_MAX+1]; 3270Sstevel@tonic-gate char projname[PROJNAME_MAX+1]; 3280Sstevel@tonic-gate char zonename[ZONENAME_MAX+1]; 3290Sstevel@tonic-gate float cpu, mem; 3300Sstevel@tonic-gate double loadavg[3] = {0, 0, 0}; 3310Sstevel@tonic-gate int i, lwpid; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate if (foreach_element(&set_tbl, &loadavg, psetloadavg) == 0) { 3340Sstevel@tonic-gate /* 3350Sstevel@tonic-gate * If processor sets aren't specified, we display system-wide 3360Sstevel@tonic-gate * load averages. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gate (void) getloadavg(loadavg, 3); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 3420Sstevel@tonic-gate (void) putchar('\r'); 3430Sstevel@tonic-gate (void) putp(t_ulon); 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate switch (list->l_type) { 3460Sstevel@tonic-gate case LT_PROJECTS: 3470Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 3480Sstevel@tonic-gate (void) printf(PROJECT_HEADER_LWP); 3490Sstevel@tonic-gate else 3500Sstevel@tonic-gate (void) printf(PROJECT_HEADER_PROC); 3510Sstevel@tonic-gate break; 3520Sstevel@tonic-gate case LT_TASKS: 3530Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 3540Sstevel@tonic-gate (void) printf(TASK_HEADER_LWP); 3550Sstevel@tonic-gate else 3560Sstevel@tonic-gate (void) printf(TASK_HEADER_PROC); 3570Sstevel@tonic-gate break; 3580Sstevel@tonic-gate case LT_ZONES: 3590Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 3600Sstevel@tonic-gate (void) printf(ZONE_HEADER_LWP); 3610Sstevel@tonic-gate else 3620Sstevel@tonic-gate (void) printf(ZONE_HEADER_PROC); 3630Sstevel@tonic-gate break; 3640Sstevel@tonic-gate case LT_USERS: 3650Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 3660Sstevel@tonic-gate (void) printf(USER_HEADER_LWP); 3670Sstevel@tonic-gate else 3680Sstevel@tonic-gate (void) printf(USER_HEADER_PROC); 3690Sstevel@tonic-gate break; 3700Sstevel@tonic-gate case LT_LWPS: 3710Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) { 3722685Sakolb if (opts.o_outpmode & OPT_PSINFO) { 3732685Sakolb if (opts.o_outpmode & OPT_LGRP) 3742685Sakolb (void) printf(PSINFO_HEADER_LWP_LGRP); 3752685Sakolb else 3762685Sakolb (void) printf(PSINFO_HEADER_LWP); 3772685Sakolb } 3780Sstevel@tonic-gate if (opts.o_outpmode & OPT_MSACCT) 3790Sstevel@tonic-gate (void) printf(USAGE_HEADER_LWP); 3800Sstevel@tonic-gate } else { 3812685Sakolb if (opts.o_outpmode & OPT_PSINFO) { 3822685Sakolb if (opts.o_outpmode & OPT_LGRP) 3832685Sakolb (void) printf(PSINFO_HEADER_PROC_LGRP); 3842685Sakolb else 3852685Sakolb (void) printf(PSINFO_HEADER_PROC); 3862685Sakolb } 3870Sstevel@tonic-gate if (opts.o_outpmode & OPT_MSACCT) 3880Sstevel@tonic-gate (void) printf(USAGE_HEADER_PROC); 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate break; 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate (void) putp(t_uloff); 3940Sstevel@tonic-gate (void) putp(t_eol); 3950Sstevel@tonic-gate (void) putchar('\n'); 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate for (i = 0; i < list->l_used; i++) { 3980Sstevel@tonic-gate switch (list->l_type) { 3990Sstevel@tonic-gate case LT_PROJECTS: 4000Sstevel@tonic-gate case LT_TASKS: 4010Sstevel@tonic-gate case LT_USERS: 4020Sstevel@tonic-gate case LT_ZONES: 4030Sstevel@tonic-gate id = list->l_ptrs[i]; 4040Sstevel@tonic-gate /* 4050Sstevel@tonic-gate * CPU usage and memory usage normalization 4060Sstevel@tonic-gate */ 4070Sstevel@tonic-gate if (total_cpu >= 100) 4080Sstevel@tonic-gate cpu = (100 * id->id_pctcpu) / total_cpu; 4090Sstevel@tonic-gate else 4100Sstevel@tonic-gate cpu = id->id_pctcpu; 411*3247Sgjelinek if (id->id_sizematch == B_FALSE && total_mem >= 100) 4120Sstevel@tonic-gate mem = (100 * id->id_pctmem) / total_mem; 4130Sstevel@tonic-gate else 4140Sstevel@tonic-gate mem = id->id_pctmem; 4150Sstevel@tonic-gate if (list->l_type == LT_USERS) 4160Sstevel@tonic-gate pwd_getname(id->id_uid, pname, LOGNAME_MAX + 1); 4170Sstevel@tonic-gate else if (list->l_type == LT_ZONES) 4180Sstevel@tonic-gate getzonename(id->id_zoneid, zonename, 4190Sstevel@tonic-gate ZONENAME_MAX); 4200Sstevel@tonic-gate else 4210Sstevel@tonic-gate getprojname(id->id_projid, projname, 4220Sstevel@tonic-gate PROJNAME_MAX); 4230Sstevel@tonic-gate Format_size(psize, id->id_size, 6); 4240Sstevel@tonic-gate Format_size(prssize, id->id_rssize, 6); 4250Sstevel@tonic-gate Format_pct(pmem, mem, 4); 4260Sstevel@tonic-gate Format_pct(pcpu, cpu, 4); 4270Sstevel@tonic-gate Format_time(ptime, id->id_time, 10); 4280Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 4290Sstevel@tonic-gate (void) putchar('\r'); 4300Sstevel@tonic-gate if (list->l_type == LT_PROJECTS) 4310Sstevel@tonic-gate (void) printf(PROJECT_LINE, (int)id->id_projid, 4320Sstevel@tonic-gate id->id_nproc, psize, prssize, pmem, ptime, 4330Sstevel@tonic-gate pcpu, projname); 4340Sstevel@tonic-gate else if (list->l_type == LT_TASKS) 4350Sstevel@tonic-gate (void) printf(TASK_LINE, (int)id->id_taskid, 4360Sstevel@tonic-gate id->id_nproc, psize, prssize, pmem, ptime, 4370Sstevel@tonic-gate pcpu, projname); 4380Sstevel@tonic-gate else if (list->l_type == LT_ZONES) 4390Sstevel@tonic-gate (void) printf(ZONE_LINE, (int)id->id_zoneid, 4400Sstevel@tonic-gate id->id_nproc, psize, prssize, pmem, ptime, 4410Sstevel@tonic-gate pcpu, zonename); 4420Sstevel@tonic-gate else 4430Sstevel@tonic-gate (void) printf(USER_LINE, id->id_nproc, pname, 4440Sstevel@tonic-gate psize, prssize, pmem, ptime, pcpu); 4450Sstevel@tonic-gate (void) putp(t_eol); 4460Sstevel@tonic-gate (void) putchar('\n'); 4470Sstevel@tonic-gate break; 4480Sstevel@tonic-gate case LT_LWPS: 4490Sstevel@tonic-gate lwp = list->l_ptrs[i]; 4500Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 4510Sstevel@tonic-gate lwpid = lwp->li_info.pr_lwp.pr_lwpid; 4520Sstevel@tonic-gate else 4530Sstevel@tonic-gate lwpid = lwp->li_info.pr_nlwp + 4540Sstevel@tonic-gate lwp->li_info.pr_nzomb; 4550Sstevel@tonic-gate pwd_getname(lwp->li_info.pr_uid, pname, 4560Sstevel@tonic-gate LOGNAME_MAX + 1); 4570Sstevel@tonic-gate if (opts.o_outpmode & OPT_PSINFO) { 4580Sstevel@tonic-gate Format_size(psize, lwp->li_info.pr_size, 6); 4590Sstevel@tonic-gate Format_size(prssize, lwp->li_info.pr_rssize, 6); 4600Sstevel@tonic-gate Format_state(pstate, 4610Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_sname, 4620Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_onpro, 7); 4630Sstevel@tonic-gate if (strcmp(lwp->li_info.pr_lwp.pr_clname, 4640Sstevel@tonic-gate "RT") == 0 || 4650Sstevel@tonic-gate strcmp(lwp->li_info.pr_lwp.pr_clname, 4660Sstevel@tonic-gate "SYS") == 0 || 4670Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_sname == 'Z') 4680Sstevel@tonic-gate (void) strcpy(pnice, " -"); 4690Sstevel@tonic-gate else 4700Sstevel@tonic-gate Format_num(pnice, 4710Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_nice - NZERO, 4720Sstevel@tonic-gate 4); 4730Sstevel@tonic-gate Format_num(ppri, lwp->li_info.pr_lwp.pr_pri, 4); 4740Sstevel@tonic-gate Format_pct(pcpu, 4750Sstevel@tonic-gate FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu), 4); 4760Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 4770Sstevel@tonic-gate Format_time(ptime, 4780Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_time.tv_sec, 4790Sstevel@tonic-gate 10); 4800Sstevel@tonic-gate else 4810Sstevel@tonic-gate Format_time(ptime, 4820Sstevel@tonic-gate lwp->li_info.pr_time.tv_sec, 10); 4830Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 4840Sstevel@tonic-gate (void) putchar('\r'); 4850Sstevel@tonic-gate stripfname(lwp->li_info.pr_fname); 4862685Sakolb if (opts.o_outpmode & OPT_LGRP) { 4872685Sakolb (void) printf(PSINFO_LINE_LGRP, 4882685Sakolb (int)lwp->li_info.pr_pid, pname, 4892685Sakolb psize, prssize, pstate, ppri, pnice, 4902685Sakolb ptime, pcpu, 4912685Sakolb (int)lwp->li_info.pr_lwp.pr_lgrp, 4922685Sakolb lwp->li_info.pr_fname, lwpid); 4932685Sakolb } else { 4942685Sakolb (void) printf(PSINFO_LINE, 4952685Sakolb (int)lwp->li_info.pr_pid, pname, 4962685Sakolb psize, prssize, pstate, ppri, pnice, 4972685Sakolb ptime, pcpu, 4982685Sakolb lwp->li_info.pr_fname, lwpid); 4992685Sakolb } 5000Sstevel@tonic-gate (void) putp(t_eol); 5010Sstevel@tonic-gate (void) putchar('\n'); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate if (opts.o_outpmode & OPT_MSACCT) { 5040Sstevel@tonic-gate Format_pct(usr, lwp->li_usr, 4); 5050Sstevel@tonic-gate Format_pct(sys, lwp->li_sys, 4); 5060Sstevel@tonic-gate Format_pct(slp, lwp->li_slp, 4); 5070Sstevel@tonic-gate Format_num(vcx, lwp->li_vcx, 4); 5080Sstevel@tonic-gate Format_num(icx, lwp->li_icx, 4); 5090Sstevel@tonic-gate Format_num(scl, lwp->li_scl, 4); 5100Sstevel@tonic-gate Format_num(sig, lwp->li_sig, 4); 5110Sstevel@tonic-gate Format_pct(trp, lwp->li_trp, 4); 5120Sstevel@tonic-gate Format_pct(tfl, lwp->li_tfl, 4); 5130Sstevel@tonic-gate Format_pct(dfl, lwp->li_dfl, 4); 5140Sstevel@tonic-gate Format_pct(lck, lwp->li_lck, 4); 5150Sstevel@tonic-gate Format_pct(lat, lwp->li_lat, 4); 5160Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 5170Sstevel@tonic-gate (void) putchar('\r'); 5180Sstevel@tonic-gate stripfname(lwp->li_info.pr_fname); 5190Sstevel@tonic-gate (void) printf(USAGE_LINE, 5200Sstevel@tonic-gate (int)lwp->li_info.pr_pid, pname, 5210Sstevel@tonic-gate usr, sys, trp, tfl, dfl, lck, 5220Sstevel@tonic-gate slp, lat, vcx, icx, scl, sig, 5230Sstevel@tonic-gate lwp->li_info.pr_fname, lwpid); 5240Sstevel@tonic-gate (void) putp(t_eol); 5250Sstevel@tonic-gate (void) putchar('\n'); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate break; 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 5320Sstevel@tonic-gate (void) putchar('\r'); 5330Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP) { 5340Sstevel@tonic-gate switch (list->l_type) { 5350Sstevel@tonic-gate case LT_PROJECTS: 5360Sstevel@tonic-gate case LT_USERS: 5370Sstevel@tonic-gate case LT_TASKS: 5380Sstevel@tonic-gate case LT_ZONES: 5390Sstevel@tonic-gate while (i++ < opts.o_nbottom) { 5400Sstevel@tonic-gate (void) putp(t_eol); 5410Sstevel@tonic-gate (void) putchar('\n'); 5420Sstevel@tonic-gate } 5430Sstevel@tonic-gate break; 5440Sstevel@tonic-gate case LT_LWPS: 5450Sstevel@tonic-gate while (i++ < opts.o_ntop) { 5460Sstevel@tonic-gate (void) putp(t_eol); 5470Sstevel@tonic-gate (void) putchar('\n'); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate 5520Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 5530Sstevel@tonic-gate (void) putchar('\r'); 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate if ((opts.o_outpmode & OPT_SPLIT) && list->l_type == LT_LWPS) 5560Sstevel@tonic-gate return; 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate (void) printf(TOTAL_LINE, total_procs, total_lwps, 5590Sstevel@tonic-gate loadavg[LOADAVG_1MIN], loadavg[LOADAVG_5MIN], 5600Sstevel@tonic-gate loadavg[LOADAVG_15MIN]); 5610Sstevel@tonic-gate (void) putp(t_eol); 5620Sstevel@tonic-gate (void) putchar('\n'); 5630Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 5640Sstevel@tonic-gate (void) putchar('\r'); 5650Sstevel@tonic-gate (void) putp(t_eol); 5660Sstevel@tonic-gate (void) fflush(stdout); 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate static lwp_info_t * 5700Sstevel@tonic-gate list_add_lwp(list_t *list, pid_t pid, id_t lwpid) 5710Sstevel@tonic-gate { 5720Sstevel@tonic-gate lwp_info_t *lwp; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate if (list->l_head == NULL) { 5750Sstevel@tonic-gate list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t)); 5760Sstevel@tonic-gate } else { 5770Sstevel@tonic-gate lwp = Zalloc(sizeof (lwp_info_t)); 5780Sstevel@tonic-gate lwp->li_prev = list->l_tail; 5790Sstevel@tonic-gate ((lwp_info_t *)list->l_tail)->li_next = lwp; 5800Sstevel@tonic-gate list->l_tail = lwp; 5810Sstevel@tonic-gate } 5820Sstevel@tonic-gate lwp->li_info.pr_pid = pid; 5830Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_lwpid = lwpid; 5840Sstevel@tonic-gate lwpid_add(lwp, pid, lwpid); 5850Sstevel@tonic-gate list->l_count++; 5860Sstevel@tonic-gate return (lwp); 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate static void 5900Sstevel@tonic-gate list_remove_lwp(list_t *list, lwp_info_t *lwp) 5910Sstevel@tonic-gate { 5920Sstevel@tonic-gate if (lwp->li_prev) 5930Sstevel@tonic-gate lwp->li_prev->li_next = lwp->li_next; 5940Sstevel@tonic-gate else 5950Sstevel@tonic-gate list->l_head = lwp->li_next; /* removing the head */ 5960Sstevel@tonic-gate if (lwp->li_next) 5970Sstevel@tonic-gate lwp->li_next->li_prev = lwp->li_prev; 5980Sstevel@tonic-gate else 5990Sstevel@tonic-gate list->l_tail = lwp->li_prev; /* removing the tail */ 6000Sstevel@tonic-gate lwpid_del(lwp->li_info.pr_pid, lwp->li_info.pr_lwp.pr_lwpid); 6010Sstevel@tonic-gate if (lwpid_pidcheck(lwp->li_info.pr_pid) == 0) 6020Sstevel@tonic-gate fds_rm(lwp->li_info.pr_pid); 6030Sstevel@tonic-gate list->l_count--; 6040Sstevel@tonic-gate free(lwp); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate static void 6080Sstevel@tonic-gate list_clear(list_t *list) 6090Sstevel@tonic-gate { 6100Sstevel@tonic-gate if (list->l_type == LT_LWPS) { 6110Sstevel@tonic-gate lwp_info_t *lwp = list->l_tail; 6120Sstevel@tonic-gate lwp_info_t *lwp_tmp; 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate fd_closeall(); 6150Sstevel@tonic-gate while (lwp) { 6160Sstevel@tonic-gate lwp_tmp = lwp; 6170Sstevel@tonic-gate lwp = lwp->li_prev; 6180Sstevel@tonic-gate list_remove_lwp(&lwps, lwp_tmp); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate } else { 6210Sstevel@tonic-gate id_info_t *id = list->l_head; 6220Sstevel@tonic-gate id_info_t *nextid; 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate while (id) { 6250Sstevel@tonic-gate nextid = id->id_next; 6260Sstevel@tonic-gate free(id); 6270Sstevel@tonic-gate id = nextid; 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate list->l_count = 0; 6300Sstevel@tonic-gate list->l_head = list->l_tail = NULL; 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate static void 6350Sstevel@tonic-gate list_update(list_t *list, lwp_info_t *lwp) 6360Sstevel@tonic-gate { 6370Sstevel@tonic-gate id_info_t *id; 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate if (list->l_head == NULL) { /* first element */ 6400Sstevel@tonic-gate list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t)); 6410Sstevel@tonic-gate goto update; 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate for (id = list->l_head; id; id = id->id_next) { 6450Sstevel@tonic-gate if ((list->l_type == LT_USERS) && 6460Sstevel@tonic-gate (id->id_uid != lwp->li_info.pr_uid)) 6470Sstevel@tonic-gate continue; 6480Sstevel@tonic-gate if ((list->l_type == LT_TASKS) && 6490Sstevel@tonic-gate (id->id_taskid != lwp->li_info.pr_taskid)) 6500Sstevel@tonic-gate continue; 6510Sstevel@tonic-gate if ((list->l_type == LT_PROJECTS) && 6520Sstevel@tonic-gate (id->id_projid != lwp->li_info.pr_projid)) 6530Sstevel@tonic-gate continue; 6540Sstevel@tonic-gate if ((list->l_type == LT_ZONES) && 6550Sstevel@tonic-gate (id->id_zoneid != lwp->li_info.pr_zoneid)) 6560Sstevel@tonic-gate continue; 6572685Sakolb if ((list->l_type == LT_LGRPS) && 6582685Sakolb (id->id_lgroup != lwp->li_info.pr_lwp.pr_lgrp)) 6592685Sakolb continue; 6600Sstevel@tonic-gate id->id_nproc++; 6610Sstevel@tonic-gate id->id_taskid = lwp->li_info.pr_taskid; 6620Sstevel@tonic-gate id->id_projid = lwp->li_info.pr_projid; 6630Sstevel@tonic-gate id->id_zoneid = lwp->li_info.pr_zoneid; 6642685Sakolb id->id_lgroup = lwp->li_info.pr_lwp.pr_lgrp; 6652685Sakolb 6660Sstevel@tonic-gate if (lwp->li_flags & LWP_REPRESENT) { 6670Sstevel@tonic-gate id->id_size += lwp->li_info.pr_size; 6680Sstevel@tonic-gate id->id_rssize += lwp->li_info.pr_rssize; 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate id->id_pctcpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu); 6710Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 6720Sstevel@tonic-gate id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time); 6730Sstevel@tonic-gate else 6740Sstevel@tonic-gate id->id_time += TIME2SEC(lwp->li_info.pr_time); 6750Sstevel@tonic-gate id->id_pctmem += FRC2PCT(lwp->li_info.pr_pctmem); 6760Sstevel@tonic-gate id->id_key += lwp->li_key; 6770Sstevel@tonic-gate total_cpu += FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu); 6780Sstevel@tonic-gate total_mem += FRC2PCT(lwp->li_info.pr_pctmem); 6790Sstevel@tonic-gate return; 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate id = list->l_tail; 6830Sstevel@tonic-gate id->id_next = Zalloc(sizeof (id_info_t)); 6840Sstevel@tonic-gate id->id_next->id_prev = list->l_tail; 6850Sstevel@tonic-gate id->id_next->id_next = NULL; 6860Sstevel@tonic-gate list->l_tail = id->id_next; 6870Sstevel@tonic-gate id = list->l_tail; 6880Sstevel@tonic-gate update: 6890Sstevel@tonic-gate id->id_uid = lwp->li_info.pr_uid; 6900Sstevel@tonic-gate id->id_projid = lwp->li_info.pr_projid; 6910Sstevel@tonic-gate id->id_taskid = lwp->li_info.pr_taskid; 6920Sstevel@tonic-gate id->id_zoneid = lwp->li_info.pr_zoneid; 6932685Sakolb id->id_lgroup = lwp->li_info.pr_lwp.pr_lgrp; 6940Sstevel@tonic-gate id->id_nproc++; 695*3247Sgjelinek id->id_sizematch = B_FALSE; 6960Sstevel@tonic-gate if (lwp->li_flags & LWP_REPRESENT) { 6970Sstevel@tonic-gate id->id_size = lwp->li_info.pr_size; 6980Sstevel@tonic-gate id->id_rssize = lwp->li_info.pr_rssize; 6990Sstevel@tonic-gate } 7000Sstevel@tonic-gate id->id_pctcpu = FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu); 7010Sstevel@tonic-gate if (opts.o_outpmode & OPT_LWPS) 7020Sstevel@tonic-gate id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time); 7030Sstevel@tonic-gate else 7040Sstevel@tonic-gate id->id_time = TIME2SEC(lwp->li_info.pr_time); 7050Sstevel@tonic-gate id->id_pctmem = FRC2PCT(lwp->li_info.pr_pctmem); 7060Sstevel@tonic-gate id->id_key = lwp->li_key; 7070Sstevel@tonic-gate total_cpu += id->id_pctcpu; 7080Sstevel@tonic-gate total_mem += id->id_pctmem; 7090Sstevel@tonic-gate list->l_count++; 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate static void 7130Sstevel@tonic-gate lwp_update(lwp_info_t *lwp, pid_t pid, id_t lwpid, struct prusage *usage) 7140Sstevel@tonic-gate { 7150Sstevel@tonic-gate float period; 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate if (!lwpid_is_active(pid, lwpid)) { 7180Sstevel@tonic-gate /* 7190Sstevel@tonic-gate * If we are reading cpu times for the first time then 7200Sstevel@tonic-gate * calculate average cpu times based on whole process 7210Sstevel@tonic-gate * execution time. 7220Sstevel@tonic-gate */ 7230Sstevel@tonic-gate (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t)); 7240Sstevel@tonic-gate period = TIME2NSEC(usage->pr_rtime); 7250Sstevel@tonic-gate period = period/(float)100; 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate if (period == 0) { /* zombie */ 7280Sstevel@tonic-gate period = 1; 7290Sstevel@tonic-gate lwp->li_usr = 0; 7300Sstevel@tonic-gate lwp->li_sys = 0; 7310Sstevel@tonic-gate lwp->li_slp = 0; 7320Sstevel@tonic-gate } else { 7330Sstevel@tonic-gate lwp->li_usr = TIME2NSEC(usage->pr_utime)/period; 7340Sstevel@tonic-gate lwp->li_sys = TIME2NSEC(usage->pr_stime)/period; 7350Sstevel@tonic-gate lwp->li_slp = TIME2NSEC(usage->pr_slptime)/period; 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate lwp->li_trp = TIME2NSEC(usage->pr_ttime)/period; 7380Sstevel@tonic-gate lwp->li_tfl = TIME2NSEC(usage->pr_tftime)/period; 7390Sstevel@tonic-gate lwp->li_dfl = TIME2NSEC(usage->pr_dftime)/period; 7400Sstevel@tonic-gate lwp->li_lck = TIME2NSEC(usage->pr_ltime)/period; 7410Sstevel@tonic-gate lwp->li_lat = TIME2NSEC(usage->pr_wtime)/period; 7420Sstevel@tonic-gate period = (period / NANOSEC)*(float)100; /* now in seconds */ 7430Sstevel@tonic-gate lwp->li_vcx = (ulong_t) 7440Sstevel@tonic-gate (opts.o_interval * (usage->pr_vctx/period)); 7450Sstevel@tonic-gate lwp->li_icx = (ulong_t) 7460Sstevel@tonic-gate (opts.o_interval * (usage->pr_ictx/period)); 7470Sstevel@tonic-gate lwp->li_scl = (ulong_t) 7480Sstevel@tonic-gate (opts.o_interval * (usage->pr_sysc/period)); 7490Sstevel@tonic-gate lwp->li_sig = (ulong_t) 7500Sstevel@tonic-gate (opts.o_interval * (usage->pr_sigs/period)); 7510Sstevel@tonic-gate (void) lwpid_set_active(pid, lwpid); 7520Sstevel@tonic-gate } else { 7530Sstevel@tonic-gate /* 7540Sstevel@tonic-gate * If this is not a first time we are reading a process's 7550Sstevel@tonic-gate * CPU times then recalculate CPU times based on fresh data 7560Sstevel@tonic-gate * obtained from procfs and previous CPU time usage values. 7570Sstevel@tonic-gate */ 7580Sstevel@tonic-gate period = TIME2NSEC(usage->pr_rtime)- 7590Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_rtime); 7600Sstevel@tonic-gate period = period/(float)100; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate if (period == 0) { /* zombie */ 7630Sstevel@tonic-gate period = 1; 7640Sstevel@tonic-gate lwp->li_usr = 0; 7650Sstevel@tonic-gate lwp->li_sys = 0; 7660Sstevel@tonic-gate lwp->li_slp = 0; 7670Sstevel@tonic-gate } else { 7680Sstevel@tonic-gate lwp->li_usr = (TIME2NSEC(usage->pr_utime)- 7690Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_utime))/period; 7700Sstevel@tonic-gate lwp->li_sys = (TIME2NSEC(usage->pr_stime) - 7710Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_stime))/period; 7720Sstevel@tonic-gate lwp->li_slp = (TIME2NSEC(usage->pr_slptime) - 7730Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_slptime))/period; 7740Sstevel@tonic-gate } 7750Sstevel@tonic-gate lwp->li_trp = (TIME2NSEC(usage->pr_ttime) - 7760Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_ttime))/period; 7770Sstevel@tonic-gate lwp->li_tfl = (TIME2NSEC(usage->pr_tftime) - 7780Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_tftime))/period; 7790Sstevel@tonic-gate lwp->li_dfl = (TIME2NSEC(usage->pr_dftime) - 7800Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_dftime))/period; 7810Sstevel@tonic-gate lwp->li_lck = (TIME2NSEC(usage->pr_ltime) - 7820Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_ltime))/period; 7830Sstevel@tonic-gate lwp->li_lat = (TIME2NSEC(usage->pr_wtime) - 7840Sstevel@tonic-gate TIME2NSEC(lwp->li_usage.pr_wtime))/period; 7850Sstevel@tonic-gate lwp->li_vcx = usage->pr_vctx - lwp->li_usage.pr_vctx; 7860Sstevel@tonic-gate lwp->li_icx = usage->pr_ictx - lwp->li_usage.pr_ictx; 7870Sstevel@tonic-gate lwp->li_scl = usage->pr_sysc - lwp->li_usage.pr_sysc; 7880Sstevel@tonic-gate lwp->li_sig = usage->pr_sigs - lwp->li_usage.pr_sigs; 7890Sstevel@tonic-gate (void) memcpy(&lwp->li_usage, usage, sizeof (prusage_t)); 7900Sstevel@tonic-gate } 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate static int 7940Sstevel@tonic-gate read_procfile(fd_t **fd, char *pidstr, char *file, void *buf, size_t bufsize) 7950Sstevel@tonic-gate { 7960Sstevel@tonic-gate char procfile[MAX_PROCFS_PATH]; 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate (void) snprintf(procfile, MAX_PROCFS_PATH, 7990Sstevel@tonic-gate "/proc/%s/%s", pidstr, file); 8000Sstevel@tonic-gate if ((*fd = fd_open(procfile, O_RDONLY, *fd)) == NULL) 8010Sstevel@tonic-gate return (1); 8020Sstevel@tonic-gate if (pread(fd_getfd(*fd), buf, bufsize, 0) != bufsize) { 8030Sstevel@tonic-gate fd_close(*fd); 8040Sstevel@tonic-gate return (1); 8050Sstevel@tonic-gate } 8060Sstevel@tonic-gate return (0); 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate static void 8100Sstevel@tonic-gate add_proc(psinfo_t *psinfo) 8110Sstevel@tonic-gate { 8120Sstevel@tonic-gate lwp_info_t *lwp; 8130Sstevel@tonic-gate id_t lwpid; 8140Sstevel@tonic-gate pid_t pid = psinfo->pr_pid; 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate lwpid = psinfo->pr_lwp.pr_lwpid; 8170Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL) 8180Sstevel@tonic-gate lwp = list_add_lwp(&lwps, pid, lwpid); 8190Sstevel@tonic-gate lwp->li_flags |= LWP_ALIVE | LWP_REPRESENT; 8200Sstevel@tonic-gate (void) memcpy(&lwp->li_info, psinfo, sizeof (psinfo_t)); 8210Sstevel@tonic-gate lwp->li_info.pr_lwp.pr_pctcpu = lwp->li_info.pr_pctcpu; 8220Sstevel@tonic-gate } 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate static void 8250Sstevel@tonic-gate add_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, int flags) 8260Sstevel@tonic-gate { 8270Sstevel@tonic-gate lwp_info_t *lwp; 8280Sstevel@tonic-gate pid_t pid = psinfo->pr_pid; 8290Sstevel@tonic-gate id_t lwpid = lwpsinfo->pr_lwpid; 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL) 8320Sstevel@tonic-gate lwp = list_add_lwp(&lwps, pid, lwpid); 8330Sstevel@tonic-gate lwp->li_flags &= ~LWP_REPRESENT; 8340Sstevel@tonic-gate lwp->li_flags |= LWP_ALIVE; 8350Sstevel@tonic-gate lwp->li_flags |= flags; 8360Sstevel@tonic-gate (void) memcpy(&lwp->li_info, psinfo, 8370Sstevel@tonic-gate sizeof (psinfo_t) - sizeof (lwpsinfo_t)); 8380Sstevel@tonic-gate (void) memcpy(&lwp->li_info.pr_lwp, lwpsinfo, sizeof (lwpsinfo_t)); 8390Sstevel@tonic-gate } 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate static void 8420Sstevel@tonic-gate prstat_scandir(DIR *procdir) 8430Sstevel@tonic-gate { 8440Sstevel@tonic-gate char *pidstr; 8450Sstevel@tonic-gate pid_t pid; 8460Sstevel@tonic-gate id_t lwpid; 8470Sstevel@tonic-gate size_t entsz; 8480Sstevel@tonic-gate long nlwps, nent, i; 8490Sstevel@tonic-gate char *buf, *ptr; 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate fds_t *fds; 8520Sstevel@tonic-gate lwp_info_t *lwp; 8530Sstevel@tonic-gate dirent_t *direntp; 8540Sstevel@tonic-gate 8550Sstevel@tonic-gate prheader_t header; 8560Sstevel@tonic-gate psinfo_t psinfo; 8570Sstevel@tonic-gate prusage_t usage; 8580Sstevel@tonic-gate lwpsinfo_t *lwpsinfo; 8590Sstevel@tonic-gate prusage_t *lwpusage; 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate total_procs = 0; 8620Sstevel@tonic-gate total_lwps = 0; 8630Sstevel@tonic-gate total_cpu = 0; 8640Sstevel@tonic-gate total_mem = 0; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate convert_zone(&zone_tbl); 8670Sstevel@tonic-gate for (rewinddir(procdir); (direntp = readdir(procdir)); ) { 8680Sstevel@tonic-gate pidstr = direntp->d_name; 8690Sstevel@tonic-gate if (pidstr[0] == '.') /* skip "." and ".." */ 8700Sstevel@tonic-gate continue; 8710Sstevel@tonic-gate pid = atoi(pidstr); 8720Sstevel@tonic-gate if (pid == 0 || pid == 2 || pid == 3) 8730Sstevel@tonic-gate continue; /* skip sched, pageout and fsflush */ 8740Sstevel@tonic-gate if (has_element(&pid_tbl, pid) == 0) 8750Sstevel@tonic-gate continue; /* check if we really want this pid */ 8760Sstevel@tonic-gate fds = fds_get(pid); /* get ptr to file descriptors */ 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate if (read_procfile(&fds->fds_psinfo, pidstr, 8790Sstevel@tonic-gate "psinfo", &psinfo, sizeof (psinfo_t)) != 0) 8800Sstevel@tonic-gate continue; 8810Sstevel@tonic-gate if (!has_uid(&ruid_tbl, psinfo.pr_uid) || 8820Sstevel@tonic-gate !has_uid(&euid_tbl, psinfo.pr_euid) || 8830Sstevel@tonic-gate !has_element(&prj_tbl, psinfo.pr_projid) || 8840Sstevel@tonic-gate !has_element(&tsk_tbl, psinfo.pr_taskid) || 8850Sstevel@tonic-gate !has_zone(&zone_tbl, psinfo.pr_zoneid)) { 8860Sstevel@tonic-gate fd_close(fds->fds_psinfo); 8870Sstevel@tonic-gate continue; 8880Sstevel@tonic-gate } 8890Sstevel@tonic-gate nlwps = psinfo.pr_nlwp + psinfo.pr_nzomb; 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate if (nlwps > 1 && (opts.o_outpmode & (OPT_LWPS | OPT_PSETS))) { 8920Sstevel@tonic-gate int rep_lwp = 0; 8930Sstevel@tonic-gate 8940Sstevel@tonic-gate if (read_procfile(&fds->fds_lpsinfo, pidstr, "lpsinfo", 8950Sstevel@tonic-gate &header, sizeof (prheader_t)) != 0) { 8960Sstevel@tonic-gate fd_close(fds->fds_psinfo); 8970Sstevel@tonic-gate continue; 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate nent = header.pr_nent; 9010Sstevel@tonic-gate entsz = header.pr_entsize * nent; 9020Sstevel@tonic-gate ptr = buf = Malloc(entsz); 9030Sstevel@tonic-gate if (pread(fd_getfd(fds->fds_lpsinfo), buf, 9040Sstevel@tonic-gate entsz, sizeof (struct prheader)) != entsz) { 9050Sstevel@tonic-gate fd_close(fds->fds_lpsinfo); 9060Sstevel@tonic-gate fd_close(fds->fds_psinfo); 9070Sstevel@tonic-gate free(buf); 9080Sstevel@tonic-gate continue; 9090Sstevel@tonic-gate } 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate nlwps = 0; 9120Sstevel@tonic-gate for (i = 0; i < nent; i++, ptr += header.pr_entsize) { 9130Sstevel@tonic-gate /*LINTED ALIGNMENT*/ 9140Sstevel@tonic-gate lwpsinfo = (lwpsinfo_t *)ptr; 9150Sstevel@tonic-gate if (!has_element(&cpu_tbl, 9160Sstevel@tonic-gate lwpsinfo->pr_onpro) || 9170Sstevel@tonic-gate !has_element(&set_tbl, 9182685Sakolb lwpsinfo->pr_bindpset) || 9192685Sakolb !has_element(&lgr_tbl, 9202685Sakolb lwpsinfo->pr_lgrp)) 9210Sstevel@tonic-gate continue; 9220Sstevel@tonic-gate nlwps++; 9230Sstevel@tonic-gate if ((opts.o_outpmode & (OPT_PSETS | OPT_LWPS)) 9240Sstevel@tonic-gate == OPT_PSETS) { 9250Sstevel@tonic-gate /* 9260Sstevel@tonic-gate * If one of process's LWPs is bound 9270Sstevel@tonic-gate * to a given processor set, report the 9280Sstevel@tonic-gate * whole process. We may be doing this 9290Sstevel@tonic-gate * a few times but we'll get an accurate 9300Sstevel@tonic-gate * lwp count in return. 9310Sstevel@tonic-gate */ 9320Sstevel@tonic-gate add_proc(&psinfo); 9330Sstevel@tonic-gate } else { 9340Sstevel@tonic-gate if (rep_lwp == 0) { 9350Sstevel@tonic-gate rep_lwp = 1; 9360Sstevel@tonic-gate add_lwp(&psinfo, lwpsinfo, 9370Sstevel@tonic-gate LWP_REPRESENT); 9380Sstevel@tonic-gate } else { 9390Sstevel@tonic-gate add_lwp(&psinfo, lwpsinfo, 0); 9400Sstevel@tonic-gate } 9410Sstevel@tonic-gate } 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate free(buf); 9440Sstevel@tonic-gate if (nlwps == 0) { 9450Sstevel@tonic-gate fd_close(fds->fds_lpsinfo); 9460Sstevel@tonic-gate fd_close(fds->fds_psinfo); 9470Sstevel@tonic-gate continue; 9480Sstevel@tonic-gate } 9490Sstevel@tonic-gate } else { 9500Sstevel@tonic-gate if (!has_element(&cpu_tbl, psinfo.pr_lwp.pr_onpro) || 9512685Sakolb !has_element(&set_tbl, psinfo.pr_lwp.pr_bindpset) || 9522685Sakolb !has_element(&lgr_tbl, psinfo.pr_lwp.pr_lgrp)) { 9530Sstevel@tonic-gate fd_close(fds->fds_psinfo); 9540Sstevel@tonic-gate continue; 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate add_proc(&psinfo); 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate if (!(opts.o_outpmode & OPT_MSACCT)) { 9590Sstevel@tonic-gate total_procs++; 9600Sstevel@tonic-gate total_lwps += nlwps; 9610Sstevel@tonic-gate continue; 9620Sstevel@tonic-gate } 9630Sstevel@tonic-gate /* 9640Sstevel@tonic-gate * Get more information about processes from /proc/pid/usage. 9650Sstevel@tonic-gate * If process has more than one lwp, then we may have to 9660Sstevel@tonic-gate * also look at the /proc/pid/lusage file. 9670Sstevel@tonic-gate */ 9680Sstevel@tonic-gate if ((opts.o_outpmode & OPT_LWPS) && (nlwps > 1)) { 9690Sstevel@tonic-gate if (read_procfile(&fds->fds_lusage, pidstr, "lusage", 9700Sstevel@tonic-gate &header, sizeof (prheader_t)) != 0) { 9710Sstevel@tonic-gate fd_close(fds->fds_lpsinfo); 9720Sstevel@tonic-gate fd_close(fds->fds_psinfo); 9730Sstevel@tonic-gate continue; 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate nent = header.pr_nent; 9760Sstevel@tonic-gate entsz = header.pr_entsize * nent; 9770Sstevel@tonic-gate buf = Malloc(entsz); 9780Sstevel@tonic-gate if (pread(fd_getfd(fds->fds_lusage), buf, 9790Sstevel@tonic-gate entsz, sizeof (struct prheader)) != entsz) { 9800Sstevel@tonic-gate fd_close(fds->fds_lusage); 9810Sstevel@tonic-gate fd_close(fds->fds_lpsinfo); 9820Sstevel@tonic-gate fd_close(fds->fds_psinfo); 9830Sstevel@tonic-gate free(buf); 9840Sstevel@tonic-gate continue; 9850Sstevel@tonic-gate } 9860Sstevel@tonic-gate for (i = 1, ptr = buf + header.pr_entsize; i < nent; 9870Sstevel@tonic-gate i++, ptr += header.pr_entsize) { 9880Sstevel@tonic-gate /*LINTED ALIGNMENT*/ 9890Sstevel@tonic-gate lwpusage = (prusage_t *)ptr; 9900Sstevel@tonic-gate lwpid = lwpusage->pr_lwpid; 9910Sstevel@tonic-gate /* 9920Sstevel@tonic-gate * New LWPs created after we read lpsinfo 9930Sstevel@tonic-gate * will be ignored. Don't want to do 9940Sstevel@tonic-gate * everything all over again. 9950Sstevel@tonic-gate */ 9960Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL) 9970Sstevel@tonic-gate continue; 9980Sstevel@tonic-gate lwp_update(lwp, pid, lwpid, lwpusage); 9990Sstevel@tonic-gate } 10000Sstevel@tonic-gate free(buf); 10010Sstevel@tonic-gate } else { 10020Sstevel@tonic-gate if (read_procfile(&fds->fds_usage, pidstr, "usage", 10030Sstevel@tonic-gate &usage, sizeof (prusage_t)) != 0) { 10040Sstevel@tonic-gate fd_close(fds->fds_lpsinfo); 10050Sstevel@tonic-gate fd_close(fds->fds_psinfo); 10060Sstevel@tonic-gate continue; 10070Sstevel@tonic-gate } 10080Sstevel@tonic-gate lwpid = psinfo.pr_lwp.pr_lwpid; 10090Sstevel@tonic-gate if ((lwp = lwpid_get(pid, lwpid)) == NULL) 10100Sstevel@tonic-gate continue; 10110Sstevel@tonic-gate lwp_update(lwp, pid, lwpid, &usage); 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate total_procs++; 10140Sstevel@tonic-gate total_lwps += nlwps; 10150Sstevel@tonic-gate } 10160Sstevel@tonic-gate fd_update(); 10170Sstevel@tonic-gate } 10180Sstevel@tonic-gate 10190Sstevel@tonic-gate /* 10200Sstevel@tonic-gate * This procedure removes all dead lwps from the linked list of all lwps. 10210Sstevel@tonic-gate * It also creates linked list of ids if necessary. 10220Sstevel@tonic-gate */ 10230Sstevel@tonic-gate static void 10240Sstevel@tonic-gate list_refresh(list_t *list) 10250Sstevel@tonic-gate { 10260Sstevel@tonic-gate lwp_info_t *lwp, *lwp_next; 10270Sstevel@tonic-gate 10280Sstevel@tonic-gate if (!(list->l_type & LT_LWPS)) 10290Sstevel@tonic-gate return; 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate for (lwp = list->l_head; lwp != NULL; ) { 10320Sstevel@tonic-gate if (lwp->li_flags & LWP_ALIVE) { 10330Sstevel@tonic-gate /* 10340Sstevel@tonic-gate * Process all live LWPs. 10350Sstevel@tonic-gate * When we're done, mark them as dead. 10360Sstevel@tonic-gate * They will be marked "alive" on the next 10370Sstevel@tonic-gate * /proc scan if they still exist. 10380Sstevel@tonic-gate */ 10390Sstevel@tonic-gate lwp->li_key = list_getkeyval(list, lwp); 10400Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS) 10410Sstevel@tonic-gate list_update(&users, lwp); 10420Sstevel@tonic-gate if (opts.o_outpmode & OPT_TASKS) 10430Sstevel@tonic-gate list_update(&tasks, lwp); 10440Sstevel@tonic-gate if (opts.o_outpmode & OPT_PROJECTS) 10450Sstevel@tonic-gate list_update(&projects, lwp); 10460Sstevel@tonic-gate if (opts.o_outpmode & OPT_ZONES) 10470Sstevel@tonic-gate list_update(&zones, lwp); 10482685Sakolb if (opts.o_outpmode & OPT_LGRP) 10492685Sakolb list_update(&lgroups, lwp); 10500Sstevel@tonic-gate lwp->li_flags &= ~LWP_ALIVE; 10510Sstevel@tonic-gate lwp = lwp->li_next; 10520Sstevel@tonic-gate 10530Sstevel@tonic-gate } else { 10540Sstevel@tonic-gate lwp_next = lwp->li_next; 10550Sstevel@tonic-gate list_remove_lwp(&lwps, lwp); 10560Sstevel@tonic-gate lwp = lwp_next; 10570Sstevel@tonic-gate } 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate } 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate static void 10620Sstevel@tonic-gate curses_on() 10630Sstevel@tonic-gate { 10640Sstevel@tonic-gate if ((opts.o_outpmode & OPT_TERMCAP) && (is_curses_on == FALSE)) { 10650Sstevel@tonic-gate (void) initscr(); 10660Sstevel@tonic-gate (void) nonl(); 10670Sstevel@tonic-gate (void) putp(t_smcup); 10680Sstevel@tonic-gate is_curses_on = TRUE; 10690Sstevel@tonic-gate } 10700Sstevel@tonic-gate } 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate static void 10730Sstevel@tonic-gate curses_off() 10740Sstevel@tonic-gate { 10750Sstevel@tonic-gate if ((is_curses_on == TRUE) && (opts.o_outpmode & OPT_TERMCAP)) { 10760Sstevel@tonic-gate (void) putp(t_rmcup); 10770Sstevel@tonic-gate (void) endwin(); 10780Sstevel@tonic-gate is_curses_on = FALSE; 10790Sstevel@tonic-gate } 10800Sstevel@tonic-gate (void) fflush(stdout); 10810Sstevel@tonic-gate } 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate static int 10840Sstevel@tonic-gate nlines() 10850Sstevel@tonic-gate { 10860Sstevel@tonic-gate struct winsize ws; 10870Sstevel@tonic-gate char *envp; 10880Sstevel@tonic-gate int n; 10890Sstevel@tonic-gate if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) { 10900Sstevel@tonic-gate if (ws.ws_row > 0) 10910Sstevel@tonic-gate return (ws.ws_row); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate if (envp = getenv("LINES")) { 10940Sstevel@tonic-gate if ((n = Atoi(envp)) > 0) { 10950Sstevel@tonic-gate opts.o_outpmode &= ~OPT_USEHOME; 10960Sstevel@tonic-gate return (n); 10970Sstevel@tonic-gate } 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate return (-1); 11000Sstevel@tonic-gate } 11010Sstevel@tonic-gate 11020Sstevel@tonic-gate static void 11030Sstevel@tonic-gate setmovecur() 11040Sstevel@tonic-gate { 11050Sstevel@tonic-gate int i, n; 11060Sstevel@tonic-gate if ((opts.o_outpmode & OPT_FULLSCREEN) && 11070Sstevel@tonic-gate (opts.o_outpmode & OPT_USEHOME)) { 11080Sstevel@tonic-gate movecur = t_home; 11090Sstevel@tonic-gate return; 11100Sstevel@tonic-gate } 11110Sstevel@tonic-gate if (opts.o_outpmode & OPT_SPLIT) { 11120Sstevel@tonic-gate n = opts.o_ntop + opts.o_nbottom + 2; 11130Sstevel@tonic-gate } else { 11140Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS) 11150Sstevel@tonic-gate n = opts.o_nbottom + 1; 11160Sstevel@tonic-gate else 11170Sstevel@tonic-gate n = opts.o_ntop + 1; 11180Sstevel@tonic-gate } 11190Sstevel@tonic-gate if (movecur != NULL && movecur != empty_string && movecur != t_home) 11200Sstevel@tonic-gate free(movecur); 11210Sstevel@tonic-gate movecur = Zalloc(strlen(t_up) * (n + 5)); 11220Sstevel@tonic-gate for (i = 0; i <= n; i++) 11230Sstevel@tonic-gate (void) strcat(movecur, t_up); 11240Sstevel@tonic-gate } 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate static int 11270Sstevel@tonic-gate setsize() 11280Sstevel@tonic-gate { 11290Sstevel@tonic-gate static int oldn = 0; 11300Sstevel@tonic-gate int n; 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate if (opts.o_outpmode & OPT_FULLSCREEN) { 11330Sstevel@tonic-gate n = nlines(); 11340Sstevel@tonic-gate if (n == oldn) 11350Sstevel@tonic-gate return (0); 11360Sstevel@tonic-gate oldn = n; 11370Sstevel@tonic-gate if (n == -1) { 11380Sstevel@tonic-gate opts.o_outpmode &= ~OPT_USEHOME; 11390Sstevel@tonic-gate setmovecur(); /* set default window size */ 11400Sstevel@tonic-gate return (1); 11410Sstevel@tonic-gate } 11420Sstevel@tonic-gate n = n - 3; /* minus header, total and cursor lines */ 11430Sstevel@tonic-gate if (n < 1) 11440Sstevel@tonic-gate Die(gettext("window is too small (try -n)\n")); 11450Sstevel@tonic-gate if (opts.o_outpmode & OPT_SPLIT) { 11460Sstevel@tonic-gate if (n < 8) { 11470Sstevel@tonic-gate Die(gettext("window is too small (try -n)\n")); 11480Sstevel@tonic-gate } else { 11490Sstevel@tonic-gate opts.o_ntop = (n / 4) * 3; 11500Sstevel@tonic-gate opts.o_nbottom = n - 1 - opts.o_ntop; 11510Sstevel@tonic-gate } 11520Sstevel@tonic-gate } else { 11530Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS) 11540Sstevel@tonic-gate opts.o_nbottom = n; 11550Sstevel@tonic-gate else 11560Sstevel@tonic-gate opts.o_ntop = n; 11570Sstevel@tonic-gate } 11580Sstevel@tonic-gate } 11590Sstevel@tonic-gate setmovecur(); 11600Sstevel@tonic-gate return (1); 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate static void 11640Sstevel@tonic-gate ldtermcap() 11650Sstevel@tonic-gate { 11660Sstevel@tonic-gate int err; 11670Sstevel@tonic-gate if (setupterm(NULL, STDIN_FILENO, &err) == ERR) { 11680Sstevel@tonic-gate switch (err) { 11690Sstevel@tonic-gate case 0: 11700Sstevel@tonic-gate Warn(gettext("failed to load terminal info, " 11710Sstevel@tonic-gate "defaulting to -c option\n")); 11720Sstevel@tonic-gate break; 11730Sstevel@tonic-gate case -1: 11740Sstevel@tonic-gate Warn(gettext("terminfo database not found, " 11750Sstevel@tonic-gate "defaulting to -c option\n")); 11760Sstevel@tonic-gate break; 11770Sstevel@tonic-gate default: 11780Sstevel@tonic-gate Warn(gettext("failed to initialize terminal, " 11790Sstevel@tonic-gate "defaulting to -c option\n")); 11800Sstevel@tonic-gate } 11810Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP; 11820Sstevel@tonic-gate t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string; 11830Sstevel@tonic-gate t_ulon = t_uloff = empty_string; 11840Sstevel@tonic-gate return; 11850Sstevel@tonic-gate } 11860Sstevel@tonic-gate t_ulon = tigetstr("smul"); 11870Sstevel@tonic-gate t_uloff = tigetstr("rmul"); 11880Sstevel@tonic-gate t_up = tigetstr("cuu1"); 11890Sstevel@tonic-gate t_eol = tigetstr("el"); 11900Sstevel@tonic-gate t_smcup = tigetstr("smcup"); 11910Sstevel@tonic-gate t_rmcup = tigetstr("rmcup"); 11920Sstevel@tonic-gate t_home = tigetstr("home"); 11930Sstevel@tonic-gate if ((t_up == (char *)-1) || (t_eol == (char *)-1) || 11940Sstevel@tonic-gate (t_smcup == (char *)-1) || (t_rmcup == (char *)-1)) { 11950Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP; 11960Sstevel@tonic-gate t_up = t_eol = t_smcup = t_rmcup = movecur = empty_string; 11970Sstevel@tonic-gate return; 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate if (t_up == NULL || t_eol == NULL) { 12000Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP; 12010Sstevel@tonic-gate t_eol = t_up = movecur = empty_string; 12020Sstevel@tonic-gate return; 12030Sstevel@tonic-gate } 12040Sstevel@tonic-gate if (t_ulon == (char *)-1 || t_uloff == (char *)-1 || 12050Sstevel@tonic-gate t_ulon == NULL || t_uloff == NULL) { 12060Sstevel@tonic-gate t_ulon = t_uloff = empty_string; /* can live without it */ 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate if (t_smcup == NULL || t_rmcup == NULL) 12090Sstevel@tonic-gate t_smcup = t_rmcup = empty_string; 12100Sstevel@tonic-gate if (t_home == (char *)-1 || t_home == NULL) { 12110Sstevel@tonic-gate opts.o_outpmode &= ~OPT_USEHOME; 12120Sstevel@tonic-gate t_home = empty_string; 12130Sstevel@tonic-gate } 12140Sstevel@tonic-gate } 12150Sstevel@tonic-gate 12160Sstevel@tonic-gate static void 12170Sstevel@tonic-gate sig_handler(int sig) 12180Sstevel@tonic-gate { 12190Sstevel@tonic-gate switch (sig) { 12200Sstevel@tonic-gate case SIGTSTP: sigtstp = 1; 12210Sstevel@tonic-gate break; 12220Sstevel@tonic-gate case SIGWINCH: sigwinch = 1; 12230Sstevel@tonic-gate break; 12240Sstevel@tonic-gate case SIGINT: 12250Sstevel@tonic-gate case SIGTERM: sigterm = 1; 12260Sstevel@tonic-gate break; 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate } 12290Sstevel@tonic-gate 12300Sstevel@tonic-gate static void 12310Sstevel@tonic-gate set_signals() 12320Sstevel@tonic-gate { 12330Sstevel@tonic-gate (void) signal(SIGTSTP, sig_handler); 12340Sstevel@tonic-gate (void) signal(SIGINT, sig_handler); 12350Sstevel@tonic-gate (void) signal(SIGTERM, sig_handler); 12360Sstevel@tonic-gate if (opts.o_outpmode & OPT_FULLSCREEN) 12370Sstevel@tonic-gate (void) signal(SIGWINCH, sig_handler); 12380Sstevel@tonic-gate } 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate static void 1241586Svb160487 fill_table(table_t *table, char *arg, char option) 12420Sstevel@tonic-gate { 12430Sstevel@tonic-gate char *p = strtok(arg, ", "); 1244586Svb160487 1245586Svb160487 if (p == NULL) 1246586Svb160487 Die(gettext("invalid argument for -%c\n"), option); 12470Sstevel@tonic-gate 1248586Svb160487 add_element(table, (long)Atoi(p)); 1249586Svb160487 while (p = strtok(NULL, ", ")) 1250586Svb160487 add_element(table, (long)Atoi(p)); 12510Sstevel@tonic-gate } 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate static void 12540Sstevel@tonic-gate fill_prj_table(char *arg) 12550Sstevel@tonic-gate { 12560Sstevel@tonic-gate projid_t projid; 12570Sstevel@tonic-gate char *p = strtok(arg, ", "); 12580Sstevel@tonic-gate 1259586Svb160487 if (p == NULL) 1260586Svb160487 Die(gettext("invalid argument for -j\n")); 1261586Svb160487 12620Sstevel@tonic-gate if ((projid = getprojidbyname(p)) == -1) 12630Sstevel@tonic-gate projid = Atoi(p); 12640Sstevel@tonic-gate add_element(&prj_tbl, (long)projid); 12650Sstevel@tonic-gate 12660Sstevel@tonic-gate while (p = strtok(NULL, ", ")) { 12670Sstevel@tonic-gate if ((projid = getprojidbyname(p)) == -1) 12680Sstevel@tonic-gate projid = Atoi(p); 12690Sstevel@tonic-gate add_element(&prj_tbl, (long)projid); 12700Sstevel@tonic-gate } 12710Sstevel@tonic-gate } 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate static void 12740Sstevel@tonic-gate fill_set_table(char *arg) 12750Sstevel@tonic-gate { 12760Sstevel@tonic-gate char *p = strtok(arg, ", "); 12770Sstevel@tonic-gate psetid_t id; 12780Sstevel@tonic-gate 1279586Svb160487 if (p == NULL) 1280586Svb160487 Die(gettext("invalid argument for -C\n")); 1281586Svb160487 12820Sstevel@tonic-gate if ((id = Atoi(p)) == 0) 12830Sstevel@tonic-gate id = PS_NONE; 12840Sstevel@tonic-gate add_element(&set_tbl, id); 12850Sstevel@tonic-gate while (p = strtok(NULL, ", ")) { 12860Sstevel@tonic-gate if ((id = Atoi(p)) == 0) 12870Sstevel@tonic-gate id = PS_NONE; 12880Sstevel@tonic-gate if (!has_element(&set_tbl, id)) 12890Sstevel@tonic-gate add_element(&set_tbl, id); 12900Sstevel@tonic-gate } 12910Sstevel@tonic-gate } 12920Sstevel@tonic-gate 12930Sstevel@tonic-gate static void 12940Sstevel@tonic-gate Exit() 12950Sstevel@tonic-gate { 12960Sstevel@tonic-gate curses_off(); 12970Sstevel@tonic-gate list_clear(&lwps); 12980Sstevel@tonic-gate list_clear(&users); 12990Sstevel@tonic-gate list_clear(&tasks); 13000Sstevel@tonic-gate list_clear(&projects); 13010Sstevel@tonic-gate list_clear(&zones); 13020Sstevel@tonic-gate fd_exit(); 13030Sstevel@tonic-gate } 13040Sstevel@tonic-gate 1305*3247Sgjelinek 13060Sstevel@tonic-gate int 13070Sstevel@tonic-gate main(int argc, char **argv) 13080Sstevel@tonic-gate { 13090Sstevel@tonic-gate DIR *procdir; 13100Sstevel@tonic-gate char *p; 13110Sstevel@tonic-gate char *sortk = "cpu"; /* default sort key */ 13120Sstevel@tonic-gate int opt; 13130Sstevel@tonic-gate int timeout; 13140Sstevel@tonic-gate struct pollfd pollset; 13150Sstevel@tonic-gate char key; 13160Sstevel@tonic-gate 13170Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 13180Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 13190Sstevel@tonic-gate Progname(argv[0]); 13200Sstevel@tonic-gate lwpid_init(); 13210Sstevel@tonic-gate fd_init(Setrlimit()); 13220Sstevel@tonic-gate 1323*3247Sgjelinek pagesize = sysconf(_SC_PAGESIZE); 1324*3247Sgjelinek 13252685Sakolb while ((opt = getopt(argc, argv, "vcHmaRLtu:U:n:p:C:P:h:s:S:j:k:TJz:Z")) 13260Sstevel@tonic-gate != (int)EOF) { 13270Sstevel@tonic-gate switch (opt) { 13280Sstevel@tonic-gate case 'R': 13290Sstevel@tonic-gate opts.o_outpmode |= OPT_REALTIME; 13300Sstevel@tonic-gate break; 13310Sstevel@tonic-gate case 'c': 13320Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP; 13330Sstevel@tonic-gate opts.o_outpmode &= ~OPT_FULLSCREEN; 13340Sstevel@tonic-gate break; 13352685Sakolb case 'h': 13362685Sakolb fill_table(&lgr_tbl, optarg, 'h'); 13372685Sakolb break; 13382685Sakolb case 'H': 13392685Sakolb opts.o_outpmode |= OPT_LGRP; 13402685Sakolb break; 13410Sstevel@tonic-gate case 'm': 13420Sstevel@tonic-gate case 'v': 13430Sstevel@tonic-gate opts.o_outpmode &= ~OPT_PSINFO; 13440Sstevel@tonic-gate opts.o_outpmode |= OPT_MSACCT; 13450Sstevel@tonic-gate break; 13460Sstevel@tonic-gate case 't': 13470Sstevel@tonic-gate opts.o_outpmode &= ~OPT_PSINFO; 13480Sstevel@tonic-gate opts.o_outpmode |= OPT_USERS; 13490Sstevel@tonic-gate break; 13500Sstevel@tonic-gate case 'a': 13510Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_USERS; 13520Sstevel@tonic-gate break; 13530Sstevel@tonic-gate case 'T': 13540Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_TASKS; 13550Sstevel@tonic-gate break; 13560Sstevel@tonic-gate case 'J': 13570Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_PROJECTS; 13580Sstevel@tonic-gate break; 13590Sstevel@tonic-gate case 'n': 1360586Svb160487 if ((p = strtok(optarg, ",")) == NULL) 1361586Svb160487 Die(gettext("invalid argument for -n\n")); 13620Sstevel@tonic-gate opts.o_ntop = Atoi(p); 13630Sstevel@tonic-gate if (p = strtok(NULL, ",")) 13640Sstevel@tonic-gate opts.o_nbottom = Atoi(p); 13650Sstevel@tonic-gate opts.o_outpmode &= ~OPT_FULLSCREEN; 13660Sstevel@tonic-gate break; 13670Sstevel@tonic-gate case 's': 13680Sstevel@tonic-gate opts.o_sortorder = -1; 13690Sstevel@tonic-gate sortk = optarg; 13700Sstevel@tonic-gate break; 13710Sstevel@tonic-gate case 'S': 13720Sstevel@tonic-gate opts.o_sortorder = 1; 13730Sstevel@tonic-gate sortk = optarg; 13740Sstevel@tonic-gate break; 13750Sstevel@tonic-gate case 'u': 1376586Svb160487 if ((p = strtok(optarg, ", ")) == NULL) 1377586Svb160487 Die(gettext("invalid argument for -u\n")); 13780Sstevel@tonic-gate add_uid(&euid_tbl, p); 13790Sstevel@tonic-gate while (p = strtok(NULL, ", ")) 13800Sstevel@tonic-gate add_uid(&euid_tbl, p); 13810Sstevel@tonic-gate break; 13820Sstevel@tonic-gate case 'U': 1383586Svb160487 if ((p = strtok(optarg, ", ")) == NULL) 1384586Svb160487 Die(gettext("invalid argument for -U\n")); 13850Sstevel@tonic-gate add_uid(&ruid_tbl, p); 13860Sstevel@tonic-gate while (p = strtok(NULL, ", ")) 13870Sstevel@tonic-gate add_uid(&ruid_tbl, p); 13880Sstevel@tonic-gate break; 13890Sstevel@tonic-gate case 'p': 1390586Svb160487 fill_table(&pid_tbl, optarg, 'p'); 13910Sstevel@tonic-gate break; 13920Sstevel@tonic-gate case 'C': 13930Sstevel@tonic-gate fill_set_table(optarg); 13940Sstevel@tonic-gate opts.o_outpmode |= OPT_PSETS; 13950Sstevel@tonic-gate break; 13960Sstevel@tonic-gate case 'P': 1397586Svb160487 fill_table(&cpu_tbl, optarg, 'P'); 13980Sstevel@tonic-gate break; 13990Sstevel@tonic-gate case 'k': 1400586Svb160487 fill_table(&tsk_tbl, optarg, 'k'); 14010Sstevel@tonic-gate break; 14020Sstevel@tonic-gate case 'j': 14030Sstevel@tonic-gate fill_prj_table(optarg); 14040Sstevel@tonic-gate break; 14050Sstevel@tonic-gate case 'L': 14060Sstevel@tonic-gate opts.o_outpmode |= OPT_LWPS; 14070Sstevel@tonic-gate break; 14080Sstevel@tonic-gate case 'z': 1409586Svb160487 if ((p = strtok(optarg, ", ")) == NULL) 1410586Svb160487 Die(gettext("invalid argument for -z\n")); 14110Sstevel@tonic-gate add_zone(&zone_tbl, p); 14120Sstevel@tonic-gate while (p = strtok(NULL, ", ")) 14130Sstevel@tonic-gate add_zone(&zone_tbl, p); 14140Sstevel@tonic-gate break; 14150Sstevel@tonic-gate case 'Z': 14160Sstevel@tonic-gate opts.o_outpmode |= OPT_SPLIT | OPT_ZONES; 14170Sstevel@tonic-gate break; 14180Sstevel@tonic-gate default: 14190Sstevel@tonic-gate Usage(); 14200Sstevel@tonic-gate } 14210Sstevel@tonic-gate } 14220Sstevel@tonic-gate 14230Sstevel@tonic-gate (void) atexit(Exit); 14240Sstevel@tonic-gate if ((opts.o_outpmode & OPT_USERS) && 14250Sstevel@tonic-gate !(opts.o_outpmode & OPT_SPLIT)) 14260Sstevel@tonic-gate opts.o_nbottom = opts.o_ntop; 14270Sstevel@tonic-gate if (opts.o_ntop == 0 || opts.o_nbottom == 0) 14280Sstevel@tonic-gate Die(gettext("invalid argument for -n\n")); 14290Sstevel@tonic-gate if (!(opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode & OPT_USERS) && 14300Sstevel@tonic-gate ((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT)))) 14310Sstevel@tonic-gate Die(gettext("-t option cannot be used with -v or -m\n")); 14320Sstevel@tonic-gate 14330Sstevel@tonic-gate if ((opts.o_outpmode & OPT_SPLIT) && (opts.o_outpmode && OPT_USERS) && 14340Sstevel@tonic-gate !((opts.o_outpmode & (OPT_PSINFO | OPT_MSACCT)))) 14350Sstevel@tonic-gate Die(gettext("-t option cannot be used with " 14360Sstevel@tonic-gate "-a, -J, -T or -Z\n")); 14370Sstevel@tonic-gate 14380Sstevel@tonic-gate if ((opts.o_outpmode & OPT_USERS) && 14392685Sakolb (opts.o_outpmode & 14402685Sakolb (OPT_TASKS | OPT_PROJECTS | OPT_ZONES))) 14410Sstevel@tonic-gate Die(gettext("-a option cannot be used with " 14420Sstevel@tonic-gate "-t, -J, -T or -Z\n")); 14430Sstevel@tonic-gate 14440Sstevel@tonic-gate if (((opts.o_outpmode & OPT_TASKS) && 14450Sstevel@tonic-gate (opts.o_outpmode & (OPT_PROJECTS|OPT_ZONES))) || 14460Sstevel@tonic-gate ((opts.o_outpmode & OPT_PROJECTS) && 14472685Sakolb (opts.o_outpmode & (OPT_TASKS|OPT_ZONES)))) { 14482685Sakolb Die(gettext( 14492685Sakolb "-J, -T and -Z options are mutually exclusive\n")); 14502685Sakolb } 14512685Sakolb 14522685Sakolb /* 14532685Sakolb * There is not enough space to combine microstate information and 14542685Sakolb * lgroup information and still fit in 80-column output. 14552685Sakolb */ 14562685Sakolb if ((opts.o_outpmode & OPT_LGRP) && (opts.o_outpmode & OPT_MSACCT)) { 14572685Sakolb Die(gettext("-H and -m options are mutually exclusive\n")); 14580Sstevel@tonic-gate } 14590Sstevel@tonic-gate 14600Sstevel@tonic-gate if (argc > optind) 14610Sstevel@tonic-gate opts.o_interval = Atoi(argv[optind++]); 14620Sstevel@tonic-gate if (argc > optind) 14630Sstevel@tonic-gate opts.o_count = Atoi(argv[optind++]); 14640Sstevel@tonic-gate if (opts.o_count == 0) 14650Sstevel@tonic-gate Die(gettext("invalid counter value\n")); 14660Sstevel@tonic-gate if (argc > optind) 14670Sstevel@tonic-gate Usage(); 14680Sstevel@tonic-gate if (opts.o_outpmode & OPT_REALTIME) 14690Sstevel@tonic-gate Priocntl("RT"); 14700Sstevel@tonic-gate if (isatty(STDOUT_FILENO) == 1 && isatty(STDIN_FILENO)) 14710Sstevel@tonic-gate opts.o_outpmode |= OPT_TTY; /* interactive */ 14720Sstevel@tonic-gate if (!(opts.o_outpmode & OPT_TTY)) { 14730Sstevel@tonic-gate opts.o_outpmode &= ~OPT_TERMCAP; /* no termcap for pipes */ 14740Sstevel@tonic-gate opts.o_outpmode &= ~OPT_FULLSCREEN; 14750Sstevel@tonic-gate } 14760Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP) 14770Sstevel@tonic-gate ldtermcap(); /* can turn OPT_TERMCAP off */ 14780Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP) 14790Sstevel@tonic-gate (void) setsize(); 14800Sstevel@tonic-gate list_alloc(&lwps, opts.o_ntop); 14810Sstevel@tonic-gate list_alloc(&users, opts.o_nbottom); 14820Sstevel@tonic-gate list_alloc(&tasks, opts.o_nbottom); 14830Sstevel@tonic-gate list_alloc(&projects, opts.o_nbottom); 14840Sstevel@tonic-gate list_alloc(&zones, opts.o_nbottom); 14852685Sakolb list_alloc(&lgroups, opts.o_nbottom); 14860Sstevel@tonic-gate list_setkeyfunc(sortk, &opts, &lwps, LT_LWPS); 14870Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &users, LT_USERS); 14880Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &tasks, LT_TASKS); 14890Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &projects, LT_PROJECTS); 14900Sstevel@tonic-gate list_setkeyfunc(NULL, &opts, &zones, LT_ZONES); 14912685Sakolb list_setkeyfunc(NULL, &opts, &lgroups, LT_LGRPS); 14920Sstevel@tonic-gate if (opts.o_outpmode & OPT_TERMCAP) 14930Sstevel@tonic-gate curses_on(); 14940Sstevel@tonic-gate if ((procdir = opendir("/proc")) == NULL) 14950Sstevel@tonic-gate Die(gettext("cannot open /proc directory\n")); 14960Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) { 14970Sstevel@tonic-gate (void) printf(gettext("Please wait...\r")); 14980Sstevel@tonic-gate (void) fflush(stdout); 14990Sstevel@tonic-gate } 15000Sstevel@tonic-gate set_signals(); 15010Sstevel@tonic-gate pollset.fd = STDIN_FILENO; 15020Sstevel@tonic-gate pollset.events = POLLIN; 15030Sstevel@tonic-gate timeout = opts.o_interval * MILLISEC; 15040Sstevel@tonic-gate 15050Sstevel@tonic-gate /* 15060Sstevel@tonic-gate * main program loop 15070Sstevel@tonic-gate */ 15080Sstevel@tonic-gate do { 15090Sstevel@tonic-gate if (sigterm == 1) 15100Sstevel@tonic-gate break; 15110Sstevel@tonic-gate if (sigtstp == 1) { 15120Sstevel@tonic-gate curses_off(); 15130Sstevel@tonic-gate (void) signal(SIGTSTP, SIG_DFL); 15140Sstevel@tonic-gate (void) kill(0, SIGTSTP); 15150Sstevel@tonic-gate /* 15160Sstevel@tonic-gate * prstat stops here until it receives SIGCONT signal. 15170Sstevel@tonic-gate */ 15180Sstevel@tonic-gate sigtstp = 0; 15190Sstevel@tonic-gate (void) signal(SIGTSTP, sig_handler); 15200Sstevel@tonic-gate curses_on(); 15210Sstevel@tonic-gate print_movecur = FALSE; 15220Sstevel@tonic-gate if (opts.o_outpmode & OPT_FULLSCREEN) 15230Sstevel@tonic-gate sigwinch = 1; 15240Sstevel@tonic-gate } 15250Sstevel@tonic-gate if (sigwinch == 1) { 15260Sstevel@tonic-gate if (setsize() == 1) { 15270Sstevel@tonic-gate list_free(&lwps); 15280Sstevel@tonic-gate list_free(&users); 15290Sstevel@tonic-gate list_free(&tasks); 15300Sstevel@tonic-gate list_free(&projects); 15310Sstevel@tonic-gate list_free(&zones); 15320Sstevel@tonic-gate list_alloc(&lwps, opts.o_ntop); 15330Sstevel@tonic-gate list_alloc(&users, opts.o_nbottom); 15340Sstevel@tonic-gate list_alloc(&tasks, opts.o_nbottom); 15350Sstevel@tonic-gate list_alloc(&projects, opts.o_nbottom); 15360Sstevel@tonic-gate list_alloc(&zones, opts.o_nbottom); 15370Sstevel@tonic-gate } 15380Sstevel@tonic-gate sigwinch = 0; 15390Sstevel@tonic-gate (void) signal(SIGWINCH, sig_handler); 15400Sstevel@tonic-gate } 15410Sstevel@tonic-gate prstat_scandir(procdir); 15420Sstevel@tonic-gate list_refresh(&lwps); 15430Sstevel@tonic-gate if (print_movecur) 15440Sstevel@tonic-gate (void) putp(movecur); 15450Sstevel@tonic-gate print_movecur = TRUE; 15460Sstevel@tonic-gate if ((opts.o_outpmode & OPT_PSINFO) || 15470Sstevel@tonic-gate (opts.o_outpmode & OPT_MSACCT)) { 15480Sstevel@tonic-gate list_sort(&lwps); 15490Sstevel@tonic-gate list_print(&lwps); 15500Sstevel@tonic-gate } 15510Sstevel@tonic-gate if (opts.o_outpmode & OPT_USERS) { 1552*3247Sgjelinek list_getsize(&users); 15530Sstevel@tonic-gate list_sort(&users); 15540Sstevel@tonic-gate list_print(&users); 15550Sstevel@tonic-gate list_clear(&users); 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate if (opts.o_outpmode & OPT_TASKS) { 1558*3247Sgjelinek list_getsize(&tasks); 15590Sstevel@tonic-gate list_sort(&tasks); 15600Sstevel@tonic-gate list_print(&tasks); 15610Sstevel@tonic-gate list_clear(&tasks); 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate if (opts.o_outpmode & OPT_PROJECTS) { 1564*3247Sgjelinek list_getsize(&projects); 15650Sstevel@tonic-gate list_sort(&projects); 15660Sstevel@tonic-gate list_print(&projects); 15670Sstevel@tonic-gate list_clear(&projects); 15680Sstevel@tonic-gate } 15690Sstevel@tonic-gate if (opts.o_outpmode & OPT_ZONES) { 1570*3247Sgjelinek list_getsize(&zones); 15710Sstevel@tonic-gate list_sort(&zones); 15720Sstevel@tonic-gate list_print(&zones); 15730Sstevel@tonic-gate list_clear(&zones); 15740Sstevel@tonic-gate } 15750Sstevel@tonic-gate if (opts.o_count == 1) 15760Sstevel@tonic-gate break; 15770Sstevel@tonic-gate /* 15780Sstevel@tonic-gate * If poll() returns -1 and sets errno to EINTR here because 15790Sstevel@tonic-gate * the process received a signal, it is Ok to abort this 15800Sstevel@tonic-gate * timeout and loop around because we check the signals at the 15810Sstevel@tonic-gate * top of the loop. 15820Sstevel@tonic-gate */ 15830Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) { 15840Sstevel@tonic-gate if (poll(&pollset, (nfds_t)1, timeout) > 0) { 15850Sstevel@tonic-gate if (read(STDIN_FILENO, &key, 1) == 1) { 15860Sstevel@tonic-gate if (tolower(key) == 'q') 15870Sstevel@tonic-gate break; 15880Sstevel@tonic-gate } 15890Sstevel@tonic-gate } 15900Sstevel@tonic-gate } else { 15910Sstevel@tonic-gate (void) sleep(opts.o_interval); 15920Sstevel@tonic-gate } 15930Sstevel@tonic-gate } while (opts.o_count == (-1) || --opts.o_count); 15940Sstevel@tonic-gate 15950Sstevel@tonic-gate if (opts.o_outpmode & OPT_TTY) 15960Sstevel@tonic-gate (void) putchar('\r'); 15970Sstevel@tonic-gate return (0); 15980Sstevel@tonic-gate } 1599