=================================================================== RCS file: /cvs/mandoc/main.c,v retrieving revision 1.254 retrieving revision 1.258 diff -u -p -r1.254 -r1.258 --- mandoc/main.c 2015/11/06 16:30:33 1.254 +++ mandoc/main.c 2015/11/14 23:57:47 1.258 @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.254 2015/11/06 16:30:33 schwarze Exp $ */ +/* $Id: main.c,v 1.258 2015/11/14 23:57:47 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze @@ -24,7 +24,10 @@ #include #include +#if HAVE_ERR #include +#endif +#include #include #include #include @@ -129,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(); @@ -149,6 +154,11 @@ main(int argc, char *argv[]) return mandocdb(argc, argv); #endif +#if HAVE_PLEDGE + if (pledge("stdio rpath tmppath tty proc exec flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + /* Search options. */ memset(&conf, 0, sizeof(conf)); @@ -288,6 +298,11 @@ main(int argc, char *argv[]) !isatty(STDOUT_FILENO)) use_pager = 0; +#if HAVE_PLEDGE + if (!use_pager && pledge("stdio rpath flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + /* Parse arguments. */ if (argc > 0) { @@ -414,6 +429,12 @@ main(int argc, char *argv[]) /* mandoc(1) */ +#if HAVE_PLEDGE + if (pledge(use_pager ? "stdio rpath tmppath tty proc exec" : + "stdio rpath", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths)) return (int)MANDOCLEVEL_BADARG; @@ -509,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(); } @@ -756,12 +799,12 @@ passthrough(const char *file, int fd, int synopsis_onl FILE *stream; const char *syscall; - char *line; - size_t len, off; - ssize_t nw; + char *line, *cp; + size_t linesz; int print; - fflush(stdout); + line = NULL; + linesz = 0; if ((stream = fdopen(fd, "r")) == NULL) { close(fd); @@ -770,45 +813,41 @@ passthrough(const char *file, int fd, int synopsis_onl } print = 0; - while ((line = fgetln(stream, &len)) != NULL) { + while (getline(&line, &linesz, stream) != -1) { + cp = line; if (synopsis_only) { if (print) { - if ( ! isspace((unsigned char)*line)) + if ( ! isspace((unsigned char)*cp)) goto done; - while (len && - isspace((unsigned char)*line)) { - line++; - len--; - } + while (isspace((unsigned char)*cp)) + cp++; } else { - if ((len == sizeof(synb) && - ! strncmp(line, synb, len - 1)) || - (len == sizeof(synr) && - ! strncmp(line, synr, len - 1))) + if (strcmp(cp, synb) == 0 || + strcmp(cp, synr) == 0) print = 1; continue; } } - for (off = 0; off < len; off += nw) - if ((nw = write(STDOUT_FILENO, line + off, - len - off)) == -1 || nw == 0) { - fclose(stream); - syscall = "write"; - goto fail; - } + if (fputs(cp, stdout)) { + fclose(stream); + syscall = "fputs"; + goto fail; + } } if (ferror(stream)) { fclose(stream); - syscall = "fgetln"; + syscall = "getline"; goto fail; } done: + free(line); fclose(stream); return; fail: + free(line); warn("%s: SYSERR: %s", file, syscall); if (rc < MANDOCLEVEL_SYSERR) rc = MANDOCLEVEL_SYSERR; @@ -1002,8 +1041,17 @@ 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 tty proc", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif return pager_pid; }