home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume34 / netuse / part01 < prev    next >
Encoding:
Text File  |  1993-01-09  |  49.9 KB  |  1,419 lines

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