rsalz@uunet.uu.net (Rich Salz) (11/16/88)
Submitted-by: Steven Grimm <koreth@ssyx.ucsc.edu> Posting-number: Volume 16, Issue 84 Archive-name: lumberjack [ I have no idea where the name came from... --r$ ] Enclosed is a program which monitors logfiles. It will alert the user to changes in one of the monitored files when in icon form (described in the manual page). It has been compiled and tested on SunOS 3.4, but should work with more recent versions of SunOS as well. #! /bin/sh # This is a shell archive. Remove anything before the "#! /bin/sh" line, # then unpack it by saving it in a file and typing "sh file." # Contents : Makefile ljack.c ljack.l new1.icon new2.icon none.icon if `test ! -s Makefile` then echo "x - Makefile" cat > Makefile << '@\Rogue\Monster\' LIBS=-lsuntool -lsunwindow -lpixrect CFLAGS=-pipe ljack: ljack.c new1.icon new2.icon none.icon $(CC) $(CFLAGS) -o $@ ljack.c $(LIBS) install: ljack install -s -c ljack /usr/local clean: rm ljack @\Rogue\Monster\ else echo "shar: Will not over write Makefile" fi if `test ! -s ljack.c` then echo "x - ljack.c" cat > ljack.c << '@\Rogue\Monster\' #include <stdio.h> #include <values.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <sys/time.h> #include <suntool/sunview.h> #include <suntool/frame.h> #include <suntool/textsw.h> #include <sunwindow/notify.h> /* * SunView size definitions. I shouldn't have to define these, but * there is no way to query SunView for them. */ #define LMARGIN 5 /* left frame margin */ #define RMARGIN 5 /* right frame margin */ #define BMARGIN 5 /* bottom frame margin */ #define SMARGIN 5 /* subwindow spacing */ Frame frame; int files, updating = 0; Textsw text[16]; /* text subwindows */ Menu menu[16]; /* menus for each subwindow */ char *file[16]; /* filenames */ off_t length[16]; /* file lengths */ char alert[16]; /* flags: blink icon on update? */ /* * Construct the icons. * None.icon is displayed when there are no new files; otherwise, * new1.icon and new2.icon are toggled once a second. */ static short none_icon_i[] = { #include "none.icon" }; mpr_static(none_icon_p, 64, 64, 1, none_icon_i); static short new1_icon_i[] = { #include "new1.icon" }; mpr_static(new1_icon_p, 64, 64, 1, new1_icon_i); static short new2_icon_i[] = { #include "new2.icon" }; mpr_static(new2_icon_p, 64, 64, 1, new2_icon_i); Icon ikes[3]; int inum = 1; int newstuff; main(argc, argv) char **argv; { ikes[0] = icon_create(ICON_IMAGE, &none_icon_p, 0); ikes[1] = icon_create(ICON_IMAGE, &new1_icon_p, 0); ikes[2] = icon_create(ICON_IMAGE, &new2_icon_p, 0); frame = window_create(NULL, FRAME, FRAME_LABEL, "LUMBERJACK 1.0 by Steven Grimm (koreth@ssyx.ucsc.edu)", FRAME_ARGC_PTR_ARGV, &argc, argv, FRAME_SUBWINDOWS_ADJUSTABLE, FALSE, FRAME_ICON, ikes[0], WIN_ERROR_MSG, "Couldn't open window", 0); parse_args(argc, argv); create_subwindows(); set_window_sizes(); load_files(); newstuff = 0; window_set(frame, FRAME_ICON, ikes[0], 0); set_notifier(); window_main_loop(frame); } /* * Create all the necessary subwindows. */ create_subwindows() { int i, domenu(); for (i=0; i<files; i++) { menu[i] = menu_create(MENU_TITLE_ITEM, file[i], MENU_ACTION_ITEM, "Close", domenu, 0); text[i] = window_create(frame, TEXTSW, WIN_ERROR_MSG, "Couldn't create subwindow", WIN_IGNORE_PICK_EVENT, WIN_RESIZE, TEXTSW_DISABLE_CD, TRUE, TEXTSW_DISABLE_LOAD, TRUE, TEXTSW_INSERT_MAKES_VISIBLE, TEXTSW_ALWAYS, TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY, TEXTSW_MENU, menu[i], 0); } } /* * Set all the window sizes. This gets called whenever the base * frame gets resized, and once at initialization. * * For now, all the subwindows are assumed to be of equal size. */ set_window_sizes() { int i, fr_height, fr_width, ts_height, ts_width; fr_height = (int)window_get(frame, WIN_HEIGHT) - (int)window_get(frame, WIN_TOP_MARGIN); fr_width = (int)window_get(frame, WIN_WIDTH) - LMARGIN - RMARGIN; ts_height = fr_height/files - SMARGIN; ts_width = fr_width; for (i=0; i<files; i++) { window_set(text[i], WIN_HEIGHT, ts_height, WIN_WIDTH, ts_width, 0); if (i) window_set(text[i], WIN_BELOW, text[i-1], 0); } } /* * Parse command line arguments. * For now, this is just a list of filenames. */ parse_args(c, v) char **v; { int i, nflag = 0; files = 0; for (i=1; i<c; i++) { if (! strcmp(v[i], "-n")) nflag = 1; else if (access(v[i], R_OK) == 0) { file[files] = v[i]; length[files] = MAXINT; alert[files] = !nflag; nflag = 0; if (++files == 16) break; } else perror(v[i]); } if (! files) exit(1); } /* * Load all the files into their windows, and place the cursors at the * infinity position. This gets called once every second. */ load_files() { int i; struct stat st; for (i=0; i<files; i++) { if (stat(file[i], &st) < 0 || access(file[i], R_OK)) { kill_file(i); continue; } if (st.st_size == length[i]) continue; if (st.st_size < length[i]) /* file has gotten smaller */ window_set(text[i], TEXTSW_FILE, file[i], 0); else if (st.st_size > length[i]) { char *buf; int fd, bsiz; buf = (char *)malloc(bsiz = (st.st_size - length[i])); fd = open(file[i], O_RDONLY); if (fd < 0) { filerror: free(buf); kill_file(i); } if (lseek(fd, length[i], L_SET) < 0) goto filerror; if (read(fd, buf, bsiz) < 0) goto filerror; window_set(text[i], TEXTSW_INSERTION_POINT, TEXTSW_INFINITY, 0); textsw_insert(text[i], buf, bsiz); textsw_possibly_normalize(text[i], (Textsw_index)length[i]); free(buf); } length[i] = st.st_size; if (alert[i]) newstuff++; } if (newstuff) if ((int)window_get(frame, FRAME_CLOSED)) { inum ^= 3; window_set(frame, FRAME_ICON, ikes[inum], 0); } else { newstuff = 0; window_set(frame, FRAME_ICON, ikes[0], 0); } } /* * Handle events. */ Notify_value event(window, event, arg, type) Window window; Event *event; Notify_arg arg; Notify_event_type type; { Notify_value value; value = notify_next_event_func(window, event, arg, type); if (event_id(event) == WIN_RESIZE) set_window_sizes(); return(value); } /* * Handle a menu selection. */ domenu(m, mi) Menu m; Menu_item mi; { int win; for (win = 0; win < files; win++) if (menu[win] == m) break; if (win == files) return; if ((int)menu_get(m, MENU_SELECTED) == 2) kill_file(win); } /* * Kill a file, either because we got an error reading it or because * the user said so. */ kill_file(num) int num; { int i; menu_destroy(menu[num]); window_destroy(text[num]); if (num != files-1) { for (i = num+1; i < files; i++) { menu[i-1] = menu[i]; text[i-1] = text[i]; file[i-1] = file[i]; length[i-1] = length[i]; alert[i-1] = alert[i]; } } if (num == 0) window_set(text[0], WIN_Y, 0, 0); if (--files == 0) exit(0); set_window_sizes(); } /* * Set up a timer. It checks all the files once a second. * Also, tell the notifier what to do about resizes and so forth. */ set_notifier() { static struct itimerval timer; /* this is our handle */ bzero(&timer, sizeof(timer)); timer.it_interval.tv_sec = 1; timer.it_value.tv_sec = 1; notify_set_itimer_func(&timer, load_files, ITIMER_REAL, &timer, NULL); notify_interpose_event_func(frame, event, NOTIFY_SAFE); } @\Rogue\Monster\ else echo "shar: Will not over write ljack.c" fi if `test ! -s ljack.l` then echo "x - ljack.l" cat > ljack.l << '@\Rogue\Monster\' .TH LJACK LOCAL "2 September 1988" .SH NAME ljack \- monitor system logs .SH SYNOPSIS .B ljack [ -n ] file1 [[ -n ] file2 ... ] .SH DESCRIPTION .I Ljack (short for "lumberjack") runs under the SunView windowing environment. It monitors one or more logfiles, optionally alerting the user when an update takes place. The .BR file s specified on the command line should be readable by the user; if a file is not readable, no subwindow will be created for it. .PP .IR Ljack 's display is organized into a number of equal-sized subwindows, one for each .B file. The subwindows are standard text-editing windows (see .IR textedit (1)) that can be scrolled and searched as usual. New information is added to the appropriate subwindow as it appears in a .B file, and the display scrolls to show the new data if necessary. .PP If .I ljack is in icon form when a .B file is updated, an animated axe chops at the log in the icon to inform the user that something new has arrived. The axe disappears when the icon is opened and closed again. .PP Up to sixteen .BR file s can be viewed; in some versions of SunOS (3.x and lower) there are not enough file descriptors to view more than six files. .SH OPTION .IP \fB\-n\fR If a .B file is preceded by a \-n argument, the axe will not appear when the .B file is updated. .SH AUTHOR Steven Grimm, koreth@ssyx.ucsc.edu .SH "SEE ALSO" textedit(1), suntools(1) @\Rogue\Monster\ else echo "shar: Will not over write ljack.l" fi if `test ! -s new1.icon` then echo "x - new1.icon" cat > new1.icon << '@\Rogue\Monster\' /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x01FF,0x0000,0x0000,0x0000,0x060F,0xFC00,0x0000,0x0000, 0x09F3,0xFFF8,0x0000,0x0000,0x1209,0xFFFF,0xE000,0x0000, 0x24E4,0xF7FF,0xFFC0,0x0000,0x2B1A,0xFFFF,0xFFF8,0x0000, 0x5209,0x7FF7,0xFFFC,0x0000,0x5445,0x77FF,0xFFBE,0x0000, 0x54A5,0x7FFF,0xFFFE,0x0000,0x5445,0x7FFF,0xFBFE,0x0000, 0x5209,0x7FFF,0xDFFE,0x0000,0x2B1A,0xFDFB,0x9FFE,0x0000, 0x24E4,0xFFFF,0x1EFC,0x0000,0x1209,0xFFFE,0x1FF8,0x0000, 0x09F3,0xBFBC,0x0FF0,0x0000,0x060F,0xFFF8,0x0C00,0x0000, 0x01FF,0xE010,0x0400,0x0000,0x0000,0x001E,0x0300,0x0000, 0x0000,0x0001,0xC180,0x0000,0x0000,0x0000,0xB0C0,0x0000, 0x0000,0x0000,0x98C0,0x0000,0x0000,0x0001,0x1D00,0x0000, 0x0000,0x0002,0x2600,0x0000,0x0000,0x0004,0x2000,0x0000, 0x0000,0x0004,0x4000,0x0000,0x0000,0x0008,0x8000,0x0000, 0x0000,0x0011,0x0000,0x0000,0x0000,0x0021,0x0000,0x0000, 0x0000,0x0022,0x0000,0x0000,0x0000,0x0044,0x0000,0x0000, 0x0000,0x0088,0x0000,0x0000,0x0000,0x0090,0x0000,0x0000, 0x0000,0x0110,0x0000,0x0000,0x0000,0x0220,0x0000,0x0000, 0x0000,0x0440,0x0000,0x0000,0x0000,0x0480,0x0000,0x0000, 0x0000,0x0880,0x0000,0x0000,0x0000,0x1100,0x0000,0x0000, 0x0000,0x2200,0x0000,0x0000,0x0000,0x2400,0x0000,0x0000, 0x0000,0x4400,0x0000,0x0000,0x0000,0x2800,0x0000,0x0000, 0x0000,0x1000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x1000,0x0400,0x0040,0x0040,0x1049,0xA70C,0x5003,0x0E48, 0x1049,0x5492,0x68C0,0x9050,0x1049,0x549C,0x4043,0x9060, 0x1059,0x5490,0x4044,0x9050,0x1E29,0x570E,0x4042,0x8E48, 0x0000,0x0000,0x0180,0x0000,0x0000,0x0000,0x0000,0x0000 @\Rogue\Monster\ else echo "shar: Will not over write new1.icon" fi if `test ! -s new2.icon` then echo "x - new2.icon" cat > new2.icon << '@\Rogue\Monster\' /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x01FF,0x0000,0x0000,0x0000,0x060F,0xFC00,0x0000,0x0000, 0x09F3,0xFFF8,0x0000,0x0000,0x1209,0xFFFF,0xE000,0x0000, 0x24E4,0xF7FF,0xFFC0,0x0000,0x2B1A,0xFFFF,0xFFF8,0x0000, 0x5209,0x7FF7,0xFFFC,0x0000,0x5445,0x77FF,0xFFBE,0x0000, 0x54A5,0x7FFF,0xFFFE,0x0000,0x5445,0x7FFF,0xFBFE,0x0000, 0x5209,0x7FFF,0xFFFE,0x0000,0x2B1A,0xFDFB,0xFFFE,0x0000, 0x24E4,0xFFFF,0xFEFC,0x0000,0x1209,0xFFFF,0xFFF8,0x0000, 0x09F3,0xBFBF,0xFFF0,0x0000,0x060F,0xFFFF,0x0000,0x0000, 0x01FF,0xE000,0x0000,0x0000,0x0000,0x0000,0x0038,0x0000, 0x0000,0x0000,0x00C8,0x0000,0x0000,0x0000,0x0310,0x0000, 0x0000,0x0000,0x0C10,0x0000,0x0000,0x0000,0x3010,0x0000, 0x0000,0x0000,0x3810,0x0000,0x0000,0x0000,0x0610,0x0000, 0x0000,0x0000,0x0118,0x0000,0x0000,0x0000,0x0108,0x0000, 0x0000,0x0000,0x0684,0x0000,0x0000,0x0000,0x0884,0x0000, 0x0000,0x0000,0x3066,0x0000,0x0000,0x0000,0x4198,0x0000, 0x0000,0x0001,0x8210,0x0000,0x0000,0x0002,0x0C00,0x0000, 0x0000,0x000C,0x3000,0x0000,0x0000,0x0010,0x4000,0x0000, 0x0000,0x0061,0x8000,0x0000,0x0000,0x0082,0x0000,0x0000, 0x0000,0x030C,0x0000,0x0000,0x0000,0x0410,0x0000,0x0000, 0x0000,0x1860,0x0000,0x0000,0x0000,0x2180,0x0000,0x0000, 0x0000,0x2200,0x0000,0x0000,0x0000,0x1C00,0x0000,0x0000, 0x0000,0x1000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x1000,0x0400,0x0040,0x0040,0x1049,0xA70C,0x5003,0x0E48, 0x1049,0x5492,0x68C0,0x9050,0x1049,0x549C,0x4043,0x9060, 0x1059,0x5490,0x4044,0x9050,0x1E29,0x570E,0x4042,0x8E48, 0x0000,0x0000,0x0180,0x0000,0x0000,0x0000,0x0000,0x0000 @\Rogue\Monster\ else echo "shar: Will not over write new2.icon" fi if `test ! -s none.icon` then echo "x - none.icon" cat > none.icon << '@\Rogue\Monster\' /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 */ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x01FF,0x0000,0x0000,0x0000,0x060F,0xFC00,0x0000,0x0000, 0x09F3,0xFFF8,0x0000,0x0000,0x1209,0xFFFF,0xE000,0x0000, 0x24E4,0xF7FF,0xFFC0,0x0000,0x2B1A,0xFFFF,0xFFF8,0x0000, 0x5209,0x7FF7,0xFFFC,0x0000,0x5445,0x77FF,0xFFBE,0x0000, 0x54A5,0x7FFF,0xFFFE,0x0000,0x5445,0x7FFF,0xFBFE,0x0000, 0x5209,0x7FFF,0xFFFE,0x0000,0x2B1A,0xFDFB,0xFFFE,0x0000, 0x24E4,0xFFFF,0xFEFC,0x0000,0x1209,0xFFFF,0xFFF8,0x0000, 0x09F3,0xBFBF,0xFFF0,0x0000,0x060F,0xFFFF,0x0000,0x0000, 0x01FF,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x1000,0x0400,0x0040,0x0040,0x1049,0xA70C,0x5003,0x0E48, 0x1049,0x5492,0x68C0,0x9050,0x1049,0x549C,0x4043,0x9060, 0x1059,0x5490,0x4044,0x9050,0x1E29,0x570E,0x4042,0x8E48, 0x0000,0x0000,0x0180,0x0000,0x0000,0x0000,0x0000,0x0000 @\Rogue\Monster\ else echo "shar: Will not over write none.icon" fi # to concatenate archives, remove anything after this line exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.