version 1.6, 2011/11/23 10:01:04 |
version 1.9, 2011/12/04 22:52:50 |
|
|
|
|
#include "apropos_db.h" |
#include "apropos_db.h" |
#include "mandoc.h" |
#include "mandoc.h" |
|
#include "mdoc.h" |
|
#include "man.h" |
|
#include "main.h" |
#include "manpath.h" |
#include "manpath.h" |
|
|
#ifdef __linux__ |
#ifdef __linux__ |
|
|
}; |
}; |
|
|
static int atou(const char *, unsigned *); |
static int atou(const char *, unsigned *); |
|
static void catman(const char *); |
|
static void format(const char *); |
static void html_print(const char *); |
static void html_print(const char *); |
static int kval_decode(char *); |
static int kval_decode(char *); |
static void kval_parse(struct kval **, size_t *, char *); |
static void kval_parse(struct kval **, size_t *, char *); |
Line 73 static void pg_search(const struct manpaths *, |
|
Line 78 static void pg_search(const struct manpaths *, |
|
const struct req *, char *); |
const struct req *, char *); |
static void pg_show(const struct manpaths *, |
static void pg_show(const struct manpaths *, |
const struct req *, char *); |
const struct req *, char *); |
|
static void resp_bad(void); |
static void resp_baddb(void); |
static void resp_baddb(void); |
static void resp_badexpr(const struct req *); |
static void resp_badexpr(const struct req *); |
static void resp_badmanual(void); |
static void resp_badmanual(void); |
|
static void resp_badpage(void); |
static void resp_begin_html(int, const char *); |
static void resp_begin_html(int, const char *); |
static void resp_begin_http(int, const char *); |
static void resp_begin_http(int, const char *); |
static void resp_end_html(void); |
static void resp_end_html(void); |
Line 84 static void resp_search(struct res *, size_t, void * |
|
Line 91 static void resp_search(struct res *, size_t, void * |
|
static void resp_searchform(const struct req *); |
static void resp_searchform(const struct req *); |
|
|
static const char *progname; |
static const char *progname; |
|
static const char *cache; |
static const char *host; |
static const char *host; |
|
|
static const char * const pages[PAGE__MAX] = { |
static const char * const pages[PAGE__MAX] = { |
Line 314 resp_searchform(const struct req *req) |
|
Line 322 resp_searchform(const struct req *req) |
|
puts("<!-- Begin search form. //-->"); |
puts("<!-- Begin search form. //-->"); |
printf("<FORM ACTION=\""); |
printf("<FORM ACTION=\""); |
html_print(progname); |
html_print(progname); |
printf("/search\" METHOD=\"get\">\n"); |
printf("/search.html\" METHOD=\"get\">\n"); |
puts(" <FIELDSET>" "\n" |
puts(" <FIELDSET>" "\n" |
" <INPUT TYPE=\"submit\" VALUE=\"Search:\">"); |
" <INPUT TYPE=\"submit\" VALUE=\"Search:\">"); |
printf(" Terms: <INPUT TYPE=\"text\" " |
printf(" Terms: <INPUT TYPE=\"text\" " |
Line 342 resp_index(const struct req *req) |
|
Line 350 resp_index(const struct req *req) |
|
} |
} |
|
|
static void |
static void |
|
resp_badpage(void) |
|
{ |
|
|
|
resp_begin_html(404, "Not Found"); |
|
puts("<P>Page not found.</P>"); |
|
resp_end_html(); |
|
} |
|
|
|
static void |
resp_badmanual(void) |
resp_badmanual(void) |
{ |
{ |
|
|
Line 361 resp_badexpr(const struct req *req) |
|
Line 378 resp_badexpr(const struct req *req) |
|
} |
} |
|
|
static void |
static void |
|
resp_bad(void) |
|
{ |
|
resp_begin_html(500, "Internal Server Error"); |
|
puts("<P>Generic badness happened.</P>"); |
|
resp_end_html(); |
|
} |
|
|
|
static void |
resp_baddb(void) |
resp_baddb(void) |
{ |
{ |
|
|
Line 421 pg_index(const struct manpaths *ps, const struct req * |
|
Line 446 pg_index(const struct manpaths *ps, const struct req * |
|
} |
} |
|
|
static void |
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) |
pg_show(const struct manpaths *ps, const struct req *req, char *path) |
{ |
{ |
pid_t pid; |
|
char *sub; |
char *sub; |
char file[MAXPATHLEN], cmd[MAXPATHLEN]; |
char file[MAXPATHLEN]; |
|
const char *fn, *cp; |
int rc; |
int rc; |
unsigned int vol, rec; |
unsigned int vol, rec; |
DB *db; |
DB *idx; |
DBT key, val; |
DBT key, val; |
|
|
if (NULL == path) { |
if (NULL == path) { |
Line 453 pg_show(const struct manpaths *ps, const struct req *r |
|
Line 541 pg_show(const struct manpaths *ps, const struct req *r |
|
|
|
/* Open the index recno(3) database. */ |
/* Open the index recno(3) database. */ |
|
|
db = dbopen(file, O_RDONLY, 0, DB_RECNO, NULL); |
idx = dbopen(file, O_RDONLY, 0, DB_RECNO, NULL); |
if (NULL == db) { |
if (NULL == idx) { |
resp_baddb(); |
resp_baddb(); |
return; |
return; |
} |
} |
Line 462 pg_show(const struct manpaths *ps, const struct req *r |
|
Line 550 pg_show(const struct manpaths *ps, const struct req *r |
|
key.data = &rec; |
key.data = &rec; |
key.size = 4; |
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(); |
rc < 0 ? resp_baddb() : resp_badmanual(); |
(*db->close)(db); |
goto out; |
return; |
|
} |
} |
|
|
/* Extra filename: the first nil-terminated entry. */ |
cp = (char *)val.data; |
|
|
strlcpy(file, ps->paths[vol], MAXPATHLEN); |
if (NULL == (fn = memchr(cp, '\0', val.size))) |
strlcat(file, "/", MAXPATHLEN); |
resp_baddb(); |
strlcat(file, (char *)val.data, MAXPATHLEN); |
else if (++fn - cp >= (int)val.size) |
|
resp_baddb(); |
(*db->close)(db); |
else if (NULL == memchr(fn, '\0', val.size - (fn - cp))) |
|
resp_baddb(); |
strlcpy(cmd, "man=", MAXPATHLEN); |
else { |
strlcat(cmd, progname, MAXPATHLEN); |
strlcpy(file, ps->paths[vol], MAXPATHLEN); |
strlcat(cmd, "/search?expr=%N&sec=%S", MAXPATHLEN); |
strlcat(file, "/", MAXPATHLEN); |
|
strlcat(file, fn, MAXPATHLEN); |
/* Get ready to call the child mandoc(1) process. */ |
if (0 == strcmp(cp, "cat")) |
|
catman(file); |
if (-1 == (pid = fork())) |
else |
exit(EXIT_FAILURE); |
format(file); |
|
|
if (pid > 0) { |
|
waitpid(pid, NULL, 0); |
|
return; |
|
} |
} |
|
out: |
dup2(STDOUT_FILENO, STDERR_FILENO); |
(*idx->close)(idx); |
|
|
puts("Content-Type: text/html; charset=utf-8\n"); |
|
|
|
fflush(stdout); |
|
|
|
execlp("mandoc", "mandoc", "-T", |
|
"html", "-O", cmd, file, (char *)NULL); |
|
} |
} |
|
|
static void |
static void |
|
|
if (NULL == progname) |
if (NULL == progname) |
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"); |
host = getenv("HTTP_HOST"); |
if (NULL == host) |
if (NULL == host) |
host = "localhost"; |
host = "localhost"; |
|
|
/* Initialise MANPATH. */ |
/* Initialise MANPATH. */ |
|
|
memset(&paths, 0, sizeof(struct manpaths)); |
memset(&paths, 0, sizeof(struct manpaths)); |
manpath_parse(&paths, NULL, NULL); |
manpath_manconf("etc/catman.conf", &paths); |
|
|
/* Route pages. */ |
/* Route pages. */ |
|
|
|
|
pg_show(&paths, &req, subpath); |
pg_show(&paths, &req, subpath); |
break; |
break; |
default: |
default: |
|
resp_badpage(); |
break; |
break; |
} |
} |
|
|