rup.c revision 1.7 1 /*-
2 * Copyright (c) 1993, John Brezak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char rcsid[] = "$Id: rup.c,v 1.7 1993/11/10 03:52:21 deraadt Exp $";
36 #endif /* not lint */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <sys/param.h>
43 #include <sys/socket.h>
44 #include <netdb.h>
45 #include <rpc/rpc.h>
46 #include <arpa/inet.h>
47
48 #undef FSHIFT /* Use protocol's shift and scale values */
49 #undef FSCALE
50 #include <rpcsvc/rstat.h>
51
52 #define HOST_WIDTH 24
53
54 char *argv0;
55
56 int printtime; /* print the remote host(s)'s time */
57
58 struct host_list {
59 struct host_list *next;
60 struct in_addr addr;
61 } *hosts;
62
63 int
64 search_host(addr)
65 struct in_addr addr;
66 {
67 struct host_list *hp;
68
69 if (!hosts)
70 return(0);
71
72 for (hp = hosts; hp != NULL; hp = hp->next) {
73 if (hp->addr.s_addr == addr.s_addr)
74 return(1);
75 }
76 return(0);
77 }
78
79 void
80 remember_host(addr)
81 struct in_addr addr;
82 {
83 struct host_list *hp;
84
85 if (!(hp = (struct host_list *)malloc(sizeof(struct host_list)))) {
86 fprintf(stderr, "%s: no memory.\n", argv0);
87 exit(1);
88 }
89 hp->addr.s_addr = addr.s_addr;
90 hp->next = hosts;
91 hosts = hp;
92 }
93
94 rstat_reply(replyp, raddrp)
95 char *replyp;
96 struct sockaddr_in *raddrp;
97 {
98 struct tm *tmp_time;
99 struct tm host_time;
100 struct tm host_uptime;
101 char days_buf[16];
102 char hours_buf[16];
103 struct hostent *hp;
104 char *host;
105 statstime *host_stat = (statstime *)replyp;
106
107 if (search_host(raddrp->sin_addr))
108 return(0);
109
110 hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
111 sizeof(struct in_addr), AF_INET);
112 if (hp)
113 host = hp->h_name;
114 else
115 host = inet_ntoa(raddrp->sin_addr);
116
117 printf("%-*.*s", HOST_WIDTH, HOST_WIDTH, host);
118
119 tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec);
120 host_time = *tmp_time;
121
122 host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec;
123
124 tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec);
125 host_uptime = *tmp_time;
126
127 if (host_uptime.tm_yday != 0)
128 sprintf(days_buf, "%3d day%s, ", host_uptime.tm_yday,
129 (host_uptime.tm_yday > 1) ? "s" : "");
130 else
131 days_buf[0] = '\0';
132
133 if (host_uptime.tm_hour != 0)
134 sprintf(hours_buf, "%2d:%02d, ",
135 host_uptime.tm_hour, host_uptime.tm_min);
136 else
137 if (host_uptime.tm_min != 0)
138 sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min);
139 else
140 hours_buf[0] = '\0';
141
142 if (printtime)
143 printf(" %2d:%02d%cm", host_time.tm_hour % 12,
144 host_time.tm_min,
145 (host_time.tm_hour >= 12) ? 'p' : 'a');
146
147 printf(" up %9.9s%9.9s load average: %.2f %.2f %.2f\n",
148 days_buf, hours_buf,
149 (double)host_stat->avenrun[0]/FSCALE,
150 (double)host_stat->avenrun[1]/FSCALE,
151 (double)host_stat->avenrun[2]/FSCALE);
152
153 remember_host(raddrp->sin_addr);
154 return(0);
155 }
156
157 onehost(host)
158 char *host;
159 {
160 CLIENT *rstat_clnt;
161 statstime host_stat;
162 struct sockaddr_in addr;
163 struct hostent *hp;
164
165 hp = gethostbyname(host);
166 if (hp == NULL) {
167 fprintf(stderr, "%s: unknown host \"%s\"\n",
168 argv0, host);
169 return(-1);
170 }
171
172 rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp");
173 if (rstat_clnt == NULL) {
174 fprintf(stderr, "%s: %s %s", argv0, host, clnt_spcreateerror(""));
175 return(-1);
176 }
177
178 bzero((char *)&host_stat, sizeof(host_stat));
179 if (clnt_call(rstat_clnt, RSTATPROC_STATS, xdr_void, NULL, xdr_statstime, &host_stat, NULL) != RPC_SUCCESS) {
180 fprintf(stderr, "%s: %s: %s\n", argv0, host, clnt_sperror(rstat_clnt, host));
181 return(-1);
182 }
183
184 addr.sin_addr.s_addr = *(int *)hp->h_addr;
185 rstat_reply((char *)&host_stat, &addr);
186 }
187
188 allhosts()
189 {
190 statstime host_stat;
191 enum clnt_stat clnt_stat;
192
193 clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
194 xdr_void, NULL,
195 xdr_statstime, &host_stat, rstat_reply);
196 if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) {
197 fprintf(stderr, "%s: %s\n", argv0, clnt_sperrno(clnt_stat));
198 exit(1);
199 }
200 }
201
202 usage()
203 {
204 fprintf(stderr, "Usage: %s [hosts ...]\n", argv0);
205 exit(1);
206 }
207
208 main(argc, argv)
209 int argc;
210 char *argv[];
211 {
212 int ch;
213 extern int optind;
214
215 if (!(argv0 = rindex(argv[0], '/')))
216 argv0 = argv[0];
217 else
218 argv0++;
219
220 while ((ch = getopt(argc, argv, "?t")) != -1)
221 switch (ch) {
222 case 't':
223 printtime++;
224 break;
225 default:
226 usage();
227 /*NOTREACHED*/
228 }
229
230 setlinebuf(stdout);
231 if (argc == optind)
232 allhosts();
233 else {
234 for (; optind < argc; optind++)
235 (void) onehost(argv[optind]);
236 }
237 exit(0);
238 }
239