X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=driver%2Fsubprocs.c;h=8b6187d9a1b6732cfb17ee13c895e3c570df625c;hp=166ae5996f573b5e7a4a24d04497268362b83676;hb=551b3de3f619c04c2dd1971ee9b3f02e270c28c9;hpb=ce3185de9d9705e259f2b60dd4b5509007fa17d4 diff --git a/driver/subprocs.c b/driver/subprocs.c index 166ae599..8b6187d9 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -22,39 +22,39 @@ #include /* not used for much... */ #ifndef ESRCH -#include +# include #endif #include /* sys/resource.h needs this for timeval */ -#ifndef VMS - -# include /* for setpriority() and PRIO_PROCESS */ +#ifdef HAVE_SYS_WAIT_H # include /* for waitpid() and associated macros */ +#endif -#else /* VMS */ - -# if __DECC_VER >= 50200000 -# include -# endif +#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) +# include /* for setpriority() and PRIO_PROCESS */ +#endif +#ifdef VMS # include # include /* for close */ # include /* for getpid */ -# define pid_t int -# define fork vfork - +# define pid_t int +# define fork vfork #endif /* VMS */ #include /* for the signal names */ #if !defined(SIGCHLD) && defined(SIGCLD) -#define SIGCHLD SIGCLD +# define SIGCHLD SIGCLD #endif +#if 0 /* putenv() is declared in stdlib.h on modern linux systems. */ #ifdef HAVE_PUTENV extern int putenv (/* const char * */); /* getenv() is in stdlib.h... */ #endif +#endif + extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ /* This file doesn't need the Xt headers, so stub these types out... */ @@ -71,9 +71,6 @@ extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ extern saver_info *global_si_kludge; /* I hate C so much... */ -static void hack_subproc_environment (saver_screen_info *ssi); - - static void nice_subproc (int nice_level) { @@ -248,7 +245,8 @@ exec_screenhack (saver_info *si, const char *command) saver_preferences *p = &si->prefs; #ifndef VMS - Bool hairy_p = !!strpbrk (command, "*?$&!<>[];`'\\\""); + Bool hairy_p = !!strpbrk (command, "*?$&!<>[];`'\\\"="); + /* note: = is in the above because of the sh syntax "FOO=bar cmd". */ if (p->verbose_p) fprintf (stderr, "%s: spawning \"%s\" in pid %lu%s.\n", @@ -702,6 +700,14 @@ init_sigchld (void) +static Bool +hack_enabled_p (const char *hack) +{ + const char *s = hack; + while (isspace(*s)) s++; + return (*s != '-'); +} + static Bool select_visual_of_hack (saver_screen_info *ssi, const char *hack) { @@ -712,6 +718,9 @@ select_visual_of_hack (saver_screen_info *ssi, const char *hack) const char *in = hack; char *out = vis; while (isspace(*in)) in++; /* skip whitespace */ + if (*in == '-') in++; /* skip optional "-" */ + while (isspace(*in)) in++; /* skip whitespace */ + while (!isspace(*in) && *in != ':') *out++ = *in++; /* snarf first token */ while (isspace(*in)) in++; /* skip whitespace */ @@ -722,15 +731,15 @@ select_visual_of_hack (saver_screen_info *ssi, const char *hack) else selected = select_visual(ssi, 0); - if (!selected && (p->verbose_p || si->demo_mode_p)) + if (!selected && (p->verbose_p || si->demoing_p)) { if (*in == ':') in++; while (isspace(*in)) in++; fprintf (stderr, - (si->demo_mode_p + (si->demoing_p ? "%s: warning, no \"%s\" visual for \"%s\".\n" : "%s: no \"%s\" visual; skipping \"%s\".\n"), - blurb(), (vis ? vis : "???"), in); + blurb(), (*vis ? vis : "???"), in); } return selected; @@ -745,59 +754,81 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) raise_window (si, first_time_p, True, False); XFlush (si->dpy); - if (p->screenhacks_count || si->demo_mode_p) + if (p->screenhacks_count) { char *hack; pid_t forked; char buf [255]; int new_hack; + int retry_count = 0; + Bool force = False; - if (si->demo_mode_p) - { - hack = si->demo_hack; + AGAIN: + + if (p->screenhacks_count == 1) + /* If there is only one hack in the list, there is no choice. */ + new_hack = 0; + + else if (si->selection_mode == -1) + /* Select the next hack, wrapping. */ + new_hack = (ssi->current_hack + 1) % p->screenhacks_count; - /* Ignore visual-selection failure if in demo mode. */ - (void) select_visual_of_hack (ssi, hack); + else if (si->selection_mode == -2) + /* Select the previous hack, wrapping. */ + new_hack = ((ssi->current_hack + p->screenhacks_count - 1) + % p->screenhacks_count); + + else if (si->selection_mode > 0) + /* Select a specific hack, by number. No negotiation. */ + { + new_hack = ((si->selection_mode - 1) % p->screenhacks_count); + force = True; } else { - int retry_count = 0; - - AGAIN: - if (p->screenhacks_count == 1) - new_hack = 0; - else if (si->next_mode_p == 1) - new_hack = (ssi->current_hack + 1) % p->screenhacks_count; - else if (si->next_mode_p == 2) - new_hack = ((ssi->current_hack + p->screenhacks_count - 1) - % p->screenhacks_count); - else - while ((new_hack = random () % p->screenhacks_count) - == ssi->current_hack) - ; - ssi->current_hack = new_hack; - hack = p->screenhacks[ssi->current_hack]; + /* Select a random hack (but not the one we just ran.) */ + while ((new_hack = random () % p->screenhacks_count) + == ssi->current_hack) + ; + } - if (!select_visual_of_hack (ssi, hack)) + ssi->current_hack = new_hack; + hack = p->screenhacks[ssi->current_hack]; + + /* If the hack is disabled, or there is no visual for this hack, + then try again (move forward, or backward, or re-randomize.) + Unless this hack was specified explicitly, in which case, + use it regardless. + */ + if (force) + select_visual_of_hack (ssi, hack); + + if (!force && + (!hack_enabled_p (hack) || + !select_visual_of_hack (ssi, hack))) + { + if (++retry_count > (p->screenhacks_count*4)) { - if (++retry_count > (p->screenhacks_count*4)) - { - /* Uh, oops. Odds are, there are no suitable visuals, - and we're looping. Give up. (This is totally lame, - what we should do is make a list of suitable hacks at - the beginning, then only loop over them.) - */ - if (p->verbose_p) - fprintf(stderr, - "%s: no suitable visuals for these programs.\n", - blurb()); - return; - } - else - goto AGAIN; + /* Uh, oops. Odds are, there are no suitable visuals, + and we're looping. Give up. (This is totally lame, + what we should do is make a list of suitable hacks at + the beginning, then only loop over them.) + */ + if (p->verbose_p) + fprintf(stderr, + "%s: no suitable visuals for these programs.\n", + blurb()); + return; } + else + goto AGAIN; } - si->next_mode_p = 0; + + /* Turn off "next" and "prev" modes now, but "demo" mode is only + turned off by explicit action. + */ + if (si->selection_mode < 0) + si->selection_mode = 0; /* If there's a visual description on the front of the command, nuke it. @@ -805,6 +836,8 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) { char *in = hack; while (isspace(*in)) in++; /* skip whitespace */ + if (*in == '-') in++; /* skip optional "-" */ + while (isspace(*in)) in++; /* skip whitespace */ hack = in; while (!isspace(*in) && *in != ':') in++; /* snarf first token */ while (isspace(*in)) in++; /* skip whitespace */ @@ -927,53 +960,34 @@ screenhack_running_p (saver_info *si) } -/* Restarting the xscreensaver process from scratch. */ +/* Environment variables. */ -static char **saved_argv; +/* Modifies $PATH in the current environment, so that if DEFAULT_PATH_PREFIX + is defined, the xscreensaver daemon will search that directory for hacks. + */ void -save_argv (int argc, char **argv) +hack_environment (saver_info *si) { - saved_argv = (char **) malloc ((argc + 2) * sizeof (char *)); - saved_argv [argc] = 0; - while (argc--) +#if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX) + static const char *def_path = DEFAULT_PATH_PREFIX; + if (def_path && *def_path) { - int i = strlen (argv [argc]) + 1; - saved_argv [argc] = (char *) malloc (i); - memcpy (saved_argv [argc], argv [argc], i); + const char *opath = getenv("PATH"); + char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20); + strcpy (npath, "PATH="); + strcat (npath, def_path); + strcat (npath, ":"); + strcat (npath, opath); + + if (putenv (npath)) + abort (); } +#endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */ } -void -restart_process (saver_info *si) -{ - fflush (real_stdout); - fflush (real_stderr); - execvp (saved_argv [0], saved_argv); /* shouldn't return */ - { - char buf [512]; - sprintf (buf, "%s: could not restart process", blurb()); - perror(buf); - fflush(stderr); - } -} -/* Like restart_process(), but ensures that when it restarts, - it comes up in demo-mode. */ void -demo_mode_restart_process (saver_info *si) -{ - int i; - for (i = 0; saved_argv [i]; i++); - /* add the -initial-demo-mode switch; save_argv() left room for this. */ - saved_argv [i] = "-initial-demo-mode"; - saved_argv [i+1] = 0; - restart_process (si); /* shouldn't return */ - saved_argv [i] = 0; - XBell(si->dpy, 0); -} - -static void hack_subproc_environment (saver_screen_info *ssi) { /* Store $DISPLAY into the environment, so that the $DISPLAY variable that @@ -994,7 +1008,6 @@ hack_subproc_environment (saver_screen_info *ssi) for (screen_number = 0; screen_number < si->nscreens; screen_number++) if (ssi == &si->screens[screen_number]) break; - if (screen_number >= si->nscreens) abort(); strcpy (ndpy, "DISPLAY="); s = ndpy + strlen(ndpy); @@ -1015,23 +1028,50 @@ hack_subproc_environment (saver_screen_info *ssi) #endif /* HAVE_PUTENV */ } + +/* Restarting the xscreensaver process from scratch. */ + +static char **saved_argv; void -hack_environment (saver_info *si) +save_argv (int argc, char **argv) { -#if defined(HAVE_PUTENV) && defined(DEFAULT_PATH_PREFIX) - static const char *def_path = DEFAULT_PATH_PREFIX; - if (def_path && *def_path) + saved_argv = (char **) calloc (argc+2, sizeof (char *)); + saved_argv [argc] = 0; + while (argc--) { - const char *opath = getenv("PATH"); - char *npath = (char *) malloc(strlen(def_path) + strlen(opath) + 20); - strcpy (npath, "PATH="); - strcat (npath, def_path); - strcat (npath, ":"); - strcat (npath, opath); + int i = strlen (argv [argc]) + 1; + saved_argv [argc] = (char *) malloc (i); + memcpy (saved_argv [argc], argv [argc], i); + } +} - if (putenv (npath)) - abort (); + +/* Re-execs the process with the arguments in saved_argv. + Does not return unless there was an error. + */ +void +restart_process (saver_info *si) +{ + if (si->prefs.verbose_p) + { + int i; + fprintf (real_stderr, "%s: re-executing", blurb()); + for (i = 0; saved_argv[i]; i++) + fprintf (real_stderr, " %s", saved_argv[i]); + fprintf (real_stderr, "\n"); } -#endif /* HAVE_PUTENV && DEFAULT_PATH_PREFIX */ + describe_uids (si, real_stderr); + fprintf (real_stderr, "\n"); + + fflush (real_stdout); + fflush (real_stderr); + execvp (saved_argv [0], saved_argv); /* shouldn't return */ + { + char buf [512]; + sprintf (buf, "%s: could not restart process", blurb()); + perror(buf); + fflush(stderr); + } + XBell(si->dpy, 0); }