Get rid of grandchild hack, it was causing problems and there is really

no need for it.  This fixes a bug where we spin eating up CPU when the
user runs a long-running process like a shell.
This commit is contained in:
Todd C. Miller
2000-03-13 16:05:05 +00:00
parent 5684831592
commit a6ad7f071c

180
logging.c
View File

@@ -403,103 +403,109 @@ send_mail(line)
{ {
FILE *mail; FILE *mail;
char *p; char *p;
int pfd[2], pid; int pfd[2], pid, status;
#ifdef POSIX_SIGNALS
sigset_t set, oset;
#else
int omask;
#endif /* POSIX_SIGNALS */
/* Just return if mailer is disabled. */ /* Just return if mailer is disabled. */
if (!def_str(I_MAILERPATH) || !def_str(I_MAILTO)) if (!def_str(I_MAILERPATH) || !def_str(I_MAILTO))
return; return;
if ((pid = fork()) > 0) { /* Child. */ #ifdef POSIX_SIGNALS
(void) sigemptyset(&set);
(void) sigaddset(&set, SIGCHLD);
(void) sigprocmask(SIG_BLOCK, &set, &oset);
#else
omask = sigblock(sigmask(SIGCHLD));
#endif /* POSIX_SIGNALS */
/* We do an explicit wait() later on... */ if (pipe(pfd) == -1) {
(void) signal(SIGCHLD, SIG_IGN); (void) fprintf(stderr, "%s: cannot open pipe: %s\n",
Argv[0], strerror(errno));
exit(1);
}
if (pipe(pfd) == -1) { switch (pid = fork()) {
(void) fprintf(stderr, "%s: cannot open pipe: %s\n", case -1:
Argv[0], strerror(errno)); /* Error. */
exit(1);
}
switch (pid = fork()) {
case -1:
/* Error. */
/* XXX - parent will continue, return an exit val to
let parent know and abort? */
(void) fprintf(stderr, "%s: cannot fork: %s\n",
Argv[0], strerror(errno));
exit(1);
break;
case 0:
{
char *argv[MAX_MAILFLAGS + 1];
char *mpath, *mflags;
int i;
/* Grandchild. */
(void) close(pfd[1]);
(void) dup2(pfd[0], STDIN_FILENO);
(void) close(pfd[0]);
/* Build up an argv based the mailer path and flags */
mflags = estrdup(def_str(I_MAILERFLAGS));
mpath = estrdup(def_str(I_MAILERPATH));
if ((argv[0] = strrchr(mpath, ' ')))
argv[0]++;
else
argv[0] = mpath;
i = 1;
if ((p = strtok(mflags, " \t"))) {
do {
argv[i] = p;
} while (++i < MAX_MAILFLAGS && (p = strtok(NULL, " \t")));
}
argv[i] = NULL;
/* Run mailer as root so user cannot kill it. */
set_perms(PERM_ROOT, 0);
execv(mpath, argv);
_exit(127);
}
break;
}
mail = fdopen(pfd[1], "w");
(void) close(pfd[0]);
/* Pipes are all setup, send message via sendmail. */
(void) fprintf(mail, "To: %s\nFrom: %s\nSubject: ",
def_str(I_MAILTO), user_name);
for (p = def_str(I_MAILSUB); *p; p++) {
/* Expand escapes in the subject */
if (*p == '%' && *(p+1) != '%') {
switch (*(++p)) {
case 'h':
(void) fputs(user_host, mail);
break;
case 'u':
(void) fputs(user_name, mail);
break;
default:
p--;
break;
}
} else
(void) fputc(*p, mail);
}
(void) fprintf(mail, "\n\n%s : %s : %s : %s\n\n", user_host,
get_timestr(), user_name, line);
fclose(mail);
reapchild(0);
_exit(0);
} else {
/* Parent, just return unless there is an error. */
if (pid == -1) {
(void) fprintf(stderr, "%s: cannot fork: %s\n", (void) fprintf(stderr, "%s: cannot fork: %s\n",
Argv[0], strerror(errno)); Argv[0], strerror(errno));
exit(1); exit(1);
} break;
case 0:
{
char *argv[MAX_MAILFLAGS + 1];
char *mpath, *mflags;
int i;
/* Child. */
(void) close(pfd[1]);
(void) dup2(pfd[0], STDIN_FILENO);
(void) close(pfd[0]);
/* Build up an argv based the mailer path and flags */
mflags = estrdup(def_str(I_MAILERFLAGS));
mpath = estrdup(def_str(I_MAILERPATH));
if ((argv[0] = strrchr(mpath, ' ')))
argv[0]++;
else
argv[0] = mpath;
i = 1;
if ((p = strtok(mflags, " \t"))) {
do {
argv[i] = p;
} while (++i < MAX_MAILFLAGS && (p = strtok(NULL, " \t")));
}
argv[i] = NULL;
/* Run mailer as root so user cannot kill it. */
set_perms(PERM_ROOT, 0);
execv(mpath, argv);
_exit(127);
}
break;
} }
mail = fdopen(pfd[1], "w");
(void) close(pfd[0]);
/* Pipes are all setup, send message via sendmail. */
(void) fprintf(mail, "To: %s\nFrom: %s\nSubject: ",
def_str(I_MAILTO), user_name);
for (p = def_str(I_MAILSUB); *p; p++) {
/* Expand escapes in the subject */
if (*p == '%' && *(p+1) != '%') {
switch (*(++p)) {
case 'h':
(void) fputs(user_host, mail);
break;
case 'u':
(void) fputs(user_name, mail);
break;
default:
p--;
break;
}
} else
(void) fputc(*p, mail);
}
(void) fprintf(mail, "\n\n%s : %s : %s : %s\n\n", user_host,
get_timestr(), user_name, line);
fclose(mail);
/* If mailer is done, wait for it now. If not reapchild will get it. */
#ifdef sudo_waitpid
(void) sudo_waitpid(pid, &status, WNOHANG);
#endif
#ifdef POSIX_SIGNALS
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
#else
(void) sigsetmask(omask);
#endif /* POSIX_SIGNALS */
} }
/* /*
@@ -540,7 +546,7 @@ reapchild(sig)
int status, serrno = errno; int status, serrno = errno;
#ifdef sudo_waitpid #ifdef sudo_waitpid
while (sudo_waitpid(-1, &status, WNOHANG) != -1) while (sudo_waitpid(-1, &status, WNOHANG) != -1 && errno == EINTR)
; ;
#else #else
(void) wait(&status); (void) wait(&status);