3 * Set and fetch X atom properties
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the Edgeware X tools collection.
12 * X tools is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * X tools is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with X tools; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
37 #include <X11/cursorfont.h>
38 #include <X11/Xatom.h>
40 #include <X11/Xutil.h>
42 #include <mLib/mdwopt.h>
43 #include <mLib/quis.h>
44 #include <mLib/alloc.h>
45 #include <mLib/report.h>
49 /*----- Static variables --------------------------------------------------*/
51 static Display
*display
= 0;
52 static Window window
= None
;
54 /*----- Command implementations -------------------------------------------*/
56 static void help(char **);
57 static int c_help(int argc
, char **argv
)
58 { help(argv
+ 1); return (0); }
60 static int c_get(int argc
, char **argv
)
66 die(EXIT_FAILURE
, "Usage: get PROPERTY");
67 if ((p
= XInternAtom(display
, argv
[1], True
)) == None
||
68 (a
= xatom_get(display
, window
, p
)) == None
)
70 name
= XGetAtomName(display
, a
);
75 static int c_set(int argc
, char **argv
)
80 die(EXIT_FAILURE
, "Usage: set PROPERTY VALUE");
81 p
= XInternAtom(display
, argv
[1], False
);
82 a
= XInternAtom(display
, argv
[2], False
);
83 xatom_set(display
, window
, p
, a
);
87 static int c_delete(int argc
, char **argv
)
92 die(EXIT_FAILURE
, "Usage: delete PROPERTY");
93 if ((p
= XInternAtom(display
, argv
[1], True
)) == None
)
95 xatom_delete(display
, window
, p
);
99 static int c_wait(int argc
, char **argv
)
106 die(EXIT_FAILURE
, "Usage: wait PROPERTY [VALUE...]");
108 p
= XInternAtom(display
, argv
[1], False
);
111 aa
= xmalloc(n
* sizeof(Atom
));
112 XInternAtoms(display
, argv
+ 2, n
, False
, aa
);
115 a
= xatom_wait(display
, window
, p
, aa
, n
);
117 name
= XGetAtomName(display
, a
);
126 /*----- Utilities ---------------------------------------------------------*/
128 /* --- @choosewindow@ --- *
132 * Returns: An X window id.
134 * Use: Allows the user to select a window using the mouse.
137 static Window
choosewindow(void)
139 Cursor cross
= XCreateFontCursor(display
, XC_crosshair
);
142 XGrabPointer(display
,
143 DefaultRootWindow(display
),
153 XNextEvent(display
, &event
);
154 switch (event
.type
) {
156 switch (event
.xbutton
.button
) {
158 XUngrabPointer(display
, event
.xbutton
.time
);
159 die(EXIT_FAILURE
, "aborted window selection");
162 window
= event
.xbutton
.subwindow
;
164 window
= event
.xbutton
.window
;
165 XUngrabPointer(display
, event
.xbutton
.time
);
173 /* --- @autoreap@ --- *
179 * Use: Causes child processes to be reaped as reports of their
180 * demises come in. Their exit statuses are simply discarded.
182 * This program needs to reap child processes even though it
183 * didn't create them and doesn't know what to do with their
184 * statuses because it's often used in shell scripts of the form
186 * ... start lots of stuff ...
187 * exec xatom wait GODOT ARRIVED
190 static void reap(int sig
)
191 { int e
= errno
; while (waitpid(-1, 0, WNOHANG
) > 0) ; errno
= e
; }
193 static void autoreap(void)
198 sa
.sa_handler
= reap
;
199 sigemptyset(&sa
.sa_mask
);
200 sigaddset(&sa
.sa_mask
, SIGCHLD
);
201 sa
.sa_flags
= SA_NOCLDSTOP
;
203 sa
.sa_flags
|= SA_RESTART
;
205 sigaction(SIGCHLD
, &sa
, 0);
208 sigaddset(&ss
, SIGCHLD
);
209 sigprocmask(SIG_BLOCK
, &ss
, &oss
);
211 sigprocmask(SIG_SETMASK
, &oss
, 0);
214 /*----- Command dispatch --------------------------------------------------*/
216 static const struct cmd
{
218 int (*cmd
)(int, char **);
222 { "help", c_help
, "help [COMMANDS...]" },
223 { "get", c_get
, "get PROPERTY" },
224 { "set", c_set
, "set PROPERTY VALUE" },
225 { "delete", c_delete
, "delete PROPERTY" },
226 { "wait", c_wait
, "wait PROPERTY [VALUE...]" },
230 const struct cmd
*findcmd(const char *name
)
232 const struct cmd
*c
, *chosen
= 0;
233 size_t sz
= strlen(name
);
235 for (c
= cmds
; c
->name
; c
++) {
236 if (strncmp(name
, c
->name
, sz
) == 0) {
237 if (c
->name
[sz
] == 0) {
241 die(EXIT_FAILURE
, "ambiguous command name `%s'", name
);
247 die(EXIT_FAILURE
, "unknown command name `%s'", name
);
251 /*----- Help and version information --------------------------------------*/
253 static void version(void)
254 { pquis(stdout
, "$ version " VERSION
"\n"); }
256 static void usage(FILE *fp
)
257 { pquis(fp
, "Usage: $ [-d DISPLAY] SUBCOMMAND [ARGUMENTS...]\n"); }
259 static void help(char **av
)
263 version(); putchar('\n');
267 Sets, retrieves and waits for properties on an X window.\n\
269 Global command-line options:\n\
271 -h, --help [COMMAND] Display this help, or help on COMMAND.\n\
272 -v, --version Display program's version number.\n\
273 -u, --usage Display short usage summary.\n\
275 -d, --display=DISPLAY Connect to X DISPLAY.\n\
276 -w, --window=WINDOW Use properties on WINDOW instead of root.\n\
278 The following subcommands are understood:\n\n",
280 for (c
= cmds
; c
->name
; c
++)
281 printf("%s\n", c
->usage
);
285 printf("Usage: %s [-OPTIONS] %s\n", QUIS
, c
->usage
);
288 pquis(stdout
, c
->help
);
290 if (*av
) putchar('\n');
295 /*----- Main program ------------------------------------------------------*/
297 int main(int argc
, char *argv
[])
307 /* --- Parse arguments --- */
310 static struct option opt
[] = {
311 { "help", 0, 0, 'h' },
312 { "usage", 0, 0, 'u' },
313 { "version", 0, 0, 'v' },
314 { "display", OPTF_ARGREQ
, 0, 'd' },
315 { "window", OPTF_ARGREQ
, 0, 'w' },
319 int i
= mdwopt(argc
, argv
, "+huvd:w:", opt
, 0, 0, 0);
322 case 'h': help(argv
+ optind
); exit(0);
323 case 'u': usage(stdout
); exit(0);
324 case 'v': version(); exit(0);
325 case 'd': dpy
= optarg
; break;
326 case 'w': win
= optarg
; break;
327 default: f
|= F_BOGUS
; break;
330 if ((f
& F_BOGUS
) || optind
>= argc
) {
335 /* --- Initialize --- */
338 if ((display
= XOpenDisplay(dpy
)) == 0)
339 die(EXIT_FAILURE
, "couldn't open display");
341 /* --- Select a target window --- */
344 window
= DefaultRootWindow(display
);
345 else if (strcmp(win
, "choose") == 0)
346 window
= choosewindow();
348 window
= (Window
)strtoul(win
, 0, 0);
350 /* --- Dispatch the command --- */
355 return (findcmd(argv
[0])->cmd(argc
, argv
));
360 /*----- That's all, folks -------------------------------------------------*/