MAN.CGI(3)

NAME
man.cgi - internals of the CGI program to search and display manual pages

DESCRIPTION
The source code of man.cgi(8) is organized in four levels:

1.  Top level
2.  Page generators
3.  Result generators
4.  Utility routines

  Top level
The top level of man.cgi(8) consists of the main() program and a few parser routines.

int main(void)
    The main program
    -   limits execution time;
    -   changes to MAN_DIR, the data directory containing all the manual trees;
    -   calls parse_manpath_conf();
    -   if PATH_INFO is empty, calls parse_query_string(); otherwise, calls parse_path_info();
    -   validates the manpath and the architecture;
    -   calls the appropriate one among the Page generators.

void parse_manpath_conf(struct req *req)
    Parses and validates manpath.conf and fills req->p and req->psz.

void parse_path_info(struct req *req, const char *path)
    Parses and validates PATH_INFO, clears req->isquery, and fills req->q.

void parse_query_string(struct req *req, const char *qs)
    Parses and validates QUERY_STRING, sets req->isquery, and fills req->q. This function is the only user of the utility functions http_decode() and set_query_attr().

  Page generators
The purpose of each page generator is to print a complete HTML page, starting with the HTTP headers and continuing to the page footer. Before starting HTML output with resp_begin_html(), some page generators do some preparatory work, for example to decide which page to show. Each page generator ends with a call to resp_end_html().

void pg_show(struct req *req, const char *fullpath)
    This page generator is used when PATH_INFO contains the complete path to a manual page including manpath, section directory, optional architecture subdirectory, manual name and section number suffix. It validates the manpath, changes into it, validate the filename, and then calls resp_begin_html(), resp_searchform(), resp_show(), and resp_end_html() in that order.

void pg_search(const struct req *req)
    This page generator is used when PATH_INFO contains a search query in short format or when PATH_INFO is empty and a QUERY_STRING is provided. If possible, requests using QUERY_STRING are redirected to URIs using PATH_INFO by calling pg_redirect(). Otherwise, it changes into the manpath and calls mansearch(3). Depending on the result, it calls either pg_noresult() or pg_searchres().

void pg_redirect(const struct req *req, const char *name)
    This function is special in so far as it does not print an HTML page, but only an HTTP 303 response with a Location: of the form: http:// host/ [scriptname/] [manpath/] [arch/] name [.sec]

void pg_noresult(const struct req *req, const char *msg)
    This function calls resp_begin_html(), resp_searchform(), prints the msg passed to it, and calls resp_end_html().

void pg_searchres(const struct req *req, struct manpage *r, size_t sz)
    This function first validates the filenames found. If QUERY_STRING was used and there is exactly one result, it writes an HTTP redirect to that result. Otherwise, it writes an HTML result page beginning with resp_begin_html() and resp_searchform(). If there is more than one result, it writes a list of links to all the results. If it was a man(1) rather than an apropos(1) query or if there is only one single result, it calls resp_show(). Finally, it calls resp_end_html().

void pg_index(const struct req *req)
    This page generator is used when PATH_INFO and QUERY_STRING are both empty. It calls resp_begin_html() and resp_searchform(), writes links to help pages, and calls resp_end_html().

void pg_error_badrequest(const char *msg)
    This page generator is used when main() or pg_show() detect an invalid URI. It calls resp_begin_html(), prints the msg provided, and calls resp_end_html().

void pg_error_internal(void)
    This page generator is used by various functions when errors are detected in the manpath.conf configuration file, in mandoc.db(5) databases, in the mandoc(3) parser, in file system permissions, or when setting up timeouts. It calls resp_begin_html(), prints "Internal Server Error", and calls resp_end_html(). Before calling pg_error_internal(), call warn(3) or warnx(3) to log the reason of the error to the httpd(8) server log file.

  Result generators
The purpose of result generators is to print a chunk of HTML code. When they print untrusted strings or characters, html_print() and html_putchar() are used. The highest level result generators are:

void resp_begin_html(int code, const char *msg, const char *file)
    This generator calls resp_begin_http() to print the HTTP headers, then prints the HTML header up to the opening tag of the <body> element, then copies the file header.html to the output, if it exists and is readable. If file is not NULL, it is used for the <title> element.

void resp_searchform(const struct req *req, enum focus focus)
    This generator prints a search form, filling it with data from the provided request object. If the focus argument is FOCUS_QUERY, it sets the document's autofocus to the query input box.

void resp_show(const struct req *req, const char *file)
    This wrapper dispatches to either resp_catman() or resp_format(), depending on whether file starts with cat or man, respectively.

void resp_catman(const struct req *req, const char *file)
    This generator translates a preformatted, backspace-encoded manual page to HTML and prints it to the output.

void resp_format(const struct req *req, const char *file)
    This generator formats a manual page on the standard output, using the functions documented in mchars_alloc(3) and mandoc(3).

void resp_end_html(void)
    This generator copies the file footer.html to the output, if it exists and is readable, and closes the <body> and <html> elements.

  Utility routines
These functions take a string and return 1 if it is valid, or 0 otherwise.

int validate_urifrag(const char *frag)
    Checks that the string only contains alphanumeric ASCII characters, dashes, dots, slashes, and underscores.

int validate_manpath(const struct req *req, const char* manpath)
    Checks that the string is either "mandoc" or one of the manpaths configured in manpath.conf.

int validate_filename(const char *file)
    Checks that the string starts with "man" or "cat" and does not ascend to parent directories.

SEE ALSO
mandoc(3), mansearch(3), mchars_alloc(3), mandoc.db(5), man.cgi(8)