who.c revision 1.14 1 /* $NetBSD: who.c,v 1.14 2004/11/22 17:20:02 peter Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Michael Fischbein.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 __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
46 __RCSID("$NetBSD: who.c,v 1.14 2004/11/22 17:20:02 peter Exp $");
47 #endif /* not lint */
48
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <err.h>
52 #include <locale.h>
53 #include <pwd.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <time.h>
58 #include <unistd.h>
59 #include "utmpentry.h"
60
61 static void output_labels(void);
62 static void who_am_i(const char *, int);
63 static void usage(void);
64 static void process(const char *, int);
65 static void print(const char *, const char *, time_t, const char *);
66
67 int main(int, char **);
68
69 static int show_term; /* show term state */
70 static int show_idle; /* show idle time */
71
72 extern int maxname, maxline, maxhost;
73
74 int
75 main(int argc, char **argv)
76 {
77 int c, only_current_term, show_labels;
78
79 setlocale(LC_ALL, "");
80
81 only_current_term = show_term = show_idle = show_labels = 0;
82 while ((c = getopt(argc, argv, "HmTu")) != -1) {
83 switch (c) {
84 case 'H':
85 show_labels = 1;
86 break;
87 case 'm':
88 only_current_term = 1;
89 break;
90 case 'T':
91 show_term = 1;
92 break;
93 case 'u':
94 show_idle = 1;
95 break;
96 default:
97 usage();
98 /* NOTREACHED */
99 }
100 }
101 argc -= optind;
102 argv += optind;
103
104 if (chdir("/dev")) {
105 err(1, "cannot change directory to /dev");
106 /* NOTREACHED */
107 }
108
109 switch (argc) {
110 case 0: /* who */
111 if (only_current_term) {
112 who_am_i(NULL, show_labels);
113 } else {
114 process(NULL, show_labels);
115 }
116 break;
117 case 1: /* who utmp_file */
118 if (only_current_term) {
119 who_am_i(*argv, show_labels);
120 } else {
121 process(*argv, show_labels);
122 }
123 break;
124 case 2: /* who am i */
125 who_am_i(NULL, show_labels);
126 break;
127 default:
128 usage();
129 /* NOTREACHED */
130 }
131 exit(0);
132 }
133
134 static void
135 who_am_i(const char *fname, int show_labels)
136 {
137 struct passwd *pw;
138 char *p;
139 char *t;
140 time_t now;
141 struct utmpentry *ehead, *ep;
142
143 /* search through the utmp and find an entry for this tty */
144 if ((p = ttyname(STDIN_FILENO)) != NULL) {
145
146 /* strip any directory component */
147 if ((t = strrchr(p, '/')) != NULL)
148 p = t + 1;
149
150 (void)getutentries(fname, &ehead);
151 for (ep = ehead; ep; ep = ep->next)
152 if (strcmp(ep->line, p) == 0) {
153 if (show_labels)
154 output_labels();
155 print(ep->name, ep->line, (time_t)ep->tv.tv_sec,
156 ep->host);
157 return;
158 }
159 } else
160 p = "tty??";
161
162 (void)time(&now);
163 pw = getpwuid(getuid());
164 if (show_labels)
165 output_labels();
166 print(pw ? pw->pw_name : "?", p, now, "");
167 }
168
169 static void
170 process(const char *fname, int show_labels)
171 {
172 struct utmpentry *ehead, *ep;
173 (void)getutentries(fname, &ehead);
174 if (show_labels)
175 output_labels();
176 for (ep = ehead; ep != NULL; ep = ep->next)
177 print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host);
178 }
179
180 static void
181 print(const char *name, const char *line, time_t t, const char *host)
182 {
183 struct stat sb;
184 char state;
185 static time_t now = 0;
186 time_t idle;
187
188 state = '?';
189 idle = 0;
190
191 if (show_term || show_idle) {
192 if (now == 0)
193 time(&now);
194
195 if (stat(line, &sb) == 0) {
196 state = (sb.st_mode & 020) ? '+' : '-';
197 idle = now - sb.st_atime;
198 }
199
200 }
201
202 (void)printf("%-*.*s ", maxname, maxname, name);
203
204 if (show_term) {
205 (void)printf("%c ", state);
206 }
207
208 (void)printf("%-*.*s ", maxline, maxline, line);
209 (void)printf("%.12s ", ctime(&t) + 4);
210
211 if (show_idle) {
212 if (idle < 60)
213 (void)printf(" . ");
214 else if (idle < (24 * 60 * 60))
215 (void)printf("%02ld:%02ld ",
216 (long)(idle / (60 * 60)),
217 (long)(idle % (60 * 60)) / 60);
218 else
219 (void)printf(" old ");
220 }
221
222 if (*host)
223 printf("\t(%.*s)", maxhost, host);
224 (void)putchar('\n');
225 }
226
227 static void
228 output_labels()
229 {
230 (void)printf("%-*.*s ", maxname, maxname, "USER");
231
232 if (show_term)
233 (void)printf("S ");
234
235 (void)printf("%-*.*s ", maxline, maxline, "LINE");
236 (void)printf("WHEN ");
237
238 if (show_idle)
239 (void)printf("IDLE ");
240
241 (void)printf("\t%.*s", maxhost, "FROM");
242
243 (void)putchar('\n');
244 }
245
246 static void
247 usage()
248 {
249 (void)fprintf(stderr, "usage: %s [-HmTu] [file]\n %s am i\n",
250 getprogname(), getprogname());
251 exit(1);
252 }
253