X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utils%2Fgrabclient.c;h=7b5298dffd156f653653a550fae454f332de4dab;hb=e4fa2ac140f7bc56571373a7b7eb585fa4500e38;hp=92481b20292181a0da98844acc36ea286a2c233a;hpb=40eacb5812ef7c0e3374fb139afbb4f5bc8bbfb5;p=xscreensaver diff --git a/utils/grabclient.c b/utils/grabclient.c index 92481b20..7b5298df 100644 --- a/utils/grabclient.c +++ b/utils/grabclient.c @@ -26,6 +26,14 @@ #include "vroot.h" #include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_WAIT_H +# include /* for waitpid() and associated macros */ +#endif + + extern char *progname; @@ -104,13 +112,13 @@ static void checkerboard (Screen *screen, Drawable drawable) { Display *dpy = DisplayOfScreen (screen); - int x, y; + unsigned int x, y; int size = 24; XColor fg, bg; XGCValues gcv; GC gc = XCreateGC (dpy, drawable, 0, &gcv); Colormap cmap; - int win_width, win_height; + unsigned int win_width, win_height; fg.flags = bg.flags = DoRed|DoGreen|DoBlue; fg.red = fg.green = fg.blue = 0x0000; @@ -176,11 +184,62 @@ hack_subproc_environment (Display *dpy) } +/* Spawn a program, and wait for it to finish. + If we just use system() for this, then sometimes the subprocess + doesn't die when *this* process is sent a TERM signal. Perhaps + this is due to the intermediate /bin/sh that system() uses to + parse arguments? I'm not sure. But using fork() and execvp() + here seems to close the race. + */ + +static void +exec_simple_command (const char *command) +{ + char *av[1024]; + int ac = 0; + char *token = strtok (strdup(command), " \t"); + while (token) + { + av[ac++] = token; + token = strtok(0, " \t"); + } + av[ac] = 0; + + execvp (av[0], av); /* shouldn't return. */ +} + +static void +fork_exec_wait (const char *command) +{ + char buf [255]; + pid_t forked; + int status; + + switch ((int) (forked = fork ())) + { + case -1: + sprintf (buf, "%s: couldn't fork", progname); + perror (buf); + return; + + case 0: + exec_simple_command (command); + exit (1); /* exits child fork */ + break; + + default: + waitpid (forked, &status, 0); + break; + } +} + + /* Loads an image into the Drawable. When grabbing desktop images, the Window will be unmapped first. */ void -load_random_image (Screen *screen, Window window, Drawable drawable) +load_random_image (Screen *screen, Window window, Drawable drawable, + char **name_ret) { Display *dpy = DisplayOfScreen (screen); char *grabber = get_string_resource ("desktopGrabber", "DesktopGrabber"); @@ -215,7 +274,27 @@ load_random_image (Screen *screen, Window window, Drawable drawable) XSync (dpy, True); hack_subproc_environment (dpy); - system (cmd); + fork_exec_wait (cmd); free (cmd); XSync (dpy, True); + + if (name_ret) + { + Atom type; + int format; + unsigned long nitems, bytesafter; + char *name=NULL; + + *name_ret = NULL; + + if (XGetWindowProperty (dpy, window, + XInternAtom (dpy, XA_XSCREENSAVER_IMAGE_FILENAME, + False), + 0, 1024, False, XA_STRING, + &type, &format, &nitems, &bytesafter, + (unsigned char **) &name) + == Success + && type != None) + *name_ret = strdup(name); + } }