xref: /netbsd/usr.bin/rwho/rwho.c (revision 37e1a874)
1*37e1a874Slukem /*	$NetBSD: rwho.c,v 1.19 2009/04/13 07:11:37 lukem Exp $	*/
282920474Stls 
3e541169cScgd /*
482920474Stls  * Copyright (c) 1983, 1993
582920474Stls  *	The Regents of the University of California.  All rights reserved.
6e541169cScgd  *
7e541169cScgd  * Redistribution and use in source and binary forms, with or without
8e541169cScgd  * modification, are permitted provided that the following conditions
9e541169cScgd  * are met:
10e541169cScgd  * 1. Redistributions of source code must retain the above copyright
11e541169cScgd  *    notice, this list of conditions and the following disclaimer.
12e541169cScgd  * 2. Redistributions in binary form must reproduce the above copyright
13e541169cScgd  *    notice, this list of conditions and the following disclaimer in the
14e541169cScgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
16e541169cScgd  *    may be used to endorse or promote products derived from this software
17e541169cScgd  *    without specific prior written permission.
18e541169cScgd  *
19e541169cScgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20e541169cScgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21e541169cScgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22e541169cScgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23e541169cScgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24e541169cScgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25e541169cScgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26e541169cScgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27e541169cScgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28e541169cScgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29e541169cScgd  * SUCH DAMAGE.
30e541169cScgd  */
31e541169cScgd 
3256825985Slukem #include <sys/cdefs.h>
33e541169cScgd #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
3598e5374cSlukem  The Regents of the University of California.  All rights reserved.");
36e541169cScgd #endif /* not lint */
37e541169cScgd 
38e541169cScgd #ifndef lint
3982920474Stls /*static char sccsid[] = "from: @(#)rwho.c	8.1 (Berkeley) 6/6/93";*/
40*37e1a874Slukem __RCSID("$NetBSD: rwho.c,v 1.19 2009/04/13 07:11:37 lukem Exp $");
41e541169cScgd #endif /* not lint */
42e541169cScgd 
43e541169cScgd #include <sys/param.h>
44e541169cScgd #include <sys/file.h>
4557417153Smrg 
46e541169cScgd #include <protocols/rwhod.h>
4757417153Smrg 
4857417153Smrg #include <dirent.h>
4957417153Smrg #include <err.h>
50f40dea57Smjl #include <locale.h>
51e541169cScgd #include <stdio.h>
5257417153Smrg #include <stdlib.h>
5332411917Scgd #include <string.h>
540a87884eSkleink #include <time.h>
55377fe973Schristos #include <fcntl.h>
5657417153Smrg #include <unistd.h>
57ae3dca21Schristos #include <utmp.h>
58ae3dca21Schristos #include <sysexits.h>
59e541169cScgd 
608b0f9554Sperry static void usage(void) __dead;
61ae3dca21Schristos static int utmpcmp(const void *, const void *);
62f40dea57Smjl 
63e541169cScgd /*
64e541169cScgd  * this macro should be shared with ruptime.
65e541169cScgd  */
66ae3dca21Schristos #define	DOWN(w,now)	((now) - (w).wd_recvtime > 11 * 60)
67ae3dca21Schristos #define WHDRSIZE	(sizeof(struct whod) - \
68ae3dca21Schristos     sizeof (((struct whod *)NULL)->wd_we))
69e541169cScgd 
70ae3dca21Schristos struct	my_utmp {
71ae3dca21Schristos 	char	myhost[MAXHOSTNAMELEN];
72ae3dca21Schristos 	int	myidle;
73ae3dca21Schristos 	struct	outmp myutmp;
74ae3dca21Schristos };
75e541169cScgd 
7657417153Smrg int
main(int argc,char ** argv)77f40dea57Smjl main(int argc, char **argv)
78e541169cScgd {
79ae3dca21Schristos 	DIR *dirp;
80a3881ff7Sjtc 	struct dirent *dp;
8156825985Slukem 	struct whoent *we;
82ae3dca21Schristos 	struct whod wd;
83ae3dca21Schristos 	struct my_utmp *mp, *start;
84ae3dca21Schristos 	time_t now;
85ae3dca21Schristos 	int ch;
86ae3dca21Schristos 	size_t width, n, i, nhosts, nusers, namount;
87ae3dca21Schristos 	int aflg, qflg, hflg;
88e541169cScgd 
89ae3dca21Schristos 	setprogname(argv[0]);
90ae3dca21Schristos 	(void)setlocale(LC_TIME, "");
91ae3dca21Schristos 	aflg = nusers = nhosts = qflg = hflg = 0;
92ae3dca21Schristos 	namount = 40;
93ae3dca21Schristos 	start = NULL;
94ae3dca21Schristos 	now = 0;
95f40dea57Smjl 
96ae3dca21Schristos 	while ((ch = getopt(argc, argv, "aHq")) != -1)
97ae3dca21Schristos 		switch(ch) {
98e541169cScgd 		case 'a':
99e541169cScgd 			aflg = 1;
100e541169cScgd 			break;
101ae3dca21Schristos 		case 'q':
102ae3dca21Schristos 			qflg = 1;
103ae3dca21Schristos 			break;
104ae3dca21Schristos 		case 'H':
105ae3dca21Schristos 			hflg = 1;
106ae3dca21Schristos 			break;
107e541169cScgd 		default:
108f40dea57Smjl 			usage();
109e541169cScgd 		}
110f40dea57Smjl 
111f40dea57Smjl 	if(optind != argc)
112f40dea57Smjl 		usage();
113f40dea57Smjl 
114ae3dca21Schristos 	if (qflg) {
115ae3dca21Schristos 		aflg = 0;
116ae3dca21Schristos 		hflg = 0;
117ae3dca21Schristos 	}
118f40dea57Smjl 
119ae3dca21Schristos 	if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
120ae3dca21Schristos 		err(EXIT_FAILURE, "Cannot access `%s'", _PATH_RWHODIR);
121ae3dca21Schristos 
122e541169cScgd 	(void)time(&now);
123ae3dca21Schristos 
124ae3dca21Schristos 	if ((start = malloc(sizeof(*start) * namount)) == NULL)
125ae3dca21Schristos 		err(EXIT_FAILURE, "malloc");
126ae3dca21Schristos 
12757417153Smrg 	while ((dp = readdir(dirp)) != NULL) {
128ae3dca21Schristos 		int f;
129ae3dca21Schristos 		ssize_t cc;
130ae3dca21Schristos 
131e541169cScgd 		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
132e541169cScgd 			continue;
133ae3dca21Schristos 
134e541169cScgd 		f = open(dp->d_name, O_RDONLY);
135e541169cScgd 		if (f < 0)
136e541169cScgd 			continue;
137ae3dca21Schristos 		cc = read(f, &wd, sizeof (wd));
138*37e1a874Slukem 		if (cc < (ssize_t)WHDRSIZE) {
139e541169cScgd 			(void)close(f);
140e541169cScgd 			continue;
141e541169cScgd 		}
142d1572422Scgd 		nhosts++;
143ae3dca21Schristos 		if (DOWN(wd, now)) {
144e541169cScgd 			(void)close(f);
145e541169cScgd 			continue;
146e541169cScgd 		}
147e541169cScgd 		cc -= WHDRSIZE;
148ae3dca21Schristos 		we = wd.wd_we;
149e541169cScgd 		for (n = cc / sizeof (struct whoent); n > 0; n--) {
150e541169cScgd 			if (aflg == 0 && we->we_idle >= 60*60) {
151e541169cScgd 				we++;
152e541169cScgd 				continue;
153e541169cScgd 			}
154f40dea57Smjl 
155ae3dca21Schristos 			if (nusers == namount) {
156ae3dca21Schristos 				namount = namount + 40;
157ae3dca21Schristos 				if ((start = realloc(start,
158ae3dca21Schristos 				    sizeof(struct my_utmp) * namount)) == NULL)
159ae3dca21Schristos 					err(1, "realloc");
160ae3dca21Schristos 			}
161ae3dca21Schristos 
162ae3dca21Schristos 			mp = start + nusers;
163ae3dca21Schristos 
164ae3dca21Schristos 			mp->myutmp = we->we_utmp;
165ae3dca21Schristos 			mp->myidle = we->we_idle;
166ae3dca21Schristos 			(void)strcpy(mp->myhost, wd.wd_hostname);
167e541169cScgd 			nusers++; we++; mp++;
168e541169cScgd 		}
169e541169cScgd 		(void)close(f);
170e541169cScgd 	}
171ae3dca21Schristos 
172d1572422Scgd 	if (nhosts == 0)
173ae3dca21Schristos 		errx(EX_OK, "No hosts in `%s'.", _PATH_RWHODIR);
174ae3dca21Schristos 
175ae3dca21Schristos 	mp = start;
176ae3dca21Schristos 	qsort(start, nusers, sizeof(*start), utmpcmp);
177e541169cScgd 	width = 0;
178e541169cScgd 	for (i = 0; i < nusers; i++) {
179ae3dca21Schristos 		size_t j = strlen(mp->myhost) + 1 + strlen(mp->myutmp.out_line);
180e541169cScgd 		if (j > width)
181e541169cScgd 			width = j;
182e541169cScgd 		mp++;
183e541169cScgd 	}
184ae3dca21Schristos 	mp = start;
185ae3dca21Schristos 	if (hflg) {
186ae3dca21Schristos 		(void)printf("%-*.*s %-*s %-12s %-*s\n", UT_NAMESIZE,
187ae3dca21Schristos 		    UT_NAMESIZE, "USER", (int)width, "LINE", "WHEN",
188ae3dca21Schristos 		    (int)width, "IDLE");
189ae3dca21Schristos 	}
190e541169cScgd 	for (i = 0; i < nusers; i++) {
191f40dea57Smjl 		char buf[BUFSIZ], cbuf[80];
192ae3dca21Schristos 		time_t t;
193ae3dca21Schristos 
194ae3dca21Schristos 		if (qflg) {
195ae3dca21Schristos 			(void)printf("%-*.*s\n", UT_NAMESIZE, UT_NAMESIZE,
196ae3dca21Schristos 			    mp->myutmp.out_name);
197ae3dca21Schristos 			mp++;
198ae3dca21Schristos 			continue;
199ae3dca21Schristos 		}
200ae3dca21Schristos 		t = mp->myutmp.out_time;
201ae3dca21Schristos 		(void)strftime(cbuf, sizeof(cbuf), "%c", localtime(&t));
202ae3dca21Schristos 		(void)snprintf(buf, sizeof(buf), "%s:%s", mp->myhost,
203ae3dca21Schristos 		    mp->myutmp.out_line);
204ae3dca21Schristos 		(void)printf("%-*.*s %-*s %.12s", UT_NAMESIZE, UT_NAMESIZE,
205ae3dca21Schristos 		    mp->myutmp.out_name, (int)width, buf, cbuf + 4);
206e541169cScgd 		mp->myidle /= 60;
207e541169cScgd 		if (mp->myidle) {
208e541169cScgd 			if (aflg) {
209e541169cScgd 				if (mp->myidle >= 100 * 60)
210e541169cScgd 					mp->myidle = 100 * 60 - 1;
211e541169cScgd 				if (mp->myidle >= 60)
212ae3dca21Schristos 					(void)printf(" %2d", mp->myidle / 60);
213e541169cScgd 				else
214ae3dca21Schristos 					(void)printf("   ");
215e541169cScgd 			} else
216ae3dca21Schristos 				(void)printf(" ");
217ae3dca21Schristos 			(void)printf(":%02d", mp->myidle % 60);
218e541169cScgd 		}
219ae3dca21Schristos 		(void)printf("\n");
220e541169cScgd 		mp++;
221e541169cScgd 	}
222ae3dca21Schristos 
223ae3dca21Schristos 	if (qflg)
22492c0ed87She 		(void)printf("# users = %zd\n", nusers);
225ae3dca21Schristos 
226ae3dca21Schristos 	return EX_OK;
227e541169cScgd }
228e541169cScgd 
229ae3dca21Schristos static int
utmpcmp(const void * v1,const void * v2)230f40dea57Smjl utmpcmp(const void *v1, const void *v2)
231e541169cScgd {
232ae3dca21Schristos 	const struct my_utmp *u1, *u2;
233e541169cScgd 	int rc;
234e541169cScgd 
23557417153Smrg 	u1 = v1;
23657417153Smrg 	u2 = v2;
237e541169cScgd 	rc = strncmp(u1->myutmp.out_name, u2->myutmp.out_name, 8);
238e541169cScgd 	if (rc)
239ae3dca21Schristos 		return rc;
240ab40c546Stron 	rc = strcmp(u1->myhost, u2->myhost);
241e541169cScgd 	if (rc)
242ae3dca21Schristos 		return rc;
243ae3dca21Schristos 	return strncmp(u1->myutmp.out_line, u2->myutmp.out_line, 8);
244e541169cScgd }
245ab40c546Stron 
246ae3dca21Schristos static void
usage(void)247f40dea57Smjl usage(void)
248f40dea57Smjl {
249ae3dca21Schristos 	(void)fprintf(stderr, "Usage: %s [-aHq]\n", getprogname());
250f40dea57Smjl 	exit(1);
251f40dea57Smjl }
252