Annotation of src/usr.bin/ruptime/ruptime.c, Revision 1.9
1.9 ! millert 1: /* $OpenBSD: ruptime.c,v 1.8 2002/05/27 03:14:22 deraadt Exp $ */
1.2 deraadt 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.
1.9 ! millert 15: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
32: #ifndef lint
33: char copyright[] =
34: "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
35: All rights reserved.\n";
36: #endif /* not lint */
37:
38: #ifndef lint
39: /*static char sccsid[] = "from: @(#)ruptime.c 5.8 (Berkeley) 7/21/90";*/
1.9 ! millert 40: static char rcsid[] = "$OpenBSD: ruptime.c,v 1.8 2002/05/27 03:14:22 deraadt Exp $";
1.1 deraadt 41: #endif /* not lint */
42:
43: #include <sys/param.h>
44: #include <sys/file.h>
45: #include <dirent.h>
46: #include <protocols/rwhod.h>
47: #include <stdio.h>
1.4 deraadt 48: #include <unistd.h>
1.1 deraadt 49: #include <stdlib.h>
50: #include <string.h>
51: #include <errno.h>
52:
53: size_t nhosts, hspace = 20;
54: struct hs {
55: struct whod *hs_wd;
56: int hs_nusers;
57: } *hs;
58: struct whod awhod;
59:
60: #define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60)
61: #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we))
62:
63: time_t now;
64: int rflg = 1;
65: int hscmp(), ucmp(), lcmp(), tcmp();
66:
1.7 millert 67: void morehosts(void);
1.4 deraadt 68:
69: int
1.1 deraadt 70: main(argc, argv)
71: int argc;
72: char **argv;
73: {
74: extern char *optarg;
75: extern int optind;
1.6 mpech 76: struct hs *hsp;
77: struct whod *wd;
78: struct whoent *we;
79: DIR *dirp;
1.1 deraadt 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;
1.3 millert 88: while ((ch = getopt(argc, argv, "alrut")) != -1)
1.1 deraadt 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;
1.4 deraadt 118: while ((dp = readdir(dirp))) {
1.1 deraadt 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:
1.5 millert 188: if (tval < 0 || tval > 999*24*60*60) {
1.8 deraadt 189: (void)snprintf(resbuf, sizeof resbuf, "%s ??:??", updown);
1.1 deraadt 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)
1.8 deraadt 196: (void)snprintf(resbuf, sizeof resbuf, "%s %3d+%02d:%02d",
1.1 deraadt 197: updown, days, hours, minutes);
198: else
1.8 deraadt 199: (void)snprintf(resbuf, sizeof resbuf, "%s %2d:%02d",
1.1 deraadt 200: updown, hours, minutes);
201: return(resbuf);
202: }
203:
204: /* alphabetical comparison */
1.4 deraadt 205: int
1.1 deraadt 206: hscmp(a1, a2)
207: void *a1, *a2;
208: {
209: struct hs *h1 = a1, *h2 = a2;
210:
211: return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
212: }
213:
214: /* load average comparison */
1.4 deraadt 215: int
1.1 deraadt 216: lcmp(a1, a2)
217: void *a1, *a2;
218: {
1.6 mpech 219: struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 220:
221: if (ISDOWN(h1))
222: if (ISDOWN(h2))
223: return(tcmp(a1, a2));
224: else
225: return(rflg);
226: else if (ISDOWN(h2))
227: return(-rflg);
228: else
229: return(rflg *
230: (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
231: }
232:
233: /* number of users comparison */
1.4 deraadt 234: int
1.1 deraadt 235: ucmp(a1, a2)
236: void *a1, *a2;
237: {
1.6 mpech 238: struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 239:
240: if (ISDOWN(h1))
241: if (ISDOWN(h2))
242: return(tcmp(a1, a2));
243: else
244: return(rflg);
245: else if (ISDOWN(h2))
246: return(-rflg);
247: else
248: return(rflg * (h2->hs_nusers - h1->hs_nusers));
249: }
250:
251: /* uptime comparison */
1.4 deraadt 252: int
1.1 deraadt 253: tcmp(a1, a2)
254: void *a1, *a2;
255: {
1.6 mpech 256: struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 257:
258: return(rflg * (
259: (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now
260: : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
261: -
262: (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now
263: : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
264: ));
265: }
266:
1.4 deraadt 267: void
1.1 deraadt 268: morehosts()
269: {
270: hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs));
271: if (hs == NULL) {
272: (void)fprintf(stderr, "ruptime: %s.\n", strerror(ENOMEM));
273: exit(1);
274: }
275: }