Annotation of mandoc/man.cgi.3, Revision 1.4
1.4 ! schwarze 1: .\" $Id: man.cgi.3,v 1.3 2017/03/15 10:17:29 schwarze Exp $
1.1 schwarze 2: .\"
1.4 ! schwarze 3: .\" Copyright (c) 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
1.1 schwarze 4: .\"
5: .\" Permission to use, copy, modify, and distribute this software for any
6: .\" purpose with or without fee is hereby granted, provided that the above
7: .\" copyright notice and this permission notice appear in all copies.
8: .\"
9: .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: .\"
1.4 ! schwarze 17: .Dd $Mdocdate: March 15 2017 $
1.1 schwarze 18: .Dt MAN.CGI 3
19: .Os
20: .Sh NAME
21: .Nm man.cgi
22: .Nd internals of the CGI program to search and display manual pages
23: .Sh DESCRIPTION
24: The source code of
25: .Xr man.cgi 8
26: is organized in four levels:
27: .Pp
28: .Bl -enum -compact
29: .It
30: .Sx Top level
31: .It
32: .Sx Page generators
33: .It
34: .Sx Result generators
35: .It
36: .Sx Utility routines
37: .El
38: .Ss Top level
39: The top level of
40: .Xr man.cgi 8
41: consists of the
42: .Fn main
43: program and a few parser routines.
44: .Bl -tag -width 1n
45: .It Ft int Fn main void
46: The main program
47: .Bl -dash -compact
48: .It
49: limits execution time;
50: .It
51: changes to
52: .Dv MAN_DIR ,
53: the data directory containing all the manual trees;
54: .It
55: calls
56: .Fn parse_manpath_conf ;
57: .It
1.2 schwarze 58: if
59: .Ev PATH_INFO
60: is empty, calls
61: .Fn parse_query_string ;
62: otherwise,
1.1 schwarze 63: calls
64: .Fn parse_path_info ;
65: .It
66: validates the manpath and the architecture;
67: .It
68: calls the appropriate one among the
69: .Sx Page generators .
70: .El
71: .It Ft void Fn parse_manpath_conf "struct req *req"
72: Parses and validates
73: .Pa manpath.conf
74: and fills
75: .Va req->p
76: and
77: .Va req->psz .
78: .It Ft void Fn parse_path_info "struct req *req" "const char *path"
79: Parses and validates
80: .Ev PATH_INFO ,
81: clears
82: .Va req->isquery ,
83: and fills
84: .Va req->q .
85: .It Ft void Fn parse_query_string "struct req *req" "const char *qs"
86: Parses and validates
87: .Ev QUERY_STRING ,
88: sets
89: .Va req->isquery ,
90: and fills
91: .Va req->q .
92: This function is the only user of the utility functions
93: .Fn http_decode
94: and
95: .Fn set_query_attr .
96: .El
97: .Ss Page generators
98: The purpose of each page generator is to print a complete HTML page,
99: starting with the HTTP headers and continuing to the page footer.
100: Before starting HTML output with
101: .Fn resp_begin_html ,
102: some page generators do some preparatory work, for example to decide
103: which page to show.
104: Each page generator ends with a call to
105: .Fn resp_end_html .
106: .Bl -tag -width 1n
107: .It Ft void Fn pg_show "struct req *req" "const char *fullpath"
108: This page generator is used when
109: .Ev PATH_INFO
110: contains the complete path to a manual page including manpath,
111: section directory, optional architecture subdirectory, manual name
112: and section number suffix.
113: It validates the manpath, changes into it, validate the filename,
114: and then calls
115: .Fn resp_begin_html ,
116: .Fn resp_searchform ,
117: .Fn resp_show ,
118: and
119: .Fn resp_end_html
120: in that order.
121: .It Ft void Fn pg_search "const struct req *req"
122: This page generator is used when
123: .Ev PATH_INFO
124: contains a search query in short format or when
125: .Ev PATH_INFO
126: is empty and a
127: .Ev QUERY_STRING
128: is provided.
1.3 schwarze 129: If possible, requests using
130: .Ev QUERY_STRING
131: are redirected to URIs using
132: .Ev PATH_INFO
133: by calling
134: .Fn pg_redirect .
135: Otherwise, it changes into the manpath and calls
1.1 schwarze 136: .Xr mansearch 3 .
137: Depending on the result, it calls either
138: .Fn pg_noresult
139: or
140: .Fn pg_searchres .
1.3 schwarze 141: .It Ft void Fn pg_redirect "const struct req *req" "const char *name"
142: This function is special in so far as it does not print an HTML page,
143: but only an HTTP 303 response with a Location: of the form:
144: .Sm off
145: .No http://
146: .Ar host Ns /
147: .Op Ar scriptname Ns /
148: .Op Ar manpath Ns /
149: .Op Ar arch Ns /
150: .Fa name
151: .Op Pf . Ar sec
152: .Sm on
1.1 schwarze 153: .It Ft void Fn pg_noresult "const struct req *req" "const char *msg"
154: This function calls
155: .Fn resp_begin_html ,
156: .Fn resp_searchform ,
157: prints the
158: .Fa msg
159: passed to it, and calls
160: .Fn resp_end_html .
161: .It Ft void Fn pg_searchres "const struct req *req" "struct manpage *r"\
162: "size_t sz"
163: This function first validates the filenames found.
164: If
165: .Ev QUERY_STRING
166: was used and there is exactly one result,
167: it writes an HTTP redirect to that result.
168: Otherwise, it writes an HTML result page beginning with
169: .Fn resp_begin_html
170: and
171: .Fn resp_searchform .
172: If there is more than one result, it writes a list of links
173: to all the results.
174: If it was a
175: .Xr man 1
176: rather than an
177: .Xr apropos 1
178: query or if there is only one single result, it calls
179: .Fn resp_show .
180: Finally, it calls
181: .Fn resp_end_html .
182: .It Ft void Fn pg_index "const struct req *req"
183: This page generator is used when
184: .Ev PATH_INFO
185: and
186: .Ev QUERY_STRING
187: are both empty.
188: It calls
189: .Fn resp_begin_html
190: and
191: .Fn resp_searchform ,
192: writes links to help pages, and calls
193: .Fn resp_end_html .
194: .It Ft void Fn pg_error_badrequest "const char *msg"
195: This page generator is used when
196: .Fn main
197: or
198: .Fn pg_show
199: detect an invalid URI.
200: It calls
201: .Fn resp_begin_html ,
202: prints the
203: .Fa msg
204: provided, and calls
205: .Fn resp_end_html .
206: .It Ft void Fn pg_error_internal void
207: This page generator is used by various functions when errors are
208: detected in the
209: .Pa manpath.conf
210: configuration file, in
211: .Xr mandoc.db 5
212: databases, in the
213: .Xr mandoc 3
214: parser, in file system permissions, or when setting up timeouts.
215: It calls
216: .Fn resp_begin_html ,
217: prints
218: .Qq "Internal Server Error" ,
219: and calls
220: .Fn resp_end_html .
221: Before calling
222: .Fn pg_error_internal ,
223: call
224: .Xr warn 3
225: or
226: .Xr warnx 3
227: to log the reason of the error to the
228: .Xr httpd 8
229: server log file.
230: .El
231: .Ss Result generators
232: The purpose of result generators is to print a chunk of HTML code.
233: When they print untrusted strings or characters,
234: .Fn html_print
235: and
236: .Fn html_putchar
237: are used.
238: The highest level result generators are:
239: .Bl -tag -width 1n
1.4 ! schwarze 240: .It Ft void Fn resp_begin_html "int code" "const char *msg" "const char *file"
1.1 schwarze 241: This generator calls
242: .Fn resp_begin_http
243: to print the HTTP headers, then prints the HTML header up to the
244: opening tag of the <body> element, then copies the file
245: .Pa header.html
246: to the output, if it exists and is readable.
1.4 ! schwarze 247: If
! 248: .Fa file
! 249: is not
! 250: .Dv NULL ,
! 251: it is used for the <title> element.
1.2 schwarze 252: .It Ft void Fn resp_searchform "const struct req *req" "enum focus focus"
1.1 schwarze 253: This generator prints a search form, filling it with data
254: from the provided request object.
1.2 schwarze 255: If the
256: .Fa focus
257: argument is
258: .Dv FOCUS_QUERY ,
259: it sets the document's autofocus to the query input box.
1.1 schwarze 260: .It Ft void Fn resp_show "const struct req *req" "const char *file"
261: This wrapper dispatches to either
262: .Fn resp_catman
263: or
264: .Fn resp_format ,
265: depending on whether
266: .Ar file
267: starts with
268: .Pa cat
269: or
270: .Pa man ,
271: respectively.
272: .It Ft void Fn resp_catman "const struct req *req" "const char *file"
273: This generator translates a preformatted, backspace-encoded manual
274: page to HTML and prints it to the output.
275: .It Ft void Fn resp_format "const struct req *req" "const char *file"
276: This generator formats a manual page on the standard output,
277: using the functions documented in
278: .Xr mchars_alloc 3
279: and
280: .Xr mandoc 3 .
281: .It Ft void Fn resp_end_html void
282: This generator copies the file
283: .Pa footer.html
284: to the output, if it exists and is readable,
285: and closes the <body> and <html> elements.
286: .El
287: .Ss Utility routines
288: These functions take a string and return 1 if it is valid, or 0 otherwise.
289: .Bl -tag -width 1n
290: .It Ft int Fn validate_urifrag "const char *frag"
291: Checks that the string only contains alphanumeric ASCII characters,
292: dashes, dots, slashes, and underscores.
293: .It Ft int Fn validate_manpath "const struct req *req" "const char* manpath"
294: Checks that the string is either
295: .Qq mandoc
296: or one of the manpaths configured in
297: .Pa manpath.conf .
298: .It Ft int Fn validate_filename "const char *file"
299: Checks that the string starts with
300: .Qq man
301: or
302: .Qq cat
303: and does not ascend to parent directories.
304: .El
305: .Sh SEE ALSO
306: .Xr mandoc 3 ,
307: .Xr mansearch 3 ,
1.2 schwarze 308: .Xr mchars_alloc 3 ,
1.1 schwarze 309: .Xr mandoc.db 5 ,
310: .Xr man.cgi 8
CVSweb