From e947f78c166e1e54c705771efb740184a0d2b028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 9 Apr 2003 16:39:47 +0000 Subject: [PATCH] Apply the correct fix for bin/50679: don't mess around with process groups or the tty, just block selected signals in the parent like system(3) does. Many thanks to bde for his assistance in finding the correct solution. PR: bin/50679 --- lib/libutil/pw_util.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c index 5d831e04ae4..053ac56901f 100644 --- a/lib/libutil/pw_util.c +++ b/lib/libutil/pw_util.c @@ -287,54 +287,60 @@ pw_mkdb(const char *user) int pw_edit(int notsetuid) { + struct sigaction sa, sa_int, sa_quit; + sigset_t sigset, oldsigset; struct stat st1, st2; const char *editor; - char *editcmd; int pstat; if ((editor = getenv("EDITOR")) == NULL) editor = _PATH_VI; if (stat(tempname, &st1) == -1) return (-1); + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGINT, &sa, &sa_int); + sigaction(SIGQUIT, &sa, &sa_quit); + sigemptyset(&sigset); + sigaddset(&sigset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sigset, &oldsigset); switch ((editpid = fork())) { case -1: return (-1); case 0: - /* child */ + sigaction(SIGINT, &sa_int, NULL); + sigaction(SIGQUIT, &sa_quit, NULL); + sigprocmask(SIG_SETMASK, &oldsigset, NULL); if (notsetuid) { (void)setgid(getgid()); (void)setuid(getuid()); } - if (asprintf(&editcmd, "exec %s %s", editor, tempname) == NULL) - _exit(EXIT_FAILURE); errno = 0; - execl(_PATH_BSHELL, "sh", "-c", editcmd, NULL); - free(editcmd); + execlp(editor, editor, tempname, NULL); _exit(errno); default: /* parent */ break; } - setpgid(editpid, editpid); - tcsetpgrp(1, editpid); for (;;) { if (waitpid(editpid, &pstat, WUNTRACED) == -1) { unlink(tempname); - return (-1); + break; } else if (WIFSTOPPED(pstat)) { raise(WSTOPSIG(pstat)); - tcsetpgrp(1, getpgid(editpid)); - kill(editpid, SIGCONT); } else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) { editpid = -1; break; } else { unlink(tempname); - *tempname = '\0'; editpid = -1; - return (-1); + break; } } + sigaction(SIGINT, &sa_int, NULL); + sigaction(SIGQUIT, &sa_quit, NULL); + sigprocmask(SIG_SETMASK, &oldsigset, NULL); if (stat(tempname, &st2) == -1) return (-1); return (st1.st_mtime != st2.st_mtime);