home *** CD-ROM | disk | FTP | other *** search
- From: cs00chs@unccvax.uncc.edu (charles spell)
- Newsgroups: alt.sources
- Subject: watch.c - A SysV program to display mail, time/date, and users on/off
- Message-ID: <2843@unccvax.uncc.edu>
- Date: 15 Oct 90 23:09:56 GMT
-
-
- Here is a program for SystemV machines to display mail, new mail, the time
- and date and users logging on/off the system on the status line. You must
- put the tsl= and fsl= capabilities into the terminfo database if they do not
- already exist. A future enhancement will use sc= and rc= to put the info
- anywhere on the screen...
-
- Enjoy...
-
- ---cut here----cut here----
- /******************************************************************************
- * This program is freely distributable as long as there has been no changes
- * applied to this file.Bugs, comments, suggestions:uunet!mcnc!unccvax!cs00chs
- * If you find this program useful in part or in whole, please send a
- * contribution to John J. Ribera, Jr.If there is enough monetary interest,
- * fixes and upgrades will be available (see address below).
- */
- #include <signal.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <utmp.h>
- #include <time.h>
- /******************************************************************************
- * NAME
- * watch(1-att) - watch for mail, time, and users logging in (SystemV)
- *
- * SYNOPSIS
- * att watch [users...] [ttylines...] [&]
- *
- * DESCRIPTION
- * watch will notify the you if there is mail, when new mail arrives,
- * display the current time, and notify you of any user logging on or off
- * the system. On dual universe machines this program must be compiled and
- * run in the att universe. The terminal this is run on must have the tsl=
- * and fsl= capabilities to work properly. It helps if ws# is in terminfo
- * also. tsl= is the sequence to go to the status line, fsl= is the
- * sequence to return from status line (cursor position should be restored
- * by this sequence). ws# should be the maximum number of characters that
- * can be displayed on the status line. See your terminal reference manual
- * for these values (and TERMINFO(5) on how to apply them).
- *
- * If there are users and/or ttylines specified on the command line, only
- * those users and/or lines will be checked for logins/logouts, otherwise
- * ANY login/logout will be displayed.
- * To disable watch and clear the status line, use:
- * kill <pid>
- * where <pid> is the process id of the watch program. Do not kill
- * watch(1-att) with a -9 value, i.e., the status line will not be cleared.
- *
- * EXAMPLES
- * watch &
- * - this watches for all users logging in or out of the system.
- *
- * watch jjr smith tty01 tty03 &
- * - this will watch for users with 'jjr' and 'smith' as well as those
- * logging in tty01 and tty03.
- *
- * WARNINGS
- * Be sure to run watch(1) with an att preceeding the watch command on dual
- * universe systems. Be careful not to run watch in the backround more than
- * once. To compile type: cc watch.c -o watch -ltermlib (the att universe
- * on dual universe machines).
- *
- * BUGS
- * Most of the time you will want to execute watch in the backround. The
- * logout seems to be closing the tty faster than the clear status line
- * sequence can be sent in some cases.
- * Try putting this in your .logout: sleep 2
- *
- * AUTHOR
- *
- * clt2!jjr
- * John J. Ribera Jr.
- * 9505-J University Terrace Drive
- * Charlotte, NC 28262
- * Voice: (704) 549-5571
- *
- * If you find this program useful in part or in whole, please send a
- * contribution to John J. Ribera, Jr. If there is enough monetary interest,
- * fixes and upgrades will be available.
- */
-
- #define MAX_PORT 512
- #define UTMP "/etc/utmp"
- #define ST_MAIL 0
- #define ST_DATE 9
- #define ST_LOGIN 26
- #define ST_WIDTH 37
- #define MAIL_DIR "/usr/spool/mail"
-
- #define MAIL " MAIL"
- #define NEW_MAIL "NEW MAIL"
- #define CLR_MAIL " "
-
- char watchfor[2048];
- char St_line[256];
- char Termb[1024];
- char Ts[80];
- char Fs[80];
- short Ws;
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- struct utmp curr[MAX_PORT + 1];
- struct utmp last[MAX_PORT + 1];
- struct stat statb, save_mail;
- long last_mtime;
- long last_time;
- char mailfile[256];
- char *login;
- char *strcpy();
- char *getenv();
- char *getlogin();
- char *ctime();
- char *memcpy();
- char *strstr();
- char **getpwuid();
- short i, j, k, l;
- short watchcnt;
- short read_utmp();
- int memcmp();
- void disp_utmp();
- void disp_chng();
- void done();
-
- signal(SIGINT, done);
- signal(SIGQUIT, done);
- signal(SIGTERM, done);
- signal(SIGHUP, done);
- for (watchfor[0] = '\0', watchcnt = --argc; argc; --argc)
- strcat(strcat(watchfor, *++argv), " ");
- /* Initialize termcaps for going to/from status line and intensity */
- if (tgetent(Termb, getenv("TERM")) != 1)
- fprintf(stderr, "\nUnable to find terminfo data"), exit(1);
- if (!*strcpy(Ts, gettstr("tsl")) || !*strcpy(Fs, gettstr("fsl")))
- fprintf(stderr, "\nNeed status line caps - tsl=, and fsl=."), exit(1);
- if ((Ws = tgetnum("ws")) == -1 && (Ws = tgetnum("co")) == -1)
- Ws = 80;
- /* Initialize everything for loop below...get current utmp entries */
- sprintf(St_line, "%-*.*s", Ws, Ws, "");
- last_time = time((long *) 0);
- memcpy(&St_line[ST_DATE], ctime(&last_time), 16);
- disp_stat(St_line);
- if ((login = getenv("LOGNAME")) == NULL && (login = getenv("USER")) == NULL &&
- (login = getlogin()) == NULL && !*(login = *getpwuid(getuid())))
- fprintf(stderr, "\nUnable to find you"), exit(1);
- sprintf(mailfile, "%s/%s", MAIL_DIR, login);
- l = read_utmp(last);
- if (stat(UTMP, &statb) < 0)
- fprintf(stderr, "\nUnable to stat utmp file."), exit(1);
-
- for (last_mtime = statb.st_mtime; stat(UTMP, &statb) == 0; sleep(1))
- {
- if (statb.st_mtime > last_mtime)
- {
- last_mtime = statb.st_mtime;
- for (i = k = read_utmp(curr); i; i--)
- for (j = l; j; j--)
- if (!watchcnt ||
- (strstr(watchfor, curr[i-1].ut_line) ||
- strstr(watchfor, curr[i-1].ut_user) ||
- strstr(watchfor, last[j-1].ut_line) ||
- strstr(watchfor, last[j-1].ut_user)))
- if (!strcmp(curr[i-1].ut_line, last[j-1].ut_line))
- if (last[j-1].ut_type != curr[i-1].ut_type)
- disp_chng(&last[j-1], &curr[j-1]);
- memcpy(&last, &curr, sizeof(curr));
- l = k;
- }
- if ((last_time / 60) != (time((long *) 0) / 60))
- {
- if (!((last_time = time((long *) 0)) % 3600))
- putchar('\007');
- memcpy(&St_line[ST_DATE], ctime(&last_time), 16);
- disp_stat(St_line);
- }
- if (stat(mailfile, &statb) != 0)
- fprintf(stderr, "Unable to stat %s", mailfile), exit(1);
- if (memcmp(&save_mail, &statb, sizeof(statb)))
- {
- memcpy(&St_line[ST_MAIL], CLR_MAIL, strlen(CLR_MAIL));
- disp_stat(St_line);
- if (statb.st_mtime >= statb.st_atime && statb.st_size > 1)
- {
- memcpy(&St_line[ST_MAIL], NEW_MAIL, strlen(NEW_MAIL));
- putchar('\007');
- }
- else if (statb.st_size > 1)
- memcpy(&St_line[ST_MAIL], MAIL, strlen(MAIL));
- disp_stat(St_line);
- memcpy(&save_mail, &statb, sizeof(statb));
- }
- if (getppid() == 1)
- done();
- }
- }
-
- void
- disp_chng(last, curr)
- struct utmp *last;
- struct utmp *curr;
- {
- if (last->ut_type != USER_PROCESS && curr->ut_type == USER_PROCESS)
- sprintf(&St_line[ST_LOGIN], "%-8.8s on %s", curr->ut_user, curr->ut_line);
- if (last->ut_type == USER_PROCESS && curr->ut_type != USER_PROCESS)
- sprintf(&St_line[ST_LOGIN], "%-8.8s off %s", last->ut_user, last->ut_line);
- memcpy(last, curr, sizeof(*last));
- disp_stat(St_line);
- }
-
- void
- disp_stat(stat_line)
- char *stat_line;
- {
- int outc();
- char hold[256];
-
- tputs(Ts, 1, outc);
- strcpy(hold, stat_line);
- sprintf(stat_line, "%-*.*s", Ws-1, Ws-1, hold);
- fwrite(stat_line, strlen(stat_line), 1, stdout);
- tputs(Fs, 1, outc);
- fflush(stdout);
- }
-
- short
- read_utmp(utmps)
- struct utmp *utmps;
- {
- FILE *fp;
- short i;
-
- if ((fp = fopen(UTMP, "r")) == (FILE *) NULL)
- fprintf(stderr, "\nUnable to read utmp file."), (void)exit(1);
- i = (short) fread(utmps, sizeof(*utmps), MAX_PORT, fp);
- fclose(fp);
- return(i);
- }
- /******************************************************************************
- * strstr - returns pointer in _str_ that contains start of _sub_ (NULL if _sub_
- * not in _str_).
- * Note: I have seen lots of complex code to do the same thing - this is
- * pretty efficient (speedwise).
- */
- char *
- strstr(str, sub) /* some SysV machines do not have this */
- char *str; /* string to search */
- char *sub; /* sub-string for which to search */
- {
- register char *tstr; /* register to speed it up */
- register char *tsub=sub; /* exists only for speed */
-
- while (*str && str && tsub) /* if NULL ptrs skip loop! */
- for (tstr = str++; *tsub == *tstr++; tsub++)
- if (!*tsub)
- return(--str);
- return(NULL);
- }
-
- done()
- {
- disp_stat("");
- exit(0);
- }
-
- char *
- gettstr(id)
- char *id;
- {
- static char tstr[256];
- char *ptr;
-
- ptr = tstr;
- strcpy(tstr, tgetstr(id, &ptr));
- if (ptr == tstr)
- *tstr = '\0';
- return(tstr);
- }
-
- int
- outc(c)
- char c;
- {
- fwrite(&c, 1, 1, stdout);
- }
- ---cut here----cut here----
- --
- .--------------------------. ... |On the border of your mind lies a place
- |uunet!mcnc!unccvax!cs00chs| (") |where dreams and reality are one...I will
- `--------------------------'-w-U-w-|take you there, for I am the subject...
- \%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\|the subject of your imagination. -Aldo Nova
-