Annotation of src/usr.bin/ruptime/ruptime.c, Revision 1.15
1.15 ! sobrado 1: /* $OpenBSD: ruptime.c,v 1.14 2004/10/10 03:50:40 mickey 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
1.14 mickey 33: const char copyright[] =
1.1 deraadt 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
1.14 mickey 39: /*static const char sccsid[] = "from: @(#)ruptime.c 5.8 (Berkeley) 7/21/90";*/
1.15 ! sobrado 40: static const char rcsid[] = "$OpenBSD: ruptime.c,v 1.14 2004/10/10 03:50:40 mickey 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>
1.14 mickey 52: #include <err.h>
1.1 deraadt 53:
54: size_t nhosts, hspace = 20;
55: struct hs {
56: struct whod *hs_wd;
57: int hs_nusers;
58: } *hs;
59: struct whod awhod;
60:
61: #define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60)
62: #define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we))
63:
64: time_t now;
65: int rflg = 1;
1.11 deraadt 66: int hscmp(const void *, const void *);
67: int ucmp(const void *, const void *);
68: int lcmp(const void *, const void *);
69: int tcmp(const void *, const void *);
1.12 deraadt 70: char *interval(time_t, char *);
1.1 deraadt 71:
1.7 millert 72: void morehosts(void);
1.4 deraadt 73:
74: int
1.10 deraadt 75: main(int argc, char *argv[])
1.1 deraadt 76: {
1.14 mickey 77: extern char *__progname;
1.6 mpech 78: struct hs *hsp;
79: struct whod *wd;
80: struct whoent *we;
81: DIR *dirp;
1.1 deraadt 82: struct dirent *dp;
83: int aflg, cc, ch, f, i, maxloadav;
84: char buf[sizeof(struct whod)];
1.11 deraadt 85: int (*cmp)(const void *, const void *) = hscmp;
1.1 deraadt 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:
1.15 ! sobrado 106: fprintf(stderr, "usage: %s [-alrtu]\n", __progname);
1.1 deraadt 107: exit(1);
108: }
109:
1.14 mickey 110: if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
111: err(1, "%s", _PATH_RWHODIR);
1.1 deraadt 112: morehosts();
113: hsp = hs;
114: maxloadav = -1;
1.4 deraadt 115: while ((dp = readdir(dirp))) {
1.1 deraadt 116: if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
117: continue;
118: if ((f = open(dp->d_name, O_RDONLY, 0)) < 0) {
1.14 mickey 119: warn("%s", dp->d_name);
1.1 deraadt 120: continue;
121: }
122: cc = read(f, buf, sizeof(struct whod));
123: (void)close(f);
124: if (cc < WHDRSIZE)
125: continue;
126: if (nhosts == hspace) {
127: morehosts();
128: hsp = hs + nhosts;
129: }
130: /* NOSTRICT */
131: hsp->hs_wd = malloc((size_t)WHDRSIZE);
132: wd = (struct whod *)buf;
133: bcopy((char *)wd, (char *)hsp->hs_wd, (size_t)WHDRSIZE);
134: hsp->hs_nusers = 0;
135: for (i = 0; i < 2; i++)
136: if (wd->wd_loadav[i] > maxloadav)
137: maxloadav = wd->wd_loadav[i];
138: we = (struct whoent *)(buf+cc);
139: while (--we >= wd->wd_we)
140: if (aflg || we->we_idle < 3600)
141: hsp->hs_nusers++;
142: nhosts++;
143: hsp++;
144: }
1.14 mickey 145: if (!nhosts)
146: errx(1, "no hosts in %s.", _PATH_RWHODIR);
1.1 deraadt 147: (void)time(&now);
148: qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
149: for (i = 0; i < nhosts; i++) {
150: hsp = &hs[i];
151: if (ISDOWN(hsp)) {
152: (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
153: interval(now - hsp->hs_wd->wd_recvtime, "down"));
154: continue;
155: }
156: (void)printf(
157: "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n",
158: hsp->hs_wd->wd_hostname,
159: interval((time_t)hsp->hs_wd->wd_sendtime -
160: (time_t)hsp->hs_wd->wd_boottime, " up"),
161: hsp->hs_nusers,
162: hsp->hs_nusers == 1 ? ", " : "s,",
163: maxloadav >= 1000 ? 5 : 4,
164: hsp->hs_wd->wd_loadav[0] / 100.0,
165: maxloadav >= 1000 ? 5 : 4,
166: hsp->hs_wd->wd_loadav[1] / 100.0,
167: maxloadav >= 1000 ? 5 : 4,
168: hsp->hs_wd->wd_loadav[2] / 100.0);
169: free((void *)hsp->hs_wd);
170: }
171: exit(0);
172: }
173:
174: char *
1.10 deraadt 175: interval(time_t tval, char *updown)
1.1 deraadt 176: {
177: static char resbuf[32];
178: int days, hours, minutes;
179:
1.5 millert 180: if (tval < 0 || tval > 999*24*60*60) {
1.8 deraadt 181: (void)snprintf(resbuf, sizeof resbuf, "%s ??:??", updown);
1.1 deraadt 182: return(resbuf);
183: }
184: minutes = (tval + 59) / 60; /* round to minutes */
185: hours = minutes / 60; minutes %= 60;
186: days = hours / 24; hours %= 24;
187: if (days)
1.8 deraadt 188: (void)snprintf(resbuf, sizeof resbuf, "%s %3d+%02d:%02d",
1.1 deraadt 189: updown, days, hours, minutes);
190: else
1.8 deraadt 191: (void)snprintf(resbuf, sizeof resbuf, "%s %2d:%02d",
1.1 deraadt 192: updown, hours, minutes);
193: return(resbuf);
194: }
195:
196: /* alphabetical comparison */
1.4 deraadt 197: int
1.11 deraadt 198: hscmp(const void *a1, const void *a2)
1.1 deraadt 199: {
1.11 deraadt 200: const struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 201:
202: return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
203: }
204:
205: /* load average comparison */
1.4 deraadt 206: int
1.11 deraadt 207: lcmp(const void *a1, const void *a2)
1.1 deraadt 208: {
1.11 deraadt 209: const struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 210:
211: if (ISDOWN(h1))
212: if (ISDOWN(h2))
213: return(tcmp(a1, a2));
214: else
215: return(rflg);
216: else if (ISDOWN(h2))
217: return(-rflg);
218: else
219: return(rflg *
220: (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
221: }
222:
223: /* number of users comparison */
1.4 deraadt 224: int
1.11 deraadt 225: ucmp(const void *a1, const void *a2)
1.1 deraadt 226: {
1.11 deraadt 227: const struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 228:
229: if (ISDOWN(h1))
230: if (ISDOWN(h2))
231: return(tcmp(a1, a2));
232: else
233: return(rflg);
234: else if (ISDOWN(h2))
235: return(-rflg);
236: else
237: return(rflg * (h2->hs_nusers - h1->hs_nusers));
238: }
239:
240: /* uptime comparison */
1.4 deraadt 241: int
1.11 deraadt 242: tcmp(const void *a1, const void *a2)
1.1 deraadt 243: {
1.11 deraadt 244: const struct hs *h1 = a1, *h2 = a2;
1.1 deraadt 245:
246: return(rflg * (
247: (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now
248: : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
249: -
250: (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now
251: : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
252: ));
253: }
254:
1.4 deraadt 255: void
1.10 deraadt 256: morehosts(void)
1.1 deraadt 257: {
258: hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs));
1.14 mickey 259: if (hs == NULL)
260: err(1, "realloc");
1.1 deraadt 261: }