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