Annotation of src/usr.bin/who/who.c, Revision 1.6
1.6 ! denny 1: /* $OpenBSD: who.c,v 1.5 1997/07/28 17:38:53 flipk Exp $ */
1.1 deraadt 2: /* $NetBSD: who.c,v 1.4 1994/12/07 04:28:49 jtc Exp $ */
3:
4: /*
5: * Copyright (c) 1989, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Michael Fischbein.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the University of
22: * California, Berkeley and its contributors.
23: * 4. Neither the name of the University nor the names of its contributors
24: * may be used to endorse or promote products derived from this software
25: * without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37: * SUCH DAMAGE.
38: */
39:
40: #ifndef lint
41: static char copyright[] =
42: "@(#) Copyright (c) 1989, 1993\n\
43: The Regents of the University of California. All rights reserved.\n";
44: #endif /* not lint */
45:
46: #ifndef lint
47: #if 0
48: static char sccsid[] = "@(#)who.c 8.1 (Berkeley) 6/6/93";
49: #endif
1.6 ! denny 50: static char rcsid[] = "$OpenBSD: who.c,v 1.5 1997/07/28 17:38:53 flipk Exp $";
1.1 deraadt 51: #endif /* not lint */
52:
53: #include <sys/types.h>
54: #include <sys/stat.h>
55: #include <pwd.h>
56: #include <utmp.h>
57: #include <stdio.h>
58: #include <string.h>
59: #include <stdlib.h>
60: #include <unistd.h>
61: #include <time.h>
62: #include <err.h>
1.5 flipk 63: #include <locale.h>
64:
65: void output __P((struct utmp *));
66: void output_labels __P((void));
67: void who_am_i __P((FILE *));
68: void usage __P((void));
69: FILE *file __P((char *));
1.1 deraadt 70:
71: int only_current_term; /* show info about the current terminal only */
72: int show_term; /* show term state */
73: int show_idle; /* show idle time */
1.5 flipk 74: int show_labels; /* show column labels */
1.6 ! denny 75: int show_quick; /* quick, names only */
1.1 deraadt 76:
77: int
78: main(argc, argv)
79: int argc;
80: char **argv;
81: {
82: struct utmp usr;
1.5 flipk 83: FILE *ufp;
1.1 deraadt 84: int c;
85:
1.5 flipk 86: setlocale(LC_ALL, "");
87:
88: only_current_term = show_term = show_idle = show_labels = 0;
1.6 ! denny 89: show_quick = 0;
! 90: while ((c = getopt(argc, argv, "HmqTu")) != -1) {
1.1 deraadt 91: switch (c) {
1.6 ! denny 92: case 'H':
! 93: show_labels = 1;
! 94: break;
1.1 deraadt 95: case 'm':
96: only_current_term = 1;
97: break;
1.6 ! denny 98: case 'q':
! 99: show_quick = 1;
! 100: break;
1.1 deraadt 101: case 'T':
102: show_term = 1;
103: break;
104: case 'u':
105: show_idle = 1;
106: break;
107: default:
108: usage();
109: /* NOTREACHED */
110: }
111: }
112: argc -= optind;
113: argv += optind;
114:
1.6 ! denny 115: if (show_quick) {
! 116: only_current_term = show_term = show_idle = show_labels = 0;
! 117: }
! 118:
1.1 deraadt 119: if (chdir("/dev")) {
120: err(1, "cannot change directory to /dev");
121: /* NOTREACHED */
122: }
123:
1.5 flipk 124: if (show_labels)
125: output_labels();
126:
1.1 deraadt 127: switch (argc) {
128: case 0: /* who */
129: ufp = file(_PATH_UTMP);
130:
131: if (only_current_term) {
132: who_am_i(ufp);
1.6 ! denny 133: } else if (show_quick) {
! 134: int count = 0;
! 135:
! 136: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) {
! 137: if (*usr.ut_name && *usr.ut_line) {
! 138: (void)printf("%-*.*s ", UT_NAMESIZE,
! 139: UT_NAMESIZE, usr.ut_name);
! 140: if ((++count % 8) == 0)
! 141: (void) printf("\n");
! 142: }
! 143: }
! 144: if (count % 8)
! 145: (void) printf("\n");
! 146: (void) printf ("# users=%d\n", count);
1.1 deraadt 147: } else {
148: /* only entries with both name and line fields */
149: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
150: if (*usr.ut_name && *usr.ut_line)
151: output(&usr);
152: }
153: break;
154: case 1: /* who utmp_file */
155: ufp = file(*argv);
156:
157: if (only_current_term) {
158: who_am_i(ufp);
1.6 ! denny 159: } else if (show_quick) {
! 160: int count = 0;
! 161:
! 162: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) {
! 163: if (*usr.ut_name && *usr.ut_line) {
! 164: (void)printf("%-*.*s ", UT_NAMESIZE,
! 165: UT_NAMESIZE, usr.ut_name);
! 166: if ((++count % 8) == 0)
! 167: (void) printf("\n");
! 168: }
! 169: }
! 170: if (count % 8)
! 171: (void) printf("\n");
! 172: (void) printf ("# users=%d\n", count);
1.1 deraadt 173: } else {
174: /* all entries */
175: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
176: output(&usr);
177: }
178: break;
179: case 2: /* who am i */
180: ufp = file(_PATH_UTMP);
181: who_am_i(ufp);
182: break;
183: default:
184: usage();
185: /* NOTREACHED */
186: }
187: exit(0);
188: }
189:
190: void
191: who_am_i(ufp)
192: FILE *ufp;
193: {
194: struct utmp usr;
195: struct passwd *pw;
196: register char *p;
197: char *t;
198:
199: /* search through the utmp and find an entry for this tty */
1.5 flipk 200: if ((p = ttyname(0))) {
1.1 deraadt 201: /* strip any directory component */
1.5 flipk 202: if ((t = strrchr(p, '/')))
1.1 deraadt 203: p = t + 1;
204: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
1.4 deraadt 205: if (*usr.ut_name && !strcmp(usr.ut_line, p)) {
1.1 deraadt 206: output(&usr);
207: return;
208: }
209: /* well, at least we know what the tty is */
210: (void)strncpy(usr.ut_line, p, UT_LINESIZE);
211: } else
212: (void)strcpy(usr.ut_line, "tty??");
213:
214: pw = getpwuid(getuid());
215: (void)strncpy(usr.ut_name, pw ? pw->pw_name : "?", UT_NAMESIZE);
216: (void)time(&usr.ut_time);
217: *usr.ut_host = '\0';
218: output(&usr);
219: }
220:
221: void
222: output(up)
223: struct utmp *up;
224: {
225: struct stat sb;
226: char line[sizeof (up->ut_line) + 1];
1.5 flipk 227: char state = '?';
1.1 deraadt 228: static time_t now = 0;
1.5 flipk 229: time_t idle = 0;
1.1 deraadt 230:
231: if (show_term || show_idle) {
232: if (now == 0)
233: time(&now);
234:
235: strncpy (line, up->ut_line, sizeof (up->ut_line));
236: line[sizeof (up->ut_line)] = '\0';
237:
238: if (stat(line, &sb) == 0) {
239: state = (sb.st_mode & 020) ? '+' : '-';
240: idle = now - sb.st_atime;
241: } else {
242: state = '?';
243: idle = 0;
244: }
245:
246: }
247:
248: (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, up->ut_name);
249:
250: if (show_term) {
251: (void)printf("%c ", state);
252: }
253:
254: (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, up->ut_line);
255: (void)printf("%.12s ", ctime(&up->ut_time) + 4);
256:
257: if (show_idle) {
258: if (idle < 60)
259: (void)printf(" . ");
260: else if (idle < (24 * 60 * 60))
261: (void)printf("%02d:%02d ",
262: (idle / (60 * 60)),
263: (idle % (60 * 60)) / 60);
264: else
265: (void)printf(" old ");
266: }
267:
268: if (*up->ut_host)
269: printf("\t(%.*s)", UT_HOSTSIZE, up->ut_host);
270: (void)putchar('\n');
271: }
272:
1.5 flipk 273: void
274: output_labels()
275: {
276: (void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, "USER");
277:
278: if (show_term)
279: (void)printf("S ");
280:
281: (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, "LINE");
282: (void)printf("WHEN ");
283:
284: if (show_idle)
285: (void)printf("IDLE ");
286:
287: (void)printf("\t%.*s", UT_HOSTSIZE, "FROM");
288:
289: (void)putchar('\n');
290: }
291:
1.1 deraadt 292: FILE *
293: file(name)
294: char *name;
295: {
296: FILE *ufp;
297:
298: if (!(ufp = fopen(name, "r"))) {
299: err(1, "%s", name);
300: /* NOTREACHED */
301: }
302: return(ufp);
303: }
304:
305: void
306: usage()
307: {
1.6 ! denny 308: (void)fprintf(stderr, "usage: who [-mqTuH] [ file ]\n who am i\n");
1.1 deraadt 309: exit(1);
310: }