Annotation of src/usr.bin/who/who.c, Revision 1.20
1.20 ! guenther 1: /* $OpenBSD: who.c,v 1.19 2010/11/15 10:57:49 otto 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: #include <sys/types.h>
37: #include <sys/stat.h>
1.9 millert 38: #include <paths.h>
1.1 deraadt 39: #include <pwd.h>
40: #include <utmp.h>
41: #include <stdio.h>
42: #include <string.h>
43: #include <stdlib.h>
44: #include <unistd.h>
45: #include <time.h>
46: #include <err.h>
1.5 flipk 47: #include <locale.h>
48:
1.12 millert 49: void output(struct utmp *);
50: void output_labels(void);
51: void who_am_i(FILE *);
52: void usage(void);
53: FILE *file(char *);
1.1 deraadt 54:
55: int only_current_term; /* show info about the current terminal only */
56: int show_term; /* show term state */
57: int show_idle; /* show idle time */
1.5 flipk 58: int show_labels; /* show column labels */
1.6 denny 59: int show_quick; /* quick, names only */
1.1 deraadt 60:
1.10 deraadt 61: #define NAME_WIDTH 8
1.19 otto 62: #define HOST_WIDTH 45
63:
64: int hostwidth = HOST_WIDTH;
1.10 deraadt 65:
1.1 deraadt 66: int
1.16 deraadt 67: main(int argc, char *argv[])
1.1 deraadt 68: {
69: struct utmp usr;
1.5 flipk 70: FILE *ufp;
1.1 deraadt 71: int c;
72:
1.5 flipk 73: setlocale(LC_ALL, "");
74:
75: only_current_term = show_term = show_idle = show_labels = 0;
1.6 denny 76: show_quick = 0;
77: while ((c = getopt(argc, argv, "HmqTu")) != -1) {
1.1 deraadt 78: switch (c) {
1.6 denny 79: case 'H':
80: show_labels = 1;
81: break;
1.1 deraadt 82: case 'm':
83: only_current_term = 1;
84: break;
1.6 denny 85: case 'q':
86: show_quick = 1;
87: break;
1.1 deraadt 88: case 'T':
89: show_term = 1;
90: break;
91: case 'u':
92: show_idle = 1;
93: break;
94: default:
95: usage();
96: /* NOTREACHED */
97: }
98: }
99: argc -= optind;
100: argv += optind;
101:
1.6 denny 102: if (show_quick) {
103: only_current_term = show_term = show_idle = show_labels = 0;
104: }
1.19 otto 105:
106: if (show_term)
107: hostwidth -= 2;
108: if (show_idle)
109: hostwidth -= 6;
1.6 denny 110:
1.5 flipk 111: if (show_labels)
112: output_labels();
113:
1.1 deraadt 114: switch (argc) {
115: case 0: /* who */
116: ufp = file(_PATH_UTMP);
117:
118: if (only_current_term) {
119: who_am_i(ufp);
1.6 denny 120: } else if (show_quick) {
121: int count = 0;
122:
123: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) {
124: if (*usr.ut_name && *usr.ut_line) {
1.10 deraadt 125: (void)printf("%-*.*s ", NAME_WIDTH,
1.6 denny 126: UT_NAMESIZE, usr.ut_name);
127: if ((++count % 8) == 0)
128: (void) printf("\n");
129: }
130: }
131: if (count % 8)
132: (void) printf("\n");
133: (void) printf ("# users=%d\n", count);
1.1 deraadt 134: } else {
135: /* only entries with both name and line fields */
136: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
137: if (*usr.ut_name && *usr.ut_line)
138: output(&usr);
139: }
140: break;
141: case 1: /* who utmp_file */
142: ufp = file(*argv);
143:
144: if (only_current_term) {
145: who_am_i(ufp);
1.6 denny 146: } else if (show_quick) {
147: int count = 0;
148:
149: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) {
150: if (*usr.ut_name && *usr.ut_line) {
1.10 deraadt 151: (void)printf("%-*.*s ", NAME_WIDTH,
1.6 denny 152: UT_NAMESIZE, usr.ut_name);
153: if ((++count % 8) == 0)
154: (void) printf("\n");
155: }
156: }
157: if (count % 8)
158: (void) printf("\n");
159: (void) printf ("# users=%d\n", count);
1.1 deraadt 160: } else {
161: /* all entries */
162: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
163: output(&usr);
164: }
165: break;
166: case 2: /* who am i */
167: ufp = file(_PATH_UTMP);
168: who_am_i(ufp);
169: break;
170: default:
171: usage();
172: /* NOTREACHED */
173: }
174: exit(0);
175: }
176:
177: void
1.16 deraadt 178: who_am_i(FILE *ufp)
1.1 deraadt 179: {
180: struct utmp usr;
181: struct passwd *pw;
1.11 mpech 182: char *p;
1.1 deraadt 183: char *t;
184:
185: /* search through the utmp and find an entry for this tty */
1.5 flipk 186: if ((p = ttyname(0))) {
1.1 deraadt 187: /* strip any directory component */
1.5 flipk 188: if ((t = strrchr(p, '/')))
1.1 deraadt 189: p = t + 1;
190: while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
1.4 deraadt 191: if (*usr.ut_name && !strcmp(usr.ut_line, p)) {
1.1 deraadt 192: output(&usr);
193: return;
194: }
195: /* well, at least we know what the tty is */
196: (void)strncpy(usr.ut_line, p, UT_LINESIZE);
197: } else
1.13 deraadt 198: (void)strncpy(usr.ut_line, "tty??", UT_LINESIZE);
1.1 deraadt 199:
200: pw = getpwuid(getuid());
201: (void)strncpy(usr.ut_name, pw ? pw->pw_name : "?", UT_NAMESIZE);
202: (void)time(&usr.ut_time);
203: *usr.ut_host = '\0';
204: output(&usr);
205: }
206:
207: void
1.16 deraadt 208: output(struct utmp *up)
1.1 deraadt 209: {
210: struct stat sb;
1.9 millert 211: char line[sizeof(_PATH_DEV) + sizeof (up->ut_line)];
1.5 flipk 212: char state = '?';
1.1 deraadt 213: static time_t now = 0;
1.5 flipk 214: time_t idle = 0;
1.1 deraadt 215:
216: if (show_term || show_idle) {
217: if (now == 0)
218: time(&now);
219:
1.14 deraadt 220: memset(line, 0, sizeof line);
221: strlcpy(line, _PATH_DEV, sizeof line);
222: strlcat(line, up->ut_line, sizeof line);
1.1 deraadt 223:
224: if (stat(line, &sb) == 0) {
225: state = (sb.st_mode & 020) ? '+' : '-';
226: idle = now - sb.st_atime;
227: } else {
228: state = '?';
229: idle = 0;
230: }
231:
232: }
233:
1.10 deraadt 234: (void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, up->ut_name);
1.1 deraadt 235:
236: if (show_term) {
237: (void)printf("%c ", state);
238: }
239:
240: (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, up->ut_line);
241: (void)printf("%.12s ", ctime(&up->ut_time) + 4);
242:
243: if (show_idle) {
244: if (idle < 60)
245: (void)printf(" . ");
246: else if (idle < (24 * 60 * 60))
247: (void)printf("%02d:%02d ",
1.20 ! guenther 248: ((int)idle / (60 * 60)),
! 249: ((int)idle % (60 * 60)) / 60);
1.1 deraadt 250: else
251: (void)printf(" old ");
252: }
253:
254: if (*up->ut_host)
1.19 otto 255: printf(" (%.*s)", hostwidth, up->ut_host);
1.1 deraadt 256: (void)putchar('\n');
257: }
258:
1.5 flipk 259: void
1.16 deraadt 260: output_labels(void)
1.5 flipk 261: {
1.10 deraadt 262: (void)printf("%-*.*s ", NAME_WIDTH, UT_NAMESIZE, "USER");
1.5 flipk 263:
264: if (show_term)
265: (void)printf("S ");
266:
267: (void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, "LINE");
268: (void)printf("WHEN ");
269:
270: if (show_idle)
271: (void)printf("IDLE ");
272:
1.19 otto 273: (void)printf(" %.*s", hostwidth, "FROM");
1.5 flipk 274:
275: (void)putchar('\n');
276: }
277:
1.1 deraadt 278: FILE *
1.16 deraadt 279: file(char *name)
1.1 deraadt 280: {
281: FILE *ufp;
282:
283: if (!(ufp = fopen(name, "r"))) {
284: err(1, "%s", name);
285: /* NOTREACHED */
286: }
287: return(ufp);
288: }
289:
290: void
1.16 deraadt 291: usage(void)
1.1 deraadt 292: {
1.17 jmc 293: (void)fprintf(stderr, "usage: who [-HmqTu] [file]\n who am i\n");
1.1 deraadt 294: exit(1);
295: }