xref: /original-bsd/usr.bin/ruptime/ruptime.c (revision 2301fdfb)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)ruptime.c	5.5 (Berkeley) 08/25/88";
26 #endif /* not lint */
27 
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <sys/file.h>
31 #include <protocols/rwhod.h>
32 #include <stdio.h>
33 
34 #define	NHOSTS	100
35 int	nhosts;
36 struct hs {
37 	struct	whod *hs_wd;
38 	int	hs_nusers;
39 } hs[NHOSTS];
40 struct	whod awhod;
41 
42 #define	WHDRSIZE	(sizeof (awhod) - sizeof (awhod.wd_we))
43 #define	RWHODIR		"/usr/spool/rwho"
44 #define	down(h)		(now - (h)->hs_wd->wd_recvtime > 11 * 60)
45 
46 time_t	now;
47 int	rflg = 1;
48 int	hscmp(), ucmp(), lcmp(), tcmp();
49 
50 main(argc, argv)
51 	int argc;
52 	char **argv;
53 {
54 	extern char *optarg;
55 	extern int optind;
56 	register struct hs *hsp = hs;
57 	register struct whod *wd;
58 	register struct whoent *we;
59 	register DIR *dirp;
60 	struct direct *dp;
61 	int aflg, cc, ch, f, i, maxloadav;
62 	char buf[sizeof(struct whod)];
63 	int (*cmp)() = hscmp;
64 	time_t time();
65 	char *interval(), *malloc();
66 
67 	aflg = 0;
68 	maxloadav = -1;
69 	while ((ch = getopt(argc, argv, "alrut")) != EOF)
70 		switch((char)ch) {
71 		case 'a':
72 			aflg = 1;
73 			break;
74 		case 'l':
75 			cmp = lcmp;
76 			break;
77 		case 'r':
78 			rflg = -1;
79 			break;
80 		case 't':
81 			cmp = tcmp;
82 			break;
83 		case 'u':
84 			cmp = ucmp;
85 			break;
86 		default:
87 			fprintf(stderr, "usage: ruptime [-alrut]\n");
88 			exit(1);
89 		}
90 
91 	if (chdir(RWHODIR) || (dirp = opendir(".")) == NULL) {
92 		perror(RWHODIR);
93 		exit(1);
94 	}
95 	while (dp = readdir(dirp)) {
96 		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
97 			continue;
98 		if (nhosts == NHOSTS) {
99 			fprintf(stderr, "ruptime: too many hosts\n");
100 			exit(1);
101 		}
102 		f = open(dp->d_name, O_RDONLY, 0);
103 		if (f > 0) {
104 			cc = read(f, buf, sizeof(struct whod));
105 			if (cc >= WHDRSIZE) {
106 				/* NOSTRICT */
107 				hsp->hs_wd = (struct whod *)malloc(WHDRSIZE);
108 				wd = (struct whod *)buf;
109 				bcopy(wd, hsp->hs_wd, WHDRSIZE);
110 				hsp->hs_nusers = 0;
111 				for (i = 0; i < 2; i++)
112 					if (wd->wd_loadav[i] > maxloadav)
113 						maxloadav = wd->wd_loadav[i];
114 				we = (struct whoent *)(buf+cc);
115 				while (--we >= wd->wd_we)
116 					if (aflg || we->we_idle < 3600)
117 						hsp->hs_nusers++;
118 				nhosts++; hsp++;
119 			}
120 			(void)close(f);
121 		}
122 	}
123 	if (!nhosts) {
124 		printf("ruptime: no hosts!?!\n");
125 		exit(1);
126 	}
127 	qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
128 	(void)time(&now);
129 	for (i = 0; i < nhosts; i++) {
130 		hsp = &hs[i];
131 		if (down(hsp)) {
132 			printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
133 			    interval(now - hsp->hs_wd->wd_recvtime, "down"));
134 			continue;
135 		}
136 		printf("%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
137 		    hsp->hs_wd->wd_hostname,
138 		    interval(hsp->hs_wd->wd_sendtime -
139 			hsp->hs_wd->wd_boottime, "  up"),
140 		    hsp->hs_nusers,
141 		    hsp->hs_nusers == 1 ? ", " : "s,",
142 		    maxloadav >= 1000 ? 5 : 4,
143 			hsp->hs_wd->wd_loadav[0] / 100.0,
144 		    maxloadav >= 1000 ? 5 : 4,
145 		        hsp->hs_wd->wd_loadav[1] / 100.0,
146 		    maxloadav >= 1000 ? 5 : 4,
147 		        hsp->hs_wd->wd_loadav[2] / 100.0);
148 		cfree(hsp->hs_wd);
149 	}
150 	exit(0);
151 }
152 
153 char *
154 interval(tval, updown)
155 	time_t tval;
156 	char *updown;
157 {
158 	static char resbuf[32];
159 	int days, hours, minutes;
160 
161 	if (tval < 0 || tval > 365*24*60*60) {
162 		(void)sprintf(resbuf, "   %s ??:??", updown);
163 		return(resbuf);
164 	}
165 	minutes = (tval + 59) / 60;		/* round to minutes */
166 	hours = minutes / 60; minutes %= 60;
167 	days = hours / 24; hours %= 24;
168 	if (days)
169 		(void)sprintf(resbuf, "%s %2d+%02d:%02d",
170 		    updown, days, hours, minutes);
171 	else
172 		(void)sprintf(resbuf, "%s    %2d:%02d",
173 		    updown, hours, minutes);
174 	return(resbuf);
175 }
176 
177 hscmp(h1, h2)
178 	struct hs *h1, *h2;
179 {
180 	return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
181 }
182 
183 /*
184  * Compare according to load average.
185  */
186 lcmp(h1, h2)
187 	struct hs *h1, *h2;
188 {
189 	if (down(h1))
190 		if (down(h2))
191 			return(tcmp(h1, h2));
192 		else
193 			return(rflg);
194 	else if (down(h2))
195 		return(-rflg);
196 	else
197 		return(rflg *
198 			(h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
199 }
200 
201 /*
202  * Compare according to number of users.
203  */
204 ucmp(h1, h2)
205 	struct hs *h1, *h2;
206 {
207 	if (down(h1))
208 		if (down(h2))
209 			return(tcmp(h1, h2));
210 		else
211 			return(rflg);
212 	else if (down(h2))
213 		return(-rflg);
214 	else
215 		return(rflg * (h2->hs_nusers - h1->hs_nusers));
216 }
217 
218 /*
219  * Compare according to uptime.
220  */
221 tcmp(h1, h2)
222 	struct hs *h1, *h2;
223 {
224 	return(rflg * (
225 		(down(h2) ? h2->hs_wd->wd_recvtime - now
226 			  : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
227 		-
228 		(down(h1) ? h1->hs_wd->wd_recvtime - now
229 			  : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
230 	));
231 }
232