New program: captures input and puts it in a window.
authormdw <mdw>
Tue, 15 Dec 1998 23:46:50 +0000 (23:46 +0000)
committermdw <mdw>
Tue, 15 Dec 1998 23:46:50 +0000 (23:46 +0000)
xcatch.1 [new file with mode: 0644]
xcatch.c [new file with mode: 0644]

diff --git a/xcatch.1 b/xcatch.1
new file mode 100644 (file)
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 (file)
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 <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <gtk/gtk.h>
+
+#include <mLib/dstr.h>
+#include <mLib/mdwopt.h>
+#include <mLib/report.h>
+#include <mLib/quis.h>
+
+#include <mgLib/cancel.h>
+#include <mgLib/msg.h>
+
+/*----- 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 -------------------------------------------------*/