+ while (NULL != (p = fgetln(f, &len))) {
+ bold = italic = 0;
+ for (i = 0; i < (int)len - 1; i++) {
+ /*
+ * This means that the catpage is out of state.
+ * Ignore it and keep going (although the
+ * catpage is bogus).
+ */
+
+ if ('\b' == p[i] || '\n' == p[i])
+ continue;
+
+ /*
+ * Print a regular character.
+ * Close out any bold/italic scopes.
+ * If we're in back-space mode, make sure we'll
+ * have something to enter when we backspace.
+ */
+
+ if ('\b' != p[i + 1]) {
+ if (italic)
+ printf("</I>");
+ if (bold)
+ printf("</B>");
+ italic = bold = 0;
+ html_putchar(p[i]);
+ continue;
+ } else if (i + 2 >= (int)len)
+ continue;
+
+ /* Italic mode. */
+
+ if ('_' == p[i]) {
+ if (bold)
+ printf("</B>");
+ if ( ! italic)
+ printf("<I>");
+ bold = 0;
+ italic = 1;
+ i += 2;
+ html_putchar(p[i]);
+ continue;
+ }
+
+ /*
+ * Handle funny behaviour troff-isms.
+ * These grok'd from the original man2html.c.
+ */
+
+ if (('+' == p[i] && 'o' == p[i + 2]) ||
+ ('o' == p[i] && '+' == p[i + 2]) ||
+ ('|' == p[i] && '=' == p[i + 2]) ||
+ ('=' == p[i] && '|' == p[i + 2]) ||
+ ('*' == p[i] && '=' == p[i + 2]) ||
+ ('=' == p[i] && '*' == p[i + 2]) ||
+ ('*' == p[i] && '|' == p[i + 2]) ||
+ ('|' == p[i] && '*' == p[i + 2])) {
+ if (italic)
+ printf("</I>");
+ if (bold)
+ printf("</B>");
+ italic = bold = 0;
+ putchar('*');
+ i += 2;
+ continue;
+ } else if (('|' == p[i] && '-' == p[i + 2]) ||
+ ('-' == p[i] && '|' == p[i + 1]) ||
+ ('+' == p[i] && '-' == p[i + 1]) ||
+ ('-' == p[i] && '+' == p[i + 1]) ||
+ ('+' == p[i] && '|' == p[i + 1]) ||
+ ('|' == p[i] && '+' == p[i + 1])) {
+ if (italic)
+ printf("</I>");
+ if (bold)
+ printf("</B>");
+ italic = bold = 0;
+ putchar('+');
+ i += 2;
+ continue;
+ }
+
+ /* Bold mode. */
+
+ if (italic)
+ printf("</I>");
+ if ( ! bold)
+ printf("<B>");
+ bold = 1;
+ italic = 0;
+ i += 2;
+ html_putchar(p[i]);
+ }
+
+ /*
+ * Clean up the last character.
+ * We can get to a newline; don't print that.
+ */
+
+ if (italic)
+ printf("</I>");
+ if (bold)
+ printf("</B>");
+
+ if (i == (int)len - 1 && '\n' != p[i])
+ html_putchar(p[i]);
+
+ putchar('\n');
+ }
+
+ puts("</PRE>\n"
+ "</DIV>\n"
+ "</BODY>\n"
+ "</HTML>");
+
+ fclose(f);
+}
+
+static void
+format(const struct req *req, const char *file)
+{
+ struct mparse *mp;
+ int fd;
+ struct mdoc *mdoc;
+ struct man *man;
+ void *vp;
+ enum mandoclevel rc;
+ char opts[PATH_MAX + 128];
+
+ if (-1 == (fd = open(file, O_RDONLY, 0))) {
+ resp_baddb();
+ return;
+ }
+
+ mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL, NULL);
+ rc = mparse_readfd(mp, fd, file);
+ close(fd);
+
+ if (rc >= MANDOCLEVEL_FATAL) {
+ resp_baddb();
+ return;
+ }
+
+ snprintf(opts, sizeof(opts), "fragment,"
+ "man=%s/search.html?sec=%%S&expr=Nm~^%%N$,"
+ /*"includes=/cgi-bin/man.cgi/usr/include/%%I"*/,
+ progname);
+
+ mparse_result(mp, &mdoc, &man);
+ if (NULL == man && NULL == mdoc) {
+ resp_baddb();
+ mparse_free(mp);
+ return;
+ }
+
+ resp_begin_html(200, NULL);
+ resp_searchform(req);
+
+ vp = html_alloc(opts);
+
+ if (NULL != mdoc)
+ html_mdoc(vp, mdoc);
+ else
+ html_man(vp, man);
+
+ puts("</BODY>\n"
+ "</HTML>");
+
+ html_free(vp);
+ mparse_free(mp);
+}
+
+static void
+pg_show(const struct req *req, char *path)
+{
+ struct manpaths ps;
+ size_t sz;
+ char *sub;
+ char file[PATH_MAX];
+ const char *cp;
+ int rc, catm;
+ unsigned int vol, rec, mr;
+ DB *idx;
+ DBT key, val;
+
+ idx = NULL;
+
+ /* Parse out mroot, volume, and record from the path. */
+
+ if (NULL == path || NULL == (sub = strchr(path, '/'))) {
+ resp_error400();
+ return;
+ }
+ *sub++ = '\0';
+ if ( ! atou(path, &mr)) {
+ resp_error400();
+ return;
+ }
+ path = sub;
+ if (NULL == (sub = strchr(path, '/'))) {
+ resp_error400();
+ return;
+ }
+ *sub++ = '\0';
+ if ( ! atou(path, &vol) || ! atou(sub, &rec)) {
+ resp_error400();
+ return;
+ } else if (mr >= (unsigned int)req->psz) {
+ resp_error400();
+ return;
+ }
+
+ /*
+ * Begin by chdir()ing into the manroot.
+ * This way we can pick up the database files, which are
+ * relative to the manpath root.
+ */
+
+ if (-1 == chdir(req->p[(int)mr].path)) {
+ perror(req->p[(int)mr].path);
+ resp_baddb();