Annotation of src/usr.bin/ruptime/ruptime.c, Revision 1.2
1.2 ! deraadt 1: /* $OpenBSD$ */
! 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1983 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: char copyright[] =
38: "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
39: All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: /*static char sccsid[] = "from: @(#)ruptime.c 5.8 (Berkeley) 7/21/90";*/
1.2 ! deraadt 44: static char rcsid[] = "$OpenBSD: ruptime.c,v 1.1.1.1 1995/10/18 08:46:04 deraadt Exp $";
1.1 deraadt 45: #endif /* not lint */
46:
47: #include <sys/param.h>
48: #include <sys/file.h>
49: #include <dirent.h>
50: #include <protocols/rwhod.h>
51: #include <stdio.h>
52: #include <stdlib.h>
53: #include <string.h>
54: #include <errno.h>
55:
56: size_t nhosts, hspace = 20;
57: struct hs {
58: struct whod *hs_wd;
59: int hs_nusers;
60: } *hs;
61: struct whod awhod;
62:
63: #define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60)
64: #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we))
65:
66: time_t now;
67: int rflg = 1;
68: int hscmp(), ucmp(), lcmp(), tcmp();
69:
70: main(argc, argv)
71: int argc;
72: char **argv;
73: {
74: extern char *optarg;
75: extern int optind;
76: register struct hs *hsp;
77: register struct whod *wd;
78: register struct whoent *we;
79: register DIR *dirp;
80: struct dirent *dp;
81: int aflg, cc, ch, f, i, maxloadav;
82: char buf[sizeof(struct whod)];
83: int (*cmp)() = hscmp;
84: time_t time();
85: char *interval();
86:
87: aflg = 0;
88: while ((ch = getopt(argc, argv, "alrut")) != EOF)
89: switch((char)ch) {
90: case 'a':
91: aflg = 1;
92: break;
93: case 'l':
94: cmp = lcmp;
95: break;
96: case 'r':
97: rflg = -1;
98: break;
99: case 't':
100: cmp = tcmp;
101: break;
102: case 'u':
103: cmp = ucmp;
104: break;
105: default:
106: (void)fprintf(stderr, "usage: ruptime [-alrut]\n");
107: exit(1);
108: }
109:
110: if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) {
111: (void)fprintf(stderr, "ruptime: %s: %s.\n",
112: _PATH_RWHODIR, strerror(errno));
113: exit(1);
114: }
115: morehosts();
116: hsp = hs;
117: maxloadav = -1;
118: while (dp = readdir(dirp)) {
119: if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
120: continue;
121: if ((f = open(dp->d_name, O_RDONLY, 0)) < 0) {
122: (void)fprintf(stderr, "ruptime: %s: %s\n",
123: dp->d_name, strerror(errno));
124: continue;
125: }
126: cc = read(f, buf, sizeof(struct whod));
127: (void)close(f);
128: if (cc < WHDRSIZE)
129: continue;
130: if (nhosts == hspace) {
131: morehosts();
132: hsp = hs + nhosts;
133: }
134: /* NOSTRICT */
135: hsp->hs_wd = malloc((size_t)WHDRSIZE);
136: wd = (struct whod *)buf;
137: bcopy((char *)wd, (char *)hsp->hs_wd, (size_t)WHDRSIZE);
138: hsp->hs_nusers = 0;
139: for (i = 0; i < 2; i++)
140: if (wd->wd_loadav[i] > maxloadav)
141: maxloadav = wd->wd_loadav[i];
142: we = (struct whoent *)(buf+cc);
143: while (--we >= wd->wd_we)
144: if (aflg || we->we_idle < 3600)
145: hsp->hs_nusers++;
146: nhosts++;
147: hsp++;
148: }
149: if (!nhosts) {
150: (void)printf("ruptime: no hosts in %s.\n", _PATH_RWHODIR);
151: exit(1);
152: }
153: (void)time(&now);
154: qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
155: for (i = 0; i < nhosts; i++) {
156: hsp = &hs[i];
157: if (ISDOWN(hsp)) {
158: (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
159: interval(now - hsp->hs_wd->wd_recvtime, "down"));
160: continue;
161: }
162: (void)printf(
163: "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n",
164: hsp->hs_wd->wd_hostname,
165: interval((time_t)hsp->hs_wd->wd_sendtime -
166: (time_t)hsp->hs_wd->wd_boottime, " up"),
167: hsp->hs_nusers,
168: hsp->hs_nusers == 1 ? ", " : "s,",
169: maxloadav >= 1000 ? 5 : 4,
170: hsp->hs_wd->wd_loadav[0] / 100.0,
171: maxloadav >= 1000 ? 5 : 4,
172: hsp->hs_wd->wd_loadav[1] / 100.0,
173: maxloadav >= 1000 ? 5 : 4,
174: hsp->hs_wd->wd_loadav[2] / 100.0);
175: free((void *)hsp->hs_wd);
176: }
177: exit(0);
178: }
179:
180: char *
181: interval(tval, updown)
182: time_t tval;
183: char *updown;
184: {
185: static char resbuf[32];
186: int days, hours, minutes;
187:
188: if (tval < 0 || tval > 365*24*60*60) {
189: (void)sprintf(resbuf, " %s ??:??", updown);
190: return(resbuf);
191: }
192: minutes = (tval + 59) / 60; /* round to minutes */
193: hours = minutes / 60; minutes %= 60;
194: days = hours / 24; hours %= 24;
195: if (days)
196: (void)sprintf(resbuf, "%s %2d+%02d:%02d",
197: updown, days, hours, minutes);
198: else
199: (void)sprintf(resbuf, "%s %2d:%02d",
200: updown, hours, minutes);
201: return(resbuf);
202: }
203:
204: /* alphabetical comparison */
205: hscmp(a1, a2)
206: void *a1, *a2;
207: {
208: struct hs *h1 = a1, *h2 = a2;
209:
210: return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
211: }
212:
213: /* load average comparison */
214: lcmp(a1, a2)
215: void *a1, *a2;
216: {
217: register struct hs *h1 = a1, *h2 = a2;
218:
219: if (ISDOWN(h1))
220: if (ISDOWN(h2))
221: return(tcmp(a1, a2));
222: else
223: return(rflg);
224: else if (ISDOWN(h2))
225: return(-rflg);
226: else
227: return(rflg *
228: (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
229: }
230:
231: /* number of users comparison */
232: ucmp(a1, a2)
233: void *a1, *a2;
234: {
235: register struct hs *h1 = a1, *h2 = a2;
236:
237: if (ISDOWN(h1))
238: if (ISDOWN(h2))
239: return(tcmp(a1, a2));
240: else
241: return(rflg);
242: else if (ISDOWN(h2))
243: return(-rflg);
244: else
245: return(rflg * (h2->hs_nusers - h1->hs_nusers));
246: }
247:
248: /* uptime comparison */
249: tcmp(a1, a2)
250: void *a1, *a2;
251: {
252: register struct hs *h1 = a1, *h2 = a2;
253:
254: return(rflg * (
255: (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now
256: : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
257: -
258: (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now
259: : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
260: ));
261: }
262:
263: morehosts()
264: {
265: hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs));
266: if (hs == NULL) {
267: (void)fprintf(stderr, "ruptime: %s.\n", strerror(ENOMEM));
268: exit(1);
269: }
270: }