summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/mandoc/main.c38
-rw-r--r--usr.bin/mandoc/mandoc.h14
-rw-r--r--usr.bin/mandoc/mandocdb.c66
-rw-r--r--usr.bin/mandoc/msec.c4
-rw-r--r--usr.bin/mandoc/read.c100
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)