rwho.c revision 252596
1186904Ssam/*-
2186904Ssam * Copyright (c) 1983, 1993 The Regents of the University of California.
3186904Ssam * All rights reserved.
4186904Ssam *
5186904Ssam * Redistribution and use in source and binary forms, with or without
6186904Ssam * modification, are permitted provided that the following conditions
7186904Ssam * are met:
8186904Ssam * 1. Redistributions of source code must retain the above copyright
9186904Ssam *    notice, this list of conditions and the following disclaimer.
10186904Ssam * 2. Redistributions in binary form must reproduce the above copyright
11186904Ssam *    notice, this list of conditions and the following disclaimer in the
12186904Ssam *    documentation and/or other materials provided with the distribution.
13186904Ssam * 4. Neither the name of the University nor the names of its contributors
14186904Ssam *    may be used to endorse or promote products derived from this software
15186904Ssam *    without specific prior written permission.
16186904Ssam *
17186904Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18186904Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19186904Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20186904Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21186904Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22186904Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23186904Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24186904Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25186904Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26186904Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27186904Ssam * SUCH DAMAGE.
28186904Ssam */
29186904Ssam
30186904Ssam#ifndef lint
31186904Ssamstatic const char copyright[] =
32186904Ssam"@(#) Copyright (c) 1983, 1993\n\
33186904Ssam	The Regents of the University of California.  All rights reserved.\n";
34186904Ssam#endif /* not lint */
35186904Ssam
36186904Ssam#ifndef lint
37186904Ssam#if 0
38186904Ssamstatic char sccsid[] = "@(#)rwho.c	8.1 (Berkeley) 6/6/93";
39186904Ssam#endif
40186904Ssam#endif /* not lint */
41186904Ssam
42186904Ssam#include <sys/cdefs.h>
43186904Ssam__FBSDID("$FreeBSD: head/usr.bin/rwho/rwho.c 252596 2013-07-03 20:28:33Z pjd $");
44186904Ssam
45186904Ssam#include <sys/param.h>
46186904Ssam#include <sys/file.h>
47186904Ssam
48186904Ssam#include <protocols/rwhod.h>
49186904Ssam
50186904Ssam#include <dirent.h>
51186904Ssam#include <err.h>
52186904Ssam#include <langinfo.h>
53186904Ssam#include <locale.h>
54186904Ssam#include <stdio.h>
55186904Ssam#include <stdlib.h>
56186904Ssam#include <string.h>
57186904Ssam#include <time.h>
58186904Ssam#include <timeconv.h>
59186904Ssam#include <unistd.h>
60186904Ssam
61186904Ssam#define	NUSERS		1000
62186904Ssam#define	WHDRSIZE	(ssize_t)(sizeof (wd) - sizeof (wd.wd_we))
63186904Ssam/*
64186904Ssam * this macro should be shared with ruptime.
65186904Ssam */
66186904Ssam#define	down(w,now)	((now) - (w)->wd_recvtime > 11 * 60)
67186904Ssam
68186904Ssamstatic DIR	*dirp;
69186904Ssamstatic struct	whod wd;
70186904Ssamstatic int	nusers;
71186904Ssamstatic struct	myutmp {
72186904Ssam	char    myhost[sizeof(wd.wd_hostname)];
73186904Ssam	int	myidle;
74186904Ssam	struct	outmp myutmp;
75186904Ssam} myutmp[NUSERS];
76186904Ssam
77186904Ssamstatic time_t	now;
78186904Ssamstatic int	aflg;
79186904Ssam
80186904Ssamstatic void usage(void);
81187899Ssamstatic int utmpcmp(const void *, const void *);
82187899Ssam
83187899Ssamint
84188782Ssammain(int argc, char *argv[])
85188782Ssam{
86188782Ssam	int ch;
87188782Ssam	struct dirent *dp;
88188782Ssam	int width;
89188782Ssam	ssize_t cc;
90187899Ssam	struct whod *w;
91187899Ssam	struct whoent *we;
92187899Ssam	struct myutmp *mp;
93187899Ssam	int f, n, i;
94187899Ssam	int d_first;
95187899Ssam
96186904Ssam	w = &wd;
97186904Ssam	(void) setlocale(LC_TIME, "");
98186904Ssam	d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
99186904Ssam
100186904Ssam	while ((ch = getopt(argc, argv, "a")) != -1) {
101186904Ssam		switch ((char)ch) {
102186904Ssam		case 'a':
103186904Ssam			aflg = 1;
104186904Ssam			break;
105186904Ssam		case '?':
106186904Ssam		default:
107186904Ssam			usage();
108186904Ssam		}
109187899Ssam	}
110187899Ssam	argc -= optind;
111187899Ssam	argv += optind;
112187899Ssam
113187899Ssam	if (argc != 0)
114187899Ssam		usage();
115187899Ssam
116186904Ssam	if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
117186904Ssam		err(1, "%s", _PATH_RWHODIR);
118186904Ssam	mp = myutmp;
119186904Ssam	(void) time(&now);
120186904Ssam	while ((dp = readdir(dirp)) != NULL) {
121186904Ssam		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
122186904Ssam			continue;
123186904Ssam		f = open(dp->d_name, O_RDONLY);
124186904Ssam		if (f < 0)
125186904Ssam			continue;
126186904Ssam		cc = read(f, (char *)&wd, sizeof (struct whod));
127186904Ssam		if (cc < WHDRSIZE) {
128186904Ssam			(void) close(f);
129186904Ssam			continue;
130186904Ssam		}
131186904Ssam		if (down(w,now) != 0) {
132186904Ssam			(void) close(f);
133186904Ssam			continue;
134186904Ssam		}
135186904Ssam		cc -= WHDRSIZE;
136186904Ssam		we = w->wd_we;
137186904Ssam		for (n = cc / sizeof (struct whoent); n > 0; n--) {
138186904Ssam			if (aflg == 0 && we->we_idle >= 60 * 60) {
139186904Ssam				we++;
140186904Ssam				continue;
141186904Ssam			}
142186904Ssam			if (nusers >= NUSERS)
143186904Ssam				errx(1, "too many users");
144189980Ssam			mp->myutmp = we->we_utmp;
145186904Ssam			mp->myidle = we->we_idle;
146186904Ssam			(void) strcpy(mp->myhost, w->wd_hostname);
147186904Ssam			nusers++;
148186904Ssam			we++;
149186904Ssam			mp++;
150186904Ssam		}
151187899Ssam		(void) close(f);
152187899Ssam	}
153187899Ssam	qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp);
154187899Ssam	mp = myutmp;
155187899Ssam	width = 0;
156187899Ssam	for (i = 0; i < nusers; i++) {
157188782Ssam		/* append one for the blank and use 8 for the out_line */
158188782Ssam		int j;
159186904Ssam
160186904Ssam		j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line);
161186904Ssam		if (j > width)
162186904Ssam			width = j;
163186904Ssam		mp++;
164186904Ssam	}
165186904Ssam	mp = myutmp;
166186904Ssam	for (i = 0; i < nusers; i++) {
167186904Ssam		char buf[BUFSIZ], cbuf[80];
168186904Ssam		time_t t;
169186904Ssam
170186904Ssam		t = _int_to_time(mp->myutmp.out_time);
171186904Ssam		strftime(cbuf, sizeof(cbuf),
172186904Ssam		    d_first ? "%e %b %R" : "%b %e %R",
173186904Ssam		    localtime(&t));
174186904Ssam		(void) sprintf(buf, "%s:%-.*s", mp->myhost,
175186904Ssam		    (int)sizeof(mp->myutmp.out_line), mp->myutmp.out_line);
176186904Ssam		printf("%-*.*s %-*s %s",
177186904Ssam		    (int)sizeof(mp->myutmp.out_name),
178186904Ssam		    (int)sizeof(mp->myutmp.out_name),
179186904Ssam		    mp->myutmp.out_name,
180186904Ssam		    width,
181186904Ssam		    buf,
182186904Ssam		    cbuf);
183186904Ssam		mp->myidle /= 60;
184188467Ssam		if (mp->myidle != 0) {
185188467Ssam			if (aflg != 0) {
186188467Ssam				if (mp->myidle >= 100 * 60)
187188467Ssam					mp->myidle = 100 * 60 - 1;
188188467Ssam				if (mp->myidle >= 60)
189188467Ssam					printf(" %2d", mp->myidle / 60);
190188467Ssam				else
191188467Ssam					printf("   ");
192188467Ssam			} else {
193186904Ssam				printf(" ");
194186904Ssam			}
195186904Ssam			printf(":%02d", mp->myidle % 60);
196186904Ssam		}
197186904Ssam		printf("\n");
198186904Ssam		mp++;
199186904Ssam	}
200188467Ssam	exit(0);
201186904Ssam}
202186904Ssam
203186904Ssam
204188467Ssamstatic void
205186904Ssamusage(void)
206186904Ssam{
207186904Ssam	fprintf(stderr, "usage: rwho [-a]\n");
208186904Ssam	exit(1);
209186904Ssam}
210186904Ssam
211186904Ssam#define MYUTMP(a) ((const struct myutmp *)(a))
212186904Ssam
213186904Ssamstatic int
214186904Ssamutmpcmp(const void *u1, const void *u2)
215186904Ssam{
216186904Ssam	int rc;
217186904Ssam
218186904Ssam	rc = strncmp(MYUTMP(u1)->myutmp.out_name, MYUTMP(u2)->myutmp.out_name,
219186904Ssam	    sizeof(MYUTMP(u2)->myutmp.out_name));
220186904Ssam	if (rc != 0)
221186904Ssam		return (rc);
222188467Ssam	rc = strcmp(MYUTMP(u1)->myhost, MYUTMP(u2)->myhost);
223188467Ssam	if (rc != 0)
224188467Ssam		return (rc);
225188467Ssam	return (strncmp(MYUTMP(u1)->myutmp.out_line, MYUTMP(u2)->myutmp.out_line,
226186904Ssam	    sizeof(MYUTMP(u2)->myutmp.out_line)));
227186904Ssam}
228186904Ssam