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