8764 rup: variable set but not used
[unleashed.git] / usr / src / cmd / rpcsvc / rup.c
blobec6aba5c3edbd5ceb790a0d40f9cceb70fcdedae
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <netdb.h>
31 #include <sys/param.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <rpc/rpc.h>
37 #include <netdir.h>
38 #include <rpcsvc/rstat.h>
39 #include <rpc/pmap_clnt.h>
42 #define MACHINELEN 15 /* length of machine name printed out */
43 #define MACHINELENMAX 128 /* maximum machine name length */
44 #define AVENSIZE (3 * sizeof (long))
45 #define SLOTS 256
47 int machinecmp();
48 int loadcmp();
49 int uptimecmp();
50 static int collectnames();
51 int singlehost(); /* returns 1 if rup of given host fails */
52 void printsinglehosts();
53 void printnames();
54 static void putline();
55 int netbufeq(struct netbuf *ap, struct netbuf *bp);
56 void usage(void);
58 struct entry {
59 struct netconfig *nconf;
60 struct netbuf *addr;
61 char *machine;
62 struct timeval boottime;
63 time_t curtime;
64 long avenrun[3];
67 int total_entries;
68 int curentry;
69 struct entry *entry;
70 int vers; /* which version did the broadcasting */
71 int lflag; /* load: sort by load average */
72 int tflag; /* time: sort by uptime average */
73 int hflag; /* host: sort by machine name */
74 int dflag; /* debug: list only first n machines */
75 int debug;
77 int
78 main(int argc, char *argv[])
80 statsvar sv;
81 statstime st;
82 int single, nfailed;
85 * set number of slots to be 256 to begin with,
86 * this is large enough for most subnets but not all
89 curentry = 0;
90 total_entries = SLOTS;
91 entry = malloc(sizeof (struct entry) * total_entries);
92 single = nfailed = 0;
93 while (argc > 1) {
94 if (argv[1][0] != '-') {
95 single++;
96 nfailed += singlehost(argv[1]);
97 } else {
98 switch (argv[1][1]) {
100 case 'l':
101 lflag++;
102 break;
103 case 't':
104 tflag++;
105 break;
106 case 'h':
107 hflag++;
108 break;
109 case 'd':
110 dflag++;
111 if (argc < 3)
112 usage();
113 debug = atoi(argv[2]);
114 argc--;
115 argv++;
116 break;
117 default:
118 usage();
121 argv++;
122 argc--;
124 if (single > 0) {
125 if (hflag || tflag || lflag)
126 printsinglehosts();
127 if (nfailed == single) {
128 free(entry);
129 exit(1); /* all hosts we tried failed */
130 } else {
131 free(entry);
132 exit(0);
136 if (hflag || tflag || lflag) {
137 printf("collecting responses... ");
138 fflush(stdout);
141 sv.cp_time.cp_time_val = (int *)NULL;
142 sv.dk_xfer.dk_xfer_val = (int *)NULL;
145 * Null out pointers in the statsvar struct
146 * so that we don't follow a random pointer
147 * somewhere when we get our results back.
148 * Set lengths to zero so we don't allocate
149 * some random amount of space we don't need
150 * (in the case where the reply was program
151 * not registered).
153 sv.cp_time.cp_time_len = 0;
154 sv.cp_time.cp_time_val = (int *)NULL;
155 sv.dk_xfer.dk_xfer_len = 0;
156 sv.dk_xfer.dk_xfer_val = (int *)NULL;
158 vers = RSTATVERS_VAR;
159 (void) rpc_broadcast(RSTATPROG, RSTATVERS_VAR, RSTATPROC_STATS,
160 xdr_void, NULL, xdr_statsvar, (caddr_t)&sv,
161 (resultproc_t)collectnames, (char *)0);
162 vers = RSTATVERS_TIME;
163 (void) rpc_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
164 xdr_void, NULL, xdr_statstime, (caddr_t)&st,
165 (resultproc_t)collectnames, (char *)0);
166 if (hflag || tflag || lflag)
167 printnames();
171 free(entry);
172 return (0);
176 singlehost(host)
177 char *host;
179 static int debugcnt;
180 enum clnt_stat err;
181 statstime st;
182 statsvar sw_var;
183 bool_t is_var_vers = FALSE;
186 if (curentry >= total_entries) {
187 struct entry *tmp;
189 total_entries += SLOTS;
190 tmp = realloc((struct entry *)entry, sizeof (struct entry)
191 * total_entries);
192 if (tmp == NULL) {
193 return (1);
195 entry = tmp;
198 sw_var.cp_time.cp_time_val = (int *)NULL;
199 sw_var.dk_xfer.dk_xfer_val = (int *)NULL;
200 err = (enum clnt_stat)callrpc(host, RSTATPROG, RSTATVERS_VAR,
201 RSTATPROC_STATS, xdr_void, 0, xdr_statsvar, &sw_var);
202 if (err == RPC_SUCCESS) {
203 is_var_vers = TRUE;
204 } else if (err == RPC_PROGVERSMISMATCH) {
205 err = (enum clnt_stat)callrpc(host, RSTATPROG, RSTATVERS_TIME,
206 RSTATPROC_STATS, xdr_void, 0, xdr_statstime, &st);
207 if (err != RPC_SUCCESS)
208 goto error;
209 } else
210 goto error;
212 debugcnt++;
213 if (!hflag && !lflag && !tflag) {
214 printf("%*.*s ", MACHINELEN, MACHINELEN, host);
215 if (is_var_vers == TRUE)
216 putline(sw_var.curtime.tv_sec, sw_var.boottime,
217 sw_var.avenrun);
218 else
219 putline(st.curtime.tv_sec, st.boottime, st.avenrun);
220 return (0); /* success */
221 } else {
222 entry[curentry].machine = host;
223 if (is_var_vers == FALSE) { /* RSTATVERS_TIME */
224 entry[curentry].boottime.tv_sec = st.boottime.tv_sec;
225 entry[curentry].boottime.tv_usec =
226 st.boottime.tv_usec;
227 entry[curentry].curtime = st.curtime.tv_sec;
228 memcpy(entry[curentry].avenrun, st.avenrun, AVENSIZE);
229 } else { /* RSTATVERS_VAR */
230 entry[curentry].boottime.tv_sec =
231 sw_var.boottime.tv_sec;
232 entry[curentry].boottime.tv_usec =
233 sw_var.boottime.tv_usec;
234 entry[curentry].curtime = sw_var.curtime.tv_sec;
235 memcpy(entry[curentry].avenrun, sw_var.avenrun,
236 AVENSIZE);
239 curentry++;
240 if (dflag && debugcnt >= debug)
241 return (1);
242 return (0);
244 error:
245 fprintf(stderr, "%*.*s: ", MACHINELEN, MACHINELEN, host);
246 clnt_perrno(err);
248 * clnt_perrno now prints a newline
250 /* fprintf(stderr, "\n"); */
251 return (1); /* a failure */
254 static void
255 putline(now, boottime, avenrun)
256 time_t now;
257 struct timeval boottime;
258 long avenrun[];
260 int uptime, days, hrs, mins, i;
262 uptime = now - boottime.tv_sec;
263 uptime += 30;
264 if (uptime < 0) /* unsynchronized clocks */
265 uptime = 0;
266 days = uptime / (60*60*24);
267 uptime %= (60*60*24);
268 hrs = uptime / (60*60);
269 uptime %= (60*60);
270 mins = uptime / 60;
272 printf(" up");
273 if (days > 0)
274 printf(" %2d day%s", days, days > 1 ? "s," : ", ");
275 else
276 printf(" ");
277 if (hrs > 0)
278 printf(" %2d:%02d, ", hrs, mins);
279 else
280 printf(" %2d min%s", mins, mins > 1 ? "s," : ", ");
283 * Print 1, 5, and 15 minute load averages.
284 * (Found by looking in kernel for avenrun).
286 printf(" load average:");
287 for (i = 0; i < (AVENSIZE / sizeof (avenrun[0])); i++) {
288 if (i > 0)
289 printf(",");
290 printf(" %.2f", (double)avenrun[i]/FSCALE);
292 printf("\n");
295 static int
296 collectnames(resultsp, taddr, nconf)
297 char *resultsp;
298 struct t_bind *taddr;
299 struct netconfig *nconf;
301 static int debugcnt;
302 register struct entry *entryp, *lim;
303 statstime *st;
304 statsvar *sv;
305 struct nd_hostservlist *hs;
306 extern struct netbuf *netbufdup();
307 extern struct netconfig *netconfigdup();
308 extern int netbufeq();
311 * need to realloc more space if we have more than 256 machines
312 * that responded to the broadcast
315 if (curentry >= total_entries) {
316 struct entry *tmp;
318 total_entries += SLOTS;
319 tmp = realloc((struct entry *)entry, sizeof (struct entry)
320 * total_entries);
321 if (tmp == NULL) {
322 return (1);
324 entry = tmp;
327 * weed out duplicates
329 lim = entry + curentry;
330 for (entryp = entry; entryp < lim; entryp++)
331 if (netbufeq(&taddr->addr, entryp->addr))
332 return (0);
334 if (vers == RSTATVERS_TIME) {
335 st = (statstime *)resultsp;
336 } else if (vers == RSTATVERS_VAR) {
337 sv = (statsvar *)resultsp;
338 } else {
339 return (0); /* we don't handle this version */
341 debugcnt++;
342 entry[curentry].nconf = netconfigdup(nconf);
343 entry[curentry].addr = netbufdup(&taddr->addr);
346 * if raw, print this entry out immediately
347 * otherwise store for later sorting
349 if (!hflag && !lflag && !tflag) {
350 if (netdir_getbyaddr(nconf, &hs, &taddr->addr) == ND_OK)
351 printf("%*.*s ", MACHINELEN, MACHINELEN,
352 hs->h_hostservs->h_host);
353 else {
354 char *uaddr = taddr2uaddr(nconf, &taddr->addr);
356 if (uaddr) {
357 printf(" %*.*s", MACHINELEN, MACHINELEN,
358 uaddr);
359 (void) free(uaddr);
360 } else
361 printf(" %*.*s", MACHINELEN, MACHINELEN,
362 "unknown");
364 if (vers == RSTATVERS_TIME) {
365 putline(st->curtime.tv_sec, st->boottime, st->avenrun);
366 } else if (vers == RSTATVERS_VAR) {
367 putline(sv->curtime.tv_sec, sv->boottime, sv->avenrun);
369 } else {
370 if (vers == RSTATVERS_TIME) {
371 entry[curentry].boottime.tv_sec = st->boottime.tv_sec;
372 entry[curentry].boottime.tv_usec =
373 st->boottime.tv_usec;
374 entry[curentry].curtime = st->curtime.tv_sec;
375 memcpy(entry[curentry].avenrun, st->avenrun, AVENSIZE);
376 } else if (vers == RSTATVERS_VAR) {
377 entry[curentry].boottime.tv_sec = sv->boottime.tv_sec;
378 entry[curentry].boottime.tv_usec =
379 sv->boottime.tv_usec;
380 entry[curentry].curtime = sv->curtime.tv_sec;
381 memcpy(entry[curentry].avenrun, sv->avenrun, AVENSIZE);
384 curentry++;
385 if (dflag && debugcnt >= debug)
386 return (1);
387 return (0);
390 void
391 printsinglehosts()
393 register int i;
394 register struct entry *ep;
397 if (hflag)
398 qsort(entry, curentry, sizeof (struct entry), machinecmp);
399 else if (lflag)
400 qsort(entry, curentry, sizeof (struct entry), loadcmp);
401 else
402 qsort(entry, curentry, sizeof (struct entry), uptimecmp);
403 for (i = 0; i < curentry; i++) {
404 ep = &entry[i];
405 printf("%*.*s ", MACHINELEN, MACHINELEN, ep->machine);
406 putline(ep->curtime, ep->boottime, ep->avenrun);
411 void
412 printnames()
414 char buf[MACHINELENMAX+1];
415 struct nd_hostservlist *hs;
416 register int i;
417 register struct entry *ep;
420 for (i = 0; i < curentry; i++) {
421 ep = &entry[i];
422 if (netdir_getbyaddr(ep->nconf, &hs, ep->addr) == ND_OK)
423 sprintf(buf, "%s", hs->h_hostservs->h_host);
424 else {
425 char *uaddr = taddr2uaddr(ep->nconf, ep->addr);
427 if (uaddr) {
428 sprintf(buf, "%s", uaddr);
429 (void) free(uaddr);
430 } else
431 sprintf(buf, "%s", "unknown");
433 if (ep->machine = (char *)malloc(MACHINELENMAX + 1))
434 strcpy(ep->machine, buf);
436 printf("\n");
437 printsinglehosts();
441 machinecmp(struct entry *a, struct entry *b)
443 return (strcmp(a->machine, b->machine));
447 uptimecmp(struct entry *a, struct entry *b)
449 if (a->boottime.tv_sec != b->boottime.tv_sec)
450 return (a->boottime.tv_sec - b->boottime.tv_sec);
451 else
452 return (a->boottime.tv_usec - b->boottime.tv_usec);
456 loadcmp(struct entry *a, struct entry *b)
458 register int i;
460 for (i = 0; i < AVENSIZE / sizeof (a->avenrun[0]); i++)
461 if (a->avenrun[i] != b->avenrun[i])
462 return (a->avenrun[i] - b->avenrun[i]);
464 return (0);
467 struct netbuf *
468 netbufdup(ap)
469 register struct netbuf *ap;
471 register struct netbuf *np;
473 np = (struct netbuf *) malloc(sizeof (struct netbuf) + ap->len);
474 if (np) {
475 np->maxlen = np->len = ap->len;
476 np->buf = ((char *)np) + sizeof (struct netbuf);
477 (void) memcpy(np->buf, ap->buf, ap->len);
479 return (np);
482 struct netconfig *
483 netconfigdup(onp)
484 register struct netconfig *onp;
486 register int nlookupdirs;
487 register struct netconfig *nnp;
488 extern char *strdup();
490 nnp = (struct netconfig *)malloc(sizeof (struct netconfig));
491 if (nnp) {
492 nnp->nc_netid = strdup(onp->nc_netid);
493 nnp->nc_semantics = onp->nc_semantics;
494 nnp->nc_flag = onp->nc_flag;
495 nnp->nc_protofmly = strdup(onp->nc_protofmly);
496 nnp->nc_proto = strdup(onp->nc_proto);
497 nnp->nc_device = strdup(onp->nc_device);
498 nnp->nc_nlookups = onp->nc_nlookups;
499 if (onp->nc_nlookups == 0)
500 nnp->nc_lookups = (char **)0;
501 else {
502 register int i;
504 nnp->nc_lookups = (char **)malloc(onp->nc_nlookups *
505 sizeof (char *));
506 if (nnp->nc_lookups)
507 for (i = 0; i < onp->nc_nlookups; i++)
508 nnp->nc_lookups[i] =
509 strdup(onp->nc_lookups[i]);
513 return (nnp);
517 netbufeq(struct netbuf *ap, struct netbuf *bp)
519 return (ap->len == bp->len && !memcmp(ap->buf, bp->buf, ap->len));
522 void
523 usage(void)
525 fprintf(stderr, "Usage: rup [-h] [-l] [-t] [host ...]\n");
526 free(entry);
527 exit(1);