home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- /**
- * This program may be copied, redistributed in any form,
- * source or binary, and used for any purpose, provided
- * this copyright notice is retained.
- **/
- static char *sccsid[] = {
- "@(#)rperf.c 2.1 8/30/93 (c) Copyright Brian P. Fitzgerald",
- "Rensselaer Polytechnic Institute"
- };
- #endif
- /**
-
- rperf.c -- print system performance statistics.
-
- by Brian P. Fitzgerald
- Mechanics of Materials Laboratory
- Rensselaer Polytechnic Institute
- Troy, New York
-
- usage: rperf [ options ] [ interval [ count ] ] [ +sortkey ] [ host ... ]
- rup [ options ] [ interval ] [ host ... ]
-
- Send comments and bug fixes to fitz@rpi.edu
-
- Tested:
- SunOS 4.1.1, 4.1.2, 4.1.3
- IBM AIX 3.1, 3.2
- HP-UX 8.0
- NeXT Mach 20
- Alliant FX/2800
- SGI PI Iris 4.0.1, 4.0.2
- SCO Unix 3.2.2
- MIPS RISCos
- DEC Ultrix 4.2
- ESIX
- Amiga 4.0 2.1c
-
- Not supported:
- AIX 1.2.1 on aix370
-
- Send reports of successful compilation on other platforms to
- fitz@rpi.edu
-
- History:
-
- 5/6/92 beta posted to alt.sources
- 5/18/92 1.1 Added multiple hosts, uptime display. Improved output
- format.
- 5/25/92 1.2 Added signal handler.
-
- 1/6/93 1.3 Added broadcast mode
-
- 2/6/93 1.4 Added output sorting options.
- Added rup alias.
-
- 2/10/93 1.5 Corrected rpc version mismatch. Now if_opackets right.
- Plugged some memory leaks.
-
- 3/5/93 1.6 Variable number of disks and cpu states.
- Fixed a line wrap problem. Added termcap routine.
-
- 8/26/93 2.1 posted to comp.sources.misc
-
- **/
-
- #ifdef STDC_HEADERS
- #include <stddef.h>
- #endif
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/time.h>
-
- #include <time.h>
-
- #include <sys/ioctl.h>
- #ifndef TIOCGWINSZ
- #ifdef HAVE_SYS_TERMIO_H
- #include <sys/termio.h>
- #endif
- #endif
- #ifdef HAVE_SYS_BSD_TTY_H
- #include <sys/bsd_tty.h>
- #endif
-
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <rpc/rpc.h>
- #include <rpc/pmap_clnt.h>
- #include "rstat.h"
- #include <stdio.h>
- #include <signal.h>
- #include <string.h>
- #include <assert.h>
- #include <errno.h>
-
- /* <unistd.h> */
- #define STDOUT_FILENO 1
-
- /* <sys/dk.h> */
- #define CP_USER 0
- #define CP_NICE 1
- #define CP_SYS 2
- #define CP_IDLE 3
-
- /* <sys/ioctl.h> or <sys/ttycom.h> */
- struct Winsize {
- unsigned short ws_row; /* rows, in characters */
- unsigned short ws_col; /* columns, in characters */
- unsigned short ws_xpixel; /* horizontal size, pixels - not used */
- unsigned short ws_ypixel; /* vertical size, pixels - not used */
- };
-
- #define O_CP 0x01
- #define O_DK 0x02
- #define O_VM 0x04
- #define O_IF 0x08
- #define O_TIME 0x10
- #define O_DATE 0x20
- #define O_SECS 0x40
- #define O_ALL ( O_CP | O_DK | O_VM | O_IF )
- #define O_DEFL ( O_CP | O_VM | O_IF )
- #define O_DEFL1 ( O_CP | O_DK | O_VM | O_IF )
- #define O_UP 0x100
- #define O_BCST 0x200
- #define O_BARE 0x400
- #define O_DBG 0x800
- #define O_SHOST 0x1000
- #define O_NHOST 0x8000
- #define O_SORT 0x10000
- #define O_RVRS 0x20000
-
- #define cpu(dt) (dcpu ? ((dt) * 100 + hdcpu ) / dcpu : 0)
- #define loadav(nrun) ( (float) (nrun) / FSCALE )
- #define delta(x) ((*dpp)->sn.x - (*dpp)->so.x) /* use this macro with care */
- #define rate(x) (dt ? ((x) * 1000L + hdt ) / dt : 0)
-
- #ifndef abs
- #define abs(a) ((a)>= 0 ? (a) : -(a))
- #endif /* abs */
-
- #ifndef max
- #define max(a, b) ((a) > (b) ? (a) : (b))
- #endif /* max */
-
- #define RSTATVERS_BCST RSTATVERS_TIME
- typedef statstime stats_broadcast;
- #define RSTATVERS_DEFAULT RSTATVERS_VAR
- typedef statsvar stats_default;
-
- char *getenv();
- void exit();
- long strtol();
- extern char *strdup();
-
- stats_default *from_stats();
- stats_default *from_statsswtch();
- stats_default *from_statstime();
- stats_default *from_statsvar();
-
- stats_default *((*stats_convert[]) ()) =
- {
- from_stats,
- from_statsswtch,
- from_statstime,
- from_statsvar,
- };
- #define STATS_CONVERT(version) (stats_convert[(version)-1])
-
- bool_t(*xdr_statsproc[]) () =
- {
- xdr_stats,
- xdr_statsswtch,
- xdr_statstime,
- xdr_statsvar,
- };
- #define XDR_STATSPROC(version) (xdr_statsproc[(version)-1])
-
- union stats_all {
- struct stats s1;
- struct statsswtch s2;
- struct statstime s3;
- struct statsvar s4;
- };
- typedef union stats_all stats_all;
-
- struct data {
- struct data *datap;
- unsigned long nn;
- unsigned long no;
- struct in_addr addr;
- char *host;
- CLIENT *cl;
- u_long cl_vers;
- stats_default sn;
- stats_default so;
- stats_default sd; /* delta or rate. uptime = sd.boottime */
- };
-
- struct key {
- char *k_name;
- int k_offset;
- int k_flag;
- int k_index;
- };
- typedef struct key key;
-
- #define K_DELTA 0x1 /* need delta before sorting */
- #define K_ARRAY 0x2 /* the member is an xdr_array */
-
- /* C faq */
- #ifndef offsetof
- #define offsetof(type, mem) ((size_t) \
- ((char *)&((type *) 0)->mem - (char *)((type *) 0)))
- #endif /* offsetof */
- #define sd_offset(mem) offsetof(struct data,sd.mem)
- #define sn_offset(mem) offsetof(struct data,sn.mem)
-
- #define AV1 0
- #define AV5 1
- #define AV15 2
-
- key keys[] = {
- {"avg", sn_offset(avenrun[AV1]), 0, 0},
- {"ave", sn_offset(avenrun[AV1]), 0, 0},
- {"loadavg", sn_offset(avenrun[AV1]), 0, 0},
- {"loadave", sn_offset(avenrun[AV1]), 0, 0},
- {"avenrun", sn_offset(avenrun[AV1]), 0, 0},
- {"av1", sn_offset(avenrun[AV1]), 0, 0},
- {"av5", sn_offset(avenrun[AV5]), 0, 0},
- {"av15", sn_offset(avenrun[AV15]), 0, 0},
-
- {"boottime", sn_offset(boottime.tv_sec), 0, 0},
- {"uptime", sd_offset(boottime.tv_sec), 0, 0},
-
- {"user", sd_offset(cp_time), K_DELTA | K_ARRAY, 0},
- {"us", sd_offset(cp_time), K_DELTA | K_ARRAY, 0},
- {"nice", sd_offset(cp_time), K_DELTA | K_ARRAY, 1},
- {"ni", sd_offset(cp_time), K_DELTA | K_ARRAY, 1},
- {"sys", sd_offset(cp_time), K_DELTA | K_ARRAY, 2},
- {"system", sd_offset(cp_time), K_DELTA | K_ARRAY, 2},
- {"sy", sd_offset(cp_time), K_DELTA | K_ARRAY, 2},
- {"idle", sd_offset(cp_time), K_DELTA | K_ARRAY, 3},
- {"id", sd_offset(cp_time), K_DELTA | K_ARRAY, 3},
-
- {"intr", sd_offset(v_intr), K_DELTA, 0},
- {"swtch", sd_offset(v_swtch), K_DELTA, 0},
- {"cxsw", sd_offset(v_swtch), K_DELTA, 0},
- {"csw", sd_offset(v_swtch), K_DELTA, 0},
-
- {"pgpgin", sd_offset(v_pgpgin), K_DELTA, 0},
- {"pgin", sd_offset(v_pgpgin), K_DELTA, 0},
- {"pgpgout", sd_offset(v_pgpgout), K_DELTA, 0},
- {"pgout", sd_offset(v_pgpgout), K_DELTA, 0},
- {"pgo", sd_offset(v_pgpgout), K_DELTA, 0},
-
- {"pswpin", sd_offset(v_pswpin), K_DELTA, 0},
- {"swpin", sd_offset(v_pswpin), K_DELTA, 0},
- {"swin", sd_offset(v_pswpin), K_DELTA, 0},
- {"pswpout", sd_offset(v_pswpout), K_DELTA, 0},
- {"swpout", sd_offset(v_pswpout), K_DELTA, 0},
- {"swo", sd_offset(v_pswpout), K_DELTA, 0},
-
- {"dk_xfer", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 0},
- {"sd0", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 0},
- {"disk0", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 0},
- {"d0", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 0},
- {"sd1", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 1},
- {"disk1", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 1},
- {"d1", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 1},
- {"sd2", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 2},
- {"disk2", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 2},
- {"d2", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 2},
- {"sd3", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 3},
- {"disk3", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 3},
- {"d3", sd_offset(dk_xfer), K_DELTA | K_ARRAY, 3},
-
- {"ipackets", sd_offset(if_ipackets), K_DELTA, 0},
- {"ipk", sd_offset(if_ipackets), K_DELTA, 0},
- {"ierrors", sd_offset(if_ierrors), K_DELTA, 0},
- {"ier", sd_offset(if_ierrors), K_DELTA, 0},
- {"oerrors", sd_offset(if_oerrors), K_DELTA, 0},
- {"oer", sd_offset(if_oerrors), K_DELTA, 0},
- {"opackets", sd_offset(if_opackets), K_DELTA, 0},
- {"opk", sd_offset(if_opackets), K_DELTA, 0},
- {"collisions", sd_offset(if_collisions), K_DELTA, 0},
- {"coll", sd_offset(if_collisions), K_DELTA, 0},
- {0, 0, 0, 0}
- };
-
- key *key_ptr = NULL;
-
- struct datatbl {
- int val;
- struct data *dp;
- };
-
- char *keyhelp[] = {
- "The sort keys are:\n",
- "\n",
- "loadavg user pgpgin disk0 boottime ipackets\n",
- "av1 nice pgpgout disk1 uptime ierrors\n",
- "av5 sys pswpin disk2 oerrors\n",
- "av15 idle pswpout disk3 opackets\n",
- " intr collisions\n",
- " swtch\n",
- 0
- };
-
- #define P_DATA 0
- #define P_UP 1
-
- static struct timeval TIMEOUT = {25, 0};
-
- static struct data *dp; /* link list head */
- static unsigned nhosts = 0; /* multiple hosts idea from Larry McVoy */
- int h_seen = 0; /**
- * one or more host arguments was supplied.
- * > 0 is client (non-broadcast) mode
- * == 0 is broadcast mode
- **/
- static bool_t bcst_timo;
- long opts = 0;
- static unsigned long thiscount = 0;
- unsigned nresp = 0;
-
- /* terminal characteristics */
- int term_rows;
- int term_cols;
-
- struct timeval starttime;
- struct timezone tz;
-
- char *f1_cp = "%-15s ";
- char *f2_cp = "%3s %3s %3s %3s ";
- char *fo_cp = "%3d %3d %3d %3d ";
-
- char *f1_av = "%-14s ";
- char *f2_av = "%4s %4s %4s ";
- char *fo_av = "%4.1f %4.1f %4.1f ";
- char *fo_a0 = "%4.2f %4.2f %4.2f ";
-
- char *f1_dk = "%-12s";
- char *f2_dk = "%2s %2s %2s %2s ";
- char *fo_dk = "%2d %2d %2d %2d ";
-
- char *f1_vm = "%2s %2s %2s %2s %3s %3s ";
- char *f2_vm = "%2s %2s %2s %2s %3s %3s ";
- char *fo_vm = "%2u %2u %2u %2u %3u %3u ";
-
- char *f1_if = " %2s %2s %2s %2s %2s";
- char *f2_if = " %2s %2s %2s %2s %2s";
- char *fo_if = " %2d %2d %2d %2d %2d";
-
- char *f_time = "%-9.9s ";
- char *fo_time = "%9d ";
-
- char *f_date = "%-24.24s ";
-
- char *f_secs = "%-5.5s ";
- char *fo_secs = "%5.2f ";
-
- char *f_h = "%12.12s ";
-
- char title1[160];
- char title2[160];
- char ruler[160];
-
- struct array {
- u_int len;
- int *val;
- };
- typedef struct array array;
-
- /*
- * allocate an int array struct, size n and from a if non-null
- */
- void
- create_array(a, p, n)
- array *a;
- int *p;
- int n;
- {
- int i;
-
- a->len = n;
- a->val = (int *) malloc((unsigned) n * sizeof(int));
- if (a->val == NULL) {
- perror("malloc");
- exit(1);
- }
- if (p)
- for (i = 0; i < n; i++)
- a->val[i] = p[i];
- }
-
- /*
- * 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, s->s1.cp_time, CPUSTATES_ORIG);
- create_array((array *) & r.dk_xfer, s->s1.dk_xfer, DK_NDRIVE_ORIG);
- 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;
- {
- static stats_default r;
- int i;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, s->s2.cp_time, CPUSTATES_ORIG);
- create_array((array *) & r.dk_xfer, s->s2.dk_xfer, DK_NDRIVE_ORIG);
- 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;
- {
- static stats_default r;
- int i;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, s->s3.cp_time, CPUSTATES_ORIG);
- create_array((array *) & r.dk_xfer, s->s3.dk_xfer, DK_NDRIVE_ORIG);
- 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;
- {
- static stats_default r;
- int i;
-
- bzero((char *) &r, sizeof(r));
- create_array((array *) & r.cp_time, s->s4.cp_time.cp_time_val,
- (int) s->s4.cp_time.cp_time_len);
- create_array((array *) & r.dk_xfer, s->s4.dk_xfer.dk_xfer_val,
- (int) s->s4.dk_xfer.dk_xfer_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;
- }
-
- /*
- * free the cp_time and dk_xfer array in a stats_default struct
- */
- void
- free_stats(s)
- stats_default *s;
- {
- free((char *) s->cp_time.cp_time_val);
- free((char *) s->dk_xfer.dk_xfer_val);
- }
-
- /*
- * save the results in a data structure
- */
- void
- save_res(d, res)
- struct data *d;
- stats_default *res;
- {
- if (d->nn == thiscount)
- return; /* duplicate. ignore */
- d->no = d->nn;
- d->nn = thiscount;
-
- free_stats(&d->so);
- d->so = d->sn;
- d->sn = *res;
- return;
- }
-
- /*
- * handle lack of communication with client.
- */
- void
- drop_from_list(dpp)
- struct data **dpp;
- {
- struct data *tdp;
-
- if ((*dpp)->cl)
- clnt_destroy((*dpp)->cl);
- free((*dpp)->host);
-
- tdp = *dpp;
- *dpp = (*dpp)->datap;
-
- free_stats(&tdp->so);
- free((char *) tdp);
- (void) putc('d', stdout);
- (void) fflush(stdout);
- nhosts--;
- return;
- }
-
- /**
- * this function may be called after (*dpp)->addr
- * has been filled with a valid in_addr
- **/
- int
- make_client(dpp)
- struct data **dpp;
- {
- struct sockaddr_in server_addr;
- struct timeval p_timo;
- int sock = RPC_ANYSOCK;
-
- 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 pamp_getport man page.
- **/
- (*dpp)->cl = clntudp_create(&server_addr,
- RSTATPROG,
- (*dpp)->cl_vers,
- p_timo,
- &sock);
-
- if ((*dpp)->cl == NULL) {
- (void) fprintf(stderr, "Can't contact rstatd on %s because%s\n",
- (*dpp)->host, clnt_spcreateerror(""));
- return 0;
- }
- if (opts & O_DBG) {
- (void) putc('m', stdout);
- (void) fflush(stdout);
- }
- 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()
- {
- stats_all res;
- stats_default *sn;
- static enum clnt_stat clnt_stat;
- struct data **dpp;
- int good = 0;
- int bad = 0;
- u_long vers;
-
- for (dpp = &dp; *dpp;) {
- if (opts & O_DBG)
- (void) fprintf(stdout, "%s ", inet_ntoa((*dpp)->addr));
- if ((*dpp)->nn == thiscount) {
- dpp = &(*dpp)->datap;
- if (opts & O_DBG) {
- (void) fputs("-\n", stdout);
- }
- continue; /* already have data */
- }
- if (!(*dpp)->cl_vers)
- (*dpp)->cl_vers = RSTATVERS_DEFAULT; /* highest version */
- bzero((char *) &res, sizeof(res));
- for (vers = (*dpp)->cl_vers; vers > 0; vers--) {
- (*dpp)->cl_vers = vers;
- if (!(*dpp)->cl)
- if (!make_client(dpp)) {
- drop_from_list(dpp);
- bad++;
- break; /* vers */
- }
- if (opts & O_DBG) {
- (void) fprintf(stdout, "v%d", vers);
- (void) fflush(stdout);
- }
- clnt_stat = clnt_call((*dpp)->cl,
- RSTATPROC_STATS,
- xdr_void,
- NULL,
- XDR_STATSPROC((*dpp)->cl_vers),
- &res,
- TIMEOUT);
- if (clnt_stat == RPC_SUCCESS) {
- sn = STATS_CONVERT((*dpp)->cl_vers) (&res);
- xdr_free(XDR_STATSPROC((*dpp)->cl_vers), (char *) &res);
- save_res(*dpp, sn);
- if (opts & O_DBG) {
- (void) fputs("c\n", stdout);
- }
- good++;
- dpp = &(*dpp)->datap;
- break; /* vers */
- }
- if (clnt_stat == RPC_PROGVERSMISMATCH && vers > 1) {
- if (opts & O_DBG) {
- (void) fputs("M ", stdout);
- (void) fflush(stdout);
- }
- clnt_destroy((*dpp)->cl);
- (*dpp)->cl = NULL;
- continue; /* vers-- */
- }
- (void) fprintf(stderr, "clnt_call: %s %s\n",
- (*dpp)->host, clnt_sperrno(clnt_stat));
- drop_from_list(dpp);
- bad++;
- break; /* vers */
- } /* for(vers ... */
- }
-
- if (opts & O_DBG) {
- (void) fprintf(stdout, "done clnt calls good=%d bad=%d\n", good, bad);
- }
- if (!nhosts)
- exit(1);
- return;
- }
-
- /**
- * given an internet address,
- * get the hostname,
- * or the ascii internet address
- **/
- char *
- get_hostname(addr)
- struct in_addr addr;
- {
- struct hostent *host_entry;
-
- host_entry = NULL;
- if (opts & O_NHOST) {
- return inet_ntoa(addr);
- } else {
- host_entry = gethostbyaddr((char *) &addr, 4, AF_INET);
- if (!host_entry && opts & O_DBG)
- (void) fputs("byaddr failed\n", stdout);
- return host_entry ? host_entry->h_name : inet_ntoa(addr);
- }
- }
-
- /*
- * 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);
- }
- nhosts++;
- if (!h_seen) {
- (void) putc('+', stdout);
- (void) fflush(stdout);
- }
- return newdpp;
- }
-
- /*
- * handle each reply to the broadcast
- */
- bool_t
- each_result(resp, raddr)
- stats_broadcast *resp;
- struct sockaddr_in *raddr;
- {
- char *hostname;
- struct data **dpp;
- stats_default *sn;
-
- sn = STATS_CONVERT(RSTATVERS_BCST) (resp);
- xdr_free(XDR_STATSPROC(RSTATVERS_BCST), (char *) resp);
-
- hostname = NULL;
- for (dpp = &dp; *dpp; dpp = &(*dpp)->datap) {
- if (raddr->sin_addr.s_addr == (*dpp)->addr.s_addr) {
- /* duplicate */
- save_res(*dpp, sn);
- (void) putc('.', stdout);
- (void) fflush(stdout);
- return bcst_timo;
- }
- if (!hostname)
- hostname = get_hostname(raddr->sin_addr);
-
- if (opts & O_SHOST ?
- strcmp(hostname, (*dpp)->host) < 0 :
- raddr->sin_addr.s_addr < (*dpp)->addr.s_addr) {
- /* insert */
- struct data *tdp;
- tdp = *dpp;
- *dpp = new_host(&raddr->sin_addr, hostname);
- save_res(*dpp, sn);
- (*dpp)->datap = tdp;
- return bcst_timo;
- }
- }
- /* append */
- if (!hostname)
- hostname = get_hostname(raddr->sin_addr);
- *dpp = new_host(&raddr->sin_addr, hostname);
- save_res(*dpp, sn);
- (*dpp)->datap = NULL;
- return bcst_timo;
- }
-
- /*
- * handle termination signals
- */
- RETSIGTYPE
- cleanup()
- {
- exit(0); /* flush and close stdout */
- }
-
- /*
- * force end of broadcasting
- */
- RETSIGTYPE
- bcst_done()
- {
- bcst_timo = TRUE;
- }
-
- /*
- * see if display will wrap. Try to fix.
- */
- char *
- checkwrap(cols, obuf)
- int cols;
- char *obuf;
- {
- int olen = strlen(obuf);
- int rlen = strlen(ruler);
- char *rp, *op, *tp, *sp, *cp;
- int rpos = 0, opos;
- int nsp, err = 0;
-
- if (olen <= rlen || rlen > cols)
- return obuf; /* leave alone */
-
- if (opts & O_DBG) {
- (void) fprintf(stdout, "wrap terminal=%d ruler=%d output%d\n",
- cols, rlen, olen);
- (void) fputs(ruler, stdout);
- (void) putc('\n', stdout);
- }
- op = obuf;
- for (rp = ruler; *rp;) {
- tp = op;
- for (; *rp && *rp == ' '; rp++);
- for (; *op && *op == ' '; op++);
- nsp = op - tp;
- for (; *rp && *rp != ' '; rp++);
- for (; *op && *op != ' '; op++);
-
- if (!*rp || nsp > 1) {
- rpos = rp - ruler;
- opos = op - obuf;
- err = opos - rpos;
- }
- if (err > 0) {
- if (opts & O_DBG) {
- (void) fputs(obuf, stdout);
- (void) putc('\n', stdout);
- (void) fprintf(stdout, "rpos=%d err=%d\n", rpos, err);
- }
- for (sp = op; sp != obuf; sp--) {
- if (*sp == ' ')
- sp--;
- if (*sp == ' ') { /* shift left one char */
- sp++;
- for (cp = sp; *cp; cp++)
- *cp = *(cp + 1);
- op--;
- if (!--err)
- break;
- }
- }
- }
- rpos = rp - ruler;
- opos = op - obuf;
- err = opos - rpos;
- }
-
- if (opts & O_DBG)
- (void) fputs(" . . . . 1 . . . . 2 . . . . 3 . . . . 4 . . . . 5 . . . . 6 . . . . 7 . . . .\n", stdout);
- return obuf;
- }
-
- /*
- * qsort comparison routine
- */
- static int
- datacompare(i, j)
- struct datatbl *i, *j;
- {
- return opts & O_RVRS ?
- i->val - j->val :
- j->val - i->val;
- }
-
- /*
- * calculate deltas and other items, for later sorting
- */
- struct datatbl *
- compute_data(tbl)
- struct datatbl *tbl;
- {
- struct data **dpp;
- int i;
- long dt, hdt; /* msec */
- int dcpu, hdcpu;
-
- nresp = 0;
- for (dpp = &dp; *dpp; dpp = &(*dpp)->datap) {
- /* this data is current */
- if ((*dpp)->nn == thiscount) {
-
- (*dpp)->sd.boottime.tv_sec = /* uptime */
- (*dpp)->sn.curtime.tv_sec
- - (*dpp)->sn.boottime.tv_sec;
-
- nresp++;
- if ((*dpp)->no) {
- /* this data is not the first response from that host */
-
- /* time in milliseconds, since last call */
- dt = (((*dpp)->sn.curtime.tv_sec -
- (*dpp)->so.curtime.tv_sec) * 1000000 +
- ((*dpp)->sn.curtime.tv_usec -
- (*dpp)->so.curtime.tv_usec) + 500) / 1000;
- hdt = (dt + 1) / 2;
-
- /* first reply from aix3.1 may have wrong cp_time[] */
- dcpu = 0;
- if (!(*dpp)->sd.cp_time.cp_time_val)
- create_array((array *) & (*dpp)->sd.cp_time, (int *) NULL,
- (int) (*dpp)->sn.cp_time.cp_time_len);
-
- for (i = 0; i < (*dpp)->sn.cp_time.cp_time_len; i++) {
- (*dpp)->sd.cp_time.cp_time_val[i]
- = delta(cp_time.cp_time_val[i]);
- dcpu += (*dpp)->sd.cp_time.cp_time_val[i];
- }
-
- /**
- * From vmstat.c 5.31 (Berkeley)
- * We round upward to avoid losing low-frequency events
- * (i.e., >= 1 per interval but < 1 per second).
- **/
- hdcpu = dcpu / 2;
- for (i = 0; i < (*dpp)->sn.cp_time.cp_time_len; i++)
- (*dpp)->sd.cp_time.cp_time_val[i]
- = cpu((*dpp)->sd.cp_time.cp_time_val[i]);
-
- if (!(*dpp)->sd.dk_xfer.dk_xfer_val)
- create_array((array *) & (*dpp)->sd.dk_xfer, (int *) NULL,
- (int) (*dpp)->sn.dk_xfer.dk_xfer_len);
-
- for (i = 0; i < (*dpp)->sn.dk_xfer.dk_xfer_len; i++)
- (*dpp)->sd.dk_xfer.dk_xfer_val[i]
- = rate(delta(dk_xfer.dk_xfer_val[i]));
-
- (*dpp)->sd.v_pgpgin = rate(delta(v_pgpgin));
- (*dpp)->sd.v_pgpgout = rate(delta(v_pgpgout));
- (*dpp)->sd.v_pswpin = rate(delta(v_pswpin));
- (*dpp)->sd.v_pswpout = rate(delta(v_pswpout));
- (*dpp)->sd.v_swtch = rate(delta(v_swtch));
- /* Why does v_intr count down on aix370? */
- (*dpp)->sd.v_intr = rate(abs((int) (delta(v_intr))));
-
- (*dpp)->sd.if_ipackets = rate(delta(if_ipackets));
- (*dpp)->sd.if_ierrors = rate(delta(if_ierrors));
- (*dpp)->sd.if_opackets = rate(delta(if_opackets));
- (*dpp)->sd.if_oerrors = rate(delta(if_oerrors));
- (*dpp)->sd.if_collisions = rate(delta(if_collisions));
- } /* (*dpp)->no */
- } /* (*dpp)->nn == thiscount */
- }
-
- if (tbl)
- free((char *) tbl);
- tbl = (struct datatbl *) malloc(nresp * sizeof(struct datatbl));
- if (tbl == NULL) {
- perror("malloc");
- exit(1);
- }
- i = 0;
- for (dpp = &dp; *dpp; dpp = &(*dpp)->datap) {
- if ((*dpp)->nn == thiscount) {
-
- tbl[i].dp = *dpp;
- if (opts & O_SORT &&
- (thiscount > 1 || !(key_ptr->k_flag & K_DELTA)))
- if (key_ptr->k_flag & K_ARRAY) {
- array arr;
-
- arr = *(array *) ((char *) (*dpp) + key_ptr->k_offset);
- tbl[i].val = arr.val[key_ptr->k_index];
- } else {
- tbl[i].val = *(int *) ((char *) (*dpp) + key_ptr->k_offset);
- }
- i++;
- }
- }
-
- if (opts & O_SORT)
- qsort((char *) tbl, (int) nresp, sizeof(struct datatbl), datacompare);
- return tbl;
- }
-
- /*
- * get screen size from termcap entry
- */
- check_termcap()
- {
- char *term;
- static int status;
- static int seen;
- static int t_rows;
- static int t_cols;
- char termcap_buf[1024];
- char *efmt = "Can't get terminal size because\n%s";
-
- if (seen) {
- if (status == 1) {
- term_rows = t_rows;
- term_cols = t_cols;
- }
- return;
- }
- seen = 1;
-
- term = getenv("TERM");
- if (!term) {
- (void) fprintf(stderr, efmt, "TERM environment variable not set.\n");
- return;
- }
- status = tgetent(termcap_buf, term);
- switch (status) {
- case -1:
- (void) fprintf(stderr, efmt, "can't open termcap file.\n");
- return;
- case 0:
- (void) fprintf(stderr, efmt, "no termcap entry for a ");
- (void) fprintf(stderr, "`%s' terminal\n", term);
- return;
- case 1:
- t_rows = tgetnum("li");
- if (t_rows == -1)
- t_rows = 0;
- t_cols = tgetnum("co");
- if (t_cols == -1)
- t_cols = 0;
- term_rows = t_rows;
- term_cols = t_cols;
- if (opts & O_DBG)
- (void) fprintf(stdout, "check_termcap: tgetnum: %d %d\n",
- term_rows, term_cols);
- }
- }
-
- /*
- * get terminal size
- */
- void
- check_term()
- {
- struct Winsize winsize;
-
- winsize.ws_row = 0;
- winsize.ws_col = 0;
- term_rows = 0;
- term_cols = 0;
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *) &winsize) == -1) {
- if (opts & O_DBG)
- perror("ioctl: TIOCGWINSZ");
- return; /* assume not a terminal */
- }
- term_rows = winsize.ws_row;
- term_cols = winsize.ws_col;
- if (term_rows == 0 || term_cols == 0)
- check_termcap();
- }
-
- /*
- * print the statistics or the uptime
- */
- void
- print_data(tbl, flag)
- struct datatbl *tbl;
- int flag;
- {
- char obuf[160];
- int i;
- long up, upd, uph, upm;
- float s;
-
- if (opts & O_SECS) {
- struct timeval now;
- if (gettimeofday(&now, (struct timezone *) 0) == -1) {
- perror("gettimeofday");
- exit(1);
- }
- s = (now.tv_sec - starttime.tv_sec) +
- ((now.tv_usec - starttime.tv_usec) + 5000)
- / 10000 / 100.;
- }
- for (i = 0; i < nresp; i++) {
- switch (flag) {
- case P_DATA:
- if (!tbl[i].dp->no) /* do we have delta? */
- break;
- obuf[0] = '\0';
- if (opts & O_TIME)
- (void) sprintf(obuf + strlen(obuf), fo_time,
- tbl[i].dp->sn.curtime.tv_sec);
- if (opts & O_DATE) {
- char buf[30];
- struct tm *tp;
-
- tp = localtime((long *) &tbl[i].dp->sn.curtime.tv_sec);
- if (!strftime(buf, 30, "%a %b %d %H:%M:%S %Y ", tp)) {
- (void) fputs("can't convert date\n", stderr);
- exit(1);
- }
- (void) sprintf(obuf + strlen(obuf), f_date, buf);
- }
- if (opts & O_SECS)
- (void) sprintf(obuf + strlen(obuf), fo_secs, s);
- if (nhosts > 1 || !h_seen)
- (void) sprintf(obuf + strlen(obuf), f_h, tbl[i].dp->host);
- if (opts & O_CP) {
- (void) sprintf(obuf + strlen(obuf), fo_cp,
- tbl[i].dp->sd.cp_time.cp_time_val[CP_USER],
- tbl[i].dp->sd.cp_time.cp_time_val[CP_NICE],
- tbl[i].dp->sd.cp_time.cp_time_val[CP_SYS],
- tbl[i].dp->sd.cp_time.cp_time_val[CP_IDLE]);
- /* average run queue lengths */
- (void) sprintf(obuf + strlen(obuf), fo_av,
- loadav(tbl[i].dp->sn.avenrun[AV1]),
- loadav(tbl[i].dp->sn.avenrun[AV5]),
- loadav(tbl[i].dp->sn.avenrun[AV15]));
- }
- if (opts & O_DK)
- (void) sprintf(obuf + strlen(obuf), fo_dk,
- tbl[i].dp->sd.dk_xfer.dk_xfer_val[0],
- tbl[i].dp->sd.dk_xfer.dk_xfer_val[1],
- tbl[i].dp->sd.dk_xfer.dk_xfer_val[2],
- tbl[i].dp->sd.dk_xfer.dk_xfer_val[3]);
-
- if (opts & O_VM)
- (void) sprintf(obuf + strlen(obuf), fo_vm,
- tbl[i].dp->sd.v_pgpgin,
- tbl[i].dp->sd.v_pgpgout,
- tbl[i].dp->sd.v_pswpin,
- tbl[i].dp->sd.v_pswpout,
- tbl[i].dp->sd.v_swtch,
- tbl[i].dp->sd.v_intr);
-
- if (opts & O_IF)
- (void) sprintf(obuf + strlen(obuf), fo_if,
- tbl[i].dp->sd.if_ipackets,
- tbl[i].dp->sd.if_ierrors,
- tbl[i].dp->sd.if_opackets,
- tbl[i].dp->sd.if_oerrors,
- tbl[i].dp->sd.if_collisions);
-
- check_term();
- (void) fputs(checkwrap(term_cols > 0 ? term_cols - 1 : 0,
- obuf), stdout);
- (void) putc('\n', stdout);
-
- if (opts & O_DK) {
- int d, dhigh = -1;
- int moredisks;
-
- for (d = tbl[i].dp->sn.dk_xfer.dk_xfer_len - 1; d >= 0; d--) {
- if (tbl[i].dp->sn.dk_xfer.dk_xfer_val[d]) {
- dhigh = d;
- break;
- }
- }
- moredisks = dhigh - DK_NDRIVE_ORIG + 1;
- if (moredisks > 0) {
- (void) fprintf(stdout, "%d more disk%s... ",
- moredisks, moredisks == 1 ? "" : "s");
- for (d = DK_NDRIVE_ORIG; d <= dhigh; d++)
- (void) fprintf(stdout, "%d ",
- tbl[i].dp->sd.dk_xfer.dk_xfer_val[d]);
- (void) putc('\n', stdout);
- }
- }
- break;
-
- case P_UP:
- if (tbl[i].dp->no) /* have we already printed the uptime? */
- break;
- up = tbl[i].dp->sd.boottime.tv_sec; /* uptime stored here */
- upd = up / 86400;
- up = abs(up - upd * 86400);
- uph = up / 3600;
- up -= uph * 3600;
- upm = up / 60;
- (void) fprintf(stdout, f_h, tbl[i].dp->host);
- switch (upd) {
- case 0:
- (void) fputs("up ", stdout);
- break;
- case 1:
- (void) fprintf(stdout, "up %3d day, ", upd);
- break;
- default:
- (void) fprintf(stdout, "up %3d days, ", upd);
- break;
- }
- (void) fprintf(stdout, "%2d:%02d,", uph, upm);
- (void) fputs(" load average: ", stdout);
- /* average run queue lengths */
- (void) fprintf(stdout, fo_a0,
- loadav(tbl[i].dp->sn.avenrun[AV1]),
- loadav(tbl[i].dp->sn.avenrun[AV5]),
- loadav(tbl[i].dp->sn.avenrun[AV15]));
- (void) putc('\n', stdout);
- break;
- } /* switch (flag) */
- }
- }
-
- /*
- * make the titles for the columns, depending on the options selected
- */
- void
- build_title()
- {
- title1[0] = '\0';
- title2[0] = '\0';
- ruler[0] = '\0';
- if (opts & O_BARE) {
- return;
- }
- if (opts & O_TIME) {
- (void) sprintf(title1 + strlen(title1), f_time, "unix time");
- (void) sprintf(title2 + strlen(title2), f_time, "(seconds)");
- (void) sprintf(ruler + strlen(ruler), fo_time, 100000000);
- }
- if (opts & O_DATE) {
- (void) sprintf(title1 + strlen(title1), f_date, "Date");
- (void) sprintf(title2 + strlen(title2), f_date, "(local time)");
- (void) sprintf(ruler + strlen(ruler), f_date,
- "Thu Jan 1 00:00:00 1970");
- }
- if (opts & O_SECS) {
- (void) sprintf(title1 + strlen(title1), f_secs, "time");
- (void) sprintf(title2 + strlen(title2), f_secs, "(sec)");
- (void) sprintf(ruler + strlen(ruler), fo_secs, 10.01);
- }
- if (nhosts > 1) {
- (void) sprintf(title1 + strlen(title1), f_h, "");
- (void) sprintf(title2 + strlen(title2), f_h, "hostname");
- (void) sprintf(ruler + strlen(ruler), f_h,
- "127.000.000.001");
- }
- if (opts & O_CP) {
- (void) sprintf(title1 + strlen(title1), f1_cp, "%cpu");
- (void) sprintf(title1 + strlen(title1), f1_av, "loadavg (nrun)");
- (void) sprintf(title2 + strlen(title2), f2_cp, "us", "ni", "sy", "id");
- (void) sprintf(title2 + strlen(title2), f2_av, "1m", "5m", "15m");
- (void) sprintf(ruler + strlen(ruler), fo_cp, 100, 100, 100, 100);
- (void) sprintf(ruler + strlen(ruler), fo_av, 10.00, 10.00, 10.00);
- }
- if (opts & O_DK) {
- (void) sprintf(title1 + strlen(title1), f1_dk, "disk xfers");
- (void) sprintf(title2 + strlen(title2), f2_dk,
- "d0", "d1", "d2", "d3");
- (void) sprintf(ruler + strlen(ruler), fo_dk, 10, 10, 10, 10);
- }
- if (opts & O_VM) {
- (void) sprintf(title1 + strlen(title1), f1_vm,
- "pg", "pg", "sw", "sw", "cx", "in");
- (void) sprintf(title2 + strlen(title2), f2_vm,
- "in", "o", "in", "o", "sw", "tr");
- (void) sprintf(ruler + strlen(ruler), fo_vm, 10, 10, 10, 10, 100, 100);
- }
- if (opts & O_IF) {
- (void) sprintf(title1 + strlen(title1), f1_if,
- "i", "i", "o", "o", "co");
- (void) sprintf(title2 + strlen(title2), f2_if,
- "pk", "er", "pk", "er", "ll");
- (void) sprintf(ruler + strlen(ruler), fo_if, 10, 10, 10, 10, 10);
- }
- (void) sprintf(title1 + strlen(title1), "\n");
- (void) sprintf(title2 + strlen(title2), "\n");
- return;
- }
-
- /**
- * initialize signal handlers
- * parse options
- * loop endlessly. either:
- * resolve host names, do client calls
- * or do broadcasts
- **/
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int c, do_usage = 0;
- int i_seen = 0;
- int c_seen = 0;
- unsigned interval = 10;
- char *optstring;
- char *basename;
- char *usage;
- extern int opterr, optind;
- extern char *optarg;
- int opti;
- unsigned hdrcnt;
- unsigned count;
- struct data **dpp;
- struct datatbl *tbl;
-
- tbl = NULL;
- if (gettimeofday(&starttime, &tz) == -1) {
- perror("gettimeofday");
- exit(1);
- }
- (void) signal(SIGHUP, cleanup);
- (void) signal(SIGINT, cleanup);
- (void) signal(SIGTERM, cleanup);
-
- #ifdef HAVE_SETLINEBUF
- /**
- * line-buffer the output
- * permits "tail -f" of a growing log file
- **/
- (void) setlinebuf(stdout);
- #endif
- basename = strrchr(argv[0], '/');
- basename = basename ? ++basename : argv[0];
-
- opterr = 1;
- if (strcmp(basename, "rup") == 0) {
- optstring = "hltn";
- usage = "usage: %s [ -%s ] [ interval ] [ host ... ]\n";
- while ((c = getopt(argc, argv, optstring)) != -1) {
- switch (c) {
- case 'h':
- opts |= O_SHOST;
- break;
- case 'l':
- opts |= O_SORT | O_RVRS;
- key_ptr = (key *) calloc(1, sizeof(key));
- key_ptr->k_offset = sn_offset(avenrun[AV1]);
- break;
- case 't':
- opts |= O_SORT;
- key_ptr = (key *) calloc(1, sizeof(key));
- key_ptr->k_offset = sd_offset(boottime.tv_sec); /* uptime */
- break;
- case 'n':
- opts |= O_NHOST;
- break;
- case '?':
- do_usage++;
- }
- }
- c_seen = 1;
- count = 0;
- opts |= O_UP;
- } else { /* rperf */
- optstring = "acdivhnSTsbBDr";
- usage = "usage: %s [ -%s ] [ interval [ count ] ] [ +sortkey ] [ host ... ]\n";
- while ((c = getopt(argc, argv, optstring)) != -1)
- switch (c) {
- case 'a':
- opts |= O_ALL;
- break;
- case 'c':
- opts |= O_CP;
- break;
- case 'd':
- opts |= O_DK;
- break;
- case 'i':
- opts |= O_IF;
- break;
- case 'S':
- opts |= O_TIME;
- break;
- case 'T':
- opts |= O_DATE;
- break;
- case 's':
- opts |= O_SECS;
- break;
- case 'h':
- opts |= O_SHOST;
- break;
- case 'n':
- opts |= O_NHOST;
- break;
- case 'v':
- opts |= O_VM;
- break;
- case 'b':
- opts |= O_BCST;
- break;
- case 'B':
- opts |= O_BARE;
- break;
- case 'r':
- opts |= O_RVRS;
- break;
- case 'D':
- opts |= O_DBG;
- break;
- case '?':
- do_usage++;
- }
-
- if (!(opts & O_BARE))
- opts |= O_UP;
- }
- if (opts & O_NHOST)
- f_h = "%15.15s ";
-
- opti = optind;
- while (argv[opti]) {
- char *oa;
- unsigned l;
-
- l = strtol(argv[opti], &oa, 0);
- if (argv[opti] == oa || *oa) {
- /* "mml0.meche.rpi.edu" or "128.113.14.20" or "+idle" */
- if (*argv[opti] == '+') {
- char *sortkey;
- key *kp;
-
- sortkey = argv[opti] + sizeof(char);
- for (kp = keys; kp->k_name != NULL; kp++) {
- if (strcmp(sortkey, kp->k_name) == 0) {
- key_ptr = kp;
- break;
- }
- }
- if (key_ptr) {
- opts |= O_SORT;
- } else {
- int i;
- char *p;
-
- (void) fprintf(stderr, "unknown sort key: %s\n", sortkey);
- for (i = 0; p = keyhelp[i]; i++)
- (void) fputs(p, stdout);
- }
- } else {
- h_seen++;
- }
- } else {
- if (!i_seen) {
- interval = l;
- i_seen++;
- } else if (!c_seen) {
- count = l;
- c_seen++;
- }
- }
- opti++;
- }
-
- if (do_usage)
- (void) fprintf(stderr, usage, basename, optstring);
-
- if (h_seen) { /* do client calls */
- if (opts & O_DBG)
- (void) fputs("resolving host names\n", stderr);
- opti = optind;
- dpp = &dp;
-
- while (argv[opti]) {
- char *oa;
- unsigned long host_address;
-
- (void) strtol(argv[opti], &oa, 0);
- if ((argv[opti] == oa || *oa) && *argv[opti] != '+') {
- /* "mml0.meche.rpi.edu" or "128.113.14.20" */
- struct in_addr addr;
- char *hostname;
- struct hostent *host_entry;
-
- hostname = argv[opti];
- host_entry = gethostbyname(hostname);
- if (!host_entry) { /* maybe he typed an address */
- if (opts & O_DBG)
- (void) fputs("byname failed\n", stderr);
- host_address = inet_addr(hostname);
- if (host_address != -1) {
- host_entry =
- gethostbyaddr((char *) &host_address, 4, AF_INET);
- if (!host_entry && opts & O_DBG)
- (void) fputs("byaddr failed\n", stderr);
- } else if (opts & O_DBG)
- (void) fputs("inet_addr failed\n", stderr);
- }
- if (host_entry) {
- bcopy(host_entry->h_addr,
- (char *) &addr.s_addr,
- host_entry->h_length);
- }
- /*
- * maybe he typed a valid address anyway --
- */
- if (!host_entry && (host_address != -1))
- addr.s_addr = host_address;
-
- if (host_entry || (host_address != -1)) {
- /* host ok. add to list */
- if (opts & O_DBG)
- (void) fprintf(stdout, "%s\n", inet_ntoa(addr));
- (*dpp) = new_host(&addr, hostname);
- (*dpp)->datap = NULL;
- dpp = &(*dpp)->datap;
- } else {
- (void) fprintf(stderr, "can't get address for %s\n",
- hostname);
- }
- } /* a host argument */
- opti++;
- }
- if (opts & O_DBG)
- (void) fprintf(stderr, "%d hosts\n", nhosts);
-
- if (!nhosts)
- exit(1);
-
- if (!(opts & O_ALL)) {
- if (nhosts == 1)
- opts |= O_DEFL1;
- else
- opts |= O_DEFL;
- }
- thiscount++;
- doclnt_calls();
- tbl = compute_data(tbl);
-
- if (opts & O_UP) {
- print_data(tbl, P_UP);
- }
- build_title();
-
- for (hdrcnt = 1;;) {
-
- if (c_seen && !count--)
- exit(0);
-
- (void) sleep(interval);
-
- if (!--hdrcnt || nhosts > 1) {
- (void) fputs(title1, stdout);
- (void) fputs(title2, stdout);
- check_term();
- hdrcnt = term_rows ? term_rows - 2 : 20;
- }
- thiscount++;
- doclnt_calls();
- tbl = compute_data(tbl);
- if (opts & O_DBG)
- (void) fprintf(stdout,
- "%d host%s\n", nhosts, nhosts == 1 ? "" : "s");
- print_data(tbl, P_DATA);
- }
-
- } else { /* do broadcasts */
- if (!(opts & O_ALL)) {
- opts |= O_DEFL;
- }
- nhosts = 2;
- build_title();
- nhosts = 0;
-
- for (;;) {
- thiscount++;
-
- if (thiscount == 1 || opts & O_BCST) {
- stats_broadcast resbuf;
- static enum clnt_stat clnt_stat;
-
- (void) signal(SIGALRM, bcst_done);
- (void) alarm(interval); /* broadcast interval. >54 ignored */
- bcst_timo = FALSE;
- (void) fputs("broadcasting ", stdout);
- (void) fflush(stdout);
- bzero((char *) &resbuf, sizeof resbuf);
- clnt_stat = clnt_broadcast(RSTATPROG,
- RSTATVERS_BCST,
- RSTATPROC_STATS,
- xdr_void,
- (char *) NULL,
- XDR_STATSPROC(RSTATVERS_BCST),
- (char *) &resbuf,
- each_result);
- if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) {
- (void) fprintf(stderr, "\nclnt_broadcast: %s\n",
- clnt_sperrno(clnt_stat));
- exit(1);
- }
- (void) putc('\n', stdout);
- } /* thiscount == 1 || opts & O_BCST */
- doclnt_calls();
- tbl = compute_data(tbl);
- if (opts & O_DBG)
- (void) fprintf(stdout,
- "%d host%s\n", nhosts, nhosts == 1 ? "" : "s");
-
- if (opts & O_UP) {
- print_data(tbl, P_UP);
- }
- if (thiscount > 1) {
- (void) fputs(title1, stdout);
- (void) fputs(title2, stdout);
- print_data(tbl, P_DATA);
- }
- if (c_seen && !count--)
- exit(0);
-
- if (!(opts & O_BCST))
- (void) sleep(interval);
- }
- }
- }
-