home *** CD-ROM | disk | FTP | other *** search
- /**
- * This program may be copied, redistributed in any form,
- * source or binary, and used for any purpose, provided
- * this copyright notice is retained.
- *
- * @(#)rpc.c 3.1 12/15/93 (c) Copyright Brian P. Fitzgerald
- * Rensselaer Polytechnic Institute
- *
- **/
-
- #include "common.h"
- #include "rperf.h"
-
- static bool_t bcst_timo;
-
- static struct timeval call_timo = {25, 0};
-
- bool_t(*xdr_statsproc[]) () =
- {
- xdr_stats,
- xdr_statsswtch,
- xdr_statstime,
- xdr_statsvar,
- };
-
- char *emfilehelp[] = {
- "You may be trying to monitor too many hosts at once.",
- "Consider increasing the system per-process hard limit",
- "on open files, or else monitor fewer hosts.",
- "If you are using broadcast mode, try the -b option.",
- 0
- };
-
- char *doclnt_call_help[] = {
- "",
- "client call debug mode. key:",
- "m made client\tc called client\t\tv4,v3,v2,v1 version called",
- "- no call made\tM version mismatch\tx drop\t* down",
- "",
- 0
- };
-
- struct data *dp; /* link list head */
-
- int if_opackets_fixed = 1;
-
- void
- destroy_array(a)
- array *a;
- {
- if (a->val) {
- free((char *) a->val);
- a->val = (int *) NULL;
- }
- }
-
- /**
- * copy n ints from p to a->val
- **/
- void
- copy_to_array(a, p, n)
- array *a;
- int *p;
- unsigned int n;
- {
- int i;
-
- if (n > a->len) {
- (void) fprintf(stderr,
- "copy_to_array: attempt to overwrite end of array\n");
- exit(1);
- }
- if (!p) {
- (void) fprintf(stderr,
- "copy_to_array: no source array\n");
- exit(1);
- }
- if (!a->val) {
- (void) fprintf(stderr,
- "copy_to_array: no destination array\n");
- exit(1);
- }
- for (i = 0; i < n; i++)
- a->val[i] = p[i];
- return;
- }
-
- /**
- * allocate the value part of an array struct, size n
- **/
- void
- create_array(a, n)
- array *a;
- unsigned int n;
- {
- a->len = n;
- a->val = (int *) malloc((unsigned) n * sizeof(int));
- if (a->val == NULL) {
- perror("malloc");
- exit(1);
- }
- return;
- }
-
- /**
- * convert and store the received data
- **/
- stats_default *
- from_stats(s)
- stats_all *s;
- {
- static stats_default r;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, CPUSTATES);
- copy_to_array((array *) & r.cp_time, s->s1.cp_time, CPUSTATES);
- create_array((array *) & r.dk_xfer, DK_NDRIVE);
- copy_to_array((array *) & r.dk_xfer, s->s1.dk_xfer, DK_NDRIVE);
- r.v_pgpgin = s->s1.v_pgpgin;
- r.v_pgpgout = s->s1.v_pgpgout;
- r.v_pswpin = s->s1.v_pswpin;
- r.v_pswpout = s->s1.v_pswpout;
- r.v_intr = s->s1.v_intr;
- r.if_ipackets = s->s1.if_ipackets;
- r.if_ierrors = s->s1.if_ierrors;
- r.if_opackets = s->s1.if_opackets;
- r.if_oerrors = s->s1.if_oerrors;
- r.if_collisions = s->s1.if_collisions;
- if (gettimeofday((struct timeval *) & r.curtime,
- (struct timezone *) NULL) == -1) {
- perror("gettimeofday");
- exit(1);
- }
- return &r;
- }
-
- stats_default *
- from_statsswtch(s)
- stats_all *s;
- {
- int i;
- static stats_default r;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, CPUSTATES);
- copy_to_array((array *) & r.cp_time, s->s2.cp_time, CPUSTATES);
- create_array((array *) & r.dk_xfer, DK_NDRIVE);
- copy_to_array((array *) & r.dk_xfer, s->s2.dk_xfer, DK_NDRIVE);
- r.v_pgpgin = s->s2.v_pgpgin;
- r.v_pgpgout = s->s2.v_pgpgout;
- r.v_pswpin = s->s2.v_pswpin;
- r.v_pswpout = s->s2.v_pswpout;
- r.v_intr = s->s2.v_intr;
- r.if_ipackets = s->s2.if_ipackets;
- r.if_ierrors = s->s2.if_ierrors;
- r.if_opackets = s->s2.if_opackets;
- r.if_oerrors = s->s2.if_oerrors;
- r.if_collisions = s->s2.if_collisions;
- r.v_swtch = s->s2.v_swtch;
- for (i = 0; i < 3; i++)
- r.avenrun[i] = s->s2.avenrun[i];
- r.boottime = s->s2.boottime;
- if (gettimeofday((struct timeval *) & r.curtime,
- (struct timezone *) NULL) == -1) {
- perror("gettimeofday");
- exit(1);
- }
- return &r;
- }
-
- stats_default *
- from_statstime(s)
- stats_all *s;
- {
- int i;
- static stats_default r;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, CPUSTATES);
- copy_to_array((array *) & r.cp_time, s->s3.cp_time, CPUSTATES);
- create_array((array *) & r.dk_xfer, DK_NDRIVE);
- copy_to_array((array *) & r.dk_xfer, s->s3.dk_xfer, DK_NDRIVE);
- r.v_pgpgin = s->s3.v_pgpgin;
- r.v_pgpgout = s->s3.v_pgpgout;
- r.v_pswpin = s->s3.v_pswpin;
- r.v_pswpout = s->s3.v_pswpout;
- r.v_intr = s->s3.v_intr;
- r.if_ipackets = s->s3.if_ipackets;
- r.if_ierrors = s->s3.if_ierrors;
- r.if_opackets = s->s3.if_opackets;
- r.if_oerrors = s->s3.if_oerrors;
- r.if_collisions = s->s3.if_collisions;
- r.v_swtch = s->s3.v_swtch;
- for (i = 0; i < 3; i++)
- r.avenrun[i] = s->s3.avenrun[i];
- r.boottime = s->s3.boottime;
- r.curtime = s->s3.curtime;
- return &r;
- }
-
- stats_default *
- from_statsvar(s)
- stats_all *s;
- {
- int i;
- static stats_default r;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, s->s4.cp_len);
- copy_to_array((array *) & r.cp_time, s->s4.cp_val, s->s4.cp_len);
- create_array((array *) & r.dk_xfer, s->s4.dk_len);
- copy_to_array((array *) & r.dk_xfer, s->s4.dk_val, s->s4.dk_len);
- r.v_pgpgin = s->s4.v_pgpgin;
- r.v_pgpgout = s->s4.v_pgpgout;
- r.v_pswpin = s->s4.v_pswpin;
- r.v_pswpout = s->s4.v_pswpout;
- r.v_intr = s->s4.v_intr;
- r.if_ipackets = s->s4.if_ipackets;
- r.if_ierrors = s->s4.if_ierrors;
- r.if_opackets = s->s4.if_opackets;
- r.if_oerrors = s->s4.if_oerrors;
- r.if_collisions = s->s4.if_collisions;
- r.v_swtch = s->s4.v_swtch;
- for (i = 0; i < 3; i++)
- r.avenrun[i] = s->s4.avenrun[i];
- r.boottime = s->s4.boottime;
- r.curtime = s->s4.curtime;
- return &r;
- }
-
- stats_default *((*stats_convert[]) ()) =
- {
- from_stats,
- from_statsswtch,
- from_statstime,
- from_statsvar,
- };
-
- /**
- * free the cp_time and dk_xfer array in a stats_default struct
- **/
- void
- free_stats(s)
- stats_default *s;
- {
- destroy_array((array *) & s->cp_time);
- destroy_array((array *) & s->dk_xfer);
- return;
- }
-
- /**
- * save the results in a data structure
- * return 1 if the results were saved
- * return 0 if the results were ignored
- **/
- int
- save_res(d, res)
- struct data *d;
- stats_default *res;
- {
- if (d->nn == thiscount) {
- free_stats(res);
- return 0; /* duplicate. ignore */
- }
- d->no = d->nn;
- d->nn = thiscount;
- if (!d->ok_to_call)
- (void) fprintf(stderr, " %s is back up ", d->host);
- d->ok_to_call = 1;
-
- free_stats(&d->so);
- d->so = d->sn;
- d->sn = *res;
- return 1;
- }
-
- /**
- * this function may be called after (*dpp)->addr
- * has been filled with a valid in_addr
- * return: 1=success, 0=fail
- **/
- int
- make_client(dpp)
- struct data **dpp;
- {
- int sock = RPC_ANYSOCK;
- static int emfilewarned;
- struct sockaddr_in server_addr;
- struct timeval p_timo;
-
- p_timo.tv_sec = 3;
- p_timo.tv_usec = 0;
-
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = 0;
- server_addr.sin_addr = (*dpp)->addr;
-
- /**
- * clntudp_create only determines whether the
- * program is registered. It does not actually check
- * whether the host supports the requested version.
- * see the pmap_getport man page.
- **/
- errno = 0;
- (*dpp)->cl = clntudp_create(&server_addr,
- RSTATPROG,
- (*dpp)->clnt_vers,
- p_timo,
- &sock);
-
- if ((*dpp)->cl == NULL) {
- if (rpc_createerr.cf_stat == RPC_SYSTEMERROR
- && rpc_createerr.cf_error.re_errno == EMFILE) {
- if (!emfilewarned) {
- (void) fprintf(stderr, "Can't contact rstatd on %s.\n",
- (*dpp)->host);
- (void) clnt_pcreateerror("clntudp_create");
- (void) fprintf(stderr, "Open file descriptor limit now %d\n",
- set_max_nofiles());
- msg(emfilehelp, stderr);
- emfilewarned = 1;
- }
- } else {
- (void) fprintf(stderr, "Can't contact rstatd on %s. ",
- (*dpp)->host);
- (void) clnt_pcreateerror("clntudp_create");
- }
- return 0;
- }
- if (dbg_lvl >= 2) {
- (void) putc('m', stderr);
- (void) fflush(stderr);
- }
- return 1;
- }
-
- /**
- * for each host on the linked list that still needs data:
- * loop over the rpc prog versions,
- * starting with the highest known version,
- * or highest previously successful version
- * make a client, if necessary
- * call the client
- **/
- void
- doclnt_calls(vers_max)
- u_long vers_max;
- {
- u_long vers;
- int good = 0;
- int bad = 0;
- static enum clnt_stat clnt_stat;
- stats_default *sn;
- struct data **dpp;
- stats_all resbuf;
-
- if (dbg_lvl >= 2)
- msg(doclnt_call_help, stderr);
-
- for (dpp = &dp; *dpp;) {
- if (dbg_lvl >= 2)
- (void) fprintf(stderr, "%s\t%s\t",
- inet_ntoa((*dpp)->addr), (*dpp)->host);
- if ((*dpp)->nn == thiscount) {
- dpp = &(*dpp)->datap;
- if (dbg_lvl >= 2) {
- (void) fputs("-\n", stderr);
- }
- continue; /* already have data */
- }
- if (!(*dpp)->ok_to_call) {
- dpp = &(*dpp)->datap;
- if (dbg_lvl >= 2) {
- (void) fputs("*\n", stderr);
- }
- continue; /* probably down */
- }
- if (!(*dpp)->clnt_vers)
- (*dpp)->clnt_vers = vers_max; /* try first */
-
- for (vers = (*dpp)->clnt_vers; vers > 0; vers--) {
- (*dpp)->clnt_vers = vers;
- if (!(*dpp)->cl)
- if (!make_client(dpp)) {
- (*dpp)->ok_to_call = 0;
- bad++;
- break; /* vers */
- }
- if (dbg_lvl >= 2) {
- (void) fprintf(stderr, "v%d", vers);
- (void) fflush(stderr);
- }
- bzero((char *) &resbuf, sizeof(resbuf));
- clnt_stat = clnt_call((*dpp)->cl,
- RSTATPROC_STATS,
- xdr_void,
- NULL,
- XDR_STATSPROC((*dpp)->clnt_vers),
- (char *) &resbuf,
- call_timo);
- if (clnt_stat == RPC_SUCCESS) {
- sn = STATS_CONVERT((*dpp)->clnt_vers) (&resbuf);
- /**
- * 11/3/93 I have checked that
- * xdr_free is needed here, so don't delete it
- **/
- xdr_free(XDR_STATSPROC((*dpp)->clnt_vers), (char *) &resbuf);
- (void) save_res(*dpp, sn);
-
- if (!(*dpp)->no && !if_opackets_fixed && dbg_lvl >= 1) {
- (void) fprintf(stderr,
- "%s: rpc.rstatd vers %d does not report if_opackets\n",
- (*dpp)->host, (*dpp)->clnt_vers);
- }
- if_opackets_fixed = 1;
-
- if (dbg_lvl >= 2) {
- (void) fputs("c\n", stderr);
- }
- good++;
- dpp = &(*dpp)->datap;
- break; /* vers */
- }
- xdr_free(XDR_STATSPROC((*dpp)->clnt_vers), (char *) &resbuf);
- if (clnt_stat == RPC_PROGVERSMISMATCH && vers > 1) {
- if (dbg_lvl >= 2) {
- (void) fputs("M ", stderr);
- (void) fflush(stderr);
- }
- clnt_destroy((*dpp)->cl);
- (*dpp)->cl = NULL;
- continue; /* vers-- */
- }
- (void) fprintf(stderr, "clnt_call: %s %s\n",
- (*dpp)->host, clnt_sperrno(clnt_stat));
- (*dpp)->ok_to_call = 0;
- bad++;
- break; /* vers */
- } /* for(vers ... */
- } /* for dpp */
-
- if (dbg_lvl >= 1) {
- (void) fprintf(stderr, "done clnt calls good=%d bad=%d\n", good, bad);
- }
- if (mode == MODE_CALL && !good) {
- if (nhosts > 1) {
- (void) fprintf(stderr, "None of the hosts replied. Quitting.\n");
- } else {
- dpp = &dp;
- (void) fprintf(stderr, "%s did not reply. Quitting.\n", (*dpp)->host);
- }
- exit(1);
- }
- return;
- }
-
- /**
- * create a new data structure
- **/
- struct data *
- new_host(addr, hostname)
- struct in_addr *addr;
- char *hostname;
- {
- struct data *newdpp;
-
- newdpp = (struct data *) calloc(1, sizeof(struct data));
- if (newdpp == NULL) {
- perror("calloc");
- exit(1);
- }
- newdpp->addr = *addr;
- newdpp->host = strdup(hostname);
- if (!newdpp->host) {
- perror("strdup");
- exit(1);
- }
- newdpp->host_dup = strdup(hostname);
- if (!newdpp->host_dup) {
- perror("strdup");
- exit(1);
- }
- newdpp->ok_to_call = 1;
- /**
- * assume cp_time is cumulative since boot time
- * until we find out otherwise
- **/
- newdpp->cp_kind = CP_TIME_CUM;
- nhosts++;
- if (mode == MODE_BCST) {
- (void) putc('+', stderr);
- (void) fflush(stderr);
- }
- return newdpp;
- }
-
- void
- dump_hostent(entry)
- struct hostent *entry;
- {
- char **app;
- struct in_addr in_addr;
-
- (void) fprintf(stderr, "Official name:\t%s\n", entry->h_name);
- for (app = entry->h_aliases; *app; app++)
- (void) fprintf(stderr, "Alias:\t\t%s\n", *app);
-
- for (app = entry->h_addr_list; *app; app++) {
- bcopy(*app, (char *) &in_addr.s_addr, entry->h_length);
- (void) fprintf(stderr, "Host address:\t%s\n", inet_ntoa(in_addr));
- }
- }
-
- void
- insert_dp(newdp)
- struct data *newdp;
- {
- struct data **dpp;
- struct data *tdp;
-
- tdp = NULL;
- for (dpp = &dp; *dpp; dpp = &(*dpp)->datap) {
- if (newdp->addr.s_addr == (*dpp)->addr.s_addr) {
- /* already on the list */
- (void) fprintf(stderr,
- "This can't happen! %s already on list\n",
- inet_ntoa(newdp->addr));
- exit(1);
- }
- if (opts & O_SHOST ? strcmp(newdp->host, (*dpp)->host) < 0
- : ntohl(newdp->addr.s_addr) < ntohl((*dpp)->addr.s_addr)) {
- /* insert into list */
- tdp = *dpp;
- break; /* break => insert into list */
- }
- } /* fall-through => append to list */
- *dpp = newdp;
- (*dpp)->datap = tdp;
- }
-
- void
- enter_item(itemkey, addr, datap)
- char *itemkey;
- struct in_addr addr;
- struct data *datap;
- {
- hash_info *hip;
- ENTRY item;
-
- /*
- * caution: do not use inet_ntoa() in this routine
- */
-
- hip = (hash_info *) malloc(sizeof(hash_info));
- item.key = strdup(itemkey);
- if (!item.key) {
- perror("strdup");
- exit(1);
- }
- hip->ident_addr = addr;
- hip->datap = datap;
- item.data = (char *) hip;
- /* put name into table */
- if (!hsearch(item, ENTER)) {
- (void) fprintf(stderr, "Hash table full.\n");
- exit(1);
- }
- if (dbg_lvl >= 2)
- (void) fprintf(stderr, "ENTER %s. hip: ident_addr.s_addr=0x%08x datap=0x%08x\n",
- itemkey, ntohl(hip->ident_addr.s_addr), (u_long) hip->datap);
- }
-
- /**
- * handle each reply to the broadcast
- * return FALSE to permit more broadcasting
- * return TRUE to terminate broadcasting (after alarm has timed out)
- *
- * my profuse thanks Joe Beauchamp (JRB@CSI.compuserve.com)
- * for patiently assisting me with debugging this routine.
- *
- **/
- /**
- * You are about to enter ...
- **/
- bool_t
- each_result(resp, raddr, version)
- stats_all *resp;
- struct sockaddr_in *raddr;
- u_long version;
- {
- char *hostname;
- char *dotquad1;
- struct data *resdp;
- stats_default *sn;
- ENTRY *found_item1;
- hash_info *fip;
- struct hostent *host_entry;
- char **app;
- struct in_addr in_tmp;
- ENTRY item;
-
- /**
- * * * * *
- * * * * * *
- ... the coredump zone *
- * * * * *
- * * * *
- **/
-
- /**
- * use strdup for dotquad1 because inet_ntoa uses static storage,
- * which is overwritten each call
- *
- **/
- dotquad1 = strdup(inet_ntoa(raddr->sin_addr));
- if (!dotquad1) {
- perror("strdup");
- exit(1);
- }
- item.key = dotquad1;
- found_item1 = hsearch(item, FIND);
- if (found_item1) { /* found_item1 */
- /* already on the list */
- fip = (hash_info *) found_item1->data;
- in_tmp = fip->ident_addr;
- if (in_tmp.s_addr) {
- char *dotquad2;
- ENTRY *found_item2;
- /* machine has more than one network interface */
- dotquad2 = inet_ntoa(in_tmp);
- item.key = dotquad2;
- found_item2 = hsearch(item, FIND);
- if (!found_item2) {
- (void) fprintf(stderr,
- "This can't happen! %s not in hash table\n",
- dotquad2);
- exit(1);
- }
- fip = (hash_info *) found_item2->data;
- } /* in_tmp.s_addr */
- resdp = fip->datap;
- (void) putc('.', stderr);
- (void) fflush(stderr);
- } else { /* ! found_item1 */
- if (opts & O_NHOST) {
- resdp = new_host(&raddr->sin_addr, dotquad1);
- insert_dp(resdp);
- in_tmp.s_addr = 0;
- enter_item(dotquad1, in_tmp, resdp);
- } else { /* !opts & O_NHOST */
- ENTRY *found_item3;
- host_entry = gethostbyaddr((char *) &raddr->sin_addr, 4, AF_INET);
- if (host_entry) {
- if (dbg_lvl >= 2)
- dump_hostent(host_entry);
-
- hostname = host_entry->h_name;
- if (!hostname) {
- (void) fprintf(stderr,
- "gethostbyaddr: null hostname %s\n",
- dotquad1);
- exit(1);
- }
- item.key = hostname;
- } else { /* !host_entry */
- hostname = (char *) NULL;
- if (dbg_lvl >= 1)
- (void) fprintf(stderr,
- "gethostbyaddr failed %s\n", dotquad1);
- item.key = dotquad1;
- } /* !host_entry */
- found_item3 = hsearch(item, FIND);
- if (found_item3) {
- char *dotquad2;
- ENTRY *found_item4;
- fip = (hash_info *) found_item3->data;
- in_tmp = fip->ident_addr;
- enter_item(dotquad1, in_tmp, (struct data *) NULL);
-
- if (dbg_lvl >= 1)
- (void) fprintf(stderr,
- "duplicate reply from %s received on interface %s\n",
- hostname ? hostname : "(unknown)", dotquad1);
- dotquad2 = inet_ntoa(in_tmp);
- item.key = dotquad2;
- found_item4 = hsearch(item, FIND);
- if (!found_item4) {
- (void) fprintf(stderr,
- "This can't happen! %s not in hash table\n",
- dotquad2);
- exit(1);
- }
- fip = (hash_info *) found_item4->data;
- resdp = fip->datap;
- (void) putc('.', stderr);
- (void) fflush(stderr);
- } else { /* ! found_item2 */
- resdp = (struct data *) NULL;
- if (host_entry) {
- enter_item(hostname, raddr->sin_addr, (struct data *) NULL);
- for (app = host_entry->h_addr_list; *app; app++) {
- bcopy(*app, (char *) &in_tmp, host_entry->h_length);
- if (in_tmp.s_addr == raddr->sin_addr.s_addr) {
- /* this is the normal branch */
- resdp = new_host(&raddr->sin_addr, hostname);
- insert_dp(resdp);
- in_tmp.s_addr = 0;
- enter_item(dotquad1, in_tmp, resdp);
- } else {/* other addresses */
- /* save other addresses found in host table */
- char *dotquad2;
- dotquad2 = inet_ntoa(in_tmp);
- if (dbg_lvl >= 1)
- (void) fprintf(stderr,
- "Saving address %s for host %s\n",
- dotquad2, hostname);
- enter_item(dotquad2, raddr->sin_addr,
- (struct data *) NULL);
- } /* other addresses */
- } /* for app */
- } else { /* !host_entry */
- resdp = new_host(&raddr->sin_addr, dotquad1);
- insert_dp(resdp);
- in_tmp.s_addr = 0;
- enter_item(dotquad1, in_tmp, resdp);
- } /* !host_entry */
- } /* ! found_item2 */
- } /* !opts & O_NHOST */
- } /* ! found_item1 */
-
- sn = STATS_CONVERT(version) (resp);
- /**
- * 11/3/93 I have checked that no memory leak occurs if I do not use
- * xdr_free here. (Leave this comment here, so I don't forget about it.)
- **/
- if (!resdp) {
- (void) fprintf(stderr,
- "This shouldn't happen %s resdp = NULL\n", dotquad1);
- exit(1);
- }
- if (save_res(resdp, sn))
- resdp->bcst_vers = version;
-
- if (!resdp->no && !if_opackets_fixed && dbg_lvl >= 1) {
- (void) fprintf(stderr,
- "%s: rpc.rstatd vers %d does not report if_opackets\n",
- resdp->host, resdp->bcst_vers);
- }
- if_opackets_fixed = 1;
- free(dotquad1);
-
- return bcst_timo;
- }
-
- bool_t
- each_result_orig(resp, raddr)
- stats_all *resp;
- struct sockaddr_in *raddr;
- {
- return each_result(resp, raddr, RSTATVERS_ORIG);
- }
-
- bool_t
- each_result_swtch(resp, raddr)
- stats_all *resp;
- struct sockaddr_in *raddr;
- {
- return each_result(resp, raddr, RSTATVERS_SWTCH);
- }
-
- bool_t
- each_result_time(resp, raddr)
- stats_all *resp;
- struct sockaddr_in *raddr;
- {
- return each_result(resp, raddr, RSTATVERS_TIME);
- }
-
- bool_t
- each_result_var(resp, raddr)
- stats_all *resp;
- struct sockaddr_in *raddr;
- {
- return each_result(resp, raddr, RSTATVERS_VAR);
- }
-
- bool_t(*each_result_vers[]) () =
- {
- each_result_orig,
- each_result_swtch,
- each_result_time,
- each_result_var,
- };
-
- /**
- * force end of broadcasting
- **/
- RETSIGTYPE
- bcst_done()
- {
- bcst_timo = TRUE;
- }
-
- /**
- * calculate how long the alarm should be to get
- * the desired interval
- * example: desire 30 sec. use alarm(14)
- **/
- unsigned
- get_bcst_alarm(interval)
- unsigned interval;
- {
- int j, h = 0;
-
- if (interval <= 4)
- return 1;
- for (j = 4; j <= 64; j *= 2) {
- h += j;
- if (interval <= h)
- break;
- }
- j /= 2;
- return Min(h - j, interval) - j;
- /* max is 60 */
- }
-
- void
- do_broadcast(vers_max, interval)
- u_long vers_max;
- unsigned interval; /* desired broadcast interval. 92 max */
- {
- u_long vers;
- static u_long vers_max_ok;
- static enum clnt_stat clnt_stat;
- stats_all resbuf;
-
- if (!vers_max_ok)
- vers_max_ok = vers_max;
-
- (void) fputs("broadcasting ", stderr);
- for (vers = vers_max_ok; vers >= Min(vers_max_ok, RSTATVERS_TIME); vers--) {
-
- if (dbg_lvl >= 1)
- (void) fprintf(stderr, " vers %d: ", vers);
-
- (void) signal(SIGALRM, bcst_done);
- (void) alarm(get_bcst_alarm(interval));
-
- bcst_timo = FALSE;
- (void) fflush(stderr);
- bzero((char *) &resbuf, sizeof resbuf);
- clnt_stat = clnt_broadcast(RSTATPROG,
- vers,
- RSTATPROC_STATS,
- xdr_void,
- (char *) NULL,
- XDR_STATSPROC(vers),
- (char *) &resbuf,
- EACH_RESULT(vers));
- /**
- * resultproc_t each_result in Solaris-2 (thanks
- * cmc@apus.srg-ssr.ch (Colin M. Clark))
- **/
-
- if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) {
- (void) fprintf(stderr, "\nclnt_broadcast: %s\n",
- clnt_sperrno(clnt_stat));
- exit(1);
- }
- if (!nhosts) {
- (void) fprintf(stderr,
- "\nNo hosts found with rstatd version %d on this network\n",
- vers);
- vers_max_ok = vers - 1;
- if (!vers_max_ok)
- exit(1);
- }
- }
- (void) putc('\n', stderr);
- }
-