X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fsubprocs.c;h=4126960b0bc177a0c8a48a349c6c499e569de782;hb=df053bcb240bd8d82e3bebf48a9766a8728bca4b;hp=50dd82b8a521459493a18f7506347a8be6aa9927;hpb=f3e0240915ed9f9b3a61781f5c7002d587563fe0;p=xscreensaver diff --git a/driver/subprocs.c b/driver/subprocs.c index 50dd82b8..4126960b 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,5 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991, 1992, 1993, 1995, 1997 + * xscreensaver, Copyright (c) 1991, 1992, 1993, 1995, 1997, 1998 * Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its @@ -301,8 +301,8 @@ struct screenhack_job { static struct screenhack_job *jobs = 0; -#ifdef DEBUG -static void +/* for debugging -- nothing calls this, but it's useful to invoke from gdb. */ +void show_job_list (void) { struct screenhack_job *job; @@ -317,7 +317,6 @@ show_job_list (void) job->name); fprintf (stderr, "\n"); } -#endif static void clean_job_list (void); @@ -418,9 +417,38 @@ static void describe_dead_child (saver_info *, pid_t, int wait_status); #endif -/* Semaphore to temporarily turn the SIGCHLD handler into a no-op. */ +/* Semaphore to temporarily turn the SIGCHLD handler into a no-op. + Don't alter this directly -- use block_sigchld() / unblock_sigchld(). + */ static int block_sigchld_handler = 0; + +static void +block_sigchld (void) +{ +#ifdef HAVE_SIGACTION + sigset_t child_set; + sigemptyset (&child_set); + sigaddset (&child_set, SIGCHLD); + sigprocmask (SIG_BLOCK, &child_set, 0); +#endif /* HAVE_SIGACTION */ + + block_sigchld_handler++; +} + +static void +unblock_sigchld (void) +{ +#ifdef HAVE_SIGACTION + sigset_t child_set; + sigemptyset(&child_set); + sigaddset(&child_set, SIGCHLD); + sigprocmask(SIG_UNBLOCK, &child_set, 0); +#endif /* HAVE_SIGACTION */ + + block_sigchld_handler--; +} + static int kill_job (saver_info *si, pid_t pid, int signal) { @@ -434,7 +462,7 @@ kill_job (saver_info *si, pid_t pid, int signal) /* This function should not be called from the signal handler. */ abort(); - block_sigchld_handler++; /* we control the horizontal... */ + block_sigchld(); /* we control the horizontal... */ job = find_job (pid); if (!job || @@ -489,7 +517,7 @@ kill_job (saver_info *si, pid_t pid, int signal) await_dying_children (si); DONE: - block_sigchld_handler--; + unblock_sigchld(); if (block_sigchld_handler < 0) abort(); @@ -504,24 +532,22 @@ sigchld_handler (int sig) { saver_info *si = global_si_kludge; /* I hate C so much... */ -#ifdef DEBUG if (si->prefs.debug_p) fprintf(stderr, "%s: got SIGCHLD%s\n", progname, (block_sigchld_handler ? " (blocked)" : "")); -#endif if (block_sigchld_handler < 0) abort(); else if (block_sigchld_handler == 0) { - block_sigchld_handler++; + block_sigchld(); await_dying_children (si); - block_sigchld_handler--; + unblock_sigchld(); } init_sigchld(); } -#endif +#endif /* SIGCHLD */ #ifndef VMS @@ -535,14 +561,16 @@ await_dying_children (saver_info *si) errno = 0; kid = waitpid (-1, &wait_status, WNOHANG|WUNTRACED); -#ifdef DEBUG + if (si->prefs.debug_p) - if (kid < 0 && errno) - fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", progname, - (long) kid, errno); - else - fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", progname, (long) kid); -#endif + { + if (kid < 0 && errno) + fprintf (stderr, "%s: waitpid(-1) ==> %ld (%d)\n", progname, + (long) kid, errno); + else + fprintf (stderr, "%s: waitpid(-1) ==> %ld\n", progname, + (long) kid); + } /* 0 means no more children to reap. -1 means error -- except "interrupted system call" isn't a "real" @@ -641,13 +669,37 @@ void init_sigchld (void) { #ifdef SIGCHLD + +# ifdef HAVE_SIGACTION /* Thanks to Tom Kelly */ + + static Bool sigchld_initialized_p = 0; + if (!sigchld_initialized_p) + { + struct sigaction action, old; + + action.sa_handler = sigchld_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + + if (sigaction(SIGCHLD, &action, &old) < 0) + { + char buf [255]; + sprintf (buf, "%s: couldn't catch SIGCHLD", progname); + perror (buf); + } + sigchld_initialized_p = True; + } + +# else /* !HAVE_SIGACTION */ + if (((long) signal (SIGCHLD, sigchld_handler)) == -1L) { char buf [255]; sprintf (buf, "%s: couldn't catch SIGCHLD", progname); perror (buf); } -#endif +# endif /* !HAVE_SIGACTION */ +#endif /* SIGCHLD */ } @@ -841,7 +893,7 @@ emergency_kill_subproc (saver_info *si) int i; #ifdef SIGCHLD signal (SIGCHLD, SIG_IGN); -#endif +#endif /* SIGCHLD */ for (i = 0; i < si->nscreens; i++) { @@ -1001,6 +1053,7 @@ hack_uid (saver_info *si) 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"); @@ -1036,13 +1089,14 @@ hack_uid (saver_info *si) } } } -#ifndef NO_LOCKING +# 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")) @@ -1052,7 +1106,7 @@ hack_uid (saver_info *si) sprintf (si->nolock_reason, "running as %s", p->pw_name); } } -#endif /* NO_LOCKING */ +# endif /* !NO_LOCKING */ } void