source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Add *.gz support to apropos(1) -a, man(1), and even mandoc(1).
@ 2014-09-03 23:21 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2014-09-03 23:21 UTC (permalink / raw)
  To: source

Log Message:
-----------
Add *.gz support to apropos(1) -a, man(1), and even mandoc(1).
Implemented by moving the zip code from makewhatis(8) to the parser lib.

Modified Files:
--------------
    mdocml:
        main.c
        mandoc.3
        mandoc.h
        mandocdb.c
        read.c

Revision Data
-------------
Index: mandoc.3
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.3,v
retrieving revision 1.25
retrieving revision 1.26
diff -Lmandoc.3 -Lmandoc.3 -u -p -r1.25 -r1.26
--- mandoc.3
+++ mandoc.3
@@ -31,11 +31,13 @@
 .Nm mparse_free ,
 .Nm mparse_getkeep ,
 .Nm mparse_keep ,
+.Nm mparse_open ,
 .Nm mparse_readfd ,
 .Nm mparse_reset ,
 .Nm mparse_result ,
 .Nm mparse_strerror ,
 .Nm mparse_strlevel
+.Nm mparse_wait ,
 .Nd mandoc macro compiler library
 .Sh LIBRARY
 .Lb libmandoc
@@ -74,6 +76,13 @@
 .Fa "struct mparse *parse"
 .Fc
 .Ft "enum mandoclevel"
+.Fo mparse_open
+.Fa "struct mparse *parse"
+.Fa "int *fd"
+.Fa "const char *fname"
+.Fa "pid_t *child_pid"
+.Fc
+.Ft "enum mandoclevel"
 .Fo mparse_readfd
 .Fa "struct mparse *parse"
 .Fa "int fd"
@@ -98,6 +107,11 @@
 .Fo mparse_strlevel
 .Fa "enum mandoclevel"
 .Fc
+.Ft "enum mandoclevel"
+.Fo mparse_wait
+.Fa "struct mparse *parse"
+.Fa "pid_t child_pid"
+.Fc
 .In sys/types.h
 .In mandoc.h
 .In mdoc.h
@@ -361,6 +375,33 @@ Declared in
 .In mandoc.h ,
 implemented in
 .Pa read.c .
+.It Fn mparse_open
+If the
+.Fa fname
+ends in
+.Pa .gz ,
+open with
+.Xr gunzip 1 ;
+otherwise, with
+.Xr open 2 .
+Return a file descriptor open for reading in
+.Fa fd ,
+or -1 on failure.
+It can be passed to
+.Fn mparse_readfd
+or used directly.
+If applicable, return the
+.Xr gunzip 1
+child process ID in
+.Fa child_pid ,
+or otherwise 0.
+If non-zero, it should be passed to
+.Fn mparse_wait
+after completing the parse sequence.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa read.c .
 .It Fn mparse_readfd
 Parse a file or file descriptor.
 If
@@ -409,6 +450,27 @@ implemented in
 .Pa read.c .
 .It Fn mparse_strlevel
 Return a statically-allocated string representation of a level code.
+Declared in
+.In mandoc.h ,
+implemented in
+.Pa read.c .
+.It Fn mparse_wait
+Bury a
+.Xr gunzip 1
+child process
+.Fa child_pid
+that was spawned with
+.Fn mparse_open .
+To be called after the parse sequence is complete.
+Returns
+.Dv MANDOCLEVEL_OK
+on success and
+.Dv MANDOCLEVEL_SYSERR
+on failure, that is, when
+.Xr wait 2
+fails, or when
+.Xr gunzip 1
+died from a signal or exited with non-zero status.
 Declared in
 .In mandoc.h ,
 implemented in
Index: mandocdb.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandocdb.c,v
retrieving revision 1.161
retrieving revision 1.162
diff -Lmandocdb.c -Lmandocdb.c -u -p -r1.161 -r1.162
--- mandocdb.c
+++ mandocdb.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD$ */
+/*	$Id$ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -17,8 +17,8 @@
  */
 #include "config.h"
 
