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