Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/ps/ps.c
+++ new/usr/src/cmd/ps/ps.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
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
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
29 29 /*
30 - * Copyright (c) 2012, Joyent, Inc. All rights reserved.
30 + * Copyright (c) 2018, Joyent, Inc.
31 31 */
32 32
33 33 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
34 -/* All Rights Reserved */
34 +/* All Rights Reserved */
35 35
36 36 /*
37 37 * ps -- print things about processes.
38 38 */
39 39 #include <stdio.h>
40 40 #include <ctype.h>
41 41 #include <string.h>
42 42 #include <errno.h>
43 43 #include <fcntl.h>
44 44 #include <pwd.h>
45 45 #include <grp.h>
46 46 #include <sys/types.h>
47 47 #include <sys/stat.h>
48 48 #include <sys/mkdev.h>
49 49 #include <unistd.h>
50 50 #include <stdlib.h>
51 51 #include <limits.h>
52 52 #include <dirent.h>
53 53 #include <sys/signal.h>
54 54 #include <sys/fault.h>
55 55 #include <sys/syscall.h>
56 56 #include <sys/time.h>
57 57 #include <procfs.h>
58 58 #include <locale.h>
59 59 #include <wctype.h>
60 60 #include <wchar.h>
61 61 #include <libw.h>
62 62 #include <stdarg.h>
63 63 #include <sys/proc.h>
64 64 #include <sys/pset.h>
65 65 #include <project.h>
66 66 #include <zone.h>
67 67
68 68 #define min(a, b) ((a) > (b) ? (b) : (a))
69 69 #define max(a, b) ((a) < (b) ? (b) : (a))
70 70
71 71 #define NTTYS 20 /* initial size of table for -t option */
72 72 #define SIZ 30 /* initial size of tables for -p, -s, -g, -h and -z */
73 73
74 74 /*
75 75 * Size of buffer holding args for t, p, s, g, u, U, G, z options.
76 76 * Set to ZONENAME_MAX, the minimum value needed to allow any
77 77 * zone to be specified.
78 78 */
79 79 #define ARGSIZ ZONENAME_MAX
80 80
81 81 /* Max chars in a user/group name or printed u/g id */
82 82 #define MAXUGNAME (LOGNAME_MAX+2)
83 83
84 84 /* Structure for storing user or group info */
85 85 struct ugdata {
86 86 id_t id; /* numeric user-id or group-id */
87 87 char name[MAXUGNAME+1]; /* user/group name, null terminated */
88 88 };
89 89
90 90 struct ughead {
91 91 size_t size; /* number of ugdata structs allocated */
92 92 size_t nent; /* number of active entries */
93 93 struct ugdata *ent; /* pointer to array of actual entries */
94 94 };
95 95
96 96 enum fname { /* enumeration of field names */
97 97 F_USER, /* effective user of the process */
98 98 F_RUSER, /* real user of the process */
99 99 F_GROUP, /* effective group of the process */
100 100 F_RGROUP, /* real group of the process */
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
101 101 F_UID, /* numeric effective uid of the process */
102 102 F_RUID, /* numeric real uid of the process */
103 103 F_GID, /* numeric effective gid of the process */
104 104 F_RGID, /* numeric real gid of the process */
105 105 F_PID, /* process id */
106 106 F_PPID, /* parent process id */
107 107 F_PGID, /* process group id */
108 108 F_SID, /* session id */
109 109 F_PSR, /* bound processor */
110 110 F_LWP, /* lwp-id */
111 + F_LWPNAME, /* lwp name */
111 112 F_NLWP, /* number of lwps */
112 113 F_OPRI, /* old priority (obsolete) */
113 114 F_PRI, /* new priority */
114 115 F_F, /* process flags */
115 116 F_S, /* letter indicating the state */
116 117 F_C, /* processor utilization (obsolete) */
117 118 F_PCPU, /* percent of recently used cpu time */
118 119 F_PMEM, /* percent of physical memory used (rss) */
119 120 F_OSZ, /* virtual size of the process in pages */
120 121 F_VSZ, /* virtual size of the process in kilobytes */
121 122 F_RSS, /* resident set size of the process in kilobytes */
122 123 F_NICE, /* "nice" value of the process */
123 124 F_CLASS, /* scheduler class */
124 125 F_STIME, /* start time of the process, hh:mm:ss or Month Day */
125 126 F_ETIME, /* elapsed time of the process, [[dd-]hh:]mm:ss */
126 127 F_TIME, /* cpu time of the process, [[dd-]hh:]mm:ss */
127 128 F_TTY, /* name of the controlling terminal */
128 129 F_ADDR, /* address of the process (obsolete) */
129 130 F_WCHAN, /* wait channel (sleep condition variable) */
130 131 F_FNAME, /* file name of command */
131 132 F_COMM, /* name of command (argv[0] value) */
132 133 F_ARGS, /* name of command plus all its arguments */
133 134 F_TASKID, /* task id */
134 135 F_PROJID, /* project id */
135 136 F_PROJECT, /* project name of the process */
136 137 F_PSET, /* bound processor set */
137 138 F_ZONE, /* zone name */
138 139 F_ZONEID, /* zone id */
139 140 F_CTID, /* process contract id */
140 141 F_LGRP, /* process home lgroup */
141 142 F_DMODEL /* process data model */
142 143 };
143 144
144 145 struct field {
145 146 struct field *next; /* linked list */
146 147 int fname; /* field index */
147 148 const char *header; /* header to use */
148 149 int width; /* width of field */
149 150 };
150 151
151 152 static struct field *fields = NULL; /* fields selected via -o */
152 153 static struct field *last_field = NULL;
153 154 static int do_header = 0;
154 155 static struct timeval now;
155 156
156 157 /* array of defined fields, in fname order */
157 158 struct def_field {
158 159 const char *fname;
159 160 const char *header;
160 161 int width;
161 162 int minwidth;
162 163 };
163 164
164 165 static struct def_field fname[] = {
165 166 /* fname header width minwidth */
166 167 { "user", "USER", 8, 8 },
167 168 { "ruser", "RUSER", 8, 8 },
168 169 { "group", "GROUP", 8, 8 },
169 170 { "rgroup", "RGROUP", 8, 8 },
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
170 171 { "uid", "UID", 5, 5 },
171 172 { "ruid", "RUID", 5, 5 },
172 173 { "gid", "GID", 5, 5 },
173 174 { "rgid", "RGID", 5, 5 },
174 175 { "pid", "PID", 5, 5 },
175 176 { "ppid", "PPID", 5, 5 },
176 177 { "pgid", "PGID", 5, 5 },
177 178 { "sid", "SID", 5, 5 },
178 179 { "psr", "PSR", 3, 2 },
179 180 { "lwp", "LWP", 6, 2 },
181 + { "lwpname", "LWPNAME", 32, 8 },
180 182 { "nlwp", "NLWP", 4, 2 },
181 183 { "opri", "PRI", 3, 2 },
182 184 { "pri", "PRI", 3, 2 },
183 185 { "f", "F", 2, 2 },
184 186 { "s", "S", 1, 1 },
185 187 { "c", "C", 2, 2 },
186 188 { "pcpu", "%CPU", 4, 4 },
187 189 { "pmem", "%MEM", 4, 4 },
188 190 { "osz", "SZ", 4, 4 },
189 191 { "vsz", "VSZ", 4, 4 },
190 192 { "rss", "RSS", 4, 4 },
191 193 { "nice", "NI", 2, 2 },
192 194 { "class", "CLS", 4, 2 },
193 195 { "stime", "STIME", 8, 8 },
194 196 { "etime", "ELAPSED", 11, 7 },
195 197 { "time", "TIME", 11, 5 },
196 198 { "tty", "TT", 7, 7 },
197 199 #ifdef _LP64
198 200 { "addr", "ADDR", 16, 8 },
199 201 { "wchan", "WCHAN", 16, 8 },
200 202 #else
201 203 { "addr", "ADDR", 8, 8 },
202 204 { "wchan", "WCHAN", 8, 8 },
203 205 #endif
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
204 206 { "fname", "COMMAND", 8, 8 },
205 207 { "comm", "COMMAND", 80, 8 },
206 208 { "args", "COMMAND", 80, 80 },
207 209 { "taskid", "TASKID", 5, 5 },
208 210 { "projid", "PROJID", 5, 5 },
209 211 { "project", "PROJECT", 8, 8 },
210 212 { "pset", "PSET", 3, 3 },
211 213 { "zone", "ZONE", 8, 8 },
212 214 { "zoneid", "ZONEID", 5, 5 },
213 215 { "ctid", "CTID", 5, 5 },
214 - { "lgrp", "LGRP", 4, 2 },
215 - { "dmodel", "DMODEL", 6, 6 },
216 + { "lgrp", "LGRP", 4, 2 },
217 + { "dmodel", "DMODEL", 6, 6 },
216 218 };
217 219
218 220 #define NFIELDS (sizeof (fname) / sizeof (fname[0]))
219 221
220 222 static int retcode = 1;
221 223 static int lflg;
222 224 static int Aflg;
223 225 static int uflg;
224 226 static int Uflg;
225 227 static int Gflg;
226 228 static int aflg;
227 229 static int dflg;
228 230 static int Lflg;
229 231 static int Pflg;
230 232 static int Wflg;
231 233 static int yflg;
232 234 static int pflg;
233 235 static int fflg;
234 236 static int cflg;
235 237 static int jflg;
236 238 static int gflg;
237 239 static int sflg;
238 240 static int tflg;
239 241 static int zflg;
240 242 static int Zflg;
241 243 static int hflg;
242 244 static int Hflg;
243 245 static uid_t tuid = (uid_t)-1;
244 246 static int errflg;
245 247
246 248 static int ndev; /* number of devices */
247 249 static int maxdev; /* number of devl structures allocated */
248 250
249 251 #define DNINCR 100
250 252 #define DNSIZE 14
251 253 static struct devl { /* device list */
252 254 char dname[DNSIZE]; /* device name */
253 255 dev_t ddev; /* device number */
254 256 } *devl;
255 257
256 258 static struct tty {
257 259 char *tname;
258 260 dev_t tdev;
259 261 } *tty = NULL; /* for t option */
260 262 static size_t ttysz = 0;
261 263 static int ntty = 0;
262 264
263 265 static pid_t *pid = NULL; /* for p option */
264 266 static size_t pidsz = 0;
265 267 static size_t npid = 0;
266 268
267 269 static int *lgrps = NULL; /* list of lgroup IDs for for h option */
268 270 static size_t lgrps_size = 0; /* size of the lgrps list */
269 271 static size_t nlgrps = 0; /* number elements in the list */
270 272
271 273 /* Maximum possible lgroup ID value */
272 274 #define MAX_LGRP_ID 256
273 275
274 276 static pid_t *grpid = NULL; /* for g option */
275 277 static size_t grpidsz = 0;
276 278 static int ngrpid = 0;
277 279
278 280 static pid_t *sessid = NULL; /* for s option */
279 281 static size_t sessidsz = 0;
280 282 static int nsessid = 0;
281 283
282 284 static zoneid_t *zoneid = NULL; /* for z option */
283 285 static size_t zoneidsz = 0;
284 286 static int nzoneid = 0;
285 287
286 288 static int kbytes_per_page;
287 289 static int pidwidth;
288 290
289 291 static char *procdir = "/proc"; /* standard /proc directory */
290 292
291 293 static struct ughead euid_tbl; /* table to store selected euid's */
292 294 static struct ughead ruid_tbl; /* table to store selected real uid's */
293 295 static struct ughead egid_tbl; /* table to store selected egid's */
294 296 static struct ughead rgid_tbl; /* table to store selected real gid's */
295 297 static prheader_t *lpsinfobuf; /* buffer to contain lpsinfo */
296 298 static size_t lpbufsize;
297 299
298 300 /*
299 301 * This constant defines the sentinal number of process IDs below which we
300 302 * only examine individual entries in /proc rather than scanning through
301 303 * /proc. This optimization is a huge win in the common case.
302 304 */
303 305 #define PTHRESHOLD 40
304 306
305 307 #define UCB_OPTS "-aceglnrtuvwxSU"
306 308
307 309 static void usage(void);
308 310 static char *getarg(char **);
309 311 static char *parse_format(char *);
310 312 static char *gettty(psinfo_t *);
311 313 static int prfind(int, psinfo_t *, char **);
312 314 static void prcom(psinfo_t *, char *);
313 315 static void prtpct(ushort_t, int);
314 316 static void print_time(time_t, int);
315 317 static void print_field(psinfo_t *, struct field *, const char *);
316 318 static void print_zombie_field(psinfo_t *, struct field *, const char *);
317 319 static void pr_fields(psinfo_t *, const char *,
318 320 void (*print_fld)(psinfo_t *, struct field *, const char *));
319 321 static int search(pid_t *, int, pid_t);
320 322 static void add_ugentry(struct ughead *, char *);
321 323 static int uconv(struct ughead *);
322 324 static int gconv(struct ughead *);
323 325 static int ugfind(id_t, struct ughead *);
324 326 static void prtime(timestruc_t, int, int);
325 327 static void przom(psinfo_t *);
326 328 static int namencnt(char *, int, int);
327 329 static char *err_string(int);
328 330 static int print_proc(char *pname);
329 331 static time_t delta_secs(const timestruc_t *);
330 332 static int str2id(const char *, pid_t *, long, long);
331 333 static int str2uid(const char *, uid_t *, unsigned long, unsigned long);
332 334 static void *Realloc(void *, size_t);
333 335 static int pidcmp(const void *p1, const void *p2);
334 336
335 337 extern int ucbmain(int, char **);
336 338 static int stdmain(int, char **);
337 339
338 340 int
339 341 main(int argc, char **argv)
340 342 {
341 343 const char *me;
342 344
343 345 /*
344 346 * The original two ps'es are linked in a single binary;
345 347 * their main()s are renamed to stdmain for /usr/bin/ps and
346 348 * ucbmain for /usr/ucb/ps.
347 349 * We try to figure out which instance of ps the user wants to run.
348 350 * Traditionally, the UCB variant doesn't require the flag argument
349 351 * start with a "-". If the first argument doesn't start with a
350 352 * "-", we call "ucbmain".
351 353 * If there's a first argument and it starts with a "-", we check
352 354 * whether any of the options isn't acceptable to "ucbmain"; in that
353 355 * case we run "stdmain".
354 356 * If we can't tell from the options which main to call, we check
355 357 * the binary we are running. We default to "stdmain" but
356 358 * any mention in the executable name of "ucb" causes us to call
357 359 * ucbmain.
358 360 */
359 361 if (argv[1] != NULL) {
360 362 if (argv[1][0] != '-')
361 363 return (ucbmain(argc, argv));
362 364 else if (argv[1][strspn(argv[1], UCB_OPTS)] != '\0')
363 365 return (stdmain(argc, argv));
364 366 }
365 367
366 368 me = getexecname();
367 369
368 370 if (me != NULL && strstr(me, "ucb") != NULL)
369 371 return (ucbmain(argc, argv));
370 372 else
371 373 return (stdmain(argc, argv));
372 374 }
373 375
374 376 static int
375 377 stdmain(int argc, char **argv)
376 378 {
377 379 char *p;
378 380 char *p1;
379 381 char *parg;
380 382 int c;
381 383 int i;
382 384 int pgerrflg = 0; /* err flg: non-numeric arg w/p & g options */
383 385 size_t size, len;
384 386 DIR *dirp;
385 387 struct dirent *dentp;
386 388 pid_t maxpid;
387 389 pid_t id;
388 390 int ret;
389 391 char loc_stime_str[32];
390 392
391 393 (void) setlocale(LC_ALL, "");
392 394 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
393 395 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
394 396 #endif
395 397 (void) textdomain(TEXT_DOMAIN);
396 398
397 399 (void) memset(&euid_tbl, 0, sizeof (euid_tbl));
398 400 (void) memset(&ruid_tbl, 0, sizeof (ruid_tbl));
399 401 (void) memset(&egid_tbl, 0, sizeof (egid_tbl));
400 402 (void) memset(&rgid_tbl, 0, sizeof (rgid_tbl));
401 403
402 404 kbytes_per_page = sysconf(_SC_PAGESIZE) / 1024;
403 405
404 406 (void) gettimeofday(&now, NULL);
405 407
406 408 /*
407 409 * calculate width of pid fields based on configured MAXPID
408 410 * (must be at least 5 to retain output format compatibility)
409 411 */
410 412 id = maxpid = (pid_t)sysconf(_SC_MAXPID);
411 413 pidwidth = 1;
412 414 while ((id /= 10) > 0)
413 415 ++pidwidth;
414 416 pidwidth = pidwidth < 5 ? 5 : pidwidth;
415 417
416 418 fname[F_PID].width = fname[F_PPID].width = pidwidth;
417 419 fname[F_PGID].width = fname[F_SID].width = pidwidth;
418 420
419 421 /*
420 422 * TRANSLATION_NOTE
421 423 * Specify the printf format with width and precision for
422 424 * the STIME field.
423 425 */
424 426 len = snprintf(loc_stime_str, sizeof (loc_stime_str),
425 427 dcgettext(NULL, "%8.8s", LC_TIME), "STIME");
426 428 if (len >= sizeof (loc_stime_str))
427 429 len = sizeof (loc_stime_str) - 1;
428 430
429 431 fname[F_STIME].width = fname[F_STIME].minwidth = len;
430 432
431 433 while ((c = getopt(argc, argv, "jlfceAadLPWyZHh:t:p:g:u:U:G:n:s:o:z:"))
432 434 != EOF)
433 435 switch (c) {
434 436 case 'H': /* Show home lgroups */
435 437 Hflg++;
436 438 break;
437 439 case 'h':
438 440 /*
439 441 * Show processes/threads with given home lgroups
440 442 */
441 443 hflg++;
442 444 p1 = optarg;
443 445 do {
444 446 int id;
445 447
446 448 /*
447 449 * Get all IDs in the list, verify for
448 450 * correctness and place in lgrps array.
449 451 */
450 452 parg = getarg(&p1);
451 453 /* Convert string to integer */
452 454 ret = str2id(parg, (pid_t *)&id, 0,
453 455 MAX_LGRP_ID);
454 456 /* Complain if ID didn't parse correctly */
455 457 if (ret != 0) {
456 458 pgerrflg++;
457 459 (void) fprintf(stderr,
458 460 gettext("ps: %s "), parg);
459 461 if (ret == EINVAL)
460 462 (void) fprintf(stderr,
461 463 gettext("is an invalid "
462 464 "non-numeric argument"));
463 465 else
464 466 (void) fprintf(stderr,
465 467 gettext("exceeds valid "
466 468 "range"));
467 469 (void) fprintf(stderr,
468 470 gettext(" for -h option\n"));
469 471 continue;
470 472 }
471 473
472 474 /* Extend lgrps array if needed */
473 475 if (nlgrps == lgrps_size) {
474 476 /* Double the size of the lgrps array */
475 477 if (lgrps_size == 0)
476 478 lgrps_size = SIZ;
477 479 lgrps_size *= 2;
478 480 lgrps = Realloc(lgrps,
479 481 lgrps_size * sizeof (int));
480 482 }
481 483 /* place the id in the lgrps table */
482 484 lgrps[nlgrps++] = id;
483 485 } while (*p1);
484 486 break;
485 487 case 'l': /* long listing */
486 488 lflg++;
487 489 break;
488 490 case 'f': /* full listing */
489 491 fflg++;
490 492 break;
491 493 case 'j':
492 494 jflg++;
493 495 break;
494 496 case 'c':
495 497 /*
496 498 * Format output to reflect scheduler changes:
497 499 * high numbers for high priorities and don't
498 500 * print nice or p_cpu values. 'c' option only
499 501 * effective when used with 'l' or 'f' options.
500 502 */
501 503 cflg++;
502 504 break;
503 505 case 'A': /* list every process */
504 506 case 'e': /* (obsolete) list every process */
505 507 Aflg++;
506 508 tflg = Gflg = Uflg = uflg = pflg = gflg = sflg = 0;
507 509 zflg = hflg = 0;
508 510 break;
509 511 case 'a':
510 512 /*
511 513 * Same as 'e' except no session group leaders
512 514 * and no non-terminal processes.
513 515 */
514 516 aflg++;
515 517 break;
516 518 case 'd': /* same as e except no session leaders */
517 519 dflg++;
518 520 break;
519 521 case 'L': /* show lwps */
520 522 Lflg++;
521 523 break;
522 524 case 'P': /* show bound processor */
523 525 Pflg++;
524 526 break;
525 527 case 'W': /* truncate long names */
526 528 Wflg++;
527 529 break;
528 530 case 'y': /* omit F & ADDR, report RSS & SZ in Kby */
529 531 yflg++;
530 532 break;
531 533 case 'n': /* no longer needed; retain as no-op */
532 534 (void) fprintf(stderr,
533 535 gettext("ps: warning: -n option ignored\n"));
534 536 break;
535 537 case 't': /* terminals */
536 538 #define TSZ 30
537 539 tflg++;
538 540 p1 = optarg;
539 541 do {
540 542 char nambuf[TSZ+6]; /* for "/dev/" + '\0' */
541 543 struct stat64 s;
542 544 parg = getarg(&p1);
543 545 p = Realloc(NULL, TSZ+1); /* for '\0' */
544 546 /* zero the buffer before using it */
545 547 p[0] = '\0';
546 548 size = TSZ;
547 549 if (isdigit(*parg)) {
548 550 (void) strcpy(p, "tty");
549 551 size -= 3;
550 552 }
551 553 (void) strncat(p, parg, size);
552 554 if (ntty == ttysz) {
553 555 if ((ttysz *= 2) == 0)
554 556 ttysz = NTTYS;
555 557 tty = Realloc(tty,
556 558 (ttysz + 1) * sizeof (struct tty));
557 559 }
558 560 tty[ntty].tdev = PRNODEV;
559 561 (void) strcpy(nambuf, "/dev/");
560 562 (void) strcat(nambuf, p);
561 563 if (stat64(nambuf, &s) == 0)
562 564 tty[ntty].tdev = s.st_rdev;
563 565 tty[ntty++].tname = p;
564 566 } while (*p1);
565 567 break;
566 568 case 'p': /* proc ids */
567 569 pflg++;
568 570 p1 = optarg;
569 571 do {
570 572 pid_t id;
571 573
572 574 parg = getarg(&p1);
573 575 if ((ret = str2id(parg, &id, 0, maxpid)) != 0) {
574 576 pgerrflg++;
575 577 (void) fprintf(stderr,
576 578 gettext("ps: %s "), parg);
577 579 if (ret == EINVAL)
578 580 (void) fprintf(stderr,
579 581 gettext("is an invalid "
580 582 "non-numeric argument"));
581 583 else
582 584 (void) fprintf(stderr,
583 585 gettext("exceeds valid "
584 586 "range"));
585 587 (void) fprintf(stderr,
586 588 gettext(" for -p option\n"));
587 589 continue;
588 590 }
589 591
590 592 if (npid == pidsz) {
591 593 if ((pidsz *= 2) == 0)
592 594 pidsz = SIZ;
593 595 pid = Realloc(pid,
594 596 pidsz * sizeof (pid_t));
595 597 }
596 598 pid[npid++] = id;
597 599 } while (*p1);
598 600 break;
599 601 case 's': /* session */
600 602 sflg++;
601 603 p1 = optarg;
602 604 do {
603 605 pid_t id;
604 606
605 607 parg = getarg(&p1);
606 608 if ((ret = str2id(parg, &id, 0, maxpid)) != 0) {
607 609 pgerrflg++;
608 610 (void) fprintf(stderr,
609 611 gettext("ps: %s "), parg);
610 612 if (ret == EINVAL)
611 613 (void) fprintf(stderr,
612 614 gettext("is an invalid "
613 615 "non-numeric argument"));
614 616 else
615 617 (void) fprintf(stderr,
616 618 gettext("exceeds valid "
617 619 "range"));
618 620 (void) fprintf(stderr,
619 621 gettext(" for -s option\n"));
620 622 continue;
621 623 }
622 624
623 625 if (nsessid == sessidsz) {
624 626 if ((sessidsz *= 2) == 0)
625 627 sessidsz = SIZ;
626 628 sessid = Realloc(sessid,
627 629 sessidsz * sizeof (pid_t));
628 630 }
629 631 sessid[nsessid++] = id;
630 632 } while (*p1);
631 633 break;
632 634 case 'g': /* proc group */
633 635 gflg++;
634 636 p1 = optarg;
635 637 do {
636 638 pid_t id;
637 639
638 640 parg = getarg(&p1);
639 641 if ((ret = str2id(parg, &id, 0, maxpid)) != 0) {
640 642 pgerrflg++;
641 643 (void) fprintf(stderr,
642 644 gettext("ps: %s "), parg);
643 645 if (ret == EINVAL)
644 646 (void) fprintf(stderr,
645 647 gettext("is an invalid "
646 648 "non-numeric argument"));
647 649 else
648 650 (void) fprintf(stderr,
649 651 gettext("exceeds valid "
650 652 "range"));
651 653 (void) fprintf(stderr,
652 654 gettext(" for -g option\n"));
653 655 continue;
654 656 }
655 657
656 658 if (ngrpid == grpidsz) {
657 659 if ((grpidsz *= 2) == 0)
658 660 grpidsz = SIZ;
659 661 grpid = Realloc(grpid,
660 662 grpidsz * sizeof (pid_t));
661 663 }
662 664 grpid[ngrpid++] = id;
663 665 } while (*p1);
664 666 break;
665 667 case 'u': /* effective user name or number */
666 668 uflg++;
667 669 p1 = optarg;
668 670 do {
669 671 parg = getarg(&p1);
670 672 add_ugentry(&euid_tbl, parg);
671 673 } while (*p1);
672 674 break;
673 675 case 'U': /* real user name or number */
674 676 Uflg++;
675 677 p1 = optarg;
676 678 do {
677 679 parg = getarg(&p1);
678 680 add_ugentry(&ruid_tbl, parg);
679 681 } while (*p1);
680 682 break;
681 683 case 'G': /* real group name or number */
682 684 Gflg++;
683 685 p1 = optarg;
684 686 do {
685 687 parg = getarg(&p1);
686 688 add_ugentry(&rgid_tbl, parg);
687 689 } while (*p1);
688 690 break;
689 691 case 'o': /* output format */
690 692 p = optarg;
691 693 while ((p = parse_format(p)) != NULL)
692 694 ;
693 695 break;
694 696 case 'z': /* zone name or number */
695 697 zflg++;
696 698 p1 = optarg;
697 699 do {
698 700 zoneid_t id;
699 701
700 702 parg = getarg(&p1);
701 703 if (zone_get_id(parg, &id) != 0) {
702 704 pgerrflg++;
703 705 (void) fprintf(stderr,
704 706 gettext("ps: unknown zone %s\n"),
705 707 parg);
706 708 continue;
707 709 }
708 710
709 711 if (nzoneid == zoneidsz) {
710 712 if ((zoneidsz *= 2) == 0)
711 713 zoneidsz = SIZ;
712 714 zoneid = Realloc(zoneid,
713 715 zoneidsz * sizeof (zoneid_t));
714 716 }
715 717 zoneid[nzoneid++] = id;
716 718 } while (*p1);
717 719 break;
718 720 case 'Z': /* show zone name */
719 721 Zflg++;
720 722 break;
721 723 default: /* error on ? */
722 724 errflg++;
723 725 break;
724 726 }
725 727
726 728 if (errflg || optind < argc || pgerrflg)
727 729 usage();
728 730
729 731 if (tflg)
730 732 tty[ntty].tname = NULL;
731 733 /*
732 734 * If an appropriate option has not been specified, use the
733 735 * current terminal and effective uid as the default.
734 736 */
735 737 if (!(aflg|Aflg|dflg|Gflg|hflg|Uflg|uflg|tflg|pflg|gflg|sflg|zflg)) {
736 738 psinfo_t info;
737 739 int procfd;
738 740 char *name;
739 741 char pname[100];
740 742
741 743 /* get our own controlling tty name using /proc */
742 744 (void) snprintf(pname, sizeof (pname),
743 745 "%s/self/psinfo", procdir);
744 746 if ((procfd = open(pname, O_RDONLY)) < 0 ||
745 747 read(procfd, (char *)&info, sizeof (info)) < 0 ||
746 748 info.pr_ttydev == PRNODEV) {
747 749 (void) fprintf(stderr,
748 750 gettext("ps: no controlling terminal\n"));
749 751 exit(1);
750 752 }
751 753 (void) close(procfd);
752 754
753 755 i = 0;
754 756 name = gettty(&info);
755 757 if (*name == '?') {
756 758 (void) fprintf(stderr,
757 759 gettext("ps: can't find controlling terminal\n"));
758 760 exit(1);
759 761 }
760 762 if (ntty == ttysz) {
761 763 if ((ttysz *= 2) == 0)
762 764 ttysz = NTTYS;
763 765 tty = Realloc(tty, (ttysz + 1) * sizeof (struct tty));
764 766 }
765 767 tty[ntty].tdev = info.pr_ttydev;
766 768 tty[ntty++].tname = name;
767 769 tty[ntty].tname = NULL;
768 770 tflg++;
769 771 tuid = getuid();
770 772 }
771 773 if (Aflg) {
772 774 Gflg = Uflg = uflg = pflg = sflg = gflg = aflg = dflg = 0;
773 775 zflg = hflg = 0;
774 776 }
775 777 if (Aflg | aflg | dflg)
776 778 tflg = 0;
777 779
778 780 i = 0; /* prepare to exit on name lookup errors */
779 781 i += uconv(&euid_tbl);
780 782 i += uconv(&ruid_tbl);
781 783 i += gconv(&egid_tbl);
782 784 i += gconv(&rgid_tbl);
783 785 if (i)
784 786 exit(1);
785 787
786 788 /* allocate a buffer for lwpsinfo structures */
787 789 lpbufsize = 4096;
788 790 if (Lflg && (lpsinfobuf = malloc(lpbufsize)) == NULL) {
789 791 (void) fprintf(stderr,
790 792 gettext("ps: no memory\n"));
791 793 exit(1);
792 794 }
793 795
794 796 if (fields) { /* print user-specified header */
795 797 if (do_header) {
↓ open down ↓ |
570 lines elided |
↑ open up ↑ |
796 798 struct field *f;
797 799
798 800 for (f = fields; f != NULL; f = f->next) {
799 801 if (f != fields)
800 802 (void) printf(" ");
801 803 switch (f->fname) {
802 804 case F_TTY:
803 805 (void) printf("%-*s",
804 806 f->width, f->header);
805 807 break;
808 + case F_LWPNAME:
806 809 case F_FNAME:
807 810 case F_COMM:
808 811 case F_ARGS:
809 812 /*
810 813 * Print these headers full width
811 814 * unless they appear at the end.
812 815 */
813 816 if (f->next != NULL) {
814 817 (void) printf("%-*s",
815 818 f->width, f->header);
816 819 } else {
817 820 (void) printf("%s",
818 821 f->header);
819 822 }
820 823 break;
821 824 default:
822 825 (void) printf("%*s",
823 826 f->width, f->header);
824 827 break;
825 828 }
826 829 }
827 830 (void) printf("\n");
828 831 }
829 832 } else { /* print standard header */
830 833 /*
831 834 * All fields before 'PID' are printed with a trailing space
832 835 * as a separator and that is how we print the headers too.
833 836 */
834 837 if (lflg) {
835 838 if (yflg)
836 839 (void) printf("S ");
837 840 else
838 841 (void) printf(" F S ");
839 842 }
840 843 if (Zflg)
841 844 (void) printf(" ZONE ");
842 845 if (fflg) {
843 846 (void) printf(" UID ");
844 847 } else if (lflg)
845 848 (void) printf(" UID ");
846 849
847 850 (void) printf("%*s", pidwidth, "PID");
848 851 if (lflg || fflg)
849 852 (void) printf(" %*s", pidwidth, "PPID");
850 853 if (jflg)
851 854 (void) printf(" %*s %*s", pidwidth, "PGID",
852 855 pidwidth, "SID");
853 856 if (Lflg)
854 857 (void) printf(" LWP");
855 858 if (Pflg)
856 859 (void) printf(" PSR");
857 860 if (Lflg && fflg)
858 861 (void) printf(" NLWP");
859 862 if (cflg)
860 863 (void) printf(" CLS PRI");
861 864 else if (lflg || fflg) {
862 865 (void) printf(" C");
863 866 if (lflg)
864 867 (void) printf(" PRI NI");
865 868 }
866 869 if (lflg) {
867 870 if (yflg)
868 871 (void) printf(" RSS SZ WCHAN");
869 872 else
870 873 (void) printf(" ADDR SZ WCHAN");
871 874 }
872 875 if (fflg)
873 876 (void) printf(" %s", loc_stime_str);
874 877 if (Hflg)
875 878 (void) printf(" LGRP");
876 879 if (Lflg)
877 880 (void) printf(" TTY LTIME CMD\n");
878 881 else
879 882 (void) printf(" TTY TIME CMD\n");
880 883 }
881 884
882 885
883 886 if (pflg && !(aflg|Aflg|dflg|Gflg|Uflg|uflg|hflg|tflg|gflg|sflg|zflg) &&
884 887 npid <= PTHRESHOLD) {
885 888 /*
886 889 * If we are looking at specific processes go straight
887 890 * to their /proc entries and don't scan /proc.
888 891 */
889 892 int i;
890 893
891 894 (void) qsort(pid, npid, sizeof (pid_t), pidcmp);
892 895 for (i = 0; i < npid; i++) {
893 896 char pname[12];
894 897
895 898 if (i >= 1 && pid[i] == pid[i - 1])
896 899 continue;
897 900 (void) sprintf(pname, "%d", (int)pid[i]);
898 901 if (print_proc(pname) == 0)
899 902 retcode = 0;
900 903 }
901 904 } else {
902 905 /*
903 906 * Determine which processes to print info about by searching
904 907 * the /proc directory and looking at each process.
905 908 */
906 909 if ((dirp = opendir(procdir)) == NULL) {
907 910 (void) fprintf(stderr,
908 911 gettext("ps: cannot open PROC directory %s\n"),
909 912 procdir);
910 913 exit(1);
911 914 }
912 915
913 916 /* for each active process --- */
914 917 while ((dentp = readdir(dirp)) != NULL) {
915 918 if (dentp->d_name[0] == '.') /* skip . and .. */
916 919 continue;
917 920 if (print_proc(dentp->d_name) == 0)
918 921 retcode = 0;
919 922 }
920 923
921 924 (void) closedir(dirp);
922 925 }
923 926 return (retcode);
924 927 }
925 928
926 929
927 930 int
928 931 print_proc(char *pid_name)
929 932 {
930 933 char pname[PATH_MAX];
931 934 int pdlen;
932 935 int found;
933 936 int procfd; /* filedescriptor for /proc/nnnnn/psinfo */
934 937 char *tp; /* ptr to ttyname, if any */
935 938 psinfo_t info; /* process information from /proc */
936 939 lwpsinfo_t *lwpsinfo; /* array of lwpsinfo structs */
937 940
938 941 pdlen = snprintf(pname, sizeof (pname), "%s/%s/", procdir, pid_name);
939 942 if (pdlen >= sizeof (pname) - 10)
940 943 return (1);
941 944 retry:
942 945 (void) strcpy(&pname[pdlen], "psinfo");
943 946 if ((procfd = open(pname, O_RDONLY)) == -1) {
944 947 /* Process may have exited meanwhile. */
945 948 return (1);
946 949 }
947 950 /*
948 951 * Get the info structure for the process and close quickly.
949 952 */
950 953 if (read(procfd, (char *)&info, sizeof (info)) < 0) {
951 954 int saverr = errno;
952 955
953 956 (void) close(procfd);
954 957 if (saverr == EAGAIN)
955 958 goto retry;
956 959 if (saverr != ENOENT)
957 960 (void) fprintf(stderr,
958 961 gettext("ps: read() on %s: %s\n"),
959 962 pname, err_string(saverr));
960 963 return (1);
961 964 }
962 965 (void) close(procfd);
963 966
964 967 found = 0;
965 968 if (info.pr_lwp.pr_state == 0) /* can't happen? */
966 969 return (1);
967 970
968 971 /*
969 972 * Omit session group leaders for 'a' and 'd' options.
970 973 */
971 974 if ((info.pr_pid == info.pr_sid) && (dflg || aflg))
972 975 return (1);
973 976 if (Aflg || dflg)
974 977 found++;
975 978 else if (pflg && search(pid, npid, info.pr_pid))
976 979 found++; /* ppid in p option arg list */
977 980 else if (uflg && ugfind((id_t)info.pr_euid, &euid_tbl))
978 981 found++; /* puid in u option arg list */
979 982 else if (Uflg && ugfind((id_t)info.pr_uid, &ruid_tbl))
980 983 found++; /* puid in U option arg list */
981 984 #ifdef NOT_YET
982 985 else if (gflg && ugfind((id_t)info.pr_egid, &egid_tbl))
983 986 found++; /* pgid in g option arg list */
984 987 #endif /* NOT_YET */
985 988 else if (Gflg && ugfind((id_t)info.pr_gid, &rgid_tbl))
986 989 found++; /* pgid in G option arg list */
987 990 else if (gflg && search(grpid, ngrpid, info.pr_pgid))
988 991 found++; /* grpid in g option arg list */
989 992 else if (sflg && search(sessid, nsessid, info.pr_sid))
990 993 found++; /* sessid in s option arg list */
991 994 else if (zflg && search(zoneid, nzoneid, info.pr_zoneid))
992 995 found++; /* zoneid in z option arg list */
993 996 else if (hflg && search((pid_t *)lgrps, nlgrps, info.pr_lwp.pr_lgrp))
994 997 found++; /* home lgroup in h option arg list */
995 998 if (!found && !tflg && !aflg)
996 999 return (1);
997 1000 if (!prfind(found, &info, &tp))
998 1001 return (1);
999 1002 if (Lflg && (info.pr_nlwp + info.pr_nzomb) > 1) {
1000 1003 ssize_t prsz;
1001 1004
1002 1005 (void) strcpy(&pname[pdlen], "lpsinfo");
1003 1006 if ((procfd = open(pname, O_RDONLY)) == -1)
1004 1007 return (1);
1005 1008 /*
1006 1009 * Get the info structures for the lwps.
1007 1010 */
1008 1011 prsz = read(procfd, lpsinfobuf, lpbufsize);
1009 1012 if (prsz == -1) {
1010 1013 int saverr = errno;
1011 1014
1012 1015 (void) close(procfd);
1013 1016 if (saverr == EAGAIN)
1014 1017 goto retry;
1015 1018 if (saverr != ENOENT)
1016 1019 (void) fprintf(stderr,
1017 1020 gettext("ps: read() on %s: %s\n"),
1018 1021 pname, err_string(saverr));
1019 1022 return (1);
1020 1023 }
1021 1024 (void) close(procfd);
1022 1025 if (prsz == lpbufsize) {
1023 1026 /*
1024 1027 * buffer overflow. Realloc new buffer.
1025 1028 * Error handling is done in Realloc().
1026 1029 */
1027 1030 lpbufsize *= 2;
1028 1031 lpsinfobuf = Realloc(lpsinfobuf, lpbufsize);
1029 1032 goto retry;
1030 1033 }
1031 1034 if (lpsinfobuf->pr_nent != (info.pr_nlwp + info.pr_nzomb))
1032 1035 goto retry;
1033 1036 lwpsinfo = (lwpsinfo_t *)(lpsinfobuf + 1);
1034 1037 }
1035 1038 if (!Lflg || (info.pr_nlwp + info.pr_nzomb) <= 1) {
1036 1039 prcom(&info, tp);
1037 1040 } else {
1038 1041 int nlwp = 0;
1039 1042
1040 1043 do {
1041 1044 info.pr_lwp = *lwpsinfo;
1042 1045 prcom(&info, tp);
1043 1046 /* LINTED improper alignment */
1044 1047 lwpsinfo = (lwpsinfo_t *)((char *)lwpsinfo +
1045 1048 lpsinfobuf->pr_entsize);
1046 1049 } while (++nlwp < lpsinfobuf->pr_nent);
1047 1050 }
1048 1051 return (0);
1049 1052 }
1050 1053
1051 1054 static int
1052 1055 field_cmp(const void *l, const void *r)
1053 1056 {
1054 1057 struct def_field *lhs = *((struct def_field **)l);
1055 1058 struct def_field *rhs = *((struct def_field **)r);
1056 1059
1057 1060 return (strcmp(lhs->fname, rhs->fname));
1058 1061 }
1059 1062
1060 1063 static void
1061 1064 usage(void) /* print usage message and quit */
1062 1065 {
1063 1066 struct def_field *df, *sorted[NFIELDS];
1064 1067 int pos = 80, i = 0;
1065 1068
1066 1069 static char usage1[] =
1067 1070 "ps [ -aAdefHlcjLPWyZ ] [ -o format ] [ -t termlist ]";
1068 1071 static char usage2[] =
1069 1072 "\t[ -u userlist ] [ -U userlist ] [ -G grouplist ]";
1070 1073 static char usage3[] =
1071 1074 "\t[ -p proclist ] [ -g pgrplist ] [ -s sidlist ]";
1072 1075 static char usage4[] =
1073 1076 "\t[ -z zonelist ] [-h lgrplist]";
1074 1077 static char usage5[] =
1075 1078 " 'format' is one or more of:";
1076 1079
1077 1080 (void) fprintf(stderr,
1078 1081 gettext("usage: %s\n%s\n%s\n%s\n%s"),
1079 1082 gettext(usage1), gettext(usage2), gettext(usage3),
1080 1083 gettext(usage4), gettext(usage5));
1081 1084
1082 1085 /*
1083 1086 * Now print out the possible output formats such that they neatly fit
1084 1087 * into eighty columns. Note that the fact that we are determining
1085 1088 * this output programmatically means that a gettext() is impossible --
1086 1089 * but it would be a mistake to localize the output formats anyway as
1087 1090 * they are tokens for input, not output themselves.
1088 1091 */
1089 1092 for (df = &fname[0]; df < &fname[NFIELDS]; df++)
1090 1093 sorted[i++] = df;
1091 1094
1092 1095 (void) qsort(sorted, NFIELDS, sizeof (void *), field_cmp);
1093 1096
1094 1097 for (i = 0; i < NFIELDS; i++) {
1095 1098 if (pos + strlen((df = sorted[i])->fname) + 1 >= 80) {
1096 1099 (void) fprintf(stderr, "\n\t");
1097 1100 pos = 8;
1098 1101 }
1099 1102
1100 1103 (void) fprintf(stderr, "%s%s", pos > 8 ? " " : "", df->fname);
1101 1104 pos += strlen(df->fname) + 1;
1102 1105 }
1103 1106
1104 1107 (void) fprintf(stderr, "\n");
1105 1108
1106 1109 exit(1);
1107 1110 }
1108 1111
1109 1112 /*
1110 1113 * getarg() finds the next argument in list and copies arg into argbuf.
1111 1114 * p1 first pts to arg passed back from getopt routine. p1 is then
1112 1115 * bumped to next character that is not a comma or blank -- p1 NULL
1113 1116 * indicates end of list.
1114 1117 */
1115 1118 static char *
1116 1119 getarg(char **pp1)
1117 1120 {
1118 1121 static char argbuf[ARGSIZ];
1119 1122 char *p1 = *pp1;
1120 1123 char *parga = argbuf;
1121 1124 int c;
1122 1125
1123 1126 while ((c = *p1) != '\0' && (c == ',' || isspace(c)))
1124 1127 p1++;
1125 1128
1126 1129 while ((c = *p1) != '\0' && c != ',' && !isspace(c)) {
1127 1130 if (parga < argbuf + ARGSIZ - 1)
1128 1131 *parga++ = c;
1129 1132 p1++;
1130 1133 }
1131 1134 *parga = '\0';
1132 1135
1133 1136 while ((c = *p1) != '\0' && (c == ',' || isspace(c)))
1134 1137 p1++;
1135 1138
1136 1139 *pp1 = p1;
1137 1140
1138 1141 return (argbuf);
1139 1142 }
1140 1143
1141 1144 /*
1142 1145 * parse_format() takes the argument to the -o option,
1143 1146 * sets up the next output field structure, and returns
1144 1147 * a pointer to any further output field specifier(s).
1145 1148 * As a side-effect, it increments errflg if encounters a format error.
1146 1149 */
1147 1150 static char *
1148 1151 parse_format(char *arg)
1149 1152 {
1150 1153 int c;
1151 1154 char *name;
1152 1155 char *header = NULL;
1153 1156 int width = 0;
1154 1157 struct def_field *df;
1155 1158 struct field *f;
1156 1159
1157 1160 while ((c = *arg) != '\0' && (c == ',' || isspace(c)))
1158 1161 arg++;
1159 1162 if (c == '\0')
1160 1163 return (NULL);
1161 1164 name = arg;
1162 1165 arg = strpbrk(arg, " \t\r\v\f\n,=");
1163 1166 if (arg != NULL) {
1164 1167 c = *arg;
1165 1168 *arg++ = '\0';
1166 1169 if (c == '=') {
1167 1170 char *s;
1168 1171
1169 1172 header = arg;
1170 1173 arg = NULL;
↓ open down ↓ |
355 lines elided |
↑ open up ↑ |
1171 1174 width = strlen(header);
1172 1175 s = header + width;
1173 1176 while (s > header && isspace(*--s))
1174 1177 *s = '\0';
1175 1178 while (isspace(*header))
1176 1179 header++;
1177 1180 }
1178 1181 }
1179 1182 for (df = &fname[0]; df < &fname[NFIELDS]; df++)
1180 1183 if (strcmp(name, df->fname) == 0) {
1181 - if (strcmp(name, "lwp") == 0)
1184 + if (strcmp(name, "lwp") == 0 ||
1185 + strcmp(name, "lwpname") == 0)
1182 1186 Lflg++;
1183 1187 break;
1184 1188 }
1185 1189 if (df >= &fname[NFIELDS]) {
1186 1190 (void) fprintf(stderr,
1187 1191 gettext("ps: unknown output format: -o %s\n"),
1188 1192 name);
1189 1193 errflg++;
1190 1194 return (arg);
1191 1195 }
1192 1196 if ((f = malloc(sizeof (*f))) == NULL) {
1193 1197 (void) fprintf(stderr,
1194 1198 gettext("ps: malloc() for output format failed, %s\n"),
1195 1199 err_string(errno));
1196 1200 exit(1);
1197 1201 }
1198 1202 f->next = NULL;
1199 1203 f->fname = df - &fname[0];
1200 1204 f->header = header? header : df->header;
1201 1205 if (width == 0)
1202 1206 width = df->width;
1203 1207 if (*f->header != '\0')
1204 1208 do_header = 1;
1205 1209 f->width = max(width, df->minwidth);
1206 1210
1207 1211 if (fields == NULL)
1208 1212 fields = last_field = f;
1209 1213 else {
1210 1214 last_field->next = f;
1211 1215 last_field = f;
1212 1216 }
1213 1217
1214 1218 return (arg);
1215 1219 }
1216 1220
1217 1221 static char *
1218 1222 devlookup(dev_t ddev)
1219 1223 {
1220 1224 struct devl *dp;
1221 1225 int i;
1222 1226
1223 1227 for (dp = devl, i = 0; i < ndev; dp++, i++) {
1224 1228 if (dp->ddev == ddev)
1225 1229 return (dp->dname);
1226 1230 }
1227 1231 return (NULL);
1228 1232 }
1229 1233
1230 1234 static char *
1231 1235 devadd(char *name, dev_t ddev)
1232 1236 {
1233 1237 struct devl *dp;
1234 1238 int leng, start, i;
1235 1239
1236 1240 if (ndev == maxdev) {
1237 1241 maxdev += DNINCR;
1238 1242 devl = Realloc(devl, maxdev * sizeof (struct devl));
1239 1243 }
1240 1244 dp = &devl[ndev++];
1241 1245
1242 1246 dp->ddev = ddev;
1243 1247 if (name == NULL) {
1244 1248 (void) strcpy(dp->dname, "??");
1245 1249 return (dp->dname);
1246 1250 }
1247 1251
1248 1252 leng = strlen(name);
1249 1253 /* Strip off /dev/ */
1250 1254 if (leng < DNSIZE + 4)
1251 1255 (void) strcpy(dp->dname, &name[5]);
1252 1256 else {
1253 1257 start = leng - DNSIZE - 1;
1254 1258
1255 1259 for (i = start; i < leng && name[i] != '/'; i++)
1256 1260 ;
1257 1261 if (i == leng)
1258 1262 (void) strncpy(dp->dname, &name[start], DNSIZE);
1259 1263 else
1260 1264 (void) strncpy(dp->dname, &name[i+1], DNSIZE);
1261 1265 }
1262 1266 return (dp->dname);
1263 1267 }
1264 1268
1265 1269 /*
1266 1270 * gettty returns the user's tty number or ? if none.
1267 1271 */
1268 1272 static char *
1269 1273 gettty(psinfo_t *psinfo)
1270 1274 {
1271 1275 extern char *_ttyname_dev(dev_t, char *, size_t);
1272 1276 static zoneid_t zid = -1;
1273 1277 char devname[TTYNAME_MAX];
1274 1278 char *retval;
1275 1279
1276 1280 if (zid == -1)
1277 1281 zid = getzoneid();
1278 1282
1279 1283 if (psinfo->pr_ttydev == PRNODEV || psinfo->pr_zoneid != zid)
1280 1284 return ("?");
1281 1285
1282 1286 if ((retval = devlookup(psinfo->pr_ttydev)) != NULL)
1283 1287 return (retval);
1284 1288
1285 1289 retval = _ttyname_dev(psinfo->pr_ttydev, devname, sizeof (devname));
1286 1290
1287 1291 return (devadd(retval, psinfo->pr_ttydev));
1288 1292 }
1289 1293
1290 1294 /*
1291 1295 * Find the process's tty and return 1 if process is to be printed.
1292 1296 */
1293 1297 static int
1294 1298 prfind(int found, psinfo_t *psinfo, char **tpp)
1295 1299 {
1296 1300 char *tp;
1297 1301 struct tty *ttyp;
1298 1302
1299 1303 if (psinfo->pr_nlwp == 0) {
1300 1304 /* process is a zombie */
1301 1305 *tpp = "?";
1302 1306 if (tflg && !found)
1303 1307 return (0);
1304 1308 return (1);
1305 1309 }
1306 1310
1307 1311 /*
1308 1312 * Get current terminal. If none ("?") and 'a' is set, don't print
1309 1313 * info. If 't' is set, check if term is in list of desired terminals
1310 1314 * and print it if it is.
1311 1315 */
1312 1316 tp = gettty(psinfo);
1313 1317 if (aflg && *tp == '?') {
1314 1318 *tpp = tp;
1315 1319 return (0);
1316 1320 }
1317 1321 if (tflg && !found) {
1318 1322 int match = 0;
1319 1323 char *other = NULL;
1320 1324 for (ttyp = tty; ttyp->tname != NULL; ttyp++) {
1321 1325 /*
1322 1326 * Look for a name match
1323 1327 */
1324 1328 if (strcmp(tp, ttyp->tname) == 0) {
1325 1329 match = 1;
1326 1330 break;
1327 1331 }
1328 1332 /*
1329 1333 * Look for same device under different names.
1330 1334 */
1331 1335 if ((other == NULL) &&
1332 1336 (ttyp->tdev != PRNODEV) &&
1333 1337 (psinfo->pr_ttydev == ttyp->tdev))
1334 1338 other = ttyp->tname;
1335 1339 }
1336 1340 if (!match && (other != NULL)) {
1337 1341 /*
1338 1342 * found under a different name
1339 1343 */
1340 1344 match = 1;
1341 1345 tp = other;
1342 1346 }
1343 1347 if (!match || (tuid != (uid_t)-1 && tuid != psinfo->pr_euid)) {
1344 1348 /*
1345 1349 * not found OR not matching euid
1346 1350 */
1347 1351 *tpp = tp;
1348 1352 return (0);
1349 1353 }
1350 1354 }
1351 1355 *tpp = tp;
1352 1356 return (1);
1353 1357 }
1354 1358
1355 1359 /*
1356 1360 * Print info about the process.
1357 1361 */
1358 1362 static void
1359 1363 prcom(psinfo_t *psinfo, char *ttyp)
1360 1364 {
1361 1365 char *cp;
1362 1366 long tm;
1363 1367 int bytesleft;
1364 1368 int wcnt, length;
1365 1369 wchar_t wchar;
1366 1370 struct passwd *pwd;
1367 1371 int zombie_lwp;
1368 1372 char zonename[ZONENAME_MAX];
1369 1373
1370 1374 /*
1371 1375 * If process is zombie, call zombie print routine and return.
1372 1376 */
1373 1377 if (psinfo->pr_nlwp == 0) {
1374 1378 if (fields != NULL)
1375 1379 pr_fields(psinfo, ttyp, print_zombie_field);
1376 1380 else
1377 1381 przom(psinfo);
1378 1382 return;
1379 1383 }
1380 1384
1381 1385 zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z');
1382 1386
1383 1387 /*
1384 1388 * If user specified '-o format', print requested fields and return.
1385 1389 */
1386 1390 if (fields != NULL) {
1387 1391 pr_fields(psinfo, ttyp, print_field);
1388 1392 return;
1389 1393 }
1390 1394
1391 1395 /*
1392 1396 * All fields before 'PID' are printed with a trailing space as a
1393 1397 * separator, rather than keeping track of which column is first. All
1394 1398 * other fields are printed with a leading space.
1395 1399 */
1396 1400 if (lflg) {
1397 1401 if (!yflg)
1398 1402 (void) printf("%2x ", psinfo->pr_flag & 0377); /* F */
1399 1403 (void) printf("%c ", psinfo->pr_lwp.pr_sname); /* S */
1400 1404 }
1401 1405
1402 1406 if (Zflg) { /* ZONE */
1403 1407 if (getzonenamebyid(psinfo->pr_zoneid, zonename,
1404 1408 sizeof (zonename)) < 0) {
1405 1409 if (snprintf(NULL, 0, "%d",
1406 1410 ((int)psinfo->pr_zoneid)) > 7)
1407 1411 (void) printf(" %6.6d%c ",
1408 1412 ((int)psinfo->pr_zoneid), '*');
1409 1413 else
1410 1414 (void) printf(" %7.7d ",
1411 1415 ((int)psinfo->pr_zoneid));
1412 1416 } else {
1413 1417 size_t nw;
1414 1418
1415 1419 nw = mbstowcs(NULL, zonename, 0);
1416 1420 if (nw == (size_t)-1)
1417 1421 (void) printf("%8.8s ", "ERROR");
1418 1422 else if (nw > 8)
1419 1423 (void) wprintf(L"%7.7s%c ", zonename, '*');
1420 1424 else
1421 1425 (void) wprintf(L"%8.8s ", zonename);
1422 1426 }
1423 1427 }
1424 1428
1425 1429 if (fflg) { /* UID */
1426 1430 if ((pwd = getpwuid(psinfo->pr_euid)) != NULL) {
1427 1431 size_t nw;
1428 1432
1429 1433 nw = mbstowcs(NULL, pwd->pw_name, 0);
1430 1434 if (nw == (size_t)-1)
1431 1435 (void) printf("%8.8s ", "ERROR");
1432 1436 else if (nw > 8)
1433 1437 (void) wprintf(L"%7.7s%c ", pwd->pw_name, '*');
1434 1438 else
1435 1439 (void) wprintf(L"%8.8s ", pwd->pw_name);
1436 1440 } else {
1437 1441 if (snprintf(NULL, 0, "%u",
1438 1442 (psinfo->pr_euid)) > 7)
1439 1443 (void) printf(" %6.6u%c ", psinfo->pr_euid,
1440 1444 '*');
1441 1445 else
1442 1446 (void) printf(" %7.7u ", psinfo->pr_euid);
1443 1447 }
1444 1448 } else if (lflg) {
1445 1449 if (snprintf(NULL, 0, "%u", (psinfo->pr_euid)) > 6)
1446 1450 (void) printf("%5.5u%c ", psinfo->pr_euid, '*');
1447 1451 else
1448 1452 (void) printf("%6u ", psinfo->pr_euid);
1449 1453 }
1450 1454 (void) printf("%*d", pidwidth, (int)psinfo->pr_pid); /* PID */
1451 1455 if (lflg || fflg)
1452 1456 (void) printf(" %*d", pidwidth,
1453 1457 (int)psinfo->pr_ppid); /* PPID */
1454 1458 if (jflg) {
1455 1459 (void) printf(" %*d", pidwidth,
1456 1460 (int)psinfo->pr_pgid); /* PGID */
1457 1461 (void) printf(" %*d", pidwidth,
1458 1462 (int)psinfo->pr_sid); /* SID */
1459 1463 }
1460 1464 if (Lflg)
1461 1465 (void) printf(" %5d", (int)psinfo->pr_lwp.pr_lwpid); /* LWP */
1462 1466 if (Pflg) {
1463 1467 if (psinfo->pr_lwp.pr_bindpro == PBIND_NONE) /* PSR */
1464 1468 (void) printf(" -");
1465 1469 else
1466 1470 (void) printf(" %3d", psinfo->pr_lwp.pr_bindpro);
1467 1471 }
1468 1472 if (Lflg && fflg) /* NLWP */
1469 1473 (void) printf(" %5d", psinfo->pr_nlwp + psinfo->pr_nzomb);
1470 1474 if (cflg) {
1471 1475 if (zombie_lwp) /* CLS */
1472 1476 (void) printf(" ");
1473 1477 else
1474 1478 (void) printf(" %4s", psinfo->pr_lwp.pr_clname);
1475 1479 (void) printf(" %3d", psinfo->pr_lwp.pr_pri); /* PRI */
1476 1480 } else if (lflg || fflg) {
1477 1481 (void) printf(" %3d", psinfo->pr_lwp.pr_cpu & 0377); /* C */
1478 1482 if (lflg) { /* PRI NI */
1479 1483 /*
1480 1484 * Print priorities the old way (lower numbers
1481 1485 * mean higher priority) and print nice value
1482 1486 * for time sharing procs.
1483 1487 */
1484 1488 (void) printf(" %3d", psinfo->pr_lwp.pr_oldpri);
1485 1489 if (psinfo->pr_lwp.pr_oldpri != 0)
1486 1490 (void) printf(" %2d", psinfo->pr_lwp.pr_nice);
1487 1491 else
1488 1492 (void) printf(" %2.2s",
1489 1493 psinfo->pr_lwp.pr_clname);
1490 1494 }
1491 1495 }
1492 1496 if (lflg) {
1493 1497 if (yflg) {
1494 1498 if (psinfo->pr_flag & SSYS) /* RSS */
1495 1499 (void) printf(" 0");
1496 1500 else if (psinfo->pr_rssize)
1497 1501 (void) printf(" %5lu",
1498 1502 (ulong_t)psinfo->pr_rssize);
1499 1503 else
1500 1504 (void) printf(" ?");
1501 1505 if (psinfo->pr_flag & SSYS) /* SZ */
1502 1506 (void) printf(" 0");
1503 1507 else if (psinfo->pr_size)
1504 1508 (void) printf(" %6lu",
1505 1509 (ulong_t)psinfo->pr_size);
1506 1510 else
1507 1511 (void) printf(" ?");
1508 1512 } else {
1509 1513 #ifndef _LP64
1510 1514 if (psinfo->pr_addr) /* ADDR */
1511 1515 (void) printf(" %8lx",
1512 1516 (ulong_t)psinfo->pr_addr);
1513 1517 else
1514 1518 #endif
1515 1519 (void) printf(" ?");
1516 1520 if (psinfo->pr_flag & SSYS) /* SZ */
1517 1521 (void) printf(" 0");
1518 1522 else if (psinfo->pr_size)
1519 1523 (void) printf(" %6lu",
1520 1524 (ulong_t)psinfo->pr_size / kbytes_per_page);
1521 1525 else
1522 1526 (void) printf(" ?");
1523 1527 }
1524 1528 if (psinfo->pr_lwp.pr_sname != 'S') /* WCHAN */
1525 1529 (void) printf(" ");
1526 1530 #ifndef _LP64
1527 1531 else if (psinfo->pr_lwp.pr_wchan)
1528 1532 (void) printf(" %8lx",
1529 1533 (ulong_t)psinfo->pr_lwp.pr_wchan);
1530 1534 #endif
1531 1535 else
1532 1536 (void) printf(" ?");
1533 1537 }
1534 1538 if (fflg) { /* STIME */
1535 1539 int width = fname[F_STIME].width;
1536 1540 if (Lflg)
1537 1541 prtime(psinfo->pr_lwp.pr_start, width + 1, 1);
1538 1542 else
1539 1543 prtime(psinfo->pr_start, width + 1, 1);
1540 1544 }
1541 1545
1542 1546 if (Hflg) {
1543 1547 /* Display home lgroup */
1544 1548 (void) printf(" %4d", (int)psinfo->pr_lwp.pr_lgrp);
1545 1549 }
1546 1550
1547 1551 (void) printf(" %-8.14s", ttyp); /* TTY */
1548 1552 if (Lflg) {
1549 1553 tm = psinfo->pr_lwp.pr_time.tv_sec;
1550 1554 if (psinfo->pr_lwp.pr_time.tv_nsec > 500000000)
1551 1555 tm++;
1552 1556 } else {
1553 1557 tm = psinfo->pr_time.tv_sec;
1554 1558 if (psinfo->pr_time.tv_nsec > 500000000)
1555 1559 tm++;
1556 1560 }
1557 1561 (void) printf(" %4ld:%.2ld", tm / 60, tm % 60); /* [L]TIME */
1558 1562
1559 1563 if (zombie_lwp) {
1560 1564 (void) printf(" <defunct>\n");
1561 1565 return;
1562 1566 }
1563 1567
1564 1568 if (!fflg) { /* CMD */
1565 1569 wcnt = namencnt(psinfo->pr_fname, 16, 8);
1566 1570 (void) printf(" %.*s\n", wcnt, psinfo->pr_fname);
1567 1571 return;
1568 1572 }
1569 1573
1570 1574
1571 1575 /*
1572 1576 * PRARGSZ == length of cmd arg string.
1573 1577 */
1574 1578 psinfo->pr_psargs[PRARGSZ-1] = '\0';
1575 1579 bytesleft = PRARGSZ;
1576 1580 for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) {
1577 1581 length = mbtowc(&wchar, cp, MB_LEN_MAX);
1578 1582 if (length == 0)
1579 1583 break;
1580 1584 if (length < 0 || !iswprint(wchar)) {
1581 1585 if (length < 0)
1582 1586 length = 1;
1583 1587 if (bytesleft <= length) {
1584 1588 *cp = '\0';
1585 1589 break;
1586 1590 }
1587 1591 /* omit the unprintable character */
1588 1592 (void) memmove(cp, cp+length, bytesleft-length);
1589 1593 length = 0;
1590 1594 }
1591 1595 bytesleft -= length;
1592 1596 }
1593 1597 wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, lflg ? 35 : PRARGSZ);
1594 1598 (void) printf(" %.*s\n", wcnt, psinfo->pr_psargs);
1595 1599 }
1596 1600
1597 1601 /*
1598 1602 * Print percent from 16-bit binary fraction [0 .. 1]
1599 1603 * Round up .01 to .1 to indicate some small percentage (the 0x7000 below).
1600 1604 */
1601 1605 static void
1602 1606 prtpct(ushort_t pct, int width)
1603 1607 {
1604 1608 uint_t value = pct; /* need 32 bits to compute with */
1605 1609
1606 1610 value = ((value * 1000) + 0x7000) >> 15; /* [0 .. 1000] */
1607 1611 if (value >= 1000)
1608 1612 value = 999;
1609 1613 if ((width -= 2) < 2)
1610 1614 width = 2;
1611 1615 (void) printf("%*u.%u", width, value / 10, value % 10);
1612 1616 }
1613 1617
1614 1618 static void
1615 1619 print_time(time_t tim, int width)
1616 1620 {
1617 1621 char buf[30];
1618 1622 time_t seconds;
1619 1623 time_t minutes;
1620 1624 time_t hours;
1621 1625 time_t days;
1622 1626
1623 1627 if (tim < 0) {
1624 1628 (void) printf("%*s", width, "-");
1625 1629 return;
1626 1630 }
1627 1631
1628 1632 seconds = tim % 60;
1629 1633 tim /= 60;
1630 1634 minutes = tim % 60;
1631 1635 tim /= 60;
1632 1636 hours = tim % 24;
1633 1637 days = tim / 24;
1634 1638
1635 1639 if (days > 0) {
1636 1640 (void) snprintf(buf, sizeof (buf), "%ld-%2.2ld:%2.2ld:%2.2ld",
1637 1641 days, hours, minutes, seconds);
1638 1642 } else if (hours > 0) {
1639 1643 (void) snprintf(buf, sizeof (buf), "%2.2ld:%2.2ld:%2.2ld",
1640 1644 hours, minutes, seconds);
1641 1645 } else {
1642 1646 (void) snprintf(buf, sizeof (buf), "%2.2ld:%2.2ld",
1643 1647 minutes, seconds);
1644 1648 }
1645 1649
1646 1650 (void) printf("%*s", width, buf);
1647 1651 }
1648 1652
1649 1653 static void
1650 1654 print_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
1651 1655 {
1652 1656 int width = f->width;
1653 1657 struct passwd *pwd;
1654 1658 struct group *grp;
1655 1659 time_t cputime;
1656 1660 int bytesleft;
1657 1661 int wcnt;
1658 1662 wchar_t wchar;
1659 1663 char *cp;
1660 1664 int length;
1661 1665 ulong_t mask;
1662 1666 char c = '\0', *csave = NULL;
1663 1667 int zombie_lwp;
1664 1668
1665 1669 zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z');
1666 1670
1667 1671 switch (f->fname) {
1668 1672 case F_RUSER:
1669 1673 if ((pwd = getpwuid(psinfo->pr_uid)) != NULL) {
1670 1674 size_t nw;
1671 1675
1672 1676 nw = mbstowcs(NULL, pwd->pw_name, 0);
1673 1677 if (nw == (size_t)-1)
1674 1678 (void) printf("%*s ", width, "ERROR");
1675 1679 else if (Wflg && nw > width)
1676 1680 (void) wprintf(L"%.*s%c", width - 1,
1677 1681 pwd->pw_name, '*');
1678 1682 else
1679 1683 (void) wprintf(L"%*s", width, pwd->pw_name);
1680 1684 } else {
1681 1685 if (Wflg && snprintf(NULL, 0, "%u",
1682 1686 (psinfo->pr_uid)) > width)
1683 1687
1684 1688 (void) printf("%*u%c", width - 1,
1685 1689 psinfo->pr_uid, '*');
1686 1690 else
1687 1691 (void) printf("%*u", width, psinfo->pr_uid);
1688 1692 }
1689 1693 break;
1690 1694 case F_USER:
1691 1695 if ((pwd = getpwuid(psinfo->pr_euid)) != NULL) {
1692 1696 size_t nw;
1693 1697
1694 1698 nw = mbstowcs(NULL, pwd->pw_name, 0);
1695 1699 if (nw == (size_t)-1)
1696 1700 (void) printf("%*s ", width, "ERROR");
1697 1701 else if (Wflg && nw > width)
1698 1702 (void) wprintf(L"%.*s%c", width - 1,
1699 1703 pwd->pw_name, '*');
1700 1704 else
1701 1705 (void) wprintf(L"%*s", width, pwd->pw_name);
1702 1706 } else {
1703 1707 if (Wflg && snprintf(NULL, 0, "%u",
1704 1708 (psinfo->pr_euid)) > width)
1705 1709
1706 1710 (void) printf("%*u%c", width - 1,
1707 1711 psinfo->pr_euid, '*');
1708 1712 else
1709 1713 (void) printf("%*u", width, psinfo->pr_euid);
1710 1714 }
1711 1715 break;
1712 1716 case F_RGROUP:
1713 1717 if ((grp = getgrgid(psinfo->pr_gid)) != NULL)
1714 1718 (void) printf("%*s", width, grp->gr_name);
1715 1719 else
1716 1720 (void) printf("%*u", width, psinfo->pr_gid);
1717 1721 break;
1718 1722 case F_GROUP:
1719 1723 if ((grp = getgrgid(psinfo->pr_egid)) != NULL)
1720 1724 (void) printf("%*s", width, grp->gr_name);
1721 1725 else
1722 1726 (void) printf("%*u", width, psinfo->pr_egid);
1723 1727 break;
1724 1728 case F_RUID:
1725 1729 (void) printf("%*u", width, psinfo->pr_uid);
1726 1730 break;
1727 1731 case F_UID:
1728 1732 (void) printf("%*u", width, psinfo->pr_euid);
1729 1733 break;
1730 1734 case F_RGID:
1731 1735 (void) printf("%*u", width, psinfo->pr_gid);
1732 1736 break;
1733 1737 case F_GID:
1734 1738 (void) printf("%*u", width, psinfo->pr_egid);
1735 1739 break;
1736 1740 case F_PID:
1737 1741 (void) printf("%*d", width, (int)psinfo->pr_pid);
1738 1742 break;
1739 1743 case F_PPID:
1740 1744 (void) printf("%*d", width, (int)psinfo->pr_ppid);
1741 1745 break;
1742 1746 case F_PGID:
1743 1747 (void) printf("%*d", width, (int)psinfo->pr_pgid);
1744 1748 break;
1745 1749 case F_SID:
1746 1750 (void) printf("%*d", width, (int)psinfo->pr_sid);
↓ open down ↓ |
555 lines elided |
↑ open up ↑ |
1747 1751 break;
1748 1752 case F_PSR:
1749 1753 if (zombie_lwp || psinfo->pr_lwp.pr_bindpro == PBIND_NONE)
1750 1754 (void) printf("%*s", width, "-");
1751 1755 else
1752 1756 (void) printf("%*d", width, psinfo->pr_lwp.pr_bindpro);
1753 1757 break;
1754 1758 case F_LWP:
1755 1759 (void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid);
1756 1760 break;
1761 + case F_LWPNAME: {
1762 + char lwpname[THREAD_NAME_MAX] = "";
1763 + char *path = NULL;
1764 + int fd;
1765 +
1766 + if (asprintf(&path, "%s/%d/lwp/%d/lwpname", procdir,
1767 + (int)psinfo->pr_pid, (int)psinfo->pr_lwp.pr_lwpid) != -1 &&
1768 + (fd = open(path, O_RDONLY)) != -1) {
1769 + (void) read(fd, lwpname, sizeof (lwpname));
1770 + lwpname[THREAD_NAME_MAX - 1] = '\0';
1771 + (void) close(fd);
1772 + }
1773 +
1774 + free(path);
1775 +
1776 + if (f->next != NULL)
1777 + (void) printf("%-*s", width, lwpname);
1778 + else
1779 + (void) printf("%s", lwpname);
1780 + break;
1781 + }
1757 1782 case F_NLWP:
1758 1783 (void) printf("%*d", width, psinfo->pr_nlwp + psinfo->pr_nzomb);
1759 1784 break;
1760 1785 case F_OPRI:
1761 1786 if (zombie_lwp)
1762 1787 (void) printf("%*s", width, "-");
1763 1788 else
1764 1789 (void) printf("%*d", width, psinfo->pr_lwp.pr_oldpri);
1765 1790 break;
1766 1791 case F_PRI:
1767 1792 if (zombie_lwp)
1768 1793 (void) printf("%*s", width, "-");
1769 1794 else
1770 1795 (void) printf("%*d", width, psinfo->pr_lwp.pr_pri);
1771 1796 break;
1772 1797 case F_F:
1773 1798 mask = 0xffffffffUL;
1774 1799 if (width < 8)
1775 1800 mask >>= (8 - width) * 4;
1776 1801 (void) printf("%*lx", width, psinfo->pr_flag & mask);
1777 1802 break;
1778 1803 case F_S:
1779 1804 (void) printf("%*c", width, psinfo->pr_lwp.pr_sname);
1780 1805 break;
1781 1806 case F_C:
1782 1807 if (zombie_lwp)
1783 1808 (void) printf("%*s", width, "-");
1784 1809 else
1785 1810 (void) printf("%*d", width, psinfo->pr_lwp.pr_cpu);
1786 1811 break;
1787 1812 case F_PCPU:
1788 1813 if (zombie_lwp)
1789 1814 (void) printf("%*s", width, "-");
1790 1815 else if (Lflg)
1791 1816 prtpct(psinfo->pr_lwp.pr_pctcpu, width);
1792 1817 else
1793 1818 prtpct(psinfo->pr_pctcpu, width);
1794 1819 break;
1795 1820 case F_PMEM:
1796 1821 prtpct(psinfo->pr_pctmem, width);
1797 1822 break;
1798 1823 case F_OSZ:
1799 1824 (void) printf("%*lu", width,
1800 1825 (ulong_t)psinfo->pr_size / kbytes_per_page);
1801 1826 break;
1802 1827 case F_VSZ:
1803 1828 (void) printf("%*lu", width, (ulong_t)psinfo->pr_size);
1804 1829 break;
1805 1830 case F_RSS:
1806 1831 (void) printf("%*lu", width, (ulong_t)psinfo->pr_rssize);
1807 1832 break;
1808 1833 case F_NICE:
1809 1834 /* if pr_oldpri is zero, then this class has no nice */
1810 1835 if (zombie_lwp)
1811 1836 (void) printf("%*s", width, "-");
1812 1837 else if (psinfo->pr_lwp.pr_oldpri != 0)
1813 1838 (void) printf("%*d", width, psinfo->pr_lwp.pr_nice);
1814 1839 else
1815 1840 (void) printf("%*.*s", width, width,
1816 1841 psinfo->pr_lwp.pr_clname);
1817 1842 break;
1818 1843 case F_CLASS:
1819 1844 if (zombie_lwp)
1820 1845 (void) printf("%*s", width, "-");
1821 1846 else
1822 1847 (void) printf("%*.*s", width, width,
1823 1848 psinfo->pr_lwp.pr_clname);
1824 1849 break;
1825 1850 case F_STIME:
1826 1851 if (Lflg)
1827 1852 prtime(psinfo->pr_lwp.pr_start, width, 0);
1828 1853 else
1829 1854 prtime(psinfo->pr_start, width, 0);
1830 1855 break;
1831 1856 case F_ETIME:
1832 1857 if (Lflg)
1833 1858 print_time(delta_secs(&psinfo->pr_lwp.pr_start),
1834 1859 width);
1835 1860 else
1836 1861 print_time(delta_secs(&psinfo->pr_start), width);
1837 1862 break;
1838 1863 case F_TIME:
1839 1864 if (Lflg) {
1840 1865 cputime = psinfo->pr_lwp.pr_time.tv_sec;
1841 1866 if (psinfo->pr_lwp.pr_time.tv_nsec > 500000000)
1842 1867 cputime++;
1843 1868 } else {
1844 1869 cputime = psinfo->pr_time.tv_sec;
1845 1870 if (psinfo->pr_time.tv_nsec > 500000000)
1846 1871 cputime++;
1847 1872 }
1848 1873 print_time(cputime, width);
1849 1874 break;
1850 1875 case F_TTY:
1851 1876 (void) printf("%-*s", width, ttyp);
1852 1877 break;
1853 1878 case F_ADDR:
1854 1879 if (zombie_lwp)
1855 1880 (void) printf("%*s", width, "-");
1856 1881 else if (Lflg)
1857 1882 (void) printf("%*lx", width,
1858 1883 (long)psinfo->pr_lwp.pr_addr);
1859 1884 else
1860 1885 (void) printf("%*lx", width, (long)psinfo->pr_addr);
1861 1886 break;
1862 1887 case F_WCHAN:
1863 1888 if (!zombie_lwp && psinfo->pr_lwp.pr_wchan)
1864 1889 (void) printf("%*lx", width,
1865 1890 (long)psinfo->pr_lwp.pr_wchan);
1866 1891 else
1867 1892 (void) printf("%*.*s", width, width, "-");
1868 1893 break;
1869 1894 case F_FNAME:
1870 1895 /*
1871 1896 * Print full width unless this is the last output format.
1872 1897 */
1873 1898 if (zombie_lwp) {
1874 1899 if (f->next != NULL)
1875 1900 (void) printf("%-*s", width, "<defunct>");
1876 1901 else
1877 1902 (void) printf("%s", "<defunct>");
1878 1903 break;
1879 1904 }
1880 1905 wcnt = namencnt(psinfo->pr_fname, 16, width);
1881 1906 if (f->next != NULL)
1882 1907 (void) printf("%-*.*s", width, wcnt, psinfo->pr_fname);
1883 1908 else
1884 1909 (void) printf("%-.*s", wcnt, psinfo->pr_fname);
1885 1910 break;
1886 1911 case F_COMM:
1887 1912 if (zombie_lwp) {
1888 1913 if (f->next != NULL)
1889 1914 (void) printf("%-*s", width, "<defunct>");
1890 1915 else
1891 1916 (void) printf("%s", "<defunct>");
1892 1917 break;
1893 1918 }
1894 1919 csave = strpbrk(psinfo->pr_psargs, " \t\r\v\f\n");
1895 1920 if (csave) {
1896 1921 c = *csave;
1897 1922 *csave = '\0';
1898 1923 }
1899 1924 /* FALLTHROUGH */
1900 1925 case F_ARGS:
1901 1926 /*
1902 1927 * PRARGSZ == length of cmd arg string.
1903 1928 */
1904 1929 if (zombie_lwp) {
1905 1930 (void) printf("%-*s", width, "<defunct>");
1906 1931 break;
1907 1932 }
1908 1933 psinfo->pr_psargs[PRARGSZ-1] = '\0';
1909 1934 bytesleft = PRARGSZ;
1910 1935 for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) {
1911 1936 length = mbtowc(&wchar, cp, MB_LEN_MAX);
1912 1937 if (length == 0)
1913 1938 break;
1914 1939 if (length < 0 || !iswprint(wchar)) {
1915 1940 if (length < 0)
1916 1941 length = 1;
1917 1942 if (bytesleft <= length) {
1918 1943 *cp = '\0';
1919 1944 break;
1920 1945 }
1921 1946 /* omit the unprintable character */
1922 1947 (void) memmove(cp, cp+length, bytesleft-length);
1923 1948 length = 0;
1924 1949 }
1925 1950 bytesleft -= length;
1926 1951 }
1927 1952 wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, width);
1928 1953 /*
1929 1954 * Print full width unless this is the last format.
1930 1955 */
1931 1956 if (f->next != NULL)
1932 1957 (void) printf("%-*.*s", width, wcnt,
1933 1958 psinfo->pr_psargs);
1934 1959 else
1935 1960 (void) printf("%-.*s", wcnt,
1936 1961 psinfo->pr_psargs);
1937 1962 if (f->fname == F_COMM && csave)
1938 1963 *csave = c;
1939 1964 break;
1940 1965 case F_TASKID:
1941 1966 (void) printf("%*d", width, (int)psinfo->pr_taskid);
1942 1967 break;
1943 1968 case F_PROJID:
1944 1969 (void) printf("%*d", width, (int)psinfo->pr_projid);
1945 1970 break;
1946 1971 case F_PROJECT:
1947 1972 {
1948 1973 struct project cproj;
1949 1974 char proj_buf[PROJECT_BUFSZ];
1950 1975
1951 1976 if ((getprojbyid(psinfo->pr_projid, &cproj,
1952 1977 (void *)&proj_buf, PROJECT_BUFSZ)) == NULL) {
1953 1978 if (Wflg && snprintf(NULL, 0, "%d",
1954 1979 ((int)psinfo->pr_projid)) > width)
1955 1980 (void) printf("%.*d%c", width - 1,
1956 1981 ((int)psinfo->pr_projid), '*');
1957 1982 else
1958 1983 (void) printf("%*d", width,
1959 1984 (int)psinfo->pr_projid);
1960 1985 } else {
1961 1986 size_t nw;
1962 1987
1963 1988 if (cproj.pj_name != NULL)
1964 1989 nw = mbstowcs(NULL, cproj.pj_name, 0);
1965 1990 if (cproj.pj_name == NULL)
1966 1991 (void) printf("%*s ", width, "---");
1967 1992 else if (nw == (size_t)-1)
1968 1993 (void) printf("%*s ", width, "ERROR");
1969 1994 else if (Wflg && nw > width)
1970 1995 (void) wprintf(L"%.*s%c", width - 1,
1971 1996 cproj.pj_name, '*');
1972 1997 else
1973 1998 (void) wprintf(L"%*s", width,
1974 1999 cproj.pj_name);
1975 2000 }
1976 2001 }
1977 2002 break;
1978 2003 case F_PSET:
1979 2004 if (zombie_lwp || psinfo->pr_lwp.pr_bindpset == PS_NONE)
1980 2005 (void) printf("%*s", width, "-");
1981 2006 else
1982 2007 (void) printf("%*d", width, psinfo->pr_lwp.pr_bindpset);
1983 2008 break;
1984 2009 case F_ZONEID:
1985 2010 (void) printf("%*d", width, (int)psinfo->pr_zoneid);
1986 2011 break;
1987 2012 case F_ZONE:
1988 2013 {
1989 2014 char zonename[ZONENAME_MAX];
1990 2015
1991 2016 if (getzonenamebyid(psinfo->pr_zoneid, zonename,
1992 2017 sizeof (zonename)) < 0) {
1993 2018 if (Wflg && snprintf(NULL, 0, "%d",
1994 2019 ((int)psinfo->pr_zoneid)) > width)
1995 2020 (void) printf("%.*d%c", width - 1,
1996 2021 ((int)psinfo->pr_zoneid), '*');
1997 2022 else
1998 2023 (void) printf("%*d", width,
1999 2024 (int)psinfo->pr_zoneid);
2000 2025 } else {
2001 2026 size_t nw;
2002 2027
2003 2028 nw = mbstowcs(NULL, zonename, 0);
2004 2029 if (nw == (size_t)-1)
2005 2030 (void) printf("%*s ", width, "ERROR");
2006 2031 else if (Wflg && nw > width)
2007 2032 (void) wprintf(L"%.*s%c", width - 1,
2008 2033 zonename, '*');
2009 2034 else
2010 2035 (void) wprintf(L"%*s", width, zonename);
2011 2036 }
2012 2037 }
2013 2038 break;
2014 2039 case F_CTID:
2015 2040 if (psinfo->pr_contract == -1)
2016 2041 (void) printf("%*s", width, "-");
2017 2042 else
2018 2043 (void) printf("%*ld", width, (long)psinfo->pr_contract);
2019 2044 break;
2020 2045 case F_LGRP:
2021 2046 /* Display home lgroup */
2022 2047 (void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lgrp);
2023 2048 break;
2024 2049
2025 2050 case F_DMODEL:
2026 2051 (void) printf("%*s", width,
2027 2052 psinfo->pr_dmodel == PR_MODEL_LP64 ? "_LP64" : "_ILP32");
2028 2053 break;
2029 2054 }
2030 2055 }
2031 2056
2032 2057 static void
2033 2058 print_zombie_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
2034 2059 {
2035 2060 int wcnt;
2036 2061 int width = f->width;
2037 2062
2038 2063 switch (f->fname) {
2039 2064 case F_FNAME:
2040 2065 case F_COMM:
2041 2066 case F_ARGS:
2042 2067 /*
2043 2068 * Print full width unless this is the last output format.
2044 2069 */
2045 2070 wcnt = min(width, sizeof ("<defunct>"));
2046 2071 if (f->next != NULL)
2047 2072 (void) printf("%-*.*s", width, wcnt, "<defunct>");
2048 2073 else
2049 2074 (void) printf("%-.*s", wcnt, "<defunct>");
2050 2075 break;
2051 2076
2052 2077 case F_PSR:
2053 2078 case F_PCPU:
2054 2079 case F_PMEM:
2055 2080 case F_NICE:
2056 2081 case F_CLASS:
2057 2082 case F_STIME:
2058 2083 case F_ETIME:
2059 2084 case F_WCHAN:
2060 2085 case F_PSET:
2061 2086 (void) printf("%*s", width, "-");
2062 2087 break;
2063 2088
2064 2089 case F_OPRI:
2065 2090 case F_PRI:
2066 2091 case F_OSZ:
2067 2092 case F_VSZ:
2068 2093 case F_RSS:
2069 2094 (void) printf("%*d", width, 0);
↓ open down ↓ |
303 lines elided |
↑ open up ↑ |
2070 2095 break;
2071 2096
2072 2097 default:
2073 2098 print_field(psinfo, f, ttyp);
2074 2099 break;
2075 2100 }
2076 2101 }
2077 2102
2078 2103 static void
2079 2104 pr_fields(psinfo_t *psinfo, const char *ttyp,
2080 - void (*print_fld)(psinfo_t *, struct field *, const char *))
2105 + void (*print_fld)(psinfo_t *, struct field *, const char *))
2081 2106 {
2082 2107 struct field *f;
2083 2108
2084 2109 for (f = fields; f != NULL; f = f->next) {
2085 2110 print_fld(psinfo, f, ttyp);
2086 2111 if (f->next != NULL)
2087 2112 (void) printf(" ");
2088 2113 }
2089 2114 (void) printf("\n");
2090 2115 }
2091 2116
2092 2117 /*
2093 2118 * Returns 1 if arg is found in array arr, of length num; 0 otherwise.
2094 2119 */
2095 2120 static int
2096 2121 search(pid_t *arr, int number, pid_t arg)
2097 2122 {
2098 2123 int i;
2099 2124
2100 2125 for (i = 0; i < number; i++)
2101 2126 if (arg == arr[i])
2102 2127 return (1);
2103 2128 return (0);
2104 2129 }
2105 2130
2106 2131 /*
2107 2132 * Add an entry (user, group) to the specified table.
2108 2133 */
2109 2134 static void
2110 2135 add_ugentry(struct ughead *tbl, char *name)
2111 2136 {
2112 2137 struct ugdata *entp;
2113 2138
2114 2139 if (tbl->size == tbl->nent) { /* reallocate the table entries */
2115 2140 if ((tbl->size *= 2) == 0)
2116 2141 tbl->size = 32; /* first time */
2117 2142 tbl->ent = Realloc(tbl->ent, tbl->size*sizeof (struct ugdata));
2118 2143 }
2119 2144 entp = &tbl->ent[tbl->nent++];
2120 2145 entp->id = 0;
2121 2146 (void) strncpy(entp->name, name, MAXUGNAME);
2122 2147 entp->name[MAXUGNAME] = '\0';
2123 2148 }
2124 2149
2125 2150 static int
2126 2151 uconv(struct ughead *uhead)
2127 2152 {
2128 2153 struct ugdata *utbl = uhead->ent;
2129 2154 int n = uhead->nent;
2130 2155 struct passwd *pwd;
2131 2156 int i;
2132 2157 int fnd = 0;
2133 2158 uid_t uid;
2134 2159
2135 2160 /*
2136 2161 * Ask the name service for names.
2137 2162 */
2138 2163 for (i = 0; i < n; i++) {
2139 2164 /*
2140 2165 * If name is numeric, ask for numeric id
2141 2166 */
2142 2167 if (str2uid(utbl[i].name, &uid, 0, MAXEPHUID) == 0)
2143 2168 pwd = getpwuid(uid);
2144 2169 else
2145 2170 pwd = getpwnam(utbl[i].name);
2146 2171
2147 2172 /*
2148 2173 * If found, enter found index into tbl array.
2149 2174 */
2150 2175 if (pwd == NULL) {
2151 2176 (void) fprintf(stderr,
2152 2177 gettext("ps: unknown user %s\n"), utbl[i].name);
2153 2178 continue;
2154 2179 }
2155 2180
2156 2181 utbl[fnd].id = pwd->pw_uid;
2157 2182 (void) strncpy(utbl[fnd].name, pwd->pw_name, MAXUGNAME);
2158 2183 fnd++;
2159 2184 }
2160 2185
2161 2186 uhead->nent = fnd; /* in case it changed */
2162 2187 return (n - fnd);
2163 2188 }
2164 2189
2165 2190 static int
2166 2191 gconv(struct ughead *ghead)
2167 2192 {
2168 2193 struct ugdata *gtbl = ghead->ent;
2169 2194 int n = ghead->nent;
2170 2195 struct group *grp;
2171 2196 gid_t gid;
2172 2197 int i;
2173 2198 int fnd = 0;
2174 2199
2175 2200 /*
2176 2201 * Ask the name service for names.
2177 2202 */
2178 2203 for (i = 0; i < n; i++) {
2179 2204 /*
2180 2205 * If name is numeric, ask for numeric id
2181 2206 */
2182 2207 if (str2uid(gtbl[i].name, (uid_t *)&gid, 0, MAXEPHUID) == 0)
2183 2208 grp = getgrgid(gid);
2184 2209 else
2185 2210 grp = getgrnam(gtbl[i].name);
2186 2211 /*
2187 2212 * If found, enter found index into tbl array.
2188 2213 */
2189 2214 if (grp == NULL) {
2190 2215 (void) fprintf(stderr,
2191 2216 gettext("ps: unknown group %s\n"), gtbl[i].name);
2192 2217 continue;
2193 2218 }
2194 2219
2195 2220 gtbl[fnd].id = grp->gr_gid;
2196 2221 (void) strncpy(gtbl[fnd].name, grp->gr_name, MAXUGNAME);
2197 2222 fnd++;
2198 2223 }
2199 2224
2200 2225 ghead->nent = fnd; /* in case it changed */
2201 2226 return (n - fnd);
2202 2227 }
2203 2228
2204 2229 /*
2205 2230 * Return 1 if puid is in table, otherwise 0.
2206 2231 */
2207 2232 static int
2208 2233 ugfind(id_t id, struct ughead *ughead)
2209 2234 {
2210 2235 struct ugdata *utbl = ughead->ent;
2211 2236 int n = ughead->nent;
2212 2237 int i;
2213 2238
2214 2239 for (i = 0; i < n; i++)
2215 2240 if (utbl[i].id == id)
2216 2241 return (1);
2217 2242 return (0);
2218 2243 }
2219 2244
2220 2245 /*
2221 2246 * Print starting time of process unless process started more than 24 hours
2222 2247 * ago, in which case the date is printed. The date is printed in the form
2223 2248 * "MMM dd" if old format, else the blank is replaced with an '_' so
2224 2249 * it appears as a single word (for parseability).
2225 2250 */
2226 2251 static void
2227 2252 prtime(timestruc_t st, int width, int old)
2228 2253 {
2229 2254 char sttim[26];
2230 2255 time_t starttime;
2231 2256
2232 2257 starttime = st.tv_sec;
2233 2258 if (st.tv_nsec > 500000000)
2234 2259 starttime++;
2235 2260 if ((now.tv_sec - starttime) >= 24*60*60) {
2236 2261 (void) strftime(sttim, sizeof (sttim), old?
2237 2262 /*
2238 2263 * TRANSLATION_NOTE
2239 2264 * This time format is used by STIME field when -f option
2240 2265 * is specified. Used for processes that begun more than
2241 2266 * 24 hours.
2242 2267 */
2243 2268 dcgettext(NULL, "%b %d", LC_TIME) :
2244 2269 /*
2245 2270 * TRANSLATION_NOTE
2246 2271 * This time format is used by STIME field when -o option
2247 2272 * is specified. Used for processes that begun more than
2248 2273 * 24 hours.
2249 2274 */
2250 2275 dcgettext(NULL, "%b_%d", LC_TIME), localtime(&starttime));
2251 2276 } else {
2252 2277 /*
2253 2278 * TRANSLATION_NOTE
2254 2279 * This time format is used by STIME field when -f or -o option
2255 2280 * is specified. Used for processes that begun less than
2256 2281 * 24 hours.
2257 2282 */
2258 2283 (void) strftime(sttim, sizeof (sttim),
2259 2284 dcgettext(NULL, "%H:%M:%S", LC_TIME),
2260 2285 localtime(&starttime));
2261 2286 }
2262 2287 (void) printf("%*.*s", width, width, sttim);
2263 2288 }
2264 2289
2265 2290 static void
2266 2291 przom(psinfo_t *psinfo)
2267 2292 {
2268 2293 long tm;
2269 2294 struct passwd *pwd;
2270 2295 char zonename[ZONENAME_MAX];
2271 2296
2272 2297 /*
2273 2298 * All fields before 'PID' are printed with a trailing space as a
2274 2299 * spearator, rather than keeping track of which column is first. All
2275 2300 * other fields are printed with a leading space.
2276 2301 */
2277 2302 if (lflg) { /* F S */
2278 2303 if (!yflg)
2279 2304 (void) printf("%2x ", psinfo->pr_flag & 0377); /* F */
2280 2305 (void) printf("%c ", psinfo->pr_lwp.pr_sname); /* S */
2281 2306 }
2282 2307 if (Zflg) {
2283 2308 if (getzonenamebyid(psinfo->pr_zoneid, zonename,
2284 2309 sizeof (zonename)) < 0) {
2285 2310 if (snprintf(NULL, 0, "%d",
2286 2311 ((int)psinfo->pr_zoneid)) > 7)
2287 2312 (void) printf(" %6.6d%c ",
2288 2313 ((int)psinfo->pr_zoneid), '*');
2289 2314 else
2290 2315 (void) printf(" %7.7d ",
2291 2316 ((int)psinfo->pr_zoneid));
2292 2317 } else {
2293 2318 size_t nw;
2294 2319
2295 2320 nw = mbstowcs(NULL, zonename, 0);
2296 2321 if (nw == (size_t)-1)
2297 2322 (void) printf("%8.8s ", "ERROR");
2298 2323 else if (nw > 8)
2299 2324 (void) wprintf(L"%7.7s%c ", zonename, '*');
2300 2325 else
2301 2326 (void) wprintf(L"%8.8s ", zonename);
2302 2327 }
2303 2328 }
2304 2329 if (Hflg) {
2305 2330 /* Display home lgroup */
2306 2331 (void) printf(" %6d", (int)psinfo->pr_lwp.pr_lgrp); /* LGRP */
2307 2332 }
2308 2333 if (fflg) {
2309 2334 if ((pwd = getpwuid(psinfo->pr_euid)) != NULL) {
2310 2335 size_t nw;
2311 2336
2312 2337 nw = mbstowcs(NULL, pwd->pw_name, 0);
2313 2338 if (nw == (size_t)-1)
2314 2339 (void) printf("%8.8s ", "ERROR");
2315 2340 else if (nw > 8)
2316 2341 (void) wprintf(L"%7.7s%c ", pwd->pw_name, '*');
2317 2342 else
2318 2343 (void) wprintf(L"%8.8s ", pwd->pw_name);
2319 2344 } else {
2320 2345 if (snprintf(NULL, 0, "%u",
2321 2346 (psinfo->pr_euid)) > 7)
2322 2347 (void) printf(" %6.6u%c ", psinfo->pr_euid,
2323 2348 '*');
2324 2349 else
2325 2350 (void) printf(" %7.7u ", psinfo->pr_euid);
2326 2351 }
2327 2352 } else if (lflg) {
2328 2353 if (snprintf(NULL, 0, "%u", (psinfo->pr_euid)) > 6)
2329 2354 (void) printf("%5.5u%c ", psinfo->pr_euid, '*');
2330 2355 else
2331 2356 (void) printf("%6u ", psinfo->pr_euid);
2332 2357 }
2333 2358
2334 2359 (void) printf("%*d", pidwidth, (int)psinfo->pr_pid); /* PID */
2335 2360 if (lflg || fflg)
2336 2361 (void) printf(" %*d", pidwidth,
2337 2362 (int)psinfo->pr_ppid); /* PPID */
2338 2363
2339 2364 if (jflg) {
2340 2365 (void) printf(" %*d", pidwidth,
2341 2366 (int)psinfo->pr_pgid); /* PGID */
2342 2367 (void) printf(" %*d", pidwidth,
2343 2368 (int)psinfo->pr_sid); /* SID */
2344 2369 }
2345 2370
2346 2371 if (Lflg)
2347 2372 (void) printf(" %5d", 0); /* LWP */
2348 2373 if (Pflg)
2349 2374 (void) printf(" -"); /* PSR */
2350 2375 if (Lflg && fflg)
2351 2376 (void) printf(" %5d", 0); /* NLWP */
2352 2377
2353 2378 if (cflg) {
2354 2379 (void) printf(" %4s", "-"); /* zombies have no class */
2355 2380 (void) printf(" %3d", psinfo->pr_lwp.pr_pri); /* PRI */
2356 2381 } else if (lflg || fflg) {
2357 2382 (void) printf(" %3d", psinfo->pr_lwp.pr_cpu & 0377); /* C */
2358 2383 if (lflg)
2359 2384 (void) printf(" %3d %2s",
↓ open down ↓ |
269 lines elided |
↑ open up ↑ |
2360 2385 psinfo->pr_lwp.pr_oldpri, "-"); /* PRI NI */
2361 2386 }
2362 2387 if (lflg) {
2363 2388 if (yflg) /* RSS SZ WCHAN */
2364 2389 (void) printf(" %5d %6d %8s", 0, 0, "-");
2365 2390 else /* ADDR SZ WCHAN */
2366 2391 (void) printf(" %8s %6d %8s", "-", 0, "-");
2367 2392 }
2368 2393 if (fflg) {
2369 2394 int width = fname[F_STIME].width;
2370 - (void) printf(" %*.*s", width, width, "-"); /* STIME */
2395 + (void) printf(" %*.*s", width, width, "-"); /* STIME */
2371 2396 }
2372 2397 (void) printf(" %-8.14s", "?"); /* TTY */
2373 2398
2374 2399 tm = psinfo->pr_time.tv_sec;
2375 2400 if (psinfo->pr_time.tv_nsec > 500000000)
2376 2401 tm++;
2377 2402 (void) printf(" %4ld:%.2ld", tm / 60, tm % 60); /* TIME */
2378 2403 (void) printf(" <defunct>\n");
2379 2404 }
2380 2405
2381 2406 /*
2382 2407 * Function to compute the number of printable bytes in a multibyte
2383 2408 * command string ("internationalization").
2384 2409 */
2385 2410 static int
2386 2411 namencnt(char *cmd, int csisize, int scrsize)
2387 2412 {
2388 2413 int csiwcnt = 0, scrwcnt = 0;
2389 2414 int ncsisz, nscrsz;
2390 2415 wchar_t wchar;
2391 2416 int len;
2392 2417
2393 2418 while (*cmd != '\0') {
2394 2419 if ((len = csisize - csiwcnt) > (int)MB_CUR_MAX)
2395 2420 len = MB_CUR_MAX;
2396 2421 if ((ncsisz = mbtowc(&wchar, cmd, len)) < 0)
2397 2422 return (8); /* default to use for illegal chars */
2398 2423 if ((nscrsz = wcwidth(wchar)) <= 0)
2399 2424 return (8);
2400 2425 if (csiwcnt + ncsisz > csisize || scrwcnt + nscrsz > scrsize)
2401 2426 break;
2402 2427 csiwcnt += ncsisz;
2403 2428 scrwcnt += nscrsz;
2404 2429 cmd += ncsisz;
2405 2430 }
2406 2431 return (csiwcnt);
2407 2432 }
2408 2433
2409 2434 static char *
2410 2435 err_string(int err)
2411 2436 {
2412 2437 static char buf[32];
2413 2438 char *str = strerror(err);
2414 2439
2415 2440 if (str == NULL)
2416 2441 (void) snprintf(str = buf, sizeof (buf), "Errno #%d", err);
2417 2442
2418 2443 return (str);
2419 2444 }
2420 2445
2421 2446 /* If allocation fails, die */
2422 2447 static void *
2423 2448 Realloc(void *ptr, size_t size)
2424 2449 {
2425 2450 ptr = realloc(ptr, size);
2426 2451 if (ptr == NULL) {
2427 2452 (void) fprintf(stderr, gettext("ps: no memory\n"));
2428 2453 exit(1);
2429 2454 }
2430 2455 return (ptr);
2431 2456 }
2432 2457
2433 2458 static time_t
2434 2459 delta_secs(const timestruc_t *start)
2435 2460 {
2436 2461 time_t seconds = now.tv_sec - start->tv_sec;
2437 2462 long nanosecs = now.tv_usec * 1000 - start->tv_nsec;
2438 2463
2439 2464 if (nanosecs >= (NANOSEC / 2))
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
2440 2465 seconds++;
2441 2466 else if (nanosecs < -(NANOSEC / 2))
2442 2467 seconds--;
2443 2468
2444 2469 return (seconds);
2445 2470 }
2446 2471
2447 2472 /*
2448 2473 * Returns the following:
2449 2474 *
2450 - * 0 No error
2451 - * EINVAL Invalid number
2452 - * ERANGE Value exceeds (min, max) range
2475 + * 0 No error
2476 + * EINVAL Invalid number
2477 + * ERANGE Value exceeds (min, max) range
2453 2478 */
2454 2479 static int
2455 2480 str2id(const char *p, pid_t *val, long min, long max)
2456 2481 {
2457 2482 char *q;
2458 2483 long number;
2459 2484 int error;
2460 2485
2461 2486 errno = 0;
2462 2487 number = strtol(p, &q, 10);
2463 2488
2464 2489 if (errno != 0 || q == p || *q != '\0') {
2465 2490 if ((error = errno) == 0) {
2466 2491 /*
2467 2492 * strtol() can fail without setting errno, or it can
2468 2493 * set it to EINVAL or ERANGE. In the case errno is
2469 2494 * still zero, return EINVAL.
2470 2495 */
2471 2496 error = EINVAL;
2472 2497 }
2473 2498 } else if (number < min || number > max) {
2474 2499 error = ERANGE;
2475 2500 } else {
2476 2501 error = 0;
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
2477 2502 }
2478 2503
2479 2504 *val = number;
2480 2505
2481 2506 return (error);
2482 2507 }
2483 2508
2484 2509 /*
2485 2510 * Returns the following:
2486 2511 *
2487 - * 0 No error
2488 - * EINVAL Invalid number
2489 - * ERANGE Value exceeds (min, max) range
2512 + * 0 No error
2513 + * EINVAL Invalid number
2514 + * ERANGE Value exceeds (min, max) range
2490 2515 */
2491 2516 static int
2492 2517 str2uid(const char *p, uid_t *val, unsigned long min, unsigned long max)
2493 2518 {
2494 2519 char *q;
2495 2520 unsigned long number;
2496 2521 int error;
2497 2522
2498 2523 errno = 0;
2499 2524 number = strtoul(p, &q, 10);
2500 2525
2501 2526 if (errno != 0 || q == p || *q != '\0') {
2502 2527 if ((error = errno) == 0) {
2503 2528 /*
2504 2529 * strtoul() can fail without setting errno, or it can
2505 2530 * set it to EINVAL or ERANGE. In the case errno is
2506 2531 * still zero, return EINVAL.
2507 2532 */
2508 2533 error = EINVAL;
2509 2534 }
2510 2535 } else if (number < min || number > max) {
2511 2536 error = ERANGE;
2512 2537 } else {
2513 2538 error = 0;
2514 2539 }
2515 2540
2516 2541 *val = number;
2517 2542
2518 2543 return (error);
2519 2544 }
2520 2545
2521 2546 static int
2522 2547 pidcmp(const void *p1, const void *p2)
2523 2548 {
2524 2549 pid_t i = *((pid_t *)p1);
2525 2550 pid_t j = *((pid_t *)p2);
2526 2551
2527 2552 return (i - j);
2528 2553 }
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX