diff options
-rw-r--r-- | main.c | 54 | ||||
-rw-r--r-- | manconf.h | 8 | ||||
-rw-r--r-- | tag.c | 14 | ||||
-rw-r--r-- | tag.h | 12 | ||||
-rw-r--r-- | term_tag.c | 52 | ||||
-rw-r--r-- | term_tag.h | 5 |
6 files changed, 65 insertions, 80 deletions
@@ -54,6 +54,7 @@ #include "mdoc.h" #include "man.h" #include "mandoc_parse.h" +#include "tag.h" #include "term_tag.h" #include "main.h" #include "manconf.h" @@ -107,8 +108,8 @@ static void parse(struct mparse *, int, const char *, static void passthrough(int, int); static void process_onefile(struct mparse *, struct manpage *, int, struct outstate *, struct manconf *); -static void run_pager(struct tag_files *); -static pid_t spawn_pager(struct tag_files *); +static void run_pager(struct tag_files *, char *); +static pid_t spawn_pager(struct tag_files *, char *); static void usage(enum argmode) __attribute__((__noreturn__)); static int woptions(char *, enum mandoc_os *, int *); @@ -609,7 +610,10 @@ main(int argc, char *argv[]) (void)fchdir(startdir); close(startdir); } - term_tag_finish(); + if (conf.output.tag != NULL && conf.output.tag_found == 0) { + mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", conf.output.tag); + conf.output.tag = NULL; + } if (outst.outdata != NULL) { switch (outst.outtype) { case OUTT_HTML: @@ -638,8 +642,8 @@ out: manconf_free(&conf); if (outst.tag_files != NULL) { - fclose(stdout); - run_pager(outst.tag_files); + if (term_tag_close() != -1) + run_pager(outst.tag_files, conf.output.tag); term_tag_unlink(); } else if (outst.had_output && outst.outtype != OUTT_LINT) mandoc_msg_summary(); @@ -833,7 +837,7 @@ process_onefile(struct mparse *mp, struct manpage *resp, int startdir, if (outst->use_pager) { outst->use_pager = 0; - outst->tag_files = term_tag_init(conf->output.tag); + outst->tag_files = term_tag_init(); } if (outst->had_output && outst->outtype <= OUTT_UTF8) { if (outst->outdata == NULL) @@ -947,6 +951,9 @@ parse(struct mparse *mp, int fd, const char *file, break; } } + if (outconf->tag != NULL && outconf->tag_found == 0 && + tag_exists(outconf->tag)) + outconf->tag_found = 1; if (mandoc_msg_getmin() < MANDOCERR_STYLE) check_xr(); } @@ -1137,7 +1144,7 @@ woptions(char *arg, enum mandoc_os *os_e, int *wstop) * then fork the pager and wait for the user to close it. */ static void -run_pager(struct tag_files *tag_files) +run_pager(struct tag_files *tag_files, char *tag_target) { int signum, status; pid_t man_pgid, tc_pgid; @@ -1152,10 +1159,10 @@ run_pager(struct tag_files *tag_files) for (;;) { /* Stop here until moved to the foreground. */ - tc_pgid = tcgetpgrp(tag_files->ofd); + tc_pgid = tcgetpgrp(STDOUT_FILENO); if (tc_pgid != man_pgid) { if (tc_pgid == pager_pid) { - (void)tcsetpgrp(tag_files->ofd, man_pgid); + (void)tcsetpgrp(STDOUT_FILENO, man_pgid); if (signum == SIGTTIN) continue; } else @@ -1167,10 +1174,10 @@ run_pager(struct tag_files *tag_files) /* Once in the foreground, activate the pager. */ if (pager_pid) { - (void)tcsetpgrp(tag_files->ofd, pager_pid); + (void)tcsetpgrp(STDOUT_FILENO, pager_pid); kill(pager_pid, SIGCONT); } else - pager_pid = spawn_pager(tag_files); + pager_pid = spawn_pager(tag_files, tag_target); /* Wait for the pager to stop or exit. */ @@ -1191,7 +1198,7 @@ run_pager(struct tag_files *tag_files) } static pid_t -spawn_pager(struct tag_files *tag_files) +spawn_pager(struct tag_files *tag_files, char *tag_target) { const struct timespec timeout = { 0, 100000000 }; /* 0.1s */ #define MAX_PAGER_ARGS 16 @@ -1204,6 +1211,9 @@ spawn_pager(struct tag_files *tag_files) int argc, use_ofn; pid_t pager_pid; + assert(tag_files->ofd == -1); + assert(tag_files->tfs == NULL); + pager = getenv("MANPAGER"); if (pager == NULL || *pager == '\0') pager = getenv("PAGER"); @@ -1238,9 +1248,9 @@ spawn_pager(struct tag_files *tag_files) if (strcmp(cp, "less") == 0) { argv[argc++] = mandoc_strdup("-T"); argv[argc++] = tag_files->tfn; - if (tag_files->tagname != NULL) { + if (tag_target != NULL) { argv[argc++] = mandoc_strdup("-t"); - argv[argc++] = tag_files->tagname; + argv[argc++] = tag_target; use_ofn = 0; } } @@ -1258,7 +1268,7 @@ spawn_pager(struct tag_files *tag_files) break; default: (void)setpgid(pager_pid, 0); - (void)tcsetpgrp(tag_files->ofd, pager_pid); + (void)tcsetpgrp(STDOUT_FILENO, pager_pid); #if HAVE_PLEDGE if (pledge("stdio rpath tmppath tty proc", NULL) == -1) { mandoc_msg(MANDOCERR_PLEDGE, 0, 0, @@ -1270,16 +1280,10 @@ spawn_pager(struct tag_files *tag_files) return pager_pid; } - /* The child process becomes the pager. */ - - if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) { - mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno)); - _exit(mandoc_msg_getrc()); - } - close(tag_files->ofd); - assert(tag_files->tfs == NULL); - - /* Do not start the pager before controlling the terminal. */ + /* + * The child process becomes the pager. + * Do not start it before controlling the terminal. + */ while (tcgetpgrp(STDOUT_FILENO) != getpid()) nanosleep(&timeout, NULL); @@ -1,6 +1,6 @@ -/* $Id$ */ +/* $OpenBSD: manconf.h,v 1.7 2018/11/22 11:30:15 schwarze Exp $ */ /* - * Copyright (c) 2011, 2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011,2015,2017,2018,2020 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any @@ -14,6 +14,9 @@ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Public interface to man(1) configuration management. + * For use by the main program and by the formatters. */ /* List of unique, absolute paths to manual trees. */ @@ -37,6 +40,7 @@ struct manoutput { int mdoc; int noval; int synopsisonly; + int tag_found; int toc; }; @@ -176,16 +176,8 @@ tag_put(const char *s, int prio, struct roff_node *n) } } -enum tag_result -tag_check(const char *test_tag) +int +tag_exists(const char *tag) { - unsigned int slot; - - if (ohash_first(&tag_data, &slot) == NULL) - return TAG_EMPTY; - else if (test_tag != NULL && ohash_find(&tag_data, - ohash_qlookup(&tag_data, test_tag)) == NULL) - return TAG_MISS; - else - return TAG_OK; + return ohash_find(&tag_data, ohash_qlookup(&tag_data, tag)) != NULL; } @@ -28,17 +28,7 @@ #define TAG_FALLBACK (INT_MAX - 1) /* Tag only used if unique. */ #define TAG_DELETE (INT_MAX) /* Tag not used at all. */ -/* - * Return values of tag_check(). - */ -enum tag_result { - TAG_OK, /* Argument exists as a tag. */ - TAG_MISS, /* Argument not found. */ - TAG_EMPTY /* No tag exists at all. */ -}; - - void tag_alloc(void); +int tag_exists(const char *); void tag_put(const char *, int, struct roff_node *); -enum tag_result tag_check(const char *); void tag_free(void); @@ -45,7 +45,7 @@ static struct tag_files tag_files; * but for simplicity, create it anyway. */ struct tag_files * -term_tag_init(char *tagname) +term_tag_init(void) { struct sigaction sa; int ofd; /* In /tmp/, dup(2)ed to stdout. */ @@ -54,7 +54,6 @@ term_tag_init(char *tagname) ofd = tfd = -1; tag_files.tfs = NULL; tag_files.tcpgid = -1; - tag_files.tagname = tagname; /* Clean up when dying from a signal. */ @@ -119,7 +118,6 @@ fail: close(tag_files.ofd); tag_files.ofd = -1; } - tag_files.tagname = NULL; return NULL; } @@ -141,27 +139,29 @@ term_tag_write(struct roff_node *n, size_t line) len, cp, tag_files.ofn, line); } -void -term_tag_finish(void) +/* + * Close both output files and restore the original standard output + * to the terminal. In the unlikely case that the latter fails, + * trying to start a pager would be useless, so report the failure + * to the main program. + */ +int +term_tag_close(void) { - if (tag_files.tfs == NULL) - return; - fclose(tag_files.tfs); - tag_files.tfs = NULL; - switch (tag_check(tag_files.tagname)) { - case TAG_EMPTY: - unlink(tag_files.tfn); - *tag_files.tfn = '\0'; - /* FALLTHROUGH */ - case TAG_MISS: - if (tag_files.tagname == NULL) - break; - mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", tag_files.tagname); - tag_files.tagname = NULL; - break; - case TAG_OK: - break; + int irc = 0; + + if (tag_files.tfs != NULL) { + fclose(tag_files.tfs); + tag_files.tfs = NULL; + } + if (tag_files.ofd != -1) { + fflush(stdout); + if ((irc = dup2(tag_files.ofd, STDOUT_FILENO)) == -1) + mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno)); + close(tag_files.ofd); + tag_files.ofd = -1; } + return irc; } void @@ -170,11 +170,11 @@ term_tag_unlink(void) pid_t tc_pgid; if (tag_files.tcpgid != -1) { - tc_pgid = tcgetpgrp(tag_files.ofd); + tc_pgid = tcgetpgrp(STDOUT_FILENO); if (tc_pgid == tag_files.pager_pid || tc_pgid == getpgid(0) || getpgid(tc_pgid) == -1) - (void)tcsetpgrp(tag_files.ofd, tag_files.tcpgid); + (void)tcsetpgrp(STDOUT_FILENO, tag_files.tcpgid); } if (*tag_files.ofn != '\0') { unlink(tag_files.ofn); @@ -184,10 +184,6 @@ term_tag_unlink(void) unlink(tag_files.tfn); *tag_files.tfn = '\0'; } - if (tag_files.tfs != NULL) { - fclose(tag_files.tfs); - tag_files.tfs = NULL; - } } static void @@ -21,7 +21,6 @@ struct tag_files { char ofn[20]; /* Output file name. */ char tfn[20]; /* Tag file name. */ - char *tagname; /* Target specified with -O. */ FILE *tfs; /* Tag file object. */ int ofd; /* Original output file descriptor. */ pid_t tcpgid; /* Process group controlling the terminal. */ @@ -29,7 +28,7 @@ struct tag_files { }; -struct tag_files *term_tag_init(char *); +struct tag_files *term_tag_init(void); void term_tag_write(struct roff_node *, size_t); -void term_tag_finish(void); +int term_tag_close(void); void term_tag_unlink(void); |