summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/main.c b/main.c
index f3c691d1..4ad849de 100644
--- a/main.c
+++ b/main.c
@@ -27,6 +27,7 @@
#if HAVE_ERR
#include <err.h>
#endif
+#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <signal.h>
@@ -131,7 +132,9 @@ main(int argc, char *argv[])
int show_usage;
int options;
int use_pager;
+ int status;
int c;
+ pid_t pager_pid;
#if HAVE_PROGNAME
progname = getprogname();
@@ -152,7 +155,7 @@ main(int argc, char *argv[])
#endif
#if HAVE_PLEDGE
- if (pledge("stdio rpath tmppath proc exec flock", NULL) == -1)
+ if (pledge("stdio rpath tmppath tty proc exec flock", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
@@ -427,7 +430,7 @@ main(int argc, char *argv[])
/* mandoc(1) */
#if HAVE_PLEDGE
- if (pledge(use_pager ? "stdio rpath tmppath proc exec" :
+ if (pledge(use_pager ? "stdio rpath tmppath tty proc exec" :
"stdio rpath", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
@@ -527,7 +530,29 @@ out:
if (tag_files != NULL) {
fclose(stdout);
tag_write();
- waitpid(spawn_pager(tag_files), NULL, 0);
+ pager_pid = spawn_pager(tag_files);
+ for (;;) {
+ if (waitpid(pager_pid, &status, WUNTRACED) == -1) {
+ if (errno == EINTR)
+ continue;
+ warn("wait");
+ rc = MANDOCLEVEL_SYSERR;
+ break;
+ }
+ if (!WIFSTOPPED(status))
+ break;
+
+ (void)tcsetpgrp(STDIN_FILENO, getpgid(0));
+ kill(0, WSTOPSIG(status));
+
+ /*
+ * I'm now stopped.
+ * When getting SIGCONT, continue here:
+ */
+
+ (void)tcsetpgrp(STDIN_FILENO, pager_pid);
+ kill(pager_pid, SIGCONT);
+ }
tag_unlink();
}
@@ -1016,10 +1041,15 @@ spawn_pager(struct tag_files *tag_files)
case -1:
err((int)MANDOCLEVEL_SYSERR, "fork");
case 0:
+ /* Set pgrp in both parent and child to avoid racing exec. */
+ (void)setpgid(0, 0);
break;
default:
+ (void)setpgid(pager_pid, 0);
+ if (tcsetpgrp(STDIN_FILENO, pager_pid) == -1)
+ err((int)MANDOCLEVEL_SYSERR, "tcsetpgrp");
#if HAVE_PLEDGE
- if (pledge("stdio rpath tmppath", NULL) == -1)
+ if (pledge("stdio rpath tmppath tty proc", NULL) == -1)
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
return pager_pid;