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