summaryrefslogtreecommitdiffstats
path: root/mandocdb.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2014-03-26 21:39:38 +0000
committerIngo Schwarze <schwarze@openbsd.org>2014-03-26 21:39:38 +0000
commitd82f070a5c49198d0d568df3940dfca1d933926d (patch)
treee0d77ee994e5868fc45152aedaeb3796c4b7361d /mandocdb.c
parent415c36bb5ea37b5fae2c40dd507fd4320f9034bd (diff)
downloadmandoc-d82f070a5c49198d0d568df3940dfca1d933926d.tar.gz
Without bloating mandoc(1) itself, let mandocdb(8) support files
called manN/X.N.gz and catN/X.0.gz, reading them through a pipe(2) from gunzip(1) -c. Asked for by various people in the past.
Diffstat (limited to 'mandocdb.c')
-rw-r--r--mandocdb.c96
1 files changed, 80 insertions, 16 deletions
diff --git a/mandocdb.c b/mandocdb.c
index fb98eb3d..28e19f42 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -119,6 +119,7 @@ struct mlink {
char *fsec; /* section from file name suffix */
struct mlink *next; /* singly linked list */
struct mpage *mpage; /* parent */
+ int gzip; /* filename has a .gz suffix */
};
enum stmt {
@@ -151,7 +152,7 @@ static void mlink_free(struct mlink *);
static void mlinks_undupe(struct mpage *);
static void mpages_free(void);
static void mpages_merge(struct mchars *, struct mparse *);
-static void parse_cat(struct mpage *);
+static void parse_cat(struct mpage *, int);
static void parse_man(struct mpage *, const struct man_node *);
static void parse_mdoc(struct mpage *, const struct mdoc_node *);
static int parse_mdoc_body(struct mpage *, const struct mdoc_node *);
@@ -536,7 +537,7 @@ treescan(void)
FTS *f;
FTSENT *ff;
struct mlink *mlink;
- int dform;
+ int dform, gzip;
char *dsec, *arch, *fsec, *cp;
const char *path;
const char *argv[2];
@@ -571,8 +572,18 @@ treescan(void)
if (warnings)
say(path, "Extraneous file");
continue;
- } else if (NULL == (fsec =
- strrchr(ff->fts_name, '.'))) {
+ }
+ gzip = 0;
+ fsec = NULL;
+ while (NULL == fsec) {
+ fsec = strrchr(ff->fts_name, '.');
+ if (NULL == fsec || strcmp(fsec+1, "gz"))
+ break;
+ gzip = 1;
+ *fsec = '\0';
+ fsec = NULL;
+ }
+ if (NULL == fsec) {
if ( ! use_all) {
if (warnings)
say(path,
@@ -583,10 +594,6 @@ treescan(void)
if (warnings)
say(path, "Skip html");
continue;
- } else if (0 == strcmp(fsec, "gz")) {
- if (warnings)
- say(path, "Skip gz");
- continue;
} else if (0 == strcmp(fsec, "ps")) {
if (warnings)
say(path, "Skip ps");
@@ -611,6 +618,7 @@ treescan(void)
mlink->arch = arch;
mlink->name = ff->fts_name;
mlink->fsec = fsec;
+ mlink->gzip = gzip;
mlink_add(mlink, ff->fts_statp);
continue;
} else if (FTS_D != ff->fts_info &&
@@ -964,13 +972,15 @@ 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;
struct man *man;
char *sodest;
char *cp;
- int match;
+ pid_t child_pid;
+ int match, status;
unsigned int pslot;
enum mandoclevel lvl;
@@ -994,6 +1004,41 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
mparse_reset(mp);
mdoc = NULL;
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;
+ }
+ }
/*
* Try interpreting the file as mdoc(7) or man(7)
@@ -1002,7 +1047,7 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
*/
if (FORM_CAT != mpage->mlinks->dform ||
FORM_CAT != mpage->mlinks->fform) {
- lvl = mparse_readfd(mp, -1, mpage->mlinks->file);
+ lvl = mparse_readfd(mp, fd[0], mpage->mlinks->file);
if (lvl < MANDOCLEVEL_FATAL)
mparse_result(mp, &mdoc, &man, &sodest);
}
@@ -1042,9 +1087,7 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
mlink_dest->next = mpage->mlinks;
mpage->mlinks = NULL;
}
- ohash_delete(&strings);
- mpage = ohash_next(&mpages, &pslot);
- continue;
+ goto nextpage;
} else if (NULL != mdoc) {
mpage->form = FORM_SRC;
mpage->sec =
@@ -1104,9 +1147,27 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
} else if (NULL != man)
parse_man(mpage, man_node(man));
else
- parse_cat(mpage);
+ parse_cat(mpage, fd[0]);
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));
+ }
+ }
ohash_delete(&strings);
mpage = ohash_next(&mpages, &pslot);
}
@@ -1116,13 +1177,16 @@ mpages_merge(struct mchars *mc, struct mparse *mp)
}
static void
-parse_cat(struct mpage *mpage)
+parse_cat(struct mpage *mpage, int fd)
{
FILE *stream;
char *line, *p, *title;
size_t len, plen, titlesz;
- if (NULL == (stream = fopen(mpage->mlinks->file, "r"))) {
+ stream = (-1 == fd) ?
+ fopen(mpage->mlinks->file, "r") :
+ fdopen(fd, "r");
+ if (NULL == stream) {
if (warnings)
say(mpage->mlinks->file, "&fopen");
return;