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$"); 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; 104153090Sphilip time_t tmp_time_t; 1052343Scsgr 1062343Scsgr if (search_host(raddrp->sin_addr)) 1072343Scsgr return(0); 1088874Srgrimes 1092343Scsgr hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr, 1102343Scsgr sizeof(struct in_addr), AF_INET); 1112343Scsgr if (hp) 1122343Scsgr host = hp->h_name; 1132343Scsgr else 1142343Scsgr host = inet_ntoa(raddrp->sin_addr); 1152343Scsgr 1162343Scsgr /* truncate hostname to fit nicely into field */ 1172343Scsgr if (strlen(host) > HOST_WIDTH) 1182343Scsgr host[HOST_WIDTH] = '\0'; 1192343Scsgr 1202343Scsgr printf("%-*s\t", HOST_WIDTH, host); 1212343Scsgr 122153090Sphilip if (sizeof(time_t) == sizeof(host_stat->curtime.tv_sec)) { 123153090Sphilip tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec); 124153090Sphilip host_time = *tmp_time; 1252343Scsgr 126153090Sphilip host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; 1272343Scsgr 128153090Sphilip tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec); 129153090Sphilip host_uptime = *tmp_time; 130153090Sphilip } 131153090Sphilip else { /* non-32-bit time_t */ 132153090Sphilip tmp_time_t = host_stat->curtime.tv_sec; 133153090Sphilip tmp_time = localtime(&tmp_time_t); 134153090Sphilip host_time = *tmp_time; 1352343Scsgr 136153090Sphilip host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; 137153090Sphilip 138153090Sphilip tmp_time_t = host_stat->curtime.tv_sec; 139153090Sphilip tmp_time = gmtime(&tmp_time_t); 140153090Sphilip host_uptime = *tmp_time; 141153090Sphilip } 142153090Sphilip 14312445Swpaul #define updays (host_stat->curtime.tv_sec / 86400) 1442343Scsgr if (host_uptime.tm_yday != 0) 14512445Swpaul sprintf(days_buf, "%3d day%s, ", updays, 14612445Swpaul (updays > 1) ? "s" : ""); 1472343Scsgr else 1482343Scsgr days_buf[0] = '\0'; 1492343Scsgr 1502343Scsgr if (host_uptime.tm_hour != 0) 1512343Scsgr sprintf(hours_buf, "%2d:%02d, ", 1522343Scsgr host_uptime.tm_hour, host_uptime.tm_min); 1532343Scsgr else 1542343Scsgr if (host_uptime.tm_min != 0) 1552343Scsgr sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min); 15685039Sfenner else if (host_stat->curtime.tv_sec < 60) 15785039Sfenner sprintf(hours_buf, "%2d secs, ", host_uptime.tm_sec); 1582343Scsgr else 1592343Scsgr hours_buf[0] = '\0'; 1602343Scsgr 1612343Scsgr printf(" %2d:%02d%cm up %9.9s%9.9s load average: %.2f %.2f %.2f\n", 16234993Sdanny (host_time.tm_hour % 12) ? host_time.tm_hour % 12 : 12, 1632343Scsgr host_time.tm_min, 1642343Scsgr (host_time.tm_hour >= 12) ? 'p' : 'a', 1652343Scsgr days_buf, 1662343Scsgr hours_buf, 1672343Scsgr (double)host_stat->avenrun[0]/FSCALE, 1682343Scsgr (double)host_stat->avenrun[1]/FSCALE, 1692343Scsgr (double)host_stat->avenrun[2]/FSCALE); 1702343Scsgr 1712343Scsgr remember_host(raddrp->sin_addr); 1722343Scsgr return(0); 1732343Scsgr} 1742343Scsgr 17595616Smarkmstatic int 1762343Scsgronehost(char *host) 1772343Scsgr{ 1782343Scsgr CLIENT *rstat_clnt; 1792343Scsgr statstime host_stat; 1802343Scsgr struct sockaddr_in addr; 1812343Scsgr struct hostent *hp; 18221093Speter struct timeval tv; 1838874Srgrimes 1842343Scsgr hp = gethostbyname(host); 1852343Scsgr if (hp == NULL) { 18627955Scharnier warnx("unknown host \"%s\"", host); 1872343Scsgr return(-1); 1882343Scsgr } 1892343Scsgr 1902343Scsgr rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp"); 1912343Scsgr if (rstat_clnt == NULL) { 19227955Scharnier warnx("%s %s", host, clnt_spcreateerror("")); 1932343Scsgr return(-1); 1942343Scsgr } 1952343Scsgr 1962343Scsgr bzero((char *)&host_stat, sizeof(host_stat)); 19721093Speter tv.tv_sec = 15; /* XXX ??? */ 19821093Speter tv.tv_usec = 0; 199121545Speter if (clnt_call(rstat_clnt, RSTATPROC_STATS, 200121545Speter (xdrproc_t)xdr_void, NULL, 201121545Speter (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) { 20227955Scharnier warnx("%s: %s", host, clnt_sperror(rstat_clnt, host)); 20378456Smikeh clnt_destroy(rstat_clnt); 2042343Scsgr return(-1); 2052343Scsgr } 2062343Scsgr 2072343Scsgr addr.sin_addr.s_addr = *(int *)hp->h_addr; 20874462Salfred rstat_reply((caddr_t)&host_stat, &addr); 20978456Smikeh clnt_destroy(rstat_clnt); 21027955Scharnier return (0); 2112343Scsgr} 2122343Scsgr 21395616Smarkmstatic void 21495616Smarkmallhosts(void) 2152343Scsgr{ 2162343Scsgr statstime host_stat; 2172343Scsgr enum clnt_stat clnt_stat; 2182343Scsgr 2192343Scsgr clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, 220121545Speter (xdrproc_t)xdr_void, NULL, 221121545Speter (xdrproc_t)xdr_statstime, &host_stat, 222121545Speter (resultproc_t)rstat_reply); 22327955Scharnier if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 22427955Scharnier errx(1, "%s", clnt_sperrno(clnt_stat)); 2252343Scsgr} 2262343Scsgr 22727955Scharnierstatic void 22895616Smarkmusage(void) 2292343Scsgr{ 230146466Sru fprintf(stderr, "usage: rup [host ...]\n"); 2312343Scsgr exit(1); 2322343Scsgr} 2332343Scsgr 23427955Scharnierint 2352343Scsgrmain(int argc, char *argv[]) 2362343Scsgr{ 2372343Scsgr int ch; 2382343Scsgr 2392343Scsgr while ((ch = getopt(argc, argv, "?")) != -1) 2402343Scsgr switch (ch) { 2412343Scsgr default: 2422343Scsgr usage(); 2432343Scsgr /*NOTREACHED*/ 2442343Scsgr } 2458874Srgrimes 2462343Scsgr setlinebuf(stdout); 2472343Scsgr if (argc == optind) 2482343Scsgr allhosts(); 2492343Scsgr else { 2502343Scsgr for (; optind < argc; optind++) 2512343Scsgr (void) onehost(argv[optind]); 2522343Scsgr } 2532343Scsgr exit(0); 2542343Scsgr} 255