xref: /netbsd-src/usr.bin/who/who.c (revision ae9172d6cd9432a6a1a56760d86b32c57a66c39c)
1 /*	$NetBSD: who.c,v 1.4 1994/12/07 04:28:49 jtc 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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #ifndef lint
40 static char copyright[] =
41 "@(#) Copyright (c) 1989, 1993\n\
42 	The Regents of the University of California.  All rights reserved.\n";
43 #endif /* not lint */
44 
45 #ifndef lint
46 #if 0
47 static char sccsid[] = "@(#)who.c	8.1 (Berkeley) 6/6/93";
48 #endif
49 static char rcsid[] = "$NetBSD: who.c,v 1.4 1994/12/07 04:28:49 jtc Exp $";
50 #endif /* not lint */
51 
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <pwd.h>
55 #include <utmp.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <stdlib.h>
59 #include <unistd.h>
60 #include <time.h>
61 #include <err.h>
62 
63 void output __P((struct utmp *));
64 void who_am_i __P((FILE *));
65 void usage __P((void));
66 int only_current_term;		/* show info about the current terminal only */
67 int show_term;			/* show term state */
68 int show_idle;			/* show idle time */
69 
70 int
71 main(argc, argv)
72 	int argc;
73 	char **argv;
74 {
75 	struct utmp usr;
76 	FILE *ufp, *file();
77 	int c;
78 
79 	while ((c = getopt(argc, argv, "mTu")) != -1) {
80 		switch (c) {
81 		case 'm':
82 			only_current_term = 1;
83 			break;
84 		case 'T':
85 			show_term = 1;
86 			break;
87 		case 'u':
88 			show_idle = 1;
89 			break;
90 		default:
91 			usage();
92 			/* NOTREACHED */
93 		}
94 	}
95 	argc -= optind;
96 	argv += optind;
97 
98 	if (chdir("/dev")) {
99 		err(1, "cannot change directory to /dev");
100 		/* NOTREACHED */
101 	}
102 
103 	switch (argc) {
104 	case 0:					/* who */
105 		ufp = file(_PATH_UTMP);
106 
107 		if (only_current_term) {
108 			who_am_i(ufp);
109 		} else {
110 			/* only entries with both name and line fields */
111 			while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
112 				if (*usr.ut_name && *usr.ut_line)
113 					output(&usr);
114 		}
115 		break;
116 	case 1:					/* who utmp_file */
117 		ufp = file(*argv);
118 
119 		if (only_current_term) {
120 			who_am_i(ufp);
121 		} else {
122 			/* all entries */
123 			while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
124 				output(&usr);
125 		}
126 		break;
127 	case 2:					/* who am i */
128 		ufp = file(_PATH_UTMP);
129 		who_am_i(ufp);
130 		break;
131 	default:
132 		usage();
133 		/* NOTREACHED */
134 	}
135 	exit(0);
136 }
137 
138 void
139 who_am_i(ufp)
140 	FILE *ufp;
141 {
142 	struct utmp usr;
143 	struct passwd *pw;
144 	register char *p;
145 	char *t;
146 
147 	/* search through the utmp and find an entry for this tty */
148 	if (p = ttyname(0)) {
149 		/* strip any directory component */
150 		if (t = rindex(p, '/'))
151 			p = t + 1;
152 		while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
153 			if (usr.ut_name && !strcmp(usr.ut_line, p)) {
154 				output(&usr);
155 				return;
156 			}
157 		/* well, at least we know what the tty is */
158 		(void)strncpy(usr.ut_line, p, UT_LINESIZE);
159 	} else
160 		(void)strcpy(usr.ut_line, "tty??");
161 
162 	pw = getpwuid(getuid());
163 	(void)strncpy(usr.ut_name, pw ? pw->pw_name : "?", UT_NAMESIZE);
164 	(void)time(&usr.ut_time);
165 	*usr.ut_host = '\0';
166 	output(&usr);
167 }
168 
169 void
170 output(up)
171 	struct utmp *up;
172 {
173 	struct stat sb;
174 	char line[sizeof (up->ut_line) + 1];
175 	char state;
176 	static time_t now = 0;
177 	time_t idle;
178 
179 	if (show_term || show_idle) {
180 		if (now == 0)
181 			time(&now);
182 
183 		strncpy (line, up->ut_line, sizeof (up->ut_line));
184 		line[sizeof (up->ut_line)] = '\0';
185 
186 		if (stat(line, &sb) == 0) {
187 			state = (sb.st_mode & 020) ? '+' : '-';
188 			idle = now - sb.st_atime;
189 		} else {
190 			state = '?';
191 			idle = 0;
192 		}
193 
194 	}
195 
196 	(void)printf("%-*.*s ", UT_NAMESIZE, UT_NAMESIZE, up->ut_name);
197 
198 	if (show_term) {
199 		(void)printf("%c ", state);
200 	}
201 
202 	(void)printf("%-*.*s ", UT_LINESIZE, UT_LINESIZE, up->ut_line);
203 	(void)printf("%.12s ", ctime(&up->ut_time) + 4);
204 
205 	if (show_idle) {
206 		if (idle < 60)
207 			(void)printf("  .   ");
208 		else if (idle < (24 * 60 * 60))
209 			(void)printf("%02d:%02d ",
210 				     (idle / (60 * 60)),
211 				     (idle % (60 * 60)) / 60);
212 		else
213 			(void)printf(" old  ");
214 	}
215 
216 	if (*up->ut_host)
217 		printf("\t(%.*s)", UT_HOSTSIZE, up->ut_host);
218 	(void)putchar('\n');
219 }
220 
221 FILE *
222 file(name)
223 	char *name;
224 {
225 	FILE *ufp;
226 
227 	if (!(ufp = fopen(name, "r"))) {
228 		err(1, "%s", name);
229 		/* NOTREACHED */
230 	}
231 	return(ufp);
232 }
233 
234 void
235 usage()
236 {
237 	(void)fprintf(stderr, "usage: who [-mTu] [ file ]\n       who am i\n");
238 	exit(1);
239 }
240