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