xref: /original-bsd/usr.bin/ruptime/ruptime.c (revision dfa70498)
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.6 (Berkeley) 05/11/89";
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	down(h)		(now - (h)->hs_wd->wd_recvtime > 11 * 60)
44 
45 time_t	now;
46 int	rflg = 1;
47 int	hscmp(), ucmp(), lcmp(), tcmp();
48 
49 main(argc, argv)
50 	int argc;
51 	char **argv;
52 {
53 	extern char *optarg;
54 	extern int optind;
55 	register struct hs *hsp = hs;
56 	register struct whod *wd;
57 	register struct whoent *we;
58 	register DIR *dirp;
59 	struct direct *dp;
60 	int aflg, cc, ch, f, i, maxloadav;
61 	char buf[sizeof(struct whod)];
62 	int (*cmp)() = hscmp;
63 	time_t time();
64 	char *interval(), *malloc();
65 
66 	aflg = 0;
67 	maxloadav = -1;
68 	while ((ch = getopt(argc, argv, "alrut")) != EOF)
69 		switch((char)ch) {
70 		case 'a':
71 			aflg = 1;
72 			break;
73 		case 'l':
74 			cmp = lcmp;
75 			break;
76 		case 'r':
77 			rflg = -1;
78 			break;
79 		case 't':
80 			cmp = tcmp;
81 			break;
82 		case 'u':
83 			cmp = ucmp;
84 			break;
85 		default:
86 			fprintf(stderr, "usage: ruptime [-alrut]\n");
87 			exit(1);
88 		}
89 
90 	if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) {
91 		perror(_PATH_RWHODIR);
92 		exit(1);
93 	}
94 	while (dp = readdir(dirp)) {
95 		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
96 			continue;
97 		if (nhosts == NHOSTS) {
98 			fprintf(stderr, "ruptime: too many hosts\n");
99 			exit(1);
100 		}
101 		f = open(dp->d_name, O_RDONLY, 0);
102 		if (f > 0) {
103 			cc = read(f, buf, sizeof(struct whod));
104 			if (cc >= WHDRSIZE) {
105 				/* NOSTRICT */
106 				hsp->hs_wd = (struct whod *)malloc(WHDRSIZE);
107 				wd = (struct whod *)buf;
108 				bcopy(wd, hsp->hs_wd, 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++; hsp++;
118 			}
119 			(void)close(f);
120 		}
121 	}
122 	if (!nhosts) {
123 		printf("ruptime: no hosts!?!\n");
124 		exit(1);
125 	}
126 	qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
127 	(void)time(&now);
128 	for (i = 0; i < nhosts; i++) {
129 		hsp = &hs[i];
130 		if (down(hsp)) {
131 			printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
132 			    interval(now - hsp->hs_wd->wd_recvtime, "down"));
133 			continue;
134 		}
135 		printf("%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
136 		    hsp->hs_wd->wd_hostname,
137 		    interval(hsp->hs_wd->wd_sendtime -
138 			hsp->hs_wd->wd_boottime, "  up"),
139 		    hsp->hs_nusers,
140 		    hsp->hs_nusers == 1 ? ", " : "s,",
141 		    maxloadav >= 1000 ? 5 : 4,
142 			hsp->hs_wd->wd_loadav[0] / 100.0,
143 		    maxloadav >= 1000 ? 5 : 4,
144 		        hsp->hs_wd->wd_loadav[1] / 100.0,
145 		    maxloadav >= 1000 ? 5 : 4,
146 		        hsp->hs_wd->wd_loadav[2] / 100.0);
147 		cfree(hsp->hs_wd);
148 	}
149 	exit(0);
150 }
151 
152 char *
153 interval(tval, updown)
154 	time_t tval;
155 	char *updown;
156 {
157 	static char resbuf[32];
158 	int days, hours, minutes;
159 
160 	if (tval < 0 || tval > 365*24*60*60) {
161 		(void)sprintf(resbuf, "   %s ??:??", updown);
162 		return(resbuf);
163 	}
164 	minutes = (tval + 59) / 60;		/* round to minutes */
165 	hours = minutes / 60; minutes %= 60;
166 	days = hours / 24; hours %= 24;
167 	if (days)
168 		(void)sprintf(resbuf, "%s %2d+%02d:%02d",
169 		    updown, days, hours, minutes);
170 	else
171 		(void)sprintf(resbuf, "%s    %2d:%02d",
172 		    updown, hours, minutes);
173 	return(resbuf);
174 }
175 
176 hscmp(h1, h2)
177 	struct hs *h1, *h2;
178 {
179 	return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
180 }
181 
182 /*
183  * Compare according to load average.
184  */
185 lcmp(h1, h2)
186 	struct hs *h1, *h2;
187 {
188 	if (down(h1))
189 		if (down(h2))
190 			return(tcmp(h1, h2));
191 		else
192 			return(rflg);
193 	else if (down(h2))
194 		return(-rflg);
195 	else
196 		return(rflg *
197 			(h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
198 }
199 
200 /*
201  * Compare according to number of users.
202  */
203 ucmp(h1, h2)
204 	struct hs *h1, *h2;
205 {
206 	if (down(h1))
207 		if (down(h2))
208 			return(tcmp(h1, h2));
209 		else
210 			return(rflg);
211 	else if (down(h2))
212 		return(-rflg);
213 	else
214 		return(rflg * (h2->hs_nusers - h1->hs_nusers));
215 }
216 
217 /*
218  * Compare according to uptime.
219  */
220 tcmp(h1, h2)
221 	struct hs *h1, *h2;
222 {
223 	return(rflg * (
224 		(down(h2) ? h2->hs_wd->wd_recvtime - now
225 			  : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
226 		-
227 		(down(h1) ? h1->hs_wd->wd_recvtime - now
228 			  : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
229 	));
230 }
231