X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=e97fc928944ba66a5f30de387d89c2661ef24aae;hb=8eb2873d7054e705c4e83f22d18c40946a9e2529;hp=3f43139860243883555f9a910c20f7155c579010;hpb=2a991a811de4c7b22f812682b267b616a809fd9a;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index 3f431398..e97fc928 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,6 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991, 1992, 1993, 1995, 1997, 1998 - * Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2001 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 @@ -31,8 +30,10 @@ # include /* for waitpid() and associated macros */ #endif -#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) +#if (defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)) || \ + defined(HAVE_SETRLIMIT) # include /* for setpriority() and PRIO_PROCESS */ + /* and also setrlimit() and RLIMIT_AS */ #endif #ifdef VMS @@ -67,13 +68,10 @@ extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ #include "xscreensaver.h" #include "yarandom.h" - +#include "visual.h" /* for id_to_visual() */ 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) { @@ -109,6 +107,64 @@ nice_subproc (int nice_level) } +/* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size + of a process's address space, i.e., the maximal brk(2) and mmap(2) values. + Setting this lets you put a cap on how much memory a process can allocate. + */ +#if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS) +# define RLIMIT_AS RLIMIT_VMEM +#endif + +static void +limit_subproc_memory (int address_space_limit, Bool verbose_p) +{ +#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_AS) + struct rlimit r; + + if (address_space_limit < 10 * 1024) /* let's not be crazy */ + return; + + if (getrlimit (RLIMIT_AS, &r) != 0) + { + char buf [512]; + sprintf (buf, "%s: getrlimit(RLIMIT_AS) failed", blurb()); + perror (buf); + return; + } + + r.rlim_cur = address_space_limit; + + if (setrlimit (RLIMIT_AS, &r) != 0) + { + char buf [512]; + sprintf (buf, "%s: setrlimit(RLIMIT_AS, {%lu, %lu}) failed", + blurb(), r.rlim_cur, r.rlim_max); + perror (buf); + return; + } + + if (verbose_p) + { + int i = address_space_limit; + char buf[100]; + if (i >= (1<<30) && i == ((i >> 30) << 30)) + sprintf(buf, "%dG", i >> 30); + else if (i >= (1<<20) && i == ((i >> 20) << 20)) + sprintf(buf, "%dM", i >> 20); + else if (i >= (1<<10) && i == ((i >> 10) << 10)) + sprintf(buf, "%dK", i >> 10); + else + sprintf(buf, "%d bytes", i); + + fprintf (stderr, "%s: limited pid %lu address space to %s.\n", + blurb(), (unsigned long) getpid (), buf); + } + +#endif /* HAVE_SETRLIMIT && RLIMIT_AS */ +} + + + #ifndef VMS static void @@ -172,9 +228,49 @@ exec_complex_command (const char *shell, const char *command) { char *av[5]; int ac = 0; - char *command2 = (char *) malloc (strlen (command) + 6); - memcpy (command2, "exec ", 5); - memcpy (command2 + 5, command, strlen (command) + 1); + char *command2 = (char *) malloc (strlen (command) + 10); + const char *s; + int got_eq = 0; + const char *after_vars; + + /* Skip leading whitespace. + */ + while (*command == ' ' || *command == '\t') + command++; + + /* If the string has a series of tokens with "=" in them at them, set + `after_vars' to point into the string after those tokens and any + trailing whitespace. Otherwise, after_vars == command. + */ + after_vars = command; + for (s = command; *s; s++) + { + if (*s == '=') got_eq = 1; + else if (*s == ' ') + { + if (got_eq) + { + while (*s == ' ' || *s == '\t') + s++; + after_vars = s; + got_eq = 0; + } + else + break; + } + } + + *command2 = 0; + strncat (command2, command, after_vars - command); + strcat (command2, "exec "); + strcat (command2, after_vars); + + /* We have now done these transformations: + "foo -x -y" ==> "exec foo -x -y" + "BLAT=foop foo -x" ==> "BLAT=foop exec foo -x" + "BLAT=foop A=b foo -x" ==> "BLAT=foop A=b exec foo -x" + */ + /* Invoke the shell as "/bin/sh -c 'exec prog -arg -arg ...'" */ av [ac++] = (char *) shell; @@ -209,7 +305,7 @@ exec_vms_command (const char *command) static void -exec_screenhack (saver_info *si, const char *command) +exec_screenhack (saver_screen_info *ssi, const char *command) { /* I don't believe what a sorry excuse for an operating system UNIX is! @@ -245,14 +341,28 @@ exec_screenhack (saver_info *si, const char *command) what I've seen in Emacs, dealing with process groups isn't especially portable.) */ + saver_info *si = ssi->global; 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 (getuid() == (uid_t) 0 || geteuid() == (uid_t) 0) + { + /* If you're thinking of commenting this out, think again. + If you do so, you will open a security hole. Mail jwz + so that he may enlighten you as to the error of your ways. + */ + fprintf (stderr, "%s: we're still running as root! Disaster!\n", + blurb()); + saver_exit (si, 1, 0); + } if (p->verbose_p) - fprintf (stderr, "%s: spawning \"%s\" in pid %lu%s.\n", - blurb(), command, (unsigned long) getpid (), + fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu%s.\n", + blurb(), ssi->number, command, + (unsigned long) getpid (), (hairy_p ? " (via shell)" : "")); if (hairy_p) @@ -265,8 +375,8 @@ exec_screenhack (saver_info *si, const char *command) #else /* VMS */ if (p->verbose_p) - fprintf (stderr, "%s: spawning \"%s\" in pid %lu.\n", - blurb(), command, getpid()); + fprintf (stderr, "%s: %d: spawning \"%s\" in pid %lu.\n", + blurb(), ssi->number, command, getpid()); exec_vms_command (command); #endif /* VMS */ @@ -291,6 +401,7 @@ enum job_status { struct screenhack_job { char *name; pid_t pid; + int screen; enum job_status status; struct screenhack_job *next; }; @@ -304,8 +415,9 @@ show_job_list (void) struct screenhack_job *job; fprintf(stderr, "%s: job list:\n", blurb()); for (job = jobs; job; job = job->next) - fprintf (stderr, " %5ld: (%s) %s\n", + fprintf (stderr, " %5ld: %2d: (%s) %s\n", (long) job->pid, + job->screen, (job->status == job_running ? "running" : job->status == job_stopped ? "stopped" : job->status == job_killed ? " killed" : @@ -318,31 +430,39 @@ show_job_list (void) static void clean_job_list (void); static struct screenhack_job * -make_job (pid_t pid, const char *cmd) +make_job (pid_t pid, int screen, const char *cmd) { struct screenhack_job *job = (struct screenhack_job *) malloc (sizeof(*job)); static char name [1024]; const char *in = cmd; char *out = name; + int got_eq = 0; + int first = 1; clean_job_list(); + AGAIN: while (isspace(*in)) in++; /* skip whitespace */ - while (!isspace(*in) && *in != ':') + while (!isspace(*in) && *in != ':') { + if (*in == '=') got_eq = 1; *out++ = *in++; /* snarf first token */ - while (isspace(*in)) in++; /* skip whitespace */ - if (*in == ':') /* token was a visual name; skip it. */ - { - in++; + } + + if (got_eq) /* if the first token was FOO=bar */ + { /* then get the next token instead. */ + got_eq = 0; out = name; - while (isspace(*in)) in++; /* skip whitespace */ - while (!isspace(*in)) *out++ = *in++; /* snarf first token */ + first = 0; + goto AGAIN; } + + while (isspace(*in)) in++; /* skip whitespace */ *out = 0; job->name = strdup(name); job->pid = pid; + job->screen = screen; job->status = job_running; job->next = jobs; jobs = job; @@ -419,7 +539,7 @@ static void describe_dead_child (saver_info *, pid_t, int wait_status); static int block_sigchld_handler = 0; -static void +void block_sigchld (void) { #ifdef HAVE_SIGACTION @@ -432,7 +552,7 @@ block_sigchld (void) block_sigchld_handler++; } -static void +void unblock_sigchld (void) { #ifdef HAVE_SIGACTION @@ -481,31 +601,27 @@ kill_job (saver_info *si, pid_t pid, int signal) default: abort(); } -#ifdef SIGSTOP - if (p->verbose_p) - fprintf (stderr, "%s: %s pid %lu.\n", blurb(), - (signal == SIGTERM ? "killing" : - signal == SIGSTOP ? "suspending" : - signal == SIGCONT ? "resuming" : "signalling"), - (unsigned long) job->pid); -#else /* !SIGSTOP */ if (p->verbose_p) - fprintf (stderr, "%s: %s pid %lu.\n", blurb(), "killing", - (unsigned long) job->pid); -#endif /* !SIGSTOP */ + fprintf (stderr, "%s: %d: %s pid %lu (%s)\n", + blurb(), job->screen, + (job->status == job_killed ? "killing" : + job->status == job_stopped ? "suspending" : "resuming"), + (unsigned long) job->pid, + job->name); status = kill (job->pid, signal); if (p->verbose_p && status < 0) { if (errno == ESRCH) - fprintf (stderr, "%s: child process %lu (%s) was already dead.\n", - blurb(), job->pid, job->name); + fprintf (stderr, + "%s: %d: child process %lu (%s) was already dead.\n", + blurb(), job->screen, job->pid, job->name); else { char buf [1024]; - sprintf (buf, "%s: couldn't kill child process %lu (%s)", - blurb(), job->pid, job->name); + sprintf (buf, "%s: %d: couldn't kill child process %lu (%s)", + blurb(), job->screen, job->pid, job->name); perror (buf); } } @@ -587,6 +703,7 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) saver_preferences *p = &si->prefs; struct screenhack_job *job = find_job (kid); const char *name = job ? job->name : ""; + int screen_no = job ? job->screen : 0; if (WIFEXITED (wait_status)) { @@ -605,11 +722,11 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) (exit_status != 0 && (p->verbose_p || job->status != job_killed))) fprintf (stderr, - "%s: child pid %lu (%s) exited abnormally (code %d).\n", - blurb(), (unsigned long) kid, name, exit_status); + "%s: %d: child pid %lu (%s) exited abnormally (code %d).\n", + blurb(), screen_no, (unsigned long) kid, name, exit_status); else if (p->verbose_p) - fprintf (stderr, "%s: child pid %lu (%s) exited normally.\n", - blurb(), (unsigned long) kid, name); + fprintf (stderr, "%s: %d: child pid %lu (%s) exited normally.\n", + blurb(), screen_no, (unsigned long) kid, name); if (job) job->status = job_dead; @@ -620,8 +737,8 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) !job || job->status != job_killed || WTERMSIG (wait_status) != SIGTERM) - fprintf (stderr, "%s: child pid %lu (%s) terminated with %s.\n", - blurb(), (unsigned long) kid, name, + fprintf (stderr, "%s: %d: child pid %lu (%s) terminated with %s.\n", + blurb(), screen_no, (unsigned long) kid, name, signal_name (WTERMSIG(wait_status))); if (job) @@ -703,35 +820,25 @@ init_sigchld (void) static Bool -select_visual_of_hack (saver_screen_info *ssi, const char *hack) +select_visual_of_hack (saver_screen_info *ssi, screenhack *hack) { saver_info *si = ssi->global; saver_preferences *p = &si->prefs; Bool selected; - static char vis [1024]; - const char *in = hack; - char *out = vis; - while (isspace(*in)) in++; /* skip whitespace */ - while (!isspace(*in) && *in != ':') - *out++ = *in++; /* snarf first token */ - while (isspace(*in)) in++; /* skip whitespace */ - *out = 0; - if (*in == ':') - selected = select_visual(ssi, vis); + if (hack->visual && *hack->visual) + selected = select_visual(ssi, hack->visual); else selected = select_visual(ssi, 0); - if (!selected && (p->verbose_p || si->demo_mode_p)) - { - if (*in == ':') in++; - while (isspace(*in)) in++; - fprintf (stderr, - (si->demo_mode_p - ? "%s: warning, no \"%s\" visual for \"%s\".\n" - : "%s: no \"%s\" visual; skipping \"%s\".\n"), - blurb(), (vis ? vis : "???"), in); - } + if (!selected && (p->verbose_p || si->demoing_p)) + fprintf (stderr, + (si->demoing_p + ? "%s: warning, no \"%s\" visual for \"%s\".\n" + : "%s: no \"%s\" visual; skipping \"%s\".\n"), + blurb(), + (hack->visual && *hack->visual ? hack->visual : "???"), + hack->command); return selected; } @@ -745,81 +852,107 @@ 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; + screenhack *hack; pid_t forked; char buf [255]; int new_hack; - - if (si->demo_mode_p) + int retry_count = 0; + Bool force = False; + + AGAIN: + + if (p->screenhacks_count < 1) + { + /* No hacks at all */ + new_hack = -1; + } + else if (si->selection_mode == -1) + { + /* Select the next hack, wrapping. */ + new_hack = (ssi->current_hack + 1) % p->screenhacks_count; + } + else if (si->selection_mode == -2) + { + /* Select the previous hack, wrapping. */ + if (ssi->current_hack < 0) + new_hack = p->screenhacks_count - 1; + else + new_hack = ((ssi->current_hack + p->screenhacks_count - 1) + % p->screenhacks_count); + } + else if (si->selection_mode > 0) { - hack = si->demo_hack; - - /* Ignore visual-selection failure if in demo mode. */ - (void) select_visual_of_hack (ssi, hack); + /* Select a specific hack, by number (via the ACTIVATE command.) */ + new_hack = ((si->selection_mode - 1) % p->screenhacks_count); + force = True; } - else + else if (p->mode == ONE_HACK && + p->selected_hack >= 0) { - int retry_count = 0; - - AGAIN: - if (p->screenhacks_count == 1) - new_hack = 0; - else if (si->selection_mode == -1) - new_hack = (ssi->current_hack + 1) % p->screenhacks_count; - else if (si->selection_mode == -2) - new_hack = ((ssi->current_hack + p->screenhacks_count - 1) - % p->screenhacks_count); - else if (si->selection_mode > 0) - new_hack = ((si->selection_mode - 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 specific hack, by number (via "One Saver" mode.) */ + new_hack = p->selected_hack; + force = True; + } + else if (p->mode == BLANK_ONLY || p->mode == DONT_BLANK) + { + new_hack = -1; + } + else /* (p->mode == RANDOM_HACKS) */ + { + /* 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)) + if (new_hack < 0) /* don't run a hack */ + { + ssi->current_hack = -1; + if (si->selection_mode < 0) + si->selection_mode = 0; + return; + } + + 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 || + !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; } + /* 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. - */ - { - char *in = hack; - while (isspace(*in)) in++; /* skip whitespace */ - hack = in; - while (!isspace(*in) && *in != ':') in++; /* snarf first token */ - while (isspace(*in)) in++; /* skip whitespace */ - if (*in == ':') - { - in++; - while (isspace(*in)) in++; - hack = in; - } - } - switch ((int) (forked = fork ())) { case -1: @@ -831,14 +964,15 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) case 0: close (ConnectionNumber (si->dpy)); /* close display fd */ nice_subproc (p->nice_inferior); /* change process priority */ + limit_subproc_memory (p->inferior_memory_limit, p->verbose_p); hack_subproc_environment (ssi); /* set $DISPLAY */ - exec_screenhack (si, hack); /* this does not return */ + exec_screenhack (ssi, hack->command); /* this does not return */ abort(); break; default: ssi->pid = forked; - (void) make_job (forked, hack); + (void) make_job (forked, ssi->number, hack->command); break; } } @@ -848,22 +982,21 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) void spawn_screenhack (saver_info *si, Bool first_time_p) { - int i; - - if (!monitor_powered_on_p (si)) + if (monitor_powered_on_p (si)) { - if (si->prefs.verbose_p) - fprintf (stderr, - "%s: server reports that monitor has powered down; " - "not launching a new hack.\n", blurb()); - return; + int i; + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + spawn_screenhack_1 (ssi, first_time_p); + } } + else if (si->prefs.verbose_p) + fprintf (stderr, + "%s: X says monitor has powered down; " + "not launching a hack.\n", blurb()); - for (i = 0; i < si->nscreens; i++) - { - saver_screen_info *ssi = &si->screens[i]; - spawn_screenhack_1 (ssi, first_time_p); - } + store_saver_status (si); /* store current hack numbers */ } @@ -919,15 +1052,14 @@ emergency_kill_subproc (saver_info *si) Bool screenhack_running_p (saver_info *si) { - Bool result = True; + Bool any_running_p = False; int i; for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; - if (!ssi->pid) - result = False; + if (ssi->pid) any_running_p = True; } - return result; + return any_running_p; } @@ -958,7 +1090,7 @@ hack_environment (saver_info *si) } -static void +void hack_subproc_environment (saver_screen_info *ssi) { /* Store $DISPLAY into the environment, so that the $DISPLAY variable that @@ -973,13 +1105,8 @@ hack_subproc_environment (saver_screen_info *ssi) saver_info *si = ssi->global; const char *odpy = DisplayString (si->dpy); char *ndpy = (char *) malloc(strlen(odpy) + 20); - int screen_number; char *s; - for (screen_number = 0; screen_number < si->nscreens; screen_number++) - if (ssi == &si->screens[screen_number]) - break; - strcpy (ndpy, "DISPLAY="); s = ndpy + strlen(ndpy); strcpy (s, odpy); @@ -989,7 +1116,7 @@ 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", screen_number); /* put on screen number */ + sprintf(s, "%d", ssi->number); /* put on screen number */ /* 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. */ @@ -999,6 +1126,112 @@ hack_subproc_environment (saver_screen_info *ssi) #endif /* HAVE_PUTENV */ } + +/* GL crap */ + +Visual * +get_best_gl_visual (saver_screen_info *ssi) +{ + saver_info *si = ssi->global; + pid_t forked; + int fds [2]; + int in, out; + char buf[1024]; + + char *av[10]; + int ac = 0; + + av[ac++] = "xscreensaver-gl-helper"; + av[ac] = 0; + + if (pipe (fds)) + { + perror ("error creating pipe:"); + return 0; + } + + in = fds [0]; + out = fds [1]; + + switch ((int) (forked = fork ())) + { + case -1: + { + sprintf (buf, "%s: couldn't fork", blurb()); + perror (buf); + saver_exit (si, 1, 0); + } + case 0: + { + int stdout_fd = 1; + + close (in); /* don't need this one */ + close (ConnectionNumber (si->dpy)); /* close display fd */ + + if (dup2 (out, stdout_fd) < 0) /* pipe stdout */ + { + perror ("could not dup() a new stdout:"); + return 0; + } + hack_subproc_environment (ssi); /* set $DISPLAY */ + + execvp (av[0], av); /* shouldn't return. */ + + if (errno != ENOENT || si->prefs.verbose_p) + { + /* Ignore "no such file or directory" errors, unless verbose. + Issue all other exec errors, though. */ + sprintf (buf, "%s: running %s", blurb(), av[0]); + perror (buf); + } + exit (1); /* exits fork */ + break; + } + default: + { + int result = 0; + int wait_status = 0; + + FILE *f = fdopen (in, "r"); + unsigned long v = 0; + char c; + + close (out); /* don't need this one */ + + *buf = 0; + fgets (buf, sizeof(buf)-1, f); + fclose (f); + + /* Wait for the child to die. */ + waitpid (-1, &wait_status, 0); + + if (1 == sscanf (buf, "0x%x %c", &v, &c)) + result = (int) v; + + if (result == 0) + { + if (si->prefs.verbose_p) + fprintf (stderr, "%s: %s did not report a GL visual!\n", + blurb(), av[0]); + return 0; + } + else + { + Visual *v = id_to_visual (ssi->screen, result); + if (si->prefs.verbose_p) + fprintf (stderr, "%s: %d: %s: GL visual is 0x%X%s.\n", + blurb(), ssi->number, + av[0], result, + (v == ssi->default_visual ? " (default)" : "")); + return v; + } + } + } + + abort(); +} + + /* Restarting the xscreensaver process from scratch. */ @@ -1007,7 +1240,6 @@ static char **saved_argv; void save_argv (int argc, char **argv) { - /* Leave room for one more argument, the -initial-demo-mode switch. */ saved_argv = (char **) calloc (argc+2, sizeof (char *)); saved_argv [argc] = 0; while (argc--) @@ -1018,45 +1250,24 @@ save_argv (int argc, char **argv) } } -/* Modifies saved_argv to either contain or not contain "-initial-demo-mode". + +/* Re-execs the process with the arguments in saved_argv. + Does not return unless there was an error. */ -static void -hack_saved_argv (Bool demo_mode_p) +void +restart_process (saver_info *si) { - static char *demo_mode_switch = "-initial-demo-mode"; - - if (demo_mode_p) /* We want the switch to be in the args. */ - { - /* See if the switch is there already. If so, we're done. */ - int i; - for (i = 0; saved_argv[i]; i++) - if (!strcmp (saved_argv[i], demo_mode_switch)) - return; - - /* If it wasn't there, add it to the end. save_argv() made room. */ - saved_argv [i] = demo_mode_switch; - saved_argv [i+1] = 0; - } - else /* We want the switch to not be in the args. */ + if (si->prefs.verbose_p) { int i; + fprintf (real_stderr, "%s: re-executing", blurb()); for (i = 0; saved_argv[i]; i++) - while (!strcmp (saved_argv [i], demo_mode_switch)) - { - int j; - for (j = i; saved_argv[j]; j++) - saved_argv [j] = saved_argv [j+1]; - } + fprintf (real_stderr, " %s", saved_argv[i]); + fprintf (real_stderr, "\n"); } -} - + describe_uids (si, real_stderr); + fprintf (real_stderr, "\n"); -/* Re-execs the process with the arguments in saved_argv. - Does not return unless there was an error. - */ -static void -restart_process_1 (saver_info *si) -{ fflush (real_stdout); fflush (real_stderr); execvp (saved_argv [0], saved_argv); /* shouldn't return */ @@ -1068,26 +1279,3 @@ restart_process_1 (saver_info *si) } XBell(si->dpy, 0); } - - -/* Re-execs the process with the arguments in saved_argv, - minus -initial-demo-mode. - Does not return unless there was an error. - */ -void -restart_process (saver_info *si) -{ - hack_saved_argv (True); - restart_process_1 (si); -} - -/* Re-execs the process with the arguments in saved_argv, - plus -initial-demo-mode. - Does not return unless there was an error. - */ -void -demo_mode_restart_process (saver_info *si) -{ - hack_saved_argv (False); - restart_process_1 (si); -}