From 63351ac66772542ebe1f4b38936f7ed9fd43e9b9 Mon Sep 17 00:00:00 2001 From: mdw Date: Tue, 15 Dec 1998 23:46:50 +0000 Subject: [PATCH] New program: captures input and puts it in a window. --- xcatch.1 | 46 ++++++++++ xcatch.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 xcatch.1 create mode 100644 xcatch.c diff --git a/xcatch.1 b/xcatch.1 new file mode 100644 index 0000000..c9d91d8 --- /dev/null +++ b/xcatch.1 @@ -0,0 +1,46 @@ +.TH xcatch 1 "15 December 1998" "Edgeware tools" +.SH NAME +xcatch \- catch input and trap it in a window +.SH SYNOPSIS +.B xcatch +.RB [ \-f +.IR file ] +.RB [ \-F +.IR font ] +.RI [ command +.RI [ args ]...] +.SH DESCRIPTION +The +.B xcatch +program watches an input file descriptor (usually a pipe) and displays +data from it in a GTK window. The window is displayed only when data is +first read from the descriptor; if no data ever arrives, the window is +not created. If a file is specified using the +.B \-f +option, it is read; otherwise, if a +.I command +is specified, it is executed with standard output and standard error +redirected to +.BR xcatch ; +otherwise, +.B xcatch +reads from its own standard input. +.SS OPTIONS +.TP +.BI "\-\-display " display +Create the window on the named +.IR display . +.TP +.BI "\-f, \-\-file " file +Read data from +.I file +instead of standard output. +.TP +.BI "\-F, \-\-font " font +Display output text in +.I font +rather than GTK's default (Helvetica). +.SH AUTHOR +Mark Wooding (mdw@nsict.org). +.SH BUGS +None currently known. diff --git a/xcatch.c b/xcatch.c new file mode 100644 index 0000000..cf9608b --- /dev/null +++ b/xcatch.c @@ -0,0 +1,308 @@ +/* -*-c-*- + * + * $Id: xcatch.c,v 1.1 1998/12/15 23:46:50 mdw Exp $ + * + * Catch input and trap it in an X window + * + * (c) 1998 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the Edgeware X tools collection. + * + * X tools is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * X tools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with X tools; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: xcatch.c,v $ + * Revision 1.1 1998/12/15 23:46:50 mdw + * New program: captures input and puts it in a window. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +/*----- Inportant state ---------------------------------------------------*/ + +static unsigned int flags; + +enum { + f_closed = 1, + f_bogus = 2 +}; + +GtkWidget *textbox = 0; +GdkFont *font; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- The window's closed --- */ + +static void killwin(GtkWidget *w, gpointer p) +{ + if (flags & f_closed) + gtk_main_quit(); + else + textbox = 0; +} + +/* --- Some input has arrived --- */ + +static void ready(gpointer data, gint fd, GdkInputCondition c) +{ + char buf[1024]; + int count; + + /* --- Read the next buffer of data --- */ + + if (!(c & GDK_INPUT_READ)) + return; + count = read(fd, buf, sizeof(buf)); + + /* --- Decide what to do --- */ + + if (count < 0) { + msg(":~OK", "error reading data: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + if (count == 0) { + close(fd); + if (textbox) + flags |= f_closed; + else + gtk_main_quit(); + return; + } + + /* --- If there's no output window, create one --- */ + + if (!textbox) { + GtkWidget *win; + GtkWidget *t; + GtkWidget *w; + + win = gtk_dialog_new(); + gtk_signal_connect(GTK_OBJECT(win), "destroy", + GTK_SIGNAL_FUNC(killwin), 0); + + t = gtk_table_new(2, 2, 0); + gtk_container_border_width(GTK_CONTAINER(t), 8); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), t, 1, 1, 0); + gtk_widget_show(t); + + textbox = gtk_text_new(0, 0); + gtk_table_attach(GTK_TABLE(t), textbox, 0, 1, 0, 1, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, + 0, 0); + gtk_text_set_editable(GTK_TEXT(textbox), 0); + gtk_widget_set_usize(textbox, 500, 100); + gtk_widget_show(textbox); + + w = gtk_vscrollbar_new(GTK_TEXT(textbox)->vadj); + gtk_table_attach(GTK_TABLE(t), w, 1, 2, 0, 1, + 0, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show(w); + + w = gtk_hscrollbar_new(GTK_TEXT(textbox)->hadj); + gtk_table_attach(GTK_TABLE(t), w, 0, 1, 1, 2, + GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0, 0); + gtk_widget_show(w); + + gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(win)->action_area), 0); + w = gtk_button_new_with_label("Dismiss"); + gtk_signal_connect_object(GTK_OBJECT(w), "clicked", + GTK_SIGNAL_FUNC(gtk_object_destroy), + GTK_OBJECT(win)); + gtk_box_pack_end(GTK_BOX(GTK_DIALOG(win)->action_area), w, 0, 0, 0); + GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT); + gtk_widget_grab_default(w); + cancel(GTK_WINDOW(win), w); + gtk_widget_show(w); + + gtk_widget_show(win); + } + + /* --- Append the new text --- */ + + gtk_text_insert(GTK_TEXT(textbox), font, 0, 0, buf, count); +} + +/* --- Signal handler --- */ + +static void reap(int sig) +{ + while (waitpid(-1, 0, WNOHANG) > 0) + ; +} + +/* --- Main program --- */ + +static void version(FILE *fp) +{ + fprintf(fp, "%s (xtoys version " VERSION ")\n", QUIS); +} + +static void usage(FILE *fp) +{ + fprintf(fp, "Usage: %s [-f file] [-F font] [command [args...]]\n", QUIS); +} + +int main(int argc, char *argv[]) +{ + int fd = -1; + + ego(argv[0]); + + gtk_init(&argc, &argv); + + for (;;) { + static struct option opt[] = { + { "help", 0, 0, 'h' }, + { "usage", 0, 0, 'u' }, + { "version", 0, 0, 'v' }, + { "file", gFlag_argReq, 0, 'f' }, + { "font", gFlag_argReq, 0, 'F' }, + { 0, 0, 0, 0 } + }; + int i = mdwopt(argc, argv, "huvf:F:", opt, 0, 0, 0); + + if (i < 0) + break; + + switch (i) { + case 'h': + version(stdout); + fputc('\n', stdout); + usage(stdout); + fputs( +"\n" +"Catches input from a pipe or other source, and captures it in a window.\n" +"Nothing is displayed if there's no input.\n" +"\n" +"Options provided:\n" +"\n" +"-h, --help Display this help text\n" +"-u, --usage Display a quick usage summary\n" +"-v, --version Display the version number\n" +"-f, --file=FILE Read input from the named file\n" +"-F, --font=FONT Display output in the named font\n", + stdout); + exit(0); + break; + case 'u': + usage(stdout); + exit(0); + break; + case 'v': + version(stdout); + exit(0); + break; + case 'f': + if ((fd = open(optarg, O_RDONLY)) < 0) { + die(1, "couldn't open file: %s", strerror(errno)); + exit(1); + } + break; + case 'F': + font = gdk_font_load(optarg); + break; + default: + flags |= f_bogus; + break; + } + } + + if (flags & f_bogus) { + usage(stderr); + exit(1); + } + + if (fd == -1) { + if (optind == argc) + fd = STDIN_FILENO; + else { + int pfd[2]; + pid_t kid; + struct sigaction sa; + + /* --- Set up a signal handler --- */ + + sa.sa_handler = reap; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGCHLD, &sa, 0); + + /* --- Start a child program --- */ + + if (pipe(pfd)) + die(1, "couldn't open pipe: %s", strerror(errno)); + kid = fork(); + if (kid < 0) + die(1, "couldn't fork: %s", strerror(errno)); + if (kid == 0) { + dstr d; + + close(pfd[0]); + if (pfd[1] != STDOUT_FILENO) + dup2(pfd[1], STDOUT_FILENO); + if (pfd[1] != STDERR_FILENO) + dup2(pfd[1], STDERR_FILENO); + if (pfd[1] != STDOUT_FILENO && pfd[1] != STDERR_FILENO) + close(pfd[1]); + execvp(argv[optind], argv + optind); + + dstr_create(&d); + dstr_putf(&d, "%s: couldn't run `%s': %s\n", + QUIS, argv[optind], strerror(errno)); + write(STDERR_FILENO, d.buf, d.len); + _exit(127); + } + fd = pfd[0]; + close(pfd[1]); + } + } + + gdk_input_add(fd, GDK_INPUT_READ, ready, 0); + gtk_main(); + return (0); +} + +/*----- That's all, folks -------------------------------------------------*/ -- 2.11.0