xref: /plan9/sys/src/cmd/ip/httpd/man2html.c (revision 0b9a5132554aff81f12a30adb0ffd48684252652)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include "httpd.h"
580ee5cbfSDavid du Colombier #include "httpsrv.h"
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier static	Hio		*hout;
8223a736eSDavid du Colombier static	Hio		houtb;
980ee5cbfSDavid du Colombier static	HConnect	*connect;
107dd7cddfSDavid du Colombier 
11223a736eSDavid du Colombier void	doconvert(char*, int);
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier void
error(char * title,char * fmt,...)147dd7cddfSDavid du Colombier error(char *title, char *fmt, ...)
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier 	va_list arg;
177dd7cddfSDavid du Colombier 	char buf[1024], *out;
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier 	va_start(arg, fmt);
209a747e4fSDavid du Colombier 	out = vseprint(buf, buf+sizeof(buf), fmt, arg);
217dd7cddfSDavid du Colombier 	va_end(arg);
227dd7cddfSDavid du Colombier 	*out = 0;
237dd7cddfSDavid du Colombier 
2480ee5cbfSDavid du Colombier 	hprint(hout, "%s 404 %s\n", hversion, title);
257dd7cddfSDavid du Colombier 	hprint(hout, "Date: %D\n", time(nil));
267dd7cddfSDavid du Colombier 	hprint(hout, "Server: Plan9\n");
277dd7cddfSDavid du Colombier 	hprint(hout, "Content-type: text/html\n");
287dd7cddfSDavid du Colombier 	hprint(hout, "\n");
297dd7cddfSDavid du Colombier 	hprint(hout, "<head><title>%s</title></head>\n", title);
307dd7cddfSDavid du Colombier 	hprint(hout, "<body><h1>%s</h1></body>\n", title);
317dd7cddfSDavid du Colombier 	hprint(hout, "%s\n", buf);
3214414594SDavid du Colombier 	hflush(hout);
3314414594SDavid du Colombier 	writelog(connect, "Reply: 404\nReason: %s\n", title);
347dd7cddfSDavid du Colombier 	exits(nil);
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier typedef struct Hit	Hit;
387dd7cddfSDavid du Colombier struct Hit
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier 	Hit *next;
417dd7cddfSDavid du Colombier 	char *file;
427dd7cddfSDavid du Colombier };
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier void
lookup(char * object,int section,Hit ** list)457dd7cddfSDavid du Colombier lookup(char *object, int section, Hit **list)
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier 	int fd;
487dd7cddfSDavid du Colombier 	char *p, *f;
497dd7cddfSDavid du Colombier 	Biobuf b;
509a747e4fSDavid du Colombier 	char file[256];
517dd7cddfSDavid du Colombier 	Hit *h;
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier 	while(*list != nil)
547dd7cddfSDavid du Colombier 		list = &(*list)->next;
557dd7cddfSDavid du Colombier 
567dd7cddfSDavid du Colombier 	snprint(file, sizeof(file), "/sys/man/%d/INDEX", section);
577dd7cddfSDavid du Colombier 	fd = open(file, OREAD);
587dd7cddfSDavid du Colombier 	if(fd > 0){
597dd7cddfSDavid du Colombier 		Binit(&b, fd, OREAD);
607dd7cddfSDavid du Colombier 		for(;;){
617dd7cddfSDavid du Colombier 			p = Brdline(&b, '\n');
627dd7cddfSDavid du Colombier 			if(p == nil)
637dd7cddfSDavid du Colombier 				break;
647dd7cddfSDavid du Colombier 			p[Blinelen(&b)-1] = 0;
657dd7cddfSDavid du Colombier 			f = strchr(p, ' ');
667dd7cddfSDavid du Colombier 			if(f == nil)
677dd7cddfSDavid du Colombier 				continue;
687dd7cddfSDavid du Colombier 			*f++ = 0;
697dd7cddfSDavid du Colombier 			if(strcmp(p, object) == 0){
707dd7cddfSDavid du Colombier 				h = ezalloc(sizeof *h);
717dd7cddfSDavid du Colombier 				*list = h;
727dd7cddfSDavid du Colombier 				h->next = nil;
737dd7cddfSDavid du Colombier 				snprint(file, sizeof(file), "/%d/%s", section, f);
747dd7cddfSDavid du Colombier 				h->file = estrdup(file);
757dd7cddfSDavid du Colombier 				close(fd);
767dd7cddfSDavid du Colombier 				return;
777dd7cddfSDavid du Colombier 			}
787dd7cddfSDavid du Colombier 		}
797dd7cddfSDavid du Colombier 		close(fd);
807dd7cddfSDavid du Colombier 	}
817dd7cddfSDavid du Colombier 	snprint(file, sizeof(file), "/sys/man/%d/%s", section, object);
827dd7cddfSDavid du Colombier 	if(access(file, 0) == 0){
837dd7cddfSDavid du Colombier 		h = ezalloc(sizeof *h);
847dd7cddfSDavid du Colombier 		*list = h;
857dd7cddfSDavid du Colombier 		h->next = nil;
867dd7cddfSDavid du Colombier 		h->file = estrdup(file+8);
877dd7cddfSDavid du Colombier 	}
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier 
907dd7cddfSDavid du Colombier void
manindex(int sect,int vermaj)917dd7cddfSDavid du Colombier manindex(int sect, int vermaj)
927dd7cddfSDavid du Colombier {
937dd7cddfSDavid du Colombier 	int i;
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier 	if(vermaj){
9680ee5cbfSDavid du Colombier 		hokheaders(connect);
977dd7cddfSDavid du Colombier 		hprint(hout, "Content-type: text/html\r\n");
987dd7cddfSDavid du Colombier 		hprint(hout, "\r\n");
997dd7cddfSDavid du Colombier 	}
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier 	hprint(hout, "<head><title>plan 9 section index");
1027dd7cddfSDavid du Colombier 	if(sect)
1037dd7cddfSDavid du Colombier 		hprint(hout, "(%d)\n", sect);
1047dd7cddfSDavid du Colombier 	hprint(hout, "</title></head><body>\n");
1057dd7cddfSDavid du Colombier 	hprint(hout, "<H6>Section Index");
1067dd7cddfSDavid du Colombier 	if(sect)
1077dd7cddfSDavid du Colombier 		hprint(hout, "(%d)\n", sect);
1087dd7cddfSDavid du Colombier 	hprint(hout, "</H6>\n");
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier 	if(sect)
1117dd7cddfSDavid du Colombier 		hprint(hout, "<p><a href=\"/plan9/man%d.html\">/plan9/man%d.html</a>\n",
1127dd7cddfSDavid du Colombier 			sect, sect);
1137dd7cddfSDavid du Colombier 	else for(i = 1; i < 10; i++)
1147dd7cddfSDavid du Colombier 		hprint(hout, "<p><a href=\"/plan9/man%d.html\">/plan9/man%d.html</a>\n",
1157dd7cddfSDavid du Colombier 			i, i);
1167dd7cddfSDavid du Colombier 	hprint(hout, "</body>\n");
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier 
1197dd7cddfSDavid du Colombier void
man(char * o,int sect,int vermaj)1207dd7cddfSDavid du Colombier man(char *o, int sect, int vermaj)
1217dd7cddfSDavid du Colombier {
1227dd7cddfSDavid du Colombier 	int i;
1237dd7cddfSDavid du Colombier 	Hit *list;
1247dd7cddfSDavid du Colombier 
1257dd7cddfSDavid du Colombier 	list = nil;
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	if(*o == 0){
1287dd7cddfSDavid du Colombier 		manindex(sect, vermaj);
1297dd7cddfSDavid du Colombier 		return;
1307dd7cddfSDavid du Colombier 	}
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 	if(sect > 0 && sect < 10)
1337dd7cddfSDavid du Colombier 		lookup(o, sect, &list);
1347dd7cddfSDavid du Colombier 	else
1357dd7cddfSDavid du Colombier 		for(i = 1; i < 9; i++)
1367dd7cddfSDavid du Colombier 			lookup(o, i, &list);
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier 	if(list != nil && list->next == nil){
139223a736eSDavid du Colombier 		doconvert(list->file, vermaj);
1407dd7cddfSDavid du Colombier 		return;
1417dd7cddfSDavid du Colombier 	}
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier 	if(vermaj){
14480ee5cbfSDavid du Colombier 		hokheaders(connect);
1457dd7cddfSDavid du Colombier 		hprint(hout, "Content-type: text/html\r\n");
1467dd7cddfSDavid du Colombier 		hprint(hout, "\r\n");
1477dd7cddfSDavid du Colombier 	}
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 	hprint(hout, "<head><title>plan 9 man %H", o);
1507dd7cddfSDavid du Colombier 	if(sect)
1517dd7cddfSDavid du Colombier 		hprint(hout, "(%d)\n", sect);
1527dd7cddfSDavid du Colombier 	hprint(hout, "</title></head><body>\n");
1537dd7cddfSDavid du Colombier 	hprint(hout, "<H6>Search for %H", o);
1547dd7cddfSDavid du Colombier 	if(sect)
1557dd7cddfSDavid du Colombier 		hprint(hout, "(%d)\n", sect);
1567dd7cddfSDavid du Colombier 	hprint(hout, "</H6>\n");
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier 	for(; list; list = list->next)
1597dd7cddfSDavid du Colombier 		hprint(hout, "<p><a href=\"/magic/man2html%U\">/magic/man2html%H</a>\n",
1607dd7cddfSDavid du Colombier 			list->file, list->file);
1617dd7cddfSDavid du Colombier 	hprint(hout, "</body>\n");
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier void
strlwr(char * p)165*0b9a5132SDavid du Colombier strlwr(char *p)
166*0b9a5132SDavid du Colombier {
167*0b9a5132SDavid du Colombier 	for(; *p; p++)
168*0b9a5132SDavid du Colombier 		if('A' <= *p && *p <= 'Z')
169*0b9a5132SDavid du Colombier 			*p += 'a'-'A';
170*0b9a5132SDavid du Colombier }
171*0b9a5132SDavid du Colombier 
172*0b9a5132SDavid du Colombier void
redirectto(char * uri)1737dd7cddfSDavid du Colombier redirectto(char *uri)
1747dd7cddfSDavid du Colombier {
17580ee5cbfSDavid du Colombier 	if(connect){
17680ee5cbfSDavid du Colombier 		hmoved(connect, uri);
17780ee5cbfSDavid du Colombier 		exits(0);
17880ee5cbfSDavid du Colombier 	}else
1797dd7cddfSDavid du Colombier 		hprint(hout, "Your selection moved to <a href=\"%U\"> here</a>.<p></body>\r\n", uri);
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier void
searchfor(char * search)1837dd7cddfSDavid du Colombier searchfor(char *search)
1847dd7cddfSDavid du Colombier {
1857dd7cddfSDavid du Colombier 	int i, j, n, fd;
1867dd7cddfSDavid du Colombier 	char *p, *sp;
1877dd7cddfSDavid du Colombier 	Biobufhdr *b;
1887dd7cddfSDavid du Colombier 	char *arg[32];
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier 	hprint(hout, "<head><title>plan 9 search for %H</title></head>\n", search);
1917dd7cddfSDavid du Colombier 	hprint(hout, "<body>\n");
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier 	hprint(hout, "<p>This is a keyword search through Plan 9 man pages.\n");
1947dd7cddfSDavid du Colombier 	hprint(hout, "The search is case insensitive; blanks denote \"boolean and\".\n");
1957dd7cddfSDavid du Colombier 	hprint(hout, "<FORM METHOD=\"GET\" ACTION=\"/magic/man2html\">\n");
1967dd7cddfSDavid du Colombier 	hprint(hout, "<INPUT NAME=\"pat\" TYPE=\"text\" SIZE=\"60\">\n");
1977dd7cddfSDavid du Colombier 	hprint(hout, "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n");
1987dd7cddfSDavid du Colombier 	hprint(hout, "</FORM>\n");
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier 	hprint(hout, "<hr><H6>Search for %H</H6>\n", search);
2017dd7cddfSDavid du Colombier 	n = getfields(search, arg, 32, 1, "+");
2027dd7cddfSDavid du Colombier 	for(i = 0; i < n; i++){
2037dd7cddfSDavid du Colombier 		for(j = i+1; j < n; j++){
2047dd7cddfSDavid du Colombier 			if(strcmp(arg[i], arg[j]) > 0){
2057dd7cddfSDavid du Colombier 				sp = arg[j];
2067dd7cddfSDavid du Colombier 				arg[j] = arg[i];
2077dd7cddfSDavid du Colombier 				arg[i] = sp;
2087dd7cddfSDavid du Colombier 			}
2097dd7cddfSDavid du Colombier 		}
2107dd7cddfSDavid du Colombier 		sp = malloc(strlen(arg[i]) + 2);
2117dd7cddfSDavid du Colombier 		if(sp != nil){
2127dd7cddfSDavid du Colombier 			strcpy(sp+1, arg[i]);
2137dd7cddfSDavid du Colombier 			sp[0] = ' ';
2147dd7cddfSDavid du Colombier 			arg[i] = sp;
2157dd7cddfSDavid du Colombier 		}
2167dd7cddfSDavid du Colombier 	}
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier 	/*
2197dd7cddfSDavid du Colombier 	 *  search index till line starts alphabetically < first token
2207dd7cddfSDavid du Colombier 	 */
2217dd7cddfSDavid du Colombier 	fd = open("/sys/man/searchindex", OREAD);
2227dd7cddfSDavid du Colombier 	if(fd < 0){
2237dd7cddfSDavid du Colombier 		hprint(hout, "<body>error: No Plan 9 search index\n");
2247dd7cddfSDavid du Colombier 		hprint(hout, "</body>");
2257dd7cddfSDavid du Colombier 		return;
2267dd7cddfSDavid du Colombier 	}
2277dd7cddfSDavid du Colombier 	p = malloc(32*1024);
2287dd7cddfSDavid du Colombier 	if(p == nil){
2297dd7cddfSDavid du Colombier 		close(fd);
2307dd7cddfSDavid du Colombier 		return;
2317dd7cddfSDavid du Colombier 	}
2327dd7cddfSDavid du Colombier 	b = ezalloc(sizeof *b);
2337dd7cddfSDavid du Colombier 	Binits(b, fd, OREAD, (uchar*)p, 32*1024);
2347dd7cddfSDavid du Colombier 	for(;;){
2357dd7cddfSDavid du Colombier 		p = Brdline(b, '\n');
2367dd7cddfSDavid du Colombier 		if(p == nil)
2377dd7cddfSDavid du Colombier 			break;
2387dd7cddfSDavid du Colombier 		p[Blinelen(b)-1] = 0;
2397dd7cddfSDavid du Colombier 		for(i = 0; i < n; i++){
2407dd7cddfSDavid du Colombier 			sp = strstr(p, arg[i]);
2417dd7cddfSDavid du Colombier 			if(sp == nil)
2427dd7cddfSDavid du Colombier 				break;
2437dd7cddfSDavid du Colombier 			p = sp;
2447dd7cddfSDavid du Colombier 		}
2457dd7cddfSDavid du Colombier 		if(i < n)
2467dd7cddfSDavid du Colombier 			continue;
2477dd7cddfSDavid du Colombier 		sp = strrchr(p, '\t');
2487dd7cddfSDavid du Colombier 		if(sp == nil)
2497dd7cddfSDavid du Colombier 			continue;
2507dd7cddfSDavid du Colombier 		sp++;
2517dd7cddfSDavid du Colombier 		hprint(hout, "<p><a href=\"/magic/man2html/%U\">/magic/man2html/%H</a>\n",
2527dd7cddfSDavid du Colombier 			sp, sp);
2537dd7cddfSDavid du Colombier 	}
2547dd7cddfSDavid du Colombier 	hprint(hout, "</body>");
2557dd7cddfSDavid du Colombier 
2567dd7cddfSDavid du Colombier 	Bterm(b);
2577dd7cddfSDavid du Colombier 	free(b);
2587dd7cddfSDavid du Colombier 	free(p);
2597dd7cddfSDavid du Colombier 	close(fd);
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier /*
2637dd7cddfSDavid du Colombier  *  find man pages mentioning the search string
2647dd7cddfSDavid du Colombier  */
2657dd7cddfSDavid du Colombier void
dosearch(int vermaj,char * search)2667dd7cddfSDavid du Colombier dosearch(int vermaj, char *search)
2677dd7cddfSDavid du Colombier {
2687dd7cddfSDavid du Colombier 	int sect;
2697dd7cddfSDavid du Colombier 	char *p;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier 	if(strncmp(search, "man=", 4) == 0){
2727dd7cddfSDavid du Colombier 		sect = 0;
27380ee5cbfSDavid du Colombier 		search = hurlunesc(connect, search+4);
2747dd7cddfSDavid du Colombier 		p = strchr(search, '&');
2757dd7cddfSDavid du Colombier 		if(p != nil){
2767dd7cddfSDavid du Colombier 			*p++ = 0;
2777dd7cddfSDavid du Colombier 			if(strncmp(p, "sect=", 5) == 0)
2787dd7cddfSDavid du Colombier 				sect = atoi(p+5);
2797dd7cddfSDavid du Colombier 		}
2807dd7cddfSDavid du Colombier 		man(search, sect, vermaj);
2817dd7cddfSDavid du Colombier 		return;
2827dd7cddfSDavid du Colombier 	}
2837dd7cddfSDavid du Colombier 
2847dd7cddfSDavid du Colombier 	if(vermaj){
28580ee5cbfSDavid du Colombier 		hokheaders(connect);
2867dd7cddfSDavid du Colombier 		hprint(hout, "Content-type: text/html\r\n");
2877dd7cddfSDavid du Colombier 		hprint(hout, "\r\n");
2887dd7cddfSDavid du Colombier 	}
2897dd7cddfSDavid du Colombier 
2907dd7cddfSDavid du Colombier 	if(strncmp(search, "pat=", 4) == 0){
29180ee5cbfSDavid du Colombier 		search = hurlunesc(connect, search+4);
29280ee5cbfSDavid du Colombier 		search = hlower(search);
2937dd7cddfSDavid du Colombier 		searchfor(search);
2947dd7cddfSDavid du Colombier 		return;
2957dd7cddfSDavid du Colombier 	}
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	hprint(hout, "<head><title>illegal search</title></head>\n");
2987dd7cddfSDavid du Colombier 	hprint(hout, "<body><p>Illegally formatted Plan 9 man page search</p>\n");
29980ee5cbfSDavid du Colombier 	search = hurlunesc(connect, search);
3007dd7cddfSDavid du Colombier 	hprint(hout, "<body><p>%H</p>\n", search);
3017dd7cddfSDavid du Colombier 	hprint(hout, "</body>");
3027dd7cddfSDavid du Colombier }
3037dd7cddfSDavid du Colombier 
3047dd7cddfSDavid du Colombier /*
3057dd7cddfSDavid du Colombier  *  convert a man page to html and output
3067dd7cddfSDavid du Colombier  */
3077dd7cddfSDavid du Colombier void
doconvert(char * uri,int vermaj)308223a736eSDavid du Colombier doconvert(char *uri, int vermaj)
3097dd7cddfSDavid du Colombier {
310223a736eSDavid du Colombier 	char *p;
3117dd7cddfSDavid du Colombier 	char file[256];
312223a736eSDavid du Colombier 	char title[256];
3139a747e4fSDavid du Colombier 	char err[ERRMAX];
314223a736eSDavid du Colombier 	int pfd[2];
3159a747e4fSDavid du Colombier 	Dir *d;
3169a747e4fSDavid du Colombier 	Waitmsg *w;
317223a736eSDavid du Colombier 	int x;
3187dd7cddfSDavid du Colombier 
3197dd7cddfSDavid du Colombier 	if(strstr(uri, ".."))
3207dd7cddfSDavid du Colombier 		error("bad URI", "man page URI cannot contain ..");
3217dd7cddfSDavid du Colombier 	p = strstr(uri, "/intro");
322223a736eSDavid du Colombier 
3237dd7cddfSDavid du Colombier 	if(p == nil){
324*0b9a5132SDavid du Colombier 		while(*uri == '/')
325*0b9a5132SDavid du Colombier 			uri++;
326223a736eSDavid du Colombier 		/* redirect section requests */
3277dd7cddfSDavid du Colombier 		snprint(file, sizeof(file), "/sys/man/%s", uri);
3289a747e4fSDavid du Colombier 		d = dirstat(file);
329*0b9a5132SDavid du Colombier 		if(d == nil){
330*0b9a5132SDavid du Colombier 			strlwr(file);
331*0b9a5132SDavid du Colombier 			if(dirstat(file) != nil){
332*0b9a5132SDavid du Colombier 				snprint(file, sizeof(file), "/magic/man2html/%s", uri);
333*0b9a5132SDavid du Colombier 				strlwr(file);
334*0b9a5132SDavid du Colombier 				redirectto(file);
335*0b9a5132SDavid du Colombier 			}
336223a736eSDavid du Colombier 			error(uri, "man page not found");
337*0b9a5132SDavid du Colombier 		}
3389a747e4fSDavid du Colombier 		x = d->qid.type;
3399a747e4fSDavid du Colombier 		free(d);
3409a747e4fSDavid du Colombier 		if(x & QTDIR){
3417dd7cddfSDavid du Colombier 			if(*uri == 0 || strcmp(uri, "/") == 0)
342223a736eSDavid du Colombier 				redirectto("/sys/man/index.html");
3437dd7cddfSDavid du Colombier 			else {
344223a736eSDavid du Colombier 				snprint(file, sizeof(file), "/sys/man/%s/INDEX.html",
3457dd7cddfSDavid du Colombier 					uri+1);
3467dd7cddfSDavid du Colombier 				redirectto(file);
3477dd7cddfSDavid du Colombier 			}
3487dd7cddfSDavid du Colombier 			return;
3497dd7cddfSDavid du Colombier 		}
3507dd7cddfSDavid du Colombier 	} else {
351223a736eSDavid du Colombier 		/* rewrite the name intro */
3527dd7cddfSDavid du Colombier 		*p = 0;
3537dd7cddfSDavid du Colombier 		snprint(file, sizeof(file), "/sys/man/%s/0intro", uri);
3549a747e4fSDavid du Colombier 		d = dirstat(file);
3559a747e4fSDavid du Colombier 		free(d);
3569a747e4fSDavid du Colombier 		if(d == nil)
357223a736eSDavid du Colombier 			error(uri, "man page not found");
3587dd7cddfSDavid du Colombier 	}
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier 	if(vermaj){
36180ee5cbfSDavid du Colombier 		hokheaders(connect);
3627dd7cddfSDavid du Colombier 		hprint(hout, "Content-type: text/html\r\n");
3637dd7cddfSDavid du Colombier 		hprint(hout, "\r\n");
3647dd7cddfSDavid du Colombier 	}
365223a736eSDavid du Colombier 	hflush(hout);
3667dd7cddfSDavid du Colombier 
367223a736eSDavid du Colombier 	if(pipe(pfd) < 0)
368223a736eSDavid du Colombier 		error("out of resources", "pipe failed");
369223a736eSDavid du Colombier 
370223a736eSDavid du Colombier 	/* troff -manhtml <file> | troff2html -t '' */
371223a736eSDavid du Colombier 	switch(fork()){
372223a736eSDavid du Colombier 	case -1:
373223a736eSDavid du Colombier 		error("out of resources", "fork failed");
374223a736eSDavid du Colombier 	case 0:
375223a736eSDavid du Colombier 		snprint(title, sizeof(title), "Plan 9 %s", file);
376223a736eSDavid du Colombier 		close(0);
377223a736eSDavid du Colombier 		dup(pfd[0], 0);
378223a736eSDavid du Colombier 		close(pfd[0]);
379223a736eSDavid du Colombier 		close(pfd[1]);
380f19e7b74SDavid du Colombier 		execl("/bin/troff2html", "troff2html", "-t", title, nil);
3819a747e4fSDavid du Colombier 		errstr(err, sizeof err);
382223a736eSDavid du Colombier 		exits(err);
3837dd7cddfSDavid du Colombier 	}
384223a736eSDavid du Colombier 	switch(fork()){
385223a736eSDavid du Colombier 	case -1:
386223a736eSDavid du Colombier 		error("out of resources", "fork failed");
387223a736eSDavid du Colombier 	case 0:
388223a736eSDavid du Colombier 		snprint(title, sizeof(title), "Plan 9 %s", file);
389223a736eSDavid du Colombier 		close(0);
390223a736eSDavid du Colombier 		close(1);
391223a736eSDavid du Colombier 		dup(pfd[1], 1);
392223a736eSDavid du Colombier 		close(pfd[0]);
393223a736eSDavid du Colombier 		close(pfd[1]);
394f19e7b74SDavid du Colombier 		execl("/bin/troff", "troff", "-manhtml", file, nil);
3959a747e4fSDavid du Colombier 		errstr(err, sizeof err);
396223a736eSDavid du Colombier 		exits(err);
397223a736eSDavid du Colombier 	}
398223a736eSDavid du Colombier 	close(pfd[0]);
399223a736eSDavid du Colombier 	close(pfd[1]);
4007dd7cddfSDavid du Colombier 
401223a736eSDavid du Colombier 	/* wait for completion */
4027dd7cddfSDavid du Colombier 	for(;;){
4039a747e4fSDavid du Colombier 		w = wait();
4049a747e4fSDavid du Colombier 		if(w == nil)
4057dd7cddfSDavid du Colombier 			break;
4069a747e4fSDavid du Colombier 		if(w->msg[0] != 0)
4079a747e4fSDavid du Colombier 			print("whoops %s\n", w->msg);
4089a747e4fSDavid du Colombier 		free(w);
4097dd7cddfSDavid du Colombier 	}
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier void
main(int argc,char ** argv)4137dd7cddfSDavid du Colombier main(int argc, char **argv)
4147dd7cddfSDavid du Colombier {
4159a747e4fSDavid du Colombier 	fmtinstall('H', httpfmt);
4169a747e4fSDavid du Colombier 	fmtinstall('U', hurlfmt);
417223a736eSDavid du Colombier 
418223a736eSDavid du Colombier 	if(argc == 2){
4197dd7cddfSDavid du Colombier 		hinit(&houtb, 1, Hwrite);
4207dd7cddfSDavid du Colombier 		hout = &houtb;
421223a736eSDavid du Colombier 		doconvert(argv[1], 0);
4227dd7cddfSDavid du Colombier 		exits(nil);
4237dd7cddfSDavid du Colombier 	}
4247dd7cddfSDavid du Colombier 	close(2);
4257dd7cddfSDavid du Colombier 
4267dd7cddfSDavid du Colombier 	connect = init(argc, argv);
4277dd7cddfSDavid du Colombier 	hout = &connect->hout;
42880ee5cbfSDavid du Colombier 	if(hparseheaders(connect, HSTIMEOUT) < 0)
42980ee5cbfSDavid du Colombier 		exits("failed");
4307dd7cddfSDavid du Colombier 
43180ee5cbfSDavid du Colombier 	if(strcmp(connect->req.meth, "GET") != 0 && strcmp(connect->req.meth, "HEAD") != 0){
43280ee5cbfSDavid du Colombier 		hunallowed(connect, "GET, HEAD");
43380ee5cbfSDavid du Colombier 		exits("not allowed");
43480ee5cbfSDavid du Colombier 	}
43580ee5cbfSDavid du Colombier 	if(connect->head.expectother || connect->head.expectcont){
43680ee5cbfSDavid du Colombier 		hfail(connect, HExpectFail, nil);
43780ee5cbfSDavid du Colombier 		exits("failed");
43880ee5cbfSDavid du Colombier 	}
4397dd7cddfSDavid du Colombier 
44080ee5cbfSDavid du Colombier 	bind("/usr/web/sys/man", "/sys/man", MREPL);
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier 	if(connect->req.search != nil)
4437dd7cddfSDavid du Colombier 		dosearch(connect->req.vermaj, connect->req.search);
4447dd7cddfSDavid du Colombier 	else
445223a736eSDavid du Colombier 		doconvert(connect->req.uri, connect->req.vermaj);
44614414594SDavid du Colombier 	hflush(hout);
44714414594SDavid du Colombier 	writelog(connect, "200 man2html %ld %ld\n", hout->seek, hout->seek);
4487dd7cddfSDavid du Colombier 	exits(nil);
4497dd7cddfSDavid du Colombier }
450