Merge pull request #189 from hallyn/2019-11-11/vpiw
Fix vipw not resuming correctly when suspended
This commit is contained in:
commit
9d935d9be1
47
src/vipw.c
47
src/vipw.c
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user