dwd@cbnewsc.ATT.COM (david.w.dykstra) (05/10/89)
This is another version of xtail, enhanced to do everything I wanted it to do to watch HDB uucp logfiles. Enhancements: 1. Ability to watch all files within a directory; if a new file appears, watch it too. 2. Ability to silently ignore files that are missing. 3. Performance enhancements. This version uses the opendir-readdir-closedir functions which are standard on System V Release 3. Public Domain versions of these functions are available (I could send you a copy if you'd like), otherwise it should be fairly easy to modify xtail for your system. - Dave Dykstra AT&T Bell Labs, Skokie, IL dwd@ttrdf.att.com att!ttrdf!dwd dykstra@cs.uiuc.edu --------cut here-------------------------------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Makefile ulog.1 ulog xtail.1 xtail.c # Wrapped by dwd@ttrdf on Wed May 10 10:50:12 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(175 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' XINSBIN = $(HOME)/bin X XCFLAGS = -O X Xxtail: xtail.o X cc -o xtail xtail.o X Xinstall: xtail X cp xtail $(INSBIN) X strip $(INSBIN)/xtail X cp ulog $(INSBIN) X chmod +x $(INSBIN)/ulog X END_OF_FILE if test 175 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'ulog.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ulog.1'\" else echo shar: Extracting \"'ulog.1'\" \(495 characters\) sed "s/^X//" >'ulog.1' <<'END_OF_FILE' X.TH ULOG 1L X.SH NAME Xulog - watch HDB uucp log files X.SH SYNOPSIS X.B ulog X[machine_name] ... X.SH DESCRIPTION X.I ulog Xmonitors Honey-Dan-Ber uucp log files and displays any new information Xwritten into them. If no machine_name is given, it will monitor Xuucp interactions between all other machines; otherwise only those Xmachines specified will be watched. When switching logfiles, a banner Xshowing the log file name is printed. X.SH SEE ALSO Xxtail(1) X.SH AUTHOR XDave Dykstra (dwd@ttrdf.att.com) END_OF_FILE if test 495 -ne `wc -c <'ulog.1'`; then echo shar: \"'ulog.1'\" unpacked with wrong size! fi # end of 'ulog.1' fi if test -f 'ulog' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ulog'\" else echo shar: Extracting \"'ulog'\" \(306 characters\) sed "s/^X//" >'ulog' <<'END_OF_FILE' X# tail all interesting HDB log files using xtail X# Dave Dykstra, 5/8/89 X Xcase $# in X 0) cd /usr/spool/uucp X DIRS=".Log .Admin" X ;; X *) cd /usr/spool/uucp/.Log X DIRS="" X for ARG X do X for DIR in uucico uucp uux uuxqt X do X DIRS="$DIRS $DIR/$ARG" X done X done X ;; Xesac X Xexec xtail -i $DIRS END_OF_FILE if test 306 -ne `wc -c <'ulog'`; then echo shar: \"'ulog'\" unpacked with wrong size! fi chmod +x 'ulog' # end of 'ulog' fi if test -f 'xtail.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xtail.1'\" else echo shar: Extracting \"'xtail.1'\" \(1018 characters\) sed "s/^X//" >'xtail.1' <<'END_OF_FILE' X.TH XTAIL 1L X.SH NAME Xxtail - Watch the growth of files. X.SH SYNTAX X.B xtail X[-i] file_or_directory ... X.SH DESCRIPTION X.I Xtail Xmonitors one or more files, and displays all data written to the file since Xcommand invocation. When switching files in the display, a banner showing Xthe pathname of the file is printed. This command is most useful for monitoring Xmultiple logfiles simultaneously. If a file turns out to be the directory Xis monitored so if any new files appear they will also be monitored. If Xthe "-i" option is specified, missing files will be silently ignored. X.P XAfter a period of inactivity on the files being monitored, X.I Xtail Xreduces the frequency of checking for changes, so response may be slower Xat that time. Currently it checks every second until there is no Xactivity for thirty seconds, and then it backs off to checking every Xten seconds until there is activity again. X.SH SEE ALSO Xtail(1), ulog(1) X.SH AUTHORS XChip Rosenthal (chip@vector.Dallas.TX.US) XDave Dykstra (dwd@ttrdf.att.com) END_OF_FILE if test 1018 -ne `wc -c <'xtail.1'`; then echo shar: \"'xtail.1'\" unpacked with wrong size! fi # end of 'xtail.1' fi if test -f 'xtail.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xtail.c'\" else echo shar: Extracting \"'xtail.c'\" \(5563 characters\) sed "s/^X//" >'xtail.c' <<'END_OF_FILE' X/* X * xtail - monitor the growth of files X * X * usage: xtail file_or_directory ... X * X * Mon May 1 14:44:30 1989 - Chip Rosenthal <chip@vector.Dallas.TX.US> X * Original composition. X * Mon May 8 13:02:22 CDT 1989 - Dave Dykstra <dwd@ttrdf.attcom> X * Modified to monitor all files in directories. X * Added -i option. X * Performance enhancements. X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/fcntl.h> X#include <dirent.h> X X#define MAXFILES 128 /* max number of files to watch */ X#define SLEEPTIME 1 /* time between checks, in seconds */ X#define BACKOFFCOUNT 30 /* number of SLEEPTIME intervals of */ X /* inactivity to count before backing */ X /* off to BACKTIME time between checks */ X#define BACKOFFTIME 10 /* time between checks when backed off */ X Xint Nfiles; /* number of files being watched */ Xint Lastfile; /* Flist[] index of last file displayed */ Xint Ignore; /* Silently ignore missing files */ X Xstruct { X char *name; /* path to file, or NULL for no file */ X struct stat sbuf; /* recent stat info on this file */ X} Flist[MAXFILES]; X Xchar Buf[BUFSIZ]; /* general buffer */ X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int fd, ifile, argi; X int s, n; X long pos; X int backoffcount; X struct stat sbuf; X extern long lseek(); X extern unsigned sleep(); X X /* X * Initialize. X */ X Nfiles = 0; /* no files specified */ X Lastfile = -1; /* no files printed */ X X argi = 1; X if ((argc >= 2) && (strcmp(argv[1],"-i") == 0)) { X Ignore = 1; X argi++; X } X else X Ignore = 0; X X /* X * Get files from command line. Save in list and get initial stat info. X */ X for ( ; argi < argc ; ++argi ) { X if ( Nfiles >= MAXFILES ) { X fprintf(stderr,"%s: too many files\n",argv[0]); X exit(1); X } X if ( stat(Flist[Nfiles].name=argv[argi],&Flist[Nfiles].sbuf) != 0 ) { X if ( Ignore ) { X Flist[Nfiles].sbuf.st_mtime = 0; X Flist[Nfiles].sbuf.st_size = 0; X ++Nfiles; X } X else X perror(Flist[Nfiles].name); X } X else { X ++Nfiles; X if ( Flist[Nfiles-1].sbuf.st_mode & S_IFDIR ) X getdirfiles( Flist[Nfiles-1].name, 0 ); X } X } X if ( Nfiles == 0 ) { X fprintf(stderr,"Usage: xtail [-i] file_or_directory ...\n"); X exit(1); X } X X /* X * Loop forever. X */ X backoffcount = BACKOFFCOUNT; X for (;;) { X X /* X * Go through each file in the list. X */ X for ( ifile = 0 ; ifile < Nfiles ; ++ifile ) { X X /* X * Skip entries removed from list. X */ X if ( Flist[ifile].name == NULL ) X continue; X X /* X * Stat the file. Skip it if nothing has changed. X */ X if ( stat(Flist[ifile].name,&sbuf) != 0 ) { X if ( Ignore ) { X Flist[ifile].sbuf.st_mtime = 0; X Flist[ifile].sbuf.st_size = 0; X } X else { X perror(Flist[ifile].name); X Flist[ifile].name = NULL; X } X continue; X } X if ( Flist[ifile].sbuf.st_mtime == sbuf.st_mtime ) X continue; X X if ( Flist[ifile].sbuf.st_mode & S_IFDIR ) { X /* X * A directory has changed, read it again. X */ X getdirfiles(Flist[ifile].name, 1); X Flist[ifile].sbuf.st_mtime = sbuf.st_mtime; X continue; X } X X if ( Flist[ifile].sbuf.st_size == sbuf.st_size ) X continue; X X if ( sbuf.st_size != 0 ) { X /* X * Open the file. X */ X if ( (fd=open(Flist[ifile].name,O_RDONLY)) < 0 ) { X if (!Ignore) { X perror(Flist[ifile].name); X Flist[ifile].name = NULL; X } X continue; X } X X /* X * Display banner if we are switching files. X */ X if ( Lastfile != ifile ) X printf("***** %s *****\n",Flist[ifile].name); X X /* X * Dump the recently added info. X */ X if ( (pos=Flist[ifile].sbuf.st_size) > 0 ) X (void) lseek(fd,pos,0); X X for (s = sbuf.st_size - pos; s > 0; s -= n) { X if ( (n = read(fd, Buf, (s > BUFSIZ) ? BUFSIZ : s) ) <= 0 ) X perror(Flist[ifile].name); X else X fwrite(Buf, n, 1, stdout); X } X X (void) close(fd); X Lastfile = ifile; X } X Flist[ifile].sbuf.st_mtime = sbuf.st_mtime; X Flist[ifile].sbuf.st_size = sbuf.st_size; X X /* X * Set the back-off counter back to maximum since something happend. X */ X backoffcount = BACKOFFCOUNT; X X } /* next file in list */ X X if (backoffcount == 0) X (void) sleep(BACKOFFTIME); X else { X --backoffcount; X (void) sleep(SLEEPTIME); X } X } /* next iteration */ X X /*NOTREACHED*/ X X} X Xgetdirfiles(dirname, watchnew) Xchar *dirname; Xint watchnew; X{ X DIR *dirp; X struct dirent *dp; X int i; X char *malloc(); X X if ((dirp = opendir(dirname)) == NULL) { X fprintf(stderr, "xtail: Cannot open %s directory\n", dirname); X return; X } X X while((dp = readdir(dirp)) != NULL) { X X if (dp->d_name[0] == '.') X /* skip files beginning with a dot */ X continue; X X for (i = 0; i < Nfiles; i++) { X strcpy(Buf, dirname); X strcat(Buf, "/"); X strcat(Buf, dp->d_name); X X if (strcmp(Buf, Flist[i].name) == 0) X break; X } X if (i < Nfiles) X /* it's an old file */ X continue; X X if (stat(Buf, &Flist[Nfiles].sbuf) != 0 ) X perror(Buf); X else { X if ((Flist[Nfiles].name = malloc(strlen(Buf)+1)) == NULL) { X fprintf(stderr,"xtail: no space\n"); X exit(1); X } X strcpy(Flist[Nfiles].name, Buf); X X ++Nfiles; X if (Flist[Nfiles-1].sbuf.st_mode & S_IFDIR) X /* recursive call on sub-directory */ X getdirfiles(Flist[Nfiles-1].name, watchnew); X else if (watchnew) { X /* it's a new file, make sure first lines get printed out */ X Flist[Nfiles-1].sbuf.st_mtime = 0; X Flist[Nfiles-1].sbuf.st_size = 0; X } X } X } X closedir(dirp); X} END_OF_FILE if test 5563 -ne `wc -c <'xtail.c'`; then echo shar: \"'xtail.c'\" unpacked with wrong size! fi # end of 'xtail.c' fi echo shar: End of shell archive. exit 0