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