mcgrew@aramis.rutgers.edu (Charles Mcgrew) (09/26/90)
Submitted-by: chuck@trantor.harris-atd.com (Chuck Musciano) Posting-number: Volume 2, Issue 23 Archive-name: contool3.0/part04 #! /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 archive 4 (of 6)." # Contents: contool.c # Wrapped by chuck@melmac on Fri Aug 17 10:00:53 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'contool.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'contool.c'\" else echo shar: Extracting \"'contool.c'\" \(19504 characters\) sed "s/^X//" >'contool.c' <<'END_OF_FILE' X/************************************************************************/ X/* Copyright 1988-1990 by Chuck Musciano and Harris Corporation */ X/* */ X/* Permission to use, copy, modify, and distribute this software */ X/* and its documentation for any purpose and without fee is */ X/* hereby granted, provided that the above copyright notice */ X/* appear in all copies and that both that copyright notice and */ X/* this permission notice appear in supporting documentation, and */ X/* that the name of Chuck Musciano and Harris Corporation not be */ X/* used in advertising or publicity pertaining to distribution */ X/* of the software without specific, written prior permission. */ X/* Chuck Musciano and Harris Corporation make no representations */ X/* about the suitability of this software for any purpose. It is */ X/* provided "as is" without express or implied warranty. This */ X/* software may not be sold without the prior explicit permission */ X/* of Harris Corporation. */ X/************************************************************************/ X X/************************************************************************/ X/* */ X/* contool.c main contool driver */ X/* */ X/************************************************************************/ X X#include <stdio.h> X#include <fcntl.h> X#include <strings.h> X#include <sys/ioctl.h> X#include <sys/file.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/param.h> X X#include <X11/Xlib.h> X X#include <xview/xview.h> X#include <xview/icon.h> X#include <xview/panel.h> X#include <xview/textsw.h> X#include <xview/xv_xrect.h> X X#include "manifest.h" X#include "contool.h" X#include "contool_ui.h" X X#define update_value(old, new) ((old) = ((new) > (old))? (new) : (old)) X X#define INPUT_BUFFER_SIZE 4096 X XEXPORT Attr_attribute INSTANCE; X XEXPORT contool_base_objects *contool_base; XEXPORT char *filter_file; X XPUBLIC Server_image load_icon(); X XPRIVATE short good_bits[] = { X#include "icons/default_good.icon" X }; XPRIVATE short bad_bits[] = { X#include "icons/default_bad.icon" X }; XPRIVATE short flash_bits[] = { X#include "icons/default_flash.icon" X }; XPRIVATE short mask_bits[] = { X#include "icons/mask.icon" X }; X XPRIVATE char *ct_usage = "usage: contool [-c <file>] [-l] [-L <file>]\n"; X XPRIVATE Server_image default_good_icon, good = NULL; XPRIVATE Server_image default_bad_icon, bad = NULL; XPRIVATE Server_image default_flash_icon, flash = NULL; XPRIVATE Server_image icon_mask; X XPRIVATE int bad_is_up; XPRIVATE int beep_count; XPRIVATE int blinking = FALSE; XPRIVATE FILE *command = NULL; XPRIVATE Filter *curr_filter = NULL; XPRIVATE int event_in_progress = FALSE; XPRIVATE int explicit_filters = FALSE; XPRIVATE int masking_works; XPRIVATE FILE *master = NULL; XPRIVATE int old_time = 0; XPRIVATE char *program; XPRIVATE FILE *slave = NULL; X XPRIVATE struct itimerval timer = {{0, 500000}, {0, 500000}}; X X/************************************************************************/ X/* Manage piping console output to a command */ X/************************************************************************/ X X/************************************************************************/ XPRIVATE start_command(cmd) X Xchar *cmd; X X{ X if (command) X pclose(command); X if ((command = popen(cmd, "w")) == NULL) X internal_error("could not execute \"%s\"", cmd); X} X X/************************************************************************/ XPRIVATE continue_command(buf) X Xchar *buf; X X{ X if (command) X fprintf(command, buf); X} X X/************************************************************************/ XPRIVATE end_command() X X{ X if (command) X pclose(command); X} X X/************************************************************************/ X/* Some basic console utility routines */ X/************************************************************************/ X X/************************************************************************/ XEXPORT acquire_console() X X{ X if (ioctl(fileno(slave), TIOCCONS, NULL) == -1) X abend("%s: could not attach to /dev/console", program); X} X X/************************************************************************/ XEXPORT stop_blinking() X X{ Icon icon; X X notify_set_itimer_func(contool_base->base, NULL, ITIMER_REAL, NULL, NULL); X icon = (Icon) xv_get(contool_base->base, FRAME_ICON); X xv_set(icon, ICON_IMAGE, good, NULL); X xv_set(contool_base->base, FRAME_ICON, icon, 0); X blinking = FALSE; X} X X/************************************************************************/ XEXPORT filters_changed() X X{ X curr_filter = NULL; X xv_set(contool_base->base, FRAME_LEFT_FOOTER, "", NULL); X end_command(); X} X X/************************************************************************/ X/* Various small features */ X/************************************************************************/ X X/************************************************************************/ XEXPORT Menu_item print_messages(item, op) X XMenu_item item; XMenu_generate op; X X{ int size; X char *buf; X FILE *cmd; X X if (op == MENU_NOTIFY) { X if (is_empty(defaults.print_filter)) X error("You must specify a printer command in the Properties dialog"); X else if ((cmd = popen(defaults.print_filter, "w")) == NULL) X error("Could not execute %s", defaults.print_filter); X else { X xv_set(contool_base->base, FRAME_BUSY, TRUE, NULL); X size = (int) xv_get(contool_base->display, TEXTSW_LENGTH); X buf = (char *) malloc(size); X xv_get(contool_base->display, TEXTSW_CONTENTS, 0, buf, size); X if (fwrite(buf, 1, size, cmd) != size) X error("Could not write console contents to printer"); X pclose(cmd); X xv_set(contool_base->base, FRAME_BUSY, FALSE, NULL); X } X } X return item; X} X X/************************************************************************/ XEXPORT Menu_item become_console(item, op) X XMenu_item item; XMenu_generate op; X X{ X if (op == MENU_NOTIFY) X acquire_console(); X return item; X} X X/************************************************************************/ XEXPORT Menu_item clear_messages(item, op) X XMenu_item item; XMenu_generate op; X X{ X if (op == MENU_NOTIFY) { X textsw_reset(contool_base->display, 0, 0); X old_time = 0; X } X return item; X} X X/************************************************************************/ XEXPORT Menu_item reset_filter(item, op) X XMenu_item item; XMenu_generate op; X X{ X if (op == MENU_NOTIFY) X filters_changed(); X return item; X} X X/************************************************************************/ XPRIVATE change_icon(image, use_mask) X XServer_image image; Xint use_mask; X X{ Icon icon; X X icon = (Icon) xv_get(contool_base->base, FRAME_ICON); X xv_set(icon, X ICON_IMAGE, image, X XV_WIDTH, (int) xv_get(image, XV_WIDTH), X XV_HEIGHT, (int) xv_get(image, XV_HEIGHT), X NULL); X if (masking_works && use_mask) X xv_set(icon, ICON_MASK_IMAGE, icon_mask, NULL); X xv_set(contool_base->base, FRAME_ICON, icon, NULL); X} X X/************************************************************************/ XEXPORT update_icons() X X{ char msg[1024]; X X if (good && good != default_good_icon) X xv_destroy(good); X if (bad && bad != default_bad_icon) X xv_destroy(bad); X if (flash && flash != default_flash_icon) X xv_destroy(flash); X X good = (defaults.good_icon == NULL)? default_good_icon : load_icon(defaults.good_icon, msg); X bad = (defaults.bad_icon == NULL)? default_bad_icon : load_icon(defaults.bad_icon, msg); X flash = (defaults.flash_icon == NULL)? default_flash_icon : load_icon(defaults.flash_icon, msg); X X if (!blinking) X change_icon(good, good == default_good_icon); X} X X/************************************************************************/ X/* Now, filter handlers */ X/************************************************************************/ X X/************************************************************************/ XPRIVATE internal_message(a, b, c, d, e, f) X Xint a, b, c, d, e, f; X X{ char buf[1024]; X X sprintf(buf, a, b, c, d, e, f); X time_stamp(); X write_log(buf); X do_insertion(buf, strlen(buf)); X} X X/************************************************************************/ XPRIVATE internal_error(a, b, c, d, e, f) X Xint a, b, c, d, e, f; X X{ char buf[1024]; X X sprintf(buf, a, b, c, d, e, f); X time_stamp(); X fprintf(stderr, "*** %s: %s\n", program, buf); X} X X/************************************************************************/ XPRIVATE load_filters() X X{ struct stat sb; X static int load_time = 0; X X if (access(filter_file, R_OK) == -1) { X if (explicit_filters && load_time == 0) { X internal_error("filter file %s cannot be accessed", filter_file); X load_time = 1; X } X } X else if (stat(filter_file, &sb) == 0 && sb.st_mtime > load_time) X if (lex_init(filter_file)) { X yyparse(); X if (!parse_errors_occured) { X free_list(filters); X free(parsed_defaults); X filters = parsed_filters; X internal_message("*** filters loaded from %s\n", filter_file); X load_time = sb.st_mtime; X } X } X else { X internal_error("error accessing configuration file %s", filter_file); X load_time = 1; X } X} X X/************************************************************************/ X/* Various event handlers for the console frame */ X/************************************************************************/ X X/************************************************************************/ XPRIVATE Notify_value blink_proc(me, which) X Xint *me; Xint which; X X{ X if (event_in_progress) X return(NOTIFY_DONE); X if (beep_count > 0) { X window_bell(contool_base->base); X beep_count--; X } X if (blinking) { X if (bad_is_up) X change_icon(flash, flash == default_flash_icon); X else X change_icon(bad, bad == default_bad_icon); X bad_is_up = !bad_is_up; X } X if (beep_count == 0 && !blinking) X notify_set_itimer_func(contool_base->base, blink_proc, ITIMER_REAL, NULL, NULL); X return(NOTIFY_DONE); X} X X/************************************************************************/ XPRIVATE Notify_value close_proc(frame, event, arg, type) X XFrame frame; XEvent *event; XNotify_arg arg; XNotify_event_type type; X X{ X event_in_progress = TRUE; X if (event_action(event) == ACTION_OPEN && blinking) { X notify_set_itimer_func(contool_base->base, blink_proc, ITIMER_REAL, NULL, NULL); X change_icon(good, good = default_good_icon); X blinking = FALSE; X } X event_in_progress = FALSE; X return(notify_next_event_func(frame, event, arg, type)); X} X X/************************************************************************/ XPRIVATE Notify_value destroy_proc(frame, status) X XFrame frame; XDestroy_status status; X X{ X if (status == DESTROY_CHECKING) { X textsw_reset(contool_base->display, 0, 0); X return(NOTIFY_DONE); X } X else X return(notify_next_destroy_func(frame, status)); X} X X/************************************************************************/ X/* Routines which handle capturing and displaying messages */ X/************************************************************************/ X X/************************************************************************/ XPRIVATE do_insertion(buf, len) X Xchar *buf; Xint len; X X{ int first, last, sw_len; X char *temp; X X while ((int) xv_get(contool_base->display, TEXTSW_LENGTH) + len > defaults.max_size) { X first = 1; X last = TEXTSW_INFINITY; X if (textsw_find_bytes(contool_base->display, &first, &last, "\n<<<", 4, 0) == -1) X if (textsw_find_bytes(contool_base->display, &first, &last, "\n", 1, 0) == -1) X first = defaults.delete_amount; X textsw_erase(contool_base->display, 0, first + 1); X sw_len = (int) xv_get(contool_base->display, TEXTSW_LENGTH); X temp = (char *) malloc((unsigned) sw_len); X xv_get(contool_base->display, TEXTSW_CONTENTS, 0, temp, sw_len); X textsw_reset(contool_base->display, 0, 0); X textsw_insert(contool_base->display, temp, sw_len); X free(temp); X } X xv_set(contool_base->display, TEXTSW_INSERTION_POINT, TEXTSW_INFINITY, 0); X textsw_insert(contool_base->display, buf, len); X} X X/************************************************************************/ XPRIVATE time_stamp() X X{ int t, pos; X char buf[5]; X X t = time(0); X if (t - old_time >= defaults.stamp_resolution) { X xv_set(contool_base->display, TEXTSW_INSERTION_POINT, TEXTSW_INFINITY, 0); X pos = (int) xv_get(contool_base->display, TEXTSW_LENGTH); X if (pos != 0) { X xv_get(contool_base->display, TEXTSW_CONTENTS, pos - 1, buf, 1); X if (buf[0] != '\n') X do_insertion("\n", 1); X } X do_insertion("\n<<< ", 5); X do_insertion(ctime(&t), 24); X do_insertion(" >>>\n", 5); X old_time = t; X } X} X X/************************************************************************/ XPRIVATE Notify_value input_func(me, fd) X Xint *me; Xint fd; X X{ char old_c, *s, *t, buf[1024]; X Filter *f; X int count, do_blink = FALSE, do_open = FALSE; X static char in_buf[INPUT_BUFFER_SIZE + 2]; X X while ((count = read(fileno(master), in_buf, INPUT_BUFFER_SIZE)) >= 0) { X in_buf[count] = '\0'; X while (s = index(in_buf, '\015')) { X strcpy(s, s + 1); X count--; X } X for (t = in_buf; *t; *s = old_c, t = s) { X if (s = index(t, '\n')) { X old_c = *++s; X *s = '\0'; X } X else { X s = t + strlen(t); X old_c = '\0'; X } X if (!defaults.log_after) X write_log(t); X if (curr_filter == NULL) { X load_filters(); X for (f = filters; f; f = f->next) X if (f->start_re && match_exp(f->start_re, f->start_circf, t)) { X if (f->save) { X update_value(do_blink, f->flash); X update_value(beep_count, f->beep); X update_value(do_open, f->open); X if (f->stamp) X time_stamp(); X do_insertion(t, strlen(t)); X if (f->command) { X start_command(f->command); X continue_command(t); X if (f->stop == NULL) X end_command(); X } X if (defaults.log_after) X write_log(t); X } X if (f->stop) { X curr_filter = f; X sprintf(buf, "Filtering \"%s\"...", f->start); X xv_set(contool_base->base, FRAME_LEFT_FOOTER, buf, NULL); X } X break; X } X if (f == NULL) { X if (defaults.stamp) X time_stamp(); X if (defaults.command) { X start_command(defaults.command); X continue_command(t); X end_command(); X } X if (defaults.log_after) X write_log(t); X do_insertion(t, strlen(t)); X update_value(do_blink, defaults.flash); X update_value(do_open, defaults.open); X update_value(beep_count, defaults.beep); X } X } X else { X if (curr_filter->save) { X if (curr_filter->stamp) X time_stamp(); X if (defaults.log_after) X write_log(t); X do_insertion(t, strlen(t)); X if (curr_filter->command) X continue_command(t); X } X if (match_exp(curr_filter->stop_re, curr_filter->stop_circf, t)) { X xv_set(contool_base->base, FRAME_LEFT_FOOTER, "", NULL); X if (curr_filter->command) X end_command(); X curr_filter = NULL; X } X } X } X } X xv_set(contool_base->display, TEXTSW_UPDATE_SCROLLBAR, 0); X if (do_open) X xv_set(contool_base->base, FRAME_CLOSED, FALSE, 0); X if (do_blink) X if (xv_get(contool_base->base, FRAME_CLOSED) && !blinking) { X change_icon(bad, bad == default_bad_icon); X xv_set(contool_base->base, WIN_SHOW, TRUE, 0); X blinking = TRUE; X bad_is_up = TRUE; X notify_set_itimer_func(contool_base->base, blink_proc, ITIMER_REAL, &timer, NULL); X } X if (beep_count > 0 || blinking) X notify_set_itimer_func(contool_base->base, blink_proc, ITIMER_REAL, &timer, NULL); X return(NOTIFY_DONE); X} X X/************************************************************************/ X/* Routines which parse options, create windows, and main() */ X/************************************************************************/ X X/************************************************************************/ XPRIVATE parse_options(argc, argv) X Xint *argc; Xchar **argv; X X{ char *s, c, path[1024], *log_file = NULL; X int log = FALSE; X X sprintf(path, "%s/.contool", getenv("HOME")); X filter_file = strsave(path); X X while ((c = getopt(argc, argv, "c:lL:?", &s)) != EOF) X switch (c) { X case 'c' : filter_file = expand_tilde(s); X explicit_filters = TRUE; X break; X case 'l' : log = TRUE; X break; X case 'L' : log_file = expand_tilde(s); X break; X case '?' : fprintf(stderr, ct_usage); X exit(0); X break; X default : fprintf(stderr, ct_usage); X exit(1); X } X X if (lex_init(filter_file)) { X yyparse(); X if (parsed_defaults) X defaults = *parsed_defaults; X if (log_file) X defaults.log_file = log_file; X if (log) X enable_logging(); X } X else if (explicit_filters) X error("Could not read configuration file %s", filter_file); X} X X/************************************************************************/ Xmain(argc, argv) X Xint argc; Xchar **argv; X X{ char buf[1024], *path, *open_psuedo_tty(); X int i; X XWindowAttributes attr; X X program = strsave(argv[0]); X X path = open_psuedo_tty(&master, "r", &slave, "w"); X if (master == NULL) X abend("%s: couldn't open any psuedo-tty", program); X if (slave == NULL) X abend("%s: couldn't open slave side of %s", program, path); X X i = fcntl(fileno(master), F_GETFL, 0); X i |= FNDELAY; X if (fcntl(fileno(master), F_SETFL, i) == -1) X abend("%s: could not force %s to non-blocking i/o", program); X X acquire_console(path); X X xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, 0); X INSTANCE = xv_unique_key(); X X contool_base = contool_base_objects_initialize(NULL, NULL); X default_good_icon = (Server_image) xv_create(NULL, SERVER_IMAGE, X XV_WIDTH, 64, X XV_HEIGHT, 64, X SERVER_IMAGE_BITS, good_bits, X NULL); X default_bad_icon = (Server_image) xv_create(NULL, SERVER_IMAGE, X XV_WIDTH, 64, X XV_HEIGHT, 64, X SERVER_IMAGE_BITS, bad_bits, X NULL); X default_flash_icon = (Server_image) xv_create(NULL, SERVER_IMAGE, X XV_WIDTH, 64, X XV_HEIGHT, 64, X SERVER_IMAGE_BITS, flash_bits, X NULL); X icon_mask = (Server_image) xv_create(NULL, SERVER_IMAGE, X XV_WIDTH, 64, X XV_HEIGHT, 64, X SERVER_IMAGE_BITS, mask_bits, X NULL); X disable_logging(contool_base); X X XGetWindowAttributes(xv_get(contool_base->base, XV_DISPLAY), xv_get(xv_get(contool_base->base, XV_ROOT), XV_XID), &attr); X masking_works = (attr.depth > 1); X X parse_options(&argc, argv); X load_filters(); X update_icons(); X X notify_set_input_func(contool_base->base, input_func, fileno(master)); X notify_interpose_destroy_func(contool_base->base, destroy_proc); X notify_interpose_event_func(contool_base->base, close_proc, NOTIFY_SAFE); X X xv_main_loop(contool_base->base); X exit(0); X} END_OF_FILE if test 19504 -ne `wc -c <'contool.c'`; then echo shar: \"'contool.c'\" unpacked with wrong size! fi # end of 'contool.c' fi echo shar: End of archive 4 \(of 6\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 Chuck Musciano ARPA : chuck@trantor.harris-atd.com Harris Corporation Usenet: ...!uunet!x102a!trantor!chuck PO Box 37, MS 3A/1912 AT&T : (407) 727-6131 Melbourne, FL 32902 FAX : (407) 727-{5118,5227,4004} I'm glad you asked, son. Being popular is the most important thing in the world. -- Homer Simpson