home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / sources / misc / 4241 < prev    next >
Encoding:
Text File  |  1993-01-10  |  50.0 KB  |  1,424 lines

  1. Newsgroups: comp.sources.misc
  2. Path: sparky!kent
  3. From: amber@engin.umich.edu (Lee Liming)
  4. Subject: v34i099:  netuse - A Network Host Usage Monitoring System, Part01/06
  5. Message-ID: <csm-v34i099=netuse.203327@sparky.IMD.Sterling.COM>
  6. Followup-To: comp.sources.d
  7. X-Md4-Signature: 5dbd52aa67bb6f5ea290b37c94adff6d
  8. Sender: kent@sparky.imd.sterling.com (Kent Landfield)
  9. Organization: Sterling Software
  10. Date: Mon, 11 Jan 1993 02:34:33 GMT
  11. Approved: kent@sparky.imd.sterling.com
  12. Lines: 1410
  13.  
  14. Submitted-by: amber@engin.umich.edu (Lee Liming)
  15. Posting-number: Volume 34, Issue 99
  16. Archive-name: netuse/part01
  17. Environment: UNIX, MS-DOS, OS/2, INET, MSC
  18.  
  19.                NETUSE - A Network Host Usage Monitoring System
  20.  
  21.                         Lee Liming and Michael L. Neil
  22.                       Computer Aided Engineering Network
  23.                           The University of Michigan
  24.  
  25. NETUSE is a low-budget, high-output network service used for keeping track of
  26. dynamic information about hosts on a TCP/IP network.  It is not limited to
  27. physical networks; i.e., it's monitoring crosses routers.  It monitors and
  28. updates load averages, number of login sessions, display use, free disk space 
  29. in /tmp, host names, and vendor and model types for a (potentially large) 
  30. number of hosts.  All of these items are determined dynamically by the system.
  31. One never needs to tell NETUSE anything (other than to run).
  32.  
  33. Rather than being based on broadcasts, which are limited to physical networks
  34. and which require processing time from all hosts on the network, NETUSE takes
  35. a client-server approach.  Periodic reports are sent directly to a server via
  36. UDP, and the server may subsequently be queried for near-instantaneous 
  37. information.
  38.  
  39. This service was originally developed for assistance with large-scale,
  40. course-grained distributed processing (running jobs on lots and lots of
  41. hosts!).  It's strong points are low bandwidth requirements, speed of queries,
  42. self-maintenance, and versatility.
  43.  
  44. NETUSE has been in wide use at CAEN for several years now, and we've been
  45. adding features and making it more robust through most of that time.  We now
  46. feel that it's "good enough" (in terms of robustness and usefulness) to be 
  47. distributed more broadly.
  48.  
  49. The REAL documentation is in the ./doc directory, in several formats
  50. (including plain old ASCII).
  51.  
  52. NOTICE: This distribution is also available via anonymous FTP from
  53.         freebie.engin.umich.edu (141.212.103.21) in /pub/netuse.
  54.  
  55. -------------------------------------------------------------------------------
  56. #! /bin/sh
  57. # This is a shell archive.  Remove anything before this line, then feed it
  58. # into a shell via "sh file" or similar.  To overwrite existing files,
  59. # type "sh file -c".
  60. # Contents:  netuse netuse/README netuse/clients netuse/daemons
  61. #   netuse/doc netuse/doc/NETUSE.txt netuse/lib netuse/lib/variable.c
  62. # Wrapped by kent@sparky on Sun Jan 10 20:28:33 1993
  63. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  64. echo If this archive is complete, you will see the following message:
  65. echo '          "shar: End of archive 1 (of 6)."'
  66. if test ! -d 'netuse' ; then
  67.     echo shar: Creating directory \"'netuse'\"
  68.     mkdir 'netuse'
  69. fi
  70. if test -f 'netuse/README' -a "${1}" != "-c" ; then 
  71.   echo shar: Will not clobber existing file \"'netuse/README'\"
  72. else
  73.   echo shar: Extracting \"'netuse/README'\" \(2980 characters\)
  74.   sed "s/^X//" >'netuse/README' <<'END_OF_FILE'
  75. X
  76. X                NETUSE - A Network Host Usage Monitoring System
  77. X
  78. X                        Lee Liming and Michael L. Neil
  79. X                      Computer Aided Engineering Network
  80. X                          The University of Michigan
  81. X
  82. X
  83. XNETUSE is a low-budget, high-output network service used for keeping track of
  84. Xdynamic information about hosts on a TCP/IP network.  It is not limited to
  85. Xphysical networks; i.e., it's monitoring crosses routers.  It monitors and
  86. Xupdates load averages, number of login sessions, display use, free disk space 
  87. Xin /tmp, host names, and vendor and model types for a (potentially large) 
  88. Xnumber of hosts.  All of these items are determined dynamically by the system.
  89. XOne never needs to tell NETUSE anything (other than to run).
  90. X
  91. XRather than being based on broadcasts, which are limited to physical networks
  92. Xand which require processing time from all hosts on the network, NETUSE takes
  93. Xa client-server approach.  Periodic reports are sent directly to a server via
  94. XUDP, and the server may subsequently be queried for near-instantaneous 
  95. Xinformation.
  96. X
  97. XThis service was originally developed for assistance with large-scale,
  98. Xcourse-grained distributed processing (running jobs on lots and lots of
  99. Xhosts!).  It's strong points are low bandwidth requirements, speed of queries,
  100. Xself-maintenance, and versatility.
  101. X
  102. XNETUSE has been in wide use at CAEN for several years now, and we've been
  103. Xadding features and making it more robust through most of that time.  We now
  104. Xfeel that it's "good enough" (in terms of robustness and usefulness) to be 
  105. Xdistributed more broadly.
  106. X
  107. XThe REAL documentation is in the ./doc directory, in several formats
  108. X(including plain old ASCII).
  109. X
  110. X
  111. X/******************************************************************************
  112. XCopyright (C) 1992 by the Regents of the University of Michigan.
  113. X
  114. XUser agrees to reproduce said copyright notice on all copies of the software
  115. Xmade by the recipient.  
  116. X
  117. XAll Rights Reserved. Permission is hereby granted for the recipient to make
  118. Xcopies and use this software for its own internal purposes only. Recipient of
  119. Xthis software may re-distribute this software outside of their own
  120. Xinstitution. Permission to market this software commercially, to include this
  121. Xproduct as part of a commercial product, or to make a derivative work for
  122. Xcommericial purposes, is explicitly prohibited.  All other uses are also
  123. Xprohibited unless authorized in writing by the Regents of the University of
  124. XMichigan.
  125. X
  126. XThis software is offered without warranty. The Regents of the University of
  127. XMichigan disclaim all warranties, express or implied, including but not
  128. Xlimited to the implied warranties of merchantability and fitness for any
  129. Xparticular purpose. In no event shall the Regents of the University of
  130. XMichigan be liable for loss or damage of any kind, including but not limited
  131. Xto incidental, indirect, consequential, or special damages. 
  132. X******************************************************************************/
  133. END_OF_FILE
  134.   if test 2980 -ne `wc -c <'netuse/README'`; then
  135.     echo shar: \"'netuse/README'\" unpacked with wrong size!
  136.   fi
  137.   # end of 'netuse/README'
  138. fi
  139. if test ! -d 'netuse/clients' ; then
  140.     echo shar: Creating directory \"'netuse/clients'\"
  141.     mkdir 'netuse/clients'
  142. fi
  143. if test ! -d 'netuse/daemons' ; then
  144.     echo shar: Creating directory \"'netuse/daemons'\"
  145.     mkdir 'netuse/daemons'
  146. fi
  147. if test ! -d 'netuse/doc' ; then
  148.     echo shar: Creating directory \"'netuse/doc'\"
  149.     mkdir 'netuse/doc'
  150. fi
  151. if test -f 'netuse/doc/NETUSE.txt' -a "${1}" != "-c" ; then 
  152.   echo shar: Will not clobber existing file \"'netuse/doc/NETUSE.txt'\"
  153. else
  154.   echo shar: Extracting \"'netuse/doc/NETUSE.txt'\" \(16063 characters\)
  155.   sed "s/^X//" >'netuse/doc/NETUSE.txt' <<'END_OF_FILE'
  156. XMONITORING HOSTS WITH NETUSE               Computer Aided Engineering Network
  157. XAugust 1992                                            University of Michigan
  158. X
  159. X
  160. XCopyright (C) 1992 by the Regents of the University of Michigan.
  161. X
  162. XUser agrees to reproduce said copyright notice on all copies of the software
  163. Xmade by the recipient.  
  164. X
  165. XAll Rights Reserved. Permission is hereby granted for the recipient to make
  166. Xcopies and use this software for its own internal purposes only. Recipient of
  167. Xthis software may not re-distribute this software outside of their own
  168. Xinstitution. Permission to market this software commercially, to include this
  169. Xproduct as part of a commercial product, or to make a derivative work for
  170. Xcommercial purposes, is explicitly prohibited.  All other uses are also
  171. Xprohibited unless authorized in writing by the Regents of the University of
  172. XMichigan.
  173. X
  174. XThis software is offered without warranty. The Regents of the University of
  175. XMichigan disclaim all warranties, express or implied, including but not
  176. Xlimited to the implied warranties of merchantability and fitness for any
  177. Xparticular purpose. In no event shall the Regents of the University of
  178. XMichigan be liable for loss or damage of any kind, including but not limited
  179. Xto incidental, indirect, consequential, or special damages. 
  180. X
  181. X
  182. XDESCRIPTION
  183. X
  184. XThe NETUSE system is designed to provide a fast means of obtaining the names
  185. Xof hosts on a network that are available for use. It is particularly useful
  186. Xfor determining hosts to use for chunks of distributed processing jobs. 
  187. X
  188. XThe NETUSE system consists of a server process which keeps the following
  189. Xitems of dynamic information about a (potentially large) set of Unix hosts on
  190. Xa TCP/IP network. 
  191. X
  192. X     o  Host name
  193. X     o  Vendor type
  194. X     o  Model type
  195. X     o  1, 5, and 15-minute load averages
  196. X     o  Number of current login sessions
  197. X     o  Display in use or not
  198. X     o  Free space on /tmp
  199. X
  200. XClient applications can very quickly query the server for the names of hosts
  201. Xthat meet specific criteria (e.g., a Sun 4/50 with less than 0.05 as a
  202. X5-minute load average, no one logged into the display, less than three remote
  203. Xlogins, and at least 25Mb of /tmp space free). Hosts may be obtained
  204. Xindividually or in groups. 
  205. X
  206. XAdditionally, hosts that have not reported to the server in a specified
  207. Xamount of time can be listed (a useful feature for system administrators
  208. Xlooking for crashed machines). 
  209. X
  210. XWhen hosts are requested individually, the server will not give out the name
  211. Xof any host more than once in two minutes, thus causing sequential requests
  212. Xto return unique hosts. Presumably, by the time a host is checked a second
  213. Xtime for availability its status will have been changed enough by the
  214. Xprevious request's resulting job that it will be undesirable for further
  215. Xrequests.
  216. X
  217. XThree client programs are provided with the distribution: getmach (returns a
  218. Xsingle host that meets specified criteria), hostinfo (returns a list of hosts
  219. Xof specified types), and netuseadmin (controls the server's operation
  220. Xremotely). A programmer's interface consisting of a library and header files
  221. Xfor use in other applications is also provided.  
  222. X
  223. XDynamic updates
  224. X
  225. XThe NETUSE system was designed to be self-maintaining. Human intervention in
  226. Xits operation is seldom needed. For the most part, hosts get added and
  227. Xdeleted automatically, and information is constantly updated through
  228. Xautomatic mechanisms.  
  229. X
  230. XFor example, if a host name is changed, this will be reflected in the NETUSE
  231. Xsystem as soon as the nameserver or /etc/hosts file is updated. Hosts which
  232. Xdon't report for a set period of time (configurable at compile time) are
  233. Xautomatically removed from the database. Hosts that don't report for a
  234. Xshorter period of time (also configurable) can be "woken up" by a message
  235. Xfrom the NETUSE server (assuming that the problem was a netused daemon that
  236. Xterminated abnormally). If a machine is upgraded or replaced by a new model,
  237. Xthe server's database is updated when the machine sends its next report.
  238. X
  239. X
  240. XBACKGROUND
  241. X
  242. XIn early 1990, several student staff members at the University of Michigan's
  243. XComputer Aided Engineering network realized that there were considerable
  244. Xquantities of unused CPU cycles and disk space available among the hundreds
  245. Xof Unix workstations in public CAEN labs. Unfortunately, there was no
  246. Xefficient way to detect precisely which machines were currently unused at any
  247. Xgiven instant. Existing systems such as rwho and ruptime were not useful at
  248. XCAEN because of their broadcast nature, which both required more network and
  249. XCPU resources from the monitored hosts than was considered reasonable and
  250. Xalso limited the monitoring to individual physical networks. 
  251. X
  252. XThis was the inspiration for the NETUSE system. The basic requirements were
  253. Xthat the system be based on a non-broadcasting internet protocol, allowing it
  254. Xto work across routers; very low CPU and network bandwidth requirements; and
  255. Xspeed and flexibility of querying, allowing clients to quickly find hosts
  256. Xthat meet specific requirements. Mike Neil and Lee Liming wrote the original
  257. Xversion (with significant kibitzing from Steve Falkenburg), which was used on
  258. Xa test bed of roughly 50 DECstations and SPARCstations. 
  259. X
  260. X
  261. XSPECIFICATIONS
  262. X
  263. XThe NETUSE system current runs a daemon process (netused) on each host being
  264. Xmonitored. This daemon executes continuously (it is started on booting the
  265. Xhost), sleeping most of the time but waking up periodically to reassess the
  266. Xhost's status and report it to the NETUSE server. The NETUSE server runs
  267. Xcontinuously on a single host, receiving reports from monitored hosts and
  268. Xrequests for information from clients. 
  269. X
  270. XEach status report, client request, and server response consists of a 20-byte
  271. XUDP packet. (This packet ends up being about 66 bytes after having UDP, IP
  272. Xand ethernet headers added.) For some client requests, however, the NETUSE
  273. Xserver opens a TCP connection to the client to send it's response. In these
  274. Xcases the amount of data transmitted may vary greatly. 
  275. X
  276. XAt CAEN, a NETUSE system monitoring 225 hosts with each host reporting once
  277. Xevery two minutes generates roughly 3 kbits/s on a sustained basis. Note that
  278. Xthis is the bandwidth required on the server's local network only (the
  279. Xbusiest of all). Other networks will carry only the traffic for their local
  280. Xhosts. For all but the most extraordinary networks, this represents minor
  281. Xbackground noise, and will not impact normal network use at all. Since all
  282. XNETUSE-generated traffic is host-to-host (as opposed to broadcasted),
  283. Xmonitored hosts and client workstations do not need to examine any packets
  284. Xother than those they explicitly send or request from the server.
  285. X
  286. X
  287. XSUPPORTED PLATFORMS
  288. X
  289. XWe expect that the NETUSE client programs will be usable on many types of
  290. Xsystems, but, due to the lack of standardization for obtaining load averages,
  291. Xreading utmp files, and other system-dependent items, there are currently a
  292. Xmuch smaller set of platforms that the netused daemon will compile
  293. Xsuccessfully on. Table 1 shows the systems we've used NETUSE on, and which
  294. Xones we've provided netused versions for. 
  295. X
  296. X      -----------------------------------------------------------------
  297. X      Platform                                         Clients  netused
  298. X      -----------------------------------------------------------------
  299. X      DECstation 3100, 5000 (Ultrix 3.1d, 4.x)            o        o
  300. X      HP/Apollo DN and 400-series (DOMAIN/OS SR10.x)      o        o
  301. X      HP/Apollo 700-series (HP-UX 8.0.x)                  o        o
  302. X      IBM PS/2 (DOS: Novell TCP/IP, OS/2: IBM TCP/IP)     o
  303. X      IBM RS/6000 (AIX 3.x)                               o        o
  304. X      NeXT (NeXTstep 1.0)                                 o
  305. X      Sun 4 (SunOS 4.x)                                   o        o
  306. X      -----------------------------------------------------------------
  307. X                       Table 1: Supported platforms
  308. X
  309. X
  310. XINSTALLATION
  311. X
  312. XThe NETUSE system consists of the following executables:
  313. X
  314. X     o  netuse      - NETUSE server daemon
  315. X     o  netused     - Host monitor daemon
  316. X     o  netuseadmin - NETUSE server administration utility 
  317. X     o  hostinfo    - Multiple-host display utility
  318. X     o  getmach     - Single-host selection utility
  319. X
  320. XA library of linkable C routines (libNetuse.a) and two header files with type
  321. Xdefinitions and function prototypes (protocol.h and netuse.h) are also
  322. Xprovided, as are manual pages for the hostinfo(1) and getmach(1) commands. 
  323. X
  324. XThe directory structure of the source tree is described in Table 1. 
  325. X
  326. X        ------------------------------------------------------------
  327. X        Directory    Contents
  328. X        ------------------------------------------------------------
  329. X        .            Master "Makefile"
  330. X        ./lib        Library code and protocol header files
  331. X        ./daemons    NETUSE daemons (netuse and netused)
  332. X        ./clients    NETUSE clients (getmach, hostinfo, netuseadmin)
  333. X        ------------------------------------------------------------
  334. X                      Table 2: Source tree structure
  335. X
  336. XThe process for building these executables from the sources is very simple.  
  337. X
  338. XSite Customization
  339. X
  340. XBefore compiling, first edit the ./Makefile and ./lib/config.h files. The
  341. Xcomments in each file should be straightforward. It's necessary to edit these
  342. Xfiles, since they define the host name of your server and your installation
  343. Xdirectory, among other less important parameters. 
  344. X
  345. XIf you're not building on a supported platform, you'll need to either modify
  346. Xthe information-gathering modules in ./daemons, or take netused off the list
  347. Xof daemons to be built in the Makefile. 
  348. X
  349. XCompiling and installing
  350. X
  351. XOnce you've configured your Makefile and config.h file, compile the
  352. Xexecutables by typing "make" at the top of the source directory. Once the
  353. Xexecutables and libraries are built, they can be installed using the "make
  354. Xinstall" command. Note that you can skip the "make" step if you're confident
  355. Xthat you really want to install right away. The "make install" command will
  356. Xbuild any executables it needs. 
  357. X
  358. XWhen installing, the DESTDIR variable (in the Makefile) will be taken as the
  359. Xroot of the local software tree. Unless you've made significant changes to
  360. Xthe Makefile, the netuse package will be installed in a subdirectory named
  361. X"netuse", under which bin, etc, lib, include, and man/man1 directories will
  362. Xbe created, and the files will be installed in the appropriate directories.  
  363. X
  364. XAfter the executables and man pages are installed, the source tree may be
  365. Xcleaned using the "make clean" command. This will remove all object files and
  366. Xexecutables from the source tree. 
  367. X
  368. XModifications to system configuration files
  369. X
  370. XOnce you've installed the executables on all relevant systems, you should
  371. Xfirst add the netuse and netused services to your /etc/services files. The
  372. Xservice names "netuse" and "netused" are defined in the config.h file.
  373. XDefault port numbers for these services are also defined there. However, it
  374. Xis strongly recommended that you use /etc/services to register the port
  375. Xnumbers so that NETUSE doesn't conflict with other services on your network.
  376. XExamples of the appropriate lines for a typical /etc/services file are shown
  377. Xbelow. Note that the port numbers can be anything, so long as they don't
  378. Xconflict with any other services on your network and fall within the
  379. Xappropriate range as determined by the internet standards committees. 
  380. X
  381. X     # NETUSE services
  382. X     netuse  1848/udp
  383. X     netused 1849/udp
  384. X
  385. XIf you wish to use the "auto-wakeup" feature of the NETUSE system (where the
  386. Xserver restarts the netused daemon on hosts that haven't reported recently),
  387. Xadd the following line to /etc/inetd.conf on monitored hosts. 
  388. X
  389. X     netused dgram udp wait root /usr/caen/etc/netused netused
  390. X
  391. XSubstitute the appropriate path to your netused executable. Also note that
  392. Xsome Unix versions do not allow the "root" parameter (the user ID that the
  393. Xprogram is run under); look at other entries in your inetd.conf file for
  394. Xexamples. You will most likely need to restart or send a SIGHUP signal to
  395. Xyour inetd process before it will use the new configuration. 
  396. X
  397. XTrying it out
  398. X
  399. XAfter /etc/services and /etc/inetd.conf are updated, start the netuse daemon
  400. Xon the host named in config.h. Then, start the netused daemon on any hosts
  401. Xthat you wish to monitor. At this point, hostinfo and getmach commands will
  402. Xbegin listing the monitored hosts (read the man pages). The netuseadmin
  403. Xprogram can be used to add and delete hosts from the NETUSE database. 
  404. X
  405. XAt CAEN, we start netused out of our workstations' rc files. We also take
  406. Xcare that netused only runs on workstations that any of our users can log in
  407. Xto (so people don't try to start jobs on workstations they don't have
  408. Xprivileges to). 
  409. X
  410. XAdding and removing hosts
  411. X
  412. XAdding a host to the NETUSE system is easy: just start the netused daemon on
  413. Xit. Alternatively, use the netuseadmin program to add the host to the
  414. Xserver's database, and wait for the automatic "wakeup" feature (if enabled at
  415. Xyour site) to start netused on the host. 
  416. X
  417. XDeleting a host is slightly more tricky. First, kill the netused daemon on
  418. Xthe host itself. Then, use the netuseadmin program to delete the host from
  419. Xthe server's database. 
  420. X
  421. X
  422. XPLANS FOR THE FUTURE...
  423. X
  424. XWhile avoiding the temptation to throw in every possible feature and
  425. Xconsequently overuse a good thing, there are some improvements that could and
  426. Xmight be added to the current NETUSE system. 
  427. X
  428. X     o  Support for additional platforms and models. This will, of course,   
  429. X        always be a desirable thing. Assistance from users of the current 
  430. X        system is always welcome in this arena!  
  431. X
  432. X     o  Provide memory usage and total available memory information.
  433. X
  434. X     o  Provide swap space availability information.
  435. X
  436. X
  437. XCOMMUNICATION WITH THE AUTHORS
  438. X
  439. XWe welcome your comments, complaints, and suggestions, and especially
  440. Ximprovements that you've made to the original system. We won't promise to
  441. Xincorporate everything you suggest or send us, but send it anyway! We do
  442. Xpromise that appropriate credit will be given for anything we decide to use. 
  443. X
  444. XSend electronic mail to:
  445. X
  446. X     Lee.Liming@umich.edu (amber@engin.umich.edu)
  447. X     Michael L Neil (mackid@engin.umich.edu)
  448. X
  449. XSend non-e-mail to:
  450. X
  451. X     Attn.: Lee Liming
  452. X     229 Chrysler Center (CAEN)
  453. X     The University of Michigan
  454. X     Ann Arbor, MI 48109 (U.S.A.)
  455. X
  456. X
  457. XDISTRIBUTIONS
  458. X
  459. XThere are two NETUSE distributions currently available.
  460. X
  461. XAn anonymous FTP distribution is available on freebie.engin.umich.edu 
  462. X(141.212.103.21 at the time of this document's writing) in the directory 
  463. X/pub/netuse. This version is in compressed tar format, and includes the 
  464. Xcomplete NETUSE distribution.  
  465. X
  466. XNETUSE has also been posted to several USENET source newsgroups, including 
  467. Xcomp.sources.misc. The first submission was made on January 6, 1993. The 
  468. XUSENET distribution is in a shar format, and does not include the PostScript 
  469. Xor FrameMaker documentation files.
  470. X
  471. X
  472. XCOPYRIGHT
  473. X
  474. XCopyright (C) 1992 by the Regents of the University of Michigan.
  475. X
  476. XUser agrees to reproduce said copyright notice on all copies of the software
  477. Xmade by the recipient.  
  478. X
  479. XAll Rights Reserved. Permission is hereby granted for the recipient to make
  480. Xcopies and use this software for its own internal purposes only. Recipient of
  481. Xthis software may re-distribute this software outside of their own
  482. Xinstitution. Permission to market this software commercially, to include this
  483. Xproduct as part of a commercial product, or to make a derivative work for
  484. Xcommericial purposes, is explicitly prohibited.  All other uses are also
  485. Xprohibited unless authorized in writing by the Regents of the University of
  486. XMichigan.
  487. X
  488. XThis software is offered without warranty. The Regents of the University of
  489. XMichigan disclaim all warranties, express or implied, including but not
  490. Xlimited to the implied warranties of merchantability and fitness for any
  491. Xparticular purpose. In no event shall the Regents of the University of
  492. XMichigan be liable for loss or damage of any kind, including but not limited
  493. Xto incidental, indirect, consequential, or special damages. 
  494. X
  495. END_OF_FILE
  496.   if test 16063 -ne `wc -c <'netuse/doc/NETUSE.txt'`; then
  497.     echo shar: \"'netuse/doc/NETUSE.txt'\" unpacked with wrong size!
  498.   fi
  499.   # end of 'netuse/doc/NETUSE.txt'
  500. fi
  501. if test ! -d 'netuse/lib' ; then
  502.     echo shar: Creating directory \"'netuse/lib'\"
  503.     mkdir 'netuse/lib'
  504. fi
  505. if test -f 'netuse/lib/variable.c' -a "${1}" != "-c" ; then 
  506.   echo shar: Will not clobber existing file \"'netuse/lib/variable.c'\"
  507. else
  508.   echo shar: Extracting \"'netuse/lib/variable.c'\" \(25559 characters\)
  509.   sed "s/^X//" >'netuse/lib/variable.c' <<'END_OF_FILE'
  510. X/*****************************************************************************
  511. X VARIABLE.C - The variable management module
  512. X
  513. X Lee Liming, The Computer Aided Engineering Network
  514. X The University of Michigan
  515. X
  516. X Copyright (C) 1990, 1991, 1992 by the Regents of the University of Michigan.
  517. X
  518. X User agrees to reproduce said copyright notice on all copies of the software
  519. X made by the recipient.  
  520. X
  521. X All Rights Reserved. Permission is hereby granted for the recipient to make
  522. X copies and use this software for its own internal purposes only. Recipient of
  523. X this software may re-distribute this software outside of their own
  524. X institution. Permission to market this software commercially, to include this
  525. X product as part of a commercial product, or to make a derivative work for
  526. X commercial purposes, is explicitly prohibited.  All other uses are also
  527. X prohibited unless authorized in writing by the Regents of the University of
  528. X Michigan.
  529. X
  530. X This software is offered without warranty. The Regents of the University of
  531. X Michigan disclaim all warranties, express or implied, including but not
  532. X limited to the implied warranties of merchantability and fitness for any
  533. X particular purpose. In no event shall the Regents of the University of
  534. X Michigan be liable for loss or damage of any kind, including but not limited
  535. X to incidental, indirect, consequential, or special damages. 
  536. X
  537. X
  538. X This module defines the data structures and operations for constructing
  539. X a table of variable bindings.  This is used for variable storage/retrieval
  540. X in the runtime module.
  541. X
  542. X varHashName() puts the name of a variable through the hashing algorithm
  543. X   to get a bucket number for storing the variable in.
  544. X varAllocate() allocates memory for a variable binding and initializes the
  545. X   fields to known starting values.
  546. X varFreeTable() deallocates the entire hash table of variable bindings.
  547. X varSet() sets a variable to a new value, creating the variable if necessary.
  548. X varAdd() adds a variable to the table.
  549. X varDelete() deletes a variable from the table.
  550. X varFind() gets the value of a variable.
  551. X varSaveState() saves the state of the variable table to a file.
  552. X varLoadHosts() empties the variable table and reinitializes it using
  553. X   variable names stored in a static file.
  554. X*****************************************************************************/
  555. X
  556. X#include <stdio.h>
  557. X#include <string.h>
  558. X#include <pwd.h>
  559. X#include <time.h>
  560. X#include <sys/types.h>
  561. X
  562. X#include "protocol.h"
  563. X#include "netuse.h"
  564. X#include "config.h"
  565. X#include "parser.h"
  566. X#include "variable.h"
  567. X
  568. X
  569. Xextern long lastSave;
  570. X
  571. XVARTABLE  variables;                           /* The global variable table */
  572. XTREE     *theTree;
  573. Xlong      lTime=0;
  574. X
  575. X
  576. X/*****************************************************************************
  577. X int varHashName(char *name)
  578. X
  579. X This function hashes the name sent to it and returns a bucket number.
  580. X*****************************************************************************/
  581. X
  582. X#ifdef __STDC__
  583. Xint varHashName(u_long name)
  584. X#else
  585. Xint varHashName(name)
  586. Xu_long name;
  587. X#endif
  588. X{
  589. X     int i,hash;
  590. X     u_char ipbytes[4];
  591. X
  592. X     bcopy(&name,ipbytes,sizeof(ipbytes));
  593. X     for (i=hash=0; i<4; i++)
  594. X          hash=(hash+ipbytes[i]) % VAR_ENTRIES;
  595. X     return(hash);
  596. X}
  597. X
  598. X
  599. X/*****************************************************************************
  600. X USER *userAllocate()
  601. X
  602. X This function allocates memory for another user node and sets the fields to
  603. X known, useful starting values.
  604. X*****************************************************************************/
  605. X
  606. X#ifdef __STDC__
  607. XUSER *userAllocate(void)
  608. X#else
  609. XUSER *userAllocate()
  610. X#endif
  611. X{
  612. X     USER *userNew;
  613. X
  614. X     userNew=(USER *)malloc(sizeof(USER));
  615. X     userNew->name=userNew->tty=NULL;
  616. X     userNew->next=NULL;
  617. X     return(userNew);
  618. X}
  619. X
  620. X
  621. X/*****************************************************************************
  622. X void userFree(USER *uptr)
  623. X
  624. X This function deallocates the memory used by a user node.
  625. X*****************************************************************************/
  626. X
  627. X#ifdef __STDC__
  628. Xvoid userFree(USER *uptr)
  629. X#else
  630. Xvoid userFree(uptr)
  631. XUSER *uptr;
  632. X#endif
  633. X{
  634. X     if (uptr->name!=NULL) free(uptr->name);
  635. X     if (uptr->tty!=NULL) free(uptr->tty);
  636. X     free(uptr);
  637. X}
  638. X
  639. X
  640. X/*****************************************************************************
  641. X void userFreeList(USER *uptr)
  642. X
  643. X This function deallocates an entire user list.
  644. X*****************************************************************************/
  645. X
  646. X#ifdef __STDC__
  647. Xvoid userFreeList(USER *uptr)
  648. X#else
  649. Xvoid userFreeList(uptr)
  650. XUSER *uptr;
  651. X#endif
  652. X{
  653. X     USER *utmp;
  654. X
  655. X     while (uptr!=NULL) {
  656. X          utmp=uptr->next;
  657. X          userFree(uptr);
  658. X          uptr=utmp;
  659. X     }
  660. X}
  661. X
  662. X
  663. X/*****************************************************************************
  664. X USERLIST userCopyList(USERLIST uptr)
  665. X
  666. X This function makes a copy of the user list pointed to by uptr and returns a
  667. X pointer to the new copy.
  668. X*****************************************************************************/
  669. X
  670. X#ifdef __STDC__
  671. XUSERLIST userCopyList(USERLIST uptr)
  672. X#else
  673. XUSERLIST userCopyList(uptr)
  674. XUSERLIST uptr;
  675. X#endif
  676. X{
  677. X     USER *utmp,*up;
  678. X
  679. X     utmp=NULL;
  680. X     while (uptr!=NULL) {
  681. X          if (utmp==NULL) utmp=up=userAllocate();
  682. X          else {
  683. X               up->next=userAllocate();
  684. X               up=up->next;
  685. X          }
  686. X          if (uptr->name!=NULL) {
  687. X               up->name=(char *)malloc(strlen(uptr->name)+1);
  688. X               strcpy(up->name,uptr->name);
  689. X          }
  690. X          if (uptr->tty!=NULL) {
  691. X               up->tty=(char *)malloc(strlen(uptr->tty)+1);
  692. X               strcpy(up->tty,uptr->tty);
  693. X          }
  694. X          uptr=uptr->next;
  695. X     }
  696. X     return(utmp);
  697. X}
  698. X
  699. X
  700. X/*****************************************************************************
  701. X VARENTRY *varAllocate()
  702. X
  703. X This function allocates memory for another variable binding and sets the
  704. X fields to known, useful starting values.
  705. X*****************************************************************************/
  706. X
  707. X#ifdef __STDC__
  708. XVARENTRY *varAllocate(void)
  709. X#else
  710. XVARENTRY *varAllocate()
  711. X#endif
  712. X{
  713. X     VARENTRY *varNew;
  714. X
  715. X     varNew=(VARENTRY *)malloc(sizeof(VARENTRY));
  716. X     varNew->name=varNew->class=NULL;
  717. X     varNew->ip_addr=0;
  718. X     varNew->l1=varNew->l2=varNew->l3=0.0;
  719. X     varNew->logtime=0;
  720. X     varNew->tmp=0;
  721. X     varNew->machine=0;
  722. X     varNew->model=0;
  723. X     varNew->lastused=0;
  724. X     varNew->console=varNew->users=0;
  725. X     varNew->userFirst=NULL;
  726. X     return(varNew);
  727. X}
  728. X
  729. X
  730. X/*****************************************************************************
  731. X varFree()
  732. X
  733. X This function frees the memory used by a variable table entry.
  734. X*****************************************************************************/
  735. X
  736. X#ifdef __STDC__
  737. Xvoid varFree(VARENTRY *vptr)
  738. X#else
  739. Xvoid varFree(vptr)
  740. XVARENTRY *vptr;
  741. X#endif
  742. X{
  743. X     if (vptr->name!=NULL) free(vptr->name);
  744. X     if (vptr->userFirst!=NULL) userFreeList(vptr->userFirst);
  745. X     free(vptr);
  746. X}
  747. X
  748. X
  749. X/*****************************************************************************
  750. X varFreeTable()
  751. X
  752. X This function frees the entire variable table, removing all variable
  753. X bindings.
  754. X*****************************************************************************/
  755. X
  756. X#ifdef __STDC__
  757. Xvoid varFreeTable(void)
  758. X#else
  759. Xvoid varFreeTable()
  760. X#endif
  761. X{
  762. X     VARENTRY *vptr;
  763. X     int i;
  764. X
  765. X     for (i=0; i<VAR_ENTRIES; i++)
  766. X          while (variables[i]!=NULL) {
  767. X               vptr=variables[i]->next;
  768. X               varFree(variables[i]);
  769. X               variables[i]=vptr;
  770. X          }
  771. X}
  772. X
  773. X
  774. X/*****************************************************************************
  775. X varSet(VARENTRY *var)
  776. X
  777. X This function sets a variable's value, creating a new variable if necessary.
  778. X*****************************************************************************/
  779. X
  780. X#ifdef __STDC__
  781. Xvoid varSet(VARENTRY *var)
  782. X#else
  783. Xvoid varSet(var)
  784. XVARENTRY *var;
  785. X#endif
  786. X{
  787. X     int hashval;
  788. X     VARENTRY *vptr,*follower;
  789. X
  790. X     if (var==NULL) return;
  791. X     hashval=varHashName(var->ip_addr);
  792. X     vptr=variables[hashval];
  793. X     follower=NULL;
  794. X     while ((vptr!=NULL) && (vptr->ip_addr!=var->ip_addr)) {
  795. X          follower=vptr;
  796. X          vptr=vptr->next;
  797. X     }
  798. X     if (vptr==NULL) {
  799. X          vptr=varAllocate();
  800. X          vptr->next=NULL;
  801. X          vptr->name=(char *)malloc(strlen(var->name)+1);
  802. X          strcpy(vptr->name,var->name);
  803. X          vptr->ip_addr=var->ip_addr;
  804. X          if (follower!=NULL) follower->next=vptr;
  805. X          else variables[hashval]=vptr;
  806. X     }
  807. X     else if (strcmp(vptr->name,var->name)) {
  808. X          free(vptr->name);
  809. X          vptr->name=(char *)malloc(strlen(var->name)+1);
  810. X          strcpy(vptr->name,var->name);
  811. X     }
  812. X     vptr->l1=var->l1;                               /* Update simple fields */
  813. X     vptr->l2=var->l2;
  814. X     vptr->l3=var->l3;
  815. X     vptr->logtime=time(0);
  816. X     vptr->tmp=var->tmp;
  817. X     vptr->machine=var->machine;
  818. X     vptr->model=var->model;
  819. X     vptr->console=var->console;
  820. X     vptr->users=var->users;
  821. X     if (var->class!=NULL) {                           /* Update class field */
  822. X          if (vptr->class!=NULL) {
  823. X               if (!strcmp(vptr->class,var->class)) {
  824. X                    free(vptr->class);
  825. X                    vptr->class=(char *)malloc(strlen(var->class));
  826. X                    strcpy(vptr->class,var->class);
  827. X               }
  828. X          }
  829. X          else {
  830. X               vptr->class=(char *)malloc(strlen(var->class));
  831. X               strcpy(vptr->class,var->class);
  832. X          }
  833. X     }
  834. X     else if (vptr->class!=NULL) {
  835. X          free(vptr->class);
  836. X          vptr->class=NULL;
  837. X     }
  838. X     if (var->userFirst!=NULL) {
  839. X          userFreeList(vptr->userFirst);
  840. X          vptr->userFirst=userCopyList(var->userFirst);
  841. X     }
  842. X}
  843. X
  844. X
  845. X/*****************************************************************************
  846. X void varAdd(VARENTRY *var)
  847. X
  848. X This function adds a variable to the list, using the ipaddr field as a key,
  849. X and corrects the name field if the variable already exists with a different
  850. X name.
  851. X*****************************************************************************/
  852. X
  853. X#ifdef __STDC__
  854. Xvoid varAdd(VARENTRY *var)
  855. X#else
  856. Xvoid varAdd(var)
  857. XVARENTRY *var;
  858. X#endif
  859. X{
  860. X     int hashval;
  861. X     VARENTRY *vptr,*follower;
  862. X
  863. X     if (var==NULL) return;
  864. X     hashval=varHashName(var->ip_addr);
  865. X     vptr=variables[hashval];
  866. X     follower=NULL;
  867. X     while ((vptr!=NULL) && (vptr->ip_addr!=var->ip_addr)) {
  868. X          follower=vptr;
  869. X          vptr=vptr->next;
  870. X     }
  871. X     if (vptr==NULL) {
  872. X          vptr=varAllocate();
  873. X          vptr->next=NULL;
  874. X          vptr->name=(char *)malloc(strlen(var->name)+1);
  875. X          strcpy(vptr->name,var->name);
  876. X          vptr->ip_addr=var->ip_addr;
  877. X          if (follower!=NULL) follower->next=vptr;
  878. X          else variables[hashval]=vptr;
  879. X          vptr->machine=var->machine;
  880. X          vptr->model=var->model;
  881. X          vptr->console=var->console;
  882. X          vptr->users=var->users;
  883. X          vptr->logtime=0;
  884. X     }
  885. X     else if (strcmp(vptr->name,var->name)) {
  886. X          free(vptr->name);
  887. X          vptr->name=(char *)malloc(strlen(var->name)+1);
  888. X          strcpy(vptr->name,var->name);
  889. X     }
  890. X}
  891. X
  892. X
  893. X/*****************************************************************************
  894. X void varDelete(VARENTRY *var)
  895. X
  896. X This function deletes a variable from the list, doing nothing if the
  897. X variable does not exist.
  898. X*****************************************************************************/
  899. X
  900. X#ifdef __STDC__
  901. Xvoid varDelete(VARENTRY *var)
  902. X#else
  903. Xvoid varDelete(var)
  904. XVARENTRY *var;
  905. X#endif
  906. X{
  907. X     int hashval;
  908. X     VARENTRY *vptr,*follower;
  909. X
  910. X     if (var==NULL) return;
  911. X     hashval=varHashName(var->ip_addr);
  912. X     vptr=variables[hashval];
  913. X     follower=NULL;
  914. X     while ((vptr!=NULL) && (vptr->ip_addr!=var->ip_addr)) {
  915. X          follower=vptr;
  916. X          vptr=vptr->next;
  917. X     }
  918. X     if (vptr!=NULL) {
  919. X          if (follower==NULL) variables[hashval]=vptr->next;
  920. X          else follower->next=vptr->next;
  921. X          varFree(vptr);
  922. X     }
  923. X}
  924. X
  925. X
  926. X/*****************************************************************************
  927. X VARENTRY *varFindMatch(VARENTRY *template)
  928. X
  929. X This function searches the variable table looking for a variable whose value
  930. X matches the criteria given in the template, and returns a pointer to an
  931. X entry which satisfies the criteria.  If no match can be made, the return
  932. X value is NULL.
  933. X*****************************************************************************/
  934. X
  935. X#ifdef __STDC__
  936. XVARENTRY *varFindMatch(VARENTRY *template)
  937. X#else
  938. XVARENTRY *varFindMatch(template)
  939. XVARENTRY *template;
  940. X#endif
  941. X{
  942. X     int hashval,found;
  943. X     VARENTRY *vptr;
  944. X     long nowtime;
  945. X
  946. X     time(&nowtime);
  947. X     for (found=0,hashval=0; (hashval<VAR_ENTRIES) && !found; hashval++)
  948. X          for (vptr=variables[hashval]; (vptr!=NULL) && !found;
  949. X               vptr=vptr->next) {
  950. X               if ((vptr->l1<=template->l1) && (vptr->l2<=template->l2) &&
  951. X                   (vptr->l3<=template->l3) &&
  952. X                   (varUsers(vptr)<=varUsers(template)) &&
  953. X                   (varConsole(vptr)<=varConsole(template)) &&
  954. X                   (vptr->tmp>=template->tmp) &&
  955. X                   (!template->machine || (vptr->machine==template->machine)) &&
  956. X                   (!template->model || (vptr->model==template->model)) &&
  957. X                   ((nowtime-vptr->logtime)<15*60) &&
  958. X                   ((nowtime-vptr->lastused)>2*60)) {
  959. X                    found=1;
  960. X                    vptr->lastused=nowtime;
  961. X                    break;
  962. X               }
  963. X          }
  964. X     if (!found) return(NULL);
  965. X     else return(vptr);
  966. X}
  967. X
  968. X
  969. X/*****************************************************************************
  970. X VARENTRY *varFind(u_long ip_addr)
  971. X
  972. X This function looks up an entry in the variable table which has the given
  973. X IP address.  A pointer to the matching table entry is returned.  If no match
  974. X is found, a NULL value is returned.
  975. X*****************************************************************************/
  976. X
  977. X#ifdef __STDC__
  978. XVARENTRY *varFind(u_long ip_addr)
  979. X#else
  980. XVARENTRY *varFind(ip_addr)
  981. Xu_long ip_addr;
  982. X#endif
  983. X{
  984. X     int hashval;
  985. X     VARENTRY *vptr;
  986. X
  987. X     hashval=varHashName(ip_addr);
  988. X     vptr=variables[hashval];
  989. X     while ((vptr!=NULL) && (vptr->ip_addr!=ip_addr))
  990. X          vptr=vptr->next;
  991. X     return(vptr);
  992. X}
  993. X
  994. X
  995. X#ifdef __STDC__
  996. Xint varSaveState(void)
  997. X#else
  998. Xint varSaveState()
  999. X#endif
  1000. X{
  1001. X     FILE *outf;
  1002. X     char temp[32],temp2[16];
  1003. X     VARENTRY *vptr;
  1004. X     int i;
  1005. X
  1006. X     if ((outf=fopen(NETUSEHOSTFILE,"w"))==NULL) {
  1007. X          perror(NETUSEHOSTFILE);
  1008. X          return(RV_NOFILE);
  1009. X     }
  1010. X     for (i=0; i<VAR_ENTRIES; i++) {
  1011. X          for (vptr=variables[i]; vptr!=NULL; vptr=vptr->next)
  1012. X               fprintf(outf,"%-7s %s %s\n",
  1013. X                       netGetMachType(vptr->machine,temp),vptr->name,
  1014. X                       netGetModelType(vptr->model,temp2));
  1015. X     }
  1016. X     fclose(outf);
  1017. X     lastSave=time(0);
  1018. X     return(RV_OK);
  1019. X}
  1020. X
  1021. X
  1022. X#ifdef __STDC__
  1023. Xint varLoadHosts(void)
  1024. X#else
  1025. Xint varLoadHosts()
  1026. X#endif
  1027. X{
  1028. X     FILE *inf;
  1029. X     char temp[128],inbuf[512];
  1030. X     VARENTRY *ventry;
  1031. X
  1032. X     if ((inf=fopen(NETUSEHOSTFILE,"r"))==NULL) {
  1033. X          perror(NETUSEHOSTFILE);
  1034. X          return(RV_NOFILE);
  1035. X     }
  1036. X     varFreeTable();
  1037. X     ventry=varAllocate();
  1038. X     while (fgets(inbuf,sizeof(inbuf),inf)!=NULL) {
  1039. X          inbuf[strlen(inbuf)-1]='\0';
  1040. X          if (!strlen(inbuf) || (inbuf[0]=='#')) continue;
  1041. X          if (!(ventry->ip_addr=netGetAddress(textparam(inbuf,1,temp))))
  1042. X               continue;
  1043. X          ventry->name=(char *)malloc(strlen(temp)+1);
  1044. X          strcpy(ventry->name,temp);
  1045. X          if (!strcmp(textparam(inbuf,0,temp),"Sun"))
  1046. X               ventry->machine=MACH_SUN;
  1047. X          else if (!strcmp(temp,"DEC"))
  1048. X               ventry->machine=MACH_DEC;
  1049. X          else if (!strcmp(temp,"IBM"))
  1050. X               ventry->machine=MACH_IBM_RS6000;
  1051. X          else if (!strcmp(temp,"Apo"))
  1052. X               ventry->machine=MACH_APOLLO;
  1053. X          else if (!strcmp(temp,"HP"))
  1054. X               ventry->machine=MACH_HP;
  1055. X          else ventry->machine=0;
  1056. X          ventry->model=netStrToModel(textparam(inbuf,2,temp));
  1057. X          varAdd(ventry);
  1058. X          free(ventry->name);
  1059. X     }
  1060. X     varFree(ventry);
  1061. X     fclose(inf);
  1062. X     lastSave=time(0);
  1063. X     return(RV_OK);
  1064. X}
  1065. X
  1066. X
  1067. X#ifdef __STDC__
  1068. Xvoid varInit(void)
  1069. X#else
  1070. Xvoid varInit()
  1071. X#endif
  1072. X{
  1073. X     int i;
  1074. X
  1075. X     for (i=0; i<VAR_ENTRIES; i++)
  1076. X          variables[i]=NULL;
  1077. X     varLoadHosts();
  1078. X}
  1079. X
  1080. X
  1081. X#ifdef __STDC__
  1082. Xint varConsole(VARENTRY *vptr)
  1083. X#else
  1084. Xint varConsole(vptr)
  1085. XVARENTRY *vptr;
  1086. X#endif
  1087. X{
  1088. X/*
  1089. X     USER *uptr;
  1090. X
  1091. X     if ((vptr->userFirst==NULL) && (vptr->console!=0)) return(1);
  1092. X     for (uptr=vptr->userFirst; uptr!=NULL; uptr=uptr->next)
  1093. X          if (!strcmp(uptr->tty,"cons")) return(1);
  1094. X     return(0);
  1095. X*/
  1096. X     return(vptr->console);
  1097. X}
  1098. X
  1099. X
  1100. X#ifdef __STDC__
  1101. Xint varUsers(VARENTRY *vptr)
  1102. X#else
  1103. Xint varUsers(vptr)
  1104. XVARENTRY *vptr;
  1105. X#endif
  1106. X{
  1107. X/*
  1108. X     USER *uptr;
  1109. X     int i;
  1110. X
  1111. X     if ((vptr->userFirst==NULL) && (vptr->users!=0)) return(vptr->users);
  1112. X     for (i=0,uptr=vptr->userFirst; uptr!=NULL; uptr=uptr->next)
  1113. X          ++i;
  1114. X     return(i);
  1115. X*/
  1116. X     return(vptr->users);
  1117. X}
  1118. X
  1119. X
  1120. X#ifdef __STDC__
  1121. Xchar *fmt_time(long theTime,char *s2)
  1122. X#else
  1123. Xchar *fmt_time(theTime,s2)
  1124. Xlong theTime;
  1125. Xchar *s2;
  1126. X#endif
  1127. X{
  1128. X     struct tm *tim;
  1129. X
  1130. X     tim=localtime(&theTime);
  1131. X     sprintf(s2,"%02d/%02d %2d:%02d%s",tim->tm_mon+1,tim->tm_mday,
  1132. X                ((tim->tm_hour % 12) ? (tim->tm_hour % 12) : 12),
  1133. X                tim->tm_min,(tim->tm_hour>=12 ? "pm" : "am"));
  1134. X     return(s2);
  1135. X}
  1136. X
  1137. X
  1138. X#ifdef __STDC__
  1139. Xvoid varDumpTable(char *fname)
  1140. X#else
  1141. Xvoid varDumpTable(fname)
  1142. Xchar *fname;
  1143. X#endif
  1144. X{
  1145. X     VARENTRY *vptr;
  1146. X     int i;
  1147. X     FILE *outf;
  1148. X     char temp[25],temp2[25],temp3[5];
  1149. X
  1150. X     if ((outf=fopen(fname,"w"))==NULL) {
  1151. X          perror("fopen");
  1152. X          return;
  1153. X     }
  1154. X     lTime=time(0);
  1155. X     fprintf(outf,"Last written: %s\n",ctime(&lTime));
  1156. X     fprintf(outf,"Host name            Type    Load Averages     Ses Disp Last Report   /tmp    \n");
  1157. X     fprintf(outf,"-------------------- ---- -------------------- --- ---- ------------- --------\n");
  1158. X     for (i=0; i<VAR_ENTRIES; i++)
  1159. X          for (vptr=variables[i]; vptr!=NULL; vptr=vptr->next)
  1160. X               fprintf(outf,"%20s %-4s %6.2f %6.2f %6.2f %3d %s  %s %8lu\n",
  1161. X                            spicture(vptr->name,20,temp),
  1162. X                            netGetMachType(vptr->machine,temp3),
  1163. X                            vptr->l1,vptr->l2,vptr->l3,varUsers(vptr),
  1164. X                            (varConsole(vptr) ? "YES" : "NO "),
  1165. X                            fmt_time(vptr->logtime,temp2),vptr->tmp);
  1166. X     fclose(outf);
  1167. X     chmod(fname,0644);
  1168. X}
  1169. X
  1170. X
  1171. X#ifdef __STDC__
  1172. Xvoid varDumpTableWithModels(char *fname)
  1173. X#else
  1174. Xvoid varDumpTableWithModels(fname)
  1175. Xchar *fname;
  1176. X#endif
  1177. X{
  1178. X     VARENTRY *vptr;
  1179. X     int i;
  1180. X     FILE *outf;
  1181. X     char temp[25],temp2[25],temp3[5];
  1182. X
  1183. X     if ((outf=fopen(fname,"w"))==NULL) {
  1184. X          perror("fopen");
  1185. X          return;
  1186. X     }
  1187. X     lTime=time(0);
  1188. X     fprintf(outf,"Last written: %s\n",ctime(&lTime));
  1189. X     fprintf(outf,"Host name           Type and Model         Load Averages     Ses Disp /tmp    \n");
  1190. X     fprintf(outf,"------------------- ------------------- -------------------- --- ---- --------\n");
  1191. X     for (i=0; i<VAR_ENTRIES; i++)
  1192. X          for (vptr=variables[i]; vptr!=NULL; vptr=vptr->next)
  1193. X               fprintf(outf,"%19s %-4s%-15s %6.2f %6.2f %6.2f %3d %s  %8lu\n",
  1194. X                            spicture(vptr->name,19,temp),
  1195. X                            netGetMachType(vptr->machine,temp3),
  1196. X                            netGetModelType(vptr->model,temp2),
  1197. X                            vptr->l1,vptr->l2,vptr->l3,varUsers(vptr),
  1198. X                            (varConsole(vptr) ? "YES" : "NO "),vptr->tmp);
  1199. X     fclose(outf);
  1200. X     chmod(fname,0644);
  1201. X}
  1202. X
  1203. X
  1204. X#define binval(x) (x ? 1 : 0)
  1205. X
  1206. X
  1207. X#ifdef __STDC__
  1208. Xvoid treeInsert(TREE **tptr,VARENTRY *vptr)
  1209. X#else
  1210. Xvoid treeInsert(tptr,vptr)
  1211. XTREE **tptr;
  1212. XVARENTRY *vptr;
  1213. X#endif
  1214. X{
  1215. X     if (*tptr==NULL) {
  1216. X          (*tptr)=(TREE *)malloc(sizeof(TREE));
  1217. X          (*tptr)->data=vptr;
  1218. X          (*tptr)->left=NULL;
  1219. X          (*tptr)->right=NULL;
  1220. X     }
  1221. X     else if ((varConsole(vptr)<varConsole((*tptr)->data)) ||
  1222. X              ((varConsole(vptr)==varConsole((*tptr)->data)) &&
  1223. X               (vptr->l2<((*tptr)->data->l2))))
  1224. X               treeInsert(&((*tptr)->left),vptr);
  1225. X          else treeInsert(&((*tptr)->right),vptr);
  1226. X}
  1227. X
  1228. X
  1229. X#ifdef __STDC__
  1230. Xvoid treeBuild(u_char machtype,u_char modeltype)
  1231. X#else
  1232. Xvoid treeBuild(machtype,modeltype)
  1233. Xu_char machtype,modeltype;
  1234. X#endif
  1235. X{
  1236. X     VARENTRY *vptr;
  1237. X     int i;
  1238. X
  1239. X     theTree=NULL;
  1240. X     for (i=0; i<VAR_ENTRIES; i++)
  1241. X          for (vptr=variables[i]; vptr!=NULL; vptr=vptr->next)
  1242. X               if ((!machtype || (machtype==vptr->machine)) &&
  1243. X                   (!modeltype || (modeltype==vptr->model)))
  1244. X                    treeInsert(&theTree,vptr);
  1245. X}
  1246. X
  1247. X
  1248. X#ifdef __STDC__
  1249. Xvoid treePrintHost(FILE *outf,TREE *tptr)
  1250. X#else
  1251. Xvoid treePrintHost(outf,tptr)
  1252. XFILE *outf;
  1253. XTREE *tptr;
  1254. X#endif
  1255. X{
  1256. X     char temp[132],temp2[132],temp3[132];
  1257. X
  1258. X     if (tptr->data->logtime==0) {
  1259. X          fprintf(outf,"%20s %-4s ------ ------ ------ --- ---  ------------- --------\n\r",
  1260. X                  spicture(tptr->data->name,20,temp),
  1261. X                  netGetMachType(tptr->data->machine,temp3));
  1262. X     }
  1263. X     else if ((time(NULL)-tptr->data->logtime)>=DOWNTIME*60) {
  1264. X          fprintf(outf,"%20s %-4s ------ ------ ------ --- ---  %s --------\n\r",
  1265. X                  spicture(tptr->data->name,20,temp),
  1266. X                  netGetMachType(tptr->data->machine,temp3),
  1267. X                  fmt_time(tptr->data->logtime,temp2));
  1268. X     }
  1269. X     else {
  1270. X          fprintf(outf,"%20s %-4s %6.2f %6.2f %6.2f %3hu %s  %s %8lu\n\r",
  1271. X                  spicture(tptr->data->name,20,temp),
  1272. X                  netGetMachType(tptr->data->machine,temp3),tptr->data->l1,
  1273. X                  tptr->data->l2,tptr->data->l3,varUsers(tptr->data),
  1274. X                  (varConsole(tptr->data) ? "YES" : "NO "),
  1275. X                  fmt_time(tptr->data->logtime,temp2),tptr->data->tmp);
  1276. X     }
  1277. X}
  1278. X
  1279. X
  1280. X#ifdef __STDC__
  1281. Xvoid treeDump(FILE *outf,TREE *tptr,u_char opcode,int *i)
  1282. X#else
  1283. Xvoid treeDump(outf,tptr,opcode,i)
  1284. XFILE *outf;
  1285. XTREE *tptr;
  1286. Xu_char opcode;
  1287. Xint *i;
  1288. X#endif
  1289. X{
  1290. X     if (((opcode==OP_DISPLIST) && (*i>=MAXLSTLEN)) || (tptr==NULL)) return;
  1291. X     if (tptr->left!=NULL) treeDump(outf,tptr->left,opcode,i);
  1292. X     if ((opcode==OP_GETLIST) ||
  1293. X         ((opcode==OP_GETDOWN) && (((time(NULL)-tptr->data->logtime)>=15*60)) ||
  1294. X         ((opcode==OP_DISPLIST) &&
  1295. X          ((time(NULL)-tptr->data->logtime)<15*60) && (*i<MAXLSTLEN)))) {
  1296. X          treePrintHost(outf,tptr);
  1297. X          ++(*i);
  1298. X     }
  1299. X     if (tptr->right!=NULL) treeDump(outf,tptr->right,opcode,i);
  1300. X     free(tptr);
  1301. X}
  1302. X
  1303. X
  1304. X#ifdef __STDC__
  1305. Xvoid treePrintList(FILE *outf,u_char machtype,u_char modeltype,u_char opcode)
  1306. X#else
  1307. Xvoid treePrintList(outf,machtype,modeltype,opcode)
  1308. XFILE *outf;
  1309. Xu_char machtype,modeltype,opcode;
  1310. X#endif
  1311. X{
  1312. X     long t;
  1313. X     int i;
  1314. X
  1315. X     time(&t);
  1316. X     treeBuild(machtype,modeltype);
  1317. X     fprintf(outf,"The current time is: %s\n\r",ctime(&t));
  1318. X     fprintf(outf,"Host name            Type    Load Averages     Ses Disp Last Report   /tmp    \n\r");
  1319. X     fprintf(outf,"-------------------- ---- -------------------- --- ---- ------------- --------\n\r");
  1320. X     fflush(outf);
  1321. X     i=0;
  1322. X     treeDump(outf,theTree,opcode,&i);
  1323. X     fprintf(outf,"\n\r");
  1324. X     fflush(outf);
  1325. X}
  1326. X
  1327. X
  1328. X#ifdef __STDC__
  1329. Xvoid treePrintHostWithModels(FILE *outf,TREE *tptr)
  1330. X#else
  1331. Xvoid treePrintHostWithModels(outf,tptr)
  1332. XFILE *outf;
  1333. XTREE *tptr;
  1334. X#endif
  1335. X{
  1336. X     char temp[132],temp2[132],temp3[132];
  1337. X
  1338. X     if ((tptr->data->logtime==0) || ((time(NULL)-tptr->data->logtime)>=DOWNTIME*60)) {
  1339. X          fprintf(outf,"%19s %-4s%-15s ------ ------ ------ --- ---  --------\n\r",
  1340. X                  spicture(tptr->data->name,19,temp),
  1341. X                  netGetMachType(tptr->data->machine,temp3),
  1342. X                  netGetModelType(tptr->data->model,temp2));
  1343. X     }
  1344. X     else {
  1345. X          fprintf(outf,"%19s %-4s%-15s %6.2f %6.2f %6.2f %3d %s  %8lu\n\r",
  1346. X                  spicture(tptr->data->name,19,temp),
  1347. X                  netGetMachType(tptr->data->machine,temp3),
  1348. X                  netGetModelType(tptr->data->model,temp2),
  1349. X                  tptr->data->l1,tptr->data->l2,tptr->data->l3,varUsers(tptr->data),
  1350. X                  (varConsole(tptr->data) ? "YES" : "NO "),tptr->data->tmp);
  1351. X     }
  1352. X}
  1353. X
  1354. X
  1355. X#ifdef __STDC__
  1356. Xvoid treeDumpWithModels(FILE *outf,TREE *tptr,u_char opcode,int *i)
  1357. X#else
  1358. Xvoid treeDumpWithModels(outf,tptr,opcode,i)
  1359. XFILE *outf;
  1360. XTREE *tptr;
  1361. Xu_char opcode;
  1362. Xint *i;
  1363. X#endif
  1364. X{
  1365. X     if (((opcode==OP_DISPMLIST) && (*i>=MAXLSTLEN)) || (tptr==NULL)) return;
  1366. X     if (tptr->left!=NULL) treeDumpWithModels(outf,tptr->left,opcode,i);
  1367. X     if ((opcode==OP_GETMLIST) ||
  1368. X         ((opcode==OP_GETMDOWN) && (((time(NULL)-tptr->data->logtime)>=15*60)) ||
  1369. X         ((opcode==OP_DISPMLIST) &&
  1370. X          ((time(NULL)-tptr->data->logtime)<15*60) && (*i<MAXLSTLEN)))) {
  1371. X          treePrintHostWithModels(outf,tptr);
  1372. X          ++(*i);
  1373. X     }
  1374. X     if (tptr->right!=NULL) treeDumpWithModels(outf,tptr->right,opcode,i);
  1375. X     free(tptr);
  1376. X}
  1377. X
  1378. X
  1379. X#ifdef __STDC__
  1380. Xvoid treePrintListWithModels(FILE *outf,u_char machtype,u_char modeltype,u_char opcode)
  1381. X#else
  1382. Xvoid treePrintListWithModels(outf,machtype,modeltype,opcode)
  1383. XFILE *outf;
  1384. Xu_char machtype,modeltype,opcode;
  1385. X#endif
  1386. X{
  1387. X     long t;
  1388. X     int i;
  1389. X
  1390. X     time(&t);
  1391. X     treeBuild(machtype,modeltype);
  1392. X     fprintf(outf,"The current time is: %s\n\r",ctime(&t));
  1393. X     fprintf(outf,"Host name           Type and Model         Load Averages     Ses Disp /tmp    \n");
  1394. X     fprintf(outf,"------------------- ------------------- -------------------- --- ---- --------\n\r");
  1395. X     fflush(outf);
  1396. X     i=0;
  1397. X     treeDumpWithModels(outf,theTree,opcode,&i);
  1398. X     fprintf(outf,"\n\r");
  1399. X     fflush(outf);
  1400. X}
  1401. END_OF_FILE
  1402.   if test 25559 -ne `wc -c <'netuse/lib/variable.c'`; then
  1403.     echo shar: \"'netuse/lib/variable.c'\" unpacked with wrong size!
  1404.   fi
  1405.   # end of 'netuse/lib/variable.c'
  1406. fi
  1407. echo shar: End of archive 1 \(of 6\).
  1408. cp /dev/null ark1isdone
  1409. MISSING=""
  1410. for I in 1 2 3 4 5 6 ; do
  1411.     if test ! -f ark${I}isdone ; then
  1412.     MISSING="${MISSING} ${I}"
  1413.     fi
  1414. done
  1415. if test "${MISSING}" = "" ; then
  1416.     echo You have unpacked all 6 archives.
  1417.     rm -f ark[1-9]isdone
  1418. else
  1419.     echo You still must unpack the following archives:
  1420.     echo "        " ${MISSING}
  1421. fi
  1422. exit 0
  1423. exit 0 # Just in case...
  1424.