Annotation of src/usr.bin/rup/rup.c, Revision 1.19
1.19 ! tedu 1: /* $OpenBSD: rup.c,v 1.18 2003/08/04 17:06:45 deraadt Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /*-
4: * Copyright (c) 1993, John Brezak
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
1.19 ! tedu 37: static char rcsid[] = "$OpenBSD: rup.c,v 1.18 2003/08/04 17:06:45 deraadt Exp $";
1.1 deraadt 38: #endif /* not lint */
39:
40: #include <stdio.h>
41: #include <stdlib.h>
42: #include <string.h>
43: #include <time.h>
44: #include <sys/param.h>
45: #include <sys/socket.h>
46: #include <netdb.h>
47: #include <rpc/rpc.h>
1.7 deraadt 48: #include <rpc/pmap_clnt.h>
1.1 deraadt 49: #include <arpa/inet.h>
50: #include <err.h>
51:
52: #undef FSHIFT /* Use protocol's shift and scale values */
53: #undef FSCALE
54: #include <rpcsvc/rstat.h>
55:
1.11 aaron 56: #define HOST_WIDTH 27
1.1 deraadt 57:
58: int printtime; /* print the remote host(s)'s time */
59:
60: struct host_list {
61: struct host_list *next;
62: struct in_addr addr;
63: } *hosts;
64:
1.15 millert 65: void usage(void);
66: int print_rup_data(char *, statstime *host_stat);
1.7 deraadt 67:
1.18 deraadt 68: static int
1.17 deraadt 69: search_host(struct in_addr addr)
1.1 deraadt 70: {
71: struct host_list *hp;
72:
73: if (!hosts)
74: return(0);
75:
76: for (hp = hosts; hp != NULL; hp = hp->next) {
77: if (hp->addr.s_addr == addr.s_addr)
78: return(1);
79: }
80: return(0);
81: }
82:
1.18 deraadt 83: static void
1.17 deraadt 84: remember_host(struct in_addr addr)
1.1 deraadt 85: {
86: struct host_list *hp;
87:
88: if (!(hp = (struct host_list *)malloc(sizeof(struct host_list)))) {
89: err(1, NULL);
90: /* NOTREACHED */
91: }
92: hp->addr.s_addr = addr.s_addr;
93: hp->next = hosts;
94: hosts = hp;
95: }
96:
97:
98: struct rup_data {
99: char *host;
100: struct statstime statstime;
101: };
102: struct rup_data *rup_data;
103: int rup_data_idx = 0;
104: int rup_data_max = 0;
105:
1.17 deraadt 106: enum sort_type {
1.1 deraadt 107: SORT_NONE,
108: SORT_HOST,
109: SORT_LDAV,
110: SORT_UPTIME
111: };
112: enum sort_type sort_type;
113:
1.18 deraadt 114: static int
1.17 deraadt 115: compare(const void *v1, const void *v2)
1.1 deraadt 116: {
1.17 deraadt 117: const struct rup_data *d1 = v1;
118: const struct rup_data *d2 = v2;
119:
1.1 deraadt 120: switch(sort_type) {
121: case SORT_HOST:
122: return strcmp(d1->host, d2->host);
123: case SORT_LDAV:
1.3 deraadt 124: return d1->statstime.avenrun[0]
1.1 deraadt 125: - d2->statstime.avenrun[0];
126: case SORT_UPTIME:
1.17 deraadt 127: return d1->statstime.boottime.tv_sec
1.1 deraadt 128: - d2->statstime.boottime.tv_sec;
129: default:
130: /* something's really wrong here */
131: abort();
132: }
133: }
134:
1.18 deraadt 135: static void
1.17 deraadt 136: remember_rup_data(char *host, struct statstime *st)
1.1 deraadt 137: {
1.14 deraadt 138: if (rup_data_idx >= rup_data_max) {
1.19 ! tedu 139: int newsize;
! 140: struct rup_data *newrup;
! 141:
! 142: newsize = rup_data_max + 16;
! 143: newrup = realloc(rup_data, newsize * sizeof(struct rup_data));
! 144: if (newrup == NULL) {
1.14 deraadt 145: err(1, NULL);
1.1 deraadt 146: /* NOTREACHED */
1.14 deraadt 147: }
1.19 ! tedu 148: rup_data = newrup;
! 149: rup_data_max = newsize;
1.14 deraadt 150: }
1.1 deraadt 151:
1.19 ! tedu 152: if ((rup_data[rup_data_idx].host = strdup(host)) == NULL)
! 153: err(1, NULL);
1.1 deraadt 154: rup_data[rup_data_idx].statstime = *st;
155: rup_data_idx++;
156: }
157:
158:
1.18 deraadt 159: static int
1.17 deraadt 160: rstat_reply(char *replyp, struct sockaddr_in *raddrp)
1.1 deraadt 161: {
162: struct hostent *hp;
163: char *host;
164: statstime *host_stat = (statstime *)replyp;
165:
166: if (!search_host(raddrp->sin_addr)) {
167: hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
1.3 deraadt 168: sizeof(struct in_addr), AF_INET);
1.1 deraadt 169: if (hp)
170: host = hp->h_name;
171: else
172: host = inet_ntoa(raddrp->sin_addr);
173:
174: remember_host(raddrp->sin_addr);
175:
1.3 deraadt 176: if (sort_type != SORT_NONE)
1.1 deraadt 177: remember_rup_data(host, host_stat);
1.3 deraadt 178: else
1.1 deraadt 179: print_rup_data(host, host_stat);
180: }
181:
182: return (0);
183: }
184:
185:
186: int
1.17 deraadt 187: print_rup_data(char *host, statstime *host_stat)
1.1 deraadt 188: {
1.16 deraadt 189: unsigned int ups = 0, upm = 0, uph = 0, upd = 0;
190: struct tm *tmp_time, host_time;
191: char days_buf[16], hours_buf[16];
1.1 deraadt 192:
1.9 millert 193: if (printtime)
1.11 aaron 194: printf("%-*.*s", HOST_WIDTH-8, HOST_WIDTH-8, host);
1.9 millert 195: else
196: printf("%-*.*s", HOST_WIDTH, HOST_WIDTH, host);
1.1 deraadt 197:
198: tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec);
199: host_time = *tmp_time;
200:
201: host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec;
202:
1.12 millert 203: if (host_stat->curtime.tv_sec > 0)
204: ups=host_stat->curtime.tv_sec;
1.6 tholo 205: upd=ups/(3600*24);
206: ups-=upd*3600*24;
207: uph=ups/3600;
208: ups-=uph*3600;
209: upm=ups/60;
210:
211: if (upd != 0)
1.16 deraadt 212: snprintf(days_buf, sizeof days_buf, "%3u day%s, ", upd,
213: (upd > 1) ? "s" : "");
1.1 deraadt 214: else
215: days_buf[0] = '\0';
216:
1.6 tholo 217: if (uph != 0)
1.16 deraadt 218: snprintf(hours_buf, sizeof hours_buf, "%2u:%02u, ",
219: uph, upm);
1.1 deraadt 220: else
1.6 tholo 221: if (upm != 0)
1.16 deraadt 222: snprintf(hours_buf, sizeof hours_buf, "%2u min%s ",
223: upm, (upm == 1) ? ", " : "s,");
1.1 deraadt 224: else
225: hours_buf[0] = '\0';
226:
227: if (printtime)
1.4 deraadt 228: printf(" %2d:%02d%cm",
229: (host_time.tm_hour % 12) ? (host_time.tm_hour % 12) : 12,
1.3 deraadt 230: host_time.tm_min,
231: (host_time.tm_hour >= 12) ? 'p' : 'a');
1.1 deraadt 232:
233: printf(" up %9.9s%9.9s load average: %.2f %.2f %.2f\n",
1.3 deraadt 234: days_buf, hours_buf,
235: (double)host_stat->avenrun[0]/FSCALE,
236: (double)host_stat->avenrun[1]/FSCALE,
237: (double)host_stat->avenrun[2]/FSCALE);
1.1 deraadt 238:
239: return(0);
240: }
241:
242:
1.18 deraadt 243: static void
1.17 deraadt 244: onehost(char *host)
1.1 deraadt 245: {
246: CLIENT *rstat_clnt;
247: statstime host_stat;
248: static struct timeval timeout = {25, 0};
1.5 deraadt 249: extern char *__progname;
1.1 deraadt 250:
251: rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp");
252: if (rstat_clnt == NULL) {
1.5 deraadt 253: fprintf(stderr, "%s: %s", __progname,
254: clnt_spcreateerror(host));
1.1 deraadt 255: return;
256: }
257:
258: bzero((char *)&host_stat, sizeof(host_stat));
1.3 deraadt 259: if (clnt_call(rstat_clnt, RSTATPROC_STATS, xdr_void, NULL,
260: xdr_statstime, &host_stat, timeout) != RPC_SUCCESS) {
1.5 deraadt 261: fprintf(stderr, "%s: %s", __progname,
262: clnt_sperror(rstat_clnt, host));
1.13 deraadt 263: clnt_destroy(rstat_clnt);
1.1 deraadt 264: return;
265: }
266:
267: print_rup_data(host, &host_stat);
268: clnt_destroy(rstat_clnt);
269: }
270:
1.18 deraadt 271: static void
1.17 deraadt 272: allhosts(void)
1.1 deraadt 273: {
274: statstime host_stat;
275: enum clnt_stat clnt_stat;
1.5 deraadt 276: extern char *__progname;
1.1 deraadt 277: size_t i;
278:
279: if (sort_type != SORT_NONE) {
280: printf("collecting responses...");
281: fflush(stdout);
282: }
283:
284: clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
1.7 deraadt 285: xdr_void, NULL, xdr_statstime, (char *)&host_stat, rstat_reply);
1.1 deraadt 286: if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) {
1.8 deraadt 287: fprintf(stderr, "%s: %s\n", __progname, clnt_sperrno(clnt_stat));
1.1 deraadt 288: exit(1);
289: }
290:
291: if (sort_type != SORT_NONE) {
292: putchar('\n');
1.3 deraadt 293: qsort(rup_data, rup_data_idx, sizeof(struct rup_data),
294: compare);
1.1 deraadt 295:
296: for (i = 0; i < rup_data_idx; i++) {
1.3 deraadt 297: print_rup_data(rup_data[i].host,
298: &rup_data[i].statstime);
1.1 deraadt 299: }
300: }
301: }
302:
1.7 deraadt 303: int
1.17 deraadt 304: main(int argc, char *argv[])
1.1 deraadt 305: {
306: int ch;
307: extern int optind;
308:
309: sort_type = SORT_NONE;
310: while ((ch = getopt(argc, argv, "dhlt")) != -1)
311: switch (ch) {
312: case 'd':
313: printtime = 1;
314: break;
315: case 'h':
316: sort_type = SORT_HOST;
317: break;
318: case 'l':
319: sort_type = SORT_LDAV;
320: break;
321: case 't':
322: sort_type = SORT_UPTIME;
323: break;
324: default:
325: usage();
326: /*NOTREACHED*/
327: }
328:
329: setlinebuf(stdout);
330:
331: if (argc == optind)
332: allhosts();
333: else {
334: for (; optind < argc; optind++)
335: onehost(argv[optind]);
336: }
337:
338: exit(0);
339: }
340:
341:
1.7 deraadt 342: void
1.17 deraadt 343: usage(void)
1.1 deraadt 344: {
345: fprintf(stderr, "Usage: rup [-dhlt] [hosts ...]\n");
346: exit(1);
347: }