xref: /original-bsd/usr.bin/ruptime/ruptime.c (revision 5b10f61c)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif not lint
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)ruptime.c	5.2 (Berkeley) 06/18/85";
15 #endif not lint
16 
17 #include <sys/param.h>
18 #include <stdio.h>
19 #include <sys/dir.h>
20 #include <protocols/rwhod.h>
21 
22 DIR	*dirp;
23 
24 #define	NHOSTS	100
25 int	nhosts;
26 struct	hs {
27 	struct	whod *hs_wd;
28 	int	hs_nusers;
29 } hs[NHOSTS];
30 struct	whod awhod;
31 int	hscmp(), ucmp(), lcmp(), tcmp();
32 
33 #define	WHDRSIZE	(sizeof (awhod) - sizeof (awhod.wd_we))
34 #define	RWHODIR		"/usr/spool/rwho"
35 
36 char	*interval();
37 int	now;
38 char	*malloc(), *sprintf();
39 int	aflg;
40 int 	rflg = 1;
41 
42 #define down(h)		(now - (h)->hs_wd->wd_recvtime > 11 * 60)
43 
44 main(argc, argv)
45 	int argc;
46 	char **argv;
47 {
48 	struct direct *dp;
49 	int f, i, t;
50 	char buf[sizeof(struct whod)]; int cc;
51 	char *name;
52 	register struct hs *hsp = hs;
53 	register struct whod *wd;
54 	register struct whoent *we;
55 	int maxloadav = 0;
56 	int (*cmp)() = hscmp;
57 
58 	name = *argv;
59 	while (*++argv)
60 		while (**argv)
61 			switch (*(*argv)++) {
62 			case 'a':
63 				aflg++;
64 				break;
65 			case 'l':
66 				cmp = lcmp;
67 				break;
68 			case 'u':
69 				cmp = ucmp;
70 				break;
71 			case 't':
72 				cmp = tcmp;
73 				break;
74 			case 'r':
75 				rflg = -rflg;
76 				break;
77 			case '-':
78 				break;
79 			default:
80 				fprintf(stderr, "Usage: %s [ -ar [ lut ] ]\n",
81 					name);
82 				exit (1);
83 			}
84 	time(&t);
85 	if (chdir(RWHODIR) < 0) {
86 		perror(RWHODIR);
87 		exit(1);
88 	}
89 	dirp = opendir(".");
90 	if (dirp == NULL) {
91 		perror(RWHODIR);
92 		exit(1);
93 	}
94 	while (dp = readdir(dirp)) {
95 		if (dp->d_ino == 0)
96 			continue;
97 		if (strncmp(dp->d_name, "whod.", 5))
98 			continue;
99 		if (nhosts == NHOSTS) {
100 			fprintf(stderr, "too many hosts\n");
101 			exit(1);
102 		}
103 		f = open(dp->d_name, 0);
104 		if (f > 0) {
105 			cc = read(f, buf, sizeof(struct whod));
106 			if (cc >= WHDRSIZE) {
107 				hsp->hs_wd = (struct whod *)malloc(WHDRSIZE);
108 				wd = (struct whod *)buf;
109 				bcopy(buf, 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 		}
121 		(void) close(f);
122 	}
123 	(void) time(&now);
124 	qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
125 	if (nhosts == 0) {
126 		printf("no hosts!?!\n");
127 		exit(1);
128 	}
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(time, updown)
155 	int time;
156 	char *updown;
157 {
158 	static char resbuf[32];
159 	int days, hours, minutes;
160 
161 	if (time < 0 || time > 3*30*24*60*60) {
162 		(void) sprintf(resbuf, "   %s ??:??", updown);
163 		return (resbuf);
164 	}
165 	minutes = (time + 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 
181 	return (rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
182 }
183 
184 /*
185  * Compare according to load average.
186  */
187 lcmp(h1, h2)
188 	struct hs *h1, *h2;
189 {
190 
191 	if (down(h1))
192 		if (down(h2))
193 			return (tcmp(h1, h2));
194 		else
195 			return (rflg);
196 	else if (down(h2))
197 		return (-rflg);
198 	else
199 		return (rflg *
200 			(h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
201 }
202 
203 /*
204  * Compare according to number of users.
205  */
206 ucmp(h1, h2)
207 	struct hs *h1, *h2;
208 {
209 
210 	if (down(h1))
211 		if (down(h2))
212 			return (tcmp(h1, h2));
213 		else
214 			return (rflg);
215 	else if (down(h2))
216 		return (-rflg);
217 	else
218 		return (rflg * (h2->hs_nusers - h1->hs_nusers));
219 }
220 
221 /*
222  * Compare according to uptime.
223  */
224 tcmp(h1, h2)
225 	struct hs *h1, *h2;
226 {
227 	long t1, t2;
228 
229 	return (rflg * (
230 		(down(h2) ? h2->hs_wd->wd_recvtime - now
231 			  : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
232 		-
233 		(down(h1) ? h1->hs_wd->wd_recvtime - now
234 			  : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
235 	));
236 }
237