xref: /original-bsd/usr.bin/ruptime/ruptime.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1983, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)ruptime.c	8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/dir.h>
20 #include <sys/file.h>
21 #include <sys/errno.h>
22 #include <protocols/rwhod.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 size_t	nhosts, hspace = 20;
28 struct hs {
29 	struct	whod *hs_wd;
30 	int	hs_nusers;
31 } *hs;
32 struct	whod awhod;
33 
34 #define	ISDOWN(h)		(now - (h)->hs_wd->wd_recvtime > 11 * 60)
35 #define	WHDRSIZE	(sizeof (awhod) - sizeof (awhod.wd_we))
36 
37 time_t now;
38 int rflg = 1;
39 int hscmp(), ucmp(), lcmp(), tcmp();
40 
41 main(argc, argv)
42 	int argc;
43 	char **argv;
44 {
45 	extern char *optarg;
46 	extern int optind;
47 	register struct hs *hsp;
48 	register struct whod *wd;
49 	register struct whoent *we;
50 	register DIR *dirp;
51 	struct direct *dp;
52 	int aflg, cc, ch, f, i, maxloadav;
53 	char buf[sizeof(struct whod)];
54 	int (*cmp)() = hscmp;
55 	time_t time();
56 	char *interval();
57 
58 	aflg = 0;
59 	while ((ch = getopt(argc, argv, "alrut")) != EOF)
60 		switch((char)ch) {
61 		case 'a':
62 			aflg = 1;
63 			break;
64 		case 'l':
65 			cmp = lcmp;
66 			break;
67 		case 'r':
68 			rflg = -1;
69 			break;
70 		case 't':
71 			cmp = tcmp;
72 			break;
73 		case 'u':
74 			cmp = ucmp;
75 			break;
76 		default:
77 			(void)fprintf(stderr, "usage: ruptime [-alrut]\n");
78 			exit(1);
79 		}
80 
81 	if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) {
82 		(void)fprintf(stderr, "ruptime: %s: %s.\n",
83 		    _PATH_RWHODIR, strerror(errno));
84 		exit(1);
85 	}
86 	morehosts();
87 	hsp = hs;
88 	maxloadav = -1;
89 	while (dp = readdir(dirp)) {
90 		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
91 			continue;
92 		if ((f = open(dp->d_name, O_RDONLY, 0)) < 0) {
93 			(void)fprintf(stderr, "ruptime: %s: %s\n",
94 			    dp->d_name, strerror(errno));
95 			continue;
96 		}
97 		cc = read(f, buf, sizeof(struct whod));
98 		(void)close(f);
99 		if (cc < WHDRSIZE)
100 			continue;
101 		if (nhosts == hspace) {
102 			morehosts();
103 			hsp = hs + nhosts;
104 		}
105 		/* NOSTRICT */
106 		hsp->hs_wd = malloc((size_t)WHDRSIZE);
107 		wd = (struct whod *)buf;
108 		bcopy((char *)wd, (char *)hsp->hs_wd, (size_t)WHDRSIZE);
109 		hsp->hs_nusers = 0;
110 		for (i = 0; i < 2; i++)
111 			if (wd->wd_loadav[i] > maxloadav)
112 				maxloadav = wd->wd_loadav[i];
113 		we = (struct whoent *)(buf+cc);
114 		while (--we >= wd->wd_we)
115 			if (aflg || we->we_idle < 3600)
116 				hsp->hs_nusers++;
117 		nhosts++;
118 		hsp++;
119 	}
120 	if (!nhosts) {
121 		(void)printf("ruptime: no hosts in %s.\n", _PATH_RWHODIR);
122 		exit(1);
123 	}
124 	qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
125 	(void)time(&now);
126 	for (i = 0; i < nhosts; i++) {
127 		hsp = &hs[i];
128 		if (ISDOWN(hsp)) {
129 			(void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
130 			    interval(now - hsp->hs_wd->wd_recvtime, "down"));
131 			continue;
132 		}
133 		(void)printf(
134 		    "%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
135 		    hsp->hs_wd->wd_hostname,
136 		    interval((time_t)hsp->hs_wd->wd_sendtime -
137 			(time_t)hsp->hs_wd->wd_boottime, "  up"),
138 		    hsp->hs_nusers,
139 		    hsp->hs_nusers == 1 ? ", " : "s,",
140 		    maxloadav >= 1000 ? 5 : 4,
141 			hsp->hs_wd->wd_loadav[0] / 100.0,
142 		    maxloadav >= 1000 ? 5 : 4,
143 		        hsp->hs_wd->wd_loadav[1] / 100.0,
144 		    maxloadav >= 1000 ? 5 : 4,
145 		        hsp->hs_wd->wd_loadav[2] / 100.0);
146 		free((void *)hsp->hs_wd);
147 	}
148 	exit(0);
149 }
150 
151 char *
152 interval(tval, updown)
153 	time_t tval;
154 	char *updown;
155 {
156 	static char resbuf[32];
157 	int days, hours, minutes;
158 
159 	if (tval < 0 || tval > 365*24*60*60) {
160 		(void)sprintf(resbuf, "   %s ??:??", updown);
161 		return(resbuf);
162 	}
163 	minutes = (tval + 59) / 60;		/* round to minutes */
164 	hours = minutes / 60; minutes %= 60;
165 	days = hours / 24; hours %= 24;
166 	if (days)
167 		(void)sprintf(resbuf, "%s %2d+%02d:%02d",
168 		    updown, days, hours, minutes);
169 	else
170 		(void)sprintf(resbuf, "%s    %2d:%02d",
171 		    updown, hours, minutes);
172 	return(resbuf);
173 }
174 
175 /* alphabetical comparison */
176 hscmp(a1, a2)
177 	void *a1, *a2;
178 {
179 	struct hs *h1 = a1, *h2 = a2;
180 
181 	return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
182 }
183 
184 /* load average comparison */
185 lcmp(a1, a2)
186 	void *a1, *a2;
187 {
188 	register struct hs *h1 = a1, *h2 = a2;
189 
190 	if (ISDOWN(h1))
191 		if (ISDOWN(h2))
192 			return(tcmp(a1, a2));
193 		else
194 			return(rflg);
195 	else if (ISDOWN(h2))
196 		return(-rflg);
197 	else
198 		return(rflg *
199 			(h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
200 }
201 
202 /* number of users comparison */
203 ucmp(a1, a2)
204 	void *a1, *a2;
205 {
206 	register struct hs *h1 = a1, *h2 = a2;
207 
208 	if (ISDOWN(h1))
209 		if (ISDOWN(h2))
210 			return(tcmp(a1, a2));
211 		else
212 			return(rflg);
213 	else if (ISDOWN(h2))
214 		return(-rflg);
215 	else
216 		return(rflg * (h2->hs_nusers - h1->hs_nusers));
217 }
218 
219 /* uptime comparison */
220 tcmp(a1, a2)
221 	void *a1, *a2;
222 {
223 	register struct hs *h1 = a1, *h2 = a2;
224 
225 	return(rflg * (
226 		(ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now
227 			  : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
228 		-
229 		(ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now
230 			  : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
231 	));
232 }
233 
234 morehosts()
235 {
236 	hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs));
237 	if (hs == NULL) {
238 		(void)fprintf(stderr, "ruptime: %s.\n", strerror(ENOMEM));
239 		exit(1);
240 	}
241 }
242