-#include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/wait.h>
 
 #include <assert.h>
@@ -1076,7 +1076,6 @@ mpages_merge(struct mchars *mc, struct m
 {
 	char			 any[] = "any";
 	struct ohash_info	 str_info;
-	int			 fd[2];
 	struct mpage		*mpage, *mpage_dest;
 	struct mlink		*mlink, *mlink_dest;
 	struct mdoc		*mdoc;
@@ -1084,7 +1083,7 @@ mpages_merge(struct mchars *mc, struct m
 	char			*sodest;
 	char			*cp;
 	pid_t			 child_pid;
-	int			 status;
+	int			 fd;
 	unsigned int		 pslot;
 	enum mandoclevel	 lvl;
 
@@ -1112,38 +1111,11 @@ mpages_merge(struct mchars *mc, struct m
 		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;
 		}
 
 		/*
@@ -1153,7 +1125,7 @@ mpages_merge(struct mchars *mc, struct m
 		 */
 		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);
 		}
@@ -1245,7 +1217,7 @@ mpages_merge(struct mchars *mc, struct m
 		} 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);
 
@@ -1257,21 +1229,10 @@ mpages_merge(struct mchars *mc, struct m
 		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);
@@ -2351,7 +2312,7 @@ prepare_statements:
 	    "PRAGMA synchronous = OFF", NULL, NULL, NULL)) {
 		exitcode = (int)MANDOCLEVEL_SYSERR;
 		say(MANDOC_DB, "PRAGMA synchronous: %s",
-		sqlite3_errmsg(db));
+		    sqlite3_errmsg(db));
 		sqlite3_close(db);
 		return(0);
 	}
Index: mandoc.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.h,v
retrieving revision 1.152
retrieving revision 1.153
diff -Lmandoc.h -Lmandoc.h -u -p -r1.152 -r1.153
--- mandoc.h
+++ mandoc.h
@@ -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 m
 			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 *);
 enum mandoclevel  mparse_readmem(struct mparse *, const void *, size_t,
 			const char *);
@@ -432,6 +441,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
 
Index: read.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/read.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -Lread.c -Lread.c -u -p -r1.81 -r1.82
--- read.c
+++ read.c
@@ -20,9 +20,10 @@
 
 #include <sys/types.h>
 #if HAVE_MMAP
-#include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
 #endif
+#include <sys/wait.h>
 
 #include <assert.h>
 #include <ctype.h>
@@ -213,9 +214,16 @@ static	const char * const	mandocerrs[MAN
 	".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] = {
@@ -774,6 +782,91 @@ mparse_readfd(struct mparse *curp, int f
 		perror(file);
 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 *
Index: main.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/main.c,v
retrieving revision 1.191
retrieving revision 1.192
diff -Lmain.c -Lmain.c -u -p -r1.191 -r1.192
--- main.c
+++ main.c
@@ -87,7 +87,7 @@ static	void		  mmsg(enum mandocerr, enum
 				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));
@@ -114,6 +114,8 @@ main(int argc, char *argv[])
 #endif
 	enum mandoclevel rc;
 	enum outmode	 outmode;
+	pid_t		 child_pid;
+	int		 fd;
 	int		 show_usage;
 	int		 use_pager;
 	int		 options;
@@ -370,16 +372,30 @@ main(int argc, char *argv[])
 	while (argc) {
 #if HAVE_SQLITE3
 		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
 #endif
-			parse(&curp, -1, *argv++, &rc);
+		{
+			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--;
@@ -555,18 +571,11 @@ parse(struct curparse *curp, int fd, con
 }
 
 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)
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-09-03 23:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-03 23:21 mdocml: Add *.gz support to apropos(1) -a, man(1), and even mandoc(1) schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).