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