2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39 /*
40 * This is the new whodo command which takes advantage of
41 * the /proc interface to gain access to the information
51 #include <string.h>
52 #include <stdlib.h>
53 #include <ctype.h>
54 #include <fcntl.h>
55 #include <time.h>
56 #include <errno.h>
57 #include <sys/types.h>
58 #include <utmpx.h>
59 #include <sys/utsname.h>
60 #include <sys/stat.h>
61 #include <sys/mkdev.h>
62 #include <dirent.h>
63 #include <procfs.h> /* /proc header file */
64 #include <sys/wait.h>
65 #include <locale.h>
66 #include <unistd.h>
67 #include <limits.h>
68 #include <priv_utils.h>
69
70 /*
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.
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 */
84
85 #define DIV60(t) ((t+30)/60) /* x/60 rounded */
86
87 #ifdef ERR
88 #undef ERR
89 #endif
90 #define ERR (-1)
91
92 #define DEVNAMELEN 14
93 #define HSIZE 256 /* size of process hash table */
94 #define PROCDIR "/proc"
95 #define INITPROCESS (pid_t)1 /* init process pid */
96 #define NONE 'n' /* no state */
97 #define RUNNING 'r' /* runnable process */
98 #define ZOMBIE 'z' /* zombie process */
99 #define VISITED 'v' /* marked node as visited */
100
101 static int ndevs; /* number of configured devices */
102 static int maxdev; /* slots for configured devices */
103 #define DNINCR 100
104 static struct devl { /* device list */
456
457 /* revert to non-privileged user */
458 (void) __priv_relinquish();
459
460 (void) closedir(dirp);
461 (void) time(&now); /* get current time */
462
463 /*
464 * loop through utmpx file, printing process info
465 * about each logged in user
466 */
467 for (ut = utmpbegin; ut < utmpend; ut++) {
468 time_t tim;
469
470 if (ut->ut_type != USER_PROCESS)
471 continue;
472 if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0)
473 continue; /* we're looking for somebody else */
474 if (lflag) { /* -l flag format (w command) */
475 /* print login name of the user */
476 (void) printf("%-*.*s ", NMAX, NMAX, ut->ut_name);
477
478 /* print tty user is on */
479 (void) printf("%-*.*s", LMAX, LMAX, ut->ut_line);
480
481 /* print when the user logged in */
482 tim = ut->ut_xtime;
483 (void) prtat(&tim);
484
485 /* print idle time */
486 idle = findidle(ut->ut_line);
487 if (idle >= 36 * 60)
488 (void) printf(dcgettext(NULL, "%2ddays ",
489 LC_TIME), (idle + 12 * 60) / (24 * 60));
490 else
491 prttime(idle, " ");
492 showtotals(findhash((pid_t)ut->ut_pid));
493 } else { /* standard whodo format */
494 tim = ut->ut_xtime;
495 tm = localtime(&tim);
496 (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);
499 showproc(findhash((pid_t)ut->ut_pid));
500 }
501 }
502
503 return (0);
504 }
505
506 /*
507 * Used for standard whodo format.
508 * This is the recursive routine descending the process
509 * tree starting from the given process pointer(up).
510 * It used depth-first search strategy and also marked
511 * each node as printed as it traversed down the tree.
512 */
513 static void
514 showproc(struct uproc *up)
515 {
516 struct uproc *zp;
517
518 if (up->p_state == VISITED) /* we already been here */
519 return;
520 /* print the data for this process */
521 if (up->p_state == ZOMBIE)
522 (void) printf(" %-*.*s %5d %4.1ld:%2.2ld %s\n",
523 LMAX, LMAX, " ?", (int)up->p_upid, 0L, 0L, "<defunct>");
524 else if (up->p_state != NONE) {
525 (void) printf(" %-*.*s %5d %4.1ld:%2.2ld %s\n",
526 LMAX, LMAX, getty(up->p_ttyd), (int)up->p_upid,
527 up->p_time / 60L, up->p_time % 60L,
528 up->p_comm);
529 }
530 up->p_state = VISITED;
531
532 /* descend for its children */
533 if (up->p_child) {
534 showproc(up->p_child);
535 for (zp = up->p_child->p_sibling; zp; zp = zp->p_sibling) {
536 showproc(zp);
537 }
538 }
539
540 /* print the pgrp relation */
541 if (up->p_pgrplink)
542 showproc(up->p_pgrplink);
543 }
544
545
546 /*
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2013 Gary Mills
23 *
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
30
31 /*
32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 * The Regents of the University of California
34 * All Rights Reserved
35 *
36 * University Acknowledgment- Portions of this document are derived from
37 * software developed by the University of California, Berkeley, and its
38 * contributors.
39 */
40
41 /*
42 * This is the new whodo command which takes advantage of
43 * the /proc interface to gain access to the information
53 #include <string.h>
54 #include <stdlib.h>
55 #include <ctype.h>
56 #include <fcntl.h>
57 #include <time.h>
58 #include <errno.h>
59 #include <sys/types.h>
60 #include <utmpx.h>
61 #include <sys/utsname.h>
62 #include <sys/stat.h>
63 #include <sys/mkdev.h>
64 #include <dirent.h>
65 #include <procfs.h> /* /proc header file */
66 #include <sys/wait.h>
67 #include <locale.h>
68 #include <unistd.h>
69 #include <limits.h>
70 #include <priv_utils.h>
71
72 /*
73 * Use the full lengths from utmpx for user and line.
74 */
75 #define NMAX (sizeof (((struct utmpx *)0)->ut_user))
76 #define LMAX (sizeof (((struct utmpx *)0)->ut_line))
77
78 /* Print minimum field widths. */
79 #define LOGIN_WIDTH 8
80 #define LINE_WIDTH 12
81
82 #define DIV60(t) ((t+30)/60) /* x/60 rounded */
83
84 #ifdef ERR
85 #undef ERR
86 #endif
87 #define ERR (-1)
88
89 #define DEVNAMELEN 14
90 #define HSIZE 256 /* size of process hash table */
91 #define PROCDIR "/proc"
92 #define INITPROCESS (pid_t)1 /* init process pid */
93 #define NONE 'n' /* no state */
94 #define RUNNING 'r' /* runnable process */
95 #define ZOMBIE 'z' /* zombie process */
96 #define VISITED 'v' /* marked node as visited */
97
98 static int ndevs; /* number of configured devices */
99 static int maxdev; /* slots for configured devices */
100 #define DNINCR 100
101 static struct devl { /* device list */
453
454 /* revert to non-privileged user */
455 (void) __priv_relinquish();
456
457 (void) closedir(dirp);
458 (void) time(&now); /* get current time */
459
460 /*
461 * loop through utmpx file, printing process info
462 * about each logged in user
463 */
464 for (ut = utmpbegin; ut < utmpend; ut++) {
465 time_t tim;
466
467 if (ut->ut_type != USER_PROCESS)
468 continue;
469 if (sel_user && strncmp(ut->ut_name, sel_user, NMAX) != 0)
470 continue; /* we're looking for somebody else */
471 if (lflag) { /* -l flag format (w command) */
472 /* print login name of the user */
473 (void) printf("%-*.*s ", LOGIN_WIDTH, (int)NMAX,
474 ut->ut_name);
475
476 /* print tty user is on */
477 (void) printf("%-*.*s", LINE_WIDTH, (int)LMAX,
478 ut->ut_line);
479
480 /* print when the user logged in */
481 tim = ut->ut_xtime;
482 (void) prtat(&tim);
483
484 /* print idle time */
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, " ");
491 showtotals(findhash((pid_t)ut->ut_pid));
492 } else { /* standard whodo format */
493 tim = ut->ut_xtime;
494 tm = localtime(&tim);
495 (void) printf("\n%-*.*s %-*.*s %2.1d:%2.2d\n",
496 LINE_WIDTH, (int)LMAX, ut->ut_line,
497 LOGIN_WIDTH, (int)NMAX, ut->ut_name, tm->tm_hour,
498 tm->tm_min);
499 showproc(findhash((pid_t)ut->ut_pid));
500 }
501 }
502
503 return (0);
504 }
505
506 /*
507 * Used for standard whodo format.
508 * This is the recursive routine descending the process
509 * tree starting from the given process pointer(up).
510 * It used depth-first search strategy and also marked
511 * each node as printed as it traversed down the tree.
512 */
513 static void
514 showproc(struct uproc *up)
515 {
516 struct uproc *zp;
517
518 if (up->p_state == VISITED) /* we already been here */
519 return;
520 /* print the data for this process */
521 if (up->p_state == ZOMBIE)
522 (void) printf(" %-*.*s %5d %4.1ld:%2.2ld %s\n",
523 LINE_WIDTH, (int)LMAX, " ?", (int)up->p_upid, 0L, 0L,
524 "<defunct>");
525 else if (up->p_state != NONE) {
526 (void) printf(" %-*.*s %5d %4.1ld:%2.2ld %s\n",
527 LINE_WIDTH, (int)LMAX, getty(up->p_ttyd), (int)up->p_upid,
528 up->p_time / 60L, up->p_time % 60L,
529 up->p_comm);
530 }
531 up->p_state = VISITED;
532
533 /* descend for its children */
534 if (up->p_child) {
535 showproc(up->p_child);
536 for (zp = up->p_child->p_sibling; zp; zp = zp->p_sibling) {
537 showproc(zp);
538 }
539 }
540
541 /* print the pgrp relation */
542 if (up->p_pgrplink)
543 showproc(up->p_pgrplink);
544 }
545
546
547 /*
|