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