X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=ffabe483f3b2936697e7262dc3749156c39a3ea8;hb=3f438031d610c7e15fd33876a879b97e290e05fb;hp=463b3189450310fbbeb2f8e5ae552c17537de79e;hpb=96bdd7cf6ea60c418a76921acaf0e34d6f5be930;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index 463b3189..ffabe483 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,5 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991-2003 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2005 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -655,6 +655,60 @@ print_path_error (const char *program) } +/* Executes the command in another process. + Command may be any single command acceptable to /bin/sh. + It may include wildcards, but no semicolons. + If successful, the pid of the other process is returned. + Otherwise, -1 is returned and an error may have been + printed to stderr. + */ +pid_t +fork_and_exec (saver_screen_info *ssi, const char *command) +{ + saver_info *si = ssi->global; + saver_preferences *p = &si->prefs; + pid_t forked; + + switch ((int) (forked = fork ())) + { + case -1: + { + char buf [255]; + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + break; + } + + case 0: + close (ConnectionNumber (si->dpy)); /* close display fd */ + limit_subproc_memory (p->inferior_memory_limit, p->verbose_p); + hack_subproc_environment (ssi); /* set $DISPLAY */ + + if (p->verbose_p) + fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n", + blurb(), ssi->number, command, + (unsigned long) getpid ()); + + exec_command (p->shell, command, p->nice_inferior); + + /* If that returned, we were unable to exec the subprocess. + Print an error message, if desired. + */ + if (! p->ignore_uninstalled_p) + print_path_error (command); + + exit (1); /* exits child fork */ + break; + + default: /* parent */ + (void) make_job (forked, ssi->number, command); + break; + } + + return forked; +} + + static void spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) { @@ -668,7 +722,7 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) screenhack *hack; pid_t forked; char buf [255]; - int new_hack; + int new_hack = -1; int retry_count = 0; Bool force = False; @@ -715,6 +769,14 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) { new_hack = -1; } + else if (p->mode == RANDOM_HACKS_SAME && + ssi->number != 0) + { + /* Use the same hack that's running on screen 0. + (Assumes this function was called on screen 0 first.) + */ + new_hack = si->screens[0].current_hack; + } else /* (p->mode == RANDOM_HACKS) */ { /* Select a random hack (but not the one we just ran.) */ @@ -769,38 +831,19 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) if (si->selection_mode < 0) si->selection_mode = 0; - switch ((int) (forked = fork ())) + forked = fork_and_exec (ssi, hack->command); + switch ((int) forked) { - case -1: + case -1: /* fork failed */ + case 0: /* child fork (can't happen) */ sprintf (buf, "%s: couldn't fork", blurb()); perror (buf); restore_real_vroot (si); - saver_exit (si, 1, 0); - - case 0: - close (ConnectionNumber (si->dpy)); /* close display fd */ - limit_subproc_memory (p->inferior_memory_limit, p->verbose_p); - hack_subproc_environment (ssi); /* set $DISPLAY */ - - if (p->verbose_p) - fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n", - blurb(), ssi->number, hack->command, - (unsigned long) getpid ()); - - exec_command (p->shell, hack->command, p->nice_inferior); - - /* If that returned, we were unable to exec the subprocess. - Print an error message, if desired. - */ - if (! p->ignore_uninstalled_p) - print_path_error (hack->command); - - exit (1); /* exits child fork */ + saver_exit (si, 1, "couldn't fork"); break; default: ssi->pid = forked; - (void) make_job (forked, ssi->number, hack->command); break; } } @@ -934,10 +977,15 @@ hack_subproc_environment (saver_screen_info *ssi) be the screen on which this particular hack is running -- not the display specification which the driver itself is using, since the driver ignores its screen number and manages all existing screens. + + Likewise, store a window ID in $XSCREENSAVER_WINDOW -- this will allow + us to (eventually) run multiple hacks in Xinerama mode, where each hack + has the same $DISPLAY but a different piece of glass. */ saver_info *si = ssi->global; const char *odpy = DisplayString (si->dpy); - char *ndpy = (char *) malloc(strlen(odpy) + 20); + char *ndpy = (char *) malloc (strlen(odpy) + 20); + char *nssw = (char *) malloc (40); char *s; strcpy (ndpy, "DISPLAY="); @@ -949,14 +997,23 @@ hack_subproc_environment (saver_screen_info *ssi) while (isdigit(*s)) s++; /* skip over dpy number */ while (*s == '.') s++; /* skip over dot */ if (s[-1] != '.') *s++ = '.'; /* put on a dot */ - sprintf(s, "%d", ssi->number); /* put on screen number */ + sprintf(s, "%d", ssi->real_screen_number); /* put on screen number */ + + sprintf (nssw, "XSCREENSAVER_WINDOW=0x%lX", + (unsigned long) ssi->screensaver_window); /* Allegedly, BSD 4.3 didn't have putenv(), but nobody runs such systems any more, right? It's not Posix, but everyone seems to have it. */ #ifdef HAVE_PUTENV if (putenv (ndpy)) abort (); - /* do not free(ndpy) -- see above. */ + if (putenv (nssw)) + abort (); + + /* don't free ndpy/nssw -- some implementations of putenv (BSD 4.4, + glibc 2.0) copy the argument, but some (libc4,5, glibc 2.1.2) + do not. So we must leak it (and/or the previous setting). Yay. + */ #endif /* HAVE_PUTENV */ }