=================================================================== RCS file: /cvs/mandoc/main.c,v retrieving revision 1.258 retrieving revision 1.264 diff -u -p -r1.258 -r1.264 --- mandoc/main.c 2015/11/14 23:57:47 1.258 +++ mandoc/main.c 2016/04/13 12:26:25 1.264 @@ -1,7 +1,7 @@ -/* $Id: main.c,v 1.258 2015/11/14 23:57:47 schwarze Exp $ */ +/* $Id: main.c,v 1.264 2016/04/13 12:26:25 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze + * Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze * Copyright (c) 2010 Joerg Sonnenberger * * Permission to use, copy, modify, and distribute this software for any @@ -123,18 +123,17 @@ main(int argc, char *argv[]) unsigned char *uc; struct manpage *res, *resp; char *conf_file, *defpaths; - size_t isec, i, sz; + const char *sec; + size_t i, sz; int prio, best_prio; - char sec; - enum mandoclevel rctmp; enum outmode outmode; int fd; int show_usage; int options; int use_pager; - int status; + int status, signum; int c; - pid_t pager_pid; + pid_t pager_pid, tc_pgid, man_pgid, pid; #if HAVE_PROGNAME progname = getprogname(); @@ -299,8 +298,9 @@ main(int argc, char *argv[]) use_pager = 0; #if HAVE_PLEDGE - if (!use_pager && pledge("stdio rpath flock", NULL) == -1) - err((int)MANDOCLEVEL_SYSERR, "pledge"); + if (!use_pager) + if (pledge("stdio rpath flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); #endif /* Parse arguments. */ @@ -389,7 +389,7 @@ main(int argc, char *argv[]) if (outmode == OUTMODE_ONE) { argc = 1; - best_prio = 10; + best_prio = 20; } else if (outmode == OUTMODE_ALL) argc = (int)sz; @@ -405,11 +405,13 @@ main(int argc, char *argv[]) res[i].output); else if (outmode == OUTMODE_ONE) { /* Search for the best section. */ - isec = strcspn(res[i].file, "123456789"); - sec = res[i].file[isec]; - if ('\0' == sec) + sec = res[i].file; + sec += strcspn(sec, "123456789"); + if (sec[0] == '\0') continue; - prio = sec_prios[sec - '1']; + prio = sec_prios[sec[0] - '1']; + if (sec[1] != '/') + prio += 10; if (prio >= best_prio) continue; best_prio = prio; @@ -430,9 +432,13 @@ 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"); + if (use_pager) { + if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); + } else { + if (pledge("stdio rpath", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); + } #endif if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths)) @@ -454,11 +460,7 @@ main(int argc, char *argv[]) } while (argc > 0) { - rctmp = mparse_open(curp.mp, &fd, - resp != NULL ? resp->file : *argv); - if (rc < rctmp) - rc = rctmp; - + fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv); if (fd != -1) { if (use_pager) { tag_files = tag_init(); @@ -477,7 +479,8 @@ main(int argc, char *argv[]) if (argc > 1 && curp.outtype <= OUTT_UTF8) ascii_sepline(curp.outdata); - } + } else if (rc < MANDOCLEVEL_ERROR) + rc = MANDOCLEVEL_ERROR; if (MANDOCLEVEL_OK != rc && curp.wstop) break; @@ -530,11 +533,43 @@ out: if (tag_files != NULL) { fclose(stdout); tag_write(); - pager_pid = spawn_pager(tag_files); + man_pgid = getpgid(0); + tag_files->tcpgid = man_pgid == getpid() ? + getpgid(getppid()) : man_pgid; + pager_pid = 0; + signum = SIGSTOP; for (;;) { - if (waitpid(pager_pid, &status, WUNTRACED) == -1) { - if (errno == EINTR) - continue; + + /* Stop here until moved to the foreground. */ + + tc_pgid = tcgetpgrp(STDIN_FILENO); + if (tc_pgid != man_pgid) { + if (tc_pgid == pager_pid) { + (void)tcsetpgrp(STDIN_FILENO, + man_pgid); + if (signum == SIGTTIN) + continue; + } else + tag_files->tcpgid = tc_pgid; + kill(0, signum); + continue; + } + + /* Once in the foreground, activate the pager. */ + + if (pager_pid) { + (void)tcsetpgrp(STDIN_FILENO, pager_pid); + kill(pager_pid, SIGCONT); + } else + pager_pid = spawn_pager(tag_files); + + /* Wait for the pager to stop or exit. */ + + while ((pid = waitpid(pager_pid, &status, + WUNTRACED)) == -1 && errno == EINTR) + continue; + + if (pid == -1) { warn("wait"); rc = MANDOCLEVEL_SYSERR; break; @@ -542,16 +577,7 @@ out: 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); + signum = WSTOPSIG(status); } tag_unlink(); } @@ -657,7 +683,7 @@ fs_search(const struct mansearch *cfg, const struct ma int argc, char **argv, struct manpage **res, size_t *ressz) { const char *const sections[] = - {"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"}; + {"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"}; const size_t nsec = sizeof(sections)/sizeof(sections[0]); size_t ipath, isec, lastsz; @@ -696,9 +722,11 @@ parse(struct curparse *curp, int fd, const char *file) /* Begin by parsing the file itself. */ assert(file); - assert(fd >= -1); + assert(fd >= 0); rctmp = mparse_readfd(curp->mp, fd, file); + if (fd != STDIN_FILENO) + close(fd); if (rc < rctmp) rc = rctmp; @@ -1046,12 +1074,12 @@ spawn_pager(struct tag_files *tag_files) break; default: (void)setpgid(pager_pid, 0); - if (tcsetpgrp(STDIN_FILENO, pager_pid) == -1) - err((int)MANDOCLEVEL_SYSERR, "tcsetpgrp"); + (void)tcsetpgrp(STDIN_FILENO, pager_pid); #if HAVE_PLEDGE if (pledge("stdio rpath tmppath tty proc", NULL) == -1) err((int)MANDOCLEVEL_SYSERR, "pledge"); #endif + tag_files->pager_pid = pager_pid; return pager_pid; }