From: mdw Date: Fri, 20 Aug 1999 07:29:55 +0000 (+0000) Subject: New command line syntax, and new atom protocol. Wait for multiple X-Git-Tag: 1.2.6~4 X-Git-Url: https://git.distorted.org.uk/~mdw/xtoys/commitdiff_plain/25c93171274d961fae80b2e77fc884ca253dd658 New command line syntax, and new atom protocol. Wait for multiple properties and listen for multiple (or all) values. --- diff --git a/xwait.1 b/xwait.1 index 336c595..4c09801 100644 --- a/xwait.1 +++ b/xwait.1 @@ -3,6 +3,7 @@ .SH NAME xwait \- wait until prodded by another X client .SH SYNOPSIS +.ll +5i .B xwait .RB [ \-f ] .RB [ \-d @@ -11,6 +12,10 @@ xwait \- wait until prodded by another X client .IR atom ] .RB [ \-m .IR message ] +.RI [ \c +.IB atom : msg , msg \c +\&...] +.ll -5i .SH DESCRIPTION The .B xwait @@ -24,10 +29,10 @@ 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 +The properties, and the values to listen for, can be configured at the +command line. When .B xwait -exits, it removes the property from the root window. +exits, it removes the properties from the root window. .SS OPTIONS .TP 5 .B \-f, \-\-force @@ -46,15 +51,33 @@ Sets .B xwait to listen for the property named .IR atom . -The default property to listen to is -.BR XWAIT_PROPERTY . +Use of this option is deprecated. .TP 5 .BI "\-m, \-\-msg " message Sets .B xwait to wait for the given property to be set to .IR message . -The default message to wait for is +Use of this option is deprecated. +.SS "Argument format" +The +.B \-a +and +.B \-m +options are deprecated, though retained for compatibility reasons. +It's recommended that you use the non-option specification instead. +.PP +Each argument specifies an atom name and a list of message strings to +listen to. Multiple properties may be listened for, and multiple +messages may be accepted for each property. If no messages are +specified then all values are considered to be acceptable. The program +exits when any property is set to an acceptable value. +.PP +If no atoms are given on the command line, +.B xwait +will wait for +.B XWAIT_PROPERTY +to be set to .BR XWAIT_MESSAGE . .SH AUTHOR Mark Wooding (mdw@nsict.org). diff --git a/xwait.c b/xwait.c index c74d2e2..a6b2332 100644 --- a/xwait.c +++ b/xwait.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: xwait.c,v 1.7 1999/06/19 23:42:37 mdw Exp $ + * $Id: xwait.c,v 1.8 1999/08/20 07:29:55 mdw Exp $ * * Wait until prodded by another X client * @@ -29,6 +29,10 @@ /*----- Revision history --------------------------------------------------* * * $Log: xwait.c,v $ + * Revision 1.8 1999/08/20 07:29:55 mdw + * New command line syntax, and new atom protocol. Wait for multiple + * properties and listen for multiple (or all) values. + * * Revision 1.7 1999/06/19 23:42:37 mdw * Improve signal handling. * @@ -71,9 +75,30 @@ #include #include +#include +#include +#include "xatom.h" #include "xwait.h" +/*----- Data structures ---------------------------------------------------*/ + +typedef struct xwait_msg { + struct xwait_msg *next; /* Next message in the list */ + Atom a; /* The message atom */ +} xwait_msg; + +typedef struct xwait_atom { + struct xwait_atom *next; /* Next atom in the list */ + Atom a; /* The actual atom */ + xwait_msg *m; /* List of interesting messages */ +} xwait_atom; + +/*----- Static variables --------------------------------------------------*/ + +static xwait_atom *atoms = 0; +static Display *dpy; + /*----- Main code ---------------------------------------------------------*/ /* --- @sigchld@ --- */ @@ -86,6 +111,56 @@ static void sigchld(int sig) errno = e; } +/* --- @opendisplay@ --- */ + +static void opendisplay(const char *d) +{ + if (dpy) + return; + if ((dpy = XOpenDisplay(d)) == 0) + die(EXIT_FAILURE, "couldn't open display"); +} + +/* --- @addatom@ --- */ + +static xwait_atom *addatom(const char *a) +{ + xwait_atom *xa = CREATE(xwait_atom); + opendisplay(0); + xa->next = atoms; + xa->a = XInternAtom(dpy, a, False); + xa->m = 0; + atoms = xa; + return (xa); +} + +/* --- @addmsg@ --- */ + +static void addmsg(xwait_atom *xa, const char *a) +{ + xwait_msg *xm = CREATE(xwait_msg); + opendisplay(0); + xm->next = xa->m; + xm->a = XInternAtom(dpy, a, False); + xa->m = xm; +} + +/* --- @tidy@ --- */ + +static void tidy(int sig) +{ + int i; + int nsc = ScreenCount(dpy); + xwait_atom *xa; + + for (i = 0; i < nsc; i++) { + for (xa = atoms; xa; xa = xa->next) + XDeleteProperty(dpy, RootWindow(dpy, i), xa->a); + } + XCloseDisplay(dpy); + exit(0); +} + /* --- @main@ --- */ static void version(FILE *fp) @@ -95,40 +170,41 @@ static void version(FILE *fp) static void usage(FILE *fp) { - fprintf(fp, "Usage: %s [-f] [-d DISPLAY] [-a ATOM] [-m MSG]\n", QUIS); + fprintf(fp, "Usage: %s [-f] [-d DISPLAY] [ATOM:MSG,MSG]...\n", QUIS); } int main(int argc, char *argv[]) { - char *display = 0; - Display *dpy; - Atom xwait_die; + Atom a; XEvent ev; - char *atom = XWAIT_DIE; - char *msg = XWAIT_DIE_MSG; unsigned f = 0; + xwait_atom *xa = 0; + xwait_msg *xm = 0; enum { f_force = 1 }; - /* --- Parse options --- */ + /* --- Initialize mLib --- */ ego(argv[0]); + sub_init(); + + /* --- Parse options --- */ for (;;) { static struct option opt[] = { { "help", 0, 0, 'h' }, { "usage", 0, 0, 'u' }, { "version", 0, 0, 'v' }, - { "display", required_argument, 0, 'd' }, - { "atom", required_argument, 0, 'a' }, - { "msg", required_argument, 0, 'm' }, + { "display", OPTF_ARGREQ, 0, 'd' }, + { "atom", OPTF_ARGREQ, 0, 'a' }, + { "msg", OPTF_ARGREQ, 0, 'm' }, { "force", 0, 0, 'f' }, { 0, 0, 0, 0 } }; - int i = getopt_long(argc, argv, "d:a:m:f", opt, 0); + int i = mdwopt(argc, argv, "d:a:m:f", opt, 0, 0, 0); if (i < 0) break; switch (i) { @@ -151,8 +227,8 @@ int main(int argc, char *argv[]) "-d, --display=DISPLAY Choose X display to connect to\n" "-f, --force Run even if this property is waited for by another\n" " process\n" -"-a, --atom=ATOM\t Choose property name to listen for\n" -"-m, --msg=MSG Choose value of property to wait for\n", +"-a, --atom=ATOM\t Choose property name to listen for [deprecated]\n" +"-m, --msg=MSG Choose value of property to wait for [deprecated]\n", stdout); exit(0); break; @@ -166,13 +242,15 @@ int main(int argc, char *argv[]) break; case 'd': - display = optarg; + opendisplay(optarg); break; case 'a': - atom = optarg; + xa = addatom(optarg); break; case 'm': - msg = optarg; + if (!xa) + die(EXIT_FAILURE, "no atom currently defined"); + addmsg(xa, optarg); break; case 'f': f |= f_force; @@ -184,34 +262,38 @@ int main(int argc, char *argv[]) } } - /* --- Connect to the X display --- */ + /* --- Grind through remaining arguments in the new syntax --- */ - dpy = XOpenDisplay(display); - if (!dpy) { - fprintf(stderr, "xwait: couldn't open display\n"); - exit(EXIT_FAILURE); + while (optind < argc) { + char *p = strtok(argv[optind++], ":"); + if (!p) + continue; + xa = addatom(p); + while ((p = strtok(0, ",")) != 0) + addmsg(xa, p); } - /* --- Fetch the property name atom --- */ + /* --- If there's nothing set, put in some defaults --- */ - xwait_die = XInternAtom(dpy, atom, False); + if (!atoms) { + xa = addatom(XWAIT_DIE); + addmsg(xa, XWAIT_DIE_MSG); + } - /* --- Mark ourselves as listening to all the screens --- */ + /* --- Attach the atoms to the screens --- */ { int i; + Atom ready = XInternAtom(dpy, "XWAIT_READY", False); 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); + for (xa = atoms; xa; xa = xa->next) { + if (xatom_get(dpy, RootWindow(dpy, i), xa->a) != None) + die(EXIT_FAILURE, "already waiting for `%s'"); } } } @@ -219,13 +301,9 @@ int main(int argc, char *argv[]) /* --- 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); + for (xa = atoms; xa; xa = xa->next) + xatom_set(dpy, RootWindow(dpy, i), xa->a, ready); + XSelectInput(dpy, RootWindow(dpy, i), PropertyChangeMask); } } @@ -238,9 +316,6 @@ int main(int argc, char *argv[]) { struct sigaction sa; - sigset_t ss, oss; - - /* --- Set the handler up --- */ sa.sa_handler = sigchld; sigemptyset(&sa.sa_mask); @@ -250,8 +325,12 @@ int main(int argc, char *argv[]) sa.sa_flags |= SA_RESTART; #endif sigaction(SIGCHLD, &sa, 0); + } - /* --- Now reap any which have been waiting around so far --- */ + /* --- Now reap any which have been waiting around so far --- */ + + { + sigset_t ss, oss; sigemptyset(&ss); sigaddset(&ss, SIGCHLD); @@ -260,41 +339,47 @@ int main(int argc, char *argv[]) sigprocmask(SIG_SETMASK, &oss, 0); } + signal(SIGINT, tidy); + signal(SIGTERM, tidy); + /* --- 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) + for (xa = atoms; xa; xa = xa->next) { + if (ev.xproperty.atom != xa->a) + continue; + a = xatom_get(dpy, ev.xproperty.window, xa->a); + if (a == None) + continue; + if (xa->m == 0) + goto exit; + for (xm = xa->m; xm; xm = xm->next) { + if (a == xm->a) goto exit; - XFreeStringList(sl); } } + break; } } - /* --- Finished: remove the property from all the screens --- */ + /* --- Finished: report the result if necessary --- */ exit: - { - int i; - int nsc = ScreenCount(dpy); - - for (i = 0; i < nsc; i++) - XDeleteProperty(dpy, RootWindow(dpy, i), xwait_die); - } + if (atoms->next) { + fputs(XGetAtomName(dpy, xa->a), stdout); + if (!xa->m || xa->m->next) + printf(": %s\n", XGetAtomName(dpy, a)); + else + fputc('\n', stdout); + } else if (!xa->m || xa->m->next) + printf("%s\n", XGetAtomName(dpy, a)); /* --- Go away --- */ - XCloseDisplay(dpy); + tidy(0); return (0); }