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