=================================================================== RCS file: /cvs/mandoc/cgi.c,v retrieving revision 1.6 retrieving revision 1.9 diff -u -p -r1.6 -r1.9 --- mandoc/cgi.c 2011/11/23 10:01:04 1.6 +++ mandoc/cgi.c 2011/12/04 22:52:50 1.9 @@ -1,4 +1,4 @@ -/* $Id: cgi.c,v 1.6 2011/11/23 10:01:04 kristaps Exp $ */ +/* $Id: cgi.c,v 1.9 2011/12/04 22:52:50 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -36,6 +36,9 @@ #include "apropos_db.h" #include "mandoc.h" +#include "mdoc.h" +#include "man.h" +#include "main.h" #include "manpath.h" #ifdef __linux__ @@ -63,6 +66,8 @@ struct req { }; static int atou(const char *, unsigned *); +static void catman(const char *); +static void format(const char *); static void html_print(const char *); static int kval_decode(char *); static void kval_parse(struct kval **, size_t *, char *); @@ -73,9 +78,11 @@ static void pg_search(const struct manpaths *, const struct req *, char *); static void pg_show(const struct manpaths *, const struct req *, char *); +static void resp_bad(void); static void resp_baddb(void); static void resp_badexpr(const struct req *); static void resp_badmanual(void); +static void resp_badpage(void); static void resp_begin_html(int, const char *); static void resp_begin_http(int, const char *); static void resp_end_html(void); @@ -84,6 +91,7 @@ static void resp_search(struct res *, size_t, void * static void resp_searchform(const struct req *); static const char *progname; +static const char *cache; static const char *host; static const char * const pages[PAGE__MAX] = { @@ -314,7 +322,7 @@ resp_searchform(const struct req *req) puts(""); printf("
\n"); + printf("/search.html\" METHOD=\"get\">\n"); puts("
" "\n" " "); printf(" Terms: Page not found.

"); + resp_end_html(); +} + +static void resp_badmanual(void) { @@ -361,6 +378,14 @@ resp_badexpr(const struct req *req) } static void +resp_bad(void) +{ + resp_begin_html(500, "Internal Server Error"); + puts("

Generic badness happened.

"); + resp_end_html(); +} + +static void resp_baddb(void) { @@ -421,14 +446,77 @@ pg_index(const struct manpaths *ps, const struct req * } static void +catman(const char *file) +{ + int fd; + char buf[BUFSIZ]; + ssize_t ssz; + + if (-1 == (fd = open(file, O_RDONLY, 0))) { + resp_baddb(); + return; + } + + resp_begin_http(200, NULL); + + while ((ssz = read(fd, buf, BUFSIZ)) > 0) + write(STDOUT_FILENO, buf, (size_t)ssz); + + if (ssz < 0) + perror(file); + + close(fd); +} + +static void +format(const char *file) +{ + struct mparse *mp; + int fd; + struct mdoc *mdoc; + struct man *man; + void *vp; + enum mandoclevel rc; + + 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; + } + + mparse_result(mp, &mdoc, &man); + vp = html_alloc(NULL); + + 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 manpaths *ps, const struct req *req, char *path) { - pid_t pid; char *sub; - char file[MAXPATHLEN], cmd[MAXPATHLEN]; + char file[MAXPATHLEN]; + const char *fn, *cp; int rc; unsigned int vol, rec; - DB *db; + DB *idx; DBT key, val; if (NULL == path) { @@ -453,8 +541,8 @@ pg_show(const struct manpaths *ps, const struct req *r /* Open the index recno(3) database. */ - db = dbopen(file, O_RDONLY, 0, DB_RECNO, NULL); - if (NULL == db) { + idx = dbopen(file, O_RDONLY, 0, DB_RECNO, NULL); + if (NULL == idx) { resp_baddb(); return; } @@ -462,42 +550,30 @@ pg_show(const struct manpaths *ps, const struct req *r key.data = &rec; key.size = 4; - if (0 != (rc = (*db->get)(db, &key, &val, 0))) { + if (0 != (rc = (*idx->get)(idx, &key, &val, 0))) { rc < 0 ? resp_baddb() : resp_badmanual(); - (*db->close)(db); - return; + goto out; } - /* Extra filename: the first nil-terminated entry. */ + cp = (char *)val.data; - strlcpy(file, ps->paths[vol], MAXPATHLEN); - strlcat(file, "/", MAXPATHLEN); - strlcat(file, (char *)val.data, MAXPATHLEN); - - (*db->close)(db); - - strlcpy(cmd, "man=", MAXPATHLEN); - strlcat(cmd, progname, MAXPATHLEN); - strlcat(cmd, "/search?expr=%N&sec=%S", MAXPATHLEN); - - /* Get ready to call the child mandoc(1) process. */ - - if (-1 == (pid = fork())) - exit(EXIT_FAILURE); - - if (pid > 0) { - waitpid(pid, NULL, 0); - return; + if (NULL == (fn = memchr(cp, '\0', val.size))) + resp_baddb(); + else if (++fn - cp >= (int)val.size) + resp_baddb(); + else if (NULL == memchr(fn, '\0', val.size - (fn - cp))) + resp_baddb(); + else { + strlcpy(file, ps->paths[vol], MAXPATHLEN); + strlcat(file, "/", MAXPATHLEN); + strlcat(file, fn, MAXPATHLEN); + if (0 == strcmp(cp, "cat")) + catman(file); + else + format(file); } - - dup2(STDOUT_FILENO, STDERR_FILENO); - - puts("Content-Type: text/html; charset=utf-8\n"); - - fflush(stdout); - - execlp("mandoc", "mandoc", "-T", - "html", "-O", cmd, file, (char *)NULL); +out: + (*idx->close)(idx); } static void @@ -586,6 +662,15 @@ main(void) if (NULL == progname) progname = ""; + cache = getenv("CACHE_DIR"); + if (NULL == cache) + cache = "/cache/man.cgi"; + + if (-1 == chdir(cache)) { + resp_bad(); + return(EXIT_FAILURE); + } + host = getenv("HTTP_HOST"); if (NULL == host) host = "localhost"; @@ -629,7 +714,7 @@ main(void) /* Initialise MANPATH. */ memset(&paths, 0, sizeof(struct manpaths)); - manpath_parse(&paths, NULL, NULL); + manpath_manconf("etc/catman.conf", &paths); /* Route pages. */ @@ -644,6 +729,7 @@ main(void) pg_show(&paths, &req, subpath); break; default: + resp_badpage(); break; }