Initial versions.
authormdw <mdw>
Mon, 16 Nov 1998 23:04:38 +0000 (23:04 +0000)
committermdw <mdw>
Mon, 16 Nov 1998 23:04:38 +0000 (23:04 +0000)
17 files changed:
.cvsignore [new file with mode: 0644]
.links [new file with mode: 0644]
.skelrc [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
README [new file with mode: 0644]
configure.in [new file with mode: 0644]
xgetline.1 [new file with mode: 0644]
xgetline.c [new file with mode: 0644]
xscsize.1 [new file with mode: 0644]
xscsize.c [new file with mode: 0644]
xshutdown.1 [new file with mode: 0644]
xshutdown.c [new file with mode: 0644]
xtell.1 [new file with mode: 0644]
xtell.c [new file with mode: 0644]
xwait.1 [new file with mode: 0644]
xwait.c [new file with mode: 0644]
xwait.h [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..378eac2
--- /dev/null
@@ -0,0 +1 @@
+build
diff --git a/.links b/.links
new file mode 100644 (file)
index 0000000..68709e4
--- /dev/null
+++ b/.links
@@ -0,0 +1,6 @@
+COPYING
+install-sh
+mdwopt.c
+mdwopt.h
+missing
+mkinstalldirs
diff --git a/.skelrc b/.skelrc
new file mode 100644 (file)
index 0000000..73f6f57
--- /dev/null
+++ b/.skelrc
@@ -0,0 +1,8 @@
+;;; -*-emacs-lisp-*-
+
+(setq skel-alist
+      (append
+       '((full-title . "the Edgeware X tools collection")
+        (program . "X tools")
+        (author . "Straylight/Edgeware"))
+       skel-alist))
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..10b4835
--- /dev/null
@@ -0,0 +1,57 @@
+## -*-makefile-*-
+##
+## $Id: Makefile.am,v 1.1 1998/11/16 23:00:49 mdw Exp $
+##
+## Makefile for X tools
+##
+## (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: Makefile.am,v $
+## Revision 1.1  1998/11/16 23:00:49  mdw
+## Initial versions.
+##
+
+AUTOMAKE_OPTIONS = foreign
+
+bin_PROGRAMS = xwait xtell xscsize @GTK_PROGS@
+EXTRA_PROGRAMS = xshutdown xgetline
+man_MANS = xwait.1 xtell.1 xshutdown.1 xscsize.1 xgetline.1
+EXTRA_DIST = $(man_MANS)
+
+xshutdown_SOURCES = xshutdown.c xwait.h mdwopt.c mdwopt.h
+xshutdown_LDADD = @GTK_LIBS@
+
+xgetline_SOURCES = xgetline.c mdwopt.c mdwopt.h
+xgetline_LDADD = @GTK_LIBS@
+
+xwait_SOURCES = xwait.c xwait.h
+xwait_LDADD = @X_LIBS@ -lX11
+
+xtell_SOURCES = xtell.c xwait.h
+xtell_LDADD = @X_LIBS@ -lX11
+
+xscsize_SOURCES = xscsize.c
+xscsize_LDADD = @X_LIBS@ -lX11
+
+##----- That's all, folks ---------------------------------------------------
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..705c58c
--- /dev/null
+++ b/README
@@ -0,0 +1,82 @@
+X tools, -*-text-*-
+
+
+       This is just a small collection of small X-based toys.  There's
+       nothing especially clever here, just some stuff I've found to be
+       useful.  It's a bit of a mixed bag, really; just saves me some
+       effort if I package them all up together.  The collection may
+       grow in future, if I can be bothered to write any more X toys.
+
+       A couple of the toys require GTK.  Sorry: I like GTK and I don't
+       want to play with Athena or Xt or anything like that again,
+       because they're nasty.
+
+       The tools are described more fully in the accompanying manual
+       pages.  There's not much to know about any of them, though.
+
+
+xgetline
+
+       Pops up a little window (with configurable text in it) asking
+       the user to type in a piece of text, and then writes it to
+       stdout.  It's useful when a shell script wants to solicit a
+       string from the user, and particularly handy in window manager
+       config files.  You can also turn off echo of the string being
+       typed in, which may be useful for input of passwords, but that's
+       not ever-so recommended.
+
+       The basic idea is that you say something like
+
+               if name=`xgetline -p Name`; then
+                 echo "Hello, $name, pleased to meet you!"
+               else
+                 echo "You're no fun, are you?"
+               fi
+
+       and everything is lovely.
+
+
+xscsize
+
+       Returns the size of an X display.  The idea is that you can do
+       something like
+
+               eval `xscsize`
+
+       in a `.xinitrc' file and then play with XWIDTH and XHEIGHT to
+       decide exactly where to put various windows depending on how big
+       the screen is.  This sort of thing is quite handy if you use the
+       same setup on lots of different systems or screens.
+
+
+xwait, xtell, xshutdown
+
+       The traditional thing to do at the end of a `.xinitrc' file is
+       to wait for the window manager to exit.  This is unhelpful when
+       the window manager doesn't like its configuration file, for
+       example, because your entire session goes away.  The idea
+       (filched shamelessly from SGI, actually) is to end the script
+       with a program which hangs around until told to go away by
+       another X client.  (I could have used any old IPC mechanism
+       here, but it seemed silly to use something other than X.)
+
+       The manual pages provide the low-level detail.  Basically,
+       though, you run `xwait', and it sleeps.  When you run `xtell',
+       it tells the `xwait' program to kill itself.  `xshutdown' does
+       essentially the same thing, only it pops up a pretty window
+       asking you if you're sure before it does it.
+
+
+Notes and things
+
+       All the code here is released under the GNU General Public
+       License (included in the file COPYING in the distribution).
+
+       I tested the code under Linux and not much else, but I'm usually
+       fairly conservative about portability and there shouldn't be
+       much hassle involved.
+
+       If anyone wants to do an Xaw version of the GTK bits then I'll
+       include that in the distribution; people using Motif or Qt need
+       not apply.
+
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..c0b0dc8
--- /dev/null
@@ -0,0 +1,54 @@
+dnl -*-fundamental-*-
+dnl
+dnl $Id: configure.in,v 1.1 1998/11/16 23:00:49 mdw Exp $
+dnl
+dnl Configuration script for X tools
+dnl
+dnl (c) 1998 Straylight/Edgeware
+dnl
+
+dnl ----- Licensing notice --------------------------------------------------
+dnl
+dnl This file is part of the Edgeware X tools collection.
+dnl
+dnl X tools is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl 
+dnl X tools is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl GNU General Public License for more details.
+dnl 
+dnl You should have received a copy of the GNU General Public License
+dnl along with X tools; if not, write to the Free Software Foundation,
+dnl Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+dnl ----- Revision history --------------------------------------------------
+dnl
+dnl $Log: configure.in,v $
+dnl Revision 1.1  1998/11/16 23:00:49  mdw
+dnl Initial versions.
+dnl
+
+AC_INIT(xwait.c)
+AM_INIT_AUTOMAKE(xtoys, 1.0)
+AC_PROG_CC
+mdw_GCC_FLAGS
+AC_PROG_INSTALL
+AC_ARG_PROGRAM
+
+AM_PATH_GTK(1.0.0,
+  [CFLAGS="$CFLAGS $GTK_CFLAGS"
+  GTK_PROGS="xgetline xshutdown"],
+  [AC_MSG_WARN([You appear not to have GTK.])
+  GTK_PROGS=""])
+AC_SUBST(GTK_PROGS)
+
+AC_PATH_XTRA
+CFLAGS="$CFLAGS $X_CFLAGS"
+
+AC_OUTPUT(Makefile)
+
+dnl ----- That's all, folks -------------------------------------------------
diff --git a/xgetline.1 b/xgetline.1
new file mode 100644 (file)
index 0000000..aa454ff
--- /dev/null
@@ -0,0 +1,64 @@
+.TH xgetline 1 "15 November 1998" "Edgeware tools"
+.SH NAME
+xgetline \- request a line of text in an X dialogue box
+.SH SYNOPSIS
+.B xgetline
+.RB [ \-t
+.IR title ]
+.RB [ \-p
+.IR prompt ]
+.RB [ \-d
+.IR default ]
+.SH DESCRIPTION
+The
+.B xgetline
+program reads a line of text from the user via a pretty GTK dialogue
+box.  The title bar contents, prompt string, and default text are all
+configurable.  If the user enters a string and clicks the
+.B OK
+button (or
+presses
+.IR enter ),
+the string is echoed to standard output and
+.B xgetline
+returns an exit status of zero.  If the user cancels the dialogue box
+(by closing it, or pressing
+.IR escape ),
+.B xgetline
+echoes nothing and returns an exit status of one.
+.PP
+The
+.B xgetline
+program is intended to be used in window manager configuration files, to
+allow users to fill in bits of text (e.g., hostnames or shell commands)
+in generally useful places.  For example, the author has the following
+shell command attached to a hotkey:
+.PP
+.RS 5
+.ft B
+.nf
+cmd=`xgetline -t "Shell command in window" -p "Command:"` &&
+  xterm -T "$cmd" -e sh -c "$cmd"
+.ft R
+.fi
+.SS OPTIONS
+.TP 5
+.BI "\-t, \-\-title " title
+Sets the title of the dialogue box to
+.IR title .
+The default title is
+.RB ` "Input request" '.
+.TP 5
+.BI "\-p, \-\-prompt " prompt
+Sets the prompt string in the dialogue box to
+.IR prompt .
+The default is to have no prompt string.
+.TP 5
+.BI "\-d, \-\-default " default
+Sets the default text in the entry field to
+.IR default .
+The default default is the empty string.
+.SH AUTHOR
+Mark Wooding (mdw@nsict.org).
+.SH BUGS
+Hopefully none.
diff --git a/xgetline.c b/xgetline.c
new file mode 100644 (file)
index 0000000..1da9ed1
--- /dev/null
@@ -0,0 +1,271 @@
+/* -*-c-*-
+ *
+ * $Id: xgetline.c,v 1.1 1998/11/16 23:00:49 mdw Exp $
+ *
+ * Fetch a line of text from the user
+ *
+ * (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: xgetline.c,v $
+ * Revision 1.1  1998/11/16 23:00:49  mdw
+ * Initial versions.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "mdwopt.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @cancel@ --- *
+ *
+ * Arguments:  @GtkWidget *w@ = widget raising the signal
+ *             @gpointer *p@ = pointer to integer result code
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the result code to zero (failure) and ends the loop.
+ */
+
+static void cancel(GtkWidget *w, gpointer *p)
+{
+  int *ip = (int *)p;
+  *ip = 0;
+  gtk_main_quit();
+}
+
+/* --- @done@ --- *
+ *
+ * Arguments:  @GtkWidget *w@ = widget raising the signal
+ *             @gpointer *p@ = pointer to integer result code
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets the result code nonzero (success) and ends the loop.
+ */
+
+static void done(GtkWidget *w, gpointer *p)
+{
+  int *ip = (int *)p;
+  *ip = 1;
+  gtk_main_quit();
+}
+
+/* --- @check_escape@ --- *
+ *
+ * Arguments:  @GtkWidget *w@ = widget raising the signal
+ *             @GdkEventKey *ev@ = pointer to event data
+ *             @gpointer *p@ = widget to activate in response
+ *
+ * Returns:    ---
+ *
+ * Use:                Activates a widget when an escape keypress is detected.
+ */
+
+static gboolean check_escape(GtkWidget *w, GdkEventKey *ev, gpointer *p)
+{
+  if (ev->keyval == GDK_Escape) {
+    if (p)
+      gtk_widget_activate(GTK_WIDGET(p));
+    else
+      gtk_object_destroy(GTK_OBJECT(w));
+    return (1);
+  }
+  return (0);
+}
+
+/* --- @main@ --- *
+ *
+ * Arguments:  @int argc@ = number of command line arguments
+ *             @char *argv[]@ = addresses of arguments
+ *
+ * Returns:    Zero if OK, and we read a string; nonzero if the user
+ *             cancelled.
+ *
+ * Use:                Reads a string from the user, and returns it on standard
+ *             output.
+ */
+
+int main(int argc, char *argv[])
+{
+  /* --- Configuration variables --- */
+
+  char *prompt = 0;
+  char *dfl = "";
+  char *title = "Input request";
+  int left;
+  unsigned f = 0;
+  int ok = 0;
+
+  enum {
+    f_invis = 1,
+    f_duff = 2
+  };
+
+  /* --- User interface bits --- */
+
+  GtkWidget *win;
+  GtkWidget *box;
+  GtkWidget *entry;
+  GtkWidget *btn;
+
+  /* --- Crank up the toolkit --- *
+   *
+   * Have to do this here: GTK snarfs some command line options which my
+   * parser would barf about.
+   */   
+
+  gtk_init(&argc, &argv);
+
+  /* --- Parse options from command line --- */
+
+  for (;;) {
+
+    /* --- Long options structure --- */
+
+    static struct option opt[] = {
+      { "help",                0,                      0,      'h' },
+      { "title",       required_argument,      0,      't' },
+      { "prompt",      required_argument,      0,      'p' },
+      { "default",     required_argument,      0,      'd' },
+      { "password",    0,                      0,      'i' },
+      { "invisible",   0,                      0,      'i' },
+      { 0,             0,                      0,      0 }
+    };
+    int i;
+
+    /* --- Fetch an option --- */
+
+    i = getopt_long(argc, argv, "ht:p:d:i", opt, 0);
+    if (i < 0)
+      break;
+
+    /* --- Work out what to do with it --- */
+
+    switch (i) {
+      case 't':
+       title = optarg;
+       break;
+      case 'p':
+       prompt = optarg;
+       break;
+      case 'd':
+       dfl = optarg;
+       break;
+      case 'i':
+       f |= f_invis;
+       break;
+      default:
+       f |= f_duff;
+       break;
+    }
+  }
+
+  if (f & f_duff) {
+    fprintf(stderr, "xgetline: bad arguments\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Create the main window --- */
+
+  win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title(GTK_WINDOW(win), title);
+  gtk_window_position(GTK_WINDOW(win), GTK_WIN_POS_MOUSE);
+  gtk_signal_connect(GTK_OBJECT(win), "destroy",
+                    GTK_SIGNAL_FUNC(cancel), &ok);
+
+  /* --- Create the box for laying out the widgets inside --- */
+
+  left = (prompt ? 1 : 0);
+  box = gtk_table_new(left + 2, 1, 0);
+
+  /* --- Maybe create a prompt widget --- */
+
+  if (prompt) {
+    GtkWidget *w = gtk_label_new(prompt);
+    gtk_table_attach(GTK_TABLE(box), w,
+                    0, 1, 0, 1, 0, GTK_EXPAND, 4, 2);
+    gtk_widget_show(w);
+  }
+
+  /* --- Create the entry widget --- */
+
+  entry = gtk_entry_new();
+  gtk_entry_set_text(GTK_ENTRY(entry), dfl);
+  gtk_table_attach(GTK_TABLE(box), entry,
+                  left, left + 1, 0, 1,
+                  GTK_EXPAND | GTK_FILL, GTK_EXPAND, 4, 2);
+  if (f & f_invis)
+    gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+  gtk_widget_show(entry);
+
+  /* --- Create the default action widget --- */
+
+  btn = gtk_button_new_with_label("OK");
+  gtk_table_attach(GTK_TABLE(box), btn,
+                  left + 1, left + 2, 0, 1, 0, GTK_EXPAND, 2, 2);
+  GTK_WIDGET_SET_FLAGS(btn, GTK_CAN_DEFAULT);
+  gtk_widget_show(btn);
+
+  /* --- Add the box into the main window --- */
+
+  gtk_container_add(GTK_CONTAINER(win), box);
+  gtk_widget_show(box);
+
+  /* --- Last minute configuration things --- */
+
+  gtk_widget_grab_default(btn);
+  gtk_signal_connect(GTK_OBJECT(btn), "clicked",
+                    GTK_SIGNAL_FUNC(done), &ok);
+  gtk_signal_connect_object(GTK_OBJECT(entry), "activate",
+                           GTK_SIGNAL_FUNC(gtk_widget_activate),
+                           GTK_OBJECT(btn));
+  gtk_signal_connect(GTK_OBJECT(win), "key_press_event",
+                    GTK_SIGNAL_FUNC(check_escape), 0);
+
+  /* --- Go go go --- */
+
+  gtk_widget_show(win);
+  gtk_main();
+
+  /* --- Output the result --- */
+
+  if (ok) {
+    char *p = gtk_entry_get_text(GTK_ENTRY(entry));
+    puts(p);
+  }
+
+  return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/xscsize.1 b/xscsize.1
new file mode 100644 (file)
index 0000000..30caf39
--- /dev/null
+++ b/xscsize.1
@@ -0,0 +1,59 @@
+.TH xscsize 1 "15 November 1998" "Edgeware tools"
+.SH NAME
+xscsize \- return size of an X display to a shell script
+.SH SYNOPSIS
+.B xscsize
+.RB [ \-bcx ]
+.RB [ \-d
+.IR display ]
+.SH DESCRIPTION
+The
+.B xscsize
+program interrogates an X display and writes the size of the root
+window to standard output in the form of a shell variable assignment
+statement.  The dimensions are returned in the
+.B XWIDTH
+and
+.B XHEIGHT
+variables.
+.PP
+Command line options can be used to force output in either Bourne or C
+shell syntax.  In the absence of any explicit instructions,
+.B xscsize
+looks at the
+.B SHELL
+environment variable to help make its mind up.
+.PP
+Typical use would be something like
+.RS 5
+.ft B
+.nf
+eval `xscsize`
+.ft R
+.fi
+.SS OPTIONS
+.TP 5
+.B \-b
+Output the assignments in Bourne shell syntax (usable by Bourne,
+POSIX, Korn, Z and Bourne Again shells).
+.TP 5
+.B \-c
+Output the assignments in C shell syntax (usable by C and Terminal C
+shells).
+.TP 5
+.B \-x
+Output a variable export command, so that the screen size is inherited
+by child processes.  The default is to just set local shell variables.
+.SH ENVIRONMENT
+.TP
+.B XWIDTH
+Set to the width of the display in pixels.
+.B XHEIGHT
+Set to the height of the display in pixels.
+.B SHELL
+Used to decide the nature of the calling shell.  If absent, a Bourne
+shell is assumed.
+.SH AUTHOR
+Mark Wooding (mdw@nsict.org).
+.SH BUGS
+Hopefully none.
diff --git a/xscsize.c b/xscsize.c
new file mode 100644 (file)
index 0000000..ace018e
--- /dev/null
+++ b/xscsize.c
@@ -0,0 +1,143 @@
+/* -*-c-*-
+ *
+ * $Id: xscsize.c,v 1.1 1998/11/16 23:00:49 mdw Exp $
+ *
+ * Return X display size to shell script
+ *
+ * (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: xscsize.c,v $
+ * Revision 1.1  1998/11/16 23:00:49  mdw
+ * Initial versions.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+#include <X11/Xlib.h>
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  const char *display = 0;
+  unsigned f = 0;
+  unsigned long wd, ht;
+
+  enum {
+    f_sh = 1,
+    f_csh = 2,
+    f_shell = 3,
+    f_export = 4
+  };
+
+  /* --- Parse command line options --- */
+
+  for (;;) {
+    int i = getopt(argc, argv, "d:bcx");
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'd':
+       display = optarg;
+       break;
+      case 'b':
+       f |= f_sh;
+       break;
+      case 'c':
+       f |= f_csh;
+       break;
+      case 'x':
+       f |= f_export;
+       break;
+      default:
+       fprintf(stderr, "Usage: xscsize [-bcx] [-d DISPLAY]\n");
+       exit(EXIT_FAILURE);
+       break;
+    }
+  }
+
+  /* --- Sort out the shell type --- *
+   *
+   * If the shell name contains the string `csh' then assume it's a C shell.
+   * Otherwise assume it's Bourne.  This seems to work in practice.
+   */
+
+  if (!(f & f_shell)) {
+    const char *s = getenv("SHELL");
+    if (!s)
+      f |= f_sh;
+    if (strstr(s, "csh"))
+      f |= f_csh;
+    else
+      f |= f_sh;
+  }
+
+  if ((f & f_sh) && (f & f_csh)) {
+    fprintf(stderr, "xscsize: make your mind up about your shell type\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Get the important information --- */
+
+  {
+    Display *dpy = XOpenDisplay(display);
+    int sc;
+    if (!dpy) {
+      fprintf(stderr, "xscsize: couldn't open display\n");
+      exit(EXIT_FAILURE);
+    }
+    sc = DefaultScreen(dpy);
+    wd = DisplayWidth(dpy, sc);
+    ht = DisplayHeight(dpy, sc);
+    XCloseDisplay(dpy);
+  }
+
+  /* --- Do the output thing --- */
+
+  if (f & f_sh) {
+    printf("XWIDTH=%lu XHEIGHT=%lu", wd, ht);
+    if (f & f_export)
+      printf("; export XWIDTH XHEIGHT");
+  }
+  if (f & f_csh) {
+    if (f & f_export)
+      printf("setenv XWIDTH %lu; setenv XHEIGHT %lu", wd, ht);
+    else
+      printf("set XWIDTH=%lu XHEIGHT=%lu", wd, ht);
+  }
+  putchar('\n');
+
+  /* --- Done --- */
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/xshutdown.1 b/xshutdown.1
new file mode 100644 (file)
index 0000000..17417b7
--- /dev/null
@@ -0,0 +1,60 @@
+.TH xshutdown 1 "15 November 1998" "Edgeware tools"
+.SH NAME
+xshutdown \- asks for user confirmation before waking an xwait process
+.SH SYNOPSIS
+.B xshutdown
+.RB [ \-\-display
+.IR display ]
+.RB [ \-a
+.IR atom ]
+.RB [ \-m
+.IR message ]
+.RB [ \-t
+.IR title ]
+.SH DESCRIPTION
+The
+.B xshutdown
+program pops up a pretty GTK confirmation box asking the user whether he
+(or she) wants to shutdown the current session.  If so, it sends a
+message to a waiting
+.B xwait
+process, by setting a named property on the X root window to a particular
+value.
+.SS OPTIONS
+.TP 5
+.BI "\-\-display " display
+Attempt to connect to
+.I display
+rather than the display named in the usual environment variable.
+.TP 5
+.BI "\-a, \-\-atom " atom
+Sets
+.B xshutdown
+to to set the property named
+.IR atom .
+The default property to set is
+.BR XWAIT_PROPERTY .
+.TP 5
+.BI "\-m, \-\-msg " message
+Sets
+.B xshutdown
+to set the given property to
+.IR message .
+The default message to set is
+.BR XWAIT_MESSAGE .
+.TP 5
+.BI "\-p, \-\-prompt " prompt
+Sets the prompt in the confirmation box to
+.IR prompt .
+.TP 5
+.BI "\-t, \-\-title " title
+Sets the window title to be
+.IR title .
+.SH AUTHOR
+Mark Wooding (mdw@nsict.org).
+.SH BUGS
+None currently known.
+.SH SEE ALSO
+.BR xwait (1),
+and
+.BR xtell (1).
diff --git a/xshutdown.c b/xshutdown.c
new file mode 100644 (file)
index 0000000..dd62b26
--- /dev/null
@@ -0,0 +1,231 @@
+/* -*-c-*-
+ *
+ * $Id: xshutdown.c,v 1.1 1998/11/16 23:00:49 mdw Exp $
+ *
+ * Pretty GTK interface to waking up an xwait
+ *
+ * (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: xshutdown.c,v $
+ * Revision 1.1  1998/11/16 23:00:49  mdw
+ * Initial versions.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkprivate.h>
+
+#include "mdwopt.h"
+#include "xwait.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static char *atom = XWAIT_DIE;
+static char *msg = XWAIT_DIE_MSG;
+
+static Atom xwait_die;
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @cancel@ --- *
+ *
+ * Just end the main loop.
+ */
+
+static void cancel(GtkWidget *w, gpointer *p)
+{
+  gtk_main_quit();
+}
+
+/* --- @ok@ --- *
+ *
+ * Send the xwait process a message.
+ */
+
+static void ok(GtkWidget *w, gpointer *p)
+{
+  XTextProperty prop;
+  XStringListToTextProperty(&msg, 1, &prop);
+  XSetTextProperty(gdk_display, DefaultRootWindow(gdk_display),
+                  &prop, xwait_die);
+  gtk_main_quit();
+}
+
+/* --- @main@ --- *
+ *
+ * Main program.
+ */
+
+int main(int argc, char *argv[])
+{
+  char *prompt = "Are you sure you want to shut down this session?";
+  char *title = "xshutdown";
+  gtk_init(&argc, &argv);
+
+  /* --- Parse options --- */
+
+  for (;;) {
+    static struct option opt[] = {
+      { "atom",        required_argument,      0,      'a' },
+      { "msg", required_argument,      0,      'm' },
+      { "prompt", required_argument,   0,      'p' },
+      { "title", required_argument,    0,      't' },
+      { 0,     0,                      0,      0 }
+    };
+    int i;
+
+    i = getopt_long(argc, argv, "a:m:p:t:", opt, 0);
+
+    if (i < 0)
+      break;
+
+    switch (i) {
+      case 'a':
+       atom = optarg;
+       break;
+      case 'm':
+       msg = optarg;
+       break;
+      case 'p':
+       prompt = optarg;
+       break;
+      case 't':
+       title = optarg;
+       break;
+      default:
+       exit(EXIT_FAILURE);
+    }
+  }
+
+  xwait_die = XInternAtom(gdk_display, atom, False);
+
+  /* --- Decide whether there's an xwait listening --- *
+   *
+   * If not, pop up an error box and quit.
+   */
+
+  {
+    XTextProperty prop;
+
+    if (!XGetTextProperty(gdk_display, DefaultRootWindow(gdk_display),
+                         &prop, xwait_die)) {
+      char buf[64];
+      GtkWidget *win = gtk_dialog_new();
+      GtkWidget *w;
+
+      /* --- Make the main window --- */
+
+      gtk_window_set_title(GTK_WINDOW(win), "xshutdown");
+      gtk_signal_connect(GTK_OBJECT(win), "destroy",
+                      GTK_SIGNAL_FUNC(cancel), 0);
+
+      gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(win)->action_area), 0);
+
+      /* --- Make the label --- */
+
+      sprintf(buf, "no xwait listening for `%s'\n", atom);
+      w = gtk_label_new(buf);
+      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), w, 1, 1, 0);
+      gtk_misc_set_padding(GTK_MISC(w), 8, 8);
+      gtk_widget_show(w);
+
+      /* --- Make the little button --- */
+
+      w = gtk_button_new_with_label("OK");
+      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);
+      gtk_signal_connect(GTK_OBJECT(w), "clicked",
+                        GTK_SIGNAL_FUNC(cancel), 0);
+      gtk_widget_show(w);
+
+      /* --- Make everything work --- */
+
+      gtk_widget_show(win);
+      gtk_main();
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  /* --- Main code --- */
+
+  {
+    GtkWidget *win;
+    GtkWidget *w;
+
+    /* --- Make the main dialogue box --- */
+
+    win = gtk_dialog_new();
+    gtk_window_set_title(GTK_WINDOW(win), title);
+    gtk_signal_connect(GTK_OBJECT(win), "destroy",
+                      GTK_SIGNAL_FUNC(cancel), 0);
+
+    gtk_box_set_homogeneous(GTK_BOX(GTK_DIALOG(win)->action_area), 0);
+
+    /* --- Make the prompt label --- */
+
+    w = gtk_label_new(prompt);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), w, 1, 1, 0);
+    gtk_misc_set_padding(GTK_MISC(w), 8, 8);
+    gtk_widget_show(w);
+
+    /* --- Make the OK button --- */
+
+    w = gtk_button_new_with_label("OK");
+    gtk_box_pack_end(GTK_BOX(GTK_DIALOG(win)->action_area), w, 0, 0, 0);
+    gtk_signal_connect(GTK_OBJECT(w), "clicked", GTK_SIGNAL_FUNC(ok), 0);
+    GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
+    gtk_widget_show(w);
+    gtk_widget_grab_default(w);
+
+    /* --- And the cancel button --- */
+
+    w = gtk_button_new_with_label("Cancel");
+    gtk_box_pack_end(GTK_BOX(GTK_DIALOG(win)->action_area), w, 0, 0, 0);
+    gtk_signal_connect(GTK_OBJECT(w), "clicked", GTK_SIGNAL_FUNC(cancel), 0);
+    GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
+    gtk_widget_show(w);
+
+    /* --- Show the completed window --- */
+
+    gtk_widget_show(win);
+  }
+
+  /* --- Let rip --- */
+
+  gtk_main();
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/xtell.1 b/xtell.1
new file mode 100644 (file)
index 0000000..b04d22f
--- /dev/null
+++ b/xtell.1
@@ -0,0 +1,47 @@
+.TH xtell 1 "15 November 1998" "Edgeware tools"
+.SH NAME
+xtell \- prods a waiting xwait process
+.SH SYNOPSIS
+.B xtell
+.RB [ \-d
+.IR display ]
+.RB [ \-a
+.IR atom ]
+.RB [ \-m
+.IR message ]
+.SH DESCRIPTION
+The
+.B xtell
+program sets a named property on the X root window to a particular
+value.  This is primarily useful for communicating with
+.BR xwait (1).
+.SS OPTIONS
+.TP 5
+.BI "\-d " display
+Attempt to connect to
+.I display
+rather than the display named in the usual environment variable.
+.TP 5
+.BI "\-a " atom
+Sets
+.B xtell
+to to set the property named
+.IR atom .
+The default property to set to is
+.BR XWAIT_PROPERTY .
+.TP 5
+.BI "\-m " message
+Sets
+.B xtell
+to set the given property to
+.IR message .
+The default message to set is
+.BR XWAIT_MESSAGE .
+.SH AUTHOR
+Mark Wooding (mdw@nsict.org).
+.SH BUGS
+None currently known.
+.SH SEE ALSO
+.BR xwait (1),
+and
+.BR xshutdown (1).
diff --git a/xtell.c b/xtell.c
new file mode 100644 (file)
index 0000000..7675814
--- /dev/null
+++ b/xtell.c
@@ -0,0 +1,113 @@
+/* -*-c-*-
+ *
+ * $Id: xtell.c,v 1.1 1998/11/16 23:00:49 mdw Exp $
+ *
+ * Wake up a waiting xwait process
+ *
+ * (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: xtell.c,v $
+ * Revision 1.1  1998/11/16 23:00:49  mdw
+ * Initial versions.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "xwait.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  char *display = 0;
+  Display *dpy;
+  Atom xwait_die;
+  char *atom = XWAIT_DIE;
+  char *msg = XWAIT_DIE_MSG;
+
+  /* --- Parse options --- */
+
+  for (;;) {
+    int i = getopt(argc, argv, "d:a:m:");
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'd':
+       display = optarg;
+       break;
+      case 'a':
+       atom = optarg;
+       break;
+      case 'm':
+       msg = optarg;
+       break;
+      default:
+       fprintf(stderr, "Usage: xtell [-d DISPLAY] [-a ATOM] [-m MSG]\n");
+       exit(EXIT_FAILURE);
+       break;
+    }
+  }
+
+  /* --- Connect to the display --- */
+
+  dpy = XOpenDisplay(display);
+  if (!dpy) {
+    fprintf(stderr, "xtell: couldn't open display\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Find the right atom --- */
+
+  xwait_die = XInternAtom(dpy, atom, False);
+
+  /* --- Set the property value --- */
+
+  {
+    XTextProperty prop;
+    if (!XGetTextProperty(dpy, DefaultRootWindow(dpy), &prop, xwait_die)) {
+      fprintf(stderr, "xtell: no xwait listening for `%s'\n", atom);
+      exit(EXIT_FAILURE);
+    }
+    XStringListToTextProperty(&msg, 1, &prop);
+    XSetTextProperty(dpy, DefaultRootWindow(dpy), &prop, xwait_die);
+  }
+
+  /* --- Done --- */
+
+  XCloseDisplay(dpy);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/xwait.1 b/xwait.1
new file mode 100644 (file)
index 0000000..f9b9ccb
--- /dev/null
+++ b/xwait.1
@@ -0,0 +1,65 @@
+.TH xwait 1 "15 November 1998" "Edgeware tools"
+.SH NAME
+xwait \- wait until prodded by another X client
+.SH SYNOPSIS
+.B xwait
+.RI [ \-f ]
+.RB [ \-d
+.IR display ]
+.RB [ \-a
+.IR atom ]
+.RB [ \-m
+.IR message ]
+.SH DESCRIPTION
+The
+.B xwait
+program waits until it notices that a particular property on the X root
+window has been assigned a particular value, at which point the program
+exits.  The property can be set using the
+.BR xtell (1)
+and
+.BR xshutdown (1)
+programs.  It's mostly useful for putting at the end of a user's
+.B .xinitrc
+file, so that it can be triggered to end the session.
+.PP
+The property, and the value to listen for, can be configured at
+the command line.  When
+.B xwait
+exits, it removes the property from the root window.
+.SS OPTIONS
+.TP 5
+.B \-f
+Force 
+.B xwait
+to start up, even though there may be an existing process already
+listening for the particular atom in question.
+.TP 5
+.BI "\-d " display
+Attempt to connect to
+.I display
+rather than the display named in the usual environment variable.
+.TP 5
+.BI "\-a " atom
+Sets
+.B xwait
+to listen for the property named
+.IR atom .
+The default property to listen to is
+.BR XWAIT_PROPERTY .
+.TP 5
+.BI "\-m " message
+Sets
+.B xwait
+to wait for the given property to be set to
+.IR message .
+The default message to wait for is
+.BR XWAIT_MESSAGE .
+.SH AUTHOR
+Mark Wooding (mdw@nsict.org).
+.SH BUGS
+None currently known.
+.SH SEE ALSO
+.BR xtell (1),
+and
+.BR xshutdown (1).
diff --git a/xwait.c b/xwait.c
new file mode 100644 (file)
index 0000000..7142217
--- /dev/null
+++ b/xwait.c
@@ -0,0 +1,176 @@
+/* -*-c-*-
+ *
+ * $Id: xwait.c,v 1.1 1998/11/16 23:00:49 mdw Exp $
+ *
+ * Wait until prodded by another X client
+ *
+ * (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: xwait.c,v $
+ * Revision 1.1  1998/11/16 23:00:49  mdw
+ * Initial versions.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "xwait.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  char *display = 0;
+  Display *dpy;
+  Atom xwait_die;
+  XEvent ev;
+  char *atom = XWAIT_DIE;
+  char *msg = XWAIT_DIE_MSG;
+  unsigned f = 0;
+
+  enum {
+    f_force = 1
+  };
+
+  /* --- Parse options --- */
+
+  for (;;) {
+    int i = getopt(argc, argv, "d:a:m:f");
+    if (i < 0)
+      break;
+    switch (i) {
+      case 'd':
+       display = optarg;
+       break;
+      case 'a':
+       atom = optarg;
+       break;
+      case 'm':
+       msg = optarg;
+       break;
+      case 'f':
+       f |= f_force;
+       break;
+      default:
+       fprintf(stderr,
+               "Usage: xwait [-f] [-d DISPLAY] [-a ATOM] [-m MSG]\n");
+       exit(EXIT_FAILURE);
+       break;
+    }
+  }
+
+  /* --- Connect to the X display --- */
+
+  dpy = XOpenDisplay(display);
+  if (!dpy) {
+    fprintf(stderr, "xwait: couldn't open display\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* --- Fetch the property name atom --- */
+
+  xwait_die = XInternAtom(dpy, atom, False);
+
+  /* --- Mark ourselves as listening to all the screens --- */
+
+  {
+    int i;
+    int nsc = ScreenCount(dpy);
+
+    /* --- First pass: make sure there's not a process already here --- */
+
+    if ((f & f_force) == 0) {
+      for (i = 0; i < nsc; i++) {
+       Window win = RootWindow(dpy, i);
+       XTextProperty prop;
+
+       if (XGetTextProperty(dpy, win, &prop, xwait_die)) {
+         fprintf(stderr, "xwait: already waiting for `%s'\n", atom);
+         exit(EXIT_FAILURE);
+       }
+      }
+    }
+
+    /* --- Second pass: set up listening to the property --- */
+
+    for (i = 0; i < nsc; i++) {
+      Window win = RootWindow(dpy, i);
+      XTextProperty prop;
+      char *imsg = "XWAIT_READY";
+
+      XStringListToTextProperty(&imsg, 1, &prop);
+      XSetTextProperty(dpy, win, &prop, xwait_die);
+      XSelectInput(dpy, win, PropertyChangeMask);
+    }
+  }
+
+  /* --- Now wait for an event --- */
+
+  for (;;) {
+    XNextEvent(dpy, &ev);
+    switch (ev.type) {
+      case PropertyNotify:
+       if (ev.xproperty.atom == xwait_die) {
+         XTextProperty prop;
+         char **sl;
+         int c;
+
+         if (XGetTextProperty(dpy, ev.xproperty.window, &prop, xwait_die)) {
+           XTextPropertyToStringList(&prop, &sl, &c);
+           if (strcmp(sl[0], msg) == 0)
+             goto exit;
+           XFreeStringList(sl);
+         }
+       }
+    }
+  }
+
+  /* --- Finished: remove the property from all the screens --- */
+
+exit:
+  {
+    int i;
+    int nsc = ScreenCount(dpy);
+
+    for (i = 0; i < nsc; i++)
+      XDeleteProperty(dpy, RootWindow(dpy, i), xwait_die);
+  }
+
+  /* --- Go away --- */
+
+  XCloseDisplay(dpy);
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/xwait.h b/xwait.h
new file mode 100644 (file)
index 0000000..f55e6d7
--- /dev/null
+++ b/xwait.h
@@ -0,0 +1,8 @@
+#ifndef XWAIT_H
+#define XWAIT_H
+
+
+#define XWAIT_DIE "XWAIT_PROPERTY"
+#define XWAIT_DIE_MSG "XWAIT_MESSAGE"
+
+#endif