version 1.66, 2014/07/12 17:21:45 |
version 1.70, 2014/07/13 12:31:23 |
|
|
#include "main.h" |
#include "main.h" |
#include "manpath.h" |
#include "manpath.h" |
#include "mansearch.h" |
#include "mansearch.h" |
|
#include "cgi.h" |
|
|
/* |
/* |
* A query as passed to the search function. |
* A query as passed to the search function. |
Line 76 static void resp_noresult(const struct req *, |
|
Line 77 static void resp_noresult(const struct req *, |
|
static void resp_search(const struct req *, |
static void resp_search(const struct req *, |
struct manpage *, size_t); |
struct manpage *, size_t); |
static void resp_searchform(const struct req *); |
static void resp_searchform(const struct req *); |
|
static void resp_show(const struct req *, const char *); |
|
|
static const char *scriptname; /* CGI script name */ |
static const char *scriptname; /* CGI script name */ |
static const char *mandir; /* contains all manpath directories */ |
|
static const char *cssdir; /* css directory */ |
|
static const char *httphost; /* hostname used in the URIs */ |
static const char *httphost; /* hostname used in the URIs */ |
|
|
|
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9}; |
|
static const char *const sec_numbers[] = { |
|
"0", "1", "2", "3", "3p", "4", "5", "6", "7", "8", "9" |
|
}; |
|
static const char *const sec_names[] = { |
|
"All Sections", |
|
"1 - General Commands", |
|
"2 - System Calls", |
|
"3 - Subroutines", |
|
"3p - Perl Subroutines", |
|
"4 - Special Files", |
|
"5 - File Formats", |
|
"6 - Games", |
|
"7 - Macros and Conventions", |
|
"8 - Maintenance Commands", |
|
"9 - Kernel Interface" |
|
}; |
|
static const int sec_MAX = sizeof(sec_names) / sizeof(char *); |
|
|
|
static const char *const arch_names[] = { |
|
"amd64", "alpha", "armish", "armv7", |
|
"aviion", "hppa", "hppa64", "i386", |
|
"ia64", "landisk", "loongson", "luna88k", |
|
"macppc", "mips64", "octeon", "sgi", |
|
"socppc", "solbourne", "sparc", "sparc64", |
|
"vax", "zaurus", |
|
"amiga", "arc", "arm32", "atari", |
|
"beagle", "cats", "hp300", "mac68k", |
|
"mvme68k", "mvme88k", "mvmeppc", "palm", |
|
"pc532", "pegasos", "pmax", "powerpc", |
|
"sun3", "wgrisc", "x68k" |
|
}; |
|
static const int arch_MAX = sizeof(arch_names) / sizeof(char *); |
|
|
/* |
/* |
* Print a character, escaping HTML along the way. |
* Print a character, escaping HTML along the way. |
* This will pass non-ASCII straight to output: be warned! |
* This will pass non-ASCII straight to output: be warned! |
Line 314 resp_begin_html(int code, const char *msg) |
|
Line 348 resp_begin_html(int code, const char *msg) |
|
" TYPE=\"text/css\" media=\"all\">\n" |
" TYPE=\"text/css\" media=\"all\">\n" |
"<LINK REL=\"stylesheet\" HREF=\"%s/man.css\"" |
"<LINK REL=\"stylesheet\" HREF=\"%s/man.css\"" |
" TYPE=\"text/css\" media=\"all\">\n" |
" TYPE=\"text/css\" media=\"all\">\n" |
"<TITLE>System Manpage Reference</TITLE>\n" |
"<TITLE>%s</TITLE>\n" |
"</HEAD>\n" |
"</HEAD>\n" |
"<BODY>\n" |
"<BODY>\n" |
"<!-- Begin page content. //-->\n", |
"<!-- Begin page content. //-->\n", |
cssdir, cssdir); |
CSS_DIR, CSS_DIR, CUSTOMIZE_TITLE); |
} |
} |
|
|
static void |
static void |
Line 334 resp_searchform(const struct req *req) |
|
Line 368 resp_searchform(const struct req *req) |
|
{ |
{ |
int i; |
int i; |
|
|
|
puts(CUSTOMIZE_BEGIN); |
puts("<!-- Begin search form. //-->"); |
puts("<!-- Begin search form. //-->"); |
printf("<DIV ID=\"mancgi\">\n" |
printf("<DIV ID=\"mancgi\">\n" |
"<FORM ACTION=\"%s\" METHOD=\"get\">\n" |
"<FORM ACTION=\"%s\" METHOD=\"get\">\n" |
"<FIELDSET>\n" |
"<FIELDSET>\n" |
"<LEGEND>Search Parameters</LEGEND>\n" |
"<LEGEND>Manual Page Search Parameters</LEGEND>\n", |
"<INPUT TYPE=\"submit\" VALUE=\"Search\"> " |
|
"for manuals \n", |
|
scriptname); |
scriptname); |
printf("<SELECT NAME=\"apropos\">\n" |
|
"<OPTION VALUE=\"0\""); |
/* Write query input box. */ |
|
|
|
printf( "<TABLE><TR><TD>\n" |
|
"<INPUT TYPE=\"text\" NAME=\"query\" VALUE=\""); |
|
if (NULL != req->q.expr) |
|
html_print(req->q.expr); |
|
puts("\" SIZE=\"40\">"); |
|
|
|
/* Write submission and reset buttons. */ |
|
|
|
printf( "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n" |
|
"<INPUT TYPE=\"reset\" VALUE=\"Reset\">\n"); |
|
|
|
/* Write show radio button */ |
|
|
|
printf( "</TD><TD>\n" |
|
"<INPUT TYPE=\"radio\" "); |
if (req->q.equal) |
if (req->q.equal) |
printf(" SELECTED=\"selected\""); |
printf("CHECKED "); |
printf(">named</OPTION>\n" |
printf( "NAME=\"apropos\" ID=\"show\" VALUE=\"0\">\n" |
"<OPTION VALUE=\"1\""); |
"<LABEL FOR=\"show\">Show named manual page</LABEL>\n"); |
if (0 == req->q.equal) |
|
printf(" SELECTED=\"selected\""); |
/* Write section selector. */ |
printf(">matching</OPTION>\n" |
|
"</SELECT>\n" |
printf( "</TD></TR><TR><TD>\n" |
"<INPUT TYPE=\"text\" NAME=\"query\" VALUE=\""); |
"<SELECT NAME=\"sec\">"); |
html_print(req->q.expr ? req->q.expr : ""); |
for (i = 0; i < sec_MAX; i++) { |
printf("\">, section " |
printf("<OPTION VALUE=\"%s\"", sec_numbers[i]); |
"<INPUT TYPE=\"text\"" |
if (NULL != req->q.sec && |
" SIZE=\"4\" NAME=\"sec\" VALUE=\""); |
0 == strcmp(sec_numbers[i], req->q.sec)) |
html_print(req->q.sec ? req->q.sec : ""); |
printf(" SELECTED"); |
printf("\">, arch " |
printf(">%s</OPTION>\n", sec_names[i]); |
"<INPUT TYPE=\"text\"" |
} |
" SIZE=\"8\" NAME=\"arch\" VALUE=\""); |
puts("</SELECT>"); |
html_print(req->q.arch ? req->q.arch : ""); |
|
printf("\">"); |
/* Write architecture selector. */ |
|
|
|
puts("<SELECT NAME=\"arch\">"); |
|
for (i = 0; i < arch_MAX; i++) { |
|
printf("<OPTION VALUE=\"%s\"", arch_names[i]); |
|
if (NULL != req->q.arch && |
|
0 == strcmp(arch_names[i], req->q.arch)) |
|
printf(" SELECTED"); |
|
printf(">%s</OPTION>\n", arch_names[i]); |
|
} |
|
puts("</SELECT>"); |
|
|
|
/* Write manpath selector. */ |
|
|
if (req->psz > 1) { |
if (req->psz > 1) { |
puts(", in <SELECT NAME=\"manpath\">"); |
puts("<SELECT NAME=\"manpath\">"); |
for (i = 0; i < (int)req->psz; i++) { |
for (i = 0; i < (int)req->psz; i++) { |
printf("<OPTION "); |
printf("<OPTION "); |
if (NULL == req->q.manpath ? 0 == i : |
if (NULL == req->q.manpath ? 0 == i : |
0 == strcmp(req->q.manpath, req->p[i])) |
0 == strcmp(req->q.manpath, req->p[i])) |
printf("SELECTED=\"selected\" "); |
printf("SELECTED "); |
printf("VALUE=\""); |
printf("VALUE=\""); |
html_print(req->p[i]); |
html_print(req->p[i]); |
printf("\">"); |
printf("\">"); |
Line 378 resp_searchform(const struct req *req) |
|
Line 440 resp_searchform(const struct req *req) |
|
} |
} |
puts("</SELECT>"); |
puts("</SELECT>"); |
} |
} |
puts("—\n" |
|
"<INPUT TYPE=\"reset\" VALUE=\"Reset\">\n" |
/* Write search radio button */ |
|
|
|
printf( "</TD><TD>\n" |
|
"<INPUT TYPE=\"radio\" "); |
|
if (0 == req->q.equal) |
|
printf("CHECKED "); |
|
printf( "NAME=\"apropos\" ID=\"search\" VALUE=\"1\">\n" |
|
"<LABEL FOR=\"search\">Search with apropos query</LABEL>\n"); |
|
|
|
puts("</TD></TR></TABLE>\n" |
"</FIELDSET>\n" |
"</FIELDSET>\n" |
"</FORM>\n" |
"</FORM>\n" |
"</DIV>"); |
"</DIV>"); |
Line 391 resp_index(const struct req *req) |
|
Line 462 resp_index(const struct req *req) |
|
{ |
{ |
|
|
resp_begin_html(200, NULL); |
resp_begin_html(200, NULL); |
puts("<H1>\n" |
|
"Online manuals with " |
|
"<A HREF=\"http://mdocml.bsd.lv/\">mandoc</A>\n" |
|
"</H1>"); |
|
resp_searchform(req); |
resp_searchform(req); |
printf("<P>\n" |
printf("<P>\n" |
"This web interface is documented in the " |
"This web interface is documented in the " |
"<A HREF=\"%s?query=man.cgi&sec=8\">" |
"<A HREF=\"%s/mandoc/man8/man.cgi.8\">man.cgi</A> " |
"man.cgi</A> manual, and the " |
"manual, and the " |
"<A HREF=\"%s?query=apropos&sec=1\">" |
"<A HREF=\"%s/mandoc/man1/apropos.1\">apropos</A> " |
"apropos</A> manual explains the query syntax.\n" |
"manual explains the query syntax.\n" |
"</P>\n", |
"</P>\n", |
scriptname, scriptname); |
scriptname, scriptname); |
resp_end_html(); |
resp_end_html(); |
Line 443 resp_error_internal(void) |
|
Line 510 resp_error_internal(void) |
|
static void |
static void |
resp_search(const struct req *req, struct manpage *r, size_t sz) |
resp_search(const struct req *req, struct manpage *r, size_t sz) |
{ |
{ |
size_t i; |
size_t i, iuse, isec; |
|
int prio, priouse; |
|
char sec; |
|
|
if (1 == sz) { |
if (1 == sz) { |
/* |
/* |
Line 485 resp_search(const struct req *req, struct manpage *r, |
|
Line 554 resp_search(const struct req *req, struct manpage *r, |
|
|
|
puts("</TABLE>\n" |
puts("</TABLE>\n" |
"</DIV>"); |
"</DIV>"); |
|
|
|
/* |
|
* In man(1) mode, show one of the pages |
|
* even if more than one is found. |
|
*/ |
|
|
|
if (req->q.equal) { |
|
puts("<HR>"); |
|
iuse = 0; |
|
priouse = 10; |
|
for (i = 0; i < sz; i++) { |
|
isec = strcspn(r[i].file, "123456789"); |
|
sec = r[i].file[isec]; |
|
if ('\0' == sec) |
|
continue; |
|
prio = sec_prios[sec - '1']; |
|
if (prio >= priouse) |
|
continue; |
|
priouse = prio; |
|
iuse = i; |
|
} |
|
resp_show(req, r[iuse].file); |
|
} |
|
|
resp_end_html(); |
resp_end_html(); |
} |
} |
|
|
Line 498 catman(const struct req *req, const char *file) |
|
Line 591 catman(const struct req *req, const char *file) |
|
int italic, bold; |
int italic, bold; |
|
|
if (NULL == (f = fopen(file, "r"))) { |
if (NULL == (f = fopen(file, "r"))) { |
resp_error_badrequest( |
puts("<P>You specified an invalid manual file.</P>"); |
"You specified an invalid manual file."); |
|
return; |
return; |
} |
} |
|
|
resp_begin_html(200, NULL); |
|
resp_searchform(req); |
|
puts("<DIV CLASS=\"catman\">\n" |
puts("<DIV CLASS=\"catman\">\n" |
"<PRE>"); |
"<PRE>"); |
|
|
Line 618 catman(const struct req *req, const char *file) |
|
Line 708 catman(const struct req *req, const char *file) |
|
} |
} |
|
|
puts("</PRE>\n" |
puts("</PRE>\n" |
"</DIV>\n" |
"</DIV>"); |
"</BODY>\n" |
|
"</HTML>"); |
|
|
|
fclose(f); |
fclose(f); |
} |
} |
Line 637 format(const struct req *req, const char *file) |
|
Line 725 format(const struct req *req, const char *file) |
|
char opts[PATH_MAX + 128]; |
char opts[PATH_MAX + 128]; |
|
|
if (-1 == (fd = open(file, O_RDONLY, 0))) { |
if (-1 == (fd = open(file, O_RDONLY, 0))) { |
resp_error_badrequest( |
puts("<P>You specified an invalid manual file.</P>"); |
"You specified an invalid manual file."); |
|
return; |
return; |
} |
} |
|
|
Line 667 format(const struct req *req, const char *file) |
|
Line 754 format(const struct req *req, const char *file) |
|
return; |
return; |
} |
} |
|
|
resp_begin_html(200, NULL); |
|
resp_searchform(req); |
|
|
|
vp = html_alloc(opts); |
vp = html_alloc(opts); |
|
|
if (NULL != mdoc) |
if (NULL != mdoc) |
Line 677 format(const struct req *req, const char *file) |
|
Line 761 format(const struct req *req, const char *file) |
|
else |
else |
html_man(vp, man); |
html_man(vp, man); |
|
|
puts("</BODY>\n" |
|
"</HTML>"); |
|
|
|
html_free(vp); |
html_free(vp); |
mparse_free(mp); |
mparse_free(mp); |
} |
} |
|
|
static void |
static void |
|
resp_show(const struct req *req, const char *file) |
|
{ |
|
|
|
if ('c' == *file) |
|
catman(req, file); |
|
else |
|
format(req, file); |
|
} |
|
|
|
static void |
pg_show(const struct req *req, const char *path) |
pg_show(const struct req *req, const char *path) |
{ |
{ |
char *sub; |
char *sub; |
Line 708 pg_show(const struct req *req, const char *path) |
|
Line 799 pg_show(const struct req *req, const char *path) |
|
return; |
return; |
} |
} |
|
|
if ('c' == *sub) |
resp_begin_html(200, NULL); |
catman(req, sub); |
resp_searchform(req); |
else |
resp_show(req, sub); |
format(req, sub); |
resp_end_html(); |
} |
} |
|
|
static void |
static void |
|
|
|
|
/* Scan our run-time environment. */ |
/* Scan our run-time environment. */ |
|
|
if (NULL == (mandir = getenv("MAN_DIR"))) |
|
mandir = "/man"; |
|
|
|
if (NULL == (scriptname = getenv("SCRIPT_NAME"))) |
if (NULL == (scriptname = getenv("SCRIPT_NAME"))) |
scriptname = ""; |
scriptname = ""; |
|
|
if (NULL == (cssdir = getenv("CSS_DIR"))) |
|
cssdir = ""; |
|
|
|
if (NULL == (httphost = getenv("HTTP_HOST"))) |
if (NULL == (httphost = getenv("HTTP_HOST"))) |
httphost = "localhost"; |
httphost = "localhost"; |
|
|
/* |
/* |
* First we change directory into the mandir so that |
* First we change directory into the MAN_DIR so that |
* subsequent scanning for manpath directories is rooted |
* subsequent scanning for manpath directories is rooted |
* relative to the same position. |
* relative to the same position. |
*/ |
*/ |
|
|
if (-1 == chdir(mandir)) { |
if (-1 == chdir(MAN_DIR)) { |
fprintf(stderr, "MAN_DIR: %s: %s\n", |
fprintf(stderr, "MAN_DIR: %s: %s\n", |
mandir, strerror(errno)); |
MAN_DIR, strerror(errno)); |
resp_error_internal(); |
resp_error_internal(); |
return(EXIT_FAILURE); |
return(EXIT_FAILURE); |
} |
} |