123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "httpd.h"
- #include "httpsrv.h"
- static Hio *hout;
- static Hio houtb;
- static HConnect *connect;
- void doconvert(char*, int);
- void
- error(char *title, char *fmt, ...)
- {
- va_list arg;
- char buf[1024], *out;
- va_start(arg, fmt);
- out = vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- *out = 0;
- hprint(hout, "%s 404 %s\n", hversion, title);
- hprint(hout, "Date: %D\n", time(nil));
- hprint(hout, "Server: Plan9\n");
- hprint(hout, "Content-type: text/html\n");
- hprint(hout, "\n");
- hprint(hout, "<head><title>%s</title></head>\n", title);
- hprint(hout, "<body><h1>%s</h1></body>\n", title);
- hprint(hout, "%s\n", buf);
- hflush(hout);
- writelog(connect, "Reply: 404\nReason: %s\n", title);
- exits(nil);
- }
- typedef struct Hit Hit;
- struct Hit
- {
- Hit *next;
- char *file;
- };
- void
- lookup(char *object, int section, Hit **list)
- {
- int fd;
- char *p, *f;
- Biobuf b;
- char file[256];
- Hit *h;
- while(*list != nil)
- list = &(*list)->next;
- snprint(file, sizeof(file), "/sys/man/%d/INDEX", section);
- fd = open(file, OREAD);
- if(fd > 0){
- Binit(&b, fd, OREAD);
- for(;;){
- p = Brdline(&b, '\n');
- if(p == nil)
- break;
- p[Blinelen(&b)-1] = 0;
- f = strchr(p, ' ');
- if(f == nil)
- continue;
- *f++ = 0;
- if(strcmp(p, object) == 0){
- h = ezalloc(sizeof *h);
- *list = h;
- h->next = nil;
- snprint(file, sizeof(file), "/%d/%s", section, f);
- h->file = estrdup(file);
- close(fd);
- return;
- }
- }
- close(fd);
- }
- snprint(file, sizeof(file), "/sys/man/%d/%s", section, object);
- if(access(file, 0) == 0){
- h = ezalloc(sizeof *h);
- *list = h;
- h->next = nil;
- h->file = estrdup(file+8);
- }
- }
- void
- manindex(int sect, int vermaj)
- {
- int i;
- if(vermaj){
- hokheaders(connect);
- hprint(hout, "Content-type: text/html\r\n");
- hprint(hout, "\r\n");
- }
- hprint(hout, "<head><title>plan 9 section index");
- if(sect)
- hprint(hout, "(%d)\n", sect);
- hprint(hout, "</title></head><body>\n");
- hprint(hout, "<H6>Section Index");
- if(sect)
- hprint(hout, "(%d)\n", sect);
- hprint(hout, "</H6>\n");
- if(sect)
- hprint(hout, "<p><a href=\"/plan9/man%d.html\">/plan9/man%d.html</a>\n",
- sect, sect);
- else for(i = 1; i < 10; i++)
- hprint(hout, "<p><a href=\"/plan9/man%d.html\">/plan9/man%d.html</a>\n",
- i, i);
- hprint(hout, "</body>\n");
- }
- void
- man(char *o, int sect, int vermaj)
- {
- int i;
- Hit *list;
- list = nil;
- if(*o == 0){
- manindex(sect, vermaj);
- return;
- }
- if(sect > 0 && sect < 10)
- lookup(o, sect, &list);
- else
- for(i = 1; i < 9; i++)
- lookup(o, i, &list);
- if(list != nil && list->next == nil){
- doconvert(list->file, vermaj);
- return;
- }
- if(vermaj){
- hokheaders(connect);
- hprint(hout, "Content-type: text/html\r\n");
- hprint(hout, "\r\n");
- }
- hprint(hout, "<head><title>plan 9 man %H", o);
- if(sect)
- hprint(hout, "(%d)\n", sect);
- hprint(hout, "</title></head><body>\n");
- hprint(hout, "<H6>Search for %H", o);
- if(sect)
- hprint(hout, "(%d)\n", sect);
- hprint(hout, "</H6>\n");
- for(; list; list = list->next)
- hprint(hout, "<p><a href=\"/magic/man2html%U\">/magic/man2html%H</a>\n",
- list->file, list->file);
- hprint(hout, "</body>\n");
- }
- void
- strlwr(char *p)
- {
- for(; *p; p++)
- if('A' <= *p && *p <= 'Z')
- *p += 'a'-'A';
- }
- void
- redirectto(char *uri)
- {
- if(connect){
- hmoved(connect, uri);
- exits(0);
- }else
- hprint(hout, "Your selection moved to <a href=\"%U\"> here</a>.<p></body>\r\n", uri);
- }
- void
- searchfor(char *search)
- {
- int i, j, n, fd;
- char *p, *sp;
- Biobufhdr *b;
- char *arg[32];
- hprint(hout, "<head><title>plan 9 search for %H</title></head>\n", search);
- hprint(hout, "<body>\n");
- hprint(hout, "<p>This is a keyword search through Plan 9 man pages.\n");
- hprint(hout, "The search is case insensitive; blanks denote \"boolean and\".\n");
- hprint(hout, "<FORM METHOD=\"GET\" ACTION=\"/magic/man2html\">\n");
- hprint(hout, "<INPUT NAME=\"pat\" TYPE=\"text\" SIZE=\"60\">\n");
- hprint(hout, "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n");
- hprint(hout, "</FORM>\n");
- hprint(hout, "<hr><H6>Search for %H</H6>\n", search);
- n = getfields(search, arg, 32, 1, "+");
- for(i = 0; i < n; i++){
- for(j = i+1; j < n; j++){
- if(strcmp(arg[i], arg[j]) > 0){
- sp = arg[j];
- arg[j] = arg[i];
- arg[i] = sp;
- }
- }
- sp = malloc(strlen(arg[i]) + 2);
- if(sp != nil){
- strcpy(sp+1, arg[i]);
- sp[0] = ' ';
- arg[i] = sp;
- }
- }
- /*
- * search index till line starts alphabetically < first token
- */
- fd = open("/sys/man/searchindex", OREAD);
- if(fd < 0){
- hprint(hout, "<body>error: No Plan 9 search index\n");
- hprint(hout, "</body>");
- return;
- }
- p = malloc(32*1024);
- if(p == nil){
- close(fd);
- return;
- }
- b = ezalloc(sizeof *b);
- Binits(b, fd, OREAD, (uchar*)p, 32*1024);
- for(;;){
- p = Brdline(b, '\n');
- if(p == nil)
- break;
- p[Blinelen(b)-1] = 0;
- for(i = 0; i < n; i++){
- sp = strstr(p, arg[i]);
- if(sp == nil)
- break;
- p = sp;
- }
- if(i < n)
- continue;
- sp = strrchr(p, '\t');
- if(sp == nil)
- continue;
- sp++;
- hprint(hout, "<p><a href=\"/magic/man2html/%U\">/magic/man2html/%H</a>\n",
- sp, sp);
- }
- hprint(hout, "</body>");
- Bterm(b);
- free(b);
- free(p);
- close(fd);
- }
- /*
- * find man pages mentioning the search string
- */
- void
- dosearch(int vermaj, char *search)
- {
- int sect;
- char *p;
- if(strncmp(search, "man=", 4) == 0){
- sect = 0;
- search = hurlunesc(connect, search+4);
- p = strchr(search, '&');
- if(p != nil){
- *p++ = 0;
- if(strncmp(p, "sect=", 5) == 0)
- sect = atoi(p+5);
- }
- man(search, sect, vermaj);
- return;
- }
- if(vermaj){
- hokheaders(connect);
- hprint(hout, "Content-type: text/html\r\n");
- hprint(hout, "\r\n");
- }
- if(strncmp(search, "pat=", 4) == 0){
- search = hurlunesc(connect, search+4);
- search = hlower(search);
- searchfor(search);
- return;
- }
- hprint(hout, "<head><title>illegal search</title></head>\n");
- hprint(hout, "<body><p>Illegally formatted Plan 9 man page search</p>\n");
- search = hurlunesc(connect, search);
- hprint(hout, "<body><p>%H</p>\n", search);
- hprint(hout, "</body>");
- }
- /*
- * convert a man page to html and output
- */
- void
- doconvert(char *uri, int vermaj)
- {
- char *p;
- char file[256];
- char title[256];
- char err[ERRMAX];
- int pfd[2];
- Dir *d;
- Waitmsg *w;
- int x;
- if(strstr(uri, ".."))
- error("bad URI", "man page URI cannot contain ..");
- p = strstr(uri, "/intro");
- if(p == nil){
- while(*uri == '/')
- uri++;
- /* redirect section requests */
- snprint(file, sizeof(file), "/sys/man/%s", uri);
- d = dirstat(file);
- if(d == nil){
- strlwr(file);
- if(dirstat(file) != nil){
- snprint(file, sizeof(file), "/magic/man2html/%s", uri);
- strlwr(file);
- redirectto(file);
- }
- error(uri, "man page not found");
- }
- x = d->qid.type;
- free(d);
- if(x & QTDIR){
- if(*uri == 0 || strcmp(uri, "/") == 0)
- redirectto("/sys/man/index.html");
- else {
- snprint(file, sizeof(file), "/sys/man/%s/INDEX.html",
- uri+1);
- redirectto(file);
- }
- return;
- }
- } else {
- /* rewrite the name intro */
- *p = 0;
- snprint(file, sizeof(file), "/sys/man/%s/0intro", uri);
- d = dirstat(file);
- free(d);
- if(d == nil)
- error(uri, "man page not found");
- }
- if(vermaj){
- hokheaders(connect);
- hprint(hout, "Content-type: text/html\r\n");
- hprint(hout, "\r\n");
- }
- hflush(hout);
- if(pipe(pfd) < 0)
- error("out of resources", "pipe failed");
- /* troff -manhtml <file> | troff2html -t '' */
- switch(fork()){
- case -1:
- error("out of resources", "fork failed");
- case 0:
- snprint(title, sizeof(title), "Plan 9 %s", file);
- close(0);
- dup(pfd[0], 0);
- close(pfd[0]);
- close(pfd[1]);
- execl("/bin/troff2html", "troff2html", "-t", title, nil);
- errstr(err, sizeof err);
- exits(err);
- }
- switch(fork()){
- case -1:
- error("out of resources", "fork failed");
- case 0:
- snprint(title, sizeof(title), "Plan 9 %s", file);
- close(0);
- close(1);
- dup(pfd[1], 1);
- close(pfd[0]);
- close(pfd[1]);
- execl("/bin/troff", "troff", "-manhtml", file, nil);
- errstr(err, sizeof err);
- exits(err);
- }
- close(pfd[0]);
- close(pfd[1]);
- /* wait for completion */
- for(;;){
- w = wait();
- if(w == nil)
- break;
- if(w->msg[0] != 0)
- print("whoops %s\n", w->msg);
- free(w);
- }
- }
- void
- main(int argc, char **argv)
- {
- fmtinstall('H', httpfmt);
- fmtinstall('U', hurlfmt);
- if(argc == 2){
- hinit(&houtb, 1, Hwrite);
- hout = &houtb;
- doconvert(argv[1], 0);
- exits(nil);
- }
- close(2);
- connect = init(argc, argv);
- hout = &connect->hout;
- if(hparseheaders(connect, HSTIMEOUT) < 0)
- exits("failed");
- if(strcmp(connect->req.meth, "GET") != 0 && strcmp(connect->req.meth, "HEAD") != 0){
- hunallowed(connect, "GET, HEAD");
- exits("not allowed");
- }
- if(connect->head.expectother || connect->head.expectcont){
- hfail(connect, HExpectFail, nil);
- exits("failed");
- }
- bind("/usr/web/sys/man", "/sys/man", MREPL);
- if(connect->req.search != nil)
- dosearch(connect->req.vermaj, connect->req.search);
- else
- doconvert(connect->req.uri, connect->req.vermaj);
- hflush(hout);
- writelog(connect, "200 man2html %ld %ld\n", hout->seek, hout->seek);
- exits(nil);
- }
|