v10i037: contool -- replacement for 'cmdtool -C', Part04/06
Chuck Musciano
chuck at melmac.harris-atd.com
Tue Oct 30 17:26:36 AEST 1990
Submitted-by: chuck at melmac.harris-atd.com (Chuck Musciano)
news at trantor.harris-atd.com (News stuff)
Posting-number: Volume 10, Issue 37
Archive-name: contool/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 at 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 at 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) 729-2537
A good newspaper is never good enough,
but a lousy newspaper is a joy forever. -- Garrison Keillor
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list