Home | History | Annotate | Line # | Download | only in rup
rup.c revision 1.12
      1 /*	$NetBSD: rup.c,v 1.12 1996/09/27 01:46:10 thorpej Exp $	*/
      2 
      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
     37 static char rcsid[] = "$NetBSD: rup.c,v 1.12 1996/09/27 01:46:10 thorpej Exp $";
     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 {
     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 
    106 enum sort_type {
    107 	SORT_NONE,
    108 	SORT_HOST,
    109 	SORT_LDAV,
    110 	SORT_UPTIME
    111 };
    112 enum sort_type sort_type;
    113 
    114 compare(d1, d2)
    115 	struct rup_data *d1;
    116 	struct rup_data *d2;
    117 {
    118 	switch(sort_type) {
    119 	case SORT_HOST:
    120 		return strcmp(d1->host, d2->host);
    121 	case SORT_LDAV:
    122 		return d1->statstime.avenrun[0]
    123 			- d2->statstime.avenrun[0];
    124 	case SORT_UPTIME:
    125 		return d1->statstime.boottime.tv_sec
    126 			- d2->statstime.boottime.tv_sec;
    127 	default:
    128 		/* something's really wrong here */
    129 		abort();
    130 	}
    131 }
    132 
    133 void
    134 remember_rup_data(host, st)
    135 	char *host;
    136 	struct statstime *st;
    137 {
    138         if (rup_data_idx >= rup_data_max) {
    139                 rup_data_max += 16;
    140                 rup_data = realloc (rup_data,
    141 				rup_data_max * sizeof(struct rup_data));
    142                 if (rup_data == NULL) {
    143                         err (1, NULL);
    144 			/* NOTREACHED */
    145                 }
    146         }
    147 
    148 	rup_data[rup_data_idx].host = strdup(host);
    149 	rup_data[rup_data_idx].statstime = *st;
    150 	rup_data_idx++;
    151 }
    152 
    153 
    154 int
    155 rstat_reply(replyp, raddrp)
    156 	char *replyp;
    157 	struct sockaddr_in *raddrp;
    158 {
    159 	struct hostent *hp;
    160 	char *host;
    161 	statstime *host_stat = (statstime *)replyp;
    162 
    163 	if (!search_host(raddrp->sin_addr)) {
    164 		hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
    165 			sizeof(struct in_addr), AF_INET);
    166 
    167 		if (hp)
    168 			host = hp->h_name;
    169 		else
    170 			host = inet_ntoa(raddrp->sin_addr);
    171 
    172 		remember_host(raddrp->sin_addr);
    173 
    174 		if (sort_type != SORT_NONE) {
    175 			remember_rup_data(host, host_stat);
    176 		} else {
    177 			print_rup_data(host, host_stat);
    178 		}
    179 	}
    180 
    181 	return (0);
    182 }
    183 
    184 
    185 int
    186 print_rup_data(host, host_stat)
    187 	char *host;
    188 	statstime *host_stat;
    189 {
    190 	struct tm *tmp_time;
    191 	struct tm host_time;
    192 	struct tm host_uptime;
    193 	char days_buf[16];
    194 	char hours_buf[16];
    195 
    196 	printf("%-*.*s", HOST_WIDTH, HOST_WIDTH, host);
    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 
    203 	tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec);
    204 	host_uptime = *tmp_time;
    205 
    206 	if (host_uptime.tm_yday != 0)
    207 		sprintf(days_buf, "%3d day%s, ", host_uptime.tm_yday,
    208 			(host_uptime.tm_yday > 1) ? "s" : "");
    209 	else
    210 		days_buf[0] = '\0';
    211 
    212 	if (host_uptime.tm_hour != 0)
    213 		sprintf(hours_buf, "%2d:%02d, ",
    214 			host_uptime.tm_hour, host_uptime.tm_min);
    215 	else
    216 		if (host_uptime.tm_min != 0)
    217 			sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min);
    218 		else
    219 			hours_buf[0] = '\0';
    220 
    221 	if (printtime)
    222 		printf(" %2d:%02d%cm",
    223 		    (host_time.tm_hour % 12) ? (host_time.tm_hour % 12) : 12,
    224 		    host_time.tm_min, (host_time.tm_hour >= 12) ? 'p' : 'a');
    225 
    226 	printf(" up %9.9s%9.9s load average: %.2f %.2f %.2f\n",
    227 		days_buf, hours_buf,
    228 		(double)host_stat->avenrun[0]/FSCALE,
    229 		(double)host_stat->avenrun[1]/FSCALE,
    230 		(double)host_stat->avenrun[2]/FSCALE);
    231 
    232 	return(0);
    233 }
    234 
    235 
    236 void
    237 onehost(host)
    238 	char *host;
    239 {
    240 	CLIENT *rstat_clnt;
    241 	statstime host_stat;
    242 	static struct timeval timeout = {25, 0};
    243 
    244 	rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp");
    245 	if (rstat_clnt == NULL) {
    246 		warnx("%s", clnt_spcreateerror(host));
    247 		return;
    248 	}
    249 
    250 	bzero((char *)&host_stat, sizeof(host_stat));
    251 	if (clnt_call(rstat_clnt, RSTATPROC_STATS, xdr_void, NULL, xdr_statstime, &host_stat, timeout) != RPC_SUCCESS) {
    252 		warnx("%s",  clnt_sperror(rstat_clnt, host));
    253 		return;
    254 	}
    255 
    256 	print_rup_data(host, &host_stat);
    257 	clnt_destroy(rstat_clnt);
    258 }
    259 
    260 void
    261 allhosts()
    262 {
    263 	statstime host_stat;
    264 	enum clnt_stat clnt_stat;
    265 	size_t i;
    266 
    267 	if (sort_type != SORT_NONE) {
    268 		printf("collecting responses...");
    269 		fflush(stdout);
    270 	}
    271 
    272 	clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
    273 				   xdr_void, NULL,
    274 				   xdr_statstime, &host_stat, rstat_reply);
    275 	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) {
    276 		warnx("%s", clnt_sperrno(clnt_stat));
    277 		exit(1);
    278 	}
    279 
    280 	if (sort_type != SORT_NONE) {
    281 		putchar('\n');
    282 		qsort(rup_data, rup_data_idx, sizeof(struct rup_data), compare);
    283 
    284 		for (i = 0; i < rup_data_idx; i++) {
    285 			print_rup_data(rup_data[i].host, &rup_data[i].statstime);
    286 		}
    287 	}
    288 }
    289 
    290 
    291 main(argc, argv)
    292 	int argc;
    293 	char *argv[];
    294 {
    295 	int ch;
    296 	extern int optind;
    297 
    298 	sort_type = SORT_NONE;
    299 	while ((ch = getopt(argc, argv, "dhlt")) != -1)
    300 		switch (ch) {
    301 		case 'd':
    302 			printtime = 1;
    303 			break;
    304 		case 'h':
    305 			sort_type = SORT_HOST;
    306 			break;
    307 		case 'l':
    308 			sort_type = SORT_LDAV;
    309 			break;
    310 		case 't':
    311 			sort_type = SORT_UPTIME;
    312 			break;
    313 		default:
    314 			usage();
    315 			/*NOTREACHED*/
    316 		}
    317 
    318 	setlinebuf(stdout);
    319 
    320 	if (argc == optind)
    321 		allhosts();
    322 	else {
    323 		for (; optind < argc; optind++)
    324 			onehost(argv[optind]);
    325 	}
    326 
    327 	exit(0);
    328 }
    329 
    330 
    331 usage()
    332 {
    333 	fprintf(stderr, "Usage: rup [-dhlt] [hosts ...]\n");
    334 	exit(1);
    335 }
    336