]> git.cameronkatri.com Git - pw-darwin.git/commitdiff
Apply the correct fix for bin/50679: don't mess around with process groups
authorDag-Erling Smørgrav <des@FreeBSD.org>
Wed, 9 Apr 2003 16:39:47 +0000 (16:39 +0000)
committerDag-Erling Smørgrav <des@FreeBSD.org>
Wed, 9 Apr 2003 16:39:47 +0000 (16:39 +0000)
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

libutil/pw_util.c

index 5d831e04ae4ebc94bed4317bd6e626d90c720afb..053ac56901f123d18bd10e979105edee15618de4 100644 (file)
@@ -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);