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