home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume28 / gnufusers / part01 next >
Text File  |  1992-02-26  |  38KB  |  1,359 lines

  1. Newsgroups: comp.sources.misc
  2. From: edsall@iastate.edu (David M Edsall)
  3. Subject:  v28i076:  gnufusers - a program to keep an eye on people, Part01/01
  4. Message-ID: <1992Feb26.065949.27943@sparky.imd.sterling.com>
  5. X-Md4-Signature: d0a3c919912977de1d050a9c72c53e9a
  6. Date: Wed, 26 Feb 1992 06:59:49 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: edsall@iastate.edu (David M Edsall)
  10. Posting-number: Volume 28, Issue 76
  11. Archive-name: gnufusers/part01
  12. Environment: UNIX, ANSI-C, cursesX
  13.  
  14. This is an variation on the program fusers that I posted to alt.sources last
  15. month. In the past month, our Computation Center installed a new version of
  16. finger ( gnu-finger ) which is designed to work in a distributed computing
  17. environment similar to MIT's Project Athena. Needless to say, this required 
  18. the program fusers to be changed to accomodate this. This program in no way 
  19. is associated with GNU programs.
  20.  
  21. This is a variation on the program susers posted to alt.sources by Yufan Hu 
  22. ( yufan@cs.keele.ac.uk ). Susers used the program rusers which I had never 
  23. heard of nor had a copy of anywhere.  So, I decided to rewrite it using 
  24. gnu-finger(1), which parts of the world seem to have a copy of, even me :). 
  25. I also changed the program so that it wrote multiple pages rather than just 
  26. one page allowing the user to leaf through a list of users.
  27.  
  28.     Changes:
  29.  
  30. Parts of this program and some of my own included routines are written in 
  31. ANSI C, requiring the use of an ANSI compiler such as gcc or changing of 
  32. the program, namely function declarations.
  33.  
  34. This program uses cursesX, rather than curses. Since this was my
  35. second attempt at writing a curses based program, I'm not too sure
  36. what the differences are. I was told by another user that if you change all 
  37. references to cursesX to curses that it works okay.
  38.  
  39.     Bugs:
  40.     -----
  41.  
  42. It didn't seem to like my xterm until I reset TERM to vt100 or
  43. vt200. Go figure.
  44.  
  45. You can only specify either a user on a machine running gnu-finger(1) or a
  46. user not running gnu-finger(1) on the command line and not a mixture. If 
  47. someone wishes to modify this code so that both can be used,please let me 
  48. know if you do so.
  49.  
  50.     dave
  51. ------------------
  52. #! /bin/sh
  53. # This is a shell archive.  Remove anything before this line, then feed it
  54. # into a shell via "sh file" or similar.  To overwrite existing files,
  55. # type "sh file -c".
  56. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  57. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  58. # Contents:  Makefile gnufusers.1 gnufusers.c option.c option.h
  59. #   print_errors.c print_errors.h
  60. # Wrapped by kent@sparky on Wed Feb 26 00:48:58 1992
  61. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  62. echo If this archive is complete, you will see the following message:
  63. echo '          "shar: End of archive 1 (of 1)."'
  64. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  65.   echo shar: Will not clobber existing file \"'Makefile'\"
  66. else
  67.   echo shar: Extracting \"'Makefile'\" \(465 characters\)
  68.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  69. X
  70. XCC=gcc
  71. XCFLAGS=  -g
  72. XLDFLAGS= -g
  73. XLIBS   = -lcursesX
  74. XDESTBIN= /home/edsall/bin
  75. XMAN    = 1
  76. X
  77. XSRCS   = gnufusers.c option.c print_errors.c
  78. XOBJS   = gnufusers.o option.o print_errors.o
  79. X
  80. Xall:    gnufusers
  81. X
  82. Xgnufusers:    ${OBJS}
  83. X    gcc -o gnufusers ${LDFLAGS} ${OBJS} ${LIBS}
  84. X
  85. X${OBJS}: option.h print_errors.h
  86. X
  87. Xinstall:    gnufusers
  88. X    install -s gnufusers ${DESTBIN}
  89. X    cp gnufusers.1 /home/edsall/man/man${MAN}/gnufusers.${MAN}
  90. X
  91. Xclean:
  92. X    rm -f gnufusers *.o core a.out make.log lint.out
  93. END_OF_FILE
  94.   if test 465 -ne `wc -c <'Makefile'`; then
  95.     echo shar: \"'Makefile'\" unpacked with wrong size!
  96.   fi
  97.   # end of 'Makefile'
  98. fi
  99. if test -f 'gnufusers.1' -a "${1}" != "-c" ; then 
  100.   echo shar: Will not clobber existing file \"'gnufusers.1'\"
  101. else
  102.   echo shar: Extracting \"'gnufusers.1'\" \(4312 characters\)
  103.   sed "s/^X//" >'gnufusers.1' <<'END_OF_FILE'
  104. X.TH GNUFUSERS 1 "18 February 1992"
  105. X
  106. X.SH NAME
  107. Xgnufusers \- watch people login and out
  108. X.SH SYNOPSIS
  109. X.B gnufusers [ -g -i seconds -I minutes -f file users...]
  110. X.SH DESCRIPTION
  111. X.I Gnufusers
  112. Xis a screen based utility that displays
  113. X.IR gnu-finger (1)
  114. Xinformation using the
  115. X.IR curses (3)
  116. Xpackage.
  117. X.PP
  118. XEach column displays, in order, the user name, the host and the tty the user
  119. Xcurrently logged in, the user's login time, and the
  120. Xidle time (if any) in minutes. "Active users", users with idle time less
  121. Xthan a user specified time ( -I option ) or 3 minutes by default, 
  122. Xare displayed in reverse video.
  123. X.PP
  124. X.I Gnufusers
  125. Xcollects information at a user specified interval ( -i option ) 
  126. Xor every 20 seconds by default using 
  127. X.IR finger (1).
  128. XIt also checks your mail box for new mails.
  129. X.PP
  130. X.I Gnufusers
  131. Xeither watchs those people you specified in your 
  132. X.IR $HOME/.fusers
  133. Xfile, users specified in a file given on the command line with the -f
  134. Xoption or a list of users optionally specified on the command line itself.
  135. XIf the -g option is specified along with the list of user names on the 
  136. Xcommand line, then 
  137. X.I gnufusers 
  138. Xassumes that the person is on a machine running
  139. X.IR gnu-finger(1). 
  140. XIf the -g option is not included, then 
  141. X.I gnufusers 
  142. Xassumes that the user is on a machine which is not running 
  143. X.IR gnu-finger(1).
  144. X
  145. X.SH FILE FORMAT
  146. X
  147. XEach line in the file indicates a user to be watched. A user is represented as
  148. X.I user-name@host
  149. Xfor a user on a remote host
  150. Xor
  151. X.I user-name
  152. Xfor a user on the local host.
  153. XIf
  154. X.I user-name
  155. Xis
  156. X.I all
  157. Xthen all the users on
  158. X.I host
  159. Xwill be watched.
  160. X.I #
  161. Xcan be used to delimit comments in the file. If the user is on a machine 
  162. Xrunning
  163. X.IR gnu-finger(1)
  164. Xthen you must place a
  165. X.I g 
  166. Xin the first column of that line followed by a 
  167. Xspace and then the user name. If the user is not on a machine running
  168. X.IR gnu-finger(1)
  169. Xthen the username must be preceeded by at least two spaces.
  170. XThe following is an example of a typical file format
  171. X
  172. X.S
  173. X
  174. X # People to spy on                                                     
  175. X   bob@foo.com                                                         
  176. X g bonnie@gnubar.edu                      
  177. X g all@gnuhack.gov                                                       
  178. X   jane@see.dick.run.edu                                                   
  179. X
  180. X                          
  181. X                        
  182. X                    
  183. X                                         
  184. X                          
  185. X
  186. X.I Gnufusers
  187. Xcan watch people on any machine which can be reached by
  188. X.IR gnu-finger(1).
  189. X
  190. X.SH OPTIONS
  191. X
  192. X-g   specifies that a user listed on the command line is 
  193. X     on a machine running 
  194. X.I gnu-finger(1)
  195. X
  196. X-i   specifies the interval between updates
  197. X
  198. X-I   specifies how long a user must be idle before being    
  199. X     considered inactive
  200. X-f   specifies an alternative file to 
  201. X.I   $HOME/.fusers
  202. X
  203. X.SH EXAMPLES
  204. X
  205. XThe following example will get the list of users from the file
  206. X.I $HOME/.fusers
  207. Xand update the pages every 30 seconds, considering an inactive
  208. Xuser to be one who has been idle for three minutes
  209. X
  210. X
  211. Xgnufusers
  212. X
  213. X
  214. X
  215. XIn this example the list of users is in the file local.fusers in 
  216. Xthe user's current working directory. The update has been set for 
  217. Xone and a half minutes and the idle limit set for 2 minutes
  218. X
  219. X
  220. Xgnufusers -f local.fusers -i 90 -I 2 
  221. X
  222. X
  223. X
  224. XIn this example, the user has specified the name's to keep track of
  225. Xon the command line, assuming default values for the update interval 
  226. Xand the idle limit. This assumes that the user is on a machine which
  227. Xis not running gnu-finger(1).
  228. X
  229. X
  230. Xgnufusers all@myhost worf@grep.unix.com
  231. X
  232. X
  233. X
  234. X                         
  235. X                          
  236. X                              
  237. X                                     
  238. X                                      
  239. X                                   
  240. X                           
  241. X
  242. XIn this example, the user has specified the name's to keep track of
  243. Xon the command line, assuming default values for the update interval 
  244. Xand the idle limit. This assumes that the user is on a machine which
  245. Xis running gnu-finger(1).
  246. X
  247. X
  248. Xgnufusers -g all@myhost worf@grep.unix.com
  249. X
  250. X
  251. X
  252. X
  253. X.SH "FILES"
  254. X$HOME/.fusers
  255. X
  256. X.SH "AUTHOR"
  257. X
  258. XDavid M. Edsall ( edsall@iastate.edu )
  259. X
  260. X( based on the program 
  261. X.I susers
  262. Xdeveloped by Yufan Hu (yufan@cs.keele.ac.uk) )
  263. X
  264. X.SH "SEE ALSO"
  265. Xgnu-finger(1), w(1), curses(3x), intro(3cur)
  266. END_OF_FILE
  267.   if test 4312 -ne `wc -c <'gnufusers.1'`; then
  268.     echo shar: \"'gnufusers.1'\" unpacked with wrong size!
  269.   fi
  270.   # end of 'gnufusers.1'
  271. fi
  272. if test -f 'gnufusers.c' -a "${1}" != "-c" ; then 
  273.   echo shar: Will not clobber existing file \"'gnufusers.c'\"
  274. else
  275.   echo shar: Extracting \"'gnufusers.c'\" \(16008 characters\)
  276.   sed "s/^X//" >'gnufusers.c' <<'END_OF_FILE'
  277. X/* fusers.c
  278. X * Author: Dave Edsall ( edsall@iastate.edu )
  279. X * ( based on the program susers developed by 
  280. X * Yufan Hu ( yufan@cs.keele.ac.uk )  )
  281. X * Date: 18 February 1992
  282. X */
  283. X
  284. X#include    <stdio.h>
  285. X#include    <sys/time.h>
  286. X#include    <signal.h>
  287. X#include    <cursesX.h>
  288. X#include    <sys/types.h>
  289. X#include    <sys/stat.h>
  290. X#include    <utmp.h>
  291. X#include     <ctype.h>
  292. X#include    <sys/socket.h>
  293. X#include    <netdb.h>
  294. X#include        <math.h>
  295. X#include        "print_errors.h"
  296. X#include        "option.h"
  297. X/* utmp sizes */
  298. X#define        NMAX        sizeof(utmp.ut_name)
  299. X#define        LMAX        sizeof(utmp.ut_line)
  300. X
  301. X/* width of 1 display column */
  302. X#define        COL_WIDTH    40
  303. X
  304. X/* update interval in seconds */
  305. Xint        INTERVAL = 30;
  306. X
  307. X/* Minutes the user is considerred to be no idle and
  308. X * Marked with reverse video */
  309. X
  310. Xint     IDLEMIN = 3;
  311. X
  312. X/* x/60 rounded */
  313. X#define        DIV60(t)    ((t+30)/60)
  314. X
  315. X/* number of COL_WIDTH columns on screen */
  316. Xint        ncols;
  317. X
  318. Xtime_t        pclock;
  319. X
  320. X/* set if terminal inserts blanks when standout mode is used */
  321. Xint        sg;
  322. X
  323. X/* one line of utmp information */
  324. Xstruct utmp    utmp;
  325. X
  326. X/* copy of argv[0] for error messages */
  327. Xchar        *self;
  328. X
  329. X/* standout mode disabled if set */
  330. Xint        video_flag = 0;
  331. X
  332. X/* debug messages printed if set */
  333. Xint        debug_flag = 0;
  334. X
  335. X/* interrupt handler */
  336. Xint        quit();
  337. Xchar localhost[256];
  338. X
  339. X
  340. X/* Windows for paging of finger informations */
  341. XWINDOW *win[20];
  342. X
  343. X
  344. XFILE *popen();
  345. Xchar *strchr();
  346. Xchar *strtok();
  347. Xchar *getenv();
  348. Xint check_mail();
  349. X
  350. Xstruct user_str {
  351. X    char name[10];      /* finger information */
  352. X    char tty[4];
  353. X    char on[12];
  354. X    char idle[6];
  355. X    char gidle[8];
  356. X};
  357. X
  358. X#define MAXWATCH    256
  359. X#define WATCHFILE    "/.fusers"
  360. X
  361. Xstruct watch {
  362. X    char name[11];     /* user name and */
  363. X    char host[256];    /* host to watch for them on */
  364. X        int gflag;         /* flags the program that the user is on a system
  365. X                              which uses gnu finger */
  366. X} watched[MAXWATCH];
  367. X
  368. X
  369. X
  370. X
  371. X
  372. X
  373. X
  374. X
  375. X
  376. Xstruct user_str *ubreak(ustr,gflag)
  377. X
  378. X
  379. X/*
  380. X   ubreak():
  381. X      effect: copy finger information into temporary storage
  382. X      returns: structure containing finger info
  383. X      modifies: nothing 
  384. X*/
  385. X
  386. X
  387. Xchar *ustr; 
  388. Xint gflag;
  389. X{
  390. X
  391. X
  392. X    static struct user_str usrbuf;
  393. X    strncpy(usrbuf.name,ustr,9);           /* name */
  394. X        usrbuf.name[9] = '\0';
  395. X        usrbuf.idle[0] = '\0';
  396. X        usrbuf.gidle[0] = '\0';
  397. X        if ( gflag == 1 )
  398. X       strncpy(usrbuf.tty,ustr + 43,3 );        /* tty */
  399. X        else
  400. X       strncpy(usrbuf.tty,ustr + 30,3 );        /* tty */
  401. X        usrbuf.tty[3] = '\0';
  402. X        if ( gflag == 1 ) {
  403. X/*
  404. X       strncat(usrbuf.gidle,ustr + 35,7); 
  405. X*/
  406. X   /* Idle Time */
  407. X           usrbuf.gidle[0] = ustr[35];
  408. X           usrbuf.gidle[1] = ustr[36];
  409. X           usrbuf.gidle[2] = ustr[37];
  410. X           usrbuf.gidle[3] = ustr[38];
  411. X           usrbuf.gidle[4] = ustr[39];
  412. X           usrbuf.gidle[5] = ustr[40];
  413. X           usrbuf.gidle[6] = ustr[41];
  414. X           usrbuf.gidle[7] = '\0';
  415. X        }
  416. X        else {
  417. X           strncat(usrbuf.idle,ustr + 34,5); 
  418. X        }
  419. X        if ( gflag == 1 ) 
  420. X           strncpy(usrbuf.on, "           ",11);
  421. X        else
  422. X       strncpy(usrbuf.on, ustr+39, 11);       /* On Since */
  423. X        usrbuf.on[11] = '\0';
  424. X    return &usrbuf;    
  425. X}
  426. X
  427. X
  428. X
  429. X
  430. X
  431. X
  432. X/* 
  433. X * Input has the following format:
  434. X * It consists of list of users to be watched.
  435. X * each entry is of
  436. X *    user@host   #comments
  437. X * or
  438. X *    # comments
  439. X */
  440. X
  441. X
  442. X
  443. X
  444. X
  445. X
  446. X
  447. X
  448. Xinit_watched(int argc, char **argv)
  449. X
  450. X
  451. X/*
  452. X   init_watched:
  453. X      effect: copy in user name and host to watch[i] for later use 
  454. X      returns: nothing
  455. X      modifies: structure watched[i]
  456. X*/
  457. X
  458. X
  459. X
  460. X{
  461. X    FILE *wf;
  462. X    char fname[128];
  463. X        char *home;
  464. X        char wherefrom;
  465. X    int index = 0;
  466. X        int argindex = option_past_index();
  467. X    struct hostent *hostp;
  468. X    gethostname(localhost, 256);
  469. X
  470. X        /* check for users listed on command line or an alternative */
  471. X        /* file for .fusers. If neither are present, try to open .fusers */
  472. X
  473. X
  474. X
  475. X        if ( argindex != argc ) {
  476. X            wherefrom = 'c';
  477. X        }
  478. X        else if ( option_present('f') ) {
  479. X            strcpy(fname,option_value('f'));
  480. X            wf = fopen(fname,"r");
  481. X        if(!wf)  {
  482. X        fprintf(stderr,"Cannot open file %s\n",fname);
  483. X        exit(1);
  484. X        }
  485. X            wherefrom = 'f';
  486. X        }
  487. X    else {
  488. X        home = getenv("HOME");
  489. X        if(!home) {
  490. X        fprintf(stderr,"Unable to locate home directory\n");
  491. X        exit(1);
  492. X        }
  493. X        strcpy(fname,home);
  494. X            strcat(fname, WATCHFILE);
  495. X            wf = fopen(fname,"r");
  496. X        if(!wf)  {
  497. X        fprintf(stderr,"No .fusers file\n");
  498. X        exit(1);
  499. X        }
  500. X            wherefrom = 'f';
  501. X        }
  502. X
  503. X
  504. X        /* get user information, parse it and store it */
  505. X
  506. X
  507. X
  508. X        if ( wherefrom == 'c' ) {
  509. X           if ( argindex != argc ) {
  510. X              strcpy(fname,"  ");
  511. X              strcat(fname,argv[argindex++]);
  512. X           }
  513. X           else
  514. X              strcpy(fname,"\0");
  515. X        }
  516. X        else if ( wherefrom = 'f' ) {
  517. X           if (!feof(wf)) {
  518. X              fname[0] = 0;
  519. X              home = fgets(fname, 127, wf);
  520. X        }
  521. X           else
  522. X              strcpy(fname,"\0");
  523. X        }
  524. X    while( strcmp(fname,"\0") != 0 ) {
  525. X         if(fname[0] != '#') {                     /* comment */
  526. X                if ( fname[0] == 'g' || option_present('g') ) 
  527. X                   watched[index].gflag = 1;
  528. X                else
  529. X                   watched[index].gflag = 0;
  530. X        home = strtok(fname+2, " \n");
  531. X        if(home && index < MAXWATCH){
  532. X            char *host = strchr(home,'@');
  533. X            if(host){
  534. X                 *host++ = 0; 
  535. X                 hostp = gethostbyname(host); 
  536. X                 if(!hostp) continue; 
  537. X                strcpy(watched[index].name,home);
  538. X                strcpy(watched[index].host, host);
  539. X            } else {
  540. X                strcpy(watched[index].name,home);
  541. X                strcpy(watched[index].host,localhost);
  542. X                host = localhost;
  543. X            }
  544. X                        strcat(watched[index].host,"\0");
  545. X            index++;
  546. X            home = strtok(NULL," \t\n;,.");
  547. X        }
  548. X             }
  549. X             if ( wherefrom == 'c' ) {
  550. X                if ( argindex != argc ) {
  551. X                   strcpy(fname,"  ");
  552. X                   strcat(fname,argv[argindex++]);
  553. X                }
  554. X                else
  555. X                   strcpy(fname,"\0");
  556. X             }
  557. X             else if ( wherefrom = 'f' ) {
  558. X                if (!feof(wf))  {
  559. X                   fname[0] = 0;
  560. X                   home = fgets(fname, 127, wf);
  561. X                }
  562. X                else
  563. X                   strcpy(fname,"\0");
  564. X             }
  565. X    }
  566. X    watched[index].name[0] = 0;
  567. X    if ( wherefrom == 'f' )
  568. X           fclose(wf);
  569. X}
  570. X
  571. Xmain(int argc, char **argv)
  572. X
  573. X
  574. X/*
  575. X   fusers:
  576. X      effect: print and update a list of users to be watched
  577. X      returns: nothing
  578. X      modfies: nothing
  579. X*/
  580. X
  581. X
  582. X{
  583. X    FILE *fusers;
  584. X    char where[128];
  585. X    struct user_str *ubuf;
  586. X    struct watch *wbuf;
  587. X        char *name1,*name2;
  588. X        char *mail_box = getenv("MAIL");
  589. X    char *newmail;
  590. X    
  591. X    int        i,index,iwin=0,lastwin=0;
  592. X    int        line, col;
  593. X        int        finline;
  594. X        int        c;    
  595. X        int             skip;
  596. X        char        hs[2],m10s[2],m1s[2];
  597. X        int           hour,min10,min1;
  598. X    struct tm    *tm;
  599. X
  600. X
  601. X        /* get command line options, if any and user info */
  602. X
  603. X
  604. X        program_usage_init(argv[0],"[-g -i seconds -I minutes -f file users...]");
  605. X        if (!option_initialize(argc,argv,"g","iIf"))
  606. X           exit(1);
  607. X        if ( option_present('i') )
  608. X            INTERVAL = atoi(option_value('i'));
  609. X        if ( option_present('I') )
  610. X            IDLEMIN = atoi(option_value('I'));
  611. X    init_watched(argc,argv);
  612. X    if(watched[0].name[0] == 0) {
  613. X        fprintf(stderr,"No one to be watched\n");
  614. X        exit(1);
  615. X    }
  616. X    (void) signal(SIGINT, quit);
  617. X    (void) signal(SIGHUP, quit);
  618. X    so_chk();
  619. X    fclose(stderr);
  620. X
  621. X        /* initialize curses */
  622. X
  623. X
  624. X    initscr();
  625. X        nodelay(stdscr,1); 
  626. X        nonl();
  627. X        cbreak();
  628. X    noecho(); 
  629. X        for ( i=0; i<=19 ; i++ )
  630. X          win[i] = newwin(LINES-3,COLS,2,0);
  631. X    ncols = (COLS / COL_WIDTH) - 1; 
  632. X    newmail = " "; 
  633. X
  634. X
  635. X
  636. X
  637. X        /* for each listed user
  638. X           (1) finger the host
  639. X           (2) look for the user
  640. X               (a) if user is on, write info to a page ( window )
  641. X               (b) if user is "all", write info for all users on that host */
  642. X
  643. X
  644. X
  645. X       
  646. X    while (1) {
  647. X           iwin = 0;
  648. X           mvwprintw(win[iwin],0,col*COL_WIDTH," Name      Host:tty  On Since   Idle ");
  649. X           mvwprintw(win[iwin],1,col*COL_WIDTH,"-------------------------------------");   
  650. X           mvwprintw(win[iwin],LINES-4,col*COL_WIDTH,"-------------------------------------"); 
  651. X       line = 2;
  652. X           col = 0;
  653. X       for(index=0; index < MAXWATCH && watched[index].name[0]; index++){
  654. X              char cmdline[4096]; 
  655. X              cmdline[0]='\0';
  656. X              if ( watched[index].gflag == 1)
  657. X                 strcat(cmdline,"finger .local@");
  658. X              else
  659. X                 strcat(cmdline,"finger @");
  660. X          strcat(cmdline,watched[index].host);
  661. X          strcat(cmdline," ");
  662. X          strcat(cmdline,"|sort"); 
  663. X              fusers = popen(cmdline,"r");
  664. X          if(!fusers) {
  665. X             sleep(INTERVAL);
  666. X             continue;
  667. X          }
  668. X              else {
  669. X                 skip = 2;
  670. X                 finline = 1;
  671. X                 while(fgets(where, 128, fusers) != NULL){ 
  672. X                    if ( finline <= skip ) {
  673. X                       finline++;
  674. X                       continue;
  675. X                    }
  676. X                if (line == LINES-4) {
  677. X                   if (col == ncols) {
  678. X                          col = -1;
  679. X                          iwin++;
  680. X                          if ( iwin > 19 ) break;
  681. X                       }
  682. X                   line = 2;
  683. X                   col++;
  684. X                       mvwprintw(win[iwin],0,col*COL_WIDTH," Name      Host:tty  On Since   Idle ");
  685. X                       mvwprintw(win[iwin],1,col*COL_WIDTH,"-------------------------------------");   
  686. X                       mvwprintw(win[iwin],LINES-4,col*COL_WIDTH,"-------------------------------------"); 
  687. X                    } 
  688. X                ubuf = ubreak(where,watched[index].gflag);
  689. X                    name1 = ubuf->name;
  690. X                    name2 = watched[index].name;
  691. X                    if ( watched[index].gflag == 1 ) {
  692. X                    hs[0] = ubuf->gidle[2];
  693. X                    hs[1] = '\0';
  694. X                    m10s[0] = ubuf->gidle[4];
  695. X                    m10s[1] = '\0';
  696. X                    m1s[0] = ubuf->gidle[5];
  697. X                    m1s[1] = '\0';
  698. X                    if ( isspace(ubuf->gidle[2]) || isdigit(ubuf->gidle[2]) )
  699. X                       if ( isspace(ubuf->gidle[2])  )
  700. X                           hour = 0;
  701. X                       else if ( isdigit(ubuf->gidle[2]) )
  702. X/*
  703. X                          hour = atoi(ubuf->gidle[2]);
  704. X*/
  705. X                          hour = atoi(hs);
  706. X                       else
  707. X                           hour = 1 ;
  708. X                    if ( isspace(ubuf->gidle[4]) || isdigit(ubuf->gidle[4]) ) 
  709. X                       if ( isspace(ubuf->gidle[4])  )
  710. X                           min10 = 0;
  711. X                       else if ( isdigit(ubuf->gidle[4]) )
  712. X/*
  713. X                           min10 = atoi(ubuf->gidle[4]);
  714. X*/
  715. X                           min10 = atoi(m10s);
  716. X                       else
  717. X                           min10 = 1 ;
  718. X                    if ( isspace(ubuf->gidle[5])  || isdigit(ubuf->gidle[5]) ) 
  719. X                       if ( isspace(ubuf->gidle[5])  )
  720. X                           min1 = 0;
  721. X                       else if ( isdigit(ubuf->gidle[5]) )
  722. X                           min1 = atoi(m1s);
  723. X                       else
  724. X                           min1 = 1 ;
  725. X                    if ((strncmp(name1,name2,strlen(name2)) == 0)
  726. X                    || (strncmp("all",name2,strlen(name2)) == 0)) {
  727. X                       if ( ( hour == 0 ) && ( min10 == 0 ) && ( min1 <= IDLEMIN ) )
  728. X                      i = 1;
  729. X                   else
  730. X                       i = 0; 
  731. X                   if(i) wstandout(win[iwin]); 
  732. X mvwprintw(win[iwin],line, col*COL_WIDTH, "%8.8s %6.6s:%-3.3s %9.9s %7.7s",ubuf->name,watched[index].host,ubuf->tty,ubuf->on,ubuf->gidle);
  733. X
  734. X                   if(i) wstandend(win[iwin]); 
  735. X                   line++;
  736. X                    }
  737. X                    }
  738. X                    else if ( watched[index].gflag == 0 ) {
  739. X                    if ((strncmp(name1,name2,strlen(name2)) == 0)
  740. X                    || (strncmp("all",name2,strlen(name2)) == 0)) {
  741. X                    if(ubuf->idle[2] == ' ' && atoi(ubuf->idle+3) <= IDLEMIN)
  742. X                      i = 1;
  743. X                   else
  744. X                       i = 0; 
  745. X                   if(i) wstandout(win[iwin]); 
  746. X mvwprintw(win[iwin],line, col*COL_WIDTH, "%8.8s %6.6s:%-3.3s %9.9s   %5.5s",ubuf->name,watched[index].host,ubuf->tty,ubuf->on,ubuf->idle);
  747. X                   if(i) wstandend(win[iwin]); 
  748. X                   line++;
  749. X                    }
  750. X                }
  751. X                 }
  752. X              }
  753. X          pclose(fusers);  
  754. X           }
  755. X
  756. X
  757. X
  758. X
  759. X           /* print out the windows, starting with page one, and 
  760. X              allow the user to page through them. Also check for
  761. X              mail and display the time   */
  762. X
  763. X
  764. X
  765. X
  766. X
  767. X           standout();
  768. X           mvprintw(0,COLS-7,"Page %d",lastwin+1);
  769. X           standend();
  770. X           overwrite(win[lastwin],stdscr);
  771. X           refresh();
  772. X       for(i = INTERVAL; i >= 0; i--){
  773. X            switch(check_mail(mail_box)){
  774. X             case 1: newmail = " You have new mail"; break;
  775. X             case -1: newmail ="                  "; break;
  776. X             default: newmail = 0; break;
  777. X          }
  778. X          if(newmail) mvprintw(0, 20, "%s", newmail);
  779. X          standout();
  780. X          (void) time(&pclock);
  781. X          tm = localtime(&pclock);
  782. X          mvprintw(0, 0, "%.19s", asctime(tm));
  783. X          standend();
  784. X              refresh();
  785. X              if ( iwin > 0 ) {
  786. X                 standout();
  787. X                 if ( 0 == lastwin  ) 
  788. X                    mvprintw(LINES-1,0,"Next Page (>)                     Enter CTRL-C to quit");
  789. X                 else if ( (0 < lastwin) && (lastwin < iwin) ) 
  790. X                    mvprintw(LINES-1,0,"Next Page (>)  Prev Page (<)      Enter CTRL-C to quit");
  791. X                 else if ( lastwin == iwin )
  792. X                    mvprintw(LINES-1,0,"Prev Page (<)                     Enter CTRL-C to quit");
  793. X                 standend();
  794. X                 refresh();
  795. X                 c = getch();
  796. X                 if ( c != ERR ) {
  797. X                    if ((c == '<') && ( lastwin > 0 ) ) 
  798. X                       overwrite(win[--lastwin],stdscr);
  799. X                    else if ( (c == '>') && ( lastwin < iwin ) ) 
  800. X                       overwrite(win[++lastwin],stdscr);
  801. X                    else 
  802. X                       overwrite(win[lastwin],stdscr);
  803. X                 }
  804. X              }
  805. X              standout();
  806. X              mvprintw(0,COLS-7,"Page %d",lastwin+1);
  807. X              standend();
  808. X              refresh();
  809. X              sleep(1);
  810. X          /* sleep(1); */
  811. X       }
  812. X    }
  813. X}
  814. X
  815. X/*
  816. X * quit -- cleanup after interrupt
  817. X *
  818. X *    parameters:
  819. X *        none
  820. X *    returns:
  821. X *        none
  822. X *    side effects:
  823. X *        none
  824. X *    deficiencies:
  825. X */
  826. Xquit()
  827. X{
  828. X
  829. X    (void) signal(SIGINT, SIG_IGN);
  830. X        erase();
  831. X        refresh();
  832. X    endwin();
  833. X    exit(0);
  834. X}
  835. X
  836. X/*
  837. X * so_chk -- check whether terminal inserts blanks with standout mode
  838. X *
  839. X *    parameters:
  840. X *        none
  841. X *    returns:
  842. X *        none
  843. X *    side effects:
  844. X *        sets global variable sg
  845. X *    deficiencies:
  846. X */
  847. Xso_chk()
  848. X{
  849. X    char    tbuf[1024];
  850. X    int    ret_value;
  851. X
  852. X    char    *getenv();
  853. X
  854. X    if ((ret_value = tgetent(tbuf, getenv("TERM"))) != 1) {
  855. X        if (ret_value == 0)    /* no entry */
  856. X            sg = 0;
  857. X        else {
  858. X            fprintf(stderr, "%s: so_chk: can't open /etc/termcap\n", self);
  859. X            exit(1);
  860. X        }
  861. X        return;
  862. X    }
  863. X    if ((sg = tgetnum("sg")) == -1)
  864. X        sg = 0;
  865. X    return;
  866. X}
  867. X
  868. Xint check_mail(mail_box)
  869. Xchar *mail_box;
  870. X{
  871. X        static struct stat last_stat;
  872. X        static int first = 1;
  873. X        struct stat sbuf, *statp;
  874. X
  875. X        if(first){
  876. X                if(stat(mail_box, &last_stat) < 0) return 0;
  877. X                first = 0;
  878. X                statp = &last_stat;
  879. X                if(statp->st_blocks) return 1;
  880. X        } else {
  881. X                if(stat(mail_box, &sbuf) < 0) return 0;
  882. X                statp = &sbuf;
  883. X        }
  884. X        if(statp->st_blocks){
  885. X                if(statp->st_mtime > last_stat.st_mtime){
  886. X                        bcopy(statp, &last_stat, sizeof(struct stat));
  887. X                        return 1;
  888. X                }
  889. X        } else return -1;
  890. X}
  891. X
  892. END_OF_FILE
  893.   if test 16008 -ne `wc -c <'gnufusers.c'`; then
  894.     echo shar: \"'gnufusers.c'\" unpacked with wrong size!
  895.   fi
  896.   # end of 'gnufusers.c'
  897. fi
  898. if test -f 'option.c' -a "${1}" != "-c" ; then 
  899.   echo shar: Will not clobber existing file \"'option.c'\"
  900. else
  901.   echo shar: Extracting \"'option.c'\" \(5269 characters\)
  902.   sed "s/^X//" >'option.c' <<'END_OF_FILE'
  903. Xstatic char rcs[] = "@(#)$Id: option.c,v 1.1 92/02/01 20:20:26 edsall Exp $";
  904. X
  905. X/* option.c
  906. X * Author: Dave Edsall ( edsall@iastate.edu )
  907. X * Date: 9 December 1991
  908. X */
  909. X
  910. X/* option - defines a data structure containing allowed command line options 
  911. X * that the user passes, any associated arguments and whether the option 
  912. X * and its associated arguments appeared on the command line
  913. X *
  914. X *    The following operations are defined on this structure:
  915. X *
  916. X *  option_initialize - stores the allowed options in the structure,
  917. X *                      reads the actual options from the command line,
  918. X *                      determines if the are valid, and records their
  919. X *                      presence and any associated arguments in the
  920. X *                      structure
  921. X *
  922. X *  option_present    - determines if the option was present on the command
  923. X *                      line
  924. X *
  925. X *  option_value      - gets the argument for an option which requires one
  926. X *                      from the data structure
  927. X *
  928. X *  option_past_index - gets the index pointing to the first non-optional
  929. X *                      parameter on the command line
  930. X *
  931. X *
  932. X */
  933. X
  934. X#define TRUE 1
  935. X#define FALSE 0
  936. X#include <stdio.h>
  937. X#include "print_errors.h"
  938. X
  939. X   extern int getopt(int argc, char **argv, char *optstring);
  940. X   extern int optind;
  941. X   extern char *optarg;
  942. X
  943. X   typedef int boolean;
  944. X
  945. X   static struct
  946. X   { char optchar[52];       /* allowed options */
  947. X     char *optarg[52];       /* possible argument associated with the option */
  948. X     boolean present[52];    /* true if the option was on the command line */
  949. X     boolean requiresarg[52];/* true if the option has an argument */
  950. X     int optindex;           /* index to the first non-optional command line */
  951. X                             /* parameter */
  952. X     int numopts;            /* number of allowed options */
  953. X   } options;
  954. X
  955. X   static i = 0;
  956. X
  957. X
  958. Xint option_initialize(int argc, char ** argv, char *noargs, char *argopts)
  959. X     /* requires: argv has at least argc elements */
  960. X     /* modifies: stderr */
  961. X     /* effect: process the options in argv according to the information in
  962. X    noargs and argopts.  If noargs is "rg" and argopts is "xy"
  963. X    then the following calls are legal
  964. X        prog -r -g -x arg1 -y arg2
  965. X        prog -rgx arg1 -y arg2
  966. X        prog -x arg1 -yarg2 -r          <- no g option in this line
  967. X        prog -gr
  968. X        prog -y arg2 -x arg1
  969. X        prog -rgyarg2 -- -z             <- -z not considered an option
  970. X        If the options in argv are not legal, then issue an error message
  971. X    describing at least the first error on the command line to stderr
  972. X    and return false (0); otherwise return true.
  973. X       */
  974. X{
  975. X
  976. X
  977. X    int ii,c;
  978. X    char *temp,temp2,goplist[105];
  979. X    boolean found=FALSE;
  980. X    
  981. X
  982. X
  983. X    /* set up the list of allowed arguments in the format needed by getopt */
  984. X    /* and record them in the data structure */
  985. X
  986. X    temp = goplist;
  987. X    while ( *noargs != '\0' ) {
  988. X      *(temp++) = *noargs;
  989. X      options.optchar[i] = *(noargs++);
  990. X      options.requiresarg[i++] = FALSE;
  991. X    }
  992. X    while ( *argopts != '\0' ) {
  993. X      *(temp++) = *argopts;
  994. X      options.optchar[i] = *(argopts++);
  995. X      options.requiresarg[i++] = TRUE;
  996. X      *(temp++) = ':';
  997. X    }
  998. X    *temp = '\0';
  999. X    i--;
  1000. X    options.numopts=i;
  1001. X
  1002. X    /* get the next command line option */
  1003. X    /* determine if it is allowed */
  1004. X    /* get any required arguments */
  1005. X    /* record that it was present */
  1006. X    
  1007. X    while ((c = getopt(argc, argv, goplist)) != EOF) {
  1008. X       found = FALSE;
  1009. X       for ( ii = 0 ; ii <= i ; ii++ ) { 
  1010. X          if ( options.optchar[ii] == c ) {
  1011. X             options.present[ii] = TRUE;
  1012. X             if ( options.requiresarg[ii] == TRUE ) {
  1013. X                if ( ( strlen(optarg) != 0 ) && ( optarg[0] != '-' ) )
  1014. X                   options.optarg[ii] = optarg;
  1015. X                else 
  1016. X                   usage();
  1017. X         }
  1018. X             found = TRUE;
  1019. X             break;
  1020. X      }
  1021. X       }
  1022. X       if ( !found ) 
  1023. X          usage();
  1024. X    }
  1025. X    options.optindex = optind;
  1026. X    return 1;        
  1027. X
  1028. X}
  1029. X
  1030. Xint option_present(char option)
  1031. X     /* requires: option was one of the characters in the argument noargs
  1032. X    given to option_initialize */
  1033. X     /* effect: return 0 if option was not in the options remembered  by
  1034. X    option_initialize, 1 if it was there */
  1035. X{
  1036. X
  1037. X  int ii;
  1038. X  boolean found = FALSE;
  1039. X
  1040. X  for ( ii = 0 ; ii <= options.numopts ; ii++ ) {
  1041. X     if ( options.optchar[ii] == option ) {
  1042. X        return (int) options.present[ii];
  1043. X        found = TRUE; 
  1044. X        break;
  1045. X     }
  1046. X  }
  1047. X  
  1048. X  if ( !found ) 
  1049. X     usage();
  1050. X  
  1051. X  return 0;
  1052. X
  1053. X}
  1054. X
  1055. Xchar * option_value(char option)
  1056. X     /* requires: option was one of the characters in the argument argopts
  1057. X    given to option_initialize */
  1058. X     /* effect: Return the string argument given on the command line
  1059. X    with option */
  1060. X{
  1061. X
  1062. X  int ii;
  1063. X  boolean found = FALSE;
  1064. X
  1065. X  for ( ii = 0 ; ii <= options.numopts ; ii++ ) {
  1066. X     if ( options.optchar[ii] == option ) {
  1067. X        if ( options.requiresarg[ii] ) {
  1068. X           return options.optarg[ii];
  1069. X           found = TRUE; 
  1070. X           break;
  1071. X    }
  1072. X        else
  1073. X           usage();
  1074. X     }
  1075. X  }
  1076. X  
  1077. X  if ( !found ) 
  1078. X     usage();
  1079. X  
  1080. X  return 0;
  1081. X
  1082. X   
  1083. X}
  1084. X
  1085. Xint option_past_index()
  1086. X     /* effect: return the index into the original argv containing the first
  1087. X    (i.e., lowest numbered) non-optional parameter */
  1088. X{
  1089. X  return options.optindex;
  1090. X}
  1091. X
  1092. X
  1093. X
  1094. X
  1095. X
  1096. X
  1097. X
  1098. X
  1099. X
  1100. END_OF_FILE
  1101.   if test 5269 -ne `wc -c <'option.c'`; then
  1102.     echo shar: \"'option.c'\" unpacked with wrong size!
  1103.   fi
  1104.   # end of 'option.c'
  1105. fi
  1106. if test -f 'option.h' -a "${1}" != "-c" ; then 
  1107.   echo shar: Will not clobber existing file \"'option.h'\"
  1108. else
  1109.   echo shar: Extracting \"'option.h'\" \(261 characters\)
  1110.   sed "s/^X//" >'option.h' <<'END_OF_FILE'
  1111. X
  1112. X/* option.h
  1113. X * Author: Dave Edsall ( edsall@iastate.edu )
  1114. X * Date: 9 December 1991
  1115. X */
  1116. X
  1117. Xint option_initialize(int argc, char ** argv, char *noargs, char *argopts);
  1118. Xint option_present(char option);
  1119. Xchar * option_value(char option);
  1120. Xint option_past_index();
  1121. X
  1122. X
  1123. X
  1124. X
  1125. END_OF_FILE
  1126.   if test 261 -ne `wc -c <'option.h'`; then
  1127.     echo shar: \"'option.h'\" unpacked with wrong size!
  1128.   fi
  1129.   # end of 'option.h'
  1130. fi
  1131. if test -f 'print_errors.c' -a "${1}" != "-c" ; then 
  1132.   echo shar: Will not clobber existing file \"'print_errors.c'\"
  1133. else
  1134.   echo shar: Extracting \"'print_errors.c'\" \(3256 characters\)
  1135.   sed "s/^X//" >'print_errors.c' <<'END_OF_FILE'
  1136. X/* print_errors.c
  1137. X * Author: Dave Edsall ( edsall@iastate.edu )
  1138. X * Date: 9 December 1991
  1139. X */
  1140. X
  1141. X
  1142. X/* print_errors -- routines to print error messages with name of the program
  1143. X *
  1144. X * SYNOPSIS: All output is to standard error
  1145. X *     program_usage_init(argv[0], "options arguments");
  1146. X *     sys_warning("can't open file %s, continuing", f);
  1147. X *     sys_err("can't open file %s", f);
  1148. X *     warning("This is your %drd warning", 3);
  1149. X *     error("you blew it");
  1150. X *     usage();
  1151. X */
  1152. X
  1153. X#include "stdio.h"
  1154. X#include <stdarg.h>
  1155. X#include <stdlib.h>
  1156. X#include <string.h>
  1157. X
  1158. Xstatic char * Name = NULL;
  1159. Xstatic char * Usage = "USAGE NOT DEFINED";
  1160. X
  1161. Xvoid program_usage_init(char *name, char *usage_mesg)
  1162. X     /* effect: initialize the error printing system */
  1163. X{
  1164. X  char * lastslash = strrchr(name, '/');
  1165. X  Name = (lastslash != NULL) ? lastslash+1 : name;
  1166. X  Usage = usage_mesg;
  1167. X}
  1168. X
  1169. Xstatic void print_name(void)
  1170. X     /* effect: if Name is defined, print it, a colon, and a space */
  1171. X{
  1172. X  if (Name) {
  1173. X    fprintf(stderr, "%s: ", Name);
  1174. X  }
  1175. X}
  1176. X
  1177. Xstatic void warn_head(void)
  1178. X     /* effect: if Name is defined, print it, and "Warning: " */
  1179. X{
  1180. X  print_name();
  1181. X  fprintf(stderr, "Warning: ");
  1182. X}
  1183. X
  1184. Xstatic void error_head(void)
  1185. X     /* effect: if Name is defined, print it, and "ERROR: " */
  1186. X{
  1187. X  print_name();
  1188. X  fprintf(stderr, "ERROR: ");
  1189. X}
  1190. X
  1191. Xvoid warning(const char *fmt, ...)
  1192. X     /* effect: print Name (if defined), "Warning: ",
  1193. X    then a message controlled by fmt and the other args,
  1194. X    then a newline on standard error output.
  1195. X      */
  1196. X{
  1197. X  va_list args;
  1198. X
  1199. X  va_start(args, fmt);
  1200. X  warn_head();
  1201. X  vfprintf(stderr, fmt, args);
  1202. X  fprintf(stderr, "\n");
  1203. X  va_end(args);
  1204. X}
  1205. X
  1206. X
  1207. Xvoid error(const char *fmt, ...)
  1208. X     /* effect: print Name (if defined), "Warning: ",
  1209. X    then a message controlled by fmt and the other args,
  1210. X    then a newline on standard error output.
  1211. X      */
  1212. X{
  1213. X  va_list args;
  1214. X
  1215. X  va_start(args, fmt);
  1216. X  error_head();
  1217. X  vfprintf(stderr, fmt, args);
  1218. X  fprintf(stderr, "\n");
  1219. X  va_end(args);
  1220. X
  1221. X  exit(1);
  1222. X}
  1223. X
  1224. X
  1225. Xvoid usage()
  1226. X     /* effect: print usage message on standard error output, and exit(1)
  1227. X      */
  1228. X{
  1229. X  fprintf(stderr, "Usage: %s %s\n", Name, Usage);
  1230. X  exit(1);
  1231. X}
  1232. X
  1233. X#include <errno.h>
  1234. X
  1235. Xextern int sys_nerr;
  1236. Xextern char * sys_errlist[];
  1237. Xextern int errno;
  1238. X
  1239. X
  1240. Xvoid sys_err(const char *fmt, ...)
  1241. X     /* requires: 0 <= errno && errno < sys_nerr */
  1242. X     /* effect: print Name (if defined), "ERROR: ", msg, a colon, a space,
  1243. X        the standard Unix system error message, and a newline
  1244. X        on standard error output, then exit(1).
  1245. X      */
  1246. X{
  1247. X  va_list args;
  1248. X
  1249. X  va_start(args, fmt);
  1250. X  error_head();
  1251. X  vfprintf(stderr, fmt, args);
  1252. X  if (0 <= errno && errno < sys_nerr) {
  1253. X    fprintf(stderr, ": %s", sys_errlist[errno]);
  1254. X  }
  1255. X  fprintf(stderr, "\n");
  1256. X  va_end(args);
  1257. X  exit(1);
  1258. X}
  1259. X
  1260. X
  1261. Xvoid sys_warning(const char *fmt, ...)
  1262. X     /* requires: 0 <= errno && errno < sys_nerr */
  1263. X     /* effect: print Name (if defined), "Warning: ", msg, a colon,
  1264. X        a space, then the standard Unix system error message, and a newline
  1265. X        on standard error output, then exit(1).
  1266. X      */
  1267. X{
  1268. X  va_list args;
  1269. X
  1270. X  va_start(args, fmt);
  1271. X  warn_head();
  1272. X  vfprintf(stderr, fmt, args);
  1273. X  if (0 <= errno && errno < sys_nerr) {
  1274. X    fprintf(stderr, ": %s", sys_errlist[errno]);
  1275. X  }
  1276. X  fprintf(stderr, "\n");
  1277. X  va_end(args);
  1278. X}
  1279. X
  1280. X
  1281. X
  1282. X
  1283. X
  1284. END_OF_FILE
  1285.   if test 3256 -ne `wc -c <'print_errors.c'`; then
  1286.     echo shar: \"'print_errors.c'\" unpacked with wrong size!
  1287.   fi
  1288.   # end of 'print_errors.c'
  1289. fi
  1290. if test -f 'print_errors.h' -a "${1}" != "-c" ; then 
  1291.   echo shar: Will not clobber existing file \"'print_errors.h'\"
  1292. else
  1293.   echo shar: Extracting \"'print_errors.h'\" \(1314 characters\)
  1294.   sed "s/^X//" >'print_errors.h' <<'END_OF_FILE'
  1295. X/* print_errors.h
  1296. X * Author: Dave Edsall ( edsall@iastate.edu )
  1297. X * Date: 9 December 1991
  1298. X */
  1299. X
  1300. Xextern void program_usage_init(char *name, char *usage_mesg);
  1301. X     /* effect: initialize the error printing system */
  1302. X
  1303. Xextern void warning(const char *fmt, ...);
  1304. X     /* effect: print Name (if defined), "Warning: ",
  1305. X    then a message controlled by fmt and the other args,
  1306. X    then a newline on standard error output.
  1307. X      */
  1308. X
  1309. X
  1310. Xextern void error(const char *fmt, ...);
  1311. X     /* effect: print Name (if defined), "Warning: ",
  1312. X    then a message controlled by fmt and the other args,
  1313. X    then a newline on standard error output.
  1314. X      */
  1315. X
  1316. Xextern void usage();
  1317. X     /* effect: print usage message on standard error output, and exit(1)
  1318. X      */
  1319. X
  1320. Xextern void sys_err(const char *fmt, ...);
  1321. X     /* requires: 0 <= errno && errno < sys_nerr */
  1322. X     /* effect: print Name (if defined), "ERROR: ", msg, a colon, a space,
  1323. X        the standard Unix system error message, and a newline
  1324. X        on standard error output, then exit(1).
  1325. X      */
  1326. X
  1327. Xextern void sys_warning(const char *fmt, ...);
  1328. X     /* requires: 0 <= errno && errno < sys_nerr */
  1329. X     /* effect: print Name (if defined), "Warning: ", msg, a colon,
  1330. X        a space, then the standard Unix system error message, and a newline
  1331. X        on standard error output, then exit(1).
  1332. X      */
  1333. X
  1334. END_OF_FILE
  1335.   if test 1314 -ne `wc -c <'print_errors.h'`; then
  1336.     echo shar: \"'print_errors.h'\" unpacked with wrong size!
  1337.   fi
  1338.   # end of 'print_errors.h'
  1339. fi
  1340. echo shar: End of archive 1 \(of 1\).
  1341. cp /dev/null ark1isdone
  1342. MISSING=""
  1343. for I in 1 ; do
  1344.     if test ! -f ark${I}isdone ; then
  1345.     MISSING="${MISSING} ${I}"
  1346.     fi
  1347. done
  1348. if test "${MISSING}" = "" ; then
  1349.     echo You have the archive.
  1350.     rm -f ark[1-9]isdone
  1351. else
  1352.     echo You still must unpack the following archives:
  1353.     echo "        " ${MISSING}
  1354. fi
  1355. exit 0
  1356. exit 0 # Just in case...
  1357.