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;
int status;
FILE *f;
pid_t orig_pgrp, editor_pgrp = -1;
sigset_t mask, omask;
/* FIXME: the following should have variable sizes */
char filebackup[1024], fileedit[1024];
char *to_rename;
@ -294,6 +296,8 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
editor = DEFAULT_EDITOR;
}
orig_pgrp = tcgetpgrp(STDIN_FILENO);
pid = fork ();
if (-1 == pid) {
vipwexit ("fork", 1, 1);
@ -303,6 +307,14 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
char *buf;
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);
snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
"%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 (;;) {
pid = waitpid (pid, &status, WUNTRACED);
if ((pid != -1) && (WIFSTOPPED (status) != 0)) {
/* 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);
/* 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 {
break;
}
}
if (orig_pgrp != -1)
sigprocmask(SIG_SETMASK, &omask, NULL);
if (-1 == pid) {
vipwexit (editor, 1, 1);
} else if ( WIFEXITED (status)