=================================================================== RCS file: /cvs/mandoc/mandocdb.c,v retrieving revision 1.123 retrieving revision 1.129 diff -u -p -r1.123 -r1.129 --- mandoc/mandocdb.c 2014/03/26 20:53:36 1.123 +++ mandoc/mandocdb.c 2014/04/04 15:55:19 1.129 @@ -1,4 +1,4 @@ -/* $Id: mandocdb.c,v 1.123 2014/03/26 20:53:36 schwarze Exp $ */ +/* $Id: mandocdb.c,v 1.129 2014/04/04 15:55:19 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Kristaps Dzonsons * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze @@ -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 *); @@ -178,7 +179,7 @@ static char *progname; static int nodb; /* no database changes */ static int mparse_options; /* abort the parse early */ static int use_all; /* use all found files */ -static int verb; /* print what we're doing */ +static int debug; /* print what we're doing */ static int warnings; /* warn about crap */ static int write_utf8; /* write UTF-8 output; else ASCII */ static int exitcode; /* to be returned by main */ @@ -223,7 +224,7 @@ static const struct mdoc_handler mdocs[MDOC_MAX] = { { NULL, TYPE_In }, /* In */ { NULL, TYPE_Li }, /* Li */ { parse_mdoc_Nd, TYPE_Nd }, /* Nd */ - { parse_mdoc_Nm, TYPE_Nm }, /* Nm */ + { parse_mdoc_Nm, 0 }, /* Nm */ { NULL, 0 }, /* Op */ { NULL, 0 }, /* Ot */ { NULL, TYPE_Pa }, /* Pa */ @@ -356,7 +357,7 @@ main(int argc, char *argv[]) path_arg = NULL; op = OP_DEFAULT; - while (-1 != (ch = getopt(argc, argv, "aC:d:nQT:tu:vW"))) + while (-1 != (ch = getopt(argc, argv, "aC:Dd:npQT:tu:v"))) switch (ch) { case ('a'): use_all = 1; @@ -366,6 +367,9 @@ main(int argc, char *argv[]) path_arg = optarg; op = OP_CONFFILE; break; + case ('D'): + debug++; + break; case ('d'): CHECKOP(op, ch); path_arg = optarg; @@ -374,6 +378,9 @@ main(int argc, char *argv[]) case ('n'): nodb = 1; break; + case ('p'): + warnings = 1; + break; case ('Q'): mparse_options |= MPARSE_QUICK; break; @@ -397,11 +404,8 @@ main(int argc, char *argv[]) op = OP_DELETE; break; case ('v'): - verb++; + /* Compatibility with espie@'s makewhatis. */ break; - case ('W'): - warnings = 1; - break; default: goto usage; } @@ -458,6 +462,11 @@ main(int argc, char *argv[]) } else manpath_parse(&dirs, path_arg, NULL, NULL); + if (0 == dirs.sz) { + exitcode = (int)MANDOCLEVEL_BADARG; + say("", "Empty manpath"); + } + /* * First scan the tree rooted at a base directory, then * build a new database and finally move it into place. @@ -505,10 +514,10 @@ out: ohash_delete(&mlinks); return(exitcode); usage: - fprintf(stderr, "usage: %s [-anQvW] [-C file] [-Tutf8]\n" - " %s [-anQvW] [-Tutf8] dir ...\n" - " %s [-nQvW] [-Tutf8] -d dir [file ...]\n" - " %s [-nvW] -u dir [file ...]\n" + fprintf(stderr, "usage: %s [-aDnpQ] [-C file] [-Tutf8]\n" + " %s [-aDnpQ] [-Tutf8] dir ...\n" + " %s [-DnpQ] [-Tutf8] -d dir [file ...]\n" + " %s [-Dnp] -u dir [file ...]\n" " %s [-Q] -t file ...\n", progname, progname, progname, progname, progname); @@ -536,7 +545,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 +580,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 +602,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 +626,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 +980,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,7 +1012,42 @@ 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) * source code, unless it is already known to be @@ -1002,7 +1055,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 +1095,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 +1155,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 +1185,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; @@ -1325,7 +1397,7 @@ parse_man(struct mpage *mpage, const struct man_node * ('\\' == start[0] && '-' == start[1])) break; - putkey(mpage, start, TYPE_Nm); + putkey(mpage, start, TYPE_NAME | TYPE_Nm); if (' ' == byte) { start += sz + 1; @@ -1339,7 +1411,7 @@ parse_man(struct mpage *mpage, const struct man_node * } if (start == title) { - putkey(mpage, start, TYPE_Nm); + putkey(mpage, start, TYPE_NAME | TYPE_Nm); free(title); return; } @@ -1516,8 +1588,11 @@ static int parse_mdoc_Nm(struct mpage *mpage, const struct mdoc_node *n) { - return(SEC_NAME == n->sec || - (SEC_SYNOPSIS == n->sec && MDOC_HEAD == n->type)); + if (SEC_NAME == n->sec) + putmdockey(mpage, n->child, TYPE_NAME | TYPE_Nm); + else if (SEC_SYNOPSIS == n->sec && MDOC_HEAD == n->type) + putmdockey(mpage, n->child, TYPE_Nm); + return(0); } static int @@ -1559,7 +1634,7 @@ putkeys(const struct mpage *mpage, if (0 == sz) return; - if (verb > 1) { + if (debug > 1) { for (i = 0, mask = 1; i < mansearch_keymax; i++, mask <<= 1) @@ -1786,20 +1861,54 @@ dbadd(struct mpage *mpage, struct mchars *mc) size_t i; unsigned int slot; - if (verb) - say(mpage->mlinks->file, "Adding to database"); + mlink = mpage->mlinks; - if (nodb) + if (nodb) { + while (NULL != mlink) { + fputs(mlink->name, stdout); + if (NULL == mlink->next || + strcmp(mlink->dsec, mlink->next->dsec) || + strcmp(mlink->fsec, mlink->next->fsec) || + strcmp(mlink->arch, mlink->next->arch)) { + putchar('('); + if ('\0' == *mlink->dsec) + fputs(mlink->fsec, stdout); + else + fputs(mlink->dsec, stdout); + if ('\0' != *mlink->arch) + printf("/%s", mlink->arch); + putchar(')'); + } + mlink = mlink->next; + if (NULL != mlink) + fputs(", ", stdout); + } + for (key = ohash_first(&strings, &slot); NULL != key; + key = ohash_next(&strings, &slot)) { + if (TYPE_Nd & key->mask) { + if (NULL == key->rendered) + render_key(mc, key); + printf(" - %s", key->rendered); + break; + } + } + putchar('\n'); return; + } + if (debug) + say(mlink->file, "Adding to database"); + i = 1; SQL_BIND_INT(stmts[STMT_INSERT_PAGE], i, FORM_SRC == mpage->form); SQL_STEP(stmts[STMT_INSERT_PAGE]); mpage->recno = sqlite3_last_insert_rowid(db); sqlite3_reset(stmts[STMT_INSERT_PAGE]); - for (mlink = mpage->mlinks; mlink; mlink = mlink->next) + while (NULL != mlink) { dbadd_mlink(mlink); + mlink = mlink->next; + } for (key = ohash_first(&strings, &slot); NULL != key; key = ohash_next(&strings, &slot)) { @@ -1832,7 +1941,7 @@ dbprune(void) for (mpage = ohash_first(&mpages, &slot); NULL != mpage; mpage = ohash_next(&mpages, &slot)) { mlink = mpage->mlinks; - if (verb) + if (debug) say(mlink->file, "Deleting from database"); if (nodb) continue;