9 static HConnect *connect;
11 void doconvert(char*, int);
14 error(char *title, char *fmt, ...)
20 out = vseprint(buf, buf+sizeof(buf), fmt, arg);
24 hprint(hout, "%s 404 %s\n", hversion, title);
25 hprint(hout, "Date: %D\n", time(nil));
26 hprint(hout, "Server: Plan9\n");
27 hprint(hout, "Content-type: text/html\n");
29 hprint(hout, "<head><title>%s</title></head>\n", title);
30 hprint(hout, "<body><h1>%s</h1></body>\n", title);
31 hprint(hout, "%s\n", buf);
33 writelog(connect, "Reply: 404\nReason: %s\n", title);
37 typedef struct Hit Hit;
45 lookup(char *object, int section, Hit **list)
54 list = &(*list)->next;
56 snprint(file, sizeof(file), "/sys/man/%d/INDEX", section);
57 fd = open(file, OREAD);
61 p = Brdline(&b, '\n');
64 p[Blinelen(&b)-1] = 0;
69 if(strcmp(p, object) == 0){
70 h = ezalloc(sizeof *h);
73 snprint(file, sizeof(file), "/%d/%s", section, f);
74 h->file = estrdup(file);
81 snprint(file, sizeof(file), "/sys/man/%d/%s", section, object);
82 if(access(file, 0) == 0){
83 h = ezalloc(sizeof *h);
86 h->file = estrdup(file+8);
91 manindex(int sect, int vermaj)
97 hprint(hout, "Content-type: text/html\r\n");
101 hprint(hout, "<head><title>plan 9 section index");
103 hprint(hout, "(%d)\n", sect);
104 hprint(hout, "</title></head><body>\n");
105 hprint(hout, "<H6>Section Index");
107 hprint(hout, "(%d)\n", sect);
108 hprint(hout, "</H6>\n");
111 hprint(hout, "<p><a href=\"/plan9/man%d.html\">/plan9/man%d.html</a>\n",
113 else for(i = 1; i < 10; i++)
114 hprint(hout, "<p><a href=\"/plan9/man%d.html\">/plan9/man%d.html</a>\n",
116 hprint(hout, "</body>\n");
120 man(char *o, int sect, int vermaj)
128 manindex(sect, vermaj);
132 if(sect > 0 && sect < 10)
133 lookup(o, sect, &list);
135 for(i = 1; i < 9; i++)
138 if(list != nil && list->next == nil){
139 doconvert(list->file, vermaj);
145 hprint(hout, "Content-type: text/html\r\n");
146 hprint(hout, "\r\n");
149 hprint(hout, "<head><title>plan 9 man %H", o);
151 hprint(hout, "(%d)\n", sect);
152 hprint(hout, "</title></head><body>\n");
153 hprint(hout, "<H6>Search for %H", o);
155 hprint(hout, "(%d)\n", sect);
156 hprint(hout, "</H6>\n");
158 for(; list; list = list->next)
159 hprint(hout, "<p><a href=\"/magic/man2html%U\">/magic/man2html%H</a>\n",
160 list->file, list->file);
161 hprint(hout, "</body>\n");
168 if('A' <= *p && *p <= 'Z')
173 redirectto(char *uri)
176 hmoved(connect, uri);
179 hprint(hout, "Your selection moved to <a href=\"%U\"> here</a>.<p></body>\r\n", uri);
183 searchfor(char *search)
190 hprint(hout, "<head><title>plan 9 search for %H</title></head>\n", search);
191 hprint(hout, "<body>\n");
193 hprint(hout, "<p>This is a keyword search through Plan 9 man pages.\n");
194 hprint(hout, "The search is case insensitive; blanks denote \"boolean and\".\n");
195 hprint(hout, "<FORM METHOD=\"GET\" ACTION=\"/magic/man2html\">\n");
196 hprint(hout, "<INPUT NAME=\"pat\" TYPE=\"text\" SIZE=\"60\">\n");
197 hprint(hout, "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n");
198 hprint(hout, "</FORM>\n");
200 hprint(hout, "<hr><H6>Search for %H</H6>\n", search);
201 n = getfields(search, arg, 32, 1, "+");
202 for(i = 0; i < n; i++){
203 for(j = i+1; j < n; j++){
204 if(strcmp(arg[i], arg[j]) > 0){
210 sp = malloc(strlen(arg[i]) + 2);
212 strcpy(sp+1, arg[i]);
219 * search index till line starts alphabetically < first token
221 fd = open("/sys/man/searchindex", OREAD);
223 hprint(hout, "<body>error: No Plan 9 search index\n");
224 hprint(hout, "</body>");
232 b = ezalloc(sizeof *b);
233 Binits(b, fd, OREAD, (uchar*)p, 32*1024);
235 p = Brdline(b, '\n');
238 p[Blinelen(b)-1] = 0;
239 for(i = 0; i < n; i++){
240 sp = strstr(p, arg[i]);
247 sp = strrchr(p, '\t');
251 hprint(hout, "<p><a href=\"/magic/man2html/%U\">/magic/man2html/%H</a>\n",
254 hprint(hout, "</body>");
263 * find man pages mentioning the search string
266 dosearch(int vermaj, char *search)
271 if(strncmp(search, "man=", 4) == 0){
273 search = hurlunesc(connect, search+4);
274 p = strchr(search, '&');
277 if(strncmp(p, "sect=", 5) == 0)
280 man(search, sect, vermaj);
286 hprint(hout, "Content-type: text/html\r\n");
287 hprint(hout, "\r\n");
290 if(strncmp(search, "pat=", 4) == 0){
291 search = hurlunesc(connect, search+4);
292 search = hlower(search);
297 hprint(hout, "<head><title>illegal search</title></head>\n");
298 hprint(hout, "<body><p>Illegally formatted Plan 9 man page search</p>\n");
299 search = hurlunesc(connect, search);
300 hprint(hout, "<body><p>%H</p>\n", search);
301 hprint(hout, "</body>");
305 * convert a man page to html and output
308 doconvert(char *uri, int vermaj)
319 if(strstr(uri, ".."))
320 error("bad URI", "man page URI cannot contain ..");
321 p = strstr(uri, "/intro");
326 /* redirect section requests */
327 snprint(file, sizeof(file), "/sys/man/%s", uri);
331 if(dirstat(file) != nil){
332 snprint(file, sizeof(file), "/magic/man2html/%s", uri);
336 error(uri, "man page not found");
341 if(*uri == 0 || strcmp(uri, "/") == 0)
342 redirectto("/sys/man/index.html");
344 snprint(file, sizeof(file), "/sys/man/%s/INDEX.html",
351 /* rewrite the name intro */
353 snprint(file, sizeof(file), "/sys/man/%s/0intro", uri);
357 error(uri, "man page not found");
362 hprint(hout, "Content-type: text/html\r\n");
363 hprint(hout, "\r\n");
368 error("out of resources", "pipe failed");
370 /* troff -manhtml <file> | troff2html -t '' */
373 error("out of resources", "fork failed");
375 snprint(title, sizeof(title), "Plan 9 %s", file);
380 execl("/bin/troff2html", "troff2html", "-t", title, nil);
381 errstr(err, sizeof err);
386 error("out of resources", "fork failed");
388 snprint(title, sizeof(title), "Plan 9 %s", file);
394 execl("/bin/troff", "troff", "-manhtml", file, nil);
395 errstr(err, sizeof err);
401 /* wait for completion */
407 print("whoops %s\n", w->msg);
413 main(int argc, char **argv)
415 fmtinstall('H', httpfmt);
416 fmtinstall('U', hurlfmt);
419 hinit(&houtb, 1, Hwrite);
421 doconvert(argv[1], 0);
426 connect = init(argc, argv);
427 hout = &connect->hout;
428 if(hparseheaders(connect, HSTIMEOUT) < 0)
431 if(strcmp(connect->req.meth, "GET") != 0 && strcmp(connect->req.meth, "HEAD") != 0){
432 hunallowed(connect, "GET, HEAD");
433 exits("not allowed");
435 if(connect->head.expectother || connect->head.expectcont){
436 hfail(connect, HExpectFail, nil);
440 bind("/usr/web/sys/man", "/sys/man", MREPL);
442 if(connect->req.search != nil)
443 dosearch(connect->req.vermaj, connect->req.search);
445 doconvert(connect->req.uri, connect->req.vermaj);
447 writelog(connect, "200 man2html %ld %ld\n", hout->seek, hout->seek);