-/* $Id: main.c,v 1.257 2015/11/07 17:58:55 schwarze Exp $ */
+/* $Id: main.c,v 1.258 2015/11/14 23:57:47 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
#if HAVE_ERR
#include <err.h>
#endif
+#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <signal.h>
int show_usage;
int options;
int use_pager;
+ int status;
int c;
+ pid_t pager_pid;
#if HAVE_PROGNAME
progname = getprogname();
#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
/* 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
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();
}
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;