diff options
-rw-r--r-- | usr.bin/mandoc/main.c | 38 | ||||
-rw-r--r-- | usr.bin/mandoc/mandoc.h | 14 | ||||
-rw-r--r-- | usr.bin/mandoc/mandocdb.c | 66 | ||||
-rw-r--r-- | usr.bin/mandoc/msec.c | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/read.c | 100 |
5 files changed, 149 insertions, 73 deletions
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 689a3c24a5f..09af1dbadc6 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.99 2014/09/03 18:08:26 schwarze Exp $ */ +/* $OpenBSD: main.c,v 1.100 2014/09/03 23:20:33 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -81,7 +81,7 @@ static void mmsg(enum mandocerr, enum mandoclevel, const char *, int, int, const char *); static void parse(struct curparse *, int, const char *, enum mandoclevel *); -static enum mandoclevel passthrough(const char *); +static enum mandoclevel passthrough(const char *, int); static void spawn_pager(void); static int toptions(struct curparse *, char *); static void usage(enum argmode) __attribute__((noreturn)); @@ -106,6 +106,8 @@ main(int argc, char *argv[]) char sec; enum mandoclevel rc; enum outmode outmode; + pid_t child_pid; + int fd; int show_usage; int use_pager; int options; @@ -357,15 +359,28 @@ main(int argc, char *argv[]) while (argc) { if (resp != NULL) { - if (resp->form & FORM_SRC) { + rc = mparse_open(curp.mp, &fd, resp->file, + &child_pid); + if (fd == -1) + /* nothing */; + else if (resp->form & FORM_SRC) { /* For .so only; ignore failure. */ chdir(paths.paths[resp->ipath]); - parse(&curp, -1, resp->file, &rc); + parse(&curp, fd, resp->file, &rc); } else - rc = passthrough(resp->file); + rc = passthrough(resp->file, fd); resp++; - } else - parse(&curp, -1, *argv++, &rc); + } else { + rc = mparse_open(curp.mp, &fd, *argv++, + &child_pid); + if (fd != -1) + parse(&curp, fd, argv[-1], &rc); + } + + if (child_pid && + mparse_wait(curp.mp, child_pid) != MANDOCLEVEL_OK) + rc = MANDOCLEVEL_SYSERR; + if (MANDOCLEVEL_OK != rc && curp.wstop) break; argc--; @@ -539,18 +554,11 @@ parse(struct curparse *curp, int fd, const char *file, } static enum mandoclevel -passthrough(const char *file) +passthrough(const char *file, int fd) { char buf[BUFSIZ]; const char *syscall; ssize_t nr, nw, off; - int fd; - - fd = open(file, O_RDONLY); - if (fd == -1) { - syscall = "open"; - goto fail; - } while ((nr = read(fd, buf, BUFSIZ)) != -1 && nr != 0) for (off = 0; off < nr; off += nw) diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h index 662d964cbe8..782be62a1ec 100644 --- a/usr.bin/mandoc/mandoc.h +++ b/usr.bin/mandoc/mandoc.h @@ -1,4 +1,4 @@ -/* $Id: mandoc.h,v 1.96 2014/08/08 16:17:09 schwarze Exp $ */ +/* $OpenBSD: mandoc.h,v 1.97 2014/09/03 23:20:33 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -171,9 +171,16 @@ enum mandocerr { /* ===== system errors ===== */ + MANDOCERR_SYSDUP, /* cannot dup file descriptor */ + MANDOCERR_SYSEXEC, /* cannot exec */ + MANDOCERR_SYSEXIT, /* gunzip failed with code */ + MANDOCERR_SYSFORK, /* cannot fork */ MANDOCERR_SYSOPEN, /* cannot open file */ - MANDOCERR_SYSSTAT, /* cannot stat file */ + MANDOCERR_SYSPIPE, /* cannot open pipe */ MANDOCERR_SYSREAD, /* cannot read file */ + MANDOCERR_SYSSIG, /* gunzip died from signal */ + MANDOCERR_SYSSTAT, /* cannot stat file */ + MANDOCERR_SYSWAIT, /* wait failed */ MANDOCERR_MAX }; @@ -423,6 +430,8 @@ struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg, const char *); void mparse_free(struct mparse *); void mparse_keep(struct mparse *); +enum mandoclevel mparse_open(struct mparse *, int *, const char *, + pid_t *); enum mandoclevel mparse_readfd(struct mparse *, int, const char *); void mparse_reset(struct mparse *); void mparse_result(struct mparse *, @@ -430,6 +439,7 @@ void mparse_result(struct mparse *, const char *mparse_getkeep(const struct mparse *); const char *mparse_strerror(enum mandocerr); const char *mparse_strlevel(enum mandoclevel); +enum mandoclevel mparse_wait(struct mparse *, pid_t); __END_DECLS diff --git a/usr.bin/mandoc/mandocdb.c b/usr.bin/mandoc/mandocdb.c index 6d473fd61bc..31338c8c642 100644 --- a/usr.bin/mandoc/mandocdb.c +++ b/usr.bin/mandoc/mandocdb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mandocdb.c,v 1.116 2014/09/03 18:08:26 schwarze Exp $ */ +/* $OpenBSD: mandocdb.c,v 1.117 2014/09/03 23:20:33 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -15,6 +15,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/types.h> #include <sys/stat.h> #include <sys/wait.h> @@ -1065,7 +1066,6 @@ mpages_merge(struct mchars *mc, struct mparse *mp) { char any[] = "any"; struct ohash_info str_info; - int fd[2]; struct mpage *mpage, *mpage_dest; struct mlink *mlink, *mlink_dest; struct mdoc *mdoc; @@ -1073,7 +1073,7 @@ mpages_merge(struct mchars *mc, struct mparse *mp) char *sodest; char *cp; pid_t child_pid; - int status; + int fd; unsigned int pslot; enum mandoclevel lvl; @@ -1101,38 +1101,11 @@ mpages_merge(struct mchars *mc, struct mparse *mp) man = NULL; sodest = NULL; child_pid = 0; - fd[0] = -1; - fd[1] = -1; - - if (mpage->mlinks->gzip) { - if (-1 == pipe(fd)) { - exitcode = (int)MANDOCLEVEL_SYSERR; - say(mpage->mlinks->file, "&pipe gunzip"); - goto nextpage; - } - switch (child_pid = fork()) { - case -1: - exitcode = (int)MANDOCLEVEL_SYSERR; - say(mpage->mlinks->file, "&fork gunzip"); - child_pid = 0; - close(fd[1]); - close(fd[0]); - goto nextpage; - case 0: - close(fd[0]); - if (-1 == dup2(fd[1], STDOUT_FILENO)) { - say(mpage->mlinks->file, - "&dup gunzip"); - exit(1); - } - execlp("gunzip", "gunzip", "-c", - mpage->mlinks->file, NULL); - say(mpage->mlinks->file, "&exec gunzip"); - exit(1); - default: - close(fd[1]); - break; - } + + mparse_open(mp, &fd, mpage->mlinks->file, &child_pid); + if (fd == -1) { + say(mpage->mlinks->file, "&open"); + goto nextpage; } /* @@ -1142,7 +1115,7 @@ mpages_merge(struct mchars *mc, struct mparse *mp) */ if (FORM_CAT != mpage->mlinks->dform || FORM_CAT != mpage->mlinks->fform) { - lvl = mparse_readfd(mp, fd[0], mpage->mlinks->file); + lvl = mparse_readfd(mp, fd, mpage->mlinks->file); if (lvl < MANDOCLEVEL_FATAL) mparse_result(mp, &mdoc, &man, &sodest); } @@ -1234,7 +1207,7 @@ mpages_merge(struct mchars *mc, struct mparse *mp) } else if (NULL != man) parse_man(mpage, man_node(man)); else - parse_cat(mpage, fd[0]); + parse_cat(mpage, fd); if (NULL == mpage->desc) mpage->desc = mandoc_strdup(mpage->mlinks->name); @@ -1246,21 +1219,10 @@ mpages_merge(struct mchars *mc, struct mparse *mp) dbadd(mpage, mc); nextpage: - if (child_pid) { - if (-1 == waitpid(child_pid, &status, 0)) { - exitcode = (int)MANDOCLEVEL_SYSERR; - say(mpage->mlinks->file, "&wait gunzip"); - } else if (WIFSIGNALED(status)) { - exitcode = (int)MANDOCLEVEL_SYSERR; - say(mpage->mlinks->file, - "gunzip died from signal %d", - WTERMSIG(status)); - } else if (WEXITSTATUS(status)) { - exitcode = (int)MANDOCLEVEL_SYSERR; - say(mpage->mlinks->file, - "gunzip failed with code %d", - WEXITSTATUS(status)); - } + if (child_pid && + mparse_wait(mp, child_pid) != MANDOCLEVEL_OK) { + exitcode = (int)MANDOCLEVEL_SYSERR; + say(mpage->mlinks->file, "&wait gunzip"); } ohash_delete(&strings); ohash_delete(&names); diff --git a/usr.bin/mandoc/msec.c b/usr.bin/mandoc/msec.c index d5b27d27a70..34347f25fef 100644 --- a/usr.bin/mandoc/msec.c +++ b/usr.bin/mandoc/msec.c @@ -1,4 +1,4 @@ -/* $Id: msec.c,v 1.8 2014/03/21 22:17:01 schwarze Exp $ */ +/* $OpenBSD: msec.c,v 1.9 2014/09/03 23:20:33 schwarze Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -14,6 +14,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/types.h> + #include <string.h> #include "mandoc.h" diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c index 1f8d7cca225..59ed70783ea 100644 --- a/usr.bin/mandoc/read.c +++ b/usr.bin/mandoc/read.c @@ -1,4 +1,4 @@ -/* $Id: read.c,v 1.57 2014/08/08 16:17:09 schwarze Exp $ */ +/* $OpenBSD: read.c,v 1.58 2014/09/03 23:20:33 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org> @@ -16,8 +16,10 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <sys/stat.h> +#include <sys/types.h> #include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> #include <assert.h> #include <ctype.h> @@ -206,9 +208,16 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { ".so request failed", /* system errors */ + "cannot dup file descriptor", + "cannot exec", + "gunzip failed with code", + "cannot fork", NULL, - "cannot stat file", + "cannot open pipe", "cannot read file", + "gunzip died from signal", + "cannot stat file", + "wait failed", }; static const char * const mandoclevels[MANDOCLEVEL_MAX] = { @@ -752,6 +761,91 @@ out: return(curp->file_status); } +enum mandoclevel +mparse_open(struct mparse *curp, int *fd, const char *file, + pid_t *child_pid) +{ + int pfd[2]; + char *cp; + enum mandocerr err; + + pfd[1] = -1; + curp->file = file; + if ((cp = strrchr(file, '.')) == NULL || + strcmp(cp + 1, "gz")) { + *child_pid = 0; + if ((*fd = open(file, O_RDONLY)) == -1) { + err = MANDOCERR_SYSOPEN; + goto out; + } + return(MANDOCLEVEL_OK); + } + + if (pipe(pfd) == -1) { + err = MANDOCERR_SYSPIPE; + goto out; + } + + switch (*child_pid = fork()) { + case -1: + err = MANDOCERR_SYSFORK; + close(pfd[0]); + close(pfd[1]); + pfd[1] = -1; + break; + case 0: + close(pfd[0]); + if (dup2(pfd[1], STDOUT_FILENO) == -1) { + err = MANDOCERR_SYSDUP; + break; + } + execlp("gunzip", "gunzip", "-c", file, NULL); + err = MANDOCERR_SYSEXEC; + break; + default: + close(pfd[1]); + *fd = pfd[0]; + return(MANDOCLEVEL_OK); + } + +out: + *fd = -1; + *child_pid = 0; + curp->file_status = MANDOCLEVEL_SYSERR; + if (curp->mmsg) + (*curp->mmsg)(err, curp->file_status, file, + 0, 0, strerror(errno)); + if (pfd[1] != -1) + exit(1); + return(curp->file_status); +} + +enum mandoclevel +mparse_wait(struct mparse *curp, pid_t child_pid) +{ + int status; + + if (waitpid(child_pid, &status, 0) == -1) { + mandoc_msg(MANDOCERR_SYSWAIT, curp, 0, 0, + strerror(errno)); + curp->file_status = MANDOCLEVEL_SYSERR; + return(curp->file_status); + } + if (WIFSIGNALED(status)) { + mandoc_vmsg(MANDOCERR_SYSSIG, curp, 0, 0, + "%d", WTERMSIG(status)); + curp->file_status = MANDOCLEVEL_SYSERR; + return(curp->file_status); + } + if (WEXITSTATUS(status)) { + mandoc_vmsg(MANDOCERR_SYSEXIT, curp, 0, 0, + "%d", WEXITSTATUS(status)); + curp->file_status = MANDOCLEVEL_SYSERR; + return(curp->file_status); + } + return(MANDOCLEVEL_OK); +} + struct mparse * mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg, const char *defos) |