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