rup.c revision 78456
1266733Speter/*- 2266733Speter * Copyright (c) 1993, John Brezak 3266733Speter * All rights reserved. 4266733Speter * 5266733Speter * Redistribution and use in source and binary forms, with or without 6266733Speter * modification, are permitted provided that the following conditions 7266733Speter * are met: 8266733Speter * 1. Redistributions of source code must retain the above copyright 9266733Speter * notice, this list of conditions and the following disclaimer. 10266733Speter * 2. Redistributions in binary form must reproduce the above copyright 11266733Speter * notice, this list of conditions and the following disclaimer in the 12266733Speter * documentation and/or other materials provided with the distribution. 13266733Speter * 3. All advertising materials mentioning features or use of this software 14266733Speter * must display the following acknowledgement: 15266733Speter * This product includes software developed by the University of 16266733Speter * California, Berkeley and its contributors. 17266733Speter * 4. Neither the name of the University nor the names of its contributors 18266733Speter * may be used to endorse or promote products derived from this software 19266733Speter * without specific prior written permission. 20266733Speter * 21266733Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22266733Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23266733Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24266733Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25266733Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26266733Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27266733Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28266733Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29266733Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30266733Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31266733Speter * SUCH DAMAGE. 32266733Speter */ 33266733Speter 34266733Speter#ifndef lint 35266733Speterstatic const char rcsid[] = 36266733Speter "$FreeBSD: head/usr.bin/rup/rup.c 78456 2001-06-19 03:48:26Z mikeh $"; 37266733Speter#endif /* not lint */ 38266733Speter 39266733Speter#include <err.h> 40266733Speter#include <stdio.h> 41266733Speter#include <stdlib.h> 42266733Speter#include <string.h> 43266733Speter#include <time.h> 44266733Speter#include <unistd.h> 45266733Speter#include <sys/param.h> 46266733Speter#include <sys/socket.h> 47266733Speter#include <netdb.h> 48266733Speter#include <rpc/rpc.h> 49266733Speter#include <rpc/pmap_clnt.h> 50266733Speter#include <arpa/inet.h> 51266733Speter#undef FSHIFT /* Use protocol's shift and scale values */ 52266733Speter#undef FSCALE 53266733Speter#include <rpcsvc/rstat.h> 54266733Speter 55266733Speter#define HOST_WIDTH 15 56266733Speter 57266733Speterstruct host_list { 58266733Speter struct host_list *next; 59266733Speter struct in_addr addr; 60266733Speter} *hosts; 61266733Speter 62266733Speterint search_host(struct in_addr addr) 63266733Speter{ 64266733Speter struct host_list *hp; 65266733Speter 66266733Speter if (!hosts) 67266733Speter return(0); 68266733Speter 69266733Speter for (hp = hosts; hp != NULL; hp = hp->next) { 70266733Speter if (hp->addr.s_addr == addr.s_addr) 71266733Speter return(1); 72266733Speter } 73266733Speter return(0); 74266733Speter} 75266733Speter 76266733Spetervoid remember_host(struct in_addr addr) 77266733Speter{ 78266733Speter struct host_list *hp; 79266733Speter 80266733Speter if (!(hp = (struct host_list *)malloc(sizeof(struct host_list)))) 81266733Speter errx(1, "no memory"); 82266733Speter hp->addr.s_addr = addr.s_addr; 83266733Speter hp->next = hosts; 84266733Speter hosts = hp; 85266733Speter} 86266733Speter 87266733Speterint 88266733Speterrstat_reply(caddr_t replyp, struct sockaddr_in *raddrp) 89266733Speter{ 90266733Speter struct tm *tmp_time; 91266733Speter struct tm host_time; 92266733Speter struct tm host_uptime; 93266733Speter char days_buf[16]; 94266733Speter char hours_buf[16]; 95266733Speter struct hostent *hp; 96266733Speter char *host; 97266733Speter statstime *host_stat = (statstime *)replyp; 98266733Speter 99266733Speter if (search_host(raddrp->sin_addr)) 100266733Speter return(0); 101266733Speter 102266733Speter hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr, 103266733Speter sizeof(struct in_addr), AF_INET); 104266733Speter if (hp) 105266733Speter host = hp->h_name; 106266733Speter else 107266733Speter host = inet_ntoa(raddrp->sin_addr); 108266733Speter 109266733Speter /* truncate hostname to fit nicely into field */ 110266733Speter if (strlen(host) > HOST_WIDTH) 111266733Speter host[HOST_WIDTH] = '\0'; 112266733Speter 113266733Speter printf("%-*s\t", HOST_WIDTH, host); 114266733Speter 115266733Speter tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec); 116266733Speter host_time = *tmp_time; 117266733Speter 118266733Speter host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; 119266733Speter 120266733Speter tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec); 121266733Speter host_uptime = *tmp_time; 122266733Speter 123266733Speter #define updays (host_stat->curtime.tv_sec / 86400) 124266733Speter if (host_uptime.tm_yday != 0) 125266733Speter sprintf(days_buf, "%3d day%s, ", updays, 126266733Speter (updays > 1) ? "s" : ""); 127266733Speter else 128266733Speter days_buf[0] = '\0'; 129266733Speter 130266733Speter if (host_uptime.tm_hour != 0) 131266733Speter sprintf(hours_buf, "%2d:%02d, ", 132266733Speter host_uptime.tm_hour, host_uptime.tm_min); 133266733Speter else 134266733Speter if (host_uptime.tm_min != 0) 135266733Speter sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min); 136266733Speter else 137266733Speter hours_buf[0] = '\0'; 138266733Speter 139266733Speter printf(" %2d:%02d%cm up %9.9s%9.9s load average: %.2f %.2f %.2f\n", 140266733Speter (host_time.tm_hour % 12) ? host_time.tm_hour % 12 : 12, 141266733Speter host_time.tm_min, 142266733Speter (host_time.tm_hour >= 12) ? 'p' : 'a', 143266733Speter days_buf, 144266733Speter hours_buf, 145266733Speter (double)host_stat->avenrun[0]/FSCALE, 146266733Speter (double)host_stat->avenrun[1]/FSCALE, 147266733Speter (double)host_stat->avenrun[2]/FSCALE); 148266733Speter 149266733Speter remember_host(raddrp->sin_addr); 150266733Speter return(0); 151266733Speter} 152266733Speter 153266733Speterint 154266733Speteronehost(char *host) 155266733Speter{ 156266733Speter CLIENT *rstat_clnt; 157266733Speter statstime host_stat; 158266733Speter struct sockaddr_in addr; 159266733Speter struct hostent *hp; 160266733Speter struct timeval tv; 161266733Speter 162266733Speter hp = gethostbyname(host); 163266733Speter if (hp == NULL) { 164266733Speter warnx("unknown host \"%s\"", host); 165266733Speter return(-1); 166266733Speter } 167266733Speter 168266733Speter rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp"); 169266733Speter if (rstat_clnt == NULL) { 170266733Speter warnx("%s %s", host, clnt_spcreateerror("")); 171266733Speter return(-1); 172266733Speter } 173266733Speter 174266733Speter bzero((char *)&host_stat, sizeof(host_stat)); 175266733Speter tv.tv_sec = 15; /* XXX ??? */ 176266733Speter tv.tv_usec = 0; 177266733Speter if (clnt_call(rstat_clnt, RSTATPROC_STATS, xdr_void, NULL, xdr_statstime, &host_stat, tv) != RPC_SUCCESS) { 178266733Speter warnx("%s: %s", host, clnt_sperror(rstat_clnt, host)); 179266733Speter clnt_destroy(rstat_clnt); 180266733Speter return(-1); 181266733Speter } 182266733Speter 183266733Speter addr.sin_addr.s_addr = *(int *)hp->h_addr; 184266733Speter rstat_reply((caddr_t)&host_stat, &addr); 185266733Speter clnt_destroy(rstat_clnt); 186266733Speter return (0); 187266733Speter} 188266733Speter 189266733Spetervoid 190266733Speterallhosts() 191266733Speter{ 192266733Speter statstime host_stat; 193266733Speter enum clnt_stat clnt_stat; 194266733Speter 195266733Speter clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, 196266733Speter xdr_void, NULL, 197266733Speter xdr_statstime, (char *)&host_stat, rstat_reply); 198266733Speter if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 199266733Speter errx(1, "%s", clnt_sperrno(clnt_stat)); 200266733Speter} 201266733Speter 202266733Speterstatic void 203266733Speterusage() 204266733Speter{ 205266733Speter fprintf(stderr, "usage: rup [hosts ...]\n"); 206266733Speter exit(1); 207266733Speter} 208266733Speter 209266733Speterint 210266733Spetermain(int argc, char *argv[]) 211266733Speter{ 212266733Speter int ch; 213266733Speter 214266733Speter while ((ch = getopt(argc, argv, "?")) != -1) 215266733Speter switch (ch) { 216266733Speter default: 217266733Speter usage(); 218266733Speter /*NOTREACHED*/ 219266733Speter } 220266733Speter 221266733Speter setlinebuf(stdout); 222266733Speter if (argc == optind) 223266733Speter allhosts(); 224266733Speter else { 225266733Speter for (; optind < argc; optind++) 226266733Speter (void) onehost(argv[optind]); 227266733Speter } 228266733Speter exit(0); 229266733Speter} 230266733Speter