+ if (NULL == (f = fopen(file, "r"))) {
+ resp_baddb();
+ return;
+ }
+
+ resp_begin_http(200, NULL);
+ printf("<!DOCTYPE HTML PUBLIC "
+ " \"-//W3C//DTD HTML 4.01//EN\""
+ " \"http://www.w3.org/TR/html4/strict.dtd\">\n"
+ "<HTML>\n"
+ "<HEAD>\n"
+ "<META HTTP-EQUIV=\"Content-Type\""
+ " CONTENT=\"text/html; charset=utf-8\">\n"
+ "<LINK REL=\"stylesheet\" HREF=\"%s/catman.css\""
+ " TYPE=\"text/css\" media=\"all\">\n"
+ "<TITLE>System Manpage Reference</TITLE>\n"
+ "</HEAD>\n"
+ "<BODY>\n"
+ "<!-- Begin page content. //-->\n"
+ "<PRE>\n", css);
+
+ 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"
+ "</BODY>\n"
+ "</HTML>");
+
+ fclose(f);
+}
+
+static void
+format(const char *file)
+{
+ struct mparse *mp;
+ int fd;
+ struct mdoc *mdoc;
+ struct man *man;
+ void *vp;
+ enum mandoclevel rc;
+ char opts[MAXPATHLEN + 128];
+
+ if (-1 == (fd = open(file, O_RDONLY, 0))) {
+ resp_baddb();
+ return;
+ }
+
+ mp = mparse_alloc(MPARSE_AUTO, MANDOCLEVEL_FATAL, NULL, NULL);
+ rc = mparse_readfd(mp, fd, file);
+ close(fd);
+
+ if (rc >= MANDOCLEVEL_FATAL) {
+ resp_baddb();
+ return;
+ }
+
+ snprintf(opts, sizeof(opts), "style=%s/man.css,"
+ "man=%s/search.html?sec=%%S&expr=%%N,"
+ /*"includes=/cgi-bin/man.cgi/usr/include/%%I"*/,
+ css, progname);
+
+ mparse_result(mp, &mdoc, &man);
+ vp = html_alloc(opts);
+
+ if (NULL != mdoc) {
+ resp_begin_http(200, NULL);
+ html_mdoc(vp, mdoc);
+ } else if (NULL != man) {
+ resp_begin_http(200, NULL);
+ html_man(vp, man);
+ } else
+ resp_baddb();
+
+ html_free(vp);
+ mparse_free(mp);
+}
+
+static void
+pg_show(const struct req *req, char *path)
+{
+ struct manpaths ps;
+ char *sub;
+ char file[MAXPATHLEN];
+ const char *fn, *cp;
+ int rc;
+ 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();
+ return;
+ }
+
+ memset(&ps, 0, sizeof(struct manpaths));
+ manpath_manconf(&ps, "etc/catman.conf");
+
+ if (vol >= (unsigned int)ps.sz) {
+ resp_error400();
+ goto out;
+ }
+
+ strlcpy(file, ps.paths[vol], MAXPATHLEN);
+ strlcat(file, "/mandoc.index", MAXPATHLEN);
+
+ /* Open the index recno(3) database. */
+
+ idx = dbopen(file, O_RDONLY, 0, DB_RECNO, NULL);
+ if (NULL == idx) {
+ perror(file);
+ resp_baddb();
+ goto out;
+ }