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;
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user