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/whodo/whodo.c
+++ new/usr/src/cmd/whodo/whodo.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.
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 + * Copyright (c) 2013 Gary Mills
23 + *
22 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 25 * Use is subject to license terms.
24 26 */
25 27
26 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 29 /* All Rights Reserved */
28 30
29 31 /*
30 32 * University Copyright- Copyright (c) 1982, 1986, 1988
31 33 * The Regents of the University of California
32 34 * All Rights Reserved
33 35 *
34 36 * University Acknowledgment- Portions of this document are derived from
35 37 * software developed by the University of California, Berkeley, and its
36 38 * contributors.
37 39 */
38 40
39 41 /*
40 42 * This is the new whodo command which takes advantage of
41 43 * the /proc interface to gain access to the information
42 44 * of all the processes currently on the system.
43 45 *
44 46 * Maintenance note:
45 47 *
46 48 * Much of this code is replicated in w.c. If you're
47 49 * fixing bugs here, then you should probably fix 'em there too.
48 50 */
49 51
50 52 #include <stdio.h>
51 53 #include <string.h>
52 54 #include <stdlib.h>
53 55 #include <ctype.h>
54 56 #include <fcntl.h>
55 57 #include <time.h>
56 58 #include <errno.h>
57 59 #include <sys/types.h>
58 60 #include <utmpx.h>
59 61 #include <sys/utsname.h>
60 62 #include <sys/stat.h>
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
61 63 #include <sys/mkdev.h>
62 64 #include <dirent.h>
63 65 #include <procfs.h> /* /proc header file */
64 66 #include <sys/wait.h>
65 67 #include <locale.h>
66 68 #include <unistd.h>
67 69 #include <limits.h>
68 70 #include <priv_utils.h>
69 71
70 72 /*
71 - * utmpx defines wider fields for user and line. For compatibility of output,
72 - * we are limiting these to the old maximums in utmp. Define UTMPX_NAMELEN
73 - * to use the full lengths.
73 + * Use the full lengths from utmpx for user and line.
74 74 */
75 -#ifndef UTMPX_NAMELEN
76 -/* XXX - utmp - fix name length */
77 -#define NMAX (_POSIX_LOGIN_NAME_MAX - 1)
78 -#define LMAX 12
79 -#else /* UTMPX_NAMELEN */
80 -static struct utmpx dummy;
81 -#define NMAX (sizeof (dummy.ut_user))
82 -#define LMAX (sizeof (dummy.ut_line))
83 -#endif /* UTMPX_NAMELEN */
75 +#define NMAX (sizeof (((struct utmpx *)0)->ut_user))
76 +#define LMAX (sizeof (((struct utmpx *)0)->ut_line))
84 77
78 +/* Print minimum field widths. */
79 +#define LOGIN_WIDTH 8
80 +#define LINE_WIDTH 12
81 +
85 82 #define DIV60(t) ((t+30)/60) /* x/60 rounded */
86 83
87 84 #ifdef ERR
88 85 #undef ERR
89 86 #endif
90 87 #define ERR (-1)
91 88
92 89 #define DEVNAMELEN 14
93 90 #define HSIZE 256 /* size of process hash table */
94 91 #define PROCDIR "/proc"
95 92 #define INITPROCESS (pid_t)1 /* init process pid */
96 93 #define NONE 'n' /* no state */
97 94 #define RUNNING 'r' /* runnable process */
98 95 #define ZOMBIE 'z' /* zombie process */
99 96 #define VISITED 'v' /* marked node as visited */
100 97
101 98 static int ndevs; /* number of configured devices */
102 99 static int maxdev; /* slots for configured devices */
103 100 #define DNINCR 100
104 101 static struct devl { /* device list */
105 102 char dname[DEVNAMELEN]; /* device name */
106 103 dev_t ddev; /* device number */
107 104 } *devl;
108 105
109 106 struct uproc {
110 107 pid_t p_upid; /* user process id */
111 108 char p_state; /* numeric value of process state */
112 109 dev_t p_ttyd; /* controlling tty of process */
113 110 time_t p_time; /* ticks of user & system time */
114 111 time_t p_ctime; /* ticks of child user & system time */
115 112 int p_igintr; /* 1=ignores SIGQUIT and SIGINT */
116 113 char p_comm[PRARGSZ+1]; /* command */
117 114 char p_args[PRARGSZ+1]; /* command line arguments */
118 115 struct uproc *p_child, /* first child pointer */
119 116 *p_sibling, /* sibling pointer */
120 117 *p_pgrplink, /* pgrp link */
121 118 *p_link; /* hash table chain pointer */
122 119 };
123 120
124 121 /*
125 122 * define hash table for struct uproc
126 123 * Hash function uses process id
127 124 * and the size of the hash table(HSIZE)
128 125 * to determine process index into the table.
129 126 */
130 127 static struct uproc pr_htbl[HSIZE];
131 128
132 129 static struct uproc *findhash(pid_t);
133 130 static time_t findidle(char *);
134 131 static void clnarglist(char *);
135 132 static void showproc(struct uproc *);
136 133 static void showtotals(struct uproc *);
137 134 static void calctotals(struct uproc *);
138 135 static char *getty(dev_t);
139 136 static void prttime(time_t, char *);
140 137 static void prtat(time_t *);
141 138 static void checkampm(char *);
142 139
143 140 static char *prog;
144 141 static int header = 1; /* true if -h flag: don't print heading */
145 142 static int lflag = 0; /* true if -l flag: w command format */
146 143 static char *sel_user; /* login of particular user selected */
147 144 static time_t now; /* current time of day */
148 145 static time_t uptime; /* time of last reboot & elapsed time since */
149 146 static int nusers; /* number of users logged in now */
150 147 static time_t idle; /* number of minutes user is idle */
151 148 static time_t jobtime; /* total cpu time visible */
152 149 static char doing[520]; /* process attached to terminal */
153 150 static time_t proctime; /* cpu time of process in doing */
154 151 static int empty;
155 152 static pid_t curpid;
156 153
157 154 #if SIGQUIT > SIGINT
158 155 #define ACTSIZE SIGQUIT
159 156 #else
160 157 #define ACTSIZE SIGINT
161 158 #endif
162 159
163 160 int
164 161 main(int argc, char *argv[])
165 162 {
166 163 struct utmpx *ut;
167 164 struct utmpx *utmpbegin;
168 165 struct utmpx *utmpend;
169 166 struct utmpx *utp;
170 167 struct tm *tm;
171 168 struct uproc *up, *parent, *pgrp;
172 169 struct psinfo info;
173 170 struct sigaction actinfo[ACTSIZE];
174 171 struct pstatus statinfo;
175 172 size_t size;
176 173 struct stat sbuf;
177 174 struct utsname uts;
178 175 DIR *dirp;
179 176 struct dirent *dp;
180 177 char pname[64];
181 178 char *fname;
182 179 int procfd;
183 180 int i;
184 181 int days, hrs, mins;
185 182 int entries;
186 183
187 184 /*
188 185 * This program needs the proc_owner privilege
189 186 */
190 187 (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER,
191 188 (char *)NULL);
192 189
193 190 (void) setlocale(LC_ALL, "");
194 191 #if !defined(TEXT_DOMAIN)
195 192 #define TEXT_DOMAIN "SYS_TEST"
196 193 #endif
197 194 (void) textdomain(TEXT_DOMAIN);
198 195
199 196 prog = argv[0];
200 197
201 198 while (argc > 1) {
202 199 if (argv[1][0] == '-') {
203 200 for (i = 1; argv[1][i]; i++) {
204 201 switch (argv[1][i]) {
205 202
206 203 case 'h':
207 204 header = 0;
208 205 break;
209 206
210 207 case 'l':
211 208 lflag++;
212 209 break;
213 210
214 211 default:
215 212 (void) printf(gettext(
216 213 "usage: %s [ -hl ] [ user ]\n"),
217 214 prog);
218 215 exit(1);
219 216 }
220 217 }
221 218 } else {
222 219 if (!isalnum(argv[1][0]) || argc > 2) {
223 220 (void) printf(gettext(
224 221 "usage: %s [ -hl ] [ user ]\n"), prog);
225 222 exit(1);
226 223 } else
227 224 sel_user = argv[1];
228 225 }
229 226 argc--; argv++;
230 227 }
231 228
232 229 /*
233 230 * read the UTMPX_FILE (contains information about
234 231 * each logged in user)
235 232 */
236 233 if (stat(UTMPX_FILE, &sbuf) == ERR) {
237 234 (void) fprintf(stderr, gettext("%s: stat error of %s: %s\n"),
238 235 prog, UTMPX_FILE, strerror(errno));
239 236 exit(1);
240 237 }
241 238 entries = sbuf.st_size / sizeof (struct futmpx);
242 239 size = sizeof (struct utmpx) * entries;
243 240
244 241 if ((ut = malloc(size)) == NULL) {
245 242 (void) fprintf(stderr, gettext("%s: malloc error of %s: %s\n"),
246 243 prog, UTMPX_FILE, strerror(errno));
247 244 exit(1);
248 245 }
249 246
250 247 (void) utmpxname(UTMPX_FILE);
251 248
252 249 utmpbegin = ut;
253 250 /* LINTED pointer cast may result in improper alignment */
254 251 utmpend = (struct utmpx *)((char *)utmpbegin + size);
255 252
256 253 setutxent();
257 254 while ((ut < utmpend) && ((utp = getutxent()) != NULL))
258 255 (void) memcpy(ut++, utp, sizeof (*ut));
259 256 endutxent();
260 257
261 258 (void) time(&now); /* get current time */
262 259
263 260 if (header) { /* print a header */
264 261 if (lflag) { /* w command format header */
265 262 prtat(&now);
266 263 for (ut = utmpbegin; ut < utmpend; ut++) {
267 264 if (ut->ut_type == USER_PROCESS) {
268 265 nusers++;
269 266 } else if (ut->ut_type == BOOT_TIME) {
270 267 uptime = now - ut->ut_xtime;
271 268 uptime += 30;
272 269 days = uptime / (60*60*24);
273 270 uptime %= (60*60*24);
274 271 hrs = uptime / (60*60);
275 272 uptime %= (60*60);
276 273 mins = uptime / 60;
277 274
278 275 (void) printf(dcgettext(NULL,
279 276 " up %d day(s), %d hr(s), "
280 277 "%d min(s)", LC_TIME),
281 278 days, hrs, mins);
282 279 }
283 280 }
284 281
285 282 ut = utmpbegin; /* rewind utmp data */
286 283 (void) printf(dcgettext(NULL,
287 284 " %d user(s)\n", LC_TIME), nusers);
288 285 (void) printf(dcgettext(NULL, "User tty "
289 286 "login@ idle JCPU PCPU what\n", LC_TIME));
290 287 } else { /* standard whodo header */
291 288 char date_buf[100];
292 289
293 290 /*
294 291 * print current time and date
295 292 */
296 293 (void) strftime(date_buf, sizeof (date_buf),
297 294 dcgettext(NULL, "%C", LC_TIME), localtime(&now));
298 295 (void) printf("%s\n", date_buf);
299 296
300 297 /*
301 298 * print system name
302 299 */
303 300 (void) uname(&uts);
304 301 (void) printf("%s\n", uts.nodename);
305 302 }
306 303 }
307 304
308 305 /*
309 306 * loop through /proc, reading info about each process
310 307 * and build the parent/child tree
311 308 */
312 309 if (!(dirp = opendir(PROCDIR))) {
313 310 (void) fprintf(stderr, gettext("%s: could not open %s: %s\n"),
314 311 prog, PROCDIR, strerror(errno));
315 312 exit(1);
316 313 }
317 314
318 315 while ((dp = readdir(dirp)) != NULL) {
319 316 if (dp->d_name[0] == '.')
320 317 continue;
321 318 retry:
322 319 (void) snprintf(pname, sizeof (pname),
323 320 "%s/%s/", PROCDIR, dp->d_name);
324 321 fname = pname + strlen(pname);
325 322 (void) strcpy(fname, "psinfo");
326 323 if ((procfd = open(pname, O_RDONLY)) < 0)
327 324 continue;
328 325 if (read(procfd, &info, sizeof (info)) != sizeof (info)) {
329 326 int err = errno;
330 327 (void) close(procfd);
331 328 if (err == EAGAIN)
332 329 goto retry;
333 330 if (err != ENOENT)
334 331 (void) fprintf(stderr, gettext(
335 332 "%s: read() failed on %s: %s\n"),
336 333 prog, pname, strerror(err));
337 334 continue;
338 335 }
339 336 (void) close(procfd);
340 337
341 338 up = findhash(info.pr_pid);
342 339 up->p_ttyd = info.pr_ttydev;
343 340 up->p_state = (info.pr_nlwp == 0? ZOMBIE : RUNNING);
344 341 up->p_time = 0;
345 342 up->p_ctime = 0;
346 343 up->p_igintr = 0;
347 344 (void) strncpy(up->p_comm, info.pr_fname,
348 345 sizeof (info.pr_fname));
349 346 up->p_args[0] = 0;
350 347
351 348 if (up->p_state != NONE && up->p_state != ZOMBIE) {
352 349 (void) strcpy(fname, "status");
353 350
354 351 /* now we need the proc_owner privilege */
355 352 (void) __priv_bracket(PRIV_ON);
356 353
357 354 procfd = open(pname, O_RDONLY);
358 355
359 356 /* drop proc_owner privilege after open */
360 357 (void) __priv_bracket(PRIV_OFF);
361 358
362 359 if (procfd < 0)
363 360 continue;
364 361
365 362 if (read(procfd, &statinfo, sizeof (statinfo))
366 363 != sizeof (statinfo)) {
367 364 int err = errno;
368 365 (void) close(procfd);
369 366 if (err == EAGAIN)
370 367 goto retry;
371 368 if (err != ENOENT)
372 369 (void) fprintf(stderr, gettext(
373 370 "%s: read() failed on %s: %s \n"),
374 371 prog, pname, strerror(err));
375 372 continue;
376 373 }
377 374 (void) close(procfd);
378 375
379 376 up->p_time = statinfo.pr_utime.tv_sec +
380 377 statinfo.pr_stime.tv_sec;
381 378 up->p_ctime = statinfo.pr_cutime.tv_sec +
382 379 statinfo.pr_cstime.tv_sec;
383 380
384 381 (void) strcpy(fname, "sigact");
385 382
386 383 /* now we need the proc_owner privilege */
387 384 (void) __priv_bracket(PRIV_ON);
388 385
389 386 procfd = open(pname, O_RDONLY);
390 387
391 388 /* drop proc_owner privilege after open */
392 389 (void) __priv_bracket(PRIV_OFF);
393 390
394 391 if (procfd < 0)
395 392 continue;
396 393 if (read(procfd, actinfo, sizeof (actinfo))
397 394 != sizeof (actinfo)) {
398 395 int err = errno;
399 396 (void) close(procfd);
400 397 if (err == EAGAIN)
401 398 goto retry;
402 399 if (err != ENOENT)
403 400 (void) fprintf(stderr, gettext(
404 401 "%s: read() failed on %s: %s \n"),
405 402 prog, pname, strerror(err));
406 403 continue;
407 404 }
408 405 (void) close(procfd);
409 406
410 407 up->p_igintr =
411 408 actinfo[SIGINT-1].sa_handler == SIG_IGN &&
412 409 actinfo[SIGQUIT-1].sa_handler == SIG_IGN;
413 410
414 411 up->p_args[0] = 0;
415 412
416 413 /*
417 414 * Process args if there's a chance we'll print it.
418 415 */
419 416 if (lflag) { /* w command needs args */
420 417 clnarglist(info.pr_psargs);
421 418 (void) strcpy(up->p_args, info.pr_psargs);
422 419 if (up->p_args[0] == 0 ||
423 420 up->p_args[0] == '-' &&
424 421 up->p_args[1] <= ' ' ||
425 422 up->p_args[0] == '?') {
426 423 (void) strcat(up->p_args, " (");
427 424 (void) strcat(up->p_args, up->p_comm);
428 425 (void) strcat(up->p_args, ")");
429 426 }
430 427 }
431 428
432 429 }
433 430
434 431 /*
435 432 * link pgrp together in case parents go away
436 433 * Pgrp chain is a single linked list originating
437 434 * from the pgrp leader to its group member.
438 435 */
439 436 if (info.pr_pgid != info.pr_pid) { /* not pgrp leader */
440 437 pgrp = findhash(info.pr_pgid);
441 438 up->p_pgrplink = pgrp->p_pgrplink;
442 439 pgrp->p_pgrplink = up;
443 440 }
444 441 parent = findhash(info.pr_ppid);
445 442
446 443 /* if this is the new member, link it in */
447 444 if (parent->p_upid != INITPROCESS) {
448 445 if (parent->p_child) {
449 446 up->p_sibling = parent->p_child;
450 447 up->p_child = 0;
451 448 }
452 449 parent->p_child = up;
453 450 }
454 451
455 452 }
456 453
457 454 /* revert to non-privileged user */
458 455 (void) __priv_relinquish();
459 456
460 457 (void) closedir(dirp);
461 458 (void) time(&now); /* get current time */
462 459
463 460 /*
464 461 * loop through utmpx file, printing process info
465 462 * about each logged in user
↓ open down ↓ |
371 lines elided |
↑ open up ↑ |
466 463 */
467 464 for (ut = utmpbegin; ut < utmpend; ut++) {
468 465 time_t tim;
469 466
470 467 if (ut->ut_type != USER_PROCESS)
471 468 continue;
472 469 if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0)
473 470 continue; /* we're looking for somebody else */
474 471 if (lflag) { /* -l flag format (w command) */
475 472 /* print login name of the user */
476 - (void) printf("%-*.*s ", NMAX, NMAX, ut->ut_name);
473 + (void) printf("%-*.*s ", LOGIN_WIDTH, (int)NMAX,
474 + ut->ut_name);
477 475
478 476 /* print tty user is on */
479 - (void) printf("%-*.*s", LMAX, LMAX, ut->ut_line);
477 + (void) printf("%-*.*s", LINE_WIDTH, (int)LMAX,
478 + ut->ut_line);
480 479
481 480 /* print when the user logged in */
482 481 tim = ut->ut_xtime;
483 482 (void) prtat(&tim);
484 483
485 484 /* print idle time */
486 485 idle = findidle(ut->ut_line);
487 486 if (idle >= 36 * 60)
488 487 (void) printf(dcgettext(NULL, "%2ddays ",
489 488 LC_TIME), (idle + 12 * 60) / (24 * 60));
490 489 else
491 490 prttime(idle, " ");
492 491 showtotals(findhash((pid_t)ut->ut_pid));
493 492 } else { /* standard whodo format */
494 493 tim = ut->ut_xtime;
495 494 tm = localtime(&tim);
496 495 (void) printf("\n%-*.*s %-*.*s %2.1d:%2.2d\n",
497 - LMAX, LMAX, ut->ut_line,
498 - NMAX, NMAX, ut->ut_name, tm->tm_hour, tm->tm_min);
496 + LINE_WIDTH, (int)LMAX, ut->ut_line,
497 + LOGIN_WIDTH, (int)NMAX, ut->ut_name, tm->tm_hour,
498 + tm->tm_min);
499 499 showproc(findhash((pid_t)ut->ut_pid));
500 500 }
501 501 }
502 502
503 503 return (0);
504 504 }
505 505
506 506 /*
507 507 * Used for standard whodo format.
508 508 * This is the recursive routine descending the process
509 509 * tree starting from the given process pointer(up).
510 510 * It used depth-first search strategy and also marked
511 511 * each node as printed as it traversed down the tree.
512 512 */
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
513 513 static void
514 514 showproc(struct uproc *up)
515 515 {
516 516 struct uproc *zp;
517 517
518 518 if (up->p_state == VISITED) /* we already been here */
519 519 return;
520 520 /* print the data for this process */
521 521 if (up->p_state == ZOMBIE)
522 522 (void) printf(" %-*.*s %5d %4.1ld:%2.2ld %s\n",
523 - LMAX, LMAX, " ?", (int)up->p_upid, 0L, 0L, "<defunct>");
523 + LINE_WIDTH, (int)LMAX, " ?", (int)up->p_upid, 0L, 0L,
524 + "<defunct>");
524 525 else if (up->p_state != NONE) {
525 526 (void) printf(" %-*.*s %5d %4.1ld:%2.2ld %s\n",
526 - LMAX, LMAX, getty(up->p_ttyd), (int)up->p_upid,
527 + LINE_WIDTH, (int)LMAX, getty(up->p_ttyd), (int)up->p_upid,
527 528 up->p_time / 60L, up->p_time % 60L,
528 529 up->p_comm);
529 530 }
530 531 up->p_state = VISITED;
531 532
532 533 /* descend for its children */
533 534 if (up->p_child) {
534 535 showproc(up->p_child);
535 536 for (zp = up->p_child->p_sibling; zp; zp = zp->p_sibling) {
536 537 showproc(zp);
537 538 }
538 539 }
539 540
540 541 /* print the pgrp relation */
541 542 if (up->p_pgrplink)
542 543 showproc(up->p_pgrplink);
543 544 }
544 545
545 546
546 547 /*
547 548 * Used for -l flag (w command) format.
548 549 * Prints the CPU time for all processes & children,
549 550 * and the cpu time for interesting process,
550 551 * and what the user is doing.
551 552 */
552 553 static void
553 554 showtotals(struct uproc *up)
554 555 {
555 556 jobtime = 0;
556 557 proctime = 0;
557 558 empty = 1;
558 559 curpid = -1;
559 560 (void) strcpy(doing, "-"); /* default act: normally never prints */
560 561 calctotals(up);
561 562
562 563 /* print CPU time for all processes & children */
563 564 /* and need to convert clock ticks to seconds first */
564 565 prttime((time_t)jobtime, " ");
565 566
566 567 /* print cpu time for interesting process */
567 568 /* and need to convert clock ticks to seconds first */
568 569 prttime((time_t)proctime, " ");
569 570
570 571 /* what user is doing, current process */
571 572 (void) printf(" %-.32s\n", doing);
572 573 }
573 574
574 575 /*
575 576 * Used for -l flag (w command) format.
576 577 * This recursive routine descends the process
577 578 * tree starting from the given process pointer(up).
578 579 * It used depth-first search strategy and also marked
579 580 * each node as visited as it traversed down the tree.
580 581 * It calculates the process time for all processes &
581 582 * children. It also finds the "interesting" process
582 583 * and determines its cpu time and command.
583 584 */
584 585 static void
585 586 calctotals(struct uproc *up)
586 587 {
587 588 struct uproc *zp;
588 589
589 590 if (up->p_state == VISITED)
590 591 return;
591 592 up->p_state = VISITED;
592 593 if (up->p_state == NONE || up->p_state == ZOMBIE)
593 594 return;
594 595 jobtime += up->p_time + up->p_ctime;
595 596 proctime += up->p_time;
596 597
597 598 if (empty && !up->p_igintr) {
598 599 empty = 0;
599 600 curpid = -1;
600 601 }
601 602
602 603 if (up->p_upid > curpid && (!up->p_igintr || empty)) {
603 604 curpid = up->p_upid;
604 605 (void) strcpy(doing, up->p_args);
605 606 }
606 607
607 608 /* descend for its children */
608 609 if (up->p_child) {
609 610 calctotals(up->p_child);
610 611 for (zp = up->p_child->p_sibling; zp; zp = zp->p_sibling)
611 612 calctotals(zp);
612 613 }
613 614 }
614 615
615 616 static char *
616 617 devadd(char *name, dev_t ddev)
617 618 {
618 619 struct devl *dp;
619 620 int leng, start, i;
620 621
621 622 if (ndevs == maxdev) {
622 623 maxdev += DNINCR;
623 624 dp = realloc(devl, maxdev * sizeof (struct devl));
624 625 if (!dp) {
625 626 (void) fprintf(stderr,
626 627 gettext("%s: out of memory!: %s\n"),
627 628 prog, strerror(errno));
628 629 exit(1);
629 630 }
630 631 devl = dp;
631 632 }
632 633 dp = &devl[ndevs++];
633 634
634 635 dp->ddev = ddev;
635 636 if (name == NULL) {
636 637 (void) strcpy(dp->dname, " ? ");
637 638 return (dp->dname);
638 639 }
639 640
640 641 leng = strlen(name);
641 642 if (leng < DEVNAMELEN + 4) {
642 643 /* strip off "/dev/" */
643 644 (void) strcpy(dp->dname, &name[5]);
644 645 } else {
645 646 /* strip enough off the front to fit */
646 647 start = leng - DEVNAMELEN - 1;
647 648
648 649 for (i = start; i < leng && name[i] != '/'; i++)
649 650 ;
650 651 if (i == leng)
651 652 (void) strncpy(dp->dname, &name[start], DEVNAMELEN);
652 653 else
653 654 (void) strncpy(dp->dname, &name[i+1], DEVNAMELEN);
654 655 }
655 656 return (dp->dname);
656 657 }
657 658
658 659 static char *
659 660 devlookup(dev_t ddev)
660 661 {
661 662 struct devl *dp;
662 663 int i;
663 664
664 665 for (dp = devl, i = 0; i < ndevs; dp++, i++) {
665 666 if (dp->ddev == ddev)
666 667 return (dp->dname);
667 668 }
668 669 return (NULL);
669 670 }
670 671
671 672 /*
672 673 * This routine gives back a corresponding device name
673 674 * from the device number given.
674 675 */
675 676 static char *
676 677 getty(dev_t dev)
677 678 {
678 679 extern char *_ttyname_dev(dev_t, char *, size_t);
679 680 char devname[TTYNAME_MAX];
680 681 char *retval;
681 682
682 683 if (dev == PRNODEV)
683 684 return (" ? ");
684 685
685 686 if ((retval = devlookup(dev)) != NULL)
686 687 return (retval);
687 688
688 689 retval = _ttyname_dev(dev, devname, sizeof (devname));
689 690 return (devadd(retval, dev));
690 691 }
691 692
692 693 /*
693 694 * Findhash finds the appropriate entry in the process
694 695 * hash table (pr_htbl) for the given pid in case that
695 696 * pid exists on the hash chain. It returns back a pointer
696 697 * to that uproc structure. If this is a new pid, it allocates
697 698 * a new node, initializes it, links it into the chain (after
698 699 * head) and returns a structure pointer.
699 700 */
700 701 static struct uproc *
701 702 findhash(pid_t pid)
702 703 {
703 704 struct uproc *up, *tp;
704 705
705 706 tp = up = &pr_htbl[(int)pid % HSIZE];
706 707 if (up->p_upid == 0) { /* empty slot */
707 708 up->p_upid = pid;
708 709 up->p_state = NONE;
709 710 up->p_child = up->p_sibling = up->p_pgrplink = up->p_link = 0;
710 711 return (up);
711 712 }
712 713 if (up->p_upid == pid) { /* found in hash table */
713 714 return (up);
714 715 }
715 716 for (tp = up->p_link; tp; tp = tp->p_link) { /* follow chain */
716 717 if (tp->p_upid == pid) {
717 718 return (tp);
718 719 }
719 720 }
720 721 tp = malloc(sizeof (*tp)); /* add new node */
721 722 if (!tp) {
722 723 (void) fprintf(stderr, gettext("%s: out of memory!: %s\n"),
723 724 prog, strerror(errno));
724 725 exit(1);
725 726 }
726 727 (void) memset((char *)tp, 0, sizeof (*tp));
727 728 tp->p_upid = pid;
728 729 tp->p_state = NONE;
729 730 tp->p_child = tp->p_sibling = tp->p_pgrplink = (pid_t)0;
730 731 tp->p_link = up->p_link; /* insert after head */
731 732 up->p_link = tp;
732 733 return (tp);
733 734 }
734 735
735 736 #define HR (60 * 60)
736 737 #define DAY (24 * HR)
737 738 #define MON (30 * DAY)
738 739
739 740 /*
740 741 * prints a time in hours and minutes or minutes and seconds.
741 742 * The character string 'tail' is printed at the end, obvious
742 743 * strings to pass are "", " ", or "am".
743 744 */
744 745 static void
745 746 prttime(time_t tim, char *tail)
746 747 {
747 748 if (tim >= 60)
748 749 (void) printf(dcgettext(NULL, "%3d:%02d", LC_TIME),
749 750 (int)tim/60, (int)tim%60);
750 751 else if (tim > 0)
751 752 (void) printf(dcgettext(NULL, " %2d", LC_TIME), (int)tim);
752 753 else
753 754 (void) printf(" ");
754 755 (void) printf("%s", tail);
755 756 }
756 757
757 758
758 759 /*
759 760 * prints a 12 hour time given a pointer to a time of day
760 761 */
761 762 static void
762 763 prtat(time_t *time)
763 764 {
764 765 struct tm *p;
765 766
766 767 p = localtime(time);
767 768 if (now - *time <= 18 * HR) {
768 769 char timestr[50];
769 770 (void) strftime(timestr, sizeof (timestr),
770 771 dcgettext(NULL, " %l:%M""%p", LC_TIME), p);
771 772 checkampm(timestr);
772 773 (void) printf("%s", timestr);
773 774 } else if (now - *time <= 7 * DAY) {
774 775 char weekdaytime[20];
775 776
776 777 (void) strftime(weekdaytime, sizeof (weekdaytime),
777 778 dcgettext(NULL, "%a%l%p", LC_TIME), p);
778 779 checkampm(weekdaytime);
779 780 (void) printf(" %s", weekdaytime);
780 781 } else {
781 782 char monthtime[20];
782 783
783 784 (void) strftime(monthtime, sizeof (monthtime),
784 785 dcgettext(NULL, "%e%b%y", LC_TIME), p);
785 786 (void) printf(" %s", monthtime);
786 787 }
787 788 }
788 789
789 790 /*
790 791 * find & return number of minutes current tty has been idle
791 792 */
792 793 static time_t
793 794 findidle(char *devname)
794 795 {
795 796 struct stat stbuf;
796 797 time_t lastaction, diff;
797 798 char ttyname[64];
798 799
799 800 (void) strcpy(ttyname, "/dev/");
800 801 (void) strcat(ttyname, devname);
801 802 if (stat(ttyname, &stbuf) != -1) {
802 803 lastaction = stbuf.st_atime;
803 804 diff = now - lastaction;
804 805 diff = DIV60(diff);
805 806 if (diff < 0)
806 807 diff = 0;
807 808 } else
808 809 diff = 0;
809 810 return (diff);
810 811 }
811 812
812 813 /*
813 814 * given a pointer to the argument string clean out unsavory characters.
814 815 */
815 816 static void
816 817 clnarglist(char *arglist)
817 818 {
818 819 char *c;
819 820 int err = 0;
820 821
821 822 /* get rid of unsavory characters */
822 823 for (c = arglist; *c == NULL; c++) {
823 824 if ((*c < ' ') || (*c > 0176)) {
824 825 if (err++ > 5) {
825 826 *arglist = NULL;
826 827 break;
827 828 }
828 829 *c = '?';
829 830 }
830 831 }
831 832 }
832 833
833 834 /* replaces all occurences of AM/PM with am/pm */
834 835 static void
835 836 checkampm(char *str)
836 837 {
837 838 char *ampm;
838 839 while ((ampm = strstr(str, "AM")) != NULL ||
839 840 (ampm = strstr(str, "PM")) != NULL) {
840 841 *ampm = tolower(*ampm);
841 842 *(ampm+1) = tolower(*(ampm+1));
842 843 }
843 844 }
↓ open down ↓ |
307 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX