rup.c revision 146466
12343Scsgr/*-
22343Scsgr * Copyright (c) 1993, John Brezak
32343Scsgr * All rights reserved.
42343Scsgr *
52343Scsgr * Redistribution and use in source and binary forms, with or without
62343Scsgr * modification, are permitted provided that the following conditions
72343Scsgr * are met:
82343Scsgr * 1. Redistributions of source code must retain the above copyright
92343Scsgr *    notice, this list of conditions and the following disclaimer.
102343Scsgr * 2. Redistributions in binary form must reproduce the above copyright
112343Scsgr *    notice, this list of conditions and the following disclaimer in the
122343Scsgr *    documentation and/or other materials provided with the distribution.
132343Scsgr * 3. All advertising materials mentioning features or use of this software
142343Scsgr *    must display the following acknowledgement:
152343Scsgr *	This product includes software developed by the University of
162343Scsgr *	California, Berkeley and its contributors.
172343Scsgr * 4. Neither the name of the University nor the names of its contributors
182343Scsgr *    may be used to endorse or promote products derived from this software
192343Scsgr *    without specific prior written permission.
202343Scsgr *
212343Scsgr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
222343Scsgr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232343Scsgr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242343Scsgr * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
252343Scsgr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
262343Scsgr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
272343Scsgr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
282343Scsgr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
292343Scsgr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
302343Scsgr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312343Scsgr * SUCH DAMAGE.
322343Scsgr */
332343Scsgr
3495616Smarkm#include <sys/cdefs.h>
352343Scsgr
3695616Smarkm__FBSDID("$FreeBSD: head/usr.bin/rup/rup.c 146466 2005-05-21 09:55:10Z ru $");
3795616Smarkm
382343Scsgr#include <sys/param.h>
392343Scsgr#include <sys/socket.h>
4095616Smarkm
412343Scsgr#include <rpc/rpc.h>
4227955Scharnier#include <rpc/pmap_clnt.h>
4395616Smarkm
442343Scsgr#undef FSHIFT			/* Use protocol's shift and scale values */
452343Scsgr#undef FSCALE
4695616Smarkm
472343Scsgr#include <rpcsvc/rstat.h>
482343Scsgr
4995616Smarkm#include <arpa/inet.h>
5095616Smarkm
5195616Smarkm#include <err.h>
5295616Smarkm#include <netdb.h>
5395616Smarkm#include <stdio.h>
5495616Smarkm#include <string.h>
5595616Smarkm#include <stdlib.h>
5695616Smarkm#include <time.h>
5795616Smarkm#include <unistd.h>
5895616Smarkm
592343Scsgr#define HOST_WIDTH 15
602343Scsgr
612343Scsgrstruct host_list {
622343Scsgr	struct host_list *next;
632343Scsgr	struct in_addr addr;
642343Scsgr} *hosts;
652343Scsgr
6695616Smarkmstatic int
6795616Smarkmsearch_host(struct in_addr addr)
682343Scsgr{
692343Scsgr	struct host_list *hp;
708874Srgrimes
712343Scsgr	if (!hosts)
722343Scsgr		return(0);
732343Scsgr
742343Scsgr	for (hp = hosts; hp != NULL; hp = hp->next) {
752343Scsgr		if (hp->addr.s_addr == addr.s_addr)
762343Scsgr			return(1);
772343Scsgr	}
782343Scsgr	return(0);
792343Scsgr}
802343Scsgr
8195616Smarkmstatic void
8295616Smarkmremember_host(struct in_addr addr)
832343Scsgr{
842343Scsgr	struct host_list *hp;
852343Scsgr
8627955Scharnier	if (!(hp = (struct host_list *)malloc(sizeof(struct host_list))))
8727955Scharnier		errx(1, "no memory");
882343Scsgr	hp->addr.s_addr = addr.s_addr;
892343Scsgr	hp->next = hosts;
902343Scsgr	hosts = hp;
912343Scsgr}
922343Scsgr
93121545Speterstatic bool_t
9474462Salfredrstat_reply(caddr_t replyp, struct sockaddr_in *raddrp)
952343Scsgr{
962343Scsgr	struct tm *tmp_time;
972343Scsgr	struct tm host_time;
982343Scsgr	struct tm host_uptime;
992343Scsgr	char days_buf[16];
1002343Scsgr	char hours_buf[16];
1012343Scsgr	struct hostent *hp;
1022343Scsgr	char *host;
1032343Scsgr	statstime *host_stat = (statstime *)replyp;
1042343Scsgr
1052343Scsgr	if (search_host(raddrp->sin_addr))
1062343Scsgr		return(0);
1078874Srgrimes
1082343Scsgr	hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
1092343Scsgr			   sizeof(struct in_addr), AF_INET);
1102343Scsgr	if (hp)
1112343Scsgr		host = hp->h_name;
1122343Scsgr	else
1132343Scsgr		host = inet_ntoa(raddrp->sin_addr);
1142343Scsgr
1152343Scsgr	/* truncate hostname to fit nicely into field */
1162343Scsgr	if (strlen(host) > HOST_WIDTH)
1172343Scsgr		host[HOST_WIDTH] = '\0';
1182343Scsgr
1192343Scsgr	printf("%-*s\t", HOST_WIDTH, host);
1202343Scsgr
1212343Scsgr	tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec);
1222343Scsgr	host_time = *tmp_time;
1232343Scsgr
1242343Scsgr	host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec;
1252343Scsgr
1262343Scsgr	tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec);
1272343Scsgr	host_uptime = *tmp_time;
1282343Scsgr
12912445Swpaul	#define updays (host_stat->curtime.tv_sec  / 86400)
1302343Scsgr	if (host_uptime.tm_yday != 0)
13112445Swpaul		sprintf(days_buf, "%3d day%s, ", updays,
13212445Swpaul			(updays > 1) ? "s" : "");
1332343Scsgr	else
1342343Scsgr		days_buf[0] = '\0';
1352343Scsgr
1362343Scsgr	if (host_uptime.tm_hour != 0)
1372343Scsgr		sprintf(hours_buf, "%2d:%02d, ",
1382343Scsgr			host_uptime.tm_hour, host_uptime.tm_min);
1392343Scsgr	else
1402343Scsgr		if (host_uptime.tm_min != 0)
1412343Scsgr			sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min);
14285039Sfenner		else if (host_stat->curtime.tv_sec < 60)
14385039Sfenner			sprintf(hours_buf, "%2d secs, ", host_uptime.tm_sec);
1442343Scsgr		else
1452343Scsgr			hours_buf[0] = '\0';
1462343Scsgr
1472343Scsgr	printf(" %2d:%02d%cm  up %9.9s%9.9s load average: %.2f %.2f %.2f\n",
14834993Sdanny		(host_time.tm_hour % 12) ? host_time.tm_hour % 12 : 12,
1492343Scsgr		host_time.tm_min,
1502343Scsgr		(host_time.tm_hour >= 12) ? 'p' : 'a',
1512343Scsgr		days_buf,
1522343Scsgr		hours_buf,
1532343Scsgr		(double)host_stat->avenrun[0]/FSCALE,
1542343Scsgr		(double)host_stat->avenrun[1]/FSCALE,
1552343Scsgr		(double)host_stat->avenrun[2]/FSCALE);
1562343Scsgr
1572343Scsgr	remember_host(raddrp->sin_addr);
1582343Scsgr	return(0);
1592343Scsgr}
1602343Scsgr
16195616Smarkmstatic int
1622343Scsgronehost(char *host)
1632343Scsgr{
1642343Scsgr	CLIENT *rstat_clnt;
1652343Scsgr	statstime host_stat;
1662343Scsgr	struct sockaddr_in addr;
1672343Scsgr	struct hostent *hp;
16821093Speter	struct timeval tv;
1698874Srgrimes
1702343Scsgr	hp = gethostbyname(host);
1712343Scsgr	if (hp == NULL) {
17227955Scharnier		warnx("unknown host \"%s\"", host);
1732343Scsgr		return(-1);
1742343Scsgr	}
1752343Scsgr
1762343Scsgr	rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp");
1772343Scsgr	if (rstat_clnt == NULL) {
17827955Scharnier		warnx("%s %s", host, clnt_spcreateerror(""));
1792343Scsgr		return(-1);
1802343Scsgr	}
1812343Scsgr
1822343Scsgr	bzero((char *)&host_stat, sizeof(host_stat));
18321093Speter	tv.tv_sec = 15;	/* XXX ??? */
18421093Speter	tv.tv_usec = 0;
185121545Speter	if (clnt_call(rstat_clnt, RSTATPROC_STATS,
186121545Speter	    (xdrproc_t)xdr_void, NULL,
187121545Speter	    (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) {
18827955Scharnier		warnx("%s: %s", host, clnt_sperror(rstat_clnt, host));
18978456Smikeh		clnt_destroy(rstat_clnt);
1902343Scsgr		return(-1);
1912343Scsgr	}
1922343Scsgr
1932343Scsgr	addr.sin_addr.s_addr = *(int *)hp->h_addr;
19474462Salfred	rstat_reply((caddr_t)&host_stat, &addr);
19578456Smikeh	clnt_destroy(rstat_clnt);
19627955Scharnier	return (0);
1972343Scsgr}
1982343Scsgr
19995616Smarkmstatic void
20095616Smarkmallhosts(void)
2012343Scsgr{
2022343Scsgr	statstime host_stat;
2032343Scsgr	enum clnt_stat clnt_stat;
2042343Scsgr
2052343Scsgr	clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
206121545Speter				   (xdrproc_t)xdr_void, NULL,
207121545Speter				   (xdrproc_t)xdr_statstime, &host_stat,
208121545Speter				   (resultproc_t)rstat_reply);
20927955Scharnier	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
21027955Scharnier		errx(1, "%s", clnt_sperrno(clnt_stat));
2112343Scsgr}
2122343Scsgr
21327955Scharnierstatic void
21495616Smarkmusage(void)
2152343Scsgr{
216146466Sru	fprintf(stderr, "usage: rup [host ...]\n");
2172343Scsgr	exit(1);
2182343Scsgr}
2192343Scsgr
22027955Scharnierint
2212343Scsgrmain(int argc, char *argv[])
2222343Scsgr{
2232343Scsgr	int ch;
2242343Scsgr
2252343Scsgr	while ((ch = getopt(argc, argv, "?")) != -1)
2262343Scsgr		switch (ch) {
2272343Scsgr		default:
2282343Scsgr			usage();
2292343Scsgr			/*NOTREACHED*/
2302343Scsgr		}
2318874Srgrimes
2322343Scsgr	setlinebuf(stdout);
2332343Scsgr	if (argc == optind)
2342343Scsgr		allhosts();
2352343Scsgr	else {
2362343Scsgr		for (; optind < argc; optind++)
2372343Scsgr			(void) onehost(argv[optind]);
2382343Scsgr	}
2392343Scsgr	exit(0);
2402343Scsgr}
241