X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=c693d5b68a6cb6b0180d15dbd848bd3c469569b3;hb=72c1f4c1dc6ab07fe121a327ff1c30bf51ef74c1;hp=4126960b0bc177a0c8a48a349c6c499e569de782;hpb=df053bcb240bd8d82e3bebf48a9766a8728bca4b;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index 4126960b..c693d5b6 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,6 +1,6 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. * xscreensaver, Copyright (c) 1991, 1992, 1993, 1995, 1997, 1998 - * Jamie Zawinski + * 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 @@ -22,44 +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 */ -#ifndef NO_SETUID -#include /* for getpwnam() and struct passwd */ -#include /* for getgrgid() and struct group */ -#endif /* NO_SETUID */ - #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... */ @@ -76,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_environment (saver_screen_info *ssi); - - static void nice_subproc (int nice_level) { @@ -93,7 +85,7 @@ nice_subproc (int nice_level) if (nice (n) == -1 && errno != 0) { char buf [512]; - sprintf (buf, "%s: nice(%d) failed", progname, n); + sprintf (buf, "%s: nice(%d) failed", blurb(), n); perror (buf); } } @@ -102,13 +94,13 @@ nice_subproc (int nice_level) { char buf [512]; sprintf (buf, "%s: setpriority(PRIO_PROCESS, %lu, %d) failed", - progname, (unsigned long) getpid(), nice_level); + blurb(), (unsigned long) getpid(), nice_level); perror (buf); } #else fprintf (stderr, "%s: don't know how to change process priority on this system.\n", - progname); + blurb()); #endif } @@ -133,7 +125,7 @@ exec_simple_command (const char *command) { char buf [512]; - sprintf (buf, "%s: could not execute \"%s\"", progname, av[0]); + sprintf (buf, "%s: could not execute \"%s\"", blurb(), av[0]); perror (buf); if (errno == ENOENT && @@ -177,9 +169,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; @@ -191,7 +223,7 @@ exec_complex_command (const char *shell, const char *command) { char buf [512]; - sprintf (buf, "%s: execvp(\"%s\") failed", progname, av[0]); + sprintf (buf, "%s: execvp(\"%s\") failed", blurb(), av[0]); perror (buf); fflush(stderr); fflush(stdout); @@ -253,12 +285,24 @@ 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 (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) - printf ("%s: spawning \"%s\" in pid %lu%s.\n", - progname, command, (unsigned long) getpid (), - (hairy_p ? " (via shell)" : "")); + fprintf (stderr, "%s: spawning \"%s\" in pid %lu%s.\n", + blurb(), command, (unsigned long) getpid (), + (hairy_p ? " (via shell)" : "")); if (hairy_p) /* If it contains any shell metacharacters, do it the hard way, @@ -270,7 +314,8 @@ exec_screenhack (saver_info *si, const char *command) #else /* VMS */ if (p->verbose_p) - printf ("%s: spawning \"%s\" in pid %lu.\n", progname, command, getpid()); + fprintf (stderr, "%s: spawning \"%s\" in pid %lu.\n", + blurb(), command, getpid()); exec_vms_command (command); #endif /* VMS */ @@ -306,7 +351,7 @@ void show_job_list (void) { struct screenhack_job *job; - fprintf(stderr, "%s: job list:\n", progname); + fprintf(stderr, "%s: job list:\n", blurb()); for (job = jobs; job; job = job->next) fprintf (stderr, " %5ld: (%s) %s\n", (long) job->pid, @@ -329,19 +374,32 @@ make_job (pid_t pid, const char *cmd) 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 */ + } + + if (got_eq) /* if the first token was FOO=bar */ + { /* then get the next token instead. */ + got_eq = 0; + out = name; + first = 0; + goto AGAIN; + } + while (isspace(*in)) in++; /* skip whitespace */ - if (*in == ':') /* token was a visual name; skip it. */ + if (first && *in == ':') /* token was a visual name; skip it. */ { - in++; out = name; - while (isspace(*in)) in++; /* skip whitespace */ - while (!isspace(*in)) *out++ = *in++; /* snarf first token */ + first = 0; + goto AGAIN; } *out = 0; @@ -471,7 +529,7 @@ kill_job (saver_info *si, pid_t pid, int signal) { if (p->verbose_p) fprintf (stderr, "%s: no child %ld to signal!\n", - progname, (long) pid); + blurb(), (long) pid); goto DONE; } @@ -487,14 +545,14 @@ kill_job (saver_info *si, pid_t pid, int signal) #ifdef SIGSTOP if (p->verbose_p) - fprintf (stderr, "%s: %s pid %lu.\n", progname, + 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", progname, "killing", + fprintf (stderr, "%s: %s pid %lu.\n", blurb(), "killing", (unsigned long) job->pid); #endif /* !SIGSTOP */ @@ -504,12 +562,12 @@ kill_job (saver_info *si, pid_t pid, int signal) { if (errno == ESRCH) fprintf (stderr, "%s: child process %lu (%s) was already dead.\n", - progname, job->pid, job->name); + blurb(), job->pid, job->name); else { char buf [1024]; sprintf (buf, "%s: couldn't kill child process %lu (%s)", - progname, job->pid, job->name); + blurb(), job->pid, job->name); perror (buf); } } @@ -533,7 +591,7 @@ sigchld_handler (int sig) saver_info *si = global_si_kludge; /* I hate C so much... */ if (si->prefs.debug_p) - fprintf(stderr, "%s: got SIGCHLD%s\n", progname, + fprintf(stderr, "%s: got SIGCHLD%s\n", blurb(), (block_sigchld_handler ? " (blocked)" : "")); if (block_sigchld_handler < 0) @@ -565,10 +623,10 @@ await_dying_children (saver_info *si) if (si->prefs.debug_p) { if (kid < 0 && errno) - fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", progname, + fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", blurb(), (long) kid, errno); else - fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", progname, + fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", blurb(), (long) kid); } @@ -610,10 +668,10 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) (p->verbose_p || job->status != job_killed))) fprintf (stderr, "%s: child pid %lu (%s) exited abnormally (code %d).\n", - progname, (unsigned long) kid, name, exit_status); + blurb(), (unsigned long) kid, name, exit_status); else if (p->verbose_p) - printf ("%s: child pid %lu (%s) exited normally.\n", - progname, (unsigned long) kid, name); + fprintf (stderr, "%s: child pid %lu (%s) exited normally.\n", + blurb(), (unsigned long) kid, name); if (job) job->status = job_dead; @@ -625,7 +683,7 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) job->status != job_killed || WTERMSIG (wait_status) != SIGTERM) fprintf (stderr, "%s: child pid %lu (%s) terminated with %s.\n", - progname, (unsigned long) kid, name, + blurb(), (unsigned long) kid, name, signal_name (WTERMSIG(wait_status))); if (job) @@ -635,7 +693,7 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) { if (p->verbose_p) fprintf (stderr, "%s: child pid %lu (%s) stopped with %s.\n", - progname, (unsigned long) kid, name, + blurb(), (unsigned long) kid, name, signal_name (WSTOPSIG (wait_status))); if (job) @@ -644,7 +702,7 @@ describe_dead_child (saver_info *si, pid_t kid, int wait_status) else { fprintf (stderr, "%s: child pid %lu (%s) died in a mysterious way!", - progname, (unsigned long) kid, name); + blurb(), (unsigned long) kid, name); if (job) job->status = job_dead; } @@ -684,7 +742,7 @@ init_sigchld (void) if (sigaction(SIGCHLD, &action, &old) < 0) { char buf [255]; - sprintf (buf, "%s: couldn't catch SIGCHLD", progname); + sprintf (buf, "%s: couldn't catch SIGCHLD", blurb()); perror (buf); } sigchld_initialized_p = True; @@ -695,7 +753,7 @@ init_sigchld (void) if (((long) signal (SIGCHLD, sigchld_handler)) == -1L) { char buf [255]; - sprintf (buf, "%s: couldn't catch SIGCHLD", progname); + sprintf (buf, "%s: couldn't catch SIGCHLD", blurb()); perror (buf); } # endif /* !HAVE_SIGACTION */ @@ -707,35 +765,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"), - progname, (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; } @@ -749,96 +797,101 @@ 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; + 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 || + !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", - progname); - 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; - - /* If there's a visual description on the front of the command, nuke it. + /* Turn off "next" and "prev" modes now, but "demo" mode is only + turned off by explicit action. */ - { - 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; - } - } + if (si->selection_mode < 0) + si->selection_mode = 0; switch ((int) (forked = fork ())) { case -1: - sprintf (buf, "%s: couldn't fork", progname); + sprintf (buf, "%s: couldn't fork", blurb()); perror (buf); restore_real_vroot (si); - saver_exit (si, 1); + saver_exit (si, 1, 0); case 0: close (ConnectionNumber (si->dpy)); /* close display fd */ nice_subproc (p->nice_inferior); /* change process priority */ - hack_environment (ssi); /* set $DISPLAY */ - exec_screenhack (si, hack); /* this does not return */ + hack_subproc_environment (ssi); /* set $DISPLAY */ + exec_screenhack (si, hack->command); /* this does not return */ abort(); break; default: ssi->pid = forked; - (void) make_job (forked, hack); + (void) make_job (forked, hack->command); break; } } @@ -848,12 +901,21 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p) void spawn_screenhack (saver_info *si, Bool first_time_p) { - int i; - for (i = 0; i < si->nscreens; i++) + if (monitor_powered_on_p (si)) { - saver_screen_info *ssi = &si->screens[i]; - spawn_screenhack_1 (ssi, first_time_p); + 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: server reports that monitor has powered down; " + "not launching a new hack.\n", blurb()); + + store_saver_status (si); /* store current hack numbers */ } @@ -921,54 +983,35 @@ 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", progname); - 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 -demo switch; save_argv() left room for this. */ - saved_argv [i] = "-demo"; - saved_argv [i+1] = 0; - restart_process (si); /* shouldn't return */ - saved_argv [i] = 0; - XBell(si->dpy, 0); -} - -static void -hack_environment (saver_screen_info *ssi) +hack_subproc_environment (saver_screen_info *ssi) { /* Store $DISPLAY into the environment, so that the $DISPLAY variable that the spawned processes inherit is correct. First, it must be on the same @@ -988,7 +1031,6 @@ hack_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); @@ -1010,129 +1052,49 @@ hack_environment (saver_screen_info *ssi) } -/* Change the uid/gid of the screensaver process, so that it is safe for it - to run setuid root (which it needs to do on some systems to read the - encrypted passwords from the passwd file.) - - hack_uid() is run before opening the X connection, so that XAuth works. - hack_uid_warn() is called after the connection is opened and the command - line arguments are parsed, so that the messages from hack_uid() get - printed after we know whether we're in `verbose' mode. - */ - -#ifndef NO_SETUID +/* Restarting the xscreensaver process from scratch. */ -static int hack_uid_errno; -static char hack_uid_buf [255], *hack_uid_error; +static char **saved_argv; void -hack_uid (saver_info *si) +save_argv (int argc, char **argv) { - - /* If we've been run as setuid or setgid to someone else (most likely root) - turn off the extra permissions so that random user-specified programs - don't get special privileges. (On some systems it might be necessary - to install this as setuid root in order to read the passwd file to - implement lock-mode...) - */ - setgid (getgid ()); - setuid (getuid ()); - - hack_uid_errno = 0; - hack_uid_error = 0; - - /* If we're being run as root (as from xdm) then switch the user id - to something safe. */ - if (getuid () == 0) + saved_argv = (char **) calloc (argc+2, sizeof (char *)); + saved_argv [argc] = 0; + while (argc--) { - struct passwd *p; - /* Locking can't work when running as root, because we have no way of - knowing what the user id of the logged in user is (so we don't know - whose password to prompt for.) - */ - si->locking_disabled_p = True; - si->nolock_reason = "running as root"; - p = getpwnam ("nobody"); - if (! p) p = getpwnam ("noaccess"); - if (! p) p = getpwnam ("daemon"); - if (! p) p = getpwnam ("bin"); - if (! p) p = getpwnam ("sys"); - if (! p) - { - hack_uid_error = "couldn't find safe uid; running as root."; - hack_uid_errno = -1; - } - else - { - struct group *g = getgrgid (p->pw_gid); - hack_uid_error = hack_uid_buf; - sprintf (hack_uid_error, "changing uid/gid to %s/%s (%ld/%ld).", - p->pw_name, (g ? g->gr_name : "???"), - (long) p->pw_uid, (long) p->pw_gid); - - /* Change the gid to be a safe one. If we can't do that, then - print a warning. We change the gid before the uid so that we - change the gid while still root. */ - if (setgid (p->pw_gid) != 0) - { - hack_uid_errno = errno; - sprintf (hack_uid_error, "couldn't set gid to %s (%ld)", - (g ? g->gr_name : "???"), (long) p->pw_gid); - } - - /* Now change the uid to be a safe one. */ - if (setuid (p->pw_uid) != 0) - { - hack_uid_errno = errno; - sprintf (hack_uid_error, "couldn't set uid to %s (%ld)", - p->pw_name, (long) p->pw_uid); - } - } + int i = strlen (argv [argc]) + 1; + saved_argv [argc] = (char *) malloc (i); + memcpy (saved_argv [argc], argv [argc], i); } -# ifndef NO_LOCKING - else /* disable locking if already being run as "someone else" */ - { - struct passwd *p = getpwuid (getuid ()); - if (!p || - !strcmp (p->pw_name, "root") || - !strcmp (p->pw_name, "nobody") || - !strcmp (p->pw_name, "noaccess") || - !strcmp (p->pw_name, "daemon") || - !strcmp (p->pw_name, "bin") || - !strcmp (p->pw_name, "sys")) - { - si->locking_disabled_p = True; - si->nolock_reason = hack_uid_buf; - sprintf (si->nolock_reason, "running as %s", p->pw_name); - } - } -# endif /* !NO_LOCKING */ } + +/* Re-execs the process with the arguments in saved_argv. + Does not return unless there was an error. + */ void -hack_uid_warn (saver_info *si) +restart_process (saver_info *si) { - saver_preferences *p = &si->prefs; - - if (! hack_uid_error) - ; - else if (hack_uid_errno == 0) + if (si->prefs.verbose_p) { - if (p->verbose_p) - printf ("%s: %s\n", progname, hack_uid_error); + 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"); } - else - { - char buf [255]; - sprintf (buf, "%s: %s", progname, hack_uid_error); - if (hack_uid_errno == -1) - fprintf (stderr, "%s\n", buf); - else - { - errno = hack_uid_errno; - perror (buf); - } - } -} + describe_uids (si, real_stderr); + fprintf (real_stderr, "\n"); -#endif /* !NO_SETUID */ + 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); +}