home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1958 < prev    next >
Internet Message Format  |  1990-12-28  |  9KB

  1. From: cs00chs@unccvax.uncc.edu (charles spell)
  2. Newsgroups: alt.sources
  3. Subject: watch.c - A SysV program to display mail, time/date, and users on/off
  4. Message-ID: <2843@unccvax.uncc.edu>
  5. Date: 15 Oct 90 23:09:56 GMT
  6.  
  7.  
  8. Here is a program for SystemV machines to display mail, new mail, the time
  9. and date and users logging on/off the system on the status line. You must
  10. put the tsl= and fsl= capabilities into the terminfo database if they do not
  11. already exist. A future enhancement will use sc= and rc= to put the info
  12. anywhere on the screen...
  13.  
  14. Enjoy...
  15.  
  16. ---cut here----cut here----
  17. /******************************************************************************
  18. *  This program is freely distributable as long as there has been no changes
  19. *  applied to this file.Bugs, comments, suggestions:uunet!mcnc!unccvax!cs00chs
  20. *     If you find this program useful in part or in whole, please send a
  21. *     contribution to John J. Ribera, Jr.If there is enough monetary interest,
  22. *     fixes and upgrades will be available (see address below).
  23. */
  24. #include <signal.h>
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <utmp.h>
  29. #include <time.h>
  30. /******************************************************************************
  31. * NAME 
  32. *     watch(1-att) - watch for mail, time, and users logging in (SystemV)
  33. *
  34. * SYNOPSIS
  35. *     att watch [users...] [ttylines...] [&]
  36. *
  37. * DESCRIPTION
  38. *     watch will notify the you if there is mail, when new mail arrives,
  39. *     display the current time, and notify you of any user logging on or off
  40. *     the system. On dual universe machines this program must be compiled and
  41. *     run in the att universe. The terminal this is run on must have the tsl=
  42. *     and fsl= capabilities to work properly. It helps if ws# is in terminfo
  43. *     also. tsl= is the sequence to go to the status line, fsl= is the
  44. *     sequence to return from status line (cursor position should be restored
  45. *     by this sequence). ws# should be the maximum number of characters that
  46. *     can be displayed on the status line. See your terminal reference manual
  47. *     for these values (and TERMINFO(5) on how to apply them).
  48. *
  49. *     If there are users and/or ttylines specified on the command line, only
  50. *     those users and/or lines will be checked for logins/logouts, otherwise
  51. *     ANY login/logout will be displayed.
  52. *     To disable watch and clear the status line, use:
  53. *            kill <pid>
  54. *     where <pid> is the process id of the watch program. Do not kill
  55. *     watch(1-att) with a -9 value, i.e., the status line will not be cleared.
  56. *
  57. * EXAMPLES
  58. *     watch &
  59. *        - this watches for all users logging in or out of the system.
  60. *
  61. *     watch jjr smith tty01 tty03 &
  62. *        - this will watch for users with 'jjr' and 'smith' as well as those
  63. *          logging in tty01 and tty03.
  64. *
  65. * WARNINGS
  66. *     Be sure to run watch(1) with an att preceeding the watch command on dual
  67. *     universe systems. Be careful not to run watch in the backround more than
  68. *     once.  To compile type: cc watch.c -o watch -ltermlib (the att universe
  69. *     on dual universe machines).
  70. *
  71. * BUGS
  72. *     Most of the time you will want to execute watch in the backround. The
  73. *     logout seems to be closing the tty faster than the clear status line  
  74. *     sequence can be sent in some cases.
  75. *     Try putting this in your .logout: sleep 2
  76. *
  77. * AUTHOR
  78. *
  79. *     clt2!jjr
  80. *     John J. Ribera Jr.
  81. *     9505-J University Terrace Drive
  82. *     Charlotte, NC 28262
  83. *     Voice: (704) 549-5571
  84. *
  85. *     If you find this program useful in part or in whole, please send a
  86. *     contribution to John J. Ribera, Jr. If there is enough monetary interest,
  87. *     fixes and upgrades will be available.
  88. */
  89.  
  90. #define MAX_PORT    512
  91. #define    UTMP        "/etc/utmp"
  92. #define    ST_MAIL        0
  93. #define    ST_DATE        9
  94. #define    ST_LOGIN    26
  95. #define    ST_WIDTH    37
  96. #define    MAIL_DIR    "/usr/spool/mail"
  97.  
  98. #define MAIL        "    MAIL"
  99. #define NEW_MAIL    "NEW MAIL"
  100. #define CLR_MAIL    "        "
  101.  
  102. char    watchfor[2048];
  103. char    St_line[256];
  104. char    Termb[1024];
  105. char    Ts[80];
  106. char    Fs[80];
  107. short    Ws;
  108.  
  109. main(argc, argv)
  110. int        argc;
  111. char    **argv;
  112. {
  113. struct    utmp    curr[MAX_PORT + 1];
  114. struct    utmp    last[MAX_PORT + 1];
  115. struct    stat    statb, save_mail;
  116.         long    last_mtime;
  117.         long    last_time;
  118.         char    mailfile[256];
  119.         char    *login;
  120.         char    *strcpy();
  121.         char    *getenv();
  122.         char    *getlogin();
  123.         char    *ctime();
  124.         char    *memcpy();
  125.         char    *strstr();
  126.         char    **getpwuid();
  127.         short    i, j, k, l;
  128.         short    watchcnt;
  129.         short    read_utmp();
  130.         int        memcmp();
  131.         void    disp_utmp();
  132.         void    disp_chng();
  133.         void    done();
  134.  
  135. signal(SIGINT, done);
  136. signal(SIGQUIT, done);
  137. signal(SIGTERM, done);
  138. signal(SIGHUP, done);
  139. for (watchfor[0] = '\0', watchcnt = --argc; argc; --argc)
  140.     strcat(strcat(watchfor, *++argv), " ");
  141. /* Initialize termcaps for going to/from status line and intensity    */
  142. if (tgetent(Termb, getenv("TERM")) != 1)
  143.     fprintf(stderr, "\nUnable to find terminfo data"), exit(1);
  144. if (!*strcpy(Ts, gettstr("tsl")) || !*strcpy(Fs, gettstr("fsl")))
  145.     fprintf(stderr, "\nNeed status line caps - tsl=, and fsl=."), exit(1);
  146. if ((Ws = tgetnum("ws")) == -1 && (Ws = tgetnum("co")) == -1)
  147.     Ws = 80;
  148. /* Initialize everything for loop below...get current utmp entries    */
  149. sprintf(St_line, "%-*.*s", Ws, Ws, "");
  150. last_time = time((long *) 0);
  151. memcpy(&St_line[ST_DATE], ctime(&last_time), 16);
  152. disp_stat(St_line);
  153. if ((login = getenv("LOGNAME")) == NULL && (login = getenv("USER")) == NULL &&
  154.     (login = getlogin()) == NULL && !*(login = *getpwuid(getuid())))
  155.     fprintf(stderr, "\nUnable to find you"), exit(1);
  156. sprintf(mailfile, "%s/%s", MAIL_DIR, login);
  157. l = read_utmp(last);
  158. if (stat(UTMP, &statb) < 0)
  159.     fprintf(stderr, "\nUnable to stat utmp file."), exit(1);
  160.  
  161. for (last_mtime = statb.st_mtime; stat(UTMP, &statb) == 0; sleep(1))
  162.     {
  163.     if (statb.st_mtime > last_mtime)
  164.         {
  165.         last_mtime = statb.st_mtime;
  166.         for (i = k = read_utmp(curr); i; i--)
  167.             for (j = l; j; j--)
  168.                 if (!watchcnt ||
  169.                     (strstr(watchfor, curr[i-1].ut_line) ||
  170.                      strstr(watchfor, curr[i-1].ut_user) ||
  171.                      strstr(watchfor, last[j-1].ut_line) ||
  172.                      strstr(watchfor, last[j-1].ut_user)))
  173.                      if (!strcmp(curr[i-1].ut_line, last[j-1].ut_line))
  174.                         if (last[j-1].ut_type != curr[i-1].ut_type)
  175.                             disp_chng(&last[j-1], &curr[j-1]);
  176.         memcpy(&last, &curr, sizeof(curr));
  177.         l = k;
  178.         }
  179.     if ((last_time / 60) != (time((long *) 0) / 60))
  180.         {
  181.         if (!((last_time = time((long *) 0)) % 3600))
  182.             putchar('\007');
  183.         memcpy(&St_line[ST_DATE], ctime(&last_time), 16);
  184.         disp_stat(St_line);
  185.         }
  186.     if (stat(mailfile, &statb) != 0)
  187.         fprintf(stderr, "Unable to stat %s", mailfile), exit(1);
  188.     if (memcmp(&save_mail, &statb, sizeof(statb)))
  189.         {
  190.         memcpy(&St_line[ST_MAIL], CLR_MAIL, strlen(CLR_MAIL));
  191.         disp_stat(St_line);
  192.         if (statb.st_mtime >= statb.st_atime && statb.st_size > 1)
  193.             {
  194.             memcpy(&St_line[ST_MAIL], NEW_MAIL, strlen(NEW_MAIL));
  195.             putchar('\007');
  196.             }
  197.         else if (statb.st_size > 1)
  198.             memcpy(&St_line[ST_MAIL], MAIL, strlen(MAIL));
  199.         disp_stat(St_line);
  200.         memcpy(&save_mail, &statb, sizeof(statb));
  201.         }
  202.     if (getppid() == 1)
  203.         done();
  204.     }
  205. }
  206.  
  207. void
  208. disp_chng(last, curr)
  209. struct    utmp    *last;
  210. struct    utmp    *curr;
  211. {
  212. if (last->ut_type != USER_PROCESS && curr->ut_type == USER_PROCESS)
  213.     sprintf(&St_line[ST_LOGIN], "%-8.8s on %s", curr->ut_user, curr->ut_line);
  214. if (last->ut_type == USER_PROCESS && curr->ut_type != USER_PROCESS)
  215.     sprintf(&St_line[ST_LOGIN], "%-8.8s off %s", last->ut_user, last->ut_line);
  216. memcpy(last, curr, sizeof(*last));
  217. disp_stat(St_line);
  218. }
  219.  
  220. void
  221. disp_stat(stat_line)
  222. char    *stat_line;
  223. {
  224.     int        outc();
  225.     char    hold[256];
  226.  
  227. tputs(Ts, 1, outc);
  228. strcpy(hold, stat_line);
  229. sprintf(stat_line, "%-*.*s", Ws-1, Ws-1, hold);
  230. fwrite(stat_line, strlen(stat_line), 1, stdout);
  231. tputs(Fs, 1, outc);
  232. fflush(stdout);
  233. }
  234.  
  235. short
  236. read_utmp(utmps)
  237. struct    utmp    *utmps;
  238. {
  239.         FILE    *fp;
  240.         short    i;
  241.  
  242. if ((fp = fopen(UTMP, "r")) == (FILE *) NULL)
  243.     fprintf(stderr, "\nUnable to read utmp file."), (void)exit(1);
  244. i = (short) fread(utmps, sizeof(*utmps), MAX_PORT, fp);
  245. fclose(fp);
  246. return(i);
  247. }
  248. /****************************************************************************** 
  249. * strstr - returns pointer in _str_ that contains start of _sub_ (NULL if _sub_ 
  250. *          not in _str_).
  251. * Note:  I have seen lots of complex code to do the same thing - this is
  252. *        pretty efficient (speedwise).
  253. */
  254. char    *
  255. strstr(str, sub)        /* some SysV machines do not have this    */
  256. char    *str;            /* string to search                        */
  257. char    *sub;            /* sub-string for which to search       */
  258. {
  259. register    char    *tstr;        /* register to speed it up    */
  260. register    char    *tsub=sub;    /* exists only for speed     */
  261.  
  262. while (*str && str && tsub)        /* if NULL ptrs skip loop!    */
  263.     for (tstr = str++; *tsub == *tstr++; tsub++)
  264.         if (!*tsub)
  265.             return(--str);
  266. return(NULL);
  267. }
  268.  
  269. done()
  270. {
  271. disp_stat("");
  272. exit(0);
  273. }
  274.  
  275. char    *
  276. gettstr(id)
  277. char    *id;
  278. {
  279. static    char    tstr[256];
  280.         char    *ptr;
  281.  
  282. ptr = tstr;
  283. strcpy(tstr, tgetstr(id, &ptr));
  284. if (ptr == tstr)
  285.     *tstr = '\0';
  286. return(tstr);
  287. }
  288.  
  289. int
  290. outc(c)
  291. char    c;
  292. {
  293. fwrite(&c, 1, 1, stdout);
  294. }
  295. ---cut here----cut here----
  296. -- 
  297.  .--------------------------.  ...  |On the border of your mind lies a place
  298.  |uunet!mcnc!unccvax!cs00chs|  (")  |where dreams and reality are one...I will 
  299.  `--------------------------'-w-U-w-|take you there, for I am the subject...
  300.  \%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\|the subject of your imagination. -Aldo Nova
  301.