Index: config-scripts/cups-common.m4 =================================================================== --- config-scripts/cups-common.m4 (revision 9780) +++ config-scripts/cups-common.m4 (working copy) @@ -166,6 +166,9 @@ dnl Check for geteuid function. AC_CHECK_FUNCS(geteuid) +dnl Check for setpgid function. +AC_CHECK_FUNCS(setpgid) + dnl Check for vsyslog function. AC_CHECK_FUNCS(vsyslog) Index: vcnet/config.h =================================================================== --- vcnet/config.h (revision 9780) +++ vcnet/config.h (working copy) @@ -291,6 +291,13 @@ /* + * Do we have the setpgid() function? + */ + +/* #undef HAVE_SETPGID */ + + +/* * Do we have the vsyslog() function? */ Index: config.h.in =================================================================== --- config.h.in (revision 9780) +++ config.h.in (working copy) @@ -232,6 +232,13 @@ /* + * Do we have the setpgid() function? + */ + +#undef HAVE_SETPGID + + +/* * Do we have the vsyslog() function? */ Index: xcode/config.h =================================================================== --- xcode/config.h (revision 9780) +++ xcode/config.h (working copy) @@ -230,6 +230,13 @@ /* + * Do we have the setpgid() function? + */ + +#define HAVE_SETPGID 1 + + +/* * Do we have the vsyslog() function? */ Index: scheduler/process.c =================================================================== --- scheduler/process.c (revision 9780) +++ scheduler/process.c (working copy) @@ -245,7 +245,18 @@ if (!pid) return (0); - else if (force) + + if (!RunUser) + { + /* + * When running as root, cupsd puts child processes in their own process + * group. Using "-pid" sends a signal to all processes in the group. + */ + + pid = -pid; + } + + if (force) return (kill(pid, SIGKILL)); else return (kill(pid, SIGTERM)); @@ -413,11 +424,38 @@ if ((*pid = fork()) == 0) { /* - * Child process goes here... - * - * Update stdin/stdout/stderr as needed... + * Child process goes here; update stderr as needed... */ + if (errfd != 2) + { + if (errfd < 0) + errfd = open("/dev/null", O_WRONLY); + + if (errfd != 2) + { + dup2(errfd, 2); + close(errfd); + } + } + + /* + * Put this process in its own process group so that we can kill any child + * processes it creates. + */ + +#ifdef HAVE_SETPGID + if (!RunUser && setpgid(0, 0)) + exit(errno + 100); +#else + if (!RunUser && setpgrp()) + exit(errno + 100); +#endif /* HAVE_SETPGID */ + + /* + * Update the remaining file descriptors as needed... + */ + if (infd != 0) { if (infd < 0) @@ -442,18 +480,6 @@ } } - if (errfd != 2) - { - if (errfd < 0) - errfd = open("/dev/null", O_WRONLY); - - if (errfd != 2) - { - dup2(errfd, 2); - close(errfd); - } - } - if (backfd != 3 && backfd >= 0) { dup2(backfd, 3); @@ -487,13 +513,13 @@ */ if (setgid(Group)) - exit(errno); + exit(errno + 100); if (setgroups(1, &Group)) - exit(errno); + exit(errno + 100); if (setuid(User)) - exit(errno); + exit(errno + 100); } else { @@ -502,10 +528,10 @@ */ if (setgid(Group) && !RunUser) - exit(errno); + exit(errno + 100); if (setgroups(1, &Group) && !RunUser) - exit(errno); + exit(errno + 100); } /* @@ -549,9 +575,7 @@ else execv(exec_path, argv); - perror(command); - - exit(1); + exit(errno + 100); } else if (*pid < 0) { Index: scheduler/main.c =================================================================== --- scheduler/main.c (revision 9780) +++ scheduler/main.c (working copy) @@ -1727,10 +1727,20 @@ else if (status) { if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_DEBUG, "PID %d (%s) stopped with status %d!", - pid, name, WEXITSTATUS(status)); + { + int code = WEXITSTATUS(status); /* Exit code */ + + if (code > 100) + cupsdLogMessage(CUPSD_LOG_DEBUG, + "PID %d (%s) stopped with status %d (%s)", pid, name, + code, strerror(code - 100)); + else + cupsdLogMessage(CUPSD_LOG_DEBUG, + "PID %d (%s) stopped with status %d.", pid, name, + code); + } else - cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) crashed on signal %d!", + cupsdLogMessage(CUPSD_LOG_ERROR, "PID %d (%s) crashed on signal %d.", pid, name, WTERMSIG(status)); if (LogLevel < CUPSD_LOG_DEBUG)