aboutsummaryrefslogtreecommitdiff
path: root/lib/libutil/pw_util.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2003-04-09 16:39:47 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2003-04-09 16:39:47 +0000
commite947f78c166e1e54c705771efb740184a0d2b028 (patch)
tree2879d81ad1ada7a84110a5239aa7efbfd4fcc3d6 /lib/libutil/pw_util.c
parent7e9b53e39996aab50c1db952d821b0fc17cdcdbf (diff)
downloadsrc-e947f78c166e1e54c705771efb740184a0d2b028.tar.gz
src-e947f78c166e1e54c705771efb740184a0d2b028.zip
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
Notes
Notes: svn path=/head/; revision=113301
Diffstat (limited to 'lib/libutil/pw_util.c')
-rw-r--r--lib/libutil/pw_util.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c
index 5d831e04ae4e..053ac56901f1 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);