Merge pull request #189 from hallyn/2019-11-11/vpiw

Fix vipw not resuming correctly when suspended
This commit is contained in:
Serge Hallyn 2019-11-11 20:22:49 -06:00 committed by GitHub
commit 9d935d9be1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -207,6 +207,8 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
struct stat st1, st2; struct stat st1, st2;
int status; int status;
FILE *f; FILE *f;
pid_t orig_pgrp, editor_pgrp = -1;
sigset_t mask, omask;
/* FIXME: the following should have variable sizes */ /* FIXME: the following should have variable sizes */
char filebackup[1024], fileedit[1024]; char filebackup[1024], fileedit[1024];
char *to_rename; char *to_rename;
@ -294,6 +296,8 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
editor = DEFAULT_EDITOR; editor = DEFAULT_EDITOR;
} }
orig_pgrp = tcgetpgrp(STDIN_FILENO);
pid = fork (); pid = fork ();
if (-1 == pid) { if (-1 == pid) {
vipwexit ("fork", 1, 1); vipwexit ("fork", 1, 1);
@ -303,6 +307,14 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
char *buf; char *buf;
int status; int status;
/* Wait for parent to make us the foreground pgrp. */
if (orig_pgrp != -1) {
pid = getpid();
setpgid(0, 0);
while (tcgetpgrp(STDIN_FILENO) != pid)
continue;
}
buf = (char *) malloc (strlen (editor) + strlen (fileedit) + 2); buf = (char *) malloc (strlen (editor) + strlen (fileedit) + 2);
snprintf (buf, strlen (editor) + strlen (fileedit) + 2, snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
"%s %s", editor, fileedit); "%s %s", editor, fileedit);
@ -325,19 +337,50 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
} }
} }
/* Run child in a new pgrp and make it the foreground pgrp. */
if (orig_pgrp != -1) {
setpgid(pid, pid);
tcsetpgrp(STDIN_FILENO, pid);
/* Avoid SIGTTOU when changing foreground pgrp below. */
sigemptyset(&mask);
sigaddset(&mask, SIGTTOU);
sigprocmask(SIG_BLOCK, &mask, &omask);
}
for (;;) { for (;;) {
pid = waitpid (pid, &status, WUNTRACED); pid = waitpid (pid, &status, WUNTRACED);
if ((pid != -1) && (WIFSTOPPED (status) != 0)) { if ((pid != -1) && (WIFSTOPPED (status) != 0)) {
/* The child (editor) was suspended. /* The child (editor) was suspended.
* Suspend vipw. */ * Restore terminal pgrp and suspend vipw. */
if (orig_pgrp != -1) {
editor_pgrp = tcgetpgrp(STDIN_FILENO);
if (editor_pgrp == -1) {
fprintf (stderr, "%s: %s: %s", Prog,
"tcgetpgrp", strerror (errno));
}
if (tcsetpgrp(STDIN_FILENO, orig_pgrp) == -1) {
fprintf (stderr, "%s: %s: %s", Prog,
"tcsetpgrp", strerror (errno));
}
}
kill (getpid (), SIGSTOP); kill (getpid (), SIGSTOP);
/* wake child when resumed */ /* wake child when resumed */
kill (pid, SIGCONT); if (editor_pgrp != -1) {
if (tcsetpgrp(STDIN_FILENO, editor_pgrp) == -1) {
fprintf (stderr, "%s: %s: %s", Prog,
"tcsetpgrp", strerror (errno));
}
}
killpg (pid, SIGCONT);
} else { } else {
break; break;
} }
} }
if (orig_pgrp != -1)
sigprocmask(SIG_SETMASK, &omask, NULL);
if (-1 == pid) { if (-1 == pid) {
vipwexit (editor, 1, 1); vipwexit (editor, 1, 1);
} else if ( WIFEXITED (status) } else if ( WIFEXITED (status)