home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume41 / rperf / part02 < prev    next >
Encoding:
Text File  |  1993-12-19  |  57.0 KB  |  2,264 lines

  1. Newsgroups: comp.sources.misc
  2. From: fitz@rpi.edu (Brian P. Fitzgerald)
  3. Subject: v41i040:  rperf - performance monitoring of network hosts, v3.1, Part02/04
  4. Message-ID: <1993Dec19.205254.28433@sparky.sterling.com>
  5. X-Md4-Signature: 95bc25c2dbb48827cd63845ed5a00528
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Rensselaer Polytechnic Institute, Troy NY
  8. Date: Sun, 19 Dec 1993 20:52:54 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: fitz@rpi.edu (Brian P. Fitzgerald)
  12. Posting-number: Volume 41, Issue 40
  13. Archive-name: rperf/part02
  14. Environment: UNIX
  15. Supersedes: rperf: Volume 39, Issue 69-71
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  The tool that generated this
  22. # shell archive is called "shar", and is available by anonymous ftp
  23. # from ftp.uu.net in subdirectory /usenet/comp.sources.unix, and from many
  24. # other places. Check 'archie' for the latest locations.  If this archive
  25. # is complete, you will see the following message at the end:
  26. #        "End of archive 2 (of 4)."
  27. # Contents:  rstat_xdr.c rstat_xdr.ed rperf.8 rperf.h term.c rpc.c
  28. #   common.h strdup.c hsearch.h
  29. # Wrapped by fitzgb@mml0.meche.rpi.edu on Wed Dec 15 13:06:54 1993
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'rstat_xdr.c' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'rstat_xdr.c'\"
  33. else
  34. echo shar: Extracting \"'rstat_xdr.c'\" \(5383 characters\)
  35. sed "s/^X//" >'rstat_xdr.c' <<'END_OF_FILE'
  36. X#include <stdio.h>
  37. X/*
  38. X * Please do not edit this file.
  39. X * It was generated using rpcgen.
  40. X */
  41. X
  42. X#include <rpc/rpc.h>
  43. X#include "rstat.h"
  44. Xextern int if_opackets_fixed;
  45. X
  46. Xbool_t
  47. Xxdr_rstat_timeval(xdrs, objp)
  48. X    XDR *xdrs;
  49. X    rstat_timeval *objp;
  50. X{
  51. X    if (!xdr_u_int(xdrs, &objp->tv_sec)) {
  52. X        return (FALSE);
  53. X    }
  54. X    if (!xdr_u_int(xdrs, &objp->tv_usec)) {
  55. X        return (FALSE);
  56. X    }
  57. X    return (TRUE);
  58. X}
  59. X
  60. Xbool_t
  61. Xxdr_statsvar(xdrs, objp)
  62. X    XDR *xdrs;
  63. X    statsvar *objp;
  64. X{
  65. X    if (!xdr_array(xdrs, (char **)&objp->cp_time.cp_time_val, (u_int *)&objp->cp_time.cp_time_len, ~0, sizeof(int), xdr_int)) {
  66. X        return (FALSE);
  67. X    }
  68. X    if (!xdr_array(xdrs, (char **)&objp->dk_xfer.dk_xfer_val, (u_int *)&objp->dk_xfer.dk_xfer_len, ~0, sizeof(int), xdr_int)) {
  69. X        return (FALSE);
  70. X    }
  71. X    if (!xdr_u_int(xdrs, &objp->v_pgpgin)) {
  72. X        return (FALSE);
  73. X    }
  74. X    if (!xdr_u_int(xdrs, &objp->v_pgpgout)) {
  75. X        return (FALSE);
  76. X    }
  77. X    if (!xdr_u_int(xdrs, &objp->v_pswpin)) {
  78. X        return (FALSE);
  79. X    }
  80. X    if (!xdr_u_int(xdrs, &objp->v_pswpout)) {
  81. X        return (FALSE);
  82. X    }
  83. X    if (!xdr_u_int(xdrs, &objp->v_intr)) {
  84. X        return (FALSE);
  85. X    }
  86. X    if (!xdr_int(xdrs, &objp->if_ipackets)) {
  87. X        return (FALSE);
  88. X    }
  89. X    if (!xdr_int(xdrs, &objp->if_ierrors)) {
  90. X        return (FALSE);
  91. X    }
  92. X    if (!xdr_int(xdrs, &objp->if_opackets)) {
  93. X        return (FALSE);
  94. X    }
  95. X    if (!xdr_int(xdrs, &objp->if_oerrors)) {
  96. X        return (FALSE);
  97. X    }
  98. X    if (!xdr_int(xdrs, &objp->if_collisions)) {
  99. X        return (FALSE);
  100. X    }
  101. X    if (!xdr_u_int(xdrs, &objp->v_swtch)) {
  102. X        return (FALSE);
  103. X    }
  104. X    if (!xdr_vector(xdrs, (char *)objp->avenrun, 3, sizeof(long), xdr_long)) {
  105. X        return (FALSE);
  106. X    }
  107. X    if (!xdr_rstat_timeval(xdrs, &objp->boottime)) {
  108. X        return (FALSE);
  109. X    }
  110. X    if (!xdr_rstat_timeval(xdrs, &objp->curtime)) {
  111. X        return (FALSE);
  112. X    }
  113. X    return (TRUE);
  114. X}
  115. X
  116. Xbool_t
  117. Xxdr_statstime(xdrs, objp)
  118. X    XDR *xdrs;
  119. X    statstime *objp;
  120. X{
  121. X    if (!xdr_vector(xdrs, (char *)objp->cp_time, CPUSTATES, sizeof(int), xdr_int)) {
  122. X        return (FALSE);
  123. X    }
  124. X    if (!xdr_vector(xdrs, (char *)objp->dk_xfer, DK_NDRIVE, sizeof(int), xdr_int)) {
  125. X        return (FALSE);
  126. X    }
  127. X    if (!xdr_u_int(xdrs, &objp->v_pgpgin)) {
  128. X        return (FALSE);
  129. X    }
  130. X    if (!xdr_u_int(xdrs, &objp->v_pgpgout)) {
  131. X        return (FALSE);
  132. X    }
  133. X    if (!xdr_u_int(xdrs, &objp->v_pswpin)) {
  134. X        return (FALSE);
  135. X    }
  136. X    if (!xdr_u_int(xdrs, &objp->v_pswpout)) {
  137. X        return (FALSE);
  138. X    }
  139. X    if (!xdr_u_int(xdrs, &objp->v_intr)) {
  140. X        return (FALSE);
  141. X    }
  142. X    if (!xdr_int(xdrs, &objp->if_ipackets)) {
  143. X        return (FALSE);
  144. X    }
  145. X    if (!xdr_int(xdrs, &objp->if_ierrors)) {
  146. X        return (FALSE);
  147. X    }
  148. X    if (!xdr_int(xdrs, &objp->if_oerrors)) {
  149. X        return (FALSE);
  150. X    }
  151. X    if (!xdr_int(xdrs, &objp->if_collisions)) {
  152. X        return (FALSE);
  153. X    }
  154. X    if (!xdr_u_int(xdrs, &objp->v_swtch)) {
  155. X        return (FALSE);
  156. X    }
  157. X    if (!xdr_vector(xdrs, (char *)objp->avenrun, 3, sizeof(int), xdr_int)) {
  158. X        return (FALSE);
  159. X    }
  160. X    if (!xdr_rstat_timeval(xdrs, &objp->boottime)) {
  161. X        return (FALSE);
  162. X    }
  163. X    if (!xdr_rstat_timeval(xdrs, &objp->curtime)) {
  164. X        return (FALSE);
  165. X    }
  166. X    if (!xdr_int(xdrs, &objp->if_opackets)) {
  167. X        /**
  168. X         * workaround for servers that
  169. X         * do not report if_opackets
  170. X        **/
  171. X        if_opackets_fixed = 0;
  172. X        objp->if_opackets = 0;
  173. X        /* return (FALSE); */
  174. X    }
  175. X    return (TRUE);
  176. X}
  177. X
  178. Xbool_t
  179. Xxdr_statsswtch(xdrs, objp)
  180. X    XDR *xdrs;
  181. X    statsswtch *objp;
  182. X{
  183. X    if (!xdr_vector(xdrs, (char *)objp->cp_time, CPUSTATES, sizeof(int), xdr_int)) {
  184. X        return (FALSE);
  185. X    }
  186. X    if (!xdr_vector(xdrs, (char *)objp->dk_xfer, DK_NDRIVE, sizeof(int), xdr_int)) {
  187. X        return (FALSE);
  188. X    }
  189. X    if (!xdr_u_int(xdrs, &objp->v_pgpgin)) {
  190. X        return (FALSE);
  191. X    }
  192. X    if (!xdr_u_int(xdrs, &objp->v_pgpgout)) {
  193. X        return (FALSE);
  194. X    }
  195. X    if (!xdr_u_int(xdrs, &objp->v_pswpin)) {
  196. X        return (FALSE);
  197. X    }
  198. X    if (!xdr_u_int(xdrs, &objp->v_pswpout)) {
  199. X        return (FALSE);
  200. X    }
  201. X    if (!xdr_u_int(xdrs, &objp->v_intr)) {
  202. X        return (FALSE);
  203. X    }
  204. X    if (!xdr_int(xdrs, &objp->if_ipackets)) {
  205. X        return (FALSE);
  206. X    }
  207. X    if (!xdr_int(xdrs, &objp->if_ierrors)) {
  208. X        return (FALSE);
  209. X    }
  210. X    if (!xdr_int(xdrs, &objp->if_oerrors)) {
  211. X        return (FALSE);
  212. X    }
  213. X    if (!xdr_int(xdrs, &objp->if_collisions)) {
  214. X        return (FALSE);
  215. X    }
  216. X    if (!xdr_u_int(xdrs, &objp->v_swtch)) {
  217. X        return (FALSE);
  218. X    }
  219. X    if (!xdr_vector(xdrs, (char *)objp->avenrun, 3, sizeof(u_int), xdr_u_int)) {
  220. X        return (FALSE);
  221. X    }
  222. X    if (!xdr_rstat_timeval(xdrs, &objp->boottime)) {
  223. X        return (FALSE);
  224. X    }
  225. X    if (!xdr_int(xdrs, &objp->if_opackets)) {
  226. X        /**
  227. X         * workaround for servers that
  228. X         * do not report if_opackets
  229. X        **/
  230. X        if_opackets_fixed = 0;
  231. X        objp->if_opackets = 0;
  232. X        /* return (FALSE); */
  233. X    }
  234. X    return (TRUE);
  235. X}
  236. X
  237. Xbool_t
  238. Xxdr_stats(xdrs, objp)
  239. X    XDR *xdrs;
  240. X    stats *objp;
  241. X{
  242. X    if (!xdr_vector(xdrs, (char *)objp->cp_time, CPUSTATES, sizeof(int), xdr_int)) {
  243. X        return (FALSE);
  244. X    }
  245. X    if (!xdr_vector(xdrs, (char *)objp->dk_xfer, DK_NDRIVE, sizeof(int), xdr_int)) {
  246. X        return (FALSE);
  247. X    }
  248. X    if (!xdr_u_int(xdrs, &objp->v_pgpgin)) {
  249. X        return (FALSE);
  250. X    }
  251. X    if (!xdr_u_int(xdrs, &objp->v_pgpgout)) {
  252. X        return (FALSE);
  253. X    }
  254. X    if (!xdr_u_int(xdrs, &objp->v_pswpin)) {
  255. X        return (FALSE);
  256. X    }
  257. X    if (!xdr_u_int(xdrs, &objp->v_pswpout)) {
  258. X        return (FALSE);
  259. X    }
  260. X    if (!xdr_u_int(xdrs, &objp->v_intr)) {
  261. X        return (FALSE);
  262. X    }
  263. X    if (!xdr_int(xdrs, &objp->if_ipackets)) {
  264. X        return (FALSE);
  265. X    }
  266. X    if (!xdr_int(xdrs, &objp->if_ierrors)) {
  267. X        return (FALSE);
  268. X    }
  269. X    if (!xdr_int(xdrs, &objp->if_oerrors)) {
  270. X        return (FALSE);
  271. X    }
  272. X    if (!xdr_int(xdrs, &objp->if_collisions)) {
  273. X        return (FALSE);
  274. X    }
  275. X    if (!xdr_int(xdrs, &objp->if_opackets)) {
  276. X        /**
  277. X         * workaround for servers that
  278. X         * do not report if_opackets
  279. X        **/
  280. X        if_opackets_fixed = 0;
  281. X        objp->if_opackets = 0;
  282. X        /* return (FALSE); */
  283. X    }
  284. X    return (TRUE);
  285. X}
  286. END_OF_FILE
  287. if test 5383 -ne `wc -c <'rstat_xdr.c'`; then
  288.     echo shar: \"'rstat_xdr.c'\" unpacked with wrong size!
  289. fi
  290. # end of 'rstat_xdr.c'
  291. fi
  292. if test -f 'rstat_xdr.ed' -a "${1}" != "-c" ; then 
  293.   echo shar: Will not clobber existing file \"'rstat_xdr.ed'\"
  294. else
  295. echo shar: Extracting \"'rstat_xdr.ed'\" \(611 characters\)
  296. sed "s/^X//" >'rstat_xdr.ed' <<'END_OF_FILE'
  297. X/rstat.h/a
  298. Xextern int if_opackets_fixed;
  299. X.
  300. X/^xdr_statstime(/g\
  301. X/if_opackets/+1c
  302. X        /**
  303. X         * workaround for servers that
  304. X         * do not report if_opackets
  305. X        **/
  306. X        if_opackets_fixed = 0;
  307. X        objp->if_opackets = 0;
  308. X        /* return (FALSE); */
  309. X.
  310. X/^xdr_statsswtch(/g\
  311. X/if_opackets/+1c
  312. X        /**
  313. X         * workaround for servers that
  314. X         * do not report if_opackets
  315. X        **/
  316. X        if_opackets_fixed = 0;
  317. X        objp->if_opackets = 0;
  318. X        /* return (FALSE); */
  319. X.
  320. X/^xdr_stats(/g\
  321. X/if_opackets/+1c
  322. X        /**
  323. X         * workaround for servers that
  324. X         * do not report if_opackets
  325. X        **/
  326. X        if_opackets_fixed = 0;
  327. X        objp->if_opackets = 0;
  328. X        /* return (FALSE); */
  329. X.
  330. Xw
  331. Xq
  332. END_OF_FILE
  333. if test 611 -ne `wc -c <'rstat_xdr.ed'`; then
  334.     echo shar: \"'rstat_xdr.ed'\" unpacked with wrong size!
  335. fi
  336. # end of 'rstat_xdr.ed'
  337. fi
  338. if test -f 'rperf.8' -a "${1}" != "-c" ; then 
  339.   echo shar: Will not clobber existing file \"'rperf.8'\"
  340. else
  341. echo shar: Extracting \"'rperf.8'\" \(12408 characters\)
  342. sed "s/^X//" >'rperf.8' <<'END_OF_FILE'
  343. X.\" t
  344. X.\" This program may be copied, redistributed in any form, source or
  345. X.\" binary, and used for any purpose, provided this copyright notice is
  346. X.\" retained.
  347. X.\"
  348. X.\"    @(#)rperf.8    3.1 12/15/93 (c) Copyright Brian P. Fitzgerald
  349. X.\"    Rensselaer Polytechnic Institute
  350. X.\"
  351. X.\"
  352. X.\"    format this man page with:
  353. X.\"        tbl rperf.8 | nroff -man
  354. X.\"        tbl rperf.8 | troff -man
  355. X.\"
  356. X.\"
  357. X.TH RPERF 8 "8 May 1992"
  358. X.SH NAME
  359. Xrperf \- report statistics from network hosts
  360. X.SH SYNOPSIS
  361. X.B rperf
  362. X.RB [\  -aAcdivhnSTsbu1234BDrN?\  ]
  363. X.RI [\  interval
  364. X.RI [\  count\  ]]
  365. X.RI [\  +sortkey\  ]
  366. X.RI [\  host\ ...\  ]
  367. X
  368. X.B rup
  369. X.RB [\  \-hltnD\  ]
  370. X.RI [\  interval\  ]
  371. X.RI [\  host\ ...\  ]
  372. X.SH DESCRIPTION
  373. X.IX  "rperf command"  ""  "\fLrperf\fP \(em report statistics from network hosts"
  374. X.B rperf
  375. Xobtains system statistics from network hosts and prints them to the
  376. Xstandard output at regular intervals.
  377. X.B rperf
  378. Xis similar to xmeter, or SunView perfmeter, but is intended for use on
  379. Xascii terminals, or for logging.
  380. X.LP
  381. XWithout options,
  382. X.B rperf
  383. Xbroadcasts to the local network,
  384. Xprints the uptime for each host that responds, then displays kernel statistics
  385. Xfor these hosts at 10 second intervals until the program is terminated.  If
  386. X.I interval
  387. Xis specified,
  388. X.B rperf
  389. Xsummarizes activity every
  390. X.I interval
  391. Xseconds.
  392. X.I Interval
  393. Xmust be a positive integer.
  394. X.B rperf
  395. Xalways broadcasts for at least 4 seconds per version of rstatd.  By
  396. Xdefault,
  397. X.B rperf
  398. Xbroadcasts using versions 4 and 3 of rstatd.
  399. XIf a
  400. X.I count
  401. Xis given, the statistics are repeated
  402. X.I count
  403. Xtimes.  If the
  404. X.I count
  405. Xis given as zero, rperf displays the hostname,
  406. Xuptime and load average
  407. Xand then exits.
  408. XIf one or more
  409. X.I hosts
  410. Xare specified,
  411. X.B rperf
  412. Xqueries those hosts.
  413. X.LP
  414. XWhile receiving replies,
  415. X.B rperf
  416. Xindicates its progress by printing characters on the display as follows:
  417. X.TS
  418. Xl l .
  419. X+    added a new host to the list
  420. X\.    received reply from host already on the list
  421. Xx    deleted host from the list due to an error
  422. X.TE
  423. X.LP
  424. XIf invoked as
  425. X.B rup,
  426. Xthe program prints the hostname, uptime, and the
  427. Xload average once, and exits.
  428. X.SH OPTIONS
  429. X.TP
  430. X.B \-c
  431. X.SM CPU.
  432. XReport percent utilization of cpu time (user, nice, system, and idle),
  433. Xsimilar to
  434. X.B vmstat.
  435. XFor computers with multiple processors, the average
  436. Xcpu time and load average among all processors is shown.
  437. Xrpc.rstatd on
  438. Xprocessors with more than four cpu states may merge the cpustates
  439. Xin an implementation-defined way.
  440. X.\"
  441. X.\" Thanks Colin Wynd <colin@hpwrc03.mayfield.hp.com>
  442. XFor example, on an hp9000/800 with multiple cpu's, 
  443. X"sys" represents cp_sys + cp_block + cp_swait + cp_intr + cp_ssys
  444. Xand
  445. X"idle" represents cp_idle + cp_wait.
  446. X.\"
  447. XFuture versions of rpc.rstatd may report the values individually.
  448. XAlso, the average number of processes in the run queue (load average) over
  449. Xthe past 1, 5, and 15 minutes is displayed, a` la
  450. X.B rup.
  451. X.TP
  452. X.B \-d
  453. XNumber of completed disk transfers per second.
  454. XReport operations on disks sd0
  455. Xthrough sd3, similar to
  456. X.B vmstat.
  457. XReport on additional disks if they are reported by the
  458. Xremote host being monitored (available from machines running
  459. Xversion 4 of the rpc.rstatd protocol.)
  460. XIt is assumed that the disks are numbered sequentially
  461. Xfrom zero.
  462. X.B rperf
  463. Xhas no way to determine the actual device number on the remote host.
  464. X.TP
  465. X.B \-i
  466. XNetwork interface activity, in events per second.  Report incoming and
  467. Xoutgoing packets transferred, errors, and collisions; similar to
  468. X.B netstat.
  469. X.TP
  470. X.B \-v
  471. XVirtual memory activity, in events per second.  Report pages paged
  472. Xin/out, pages swapped in/out, context switches, and device
  473. X(non-clock) interrupts; similar
  474. Xto
  475. X.B vmstat.
  476. X.TP
  477. X.B \-a
  478. XAll.  Report all of the above.
  479. X.RB ( \-a
  480. Xis the default if only one host is monitored.)
  481. X.TP
  482. X.B \-u
  483. Xuptime.  Report uptime in every data display.
  484. X.LP
  485. XIf more than one host is monitored, but no option flags are specified,
  486. Xeach hostname is printed at left, and the disk activity report is
  487. Xomitted, but this can be overridden by specifying options on the
  488. Xcommand line.
  489. X.LP
  490. XIf the standard output is attached to a terminal, the screen is cleared
  491. Xbefore each display, and as many lines of data that will fit on the
  492. Xscreen are shown, but this can be overridden with the -N option,
  493. Xdescribed below.
  494. XThe default display looks like:
  495. X.in 0
  496. X.nf
  497. Xbroadcasting +++++++++++++++++++....................
  498. Xmaxwell.ecse up   6 days, 14:13,     load average: 0.69 0.73 0.83
  499. X ozone.meche up  15 days,  9:13,     load average: 0.06 0.01 0.00
  500. X  mml0.meche up   4 days,  2:18,     load average: 0.12 0.41 0.26
  501. X\&...
  502. X             %cpu            loadavg (nrun) pg pg sw sw  cx  in   i  i  o  o co
  503. X        host  us  ni  sy  id   1m   5m  15m in  o in  o  sw  tr  pk er pk er ll
  504. Xmaxwell.ecse   9   0  15  77  1.0  0.8  0.9  0  0  0  0  59  68  20  0 19  0  0
  505. X ozone.meche   0   0   0 100  0.0  0.0  0.0  0  0  0  0   4   2   1  -  0  -  0
  506. X  mml0.meche   2   6   6  86  0.1  0.4  0.2  0  0  0  0  13   6   4  -  2  -  0
  507. X\&...
  508. X.fi
  509. X.LP
  510. XThe '-' character means that there have been zero events since boot time,
  511. Xor that the remote host is not configured to report that statistic.
  512. X.LP
  513. XHere is an explanation of the field headings:
  514. X.TS
  515. Xl l.
  516. Xus    percent cpu time in non-niced user processes
  517. Xni    percent cpu time in niced user processes
  518. Xsy    percent cpu time in system calls
  519. Xid    percent cpu time idle
  520. X1m    1 minute load average
  521. X5m    5 minute load average
  522. X15m    15 minute load average
  523. X.TE
  524. X
  525. Xvirtual memory statistics (per second):
  526. X.TS
  527. Xl l.
  528. Xpgin    pages paged in
  529. Xpgo    pages paged out
  530. Xswin    pages swapped in
  531. Xswo    pages swapped out
  532. Xcxsw    context switches
  533. Xintr    device (non-clock) interrupts
  534. X.TE
  535. X
  536. Xnetwork interface statistics (summary, all interfaces), per second:
  537. X.TS
  538. Xl l.
  539. Xipk    incoming packets
  540. Xier    errors for incoming packets
  541. Xopk    outgoing packets
  542. Xoer    errors for outgoing packets
  543. Xcoll    collisions
  544. X.TE
  545. X.LP
  546. XAlso, d0, d1, d2 ... (not shown above) are the completed disk transfers per second for each disk.
  547. XA '-' character in the disk display usually indicates the absence of a disk.
  548. X.SS Additional Options
  549. X.TP
  550. X.B \-n
  551. XDo not resolve host names.  Print the internet address instead.  The
  552. X.B \-n
  553. Xoption can save time and cut network load by eliminating name
  554. Xservice lookups.
  555. X.TP
  556. X.B \-h
  557. XSort by hostname.  By default,
  558. X.B rperf
  559. Xsorts by address.
  560. X.TP
  561. X.B +sortkey
  562. XSort the output by this field in descending order
  563. X(highest value first).
  564. XMany abbreviations are recognized.
  565. XThe sort keys are:
  566. X
  567. X.TS
  568. Xl l l l l l.
  569. Xloadavg    user    pgpgin    disk0    boottime    ipackets
  570. Xav1    nice    pgpgout    disk1    uptime    ierrors
  571. Xav5    sys    pswpin    disk2    curtime    oerrors
  572. Xav15    idle    pswpout    disk3        opackets
  573. X        intr            collisions
  574. X        swtch
  575. X.TE
  576. XFor example,
  577. X.I rperf -au +uptime
  578. Xis sorted by uptime, with the remote host with the longest uptime displayed
  579. Xfirst.
  580. X.I rperf -au +boottime
  581. Xis sorted by boot time, with the latest boot time displayed first.
  582. X.TP
  583. X.B \-r
  584. XSort in ascending order, lowest value first.
  585. X.SS Time Format Options
  586. X.LP
  587. XThe following options are useful for time stamping the output data.
  588. X.TP
  589. X.B \-S
  590. XSeconds since 00:00 Jan 1, 1970, GMT (Unix time)
  591. Xon the machine running
  592. X.B rperf.
  593. XThis format is
  594. Xappropriate if the time value is to be used for further analysis or
  595. Xdisplay plotting.
  596. X.TP
  597. X.B \-T
  598. XDate and local time on the remote machine monitored by
  599. X.B rperf.
  600. X.TP
  601. X.B \-s
  602. XElapsed run time of
  603. X.B rperf,
  604. Xin seconds.
  605. X.TP
  606. X.B \-A
  607. XEquivalent to the
  608. X.B \-a
  609. Xoption, and
  610. X.B \-STsu
  611. X.SS Miscellaneous Options
  612. X.TP
  613. X.B \-N
  614. XNever clear the screen.  Display the data for all hosts, allowing
  615. Xthe data to scroll up the screen, if necessary.
  616. X.TP
  617. X.B \-B
  618. XBare.  Do not print headers or uptime data.
  619. X.B \-B
  620. Ximplies
  621. X.B \-N.
  622. X.TP
  623. X.B \-b
  624. XBroadcast continuously.  In broadcast mode without this option,
  625. X.B rperf
  626. Xbroadcasts to the local network once, and from then on calls the hosts
  627. Xthat responded.  With the -b option,
  628. X.B rperf
  629. Xbroadcasts continuously.
  630. XSome remote hosts do not reply to every broadcast.
  631. XWhen a host that had previously replied fails to reply
  632. Xto a broadcast,
  633. X.B rperf
  634. Xattempts to create a client handle and call the
  635. Xremote host directly.  For this reason, you may notice
  636. Xthat during the first few cycles of operation
  637. Xwith the
  638. X.B \-b option,
  639. X.B rperf's
  640. Xmemory usage will continue to grow slightly from its value after
  641. Xcompleting the first pass.
  642. XContinuous broadcasting is preferable to calling individual hosts
  643. Xbecause network and system load will be lower.  AIX 3.1 users may find that
  644. Xcontinuous broadcasting will hang the machine.
  645. X.TP
  646. X.B \-4, \-3, \-2, -1
  647. XThe highest rstat version to use.  By default,
  648. Xrperf broadcasts with version 4 (which supports variable number of
  649. Xdisks), then version 3 (which is found on almost all
  650. Xreleases of rpc.rstatd).
  651. XThe
  652. X.B \-3
  653. Xoption can save time and reduce network traffic slightly.
  654. XThe
  655. X.B \-2
  656. Xand
  657. X.B \-1
  658. Xoptions are useful mainly as diagnostics for
  659. X.B rpc.rstatd
  660. Xor
  661. X.B rperf.
  662. XBoot time, load average, and context switches are not available
  663. Xwith version 1.  The remote host's local time is not available
  664. Xwith versions 1 and 2.
  665. XDue to an error in many rpc.rstatd implementations, if_opackets
  666. Xis sometimes not available for versions 1, 2 or 3.
  667. XThe presence of this bug is displayed when
  668. X.B rperf
  669. Xis run at debug level 1 or higher.
  670. X.TP
  671. X.B \-D
  672. XDebug level 1.
  673. X.B \-DD
  674. XDebug level 2, etc.
  675. XDisplay diagnostic information.
  676. X
  677. XDuring client calls at debug level 2 and higher,
  678. Xadditional status is displayed by the following characters:
  679. X.TS
  680. Xl l .
  681. X-    no clnt_call made. already have data
  682. Xm    made clnt ok
  683. XM    rpc version mismatch
  684. Xc    clnt_call ok
  685. Xv#    rpc version
  686. X.TE
  687. X.SS rup options
  688. X.TP
  689. X.B \-t
  690. Xsort by uptime in descending order.
  691. X.TP
  692. X.B \-l
  693. Xsort by (one minute) load average in descending order.
  694. X.TP
  695. X.B \-?
  696. Xhelp.  Print a summary of options and sort keys.
  697. X.TP
  698. XSee also -h, -n, and -D, above.
  699. X.SH EXAMPLES
  700. X.LP
  701. XUsually just:
  702. X.LP
  703. X.B rperf
  704. X.I host1 host2 ...
  705. X.LP
  706. Xor
  707. X.LP
  708. X.B rperf -b
  709. X(continuous broadcast mode)
  710. X.LP
  711. X.LP
  712. XYou can use
  713. X.B rperf
  714. Xto log data for later analysis or plotting.  For example,
  715. X.LP
  716. X.B rperf -sBd 900
  717. X.I host > file1
  718. X.LP
  719. Xstores disk activity statistics on
  720. X.I host
  721. Xin a "bare" file (no header) every 15 minutes along with time, in
  722. Xseconds since
  723. X.B rperf
  724. Xwas started.  The activity on disk 0 may then be
  725. Xplotted
  726. X.I vs.
  727. Xhours with:
  728. X.LP
  729. X.nf
  730. Xawk \'{print $1/3600, $2}' \fIfile1\fR > \fIfile2\fR
  731. Xgnuplot
  732. Xgnuplot> plot \fI'file2'\fR
  733. X.fi
  734. X.LP
  735. XThe command
  736. X.LP
  737. X.B rperf
  738. X-a +system
  739. X.LP
  740. Xgives all available statistics for all hosts on the local broadcast
  741. Xnetwork, sorted by system load, and repeats every 10 seconds.
  742. X.SH NOTES
  743. X.LP
  744. XAll hosts to be monitored with
  745. X.B rperf
  746. Xmust be running rpc.rstatd.  On some systems,
  747. Xrstatd is started by uncommenting it from
  748. X/etc/inetd.conf, and sending the running
  749. Xinetd process a SIGHUP.
  750. X.LP
  751. XIf the output alternates between nonzero numbers and zeros, it is
  752. Xpossible that rstatd on the remote host samples the kernel over a
  753. Xlonger interval than you have chosen.  Try running
  754. X.B rperf
  755. Xwith a longer
  756. X.I interval.
  757. X.LP
  758. XIf a host on the local broadcast network responds to rperf
  759. Xwhen the hostname is given on the command line (client call),
  760. Xbut not when 
  761. X.B rperf
  762. Xis run in broadcast mode, the remote host's
  763. Xethernet interface netmask
  764. Xconfiguration may be set incorrectly.
  765. XOn some systems, the netmask is set with
  766. X.B ifconfig
  767. Xin /etc/rc.boot.
  768. XOn other systems, the relevant configuration
  769. Xis set in /etc/tcpip.params.
  770. XYou may be able to check the netmask with "netmask le0"
  771. X(substitute the actual device for "le0").
  772. X.LP
  773. XAlso, a host connected to a smart hub may not be able to broadcast to
  774. Xother hosts.
  775. X.SH DIAGNOSTICS
  776. X.LP
  777. X.B RPC: Program not registered.
  778. XThe remote host is not running rstatd.  
  779. XLog in as root on the remote host and startup rpc.rstatd.
  780. X.LP
  781. X.B RPC: Remote system error
  782. X.B - Too many open files.
  783. X(This error message is misleading because it is
  784. Xactually a local error.) When
  785. X.B rperf
  786. Xstarts up, it increases its open file
  787. Xdescriptor limit to the maximum allowable, if it can.
  788. XIt may be that the local
  789. X.B rperf
  790. Xprocess still has
  791. Xtoo many open files because too many hosts were specified,
  792. Xthat there are too many hosts on the local area net(s)
  793. Xbeing monitored, or that
  794. X.B rperf
  795. Xdoes not know how to increase its
  796. Xopen file limit on your system.  To find out
  797. Xyour file descriptor limit, type
  798. X.B % limit descriptors
  799. Xor
  800. X.B bash$ ulimit -n
  801. X.SH AUTHOR
  802. X.nf
  803. XBrian P. Fitzgerald
  804. XMechanics of Materials Laboratory
  805. XRensselaer Polytechnic Institute
  806. XTroy, New York
  807. X.fi
  808. X
  809. XSend bug reports and patches to fitz@rpi.edu.  Please indicate the
  810. Xmanufacturer and model of your computer, the name and version of
  811. Xyour operating system and the version of
  812. X.B rperf
  813. Xthat you are using.
  814. END_OF_FILE
  815. if test 12408 -ne `wc -c <'rperf.8'`; then
  816.     echo shar: \"'rperf.8'\" unpacked with wrong size!
  817. fi
  818. # end of 'rperf.8'
  819. fi
  820. if test -f 'rperf.h' -a "${1}" != "-c" ; then 
  821.   echo shar: Will not clobber existing file \"'rperf.h'\"
  822. else
  823. echo shar: Extracting \"'rperf.h'\" \(4457 characters\)
  824. sed "s/^X//" >'rperf.h' <<'END_OF_FILE'
  825. X/**
  826. X * This program may be copied, redistributed in any form,
  827. X * source or binary, and used for any purpose, provided
  828. X * this copyright notice is retained.
  829. X *  @(#)rperf.h    3.1 12/15/93 (c) Copyright Brian P. Fitzgerald
  830. X *  Rensselaer Polytechnic Institute
  831. X **/
  832. X
  833. X#ifndef PORTMAP
  834. X#define PORTMAP
  835. X/**
  836. X * ... so that for Solaris 2, in <rpc/clnt.h>
  837. X * we include <rpc/clnt_soc.h>, which declares clntudp_create()
  838. X**/
  839. X#endif                /* !PORTMAP */
  840. X/**
  841. X * <rpc/rpc.h>    includes <rpc/types.h>
  842. X * <rpc/types.h>  includes <sys/types.h>
  843. X * <rpc/types.h>  includes <sys/time.h>
  844. X * <rpc/types.h>  ifndef KERNEL includes <malloc.h>
  845. X * <rpc/rpc.h>    includes <netinet/in.h>
  846. X * (I hope!)
  847. X**/
  848. X#include <rpc/rpc.h>
  849. X#include <rpc/pmap_clnt.h>    /* declare clnt_broadcast() */
  850. X#include "rstat.h"
  851. X
  852. X#include <time.h>
  853. X#include <stdio.h>
  854. X#include <signal.h>
  855. X#include <string.h>
  856. X#include <ctype.h>
  857. X#include <sys/socket.h>
  858. X
  859. X#include <arpa/inet.h>
  860. X#include <netdb.h>
  861. X
  862. X/**
  863. X * The C library hsearch on some systems is incompatible.
  864. X * Use the hsearch that came with this package.
  865. X**/
  866. X#include "hsearch.h"
  867. X
  868. X#ifdef HAVE_SYS_RESOURCE_H
  869. X#include <sys/resource.h>
  870. X#endif                /* HAVE_SYS_RESOURCE_H */
  871. X#ifdef RLIMIT_NOFILE
  872. X#define Rlimit rlimit
  873. X#else                /* !RLIMIT_NOFILE */
  874. Xstruct Rlimit {
  875. X    int             rlim_cur;    /* current (soft) limit */
  876. X    int             rlim_max;    /* maximum value for rlim_cur */
  877. X};
  878. X#endif                /* !RLIMIT_NOFILE */
  879. X
  880. Xtypedef statsvar stats_default;
  881. X
  882. X#define STATS_CONVERT(version) (stats_convert[(version)-1])
  883. X
  884. X#define EACH_RESULT(version) (each_result_vers[(version)-1])
  885. X
  886. X#define XDR_STATSPROC(version) (xdr_statsproc[(version)-1])
  887. X
  888. Xunion stats_all {
  889. X    struct stats    s1;
  890. X    struct statsswtch s2;
  891. X    struct statstime s3;
  892. X    struct statsvar s4;
  893. X};
  894. Xtypedef union stats_all stats_all;
  895. X
  896. X/**
  897. X * the server's rpc.rstatd reports cp_time as clock ticks since boot time
  898. X * (cumulative), or clock ticks since the previous query (incremental).
  899. X**/
  900. Xenum cp_time_kind {
  901. X    CP_TIME_CUM,        /* Sun ... */
  902. X    CP_TIME_INC            /* IBM ... */
  903. X};
  904. Xtypedef enum cp_time_kind cp_time_kind;
  905. X
  906. Xstruct hash_info {
  907. X    struct in_addr  ident_addr;
  908. X    struct data    *datap;
  909. X};
  910. Xtypedef struct hash_info hash_info;
  911. X
  912. Xstruct data {
  913. X    struct data    *datap;
  914. X    u_long          nn;
  915. X    u_long          no;
  916. X    struct in_addr  addr;
  917. X    char           *host;
  918. X    char           *host_dup;
  919. X    CLIENT         *cl;
  920. X    u_long          clnt_vers;
  921. X    u_long          bcst_vers;
  922. X    u_long          ok_to_call;
  923. X    stats_default   sn;
  924. X    stats_default   so;
  925. X    stats_default   sd;        /* delta or rate.  uptime = sd.boottime */
  926. X    cp_time_kind    cp_kind;
  927. X};
  928. Xextern struct data *dp;
  929. X
  930. Xstruct array {
  931. X    u_int           len;
  932. X    int            *val;
  933. X};
  934. Xtypedef struct array array;
  935. X
  936. X/* <sys/dk.h> */
  937. X#define CP_USER         0
  938. X#define CP_NICE         1
  939. X#define CP_SYS          2
  940. X#define CP_IDLE         3
  941. X
  942. X#define cpu(dt) (dcpu ? ((dt) * 100 + hdcpu ) / dcpu : 0)
  943. X#define loadav(nrun) ( (float) (nrun) / FSCALE )
  944. X#define delta(x) ((*dpp)->sn.x - (*dpp)->so.x)    /* use this macro with care */
  945. X#define rate(x)    (dt ? ((x) * 1000L + hdt ) / dt : 0)
  946. X
  947. X#define t_d(j) tbl[(j)].dp->sd
  948. X#define t_o(j) tbl[(j)].dp->so
  949. X#define t_n(j) tbl[(j)].dp->sn
  950. X
  951. Xstruct key {
  952. X    char           *k_name;
  953. X    int             k_noffset;
  954. X    int             k_doffset;
  955. X    int             k_flag;
  956. X    int             k_index;
  957. X};
  958. Xtypedef struct key key;
  959. X
  960. X#define        K_DELTA 0x1    /* need delta before sorting */
  961. X#define        K_NZERO 0x2    /* must be nonzero for sorting */
  962. X#define        K_ARRAY    0x4    /* the member is an xdr_array */
  963. X
  964. X/* C faq */
  965. X#ifndef offsetof
  966. X#define offsetof(type, mem) ((size_t) \
  967. X        ((char *)&((type *) 0)->mem - (char *)((type *) 0)))
  968. X#endif                /* !offsetof */
  969. X#define sd_offset(mem) offsetof(struct data,sd.mem)
  970. X#define sn_offset(mem) offsetof(struct data,sn.mem)
  971. X
  972. X#define AV1    0
  973. X#define AV5    1
  974. X#define AV15    2
  975. X
  976. Xstruct datatbl {
  977. X    int             val;
  978. X    struct data    *dp;
  979. X};
  980. X
  981. X#define    P_DATA    0
  982. X#define    P_UP    1
  983. X
  984. X#define cp_val cp_time.cp_time_val
  985. X#define cp_len cp_time.cp_time_len
  986. X#define dk_val dk_xfer.dk_xfer_val
  987. X#define dk_len dk_xfer.dk_xfer_len
  988. X
  989. X#define MODE_BCST 0        /* no host args were supplied. */
  990. X#define MODE_CALL 1        /* one or more host args was supplied. */
  991. Xextern unsigned long mode;
  992. Xextern unsigned long thiscount;
  993. Xextern unsigned long nhosts;
  994. X
  995. Xstruct data    *new_host();
  996. Xvoid            create_array();
  997. Xvoid            destroy_array();
  998. Xvoid            doclnt_calls();
  999. Xvoid            do_broadcast();
  1000. END_OF_FILE
  1001. if test 4457 -ne `wc -c <'rperf.h'`; then
  1002.     echo shar: \"'rperf.h'\" unpacked with wrong size!
  1003. fi
  1004. # end of 'rperf.h'
  1005. fi
  1006. if test -f 'term.c' -a "${1}" != "-c" ; then 
  1007.   echo shar: Will not clobber existing file \"'term.c'\"
  1008. else
  1009. echo shar: Extracting \"'term.c'\" \(3424 characters\)
  1010. sed "s/^X//" >'term.c' <<'END_OF_FILE'
  1011. X/**
  1012. X * Derived from screen.c in "top", by Paul Vixie
  1013. X**/
  1014. X#include "common.h"
  1015. X#include <stdio.h>
  1016. X#include <sys/ioctl.h>
  1017. X#ifndef TIOCGWINSZ
  1018. X#ifdef HAVE_SYS_TERMIOS_H
  1019. X#include <sys/termios.h>
  1020. X#else                /* !HAVE_SYS_TERMIOS_H */
  1021. X#ifdef HAVE_SYS_TERMIO_H
  1022. X#include <sys/termio.h>
  1023. X#endif                /* HAVE_SYS_TERMIO_H */
  1024. X#endif                /* !HAVE_SYS_TERMIOS_H */
  1025. X#endif                /* !TIOCGWINSZ */
  1026. X#ifdef HAVE_SYS_BSD_TTY_H
  1027. X#include <sys/bsd_tty.h>
  1028. X#endif                /* HAVE_SYS_BSD_TTY_H */
  1029. X
  1030. X#include "term.h"
  1031. X
  1032. X/* <sys/ioctl.h> or <sys/ttycom.h> */
  1033. Xstruct Winsize {
  1034. X    unsigned short  ws_row;    /* rows, in characters */
  1035. X    unsigned short  ws_col;    /* columns, in characters */
  1036. X    unsigned short  ws_xpixel;    /* horizontal size, pixels - not used */
  1037. X    unsigned short  ws_ypixel;    /* vertical size, pixels - not used */
  1038. X};
  1039. X
  1040. X/* system functions */
  1041. X
  1042. Xchar           *getenv();
  1043. X
  1044. Xchar           *tgetstr();
  1045. Xint             tgetent();
  1046. Xint             tgetnum();
  1047. X
  1048. X/* macros */
  1049. X
  1050. X#define TCputs(str)    tputs(str, 1, putstdout)
  1051. X#define putcap(str)    (void)((str) != NULL ? TCputs(str) : 0)
  1052. X
  1053. Xchar            termcap_buf[1024];
  1054. Xchar            string_buffer[1024];
  1055. Xint             termcap_status;
  1056. Xint             t_rows;
  1057. Xint             t_cols;
  1058. Xchar           *clear_screen;
  1059. Xstatic int      smart_terminal;
  1060. X
  1061. X/* This has to be defined as a subroutine for tputs (instead of a macro) */
  1062. Xint
  1063. Xputstdout(ch)
  1064. X    char            ch;
  1065. X{
  1066. X    return putchar(ch);
  1067. X}
  1068. X
  1069. Xvoid
  1070. Xinit_termcap()
  1071. X{
  1072. X    char           *efmt = "Can't get terminal size because\n%s";
  1073. X    char           *term;
  1074. X    char           *bufptr;
  1075. X
  1076. X    bufptr = string_buffer;
  1077. X
  1078. X    term = getenv("TERM");
  1079. X    if (!term) {
  1080. X    (void) fprintf(stderr, efmt, "TERM environment variable not set.\n");
  1081. X    return;
  1082. X    }
  1083. X    termcap_status = tgetent(termcap_buf, term);
  1084. X    switch (termcap_status) {
  1085. X    case -1:
  1086. X    (void) fprintf(stderr, efmt, "can't open termcap file.\n");
  1087. X    return;
  1088. X    case 0:
  1089. X    (void) fprintf(stderr, efmt, "no termcap entry for a ");
  1090. X    (void) fprintf(stderr, "`%s' terminal\n", term);
  1091. X    return;
  1092. X    case 1:
  1093. X    smart_terminal = 1;    /* assume */
  1094. X    t_rows = tgetnum("li");
  1095. X    if (t_rows == -1)
  1096. X        t_rows = 0;
  1097. X    t_cols = tgetnum("co");
  1098. X    if (t_cols == -1)
  1099. X        t_cols = 0;
  1100. X
  1101. X    clear_screen = tgetstr("cl", &bufptr);
  1102. X    smart_terminal = clear_screen ? 1 : 0;
  1103. X
  1104. X    return;
  1105. X    }
  1106. X}
  1107. X
  1108. Xvoid
  1109. Xclear()
  1110. X{
  1111. X    if (smart_terminal) {
  1112. X    putcap(clear_screen);
  1113. X    (void) fflush(stdout);
  1114. X    }
  1115. X}
  1116. X
  1117. X
  1118. X/**
  1119. X * get terminal size
  1120. X**/
  1121. Xvoid
  1122. Xcheck_term(t_rowp, t_colp)
  1123. X    unsigned short *t_rowp, *t_colp;
  1124. X{
  1125. X    struct Winsize  winsize;
  1126. X
  1127. X    winsize.ws_row = 0;
  1128. X    winsize.ws_col = 0;
  1129. X
  1130. X    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *) &winsize) == -1) {
  1131. X    /* if error, then assume not a terminal */
  1132. X    if (t_rowp)
  1133. X        *t_rowp = t_rows;
  1134. X    if (t_colp)
  1135. X        *t_colp = t_cols;
  1136. X
  1137. X    switch (errno) {
  1138. X        static int      einvalseen;
  1139. X        static int      enodevseen;
  1140. X        static int      eopnotsuppseen;
  1141. X        static int      enottyseen;
  1142. X
  1143. X    case EINVAL:
  1144. X        if (einvalseen)
  1145. X        return;
  1146. X        einvalseen = 1;
  1147. X        break;
  1148. X    case ENODEV:
  1149. X        if (enodevseen)
  1150. X        return;
  1151. X        enodevseen = 1;
  1152. X        break;
  1153. X    case EOPNOTSUPP:
  1154. X        if (eopnotsuppseen)
  1155. X        return;
  1156. X        eopnotsuppseen = 1;
  1157. X        break;
  1158. X    case ENOTTY:
  1159. X        if (enottyseen)
  1160. X        return;
  1161. X        enottyseen = 1;
  1162. X        break;
  1163. X    }
  1164. X    if (dbg_lvl >= 1)
  1165. X        perror("ioctl: TIOCGWINSZ");
  1166. X    return;
  1167. X    }
  1168. X    if (t_rowp)
  1169. X    *t_rowp = winsize.ws_row ? winsize.ws_row : t_rows;
  1170. X    if (t_colp)
  1171. X    *t_colp = winsize.ws_col ? winsize.ws_col : t_cols;
  1172. X}
  1173. END_OF_FILE
  1174. if test 3424 -ne `wc -c <'term.c'`; then
  1175.     echo shar: \"'term.c'\" unpacked with wrong size!
  1176. fi
  1177. # end of 'term.c'
  1178. fi
  1179. if test -f 'rpc.c' -a "${1}" != "-c" ; then 
  1180.   echo shar: Will not clobber existing file \"'rpc.c'\"
  1181. else
  1182. echo shar: Extracting \"'rpc.c'\" \(21859 characters\)
  1183. sed "s/^X//" >'rpc.c' <<'END_OF_FILE'
  1184. X/**
  1185. X * This program may be copied, redistributed in any form,
  1186. X * source or binary, and used for any purpose, provided
  1187. X * this copyright notice is retained.
  1188. X *
  1189. X * @(#)rpc.c    3.1 12/15/93 (c) Copyright Brian P. Fitzgerald
  1190. X * Rensselaer Polytechnic Institute
  1191. X *
  1192. X**/
  1193. X
  1194. X#include "common.h"
  1195. X#include "rperf.h"
  1196. X
  1197. Xstatic bool_t   bcst_timo;
  1198. X
  1199. Xstatic struct timeval call_timo = {25, 0};
  1200. X
  1201. Xbool_t(*xdr_statsproc[]) () =
  1202. X{
  1203. X    xdr_stats,
  1204. X    xdr_statsswtch,
  1205. X    xdr_statstime,
  1206. X    xdr_statsvar,
  1207. X};
  1208. X
  1209. Xchar           *emfilehelp[] = {
  1210. X    "You may be trying to monitor too many hosts at once.",
  1211. X    "Consider increasing the system per-process hard limit",
  1212. X    "on open files, or else monitor fewer hosts.",
  1213. X    "If you are using broadcast mode, try the -b option.",
  1214. X    0
  1215. X};
  1216. X
  1217. Xchar           *doclnt_call_help[] = {
  1218. X    "",
  1219. X    "client call debug mode.  key:",
  1220. X    "m made client\tc called client\t\tv4,v3,v2,v1 version called",
  1221. X    "- no call made\tM version mismatch\tx drop\t* down",
  1222. X    "",
  1223. X    0
  1224. X};
  1225. X
  1226. Xstruct data    *dp;        /* link list head */
  1227. X
  1228. Xint             if_opackets_fixed = 1;
  1229. X
  1230. Xvoid
  1231. Xdestroy_array(a)
  1232. X    array          *a;
  1233. X{
  1234. X    if (a->val) {
  1235. X    free((char *) a->val);
  1236. X    a->val = (int *) NULL;
  1237. X    }
  1238. X}
  1239. X
  1240. X/**
  1241. X * copy n ints from p to a->val
  1242. X**/
  1243. Xvoid
  1244. Xcopy_to_array(a, p, n)
  1245. X    array          *a;
  1246. X    int            *p;
  1247. X    unsigned int    n;
  1248. X{
  1249. X    int             i;
  1250. X
  1251. X    if (n > a->len) {
  1252. X    (void) fprintf(stderr,
  1253. X               "copy_to_array: attempt to overwrite end of array\n");
  1254. X    exit(1);
  1255. X    }
  1256. X    if (!p) {
  1257. X    (void) fprintf(stderr,
  1258. X               "copy_to_array: no source array\n");
  1259. X    exit(1);
  1260. X    }
  1261. X    if (!a->val) {
  1262. X    (void) fprintf(stderr,
  1263. X               "copy_to_array: no destination array\n");
  1264. X    exit(1);
  1265. X    }
  1266. X    for (i = 0; i < n; i++)
  1267. X    a->val[i] = p[i];
  1268. X    return;
  1269. X}
  1270. X
  1271. X/**
  1272. X * allocate the value part of an array struct, size n
  1273. X**/
  1274. Xvoid
  1275. Xcreate_array(a, n)
  1276. X    array          *a;
  1277. X    unsigned int    n;
  1278. X{
  1279. X    a->len = n;
  1280. X    a->val = (int *) malloc((unsigned) n * sizeof(int));
  1281. X    if (a->val == NULL) {
  1282. X    perror("malloc");
  1283. X    exit(1);
  1284. X    }
  1285. X    return;
  1286. X}
  1287. X
  1288. X/**
  1289. X * convert and store the received data
  1290. X**/
  1291. Xstats_default  *
  1292. Xfrom_stats(s)
  1293. X    stats_all      *s;
  1294. X{
  1295. X    static stats_default r;
  1296. X
  1297. X    bzero((char *) &r, sizeof(r));
  1298. X    create_array((array *) & r.cp_time, CPUSTATES);
  1299. X    copy_to_array((array *) & r.cp_time, s->s1.cp_time, CPUSTATES);
  1300. X    create_array((array *) & r.dk_xfer, DK_NDRIVE);
  1301. X    copy_to_array((array *) & r.dk_xfer, s->s1.dk_xfer, DK_NDRIVE);
  1302. X    r.v_pgpgin = s->s1.v_pgpgin;
  1303. X    r.v_pgpgout = s->s1.v_pgpgout;
  1304. X    r.v_pswpin = s->s1.v_pswpin;
  1305. X    r.v_pswpout = s->s1.v_pswpout;
  1306. X    r.v_intr = s->s1.v_intr;
  1307. X    r.if_ipackets = s->s1.if_ipackets;
  1308. X    r.if_ierrors = s->s1.if_ierrors;
  1309. X    r.if_opackets = s->s1.if_opackets;
  1310. X    r.if_oerrors = s->s1.if_oerrors;
  1311. X    r.if_collisions = s->s1.if_collisions;
  1312. X    if (gettimeofday((struct timeval *) & r.curtime,
  1313. X             (struct timezone *) NULL) == -1) {
  1314. X    perror("gettimeofday");
  1315. X    exit(1);
  1316. X    }
  1317. X    return &r;
  1318. X}
  1319. X
  1320. Xstats_default  *
  1321. Xfrom_statsswtch(s)
  1322. X    stats_all      *s;
  1323. X{
  1324. X    int             i;
  1325. X    static stats_default r;
  1326. X
  1327. X    bzero((char *) &r, sizeof(r));
  1328. X    create_array((array *) & r.cp_time, CPUSTATES);
  1329. X    copy_to_array((array *) & r.cp_time, s->s2.cp_time, CPUSTATES);
  1330. X    create_array((array *) & r.dk_xfer, DK_NDRIVE);
  1331. X    copy_to_array((array *) & r.dk_xfer, s->s2.dk_xfer, DK_NDRIVE);
  1332. X    r.v_pgpgin = s->s2.v_pgpgin;
  1333. X    r.v_pgpgout = s->s2.v_pgpgout;
  1334. X    r.v_pswpin = s->s2.v_pswpin;
  1335. X    r.v_pswpout = s->s2.v_pswpout;
  1336. X    r.v_intr = s->s2.v_intr;
  1337. X    r.if_ipackets = s->s2.if_ipackets;
  1338. X    r.if_ierrors = s->s2.if_ierrors;
  1339. X    r.if_opackets = s->s2.if_opackets;
  1340. X    r.if_oerrors = s->s2.if_oerrors;
  1341. X    r.if_collisions = s->s2.if_collisions;
  1342. X    r.v_swtch = s->s2.v_swtch;
  1343. X    for (i = 0; i < 3; i++)
  1344. X    r.avenrun[i] = s->s2.avenrun[i];
  1345. X    r.boottime = s->s2.boottime;
  1346. X    if (gettimeofday((struct timeval *) & r.curtime,
  1347. X             (struct timezone *) NULL) == -1) {
  1348. X    perror("gettimeofday");
  1349. X    exit(1);
  1350. X    }
  1351. X    return &r;
  1352. X}
  1353. X
  1354. Xstats_default  *
  1355. Xfrom_statstime(s)
  1356. X    stats_all      *s;
  1357. X{
  1358. X    int             i;
  1359. X    static stats_default r;
  1360. X
  1361. X    bzero((char *) &r, sizeof(r));
  1362. X    create_array((array *) & r.cp_time, CPUSTATES);
  1363. X    copy_to_array((array *) & r.cp_time, s->s3.cp_time, CPUSTATES);
  1364. X    create_array((array *) & r.dk_xfer, DK_NDRIVE);
  1365. X    copy_to_array((array *) & r.dk_xfer, s->s3.dk_xfer, DK_NDRIVE);
  1366. X    r.v_pgpgin = s->s3.v_pgpgin;
  1367. X    r.v_pgpgout = s->s3.v_pgpgout;
  1368. X    r.v_pswpin = s->s3.v_pswpin;
  1369. X    r.v_pswpout = s->s3.v_pswpout;
  1370. X    r.v_intr = s->s3.v_intr;
  1371. X    r.if_ipackets = s->s3.if_ipackets;
  1372. X    r.if_ierrors = s->s3.if_ierrors;
  1373. X    r.if_opackets = s->s3.if_opackets;
  1374. X    r.if_oerrors = s->s3.if_oerrors;
  1375. X    r.if_collisions = s->s3.if_collisions;
  1376. X    r.v_swtch = s->s3.v_swtch;
  1377. X    for (i = 0; i < 3; i++)
  1378. X    r.avenrun[i] = s->s3.avenrun[i];
  1379. X    r.boottime = s->s3.boottime;
  1380. X    r.curtime = s->s3.curtime;
  1381. X    return &r;
  1382. X}
  1383. X
  1384. Xstats_default  *
  1385. Xfrom_statsvar(s)
  1386. X    stats_all      *s;
  1387. X{
  1388. X    int             i;
  1389. X    static stats_default r;
  1390. X
  1391. X    bzero((char *) &r, sizeof(r));
  1392. X    create_array((array *) & r.cp_time, s->s4.cp_len);
  1393. X    copy_to_array((array *) & r.cp_time, s->s4.cp_val, s->s4.cp_len);
  1394. X    create_array((array *) & r.dk_xfer, s->s4.dk_len);
  1395. X    copy_to_array((array *) & r.dk_xfer, s->s4.dk_val, s->s4.dk_len);
  1396. X    r.v_pgpgin = s->s4.v_pgpgin;
  1397. X    r.v_pgpgout = s->s4.v_pgpgout;
  1398. X    r.v_pswpin = s->s4.v_pswpin;
  1399. X    r.v_pswpout = s->s4.v_pswpout;
  1400. X    r.v_intr = s->s4.v_intr;
  1401. X    r.if_ipackets = s->s4.if_ipackets;
  1402. X    r.if_ierrors = s->s4.if_ierrors;
  1403. X    r.if_opackets = s->s4.if_opackets;
  1404. X    r.if_oerrors = s->s4.if_oerrors;
  1405. X    r.if_collisions = s->s4.if_collisions;
  1406. X    r.v_swtch = s->s4.v_swtch;
  1407. X    for (i = 0; i < 3; i++)
  1408. X    r.avenrun[i] = s->s4.avenrun[i];
  1409. X    r.boottime = s->s4.boottime;
  1410. X    r.curtime = s->s4.curtime;
  1411. X    return &r;
  1412. X}
  1413. X
  1414. Xstats_default  *((*stats_convert[]) ()) =
  1415. X{
  1416. X    from_stats,
  1417. X    from_statsswtch,
  1418. X    from_statstime,
  1419. X    from_statsvar,
  1420. X};
  1421. X
  1422. X/**
  1423. X * free the cp_time and dk_xfer array in a stats_default struct
  1424. X**/
  1425. Xvoid
  1426. Xfree_stats(s)
  1427. X    stats_default  *s;
  1428. X{
  1429. X    destroy_array((array *) & s->cp_time);
  1430. X    destroy_array((array *) & s->dk_xfer);
  1431. X    return;
  1432. X}
  1433. X
  1434. X/**
  1435. X * save the results in a data structure
  1436. X * return 1 if the results were saved
  1437. X * return 0 if the results were ignored
  1438. X**/
  1439. Xint
  1440. Xsave_res(d, res)
  1441. X    struct data    *d;
  1442. X    stats_default  *res;
  1443. X{
  1444. X    if (d->nn == thiscount) {
  1445. X    free_stats(res);
  1446. X    return 0;        /* duplicate.  ignore */
  1447. X    }
  1448. X    d->no = d->nn;
  1449. X    d->nn = thiscount;
  1450. X    if (!d->ok_to_call)
  1451. X    (void) fprintf(stderr, " %s is back up ", d->host);
  1452. X    d->ok_to_call = 1;
  1453. X
  1454. X    free_stats(&d->so);
  1455. X    d->so = d->sn;
  1456. X    d->sn = *res;
  1457. X    return 1;
  1458. X}
  1459. X
  1460. X/**
  1461. X * this function may be called after (*dpp)->addr
  1462. X * has been filled with a valid in_addr
  1463. X * return: 1=success, 0=fail
  1464. X**/
  1465. Xint
  1466. Xmake_client(dpp)
  1467. X    struct data   **dpp;
  1468. X{
  1469. X    int             sock = RPC_ANYSOCK;
  1470. X    static int      emfilewarned;
  1471. X    struct sockaddr_in server_addr;
  1472. X    struct timeval  p_timo;
  1473. X
  1474. X    p_timo.tv_sec = 3;
  1475. X    p_timo.tv_usec = 0;
  1476. X
  1477. X    server_addr.sin_family = AF_INET;
  1478. X    server_addr.sin_port = 0;
  1479. X    server_addr.sin_addr = (*dpp)->addr;
  1480. X
  1481. X    /**
  1482. X     * clntudp_create only determines whether the
  1483. X     * program is registered.  It does not actually check
  1484. X     * whether the host supports the requested version.
  1485. X     * see the pmap_getport man page.
  1486. X     **/
  1487. X    errno = 0;
  1488. X    (*dpp)->cl = clntudp_create(&server_addr,
  1489. X                RSTATPROG,
  1490. X                (*dpp)->clnt_vers,
  1491. X                p_timo,
  1492. X                &sock);
  1493. X
  1494. X    if ((*dpp)->cl == NULL) {
  1495. X    if (rpc_createerr.cf_stat == RPC_SYSTEMERROR
  1496. X        && rpc_createerr.cf_error.re_errno == EMFILE) {
  1497. X        if (!emfilewarned) {
  1498. X        (void) fprintf(stderr, "Can't contact rstatd on %s.\n",
  1499. X                   (*dpp)->host);
  1500. X        (void) clnt_pcreateerror("clntudp_create");
  1501. X        (void) fprintf(stderr, "Open file descriptor limit now %d\n",
  1502. X                   set_max_nofiles());
  1503. X        msg(emfilehelp, stderr);
  1504. X        emfilewarned = 1;
  1505. X        }
  1506. X    } else {
  1507. X        (void) fprintf(stderr, "Can't contact rstatd on %s.  ",
  1508. X               (*dpp)->host);
  1509. X        (void) clnt_pcreateerror("clntudp_create");
  1510. X    }
  1511. X    return 0;
  1512. X    }
  1513. X    if (dbg_lvl >= 2) {
  1514. X    (void) putc('m', stderr);
  1515. X    (void) fflush(stderr);
  1516. X    }
  1517. X    return 1;
  1518. X}
  1519. X
  1520. X/**
  1521. X * for each host on the linked list that still needs data:
  1522. X * loop over the rpc prog versions,
  1523. X *    starting with the highest known version,
  1524. X *    or highest previously successful version
  1525. X *        make a client, if necessary
  1526. X *        call the client
  1527. X **/
  1528. Xvoid
  1529. Xdoclnt_calls(vers_max)
  1530. X    u_long          vers_max;
  1531. X{
  1532. X    u_long          vers;
  1533. X    int             good = 0;
  1534. X    int             bad = 0;
  1535. X    static enum clnt_stat clnt_stat;
  1536. X    stats_default  *sn;
  1537. X    struct data   **dpp;
  1538. X    stats_all       resbuf;
  1539. X
  1540. X    if (dbg_lvl >= 2)
  1541. X    msg(doclnt_call_help, stderr);
  1542. X
  1543. X    for (dpp = &dp; *dpp;) {
  1544. X    if (dbg_lvl >= 2)
  1545. X        (void) fprintf(stderr, "%s\t%s\t",
  1546. X               inet_ntoa((*dpp)->addr), (*dpp)->host);
  1547. X    if ((*dpp)->nn == thiscount) {
  1548. X        dpp = &(*dpp)->datap;
  1549. X        if (dbg_lvl >= 2) {
  1550. X        (void) fputs("-\n", stderr);
  1551. X        }
  1552. X        continue;        /* already have data */
  1553. X    }
  1554. X    if (!(*dpp)->ok_to_call) {
  1555. X        dpp = &(*dpp)->datap;
  1556. X        if (dbg_lvl >= 2) {
  1557. X        (void) fputs("*\n", stderr);
  1558. X        }
  1559. X        continue;        /* probably down */
  1560. X    }
  1561. X    if (!(*dpp)->clnt_vers)
  1562. X        (*dpp)->clnt_vers = vers_max;    /* try first */
  1563. X
  1564. X    for (vers = (*dpp)->clnt_vers; vers > 0; vers--) {
  1565. X        (*dpp)->clnt_vers = vers;
  1566. X        if (!(*dpp)->cl)
  1567. X        if (!make_client(dpp)) {
  1568. X            (*dpp)->ok_to_call = 0;
  1569. X            bad++;
  1570. X            break;    /* vers */
  1571. X        }
  1572. X        if (dbg_lvl >= 2) {
  1573. X        (void) fprintf(stderr, "v%d", vers);
  1574. X        (void) fflush(stderr);
  1575. X        }
  1576. X        bzero((char *) &resbuf, sizeof(resbuf));
  1577. X        clnt_stat = clnt_call((*dpp)->cl,
  1578. X                  RSTATPROC_STATS,
  1579. X                  xdr_void,
  1580. X                  NULL,
  1581. X                  XDR_STATSPROC((*dpp)->clnt_vers),
  1582. X                  (char *) &resbuf,
  1583. X                  call_timo);
  1584. X        if (clnt_stat == RPC_SUCCESS) {
  1585. X        sn = STATS_CONVERT((*dpp)->clnt_vers) (&resbuf);
  1586. X        /**
  1587. X         * 11/3/93 I have checked that
  1588. X         * xdr_free is needed here, so don't delete it
  1589. X        **/
  1590. X        xdr_free(XDR_STATSPROC((*dpp)->clnt_vers), (char *) &resbuf);
  1591. X        (void) save_res(*dpp, sn);
  1592. X
  1593. X        if (!(*dpp)->no && !if_opackets_fixed && dbg_lvl >= 1) {
  1594. X            (void) fprintf(stderr,
  1595. X             "%s: rpc.rstatd vers %d does not report if_opackets\n",
  1596. X                   (*dpp)->host, (*dpp)->clnt_vers);
  1597. X        }
  1598. X        if_opackets_fixed = 1;
  1599. X
  1600. X        if (dbg_lvl >= 2) {
  1601. X            (void) fputs("c\n", stderr);
  1602. X        }
  1603. X        good++;
  1604. X        dpp = &(*dpp)->datap;
  1605. X        break;        /* vers */
  1606. X        }
  1607. X        xdr_free(XDR_STATSPROC((*dpp)->clnt_vers), (char *) &resbuf);
  1608. X        if (clnt_stat == RPC_PROGVERSMISMATCH && vers > 1) {
  1609. X        if (dbg_lvl >= 2) {
  1610. X            (void) fputs("M ", stderr);
  1611. X            (void) fflush(stderr);
  1612. X        }
  1613. X        clnt_destroy((*dpp)->cl);
  1614. X        (*dpp)->cl = NULL;
  1615. X        continue;    /* vers-- */
  1616. X        }
  1617. X        (void) fprintf(stderr, "clnt_call: %s %s\n",
  1618. X               (*dpp)->host, clnt_sperrno(clnt_stat));
  1619. X        (*dpp)->ok_to_call = 0;
  1620. X        bad++;
  1621. X        break;        /* vers */
  1622. X    }            /* for(vers ... */
  1623. X    }                /* for dpp */
  1624. X
  1625. X    if (dbg_lvl >= 1) {
  1626. X    (void) fprintf(stderr, "done clnt calls good=%d bad=%d\n", good, bad);
  1627. X    }
  1628. X    if (mode == MODE_CALL && !good) {
  1629. X    if (nhosts > 1) {
  1630. X        (void) fprintf(stderr, "None of the hosts replied.  Quitting.\n");
  1631. X    } else {
  1632. X        dpp = &dp;
  1633. X        (void) fprintf(stderr, "%s did not reply.  Quitting.\n", (*dpp)->host);
  1634. X    }
  1635. X    exit(1);
  1636. X    }
  1637. X    return;
  1638. X}
  1639. X
  1640. X/**
  1641. X * create a new data structure
  1642. X**/
  1643. Xstruct data    *
  1644. Xnew_host(addr, hostname)
  1645. X    struct in_addr *addr;
  1646. X    char           *hostname;
  1647. X{
  1648. X    struct data    *newdpp;
  1649. X
  1650. X    newdpp = (struct data *) calloc(1, sizeof(struct data));
  1651. X    if (newdpp == NULL) {
  1652. X    perror("calloc");
  1653. X    exit(1);
  1654. X    }
  1655. X    newdpp->addr = *addr;
  1656. X    newdpp->host = strdup(hostname);
  1657. X    if (!newdpp->host) {
  1658. X    perror("strdup");
  1659. X    exit(1);
  1660. X    }
  1661. X    newdpp->host_dup = strdup(hostname);
  1662. X    if (!newdpp->host_dup) {
  1663. X    perror("strdup");
  1664. X    exit(1);
  1665. X    }
  1666. X    newdpp->ok_to_call = 1;
  1667. X    /**
  1668. X     * assume cp_time is cumulative since boot time
  1669. X     * until we find out otherwise
  1670. X    **/
  1671. X    newdpp->cp_kind = CP_TIME_CUM;
  1672. X    nhosts++;
  1673. X    if (mode == MODE_BCST) {
  1674. X    (void) putc('+', stderr);
  1675. X    (void) fflush(stderr);
  1676. X    }
  1677. X    return newdpp;
  1678. X}
  1679. X
  1680. Xvoid
  1681. Xdump_hostent(entry)
  1682. X    struct hostent *entry;
  1683. X{
  1684. X    char          **app;
  1685. X    struct in_addr  in_addr;
  1686. X
  1687. X    (void) fprintf(stderr, "Official name:\t%s\n", entry->h_name);
  1688. X    for (app = entry->h_aliases; *app; app++)
  1689. X    (void) fprintf(stderr, "Alias:\t\t%s\n", *app);
  1690. X
  1691. X    for (app = entry->h_addr_list; *app; app++) {
  1692. X    bcopy(*app, (char *) &in_addr.s_addr, entry->h_length);
  1693. X    (void) fprintf(stderr, "Host address:\t%s\n", inet_ntoa(in_addr));
  1694. X    }
  1695. X}
  1696. X
  1697. Xvoid
  1698. Xinsert_dp(newdp)
  1699. X    struct data    *newdp;
  1700. X{
  1701. X    struct data   **dpp;
  1702. X    struct data    *tdp;
  1703. X
  1704. X    tdp = NULL;
  1705. X    for (dpp = &dp; *dpp; dpp = &(*dpp)->datap) {
  1706. X    if (newdp->addr.s_addr == (*dpp)->addr.s_addr) {
  1707. X        /* already on the list */
  1708. X        (void) fprintf(stderr,
  1709. X               "This can't happen! %s already on list\n",
  1710. X               inet_ntoa(newdp->addr));
  1711. X        exit(1);
  1712. X    }
  1713. X    if (opts & O_SHOST ? strcmp(newdp->host, (*dpp)->host) < 0
  1714. X        : ntohl(newdp->addr.s_addr) < ntohl((*dpp)->addr.s_addr)) {
  1715. X        /* insert into list */
  1716. X        tdp = *dpp;
  1717. X        break;        /* break => insert into list */
  1718. X    }
  1719. X    }                /* fall-through => append to list */
  1720. X    *dpp = newdp;
  1721. X    (*dpp)->datap = tdp;
  1722. X}
  1723. X
  1724. Xvoid
  1725. Xenter_item(itemkey, addr, datap)
  1726. X    char           *itemkey;
  1727. X    struct in_addr  addr;
  1728. X    struct data    *datap;
  1729. X{
  1730. X    hash_info      *hip;
  1731. X    ENTRY           item;
  1732. X
  1733. X    /*
  1734. X     * caution: do not use inet_ntoa() in this routine
  1735. X     */
  1736. X
  1737. X    hip = (hash_info *) malloc(sizeof(hash_info));
  1738. X    item.key = strdup(itemkey);
  1739. X    if (!item.key) {
  1740. X    perror("strdup");
  1741. X    exit(1);
  1742. X    }
  1743. X    hip->ident_addr = addr;
  1744. X    hip->datap = datap;
  1745. X    item.data = (char *) hip;
  1746. X    /* put name into table */
  1747. X    if (!hsearch(item, ENTER)) {
  1748. X    (void) fprintf(stderr, "Hash table full.\n");
  1749. X    exit(1);
  1750. X    }
  1751. X    if (dbg_lvl >= 2)
  1752. X    (void) fprintf(stderr, "ENTER %s. hip: ident_addr.s_addr=0x%08x datap=0x%08x\n",
  1753. X           itemkey, ntohl(hip->ident_addr.s_addr), (u_long) hip->datap);
  1754. X}
  1755. X
  1756. X/**
  1757. X * handle each reply to the broadcast
  1758. X * return FALSE to permit more broadcasting
  1759. X * return TRUE to terminate broadcasting (after alarm has timed out)
  1760. X *
  1761. X * my profuse thanks Joe Beauchamp (JRB@CSI.compuserve.com)
  1762. X * for patiently assisting me with debugging this routine.
  1763. X *
  1764. X**/
  1765. X/**
  1766. X * You are about to enter ...
  1767. X**/
  1768. Xbool_t
  1769. Xeach_result(resp, raddr, version)
  1770. X    stats_all      *resp;
  1771. X    struct sockaddr_in *raddr;
  1772. X    u_long          version;
  1773. X{
  1774. X    char           *hostname;
  1775. X    char           *dotquad1;
  1776. X    struct data    *resdp;
  1777. X    stats_default  *sn;
  1778. X    ENTRY          *found_item1;
  1779. X    hash_info      *fip;
  1780. X    struct hostent *host_entry;
  1781. X    char          **app;
  1782. X    struct in_addr  in_tmp;
  1783. X    ENTRY           item;
  1784. X
  1785. X    /**
  1786. X                   *         *        *      *    *
  1787. X     *        *       *        *       *       *
  1788. X                       ... the coredump zone    *
  1789. X     *         *    *        *          *
  1790. X                *        *        *        *
  1791. X    **/
  1792. X
  1793. X    /**
  1794. X     * use strdup for dotquad1 because inet_ntoa uses static storage,
  1795. X     * which is overwritten each call
  1796. X     *
  1797. X    **/
  1798. X    dotquad1 = strdup(inet_ntoa(raddr->sin_addr));
  1799. X    if (!dotquad1) {
  1800. X    perror("strdup");
  1801. X    exit(1);
  1802. X    }
  1803. X    item.key = dotquad1;
  1804. X    found_item1 = hsearch(item, FIND);
  1805. X    if (found_item1) {        /* found_item1 */
  1806. X    /* already on the list */
  1807. X    fip = (hash_info *) found_item1->data;
  1808. X    in_tmp = fip->ident_addr;
  1809. X    if (in_tmp.s_addr) {
  1810. X        char           *dotquad2;
  1811. X        ENTRY          *found_item2;
  1812. X        /* machine has more than one network interface */
  1813. X        dotquad2 = inet_ntoa(in_tmp);
  1814. X        item.key = dotquad2;
  1815. X        found_item2 = hsearch(item, FIND);
  1816. X        if (!found_item2) {
  1817. X        (void) fprintf(stderr,
  1818. X                   "This can't happen! %s not in hash table\n",
  1819. X                   dotquad2);
  1820. X        exit(1);
  1821. X        }
  1822. X        fip = (hash_info *) found_item2->data;
  1823. X    }            /* in_tmp.s_addr */
  1824. X    resdp = fip->datap;
  1825. X    (void) putc('.', stderr);
  1826. X    (void) fflush(stderr);
  1827. X    } else {            /* ! found_item1 */
  1828. X    if (opts & O_NHOST) {
  1829. X        resdp = new_host(&raddr->sin_addr, dotquad1);
  1830. X        insert_dp(resdp);
  1831. X        in_tmp.s_addr = 0;
  1832. X        enter_item(dotquad1, in_tmp, resdp);
  1833. X    } else {        /* !opts & O_NHOST */
  1834. X        ENTRY          *found_item3;
  1835. X        host_entry = gethostbyaddr((char *) &raddr->sin_addr, 4, AF_INET);
  1836. X        if (host_entry) {
  1837. X        if (dbg_lvl >= 2)
  1838. X            dump_hostent(host_entry);
  1839. X
  1840. X        hostname = host_entry->h_name;
  1841. X        if (!hostname) {
  1842. X            (void) fprintf(stderr,
  1843. X                   "gethostbyaddr: null hostname %s\n",
  1844. X                   dotquad1);
  1845. X            exit(1);
  1846. X        }
  1847. X        item.key = hostname;
  1848. X        } else {        /* !host_entry */
  1849. X        hostname = (char *) NULL;
  1850. X        if (dbg_lvl >= 1)
  1851. X            (void) fprintf(stderr,
  1852. X                   "gethostbyaddr failed %s\n", dotquad1);
  1853. X        item.key = dotquad1;
  1854. X        }            /* !host_entry */
  1855. X        found_item3 = hsearch(item, FIND);
  1856. X        if (found_item3) {
  1857. X        char           *dotquad2;
  1858. X        ENTRY          *found_item4;
  1859. X        fip = (hash_info *) found_item3->data;
  1860. X        in_tmp = fip->ident_addr;
  1861. X        enter_item(dotquad1, in_tmp, (struct data *) NULL);
  1862. X
  1863. X        if (dbg_lvl >= 1)
  1864. X            (void) fprintf(stderr,
  1865. X               "duplicate reply from %s received on interface %s\n",
  1866. X                   hostname ? hostname : "(unknown)", dotquad1);
  1867. X        dotquad2 = inet_ntoa(in_tmp);
  1868. X        item.key = dotquad2;
  1869. X        found_item4 = hsearch(item, FIND);
  1870. X        if (!found_item4) {
  1871. X            (void) fprintf(stderr,
  1872. X                "This can't happen! %s not in hash table\n",
  1873. X                   dotquad2);
  1874. X            exit(1);
  1875. X        }
  1876. X        fip = (hash_info *) found_item4->data;
  1877. X        resdp = fip->datap;
  1878. X        (void) putc('.', stderr);
  1879. X        (void) fflush(stderr);
  1880. X        } else {        /* ! found_item2 */
  1881. X        resdp = (struct data *) NULL;
  1882. X        if (host_entry) {
  1883. X            enter_item(hostname, raddr->sin_addr, (struct data *) NULL);
  1884. X            for (app = host_entry->h_addr_list; *app; app++) {
  1885. X            bcopy(*app, (char *) &in_tmp, host_entry->h_length);
  1886. X            if (in_tmp.s_addr == raddr->sin_addr.s_addr) {
  1887. X                /* this is the normal branch */
  1888. X                resdp = new_host(&raddr->sin_addr, hostname);
  1889. X                insert_dp(resdp);
  1890. X                in_tmp.s_addr = 0;
  1891. X                enter_item(dotquad1, in_tmp, resdp);
  1892. X            } else {/* other addresses */
  1893. X                /* save other addresses found in host table */
  1894. X                char           *dotquad2;
  1895. X                dotquad2 = inet_ntoa(in_tmp);
  1896. X                if (dbg_lvl >= 1)
  1897. X                (void) fprintf(stderr,
  1898. X                      "Saving address %s for host %s\n",
  1899. X                           dotquad2, hostname);
  1900. X                enter_item(dotquad2, raddr->sin_addr,
  1901. X                       (struct data *) NULL);
  1902. X            }    /* other addresses */
  1903. X            }        /* for app */
  1904. X        } else {    /* !host_entry */
  1905. X            resdp = new_host(&raddr->sin_addr, dotquad1);
  1906. X            insert_dp(resdp);
  1907. X            in_tmp.s_addr = 0;
  1908. X            enter_item(dotquad1, in_tmp, resdp);
  1909. X        }        /* !host_entry */
  1910. X        }            /* ! found_item2 */
  1911. X    }            /* !opts & O_NHOST */
  1912. X    }                /* ! found_item1 */
  1913. X
  1914. X    sn = STATS_CONVERT(version) (resp);
  1915. X    /**
  1916. X     * 11/3/93 I have checked that no memory leak occurs if I do not use
  1917. X     * xdr_free here. (Leave this comment here, so I don't forget about it.)
  1918. X    **/
  1919. X    if (!resdp) {
  1920. X    (void) fprintf(stderr,
  1921. X               "This shouldn't happen %s resdp = NULL\n", dotquad1);
  1922. X    exit(1);
  1923. X    }
  1924. X    if (save_res(resdp, sn))
  1925. X    resdp->bcst_vers = version;
  1926. X
  1927. X    if (!resdp->no && !if_opackets_fixed && dbg_lvl >= 1) {
  1928. X    (void) fprintf(stderr,
  1929. X             "%s: rpc.rstatd vers %d does not report if_opackets\n",
  1930. X               resdp->host, resdp->bcst_vers);
  1931. X    }
  1932. X    if_opackets_fixed = 1;
  1933. X    free(dotquad1);
  1934. X
  1935. X    return bcst_timo;
  1936. X}
  1937. X
  1938. Xbool_t
  1939. Xeach_result_orig(resp, raddr)
  1940. X    stats_all      *resp;
  1941. X    struct sockaddr_in *raddr;
  1942. X{
  1943. X    return each_result(resp, raddr, RSTATVERS_ORIG);
  1944. X}
  1945. X
  1946. Xbool_t
  1947. Xeach_result_swtch(resp, raddr)
  1948. X    stats_all      *resp;
  1949. X    struct sockaddr_in *raddr;
  1950. X{
  1951. X    return each_result(resp, raddr, RSTATVERS_SWTCH);
  1952. X}
  1953. X
  1954. Xbool_t
  1955. Xeach_result_time(resp, raddr)
  1956. X    stats_all      *resp;
  1957. X    struct sockaddr_in *raddr;
  1958. X{
  1959. X    return each_result(resp, raddr, RSTATVERS_TIME);
  1960. X}
  1961. X
  1962. Xbool_t
  1963. Xeach_result_var(resp, raddr)
  1964. X    stats_all      *resp;
  1965. X    struct sockaddr_in *raddr;
  1966. X{
  1967. X    return each_result(resp, raddr, RSTATVERS_VAR);
  1968. X}
  1969. X
  1970. Xbool_t(*each_result_vers[]) () =
  1971. X{
  1972. X    each_result_orig,
  1973. X    each_result_swtch,
  1974. X    each_result_time,
  1975. X    each_result_var,
  1976. X};
  1977. X
  1978. X/**
  1979. X * force end of broadcasting
  1980. X**/
  1981. XRETSIGTYPE
  1982. Xbcst_done()
  1983. X{
  1984. X    bcst_timo = TRUE;
  1985. X}
  1986. X
  1987. X/**
  1988. X * calculate how long the alarm should be to get
  1989. X * the desired interval
  1990. X * example:  desire 30 sec.  use alarm(14)
  1991. X**/
  1992. Xunsigned
  1993. Xget_bcst_alarm(interval)
  1994. X    unsigned        interval;
  1995. X{
  1996. X    int             j, h = 0;
  1997. X
  1998. X    if (interval <= 4)
  1999. X    return 1;
  2000. X    for (j = 4; j <= 64; j *= 2) {
  2001. X    h += j;
  2002. X    if (interval <= h)
  2003. X        break;
  2004. X    }
  2005. X    j /= 2;
  2006. X    return Min(h - j, interval) - j;
  2007. X    /* max is 60 */
  2008. X}
  2009. X
  2010. Xvoid
  2011. Xdo_broadcast(vers_max, interval)
  2012. X    u_long          vers_max;
  2013. X    unsigned        interval;    /* desired broadcast interval.  92 max */
  2014. X{
  2015. X    u_long          vers;
  2016. X    static u_long   vers_max_ok;
  2017. X    static enum clnt_stat clnt_stat;
  2018. X    stats_all       resbuf;
  2019. X
  2020. X    if (!vers_max_ok)
  2021. X    vers_max_ok = vers_max;
  2022. X
  2023. X    (void) fputs("broadcasting ", stderr);
  2024. X    for (vers = vers_max_ok; vers >= Min(vers_max_ok, RSTATVERS_TIME); vers--) {
  2025. X
  2026. X    if (dbg_lvl >= 1)
  2027. X        (void) fprintf(stderr, " vers %d: ", vers);
  2028. X
  2029. X    (void) signal(SIGALRM, bcst_done);
  2030. X    (void) alarm(get_bcst_alarm(interval));
  2031. X
  2032. X    bcst_timo = FALSE;
  2033. X    (void) fflush(stderr);
  2034. X    bzero((char *) &resbuf, sizeof resbuf);
  2035. X    clnt_stat = clnt_broadcast(RSTATPROG,
  2036. X                   vers,
  2037. X                   RSTATPROC_STATS,
  2038. X                   xdr_void,
  2039. X                   (char *) NULL,
  2040. X                   XDR_STATSPROC(vers),
  2041. X                   (char *) &resbuf,
  2042. X                   EACH_RESULT(vers));
  2043. X    /**
  2044. X     * resultproc_t each_result in Solaris-2 (thanks
  2045. X     * cmc@apus.srg-ssr.ch (Colin M. Clark))
  2046. X    **/
  2047. X
  2048. X    if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) {
  2049. X        (void) fprintf(stderr, "\nclnt_broadcast: %s\n",
  2050. X               clnt_sperrno(clnt_stat));
  2051. X        exit(1);
  2052. X    }
  2053. X    if (!nhosts) {
  2054. X        (void) fprintf(stderr,
  2055. X        "\nNo hosts found with rstatd version %d on this network\n",
  2056. X               vers);
  2057. X        vers_max_ok = vers - 1;
  2058. X        if (!vers_max_ok)
  2059. X        exit(1);
  2060. X    }
  2061. X    }
  2062. X    (void) putc('\n', stderr);
  2063. X}
  2064. END_OF_FILE
  2065. if test 21859 -ne `wc -c <'rpc.c'`; then
  2066.     echo shar: \"'rpc.c'\" unpacked with wrong size!
  2067. fi
  2068. # end of 'rpc.c'
  2069. fi
  2070. if test -f 'common.h' -a "${1}" != "-c" ; then 
  2071.   echo shar: Will not clobber existing file \"'common.h'\"
  2072. else
  2073. echo shar: Extracting \"'common.h'\" \(1816 characters\)
  2074. sed "s/^X//" >'common.h' <<'END_OF_FILE'
  2075. X/**
  2076. X * This program may be copied, redistributed in any form,
  2077. X * source or binary, and used for any purpose, provided
  2078. X * this copyright notice is retained.
  2079. X *  @(#)common.h    3.1 12/15/93 (c) Copyright Brian P. Fitzgerald
  2080. X *  Rensselaer Polytechnic Institute
  2081. X **/
  2082. X#ifdef STDC_HEADERS
  2083. X#include <stddef.h>
  2084. X#endif                /* STDC_HEADERS */
  2085. X
  2086. X#ifdef HAVE_STDLIB_H
  2087. X#include <stdlib.h>
  2088. X#else                /* !HAVE_STDLIB_H */
  2089. Xextern void     exit();
  2090. X#endif                /* !HAVE_STDLIB_H */
  2091. X
  2092. X#include <string.h>
  2093. X
  2094. X#ifdef HAVE_UNISTD_H
  2095. X#include <unistd.h>
  2096. X#endif                /* HAVE_UNISTD_H */
  2097. X
  2098. X/* <unistd.h> */
  2099. X#ifndef STDOUT_FILENO
  2100. X#define STDOUT_FILENO   1
  2101. X#endif                /* STDOUT_FILENO */
  2102. X
  2103. X#include <errno.h>
  2104. X
  2105. X#ifndef Abs
  2106. X#define Abs(a) ((a)>= 0 ? (a) : -(a))
  2107. X#endif                /* Abs */
  2108. X
  2109. X#ifndef Min
  2110. X#define Min(a, b) ((a) < (b) ? (a) : (b))
  2111. X#endif                /* Min */
  2112. X
  2113. X#ifndef Max
  2114. X#define Max(a, b) ((a) > (b) ? (a) : (b))
  2115. X#endif                /* Max */
  2116. X
  2117. X#ifdef NO_BSTRING
  2118. X#define bcopy(b1,b2,len)    memmove(b2, b1, len)
  2119. X#define bzero(b,len)        memset(b, 0, len)
  2120. X#define bcmp(b1,b2,len)        memcmp(b1, b2, len)
  2121. X#endif                /* NO_BSTRING */
  2122. X
  2123. X#define O_CP    0x01
  2124. X#define O_DK    0x02
  2125. X#define O_VM    0x04
  2126. X#define O_IF    0x08
  2127. X#define O_TIME    0x10
  2128. X#define O_DATE    0x20
  2129. X#define O_SECS    0x40
  2130. X#define O_MOST    ( O_CP | O_DK | O_VM | O_IF )
  2131. X#define O_DEFL    ( O_CP | O_VM | O_IF )
  2132. X#define O_DEFL1    ( O_CP | O_DK | O_VM | O_IF )
  2133. X#define O_UP    0x100
  2134. X#define O_ALL    ( O_MOST | O_TIME | O_DATE | O_SECS | O_UP )
  2135. X#define O_BCST    0x200
  2136. X#define O_BARE    0x400
  2137. X#define O_DBG    0x800
  2138. X#define O_SHOST    0x1000
  2139. X#define O_NHOST 0x8000
  2140. X#define O_SORT 0x10000
  2141. X#define O_RVRS 0x20000
  2142. X#define O_NCLR 0x100000        /* never clear the screen */
  2143. X
  2144. Xextern int      opterr, optind;
  2145. X
  2146. Xextern long     strtol();
  2147. Xextern char    *strdup();
  2148. X
  2149. Xvoid            msg();
  2150. Xint             set_max_nofiles();
  2151. X
  2152. Xextern unsigned long dbg_lvl;
  2153. Xextern unsigned long opts;
  2154. END_OF_FILE
  2155. if test 1816 -ne `wc -c <'common.h'`; then
  2156.     echo shar: \"'common.h'\" unpacked with wrong size!
  2157. fi
  2158. # end of 'common.h'
  2159. fi
  2160. if test -f 'strdup.c' -a "${1}" != "-c" ; then 
  2161.   echo shar: Will not clobber existing file \"'strdup.c'\"
  2162. else
  2163. echo shar: Extracting \"'strdup.c'\" \(718 characters\)
  2164. sed "s/^X//" >'strdup.c' <<'END_OF_FILE'
  2165. X#ifndef lint
  2166. Xstatic char    *RCSid = "$Header: /src/common/usc/lib/libgen/RCS/strdup.c,v 1.2 1992/04/16 01:28:02 mcooper Exp $";
  2167. X#endif
  2168. X
  2169. X/*
  2170. X * $Log: strdup.c,v $ Revision 1.2  1992/04/16  01:28:02  mcooper Some
  2171. X * de-linting.
  2172. X * 
  2173. X * Revision 1.2  1992/04/16  01:28:02  mcooper Some de-linting.
  2174. X * 
  2175. X * Revision 1.1  1992/03/21  02:48:11  mcooper Initial revision
  2176. X * 
  2177. X */
  2178. X
  2179. X#include <stdio.h>
  2180. X
  2181. X#ifdef HAVE_STDLIB_H
  2182. X#include <stdlib.h>
  2183. X#endif                /* HAVE_STDLIB_H */
  2184. X
  2185. X/*
  2186. X * Most systems don't have this (yet)
  2187. X */
  2188. Xchar           *
  2189. Xstrdup(str)
  2190. X    char           *str;
  2191. X{
  2192. X    char           *p;
  2193. X
  2194. X    if ((p = malloc((unsigned) strlen(str) + 1)) == NULL)
  2195. X    return ((char *) NULL);
  2196. X
  2197. X    (void) strcpy(p, str);
  2198. X
  2199. X    return (p);
  2200. X}
  2201. END_OF_FILE
  2202. if test 718 -ne `wc -c <'strdup.c'`; then
  2203.     echo shar: \"'strdup.c'\" unpacked with wrong size!
  2204. fi
  2205. # end of 'strdup.c'
  2206. fi
  2207. if test -f 'hsearch.h' -a "${1}" != "-c" ; then 
  2208.   echo shar: Will not clobber existing file \"'hsearch.h'\"
  2209. else
  2210. echo shar: Extracting \"'hsearch.h'\" \(456 characters\)
  2211. sed "s/^X//" >'hsearch.h' <<'END_OF_FILE'
  2212. X#include <stdio.h>
  2213. X
  2214. X#ifdef HAVE_STDLIB_H
  2215. X#include <stdlib.h>
  2216. X#endif                /* HAVE_STDLIB_H */
  2217. X
  2218. X#include <string.h>
  2219. X
  2220. Xtypedef struct entry {
  2221. X    char           *key;
  2222. X    char           *data;
  2223. X}               ENTRY;
  2224. X
  2225. Xtypedef enum {
  2226. X    FIND,
  2227. X    ENTER
  2228. X}               ACTION;
  2229. X
  2230. Xtypedef struct element {
  2231. X    ENTRY           item;
  2232. X    struct element *next;
  2233. X}               ELEMENT;
  2234. X
  2235. Xextern ENTRY   *hsearch();
  2236. Xextern void     hdestroy();
  2237. Xextern int      hcreate();
  2238. END_OF_FILE
  2239. if test 456 -ne `wc -c <'hsearch.h'`; then
  2240.     echo shar: \"'hsearch.h'\" unpacked with wrong size!
  2241. fi
  2242. # end of 'hsearch.h'
  2243. fi
  2244. echo shar: End of archive 2 \(of 4\).
  2245. cp /dev/null ark2isdone
  2246. MISSING=""
  2247. for I in 1 2 3 4 ; do
  2248.     if test ! -f ark${I}isdone ; then
  2249.     MISSING="${MISSING} ${I}"
  2250.     fi
  2251. done
  2252. if test "${MISSING}" = "" ; then
  2253.     echo You have unpacked all 4 archives.
  2254.     echo "Now do 'sh ./configure' or 'sh ./configure -prefix=PATH' (Default = /usr/local)"
  2255.     rm -f ark[1-9]isdone
  2256. else
  2257.     echo You still need to unpack the following archives:
  2258.     echo "        " ${MISSING}
  2259. fi
  2260. ##  End of shell archive.
  2261. exit 0
  2262.  
  2263. exit 0 # Just in case...
  2264.