Commit | Line | Data |
---|---|---|
22e155fc | 1 | /* |
d1c16455 | 2 | * Copyright (c) 1983, 1993, 1994 |
0762e4fa | 3 | * The Regents of the University of California. All rights reserved. |
e8dcae5f | 4 | * |
6d936b27 | 5 | * %sccs.include.redist.c% |
22e155fc DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
0762e4fa | 9 | static char copyright[] = |
d1c16455 | 10 | "@(#) Copyright (c) 1983, 1993, 1994\n\ |
0762e4fa | 11 | The Regents of the University of California. All rights reserved.\n"; |
e8dcae5f | 12 | #endif /* not lint */ |
22e155fc | 13 | |
be0e2d23 | 14 | #ifndef lint |
d1c16455 | 15 | static char sccsid[] = "@(#)ruptime.c 8.2 (Berkeley) %G%"; |
e8dcae5f | 16 | #endif /* not lint */ |
be0e2d23 | 17 | |
ed0072ae | 18 | #include <sys/param.h> |
d1c16455 | 19 | |
5a7285fa | 20 | #include <protocols/rwhod.h> |
d1c16455 KB |
21 | |
22 | #include <dirent.h> | |
23 | #include <err.h> | |
24 | #include <errno.h> | |
25 | #include <fcntl.h> | |
e8dcae5f | 26 | #include <stdio.h> |
6e9687a6 KB |
27 | #include <stdlib.h> |
28 | #include <string.h> | |
d1c16455 KB |
29 | #include <time.h> |
30 | #include <tzfile.h> | |
31 | #include <unistd.h> | |
be0e2d23 | 32 | |
e8dcae5f | 33 | struct hs { |
be0e2d23 BJ |
34 | struct whod *hs_wd; |
35 | int hs_nusers; | |
6e9687a6 | 36 | } *hs; |
be0e2d23 | 37 | struct whod awhod; |
be0e2d23 | 38 | |
6e9687a6 | 39 | #define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60) |
be0e2d23 BJ |
40 | #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we)) |
41 | ||
d1c16455 | 42 | size_t nhosts; |
6e9687a6 KB |
43 | time_t now; |
44 | int rflg = 1; | |
508c25be | 45 | |
d1c16455 KB |
46 | int hscmp __P((const void *, const void *)); |
47 | char *interval __P((time_t, char *)); | |
48 | int lcmp __P((const void *, const void *)); | |
49 | void morehosts __P((void)); | |
50 | int tcmp __P((const void *, const void *)); | |
51 | int ucmp __P((const void *, const void *)); | |
52 | void usage __P((void)); | |
53 | ||
54 | int | |
be0e2d23 BJ |
55 | main(argc, argv) |
56 | int argc; | |
57 | char **argv; | |
58 | { | |
e8dcae5f | 59 | extern int optind; |
d1c16455 KB |
60 | struct dirent *dp; |
61 | struct hs *hsp; | |
62 | struct whod *wd; | |
63 | struct whoent *we; | |
64 | DIR *dirp; | |
65 | size_t hspace; | |
66 | int aflg, cc, ch, fd, i, maxloadav; | |
e8dcae5f | 67 | char buf[sizeof(struct whod)]; |
d1c16455 | 68 | int (*cmp) __P((const void *, const void *)); |
e8dcae5f KB |
69 | |
70 | aflg = 0; | |
d1c16455 | 71 | cmp = hscmp; |
e8dcae5f | 72 | while ((ch = getopt(argc, argv, "alrut")) != EOF) |
d1c16455 | 73 | switch (ch) { |
e8dcae5f KB |
74 | case 'a': |
75 | aflg = 1; | |
76 | break; | |
77 | case 'l': | |
78 | cmp = lcmp; | |
79 | break; | |
80 | case 'r': | |
81 | rflg = -1; | |
82 | break; | |
83 | case 't': | |
84 | cmp = tcmp; | |
85 | break; | |
86 | case 'u': | |
87 | cmp = ucmp; | |
88 | break; | |
89 | default: | |
d1c16455 | 90 | usage(); |
e8dcae5f | 91 | } |
d1c16455 KB |
92 | argc -= optind; |
93 | argv += optind; | |
94 | ||
95 | if (argc != 0) | |
96 | usage(); | |
97 | ||
98 | if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) | |
99 | err(1, "%s", _PATH_RWHODIR); | |
be0e2d23 | 100 | |
6e9687a6 | 101 | maxloadav = -1; |
d1c16455 | 102 | for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) { |
e8dcae5f | 103 | if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) |
be0e2d23 | 104 | continue; |
d1c16455 KB |
105 | if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) { |
106 | warn("%s", dp->d_name); | |
6e9687a6 | 107 | continue; |
be0e2d23 | 108 | } |
d1c16455 KB |
109 | cc = read(fd, buf, sizeof(struct whod)); |
110 | (void)close(fd); | |
111 | ||
6e9687a6 KB |
112 | if (cc < WHDRSIZE) |
113 | continue; | |
114 | if (nhosts == hspace) { | |
d1c16455 KB |
115 | if ((hs = |
116 | realloc(hs, (hspace += 40) * sizeof(*hs))) == NULL) | |
117 | err(1, NULL); | |
6e9687a6 | 118 | hsp = hs + nhosts; |
be0e2d23 | 119 | } |
d1c16455 KB |
120 | |
121 | if ((hsp->hs_wd = malloc((size_t)WHDRSIZE)) == NULL) | |
122 | err(1, NULL); | |
123 | memmove(hsp->hs_wd, buf, (size_t)WHDRSIZE); | |
124 | ||
125 | for (wd = (struct whod *)buf, i = 0; i < 2; ++i) | |
6e9687a6 KB |
126 | if (wd->wd_loadav[i] > maxloadav) |
127 | maxloadav = wd->wd_loadav[i]; | |
d1c16455 KB |
128 | |
129 | for (hsp->hs_nusers = 0, | |
130 | we = (struct whoent *)(buf + cc); --we >= wd->wd_we;) | |
6e9687a6 | 131 | if (aflg || we->we_idle < 3600) |
d1c16455 KB |
132 | ++hsp->hs_nusers; |
133 | ++hsp; | |
134 | ++nhosts; | |
be0e2d23 | 135 | } |
d1c16455 KB |
136 | if (nhosts == 0) |
137 | errx(0, "no hosts in %s.", _PATH_RWHODIR); | |
138 | ||
e8dcae5f | 139 | (void)time(&now); |
d1c16455 | 140 | qsort(hs, nhosts, sizeof(hs[0]), cmp); |
be0e2d23 BJ |
141 | for (i = 0; i < nhosts; i++) { |
142 | hsp = &hs[i]; | |
6e9687a6 KB |
143 | if (ISDOWN(hsp)) { |
144 | (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname, | |
be0e2d23 BJ |
145 | interval(now - hsp->hs_wd->wd_recvtime, "down")); |
146 | continue; | |
147 | } | |
6e9687a6 KB |
148 | (void)printf( |
149 | "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", | |
be0e2d23 | 150 | hsp->hs_wd->wd_hostname, |
6e9687a6 KB |
151 | interval((time_t)hsp->hs_wd->wd_sendtime - |
152 | (time_t)hsp->hs_wd->wd_boottime, " up"), | |
be0e2d23 BJ |
153 | hsp->hs_nusers, |
154 | hsp->hs_nusers == 1 ? ", " : "s,", | |
acf8f1b2 BJ |
155 | maxloadav >= 1000 ? 5 : 4, |
156 | hsp->hs_wd->wd_loadav[0] / 100.0, | |
157 | maxloadav >= 1000 ? 5 : 4, | |
158 | hsp->hs_wd->wd_loadav[1] / 100.0, | |
159 | maxloadav >= 1000 ? 5 : 4, | |
160 | hsp->hs_wd->wd_loadav[2] / 100.0); | |
be0e2d23 BJ |
161 | } |
162 | exit(0); | |
163 | } | |
164 | ||
165 | char * | |
e8dcae5f KB |
166 | interval(tval, updown) |
167 | time_t tval; | |
be0e2d23 BJ |
168 | char *updown; |
169 | { | |
170 | static char resbuf[32]; | |
171 | int days, hours, minutes; | |
172 | ||
d1c16455 KB |
173 | if (tval < 0 || tval > DAYSPERNYEAR * SECSPERDAY) { |
174 | (void)snprintf(resbuf, sizeof(resbuf), " %s ??:??", updown); | |
175 | return (resbuf); | |
be0e2d23 | 176 | } |
d1c16455 KB |
177 | /* round to minutes. */ |
178 | minutes = (tval + (SECSPERMIN - 1)) / SECSPERMIN; | |
179 | hours = minutes / MINSPERHOUR; | |
180 | minutes %= MINSPERHOUR; | |
181 | days = hours / HOURSPERDAY; | |
182 | hours %= HOURSPERDAY; | |
be0e2d23 | 183 | if (days) |
d1c16455 KB |
184 | (void)snprintf(resbuf, sizeof(resbuf), |
185 | "%s %2d+%02d:%02d", updown, days, hours, minutes); | |
be0e2d23 | 186 | else |
d1c16455 KB |
187 | (void)snprintf(resbuf, sizeof(resbuf), |
188 | "%s %2d:%02d", updown, hours, minutes); | |
189 | return (resbuf); | |
be0e2d23 BJ |
190 | } |
191 | ||
d1c16455 KB |
192 | #define HS(a) ((struct hs *)(a)) |
193 | ||
194 | /* Alphabetical comparison. */ | |
195 | int | |
6e9687a6 | 196 | hscmp(a1, a2) |
d1c16455 | 197 | const void *a1, *a2; |
be0e2d23 | 198 | { |
d1c16455 KB |
199 | return (rflg * |
200 | strcmp(HS(a1)->hs_wd->wd_hostname, HS(a2)->hs_wd->wd_hostname)); | |
be0e2d23 | 201 | } |
508c25be | 202 | |
d1c16455 KB |
203 | /* Load average comparison. */ |
204 | int | |
6e9687a6 | 205 | lcmp(a1, a2) |
d1c16455 | 206 | const void *a1, *a2; |
508c25be | 207 | { |
d1c16455 KB |
208 | if (ISDOWN(HS(a1))) |
209 | if (ISDOWN(HS(a2))) | |
210 | return (tcmp(a1, a2)); | |
508c25be | 211 | else |
d1c16455 KB |
212 | return (rflg); |
213 | else if (ISDOWN(HS(a2))) | |
214 | return (-rflg); | |
508c25be | 215 | else |
d1c16455 KB |
216 | return (rflg * |
217 | (HS(a2)->hs_wd->wd_loadav[0] - HS(a1)->hs_wd->wd_loadav[0])); | |
508c25be EC |
218 | } |
219 | ||
d1c16455 KB |
220 | /* Number of users comparison. */ |
221 | int | |
6e9687a6 | 222 | ucmp(a1, a2) |
d1c16455 | 223 | const void *a1, *a2; |
508c25be | 224 | { |
d1c16455 KB |
225 | if (ISDOWN(HS(a1))) |
226 | if (ISDOWN(HS(a2))) | |
227 | return (tcmp(a1, a2)); | |
508c25be | 228 | else |
d1c16455 KB |
229 | return (rflg); |
230 | else if (ISDOWN(HS(a2))) | |
231 | return (-rflg); | |
508c25be | 232 | else |
d1c16455 | 233 | return (rflg * (HS(a2)->hs_nusers - HS(a1)->hs_nusers)); |
508c25be EC |
234 | } |
235 | ||
d1c16455 KB |
236 | /* Uptime comparison. */ |
237 | int | |
6e9687a6 | 238 | tcmp(a1, a2) |
d1c16455 | 239 | const void *a1, *a2; |
508c25be | 240 | { |
d1c16455 KB |
241 | return (rflg * ( |
242 | (ISDOWN(HS(a2)) ? HS(a2)->hs_wd->wd_recvtime - now | |
243 | : HS(a2)->hs_wd->wd_sendtime - HS(a2)->hs_wd->wd_boottime) | |
508c25be | 244 | - |
d1c16455 KB |
245 | (ISDOWN(HS(a1)) ? HS(a1)->hs_wd->wd_recvtime - now |
246 | : HS(a1)->hs_wd->wd_sendtime - HS(a1)->hs_wd->wd_boottime) | |
44bbb118 | 247 | )); |
508c25be | 248 | } |
6e9687a6 | 249 | |
d1c16455 KB |
250 | void |
251 | usage() | |
6e9687a6 | 252 | { |
d1c16455 KB |
253 | (void)fprintf(stderr, "usage: ruptime [-alrut]\n"); |
254 | exit(1); | |
6e9687a6 | 255 | } |