#!/bin/rc # # command: /bin/boddle /n/juke/plan_9/sys/src/cmd/mothra /sys/src/cmd/mothra # srcdir: /n/juke/plan_9/sys/src/cmd/mothra # version: 836403055 # date: Wed Jul 3 10:10:55 EDT 1996 # myname=$0 doextract=no fn usage{ echo $myname: usage: $myname '[-X] [src-directory]' >[1=2] exit usage } fn sigint{ rm -rf 836403055 exit interrupt } while(~ $1 -*){ switch($1){ case -X doextract=yes case -* usage } shift } switch($#*){ case 0 srcdir=/sys/src/cmd/mothra case 1 srcdir=$1 case * usage } if(! ~ $doextract yes){ echo This shell file contains a bundle of diffs representing changes echo to original source files in the Plan 9 distribution. It will run echo against the files in echo ' ' $srcdir echo '(unless overridden by the optional source directory argument)' echo and create a directory 836403055 containing the updated files. echo It will NOT automatically update the original files. echo echo Invoke with argument -X to perform the actual extraction. exit 0 } rm -rf 836403055 mkdir 836403055 target=836403055/crackurl.c echo -n '836403055/crackurl.c: ' if(! test -f $srcdir/crackurl.c || ! test -r $srcdir/crackurl.c){ echo $srcdir/crackurl.c unreadable exit unreadable } sum=`{sum < $srcdir/crackurl.c} if(! ~ 405f6a513751 $sum(1)^$sum(2)){ echo $srcdir/crackurl.c is not the original distribution file exit original } cp $srcdir/crackurl.c 836403055/crackurl.c ed 836403055/crackurl.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM crackurl.c' 167a url->map=0; . 97c /* * In emulation of Netscape, attach a free "http://" * to names beginning with "www.". */ if(strncmp(urlname, "www.", 4)==0){ httpname=emalloc(strlen(urlname)+8); strcpy(httpname, "http://"); strcat(httpname, urlname); crackurl(url, httpname, cur); free(httpname); return; } url->port=cur->port; strcpy(url->ipaddr, cur->ipaddr); strcpy(url->reltext, cur->reltext); . 87c char *relp, *tagp, *httpname; . 83,84c * If the type identifier or the ip address and port number * or the relative address is missing from urlname or is empty, * it is copied from cur. . 45c else if(*s=='\0' || *s=='?') . 11c "https:", HTTP, IP|REL, 80, /* is this right? */ "ftp:", FTP, IP|REL, 21, . wq //GO.SYSIN DD VADIM crackurl.c sum=`{sum < 836403055/crackurl.c} if(~ efd854b24214 $sum(1)^$sum(2)) echo if not{ echo 836403055/crackurl.c checksum error creating updated file exit checksum } target=836403055/filetype.c echo -n '836403055/filetype.c: ' if(! test -f $srcdir/filetype.c || ! test -r $srcdir/filetype.c){ echo $srcdir/filetype.c unreadable exit unreadable } sum=`{sum < $srcdir/filetype.c} if(! ~ 50b1f7ad1455 $sum(1)^$sum(2)){ echo $srcdir/filetype.c is not the original distribution file exit original } cp $srcdir/filetype.c 836403055/filetype.c ed 836403055/filetype.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM filetype.c' 68,69c int content2type(char *s, char *name){ int type; type=klook(s, content); if(type==SUFFIX) type=suffix2type(name); return type; . 65a "application/pdf", PDF, "application/octet-stream", SUFFIX, . 63a "image/x-bitmap", XBM, . 62a "image/tiff", TIFF, . 51c kind|=suflook(name, len, suffix); . 33a int suflook(char *s, int len, Kind *k){ int l; while(k->name){ l=strlen(k->name); if(l<=len && cistrcmp(k->name, s+len-l)==0) return k->kind; k++; } return k->kind; } . 32c ".pdf", PDF, 0, PLAIN . 25a ".tif", TIFF, ".tiff", TIFF, . 19a "/", HTML, . wq //GO.SYSIN DD VADIM filetype.c sum=`{sum < 836403055/filetype.c} if(~ 9bb8f3a91891 $sum(1)^$sum(2)) echo if not{ echo 836403055/filetype.c checksum error creating updated file exit checksum } target=836403055/forms.c echo -n '836403055/forms.c: ' if(! test -f $srcdir/forms.c || ! test -r $srcdir/forms.c){ echo $srcdir/forms.c unreadable exit unreadable } sum=`{sum < $srcdir/forms.c} if(! ~ fa1ed0c410697 $sum(1)^$sum(2)){ echo $srcdir/forms.c is not the original distribution file exit original } cp $srcdir/forms.c 836403055/forms.c ed 836403055/forms.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM forms.c' 491,494c if(form->method==GET){ fprint(2, "GET %s\n", buf); geturl(buf, GET, 0, 0, 0); } else{ fprint(2, "POST %s: %s\n", form->action->fullname, buf); geturl(form->action->fullname, POST, buf, 0, 0); } . 477c bufp=ucpy(bufp, o->value); . 459a case INDEX: if(sep) *bufp++=sep; sep='&'; bufp=ucpy(bufp, plentryval(f->p)); break; . 450a if(form->method==GET && bufp!=buf && bufp[-1]=='?') *--bufp='\0'; /* spurious ? */ . 443c strcpy(buf, form->action->fullname); . 435c size+=ulen(f->name)+1+ulen(o->value)+1; . 430c size+=ulen(f->name)+1+ulen(f->value)+1; . 428a if(!f->state) break; . 426a case INDEX: size+=ulen(plentryval(f->p))+1; break; . 420c if(form->method==GET) size=ulen(form->action->fullname)+1; . 411a /* * If there's exactly one button with type=text, then * a CR in the button is supposed to submit the form. */ void h_submittype(Panel *p, char *){ int ntype; Field *f; ntype=0; for(f=((Field *)p->userp)->form->fields;f;f=f->next) if(f->type==TYPE) ntype++; if(ntype==1) h_submitinput(p, 0); } void h_submitindex(Panel *p, char *){ h_submitinput(p, 0); } . 393a else if(*s==' ') *buf++='+'; . 389c if(strchr("/$-_@.!*'(),", *s) . 320c plinitpulldown(f->p, FIXEDX, seloption(f), f->pulldown, PACKS); pldraw(f->p, &screen); . 285a case INDEX: f->p=plentry(0, 0, f->size*chrwidth, f->value, h_submitindex); break; . 267a plpack(f->pulldown, Rect(0,0,1024,1024)); f->p=plpulldown(0, FIXEDX, seloption(f), f->pulldown, PACKS); f->p->fixedsize.x=f->pulldown->r.max.x-f->pulldown->r.min.x; . 266c plinitlist(win, PACKN, selgen, f->size, h_select); . 261,264c f->pulldown=plgroup(0,0); scrl=plscrollbar(f->pulldown, PACKW|FILLY); win=pllist(f->pulldown, PACKN, selgen, f->size, h_select); . 250c f->p=plradiobutton(0, 0, "", h_radioinput); . 245c f->p=plcheckbutton(0, 0, "", h_checkinput); . 242c f->p=plentry(0, 0, f->size*chrwidth, f->value, h_submittype); . 234a char *seloption(Field *f){ Option *a; for(a=f->options;a!=0;a=a->next) if(a->selected) return a->label+1; return f->name; } . 219c if(g->form==0) htmlerror(g->name, g->lineno, " not in form, ignored\n"); else pl_htmloutput(g, g->nsp, g->form->efields->name,g->form->efields); . 206a /* * Make up a form with one tag, of type INDEX * I have seen a page with , * which is nonstandard and not handled here. */ form=emalloc(sizeof(Form)); form->fields=0; form->efields=0; form->action=emalloc(sizeof(Url)); s=pl_getattr(g->attr, "action"); if(s==0) *form->action=*g->dst->url; else crackurl(form->action, s, g->dst->base); form->method=GET; form->fields=0; f=newfield(form); f->name=0; f->value=strdup(""); f->size=20; f->maxlength=0x3fffffff; f->type=INDEX; pl_htmloutput(g, g->nsp, f->value[0]?f->value:"blank field", f); . 187,190c if(g->form==0) goto BadTag; f=newfield(g->form); . 184a s=pl_getattr(g->attr, "value"); if(s==0) o->value=o->label+1; /* is this right? */ else o->value=strdup(s); . 176,177c for(op=&f->options;*op;op=&(*op)->next); *op=o; o->next=0; . 174c if(g->form==0) goto BadTag; f=g->form->efields; . 149,152c if(g->form==0) goto BadTag; f=newfield(g->form); . 144a if((f->type==CHECK || f->type==RADIO) && !pl_hasattr(g->attr, "value")){ free(f->value); f->value=strdup("on"); } . 142c htmlerror(g->name, g->lineno, "bad field type %s, ignored", s); . 137c else if(cistrcmp(s, "image")==0){ /* presotto's egregious hack to make image submits do something */ if(f->name){ free(f->name); f->name=0; } f->type=SUBMIT; } else if(cistrcmp(s, "reset")==0) . 129,130c if(s==0 || cistrcmp(s, "text")==0 || cistrcmp(s, "password")==0 || cistrcmp(s, "int")==0){ s=pl_getattr(g->attr, "name"); if(s!=0 && strcmp(s, "isindex")==0) f->type=INDEX; else f->type=TYPE; /* * If there's exactly one attribute, use its value as the name, * regardless of the attribute name. This makes * http://linus.att.com/ias/puborder.html work. */ if(s==0){ if(g->attr[0].name && g->attr[1].name==0) f->name=g->attr[0].value; else f->name="no-name"; } } . 102,105c if(g->form==0){ BadTag: htmlerror(g->name, g->lineno, "<%s> not in form, ignored\n", tag[g->tag].name); break; } f=newfield(g->form); . 83,87c *g->form->action=*g->dst->url; else crackurl(g->form->action, s, g->dst->base); . 80a g->form->efields=0; g->form->action=emalloc(sizeof(Url)); . 69c Option *o, **op; Form *form; . 62a Field *newfield(Form *form){ Field *f; f=emalloc(sizeof(Field)); if(form->efields==0) form->fields=f; else form->efields->next=f; form->efields=f; f->next=0; f->form=form; return f; } . 55a void h_submittype(Panel *, char *); void h_submitindex(Panel *, char *); . 50a char *value; . 30a Panel *pulldown; . 15c Field *fields, *efields; . 2c * type=image is treated like submit . wq //GO.SYSIN DD VADIM forms.c sum=`{sum < 836403055/forms.c} if(~ b5efbb5f13828 $sum(1)^$sum(2)) echo if not{ echo 836403055/forms.c checksum error creating updated file exit checksum } target=836403055/getpix.c echo -n '836403055/getpix.c: ' if(! test -f $srcdir/getpix.c || ! test -r $srcdir/getpix.c){ echo $srcdir/getpix.c unreadable exit unreadable } sum=`{sum < $srcdir/getpix.c} if(! ~ 7422daaa2743 $sum(1)^$sum(2)){ echo $srcdir/getpix.c is not the original distribution file exit original } cp $srcdir/getpix.c 836403055/getpix.c ed 836403055/getpix.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM getpix.c' 142a } } void getpix(Rtext *t, Www *w){ Action *ap; Url url; int fd; Bitmap *b; char err[512]; for(;t!=0;t=t->next){ ap=t->user; if(ap && ap->image) getimage(t, w); . 133,134d 130c b=floyd(a->r, screen.ldepth, (uchar *)a->imagebits); . 61,125d 56,57c ap->r=Rect(0, 0, nx, ny); ap->imagebits=bits; close(fd); w->changed=1; . 52a if(bits==0){ picclose(f); werrstr("no space for image"); goto Err; } . 49a if(f==0){ werrstr("error in picopen_r"); goto Err; } . 48d 39,42c execl("/bin/rc", "rc", "-c", pixcmd[url.type], 0); . 27,28c Action *ap; Url url; Bitmap *b; int fd; char err[512]; Pix *p; ap=t->user; crackurl(&url, ap->image, w->base); free(ap->image); ap->image=strdup(url.fullname); for(p=pix;p!=epix;p++) if(strcmp(url.fullname, p->name)==0){ storebitmap(t, p->b); w->changed=1; return; } if(!inlinepix && !ap->ismap) return; fd=urlopen(&url, GET, 0); if(fd==-1){ Err: sprint(err, "[%s: %r]", url.fullname); close(fd); free(t->text); t->text=strdup(err); free(ap->image); if(ap->link==0){ free(ap); t->user=0; } return; } if(url.type!=GIF && url.type!=JPEG && url.type!=PIC && url.type!=TIFF && url.type!=XBM){ werrstr("unknown image type"); goto Err; } if(pipe(pfd)==-1){ werrstr("can't make pipe"); goto Err; } . 24c char fdname[30]; . 21c void storebitmap(Rtext *t, Bitmap *b){ Action *a; a=t->user; t->b=b; free(t->text); t->text=0; free(a->image); if(a->link==0){ free(a); t->user=0; } } void getimage(Rtext *t, Www *w){ . 16,18c [GIF] "fb/gif2pic -mv", [JPEG] "fb/jpg2pic -fast -map /lib/fb/cmap/rgbv", [PIC] "fb/3to1 /lib/fb/cmap/rgbv", [TIFF] "/sys/lib/mothra/tiffcvt", . wq //GO.SYSIN DD VADIM getpix.c sum=`{sum < 836403055/getpix.c} if(~ c26a9dbe2594 $sum(1)^$sum(2)) echo if not{ echo 836403055/getpix.c checksum error creating updated file exit checksum } target=836403055/gopher2html.c echo -n '836403055/gopher2html.c: ' if(! test -f $srcdir/gopher2html.c || ! test -r $srcdir/gopher2html.c){ echo $srcdir/gopher2html.c unreadable exit unreadable } sum=`{sum < $srcdir/gopher2html.c} if(! ~ 5406a40f3554 $sum(1)^$sum(2)){ echo $srcdir/gopher2html.c is not the original distribution file exit original } cp $srcdir/gopher2html.c 836403055/gopher2html.c ed 836403055/gopher2html.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM gopher2html.c' 148a case '4': savefile(name, "Macintosh BINHEX"); break; case '5': savefile(name, "DOS binary"); break; case '6': savefile(name, "uuencoded"); break; case '9': savefile(name, "binary"); break; case 'g': savefile(name, "GIF"); break; case 'I': savefile(name, "some sort of image"); break; . 147d 145c default: errexit("sorry, can't handle %s (type %c)", argv[3]+1, argv[3][0]); . 138a case '7': /* index query */ name=strchr(argv[3], '?'); if(name!=0){ if(name==argv[3]+1){ argv[3][1]=argv[3][0]; argv[3]++; } else *name='\t'; name++; } else name=argv[3]; fprint(ifd, "%s\r\n", argv[3]+1); copydir(name); break; . 129a unescape(argv[3]); . 121a int hexdigit(int c){ if('0'<=c && c<='9') return c-'0'; if('a'<=c && c<='f') return c-'a'+10; if('A'<=c && c<='F') return c-'A'+10; return -1; } void unescape(char *s){ char *t; int hi, lo; t=s; while(*s){ if(*s=='%' && (hi=hexdigit(s[1]))>=0 && (lo=hexdigit(s[2]))>=0){ *t++=hi*16+lo; s+=3; } else *t++=*s++; } *t='\0'; } . 116,118c switch(type){ case '3': print("
  • "); wtext(name, ename); break; case '7': print("
  • ", host, port, type, escape(selector)); wtext(name, ename); break; default: print("
  • ", host, port, type, escape(selector)); wtext(name, ename); print("\n"); break; } . 39a void savefile(char *name, char *type){ int fd, n; char save[30], buf[1024]; for(n=1;;n++){ if(n==100) errexit("can't save binary file %s: %r", name); sprint(save, "gopher.save.%d", n); fd=create(save, OWRITE, 0444); if(fd!=-1) break; } print("%s

    %s

    \n", name); print("Saving %s file %s in %s...\n", type, name, save); while((n=read(ifd, buf, sizeof buf))>0) write(fd, buf, n); close(fd); print("done\n"); } . 19,20d 16a va_list args; va_start(args, s); out = doprint(buf, buf+sizeof(buf), s, args); va_end(args); *out='\0'; . 2c * Reads gopher output from a TCP port, outputs . wq //GO.SYSIN DD VADIM gopher2html.c sum=`{sum < 836403055/gopher2html.c} if(~ 051361175266 $sum(1)^$sum(2)) echo if not{ echo 836403055/gopher2html.c checksum error creating updated file exit checksum } target=836403055/html.h echo -n '836403055/html.h: ' if(! test -f $srcdir/html.h || ! test -r $srcdir/html.h){ echo $srcdir/html.h unreadable exit unreadable } sum=`{sum < $srcdir/html.h} if(! ~ c7362c763945 $sum(1)^$sum(2)){ echo $srcdir/html.h is not the original distribution file exit original } cp $srcdir/html.h 836403055/html.h ed 836403055/html.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM html.h' 163c Entity pl_entity[]; . 109,155c Tag_center=8, Tag_cite=9, Tag_code=10, Tag_dd=11, Tag_dfn=12, Tag_dir=13, Tag_dl=14, Tag_dt=15, Tag_em=16, Tag_font=17, Tag_form=18, Tag_h1=19, Tag_h2=20, Tag_h3=21, Tag_h4=22, Tag_h5=23, Tag_h6=24, Tag_head=25, Tag_hr=26, Tag_html=27, Tag_i=28, Tag_img=29, Tag_input=30, Tag_isindex=31, Tag_kbd=32, Tag_key=33, Tag_li=34, Tag_link=35, Tag_listing=36, Tag_menu=37, Tag_meta=38, Tag_nextid=39, Tag_ol=40, Tag_option=41, Tag_p=42, Tag_plaintext=43, Tag_pre=44, Tag_samp=45, Tag_select=46, Tag_strong=47, Tag_textarea=48, Tag_title=49, Tag_tt=50, Tag_u=51, Tag_ul=52, Tag_var=53, Tag_xmp=54, Tag_end=55, /* also used to indicate unrecognized start tag */ Tag_text=56, . 61d 39a char *tp; /* pointer in text buffer */ . 17a struct Entity{ char *name; Rune value; }; . 13a typedef struct Entity Entity; . wq //GO.SYSIN DD VADIM html.h sum=`{sum < 836403055/html.h} if(~ c1ccea564051 $sum(1)^$sum(2)) echo if not{ echo 836403055/html.h checksum error creating updated file exit checksum } target=836403055/html.syntax.c echo -n '836403055/html.syntax.c: ' if(! test -f $srcdir/html.syntax.c || ! test -r $srcdir/html.syntax.c){ echo $srcdir/html.syntax.c unreadable exit unreadable } sum=`{sum < $srcdir/html.syntax.c} if(! ~ e688d1932692 $sum(1)^$sum(2)){ echo $srcdir/html.syntax.c is not the original distribution file exit original } cp $srcdir/html.syntax.c 836403055/html.syntax.c ed 836403055/html.syntax.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM html.syntax.c' 64,78c Entity pl_entity[]={ "#SPACE", L' ', "#RS", L'\n', "#RE", L'\r', "quot", L'"', "nbsp", L' ', "AElig", L'Æ', "Aacute", L'Á', "Acirc", L'Â', "Agrave", L'À', "Aring", L'Å', "Atilde", L'Ã', "Auml", L'Ä', "Ccedil", L'Ç', "ETH", L'Ð', "Eacute", L'É', "Ecirc", L'Ê', "Egrave", L'È', "Euml", L'Ë', "Iacute", L'Í', "Icirc", L'Î', "Igrave", L'Ì', "Iuml", L'Ï', "Ntilde", L'Ñ', "Oacute", L'Ó', "Ocirc", L'Ô', "Ograve", L'Ò', "Oslash", L'Ø', "Otilde", L'Õ', "Ouml", L'Ö', "THORN", L'Þ', "Uacute", L'Ú', "Ucirc", L'Û', "Ugrave", L'Ù', "Uuml", L'Ü', "Yacute", L'Ý', "aacute", L'á', "acirc", L'â', "aelig", L'æ', "agrave", L'à', "amp", L'&', "aring", L'å', "atilde", L'ã', "auml", L'ä', "ccedil", L'ç', "eacute", L'é', "ecirc", L'ê', "egrave", L'è', "eth", L'ð', "euml", L'ë', "gt", L'>', "iacute", L'í', "icirc", L'î', "igrave", L'ì', "iuml", L'ï', "lt", L'<', "ntilde", L'ñ', "oacute", L'ó', "ocirc", L'ô', "ograve", L'ò', "oslash", L'ø', "otilde", L'õ', "ouml", L'ö', "szlig", L'ß', "thorn", L'þ', "uacute", L'ú', "ucirc", L'û', "ugrave", L'ù', "uuml", L'ü', "yacute", L'ý', "yuml", L'ÿ', "copy", L'©', "reg", L'®', . 24a [Tag_font] "font", END, . 16a [Tag_center] "center", END, . 14c [Tag_blockquot] "blockquote", END, . wq //GO.SYSIN DD VADIM html.syntax.c sum=`{sum < 836403055/html.syntax.c} if(~ 5b4594b32866 $sum(1)^$sum(2)) echo if not{ echo 836403055/html.syntax.c checksum error creating updated file exit checksum } target=836403055/http.c echo -n '836403055/http.c: ' if(! test -f $srcdir/http.c || ! test -r $srcdir/http.c){ echo $srcdir/http.c unreadable exit unreadable } sum=`{sum < $srcdir/http.c} if(! ~ 567f81b23591 $sum(1)^$sum(2)){ echo $srcdir/http.c is not the original distribution file exit original } cp $srcdir/http.c 836403055/http.c ed 836403055/http.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM http.c' 146a else if(cistrcmp(name, "WWW-authenticate")==0){ strncpy(url->authtype, arg, sizeof(url->authtype)); strncpy(url->autharg, arg2, sizeof(url->autharg)); } . 144c url->type|=content2type(arg, url->reltext); . 141a if(*s == ' ' || *s == '\t') arg2 = s+1; else arg2 = s; . 137c while(*name==' ' || *name=='\t') name++; for(s=name;*s!=':';s++) if(*s=='\0') return; . 135c char *name, *arg, *s, *arg2; . 125a if(cache.fd!=-1) close(cache.fd); . 123c if(cache.fd!=-1) write(cache.fd, buf, n); } cacheclose(&cache, 1); . 121c if(cache.fd!=-1) write(cache.fd, bp, ebp-bp); } while((n=read(fd, buf, 1024))>0){ . 119c if(bp!=ebp){ . 117a notify(exitnow); /* otherwise write on closed pipe below may cause havoc */ . 114,116c goto pfdErrReturn; . 110c if(cfd!=-1){ close(cfd); cfd=cacheopen(url, &cache, 1); } if(url->type==0) url->type=suffix2type(url->fullname); if(cache.fd!=-1) fprint(cache.fd, "type %d\n", url->type); . 102,107c if(gotresponse) switch(response){ case 200: /* OK */ case 201: /* Created */ case 202: /* Accepted */ break; case 204: /* No Content */ werrstr("URL has no content"); goto pfdErrReturn; case 301: /* Moved Permanently */ case 302: /* Moved Temporarily */ if(url->redirname[0]){ url->type=FORWARD; werrstr("URL forwarded"); goto pfdErrReturn; } break; case 304: /* Not Modified */ if(cfd!=-1){ url->type=cache.type; close(pfd[0]); close(pfd[1]); close(fd); return cfd; } werrstr("Not modified!"); goto pfdErrReturn; case 400: /* Bad Request */ werrstr("Bad Request to server"); goto pfdErrReturn; case 401: /* Unauthorized */ case 402: /* ??? */ if(*authstr == 0){ close(pfd[0]); close(pfd[1]); close(fd); if(auth(url, authstr, sizeof(authstr)) == 0){ if(cfd!=-1) close(cfd); goto Authorize; } goto ErrReturn; } break; case 403: /* Forbidden */ werrstr("Forbidden by server"); goto pfdErrReturn; case 404: /* Not Found */ werrstr("Not found on server"); goto pfdErrReturn; case 500: /* Internal server error */ werrstr("Server choked"); goto pfdErrReturn; case 501: /* Not implemented */ werrstr("Server can't do it!"); goto pfdErrReturn; case 502: /* Bad gateway */ werrstr("Bad gateway"); goto pfdErrReturn; case 503: /* Service unavailable */ werrstr("Service unavailable"); goto pfdErrReturn; . 90,91d 88c gotresponse=1; . 86c if(gotresponse) httpheader(url, line); else{ . 84c if(nnl==1 && (!gotresponse || (*bp!=' ' && *bp!='\t'))){ . 71c gotresponse=0; . 63a ErrReturn: cacheclose(&cache, 0); . 61,62c if(n==0){ fprint(2, "%s: EOF in header\n", url->fullname); werrstr("EOF in header"); } pfdErrReturn: close(pfd[0]); close(pfd[1]); fdErrReturn: . 54,57c if(pipe(pfd)==-1) goto fdErrReturn; . 49c goto fdErrReturn; . 44,45c "Content-length: %d\r\n" "User-agent: mothra/%s\r\n" "\r\n", urlname, authstr, len, version); . 42c "POST %s HTTP/1.0\r\n%s" . 36c goto fdErrReturn; . 33c cfd=cacheopen(url, &cache, 0); if(cfd==-1) n=sprint(com, "GET %s HTTP/1.0\r\n%s" "Accept: */*\r\n" "User-agent: mothra/%s\r\n" "Host: %s\r\n" "\r\n", urlname, authstr, version, url->ipaddr); else n=sprint(com, "GET %s HTTP/1.0\r\n%s" "If-Modified-since: %s\r\n" "Accept: */*\r\n" "User-agent: mothra/%s\r\n" "Host: %s\r\n" "\r\n", urlname, authstr, rfc1123date(cache.modtime), version, url->ipaddr); . 29,30c if(fd==-1) goto ErrReturn; com=emalloc(strlen(urlname)+300); cache.fd=-1; . 25,26c Cache cache; int cfd; static int getproxy=1; if(getproxy){ proxyserver=getenv("httpproxy"); getproxy=0; } *authstr = 0; Authorize: cfd=-1; if(proxyserver && proxyserver[0]!='\0'){ addr=strdup(proxyserver); urlname=url->fullname; } else{ addr=emalloc(strlen(url->ipaddr)+100); sprint(addr, "tcp!%s!%d", url->ipaddr, url->port); urlname=url->reltext; } . 23c char authstr[128], *urlname; int gotresponse; . 9a * Returns fd of cached file, if found (else -1) * Fills in Cache data structure for caller * If stale is set, caller has determined that the existing * cache entry for this url is stale, so we shouldn't bother re-examining it. */ int cacheopen(Url *url, Cache *c, int stale){ #ifdef CacheEnabled int fd, n; char name[513], *s, *l; /* * If we're using a proxy server or the url contains a ? or =, * don't even bother. */ if(proxyserver || strchr(url->reltext, '?')!=0 || strchr(url->reltext, '=')!=0){ c->fd=-1; return -1; } c->hash=0; for(s=url->fullname,n=0;*s;s++,n++) c->hash=c->hash*n+(*s&255); if(stale) fd=-1; else{ hashname(name, "cache", c); fd=open(name, OREAD); } if(fd==-1){ hashname(name, "write", c); c->fd=create(name, OWRITE, 0444); if(c->fd!=-1) fprint(c->fd, "%s %10ld\n", url->fullname, time(0)); return -1; } c->fd=-1; for(l=name;l!=&name[512];l+=n){ n=&name[512]-l; n=read(fd, l, n); if(n<=0) break; } *l='\0'; s=strchr(name, ' '); if(s==0){ close(fd); return -1; } *s='\0'; if(strcmp(url->fullname, name)!=0){ close(fd); return -1; } c->modtime=atol(++s); s=strchr(s, '\n'); if(s==0){ close(fd); return -1; } s++; if(strncmp(s, "type ", 5)!=0){ close(fd); return -1; } c->type=atoi(s+5); s=strchr(s+5, '\n'); if(s==0){ close(fd); return -1; } seek(fd, s-name+1, 0); return fd; #else c->fd=-1; return -1; #endif } /* * Close url->fd and either rename the cache file or * remove it, depending on success */ void cacheclose(Cache *c, int success){ char wname[513], cname[513], *celem; Dir wdir, cdir; if(c->fd==-1) return; close(c->fd); hashname(wname, "write", c); if(!success){ remove(wname); return; } if(dirstat(wname, &wdir)==-1) return; hashname(cname, "cache", c); if(dirstat(cname, &cdir)==0){ if(remove(cname)==-1){ remove(wname); return; } /* * This looks implausible, but it's what the mv command does */ do; while(remove(cname)!=-1); } celem=strrchr(cname, '/'); if(celem==0) celem=cname; else celem++; strcpy(wdir.name, celem); if(dirwstat(wname, &wdir)==-1) remove(wname); } static char *wkday[]={ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static char *month[]={ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /* * Sun, 06 Nov 1994 08:49:38 GMT * 123456789 123456789 123456789 */ char *rfc1123date(long time){ static char buf[50]; Tm *t; t=gmtime(time); sprint(buf, "%s, %2.2d %s %4.4d %2.2d:%2.2d:%2.2d GMT", wkday[t->wday], t->mday, month[t->mon], t->year+1900, t->hour, t->min, t->sec); return buf; } /* . 8a static char *proxyserver; /* name of proxy server */ void exitnow(void*, char*){ noted(NDFLT); } void hashname(char *name, char *stem, Cache *c){ sprint(name, "/sys/lib/mothra/cache/%s.%.8lux", stem, c->hash); } #define CacheEnabled . 6a typedef struct Cache Cache; struct Cache{ int fd; /* file descriptor on which to write cached data */ ulong hash; /* hash of url, used to compute cache file name */ int modtime; /* time at which cache entry was created */ int type; /* url->type of cached entry */ }; . wq //GO.SYSIN DD VADIM http.c sum=`{sum < 836403055/http.c} if(~ 55600b389586 $sum(1)^$sum(2)) echo if not{ echo 836403055/http.c checksum error creating updated file exit checksum } target=836403055/malloc.c echo -n '836403055/malloc.c: ' if(! test -f $srcdir/malloc.c || ! test -r $srcdir/malloc.c){ echo $srcdir/malloc.c unreadable exit unreadable } sum=`{sum < $srcdir/malloc.c} if(! ~ f264689b2796 $sum(1)^$sum(2)){ echo $srcdir/malloc.c is not the original distribution file exit original } cp $srcdir/malloc.c 836403055/malloc.c ed 836403055/malloc.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM malloc.c' 113a #endif . 93a static int first=1; char buf[1]; if(first){ first=0; if(pipe(lockpipe)==-1){ fprint(2, "malloc: can't make lock pipe: %r\n"); exits("no lock"); } munlock(); } read(lockpipe[1], buf, 1); } #else /* * Old lock code using rendezvous. The gatekeeping process often * doesn't get killed on exit, especially on Brazil. */ void mlock(void){ . 92a #ifdef PIPELOCK /* * lockpipe is a pipe that holds a byte when the lock is not set * mlock reads the byte to set the lock. * munlock writes a byte to unset the lock. */ int lockpipe[2]; void munlock(void){ write(lockpipe[0], "l", 1); } . 34d 5a #define PIPELOCK . wq //GO.SYSIN DD VADIM malloc.c sum=`{sum < 836403055/malloc.c} if(~ 2fa340e43394 $sum(1)^$sum(2)) echo if not{ echo 836403055/malloc.c checksum error creating updated file exit checksum } target=836403055/mkfile echo -n '836403055/mkfile: ' if(! test -f $srcdir/mkfile || ! test -r $srcdir/mkfile){ echo $srcdir/mkfile unreadable exit unreadable } sum=`{sum < $srcdir/mkfile} if(! ~ cb4e2472588 $sum(1)^$sum(2)){ echo $srcdir/mkfile is not the original distribution file exit original } cp $srcdir/mkfile 836403055/mkfile ed 836403055/mkfile >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mkfile' 25,37d 21a CFLAGS=-Dplan9 version.c: $CFILES date|sed 's/^... //;s/ +/-/g;s/.*/char version[]="&";/' >version.c . 17,18c OFILES=${CFILES:%.c=%.$O} version.$O HFILES=mothra.h html.h rtext.h . 15a auth.c \ . 8a ftp.c \ . 7a floyd.c \ . 6a file.c \ . 4c CFILES= \ . wq //GO.SYSIN DD VADIM mkfile sum=`{sum < 836403055/mkfile} if(~ 7b845186473 $sum(1)^$sum(2)) echo if not{ echo 836403055/mkfile checksum error creating updated file exit checksum } target=836403055/mothra.c echo -n '836403055/mothra.c: ' if(! test -f $srcdir/mothra.c || ! test -r $srcdir/mothra.c){ echo $srcdir/mothra.c unreadable exit unreadable } sum=`{sum < $srcdir/mothra.c} if(! ~ 8e01901518625 $sum(1)^$sum(2)){ echo $srcdir/mothra.c is not the original distribution file exit original } cp $srcdir/mothra.c 836403055/mothra.c ed 836403055/mothra.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mothra.c' 816,819c case 7: . 813,814c sprint(name, "file:%s/lib/mothra/hit.html", home); geturl(name, GET, 0, 1, 0); . 807c case 6: . 799,800c fprint(fd, "Hit List\n"); fprint(fd, "

    Hit list

    \n"); . 791c sprint(name, "%s/lib/mothra/hit.html", home); . 785a swap=root; root=alt; alt=swap; current->yoffs=plgetpostextview(text); swap=text; text=alttext; alttext=swap; defdisplay=!defdisplay; plpack(root, screen.r); plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink); plsetpostextview(text, current->yoffs); pldraw(root, &screen); break; case 1: snarf(cmd); break; case 2: paste(cmd); break; case 3: inlinepix=!inlinepix; break; case 4: if(screen.ldepth==3) wrcolmap(&screen, map); break; case 5: . 780a Panel *swap; . 778a void snarf(Panel *p){ int fd; fd=create("/dev/snarf", OWRITE, 0666); if(fd>=0){ fprint(fd, "%s", selection->fullname); close(fd); } } void paste(Panel *p){ char buf[1024]; int n, len, fd; fd=open("/dev/snarf", OREAD); strcpy(buf, plentryval(p)); len=strlen(buf); n=read(fd, buf+len, 1023-len); if(n>0){ buf[len+n]='\0'; plinitentry(cmd, PACKE|EXPAND, 0, buf, docmd); pldraw(cmd, &screen); } close(fd); } . 756c plsetpostextview(text, w->yoffs); . 751,754c w->yoffs=plgetpostextview(text); . 733a case PDF: filter("/sys/lib/mothra/stdinleaf", fd); break; . 732c filter("fb/xbm2pic|fb/9v", fd); . 730a case TIFF: filter("/sys/lib/mothra/tiffview", fd); break; . 729c filter("fb/jpg2pic|fb/9v", fd); . 727c filter("fb/jpg2pic -fast -map /lib/fb/cmap/rgbv|fb/9v", fd); . 723c filter("fb/gif2pic -mv|fb/9v", fd); . 720c filter("/sys/lib/mothra/stdinpage", fd); . 716c if(defdisplay) pldraw(list, &screen); . 713c gettext(&www[nwww], fd, selection->type&~COMPRESSION); . 711c if(selection->map){ if(current && current->base) /* always succeeds */ www[nwww].url=copyurl(current->base); else{ fprint(2, "no base for map!\n"); www[nwww].url=copyurl(selection); } } else www[nwww].url=copyurl(selection); . 705c if(selection->type&COMPRESS) fd=uncompress("/bin/uncompress", fd); else if(selection->type&GUNZIP) fd=uncompress("/bin/pub/gunzip", fd); switch(selection->type&~COMPRESSION){ . 694,699d 685,686c if(body){ /* * Undocumented Mozilla feature */ pipe(pfd); switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ case -1: message("Can't fork!"); break; case 0: close(0); bclose(); dup(pfd[1], 0); close(pfd[1]); close(pfd[0]); execl("/bin/upas/sendmail", "sendmail", selection->reltext, 0); message("Can't exec sendmail"); _exits(0); default: close(pfd[1]); fprint(pfd[0], "Content-type: application/x-www-form-urlencoded\n" "Subject: Form posted from Mothra\n" "\n" "%s\n", body); close(pfd[0]); break; } } else{ sprint(cmd, "mail %s", selection->reltext); popwin(cmd); } . 665a selection->map=map; . 664a int pfd[2]; . 662c void geturl(char *urlname, int method, char *body, int cache, int map){ . 651c showsel(selection->fullname); . 647c if(current){ cur=current->base; /* * I believe that the following test should never succeed */ if(cur==0){ cur=current->url; if(cur==0){ fprint(2, "bad base & url, current %d, getting %s\n", current-www, urlname); cur=&defurl; } else fprint(2, "bad base, current %s, getting %s\n", current->url->fullname, urlname); } } . 588c fd=open(url->reltext, OREAD); if(fd!=-1){ dirfstat(fd, &dir); if(dir.mode&CHDIR){ url->type=HTML; return dir2html(url->reltext, fd); } } return fd; . 582a /* * I'm not convinced that the following two lines are right, * but once I got a redir loop because they were missing. */ method=GET; body=0; . 576,577c url->type = suffix2type(url->reltext); return ftp(url); . 568,569d 560a Dir dir; . 507,553d 473d 467c execl("/bin/rc", "rc", "-c", cmd, 0); . 453,456c void filter(char *cmd, int fd){ . 450c hiturl(buttons, a->link, 0); . 446,447c sprint(mapurl, "%s?%d,%d", a->link, coord.x, coord.y+yoffs); hiturl(buttons, mapurl, 1); . 444c yoffs=plgetpostextview(p); . 439c int yoffs; . 432,433d 426c switch(buttons){ case 1: setcurrent(i, 0); /* no break ... */ case 2: selurl(www[i].url->fullname); break; case 4: message("Button 3 hit on page can't happen!"); break; } . 413c case 1: geturl(url, GET, 0, 1, map); break; . 410c void hiturl(int buttons, char *url, int map){ . 408c if(defdisplay) pldraw(cmd, &screen); . 398,399c if(selection){ s=strrchr(selection->fullname, '/'); if(s) s++; } if(s==0 || *s=='\0'){ message("Usage: s file"); break; } . 394a case 'r': s = arg(s); if(*s == '\0') s = selection ? selection->fullname : helpfile; geturl(s, GET, 0, 0, 0); break; case 'W': s=arg(s); if(s=='\0'){ message("Usage: W file"); break; } screendump(s, 1); break; case 'w': s=arg(s); if(s=='\0'){ message("Usage: w file"); break; } screendump(s, 0); break; . 392,393c if(*s=='\0'){ if(selection) geturl(selection->fullname, GET, 0, 1, 0); else message("no url selected"); } else geturl(s, GET, 0, 1, 0); . 388c geturl(helpfile, GET, 0, 1, 0); . 382c /* * Non-command does a get on the url */ if(s[0]!='\0' && s[1]!='\0' && s[1]!=' ') geturl(s, GET, 0, 1, 0); else switch(s[0]){ . 375a void screendump(char *name, int full){ Bitmap *b; int fd; Rectangle r; fd=create(name, OWRITE, 0666); if(fd==-1){ message("can't create %s", name); return; } if(full) r=screen.clipr; else r=text->r; b=balloc(rsubp(r, r.min), screen.ldepth); if(b){ bitblt(b, b->r.min, &screen, r, S); wrbitmapfile(fd, b); bfree(b); } else wrbitmapfile(fd, &screen); close(fd); } . 370c if(n==-1) fprint(2, "save: %s: %r\n", url->fullname); . 368c while((n=read(ifd, buf, 4096))>0) . 363c while((n=read(ifd, buf, 4096))>0) . 359c switch(rfork(RFNOTEG|RFFDG|RFPROC|RFNOWAIT)){ . 356c message("save: %s: %r", selection->fullname); . 349c message("save: %s: %r", name); . 347c ofd=create(name, OWRITE, 0666); . 335c if(defdisplay) pldraw(list, &screen); . 328,330c plsetpostextview(text, current->yoffs); . 323c current->yoffs=tp->topy; . 317c if(defdisplay) pldraw(cururl, &screen); . 315c if(defdisplay) pldraw(curttl, &screen); . 312c current->yoffs=plgetpostextview(text); . 301c * get the document, scroll to the given tag . 293c for(i=1;i!=nwww;i++) if(index==www[i].index){ sprint(buf, "%2d %s", i, www[i].title); return buf; } . 291a static char buf[1024]; . 263,266c va_list args; if(verbose){ va_start(args, m); out=buf+sprint(buf, "%s: line %d: ", name, line); out=doprint(out, buf+sizeof(buf)-1, m, args); va_end(args); *out='\0'; fprint(2, "%s\n", buf); } . 259a void showsel(char *s){ static char buf[1024]; char *out; sprint(buf, "selection: %s", s); plinitlabel(selbox, PACKN|FILLX, buf); if(defdisplay) pldraw(selbox, &screen); } . 258c if(defdisplay) pldraw(msg, &screen); . 255c va_list args; va_start(args, s); out = doprint(buf, buf+sizeof(buf), s, args); va_end(args); . 246d 241a adjkb(); . 223c geturl(url, GET, 0, 1, 0); . 217a www[0].base=&badurl; . 213a linespace=balloc(Rect(0, 0, 2048, 5), screen.ldepth); if(linespace==0){ fprint(2, "%s: can't balloc!\n", argv[0]); exits("no mem"); } . 208c hrule=balloc(Rect(0, 0, 2048, 5), screen.ldepth); . 206a if(debug) notify(dienow); . 203c pltabsize(chrwidth, 8*chrwidth); if(getmap("/lib/fb/cmap/rgbv") && screen.ldepth==3) wrcolmap(&screen, map); . 197,200c logfile=mkmfile("mothra.log", 0666|CHAPPEND); . 184,192c errfile=mkmfile("mothra.err", 0666); . 182c case 1: url=argv[0]; break; . 177c case 0: . 175c Usage: fprint(2, "Usage: %s [-d] [url]\n", argv[0]); . 171c rfork(RFNOTEG|RFNAMEG|RFREND); . 166a ARGBEGIN{ case 'd': debug++; break; case 'i': inlinepix=0; break; case 'v': verbose=1; break; default: goto Usage; }ARGEND . 164,165d 160a int mkmfile(char *stem, int mode){ char *henv; char filename[512]; int f; Dir dir; if(home[0]=='\0'){ henv=getenv("home"); if(henv){ sprint(home, "%s/lib", henv); f=create(home, OREAD, CHDIR|0777); if(f!=-1) close(f); sprint(home, "%s/lib/mothra", henv); f=create(home, OREAD, CHDIR|0777); if(f!=-1) close(f); } else strcpy(home, "/tmp"); } sprint(filename, "%s/%s", home, stem); f=create(filename, OWRITE, mode); if(f==-1) f=create(stem, OWRITE, mode); /* * mode-correction Greek * should remove this code after it fixes the mode of everybody's mothra.log */ if(f!=-1 && mode&CHAPPEND){ dirfstat(f, &dir); if((dir.mode&CHAPPEND)==0){ dir.mode|=CHAPPEND; dirfwstat(f, &dir); } } return f; } . 148d 137d 135d 123a alt=plpopup(0, PACKE|EXPAND, 0, 0, menu3); bar=plscrollbar(alt, PACKW); alttext=pltextview(alt, PACKE|EXPAND, Pt(0, 0), 0, dolink); plscroll(alttext, 0, bar); . 120,121c text=pltextview(p, PACKE|EXPAND, Pt(0, 0), 0, dolink); . 114c p=plgroup(root, PACKN|FILLX); . 110c p=plgroup(root, PACKN|FILLX); . 107,108c list=pllist(p, PACKN|FILLX, genwww, 8, doprev); . 104c cmd=plentry(p, PACKN|FILLX, 0, "", docmd); . 102a selbox=pllabel(p, PACKN|FILLX, ""); plplacelabel(selbox, PLACEW); . 99,100c root=plpopup(root, EXPAND, 0, 0, menu3); p=plgroup(root, PACKN|FILLX); . 97c Panel *p, *bar; . 95a int subpanel(Panel *obj, Panel *subj){ if(obj==0) return 0; if(obj==subj) return 1; for(obj=obj->child;obj;obj=obj->next) if(subpanel(obj, subj)) return 1; return 0; } /* * Make sure that the keyboard focus is on-screen, by adjusting it to * be the cmd entry if necessary. */ void adjkb(void){ Rtext *t; int yoffs; extern Panel *pl_kbfocus; /* this is a secret panel library name */ yoffs=text->r.min.y-plgetpostextview(text); for(t=current->text;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){ if(t->r.max.y+yoffs>text->r.max.y) break; if(t->r.min.y+yoffs>=text->r.min.y && t->b==0 && subpanel(t->p, pl_kbfocus)) return; } plgrabkb(cmd); } . 88a "save hit", "hit list", . 86,87c "alt display", "snarf url", "paste", "inline pix", . 63,71c -10, -3, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xF0, 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x07, 0xE0, 0x01, 0xE0, 0x03, 0xE0, 0x07, 0x60, 0x0E, 0x60, 0x1C, 0x00, 0x38, 0x00, 0x71, 0xB6, 0x61, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, . 17a char helpfile[] = "file:/sys/lib/mothra/help.html"; . 15a Panel *selbox; /* show selection here */ Panel *menu3; /* button 3 menu */ . 10a Panel *alt; /* the alternate display */ Panel *alttext; /* the alternate text window */ . 9a #include "rtext.h" int verbose=0; /* -v flag causes html errors to appear in error log */ int inlinepix=1; /* get inline pix, by default */ int defdisplay=1; /* is the default (initial) display visible? */ . wq //GO.SYSIN DD VADIM mothra.c sum=`{sum < 836403055/mothra.c} if(~ 965e5d0b23320 $sum(1)^$sum(2)) echo if not{ echo 836403055/mothra.c checksum error creating updated file exit checksum } target=836403055/mothra.h echo -n '836403055/mothra.h: ' if(! test -f $srcdir/mothra.h || ! test -r $srcdir/mothra.h){ echo $srcdir/mothra.h unreadable exit unreadable } sum=`{sum < $srcdir/mothra.h} if(! ~ b56480082349 $sum(1)^$sum(2)){ echo $srcdir/mothra.h is not the original distribution file exit original } cp $srcdir/mothra.h 836403055/mothra.h ed 836403055/mothra.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM mothra.h' 99c void geturl(char *, int, char *, int, int); int dir2html(char *, int); Bitmap *floyd(Rectangle, int, uchar *); int auth(Url*, char*, int); uchar cmap[256*3]; RGB map[256]; char version[]; #ifndef brazil # define RFREND 0 #endif #ifndef nil #define nil 0 #endif . 96c int content2type(char *, char *); . 90a int ftp(Url *); . 75a int debug; /* command line flag */ int inlinepix; /* flag set if you want to fetch inline images */ . 72c /* * authentication types */ #define ANONE 0 #define ABASIC 1 Bitmap *hrule, *bullet, *linespace; . 54,58c #define TIFF 5 #define AUDIO 6 #define PLAIN 7 #define XBM 8 #define POSTSCRIPT 9 #define FORWARD 10 #define PDF 11 #define SUFFIX 12 . 48a * Changing these in a non-downward compatible way spoils cache entries . 41c int yoffs; . 38a Url *base; . 35c int map; /* is this an image map? */ . 31a char autharg[NAUTH]; char authtype[NTITLE]; . 2c #define NNAME 512 #define NAUTH 128 . wq //GO.SYSIN DD VADIM mothra.h sum=`{sum < 836403055/mothra.h} if(~ 69669bcd2947 $sum(1)^$sum(2)) echo if not{ echo 836403055/mothra.h checksum error creating updated file exit checksum } target=836403055/rdhtml.c echo -n '836403055/rdhtml.c: ' if(! test -f $srcdir/rdhtml.c || ! test -r $srcdir/rdhtml.c){ echo $srcdir/rdhtml.c unreadable exit unreadable } sum=`{sum < $srcdir/rdhtml.c} if(! ~ 1bdb0cad16676 $sum(1)^$sum(2)){ echo $srcdir/rdhtml.c is not the original distribution file exit original } cp $srcdir/rdhtml.c 836403055/rdhtml.c ed 836403055/rdhtml.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM rdhtml.c' 780a break; case Tag_pre: pl_linespace(&g); . 775d 708a g.text=dst->title+strlen(dst->title); g.tp=g.text; g.etext=dst->title+NTITLE-1; /* if(g.text>g.etext) g.text=g.etext; /* superfluous? */ . 702a pl_linespace(&g); . 699a g.state->indent=0; . 599a case Tag_font: /* more to come */ break; . 596a g.state->indent=-40; . 591,592c g.state->margin+=40; . 579a g.state->indent=0; . 569a case Tag_center: /* more to come */ break; . 551a case Tag_base: str=pl_getattr(g.attr, "href"); if(str){ dst->base=emalloc(sizeof(Url)); crackurl(dst->base, str, dst->url); } break; . 478a dst->title[0]='\0'; dst->base=dst->url; . 415a g->linebrk=1; . 411c if(c=='\t'){ do *lp++=' '; while(lp!=elp && (lp-line)%8!=0); } else if(c!='\n') . 407a g->linebrk=1; . 400d 352c } . 348c while(c=='\t'){ if(tokp!=&g->token[NTOKEN-1]) *tokp++=c; c=pl_nextc(g); } while(c!='\t' && c!='\n' && c!=STAG && c!=EOF){ . 295a pl_dnl(ap->value); . 284c s=pl_white(t+1); . 279c t=pl_white(s); . 272c s=pl_white(s); . 248a g->tag=Tag_end; . 244a void pl_dnl(char *s){ char *t; for(t=s;*s;s++) if(*s!='\r' && *s!='\n') *t++=*s; *t='\0'; } . 225c char *pl_white(char *s){ . 223c * Skip over white space . 216d 202,214c htmlerror(g->name, g->lineno, "unknown entity %s", u); s[-1]=svc; s=u; *t++='&'; . 194,199c for(ep=pl_entity;ep->name;ep++) if(strcmp(ep->name, u)==0) break; if(ep->name){ *t++=ep->value; if(svc!=';') *--s=svc; . 190,191c *s++='\0'; if(*u=='#' && '0'<=u[1] && u[1]<='9'){ r=atoi(u+1); if(r==0xa0) *t++=' '; else *t++=r; if(svc!=';') *--s=svc; . 188c svc=*s; if(svc!=';') . 175,177c char *t, *u, c, svc; Entity *ep; . 139a /* * Read a character, translating \r\n, \n\r, \r and \n into \n */ int pl_readc(Hglob *g){ int c; static int peek=-1; if(peek!=-1){ c=peek; peek=-1; } else c=pl_bread(g); if(c=='\r'){ c=pl_bread(g); if(c!='\n') peek=c; return '\n'; } if(c=='\n'){ c=pl_bread(g); if(c!='\r') peek=c; return '\n'; } return c; } . 135,136c g->hbufp=g->hbuf; g->ehbuf=g->hbuf+n; } c=*g->hbufp++&255; . 130,133c g->heof=1; return EOF; . 117,128c if(g->hbufp==g->ehbuf){ n=read(g->hfd, g->hbuf, NHBUF); if(n<=0){ if(n<0){ sprint(err, "%r reading %s", g->name); pl_htmloutput(g, 1, err, 0); . 114c /* * Buffered read, no translation * Save in cache. */ int pl_bread(Hglob *g){ . 109c if(space<0) space=0; if(indent<0) indent=0; if(g->state->pre && s[0]=='\t'){ space=0; while(s[0]=='\t'){ space++; s++; } space=PL_TAB|space; if(g->linebrk){ indent=space; space=1000000; } } plrtstr(&g->dst->text, space, indent, f->font, latin2utf(s), g->state->link!=0, ap); . 81a *g->tp='\0'; . 66c plrtbitmap(&g->dst->text, 1000000, 0, linespace, 0, 0); . 55a /* * html is in latin1 but the panel library uses utf */ char *latin2utf(char *latin){ int nutf; char *l, *u, *utf; Rune r; nutf=1; /* 1 for the nul */ for(l=latin;*l;l++) nutf+=runelen(*l&255); utf=emalloc(nutf); u=utf; for(l=latin;*l;l++){ r=*l&255; u+=runetochar(u, &r); } *u='\0'; return utf; } . 11a #include "rtext.h" . 1,5d wq //GO.SYSIN DD VADIM rdhtml.c sum=`{sum < 836403055/rdhtml.c} if(~ 984bcad418183 $sum(1)^$sum(2)) echo if not{ echo 836403055/rdhtml.c checksum error creating updated file exit checksum } target=836403055/auth.c echo -n '836403055/auth.c (new): ' cat > 836403055/auth.c >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' #include #include #include #include #include #include #include "mothra.h" char base64[64]={ "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" "ghijklmn" "opqrstuv" "wxyz0123" "456789+/" }; #define PAD64 '=' void enc64(char *out, char *in){ int b24; while(in[0]!='\0' && in[1]!='\0' && in[2]!='\0'){ b24=((in[0]&255)<<16)|((in[1]&255)<<8)|(in[2]&255); *out++=base64[(b24>>18)&63]; *out++=base64[(b24>>12)&63]; *out++=base64[(b24>> 6)&63]; *out++=base64[ b24 &63]; in+=3; } if(in[0]!='\0'){ b24=(in[0]&255)<<16; *out++=base64[(b24>>18)&63]; if(in[1]=='\0'){ *out++=base64[(b24>>12)&63]; *out++=PAD64; } else{ b24|=(in[1]&255)<<8; *out++=base64[(b24>>12)&63]; *out++=base64[(b24>> 6)&63]; } *out++=PAD64; } *out='\0'; } static int basicauth(char *arg, char *str, int n) { int i; char *p; char buf[1024]; Biobuf *b; if(strncmp(arg, "realm=", 6) == 0) arg += 6; if(*arg == '"'){ arg++; for(p = arg; *p && *p != '"'; p++); *p = 0; } else { for(p = arg; *p && *p != ' ' && *p != '\t'; p++); *p = 0; } p = getenv("home"); if(p == 0){ werrstr("$home not set"); return -1; } snprint(buf, sizeof(buf), "%s/lib/mothra/insecurity", p); b = Bopen(buf, OREAD); if(b == 0){ werrstr("www password file %s: %r", buf); return -1; } i = strlen(arg); while(p = Brdline(b, '\n')) if(strncmp(arg, p, i) == 0 && p[i] == '\t') break; if(p == 0){ Bterm(b); werrstr("no basic password for domain `%s'", arg); return -1; } p[Blinelen(b)-1] = 0; for(p += i; *p == '\t'; p++); if(strlen(p) > 3*sizeof(buf)/4){ Bterm(b); werrstr("password too long: %s", p); return -1; } enc64(buf, p); snprint(str, n, "Authorization: Basic %s\r\n", buf); return 0; } int auth(Url *url, char *str, int n) { if(cistrcmp(url->authtype, "basic") == 0) return basicauth(url->autharg, str, n); werrstr("unknown auth method %s", url->authtype); return -1; } //GO.SYSIN DD VADIM /sys/src/cmd/mothra sum=`{sum < 836403055/auth.c} if(~ 94a1ac181981 $sum(1)^$sum(2)) echo if not{ echo 836403055/auth.c checksum error extracting new file exit checksum } target=836403055/file.c echo -n '836403055/file.c (new): ' cat > 836403055/file.c >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' #include #include #include #include #include #include "mothra.h" /* * fd is the result of a successful open(name, OREAD), * where name is the name of a directory. We convert * this into an html page containing links to the files * in the directory. */ int dir2html(char *name, int fd){ int p[2], first; Dir dir; if(pipe(p)==-1){ close(fd); return -1; } switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ case -1: close(fd); return -1; case 0: close(p[1]); fprint(p[0], "\n"); fprint(p[0], "Directory %s\n", name); fprint(p[0], "\n"); fprint(p[0], "\n"); fprint(p[0], "

    %s

    \n", name); fprint(p[0], "
      \n"); first=1; while(dirread(fd, &dir, DIRLEN)==DIRLEN) fprint(p[0], "
    • %s%s\n", name, dir.name, dir.name, dir.mode&CHDIR?"/":""); fprint(p[0], "
    \n"); fprint(p[0], "\n"); _exits(0); default: close(fd); close(p[0]); return p[1]; } } //GO.SYSIN DD VADIM /sys/src/cmd/mothra sum=`{sum < 836403055/file.c} if(~ 0d93d79b999 $sum(1)^$sum(2)) echo if not{ echo 836403055/file.c checksum error extracting new file exit checksum } target=836403055/floyd.c echo -n '836403055/floyd.c (new): ' cat > 836403055/floyd.c >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' #include #include #include #include #include #include "mothra.h" #define NBIT 8 /* bits per uchar, a source of non-portability */ /* * Copy an 8 bit image into a newly allocated bitmap, using Floyd-Steinberg * if ldepth!=3 */ Bitmap *floyd(Rectangle r, int ldepth, uchar *pixels){ int wid=r.max.x-r.min.x; int hgt=r.max.y-r.min.y; int w=1< 836403055/ftp.c >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' #include #include #include #include #include #include #include #include #include #include "mothra.h" enum { /* return codes */ Extra= 1, Success= 2, Incomplete= 3, TempFail= 4, PermFail= 5, Nnetdir= 3*NAMELEN, /* max length of network directory paths */ Ndialstr= 64, /* max length of dial strings */ }; typedef struct Ftp Ftp; struct Ftp { char net[Nnetdir]; Biobuf *ftpctl; Url *u; }; static int ftpdebug; /* * read from biobuf turning cr/nl into nl */ char* getcrnl(Biobuf *b) { char *p, *ep; p = Brdline(b, '\n'); if(p == nil) return nil; ep = p + Blinelen(b) - 1; if(*(ep-1) == '\r') ep--; *ep = 0; return p; } char* readfile(char *file, char *buf, int len) { int n, fd; fd = open(file, OREAD); if(fd < 0) return nil; n = read(fd, buf, len-1); close(fd); if(n <= 0) return nil; buf[n] = 0; return buf; } char* sysname(void) { static char sys[Ndbvlen]; char *p; p = readfile("/dev/sysname", sys, sizeof(sys)); if(p == nil) return "unknown"; return p; } char* domainname(void) { static char domain[Ndbvlen]; Ndbtuple *t; if(*domain) return domain; t = csgetval(0, "sys", sysname(), "dom", domain); if(t){ ndbfree(t); return domain; } else return sysname(); } static int sendrequest(Biobuf *b, char *fmt, ...) { char buf[2*1024], *s; va_list args; va_start(args, fmt); s = doprint(buf, buf + (sizeof(buf)-4) / sizeof(*buf), fmt, args); va_end(args); *s++ = '\r'; *s++ = '\n'; if(write(Bfildes(b), buf, s - buf) != s - buf) return -1; if(ftpdebug) write(2, buf, s - buf); return 0; } static int getreply(Biobuf *b, char *msg, int len) { char *line; int rv; int i, n; while(line = getcrnl(b)){ /* add line to message buffer, strip off \r */ n = Blinelen(b); if(ftpdebug) write(2, line, n); if(n > len - 1) i = len - 1; else i = n; if(i > 0){ memmove(msg, line, i); msg += i; len -= i; *msg = 0; } /* stop if not a continuation */ rv = atoi(line); if(rv >= 100 && rv < 600 && (n == 4 || (n > 4 && line[3] == ' '))) return rv/100; } return -1; } int terminateftp(Ftp *d) { if(d->ftpctl){ close(Bfildes(d->ftpctl)); Bterm(d->ftpctl); free(d->ftpctl); d->ftpctl = nil; } free(d); return -1; } Biobuf* hello(Ftp *d) { int fd; char *p; Biobuf *b; char msg[1024]; char ndir[Nnetdir]; snprint(msg, sizeof msg, "tcp!%s!%d", d->u->ipaddr, d->u->port); fd = dial(msg, 0, ndir, 0); if(fd < 0){ d->ftpctl = nil; return nil; } b = emalloc(sizeof(Biobuf)); Binit(b, fd, OREAD); d->ftpctl = b; /* remember network for the data connections */ p = strrchr(ndir, '/'); if(p == 0){ fprint(2, "dial is out of date\n"); return nil; } *p = 0; strcpy(d->net, ndir); /* wait for hello from other side */ if(getreply(b, msg, sizeof(msg)) != Success){ fprint(2, "instead of hello: %s\n", msg); return nil; } return b; } int logon(Ftp *d) { char msg[1024]; /* login anonymous */ sendrequest(d->ftpctl, "USER anonymous"); switch(getreply(d->ftpctl, msg, sizeof(msg))){ case Success: return 0; case Incomplete: break; /* need password */ default: fprint(2, "login failed: %s\n", msg); werrstr(msg); return -1; } /* send user id as password */ sprint(msg, "%s@", getuser()); sendrequest(d->ftpctl, "PASS %s", msg); if(getreply(d->ftpctl, msg, sizeof(msg)) != Success){ fprint(2, "login failed: %s\n", msg); werrstr(msg); return -1; } return 0; } int xfertype(Ftp *d, char *t) { char msg[1024]; sendrequest(d->ftpctl, "TYPE %s", t); if(getreply(d->ftpctl, msg, sizeof(msg)) != Success){ fprint(2, "can't set type %s: %s\n", t, msg); werrstr(msg); return -1; } return 0; } int passive(Ftp *d) { char msg[1024]; char dialstr[Ndialstr]; char *f[6]; char *p; int fd; sendrequest(d->ftpctl, "PASV"); if(getreply(d->ftpctl, msg, sizeof(msg)) != Success) return -1; /* get address and port number from reply, this is AI */ p = strchr(msg, '('); if(p == nil){ for(p = msg+3; *p; p++) if(isdigit(*p)) break; } else p++; setfields(","); if(getfields(p, f, 6) < 6){ fprint(2, "passive mode protocol botch: %s\n", msg); werrstr("ftp protocol botch"); return -1; } snprint(dialstr, sizeof(dialstr), "%s!%s.%s.%s.%s!%d", d->net, f[0], f[1], f[2], f[3], ((atoi(f[4])&0xff)<<8) + (atoi(f[5])&0xff)); /* open data connection */ fd = dial(dialstr, 0, 0, 0); if(fd < 0){ fprint(2, "passive mode connect to %s failed: %r\n", dialstr); return -1; } /* tell remote to send a file */ sendrequest(d->ftpctl, "RETR %s", d->u->reltext); if(getreply(d->ftpctl, msg, sizeof(msg)) != Extra){ fprint(2, "passive mode retrieve failed: %s\n", msg); werrstr(msg); return -1; } return fd; } int active(Ftp *d) { char msg[1024]; char buf[Ndialstr]; char netdir[Nnetdir]; char newdir[Nnetdir]; uchar ipaddr[4]; int dfd, cfd, listenfd; char *p; int port; /* get a channel to listen on, let kernel pick the port number */ sprint(buf, "%s!*!0", d->net); listenfd = announce(buf, netdir); if(listenfd < 0){ fprint(2, "can't listen for ftp callback: %r\n", buf); return -1; } /* get the local address and port number */ sprint(newdir, "%s/local", netdir); readfile(newdir, buf, sizeof buf); p = strchr(buf, '!')+1; parseip(ipaddr, buf); port = atoi(p); /* tell remote side address and port*/ sendrequest(d->ftpctl, "PORT %d,%d,%d,%d,%d,%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3], port>>8, port&0xff); if(getreply(d->ftpctl, msg, sizeof(msg)) != Success){ close(listenfd); werrstr("ftp protocol botch"); fprint(2, "active mode connect failed %s\n", msg); return -1; } /* tell remote to send a file */ sendrequest(d->ftpctl, "RETR %s", d->u->reltext); if(getreply(d->ftpctl, msg, sizeof(msg)) != Extra){ close(listenfd); fprint(2, "active mode connect failed: %s\n", msg); werrstr(msg); return -1; } /* wait for a new call */ cfd = listen(netdir, newdir); close(listenfd); if(cfd < 0){ fprint(2, "active mode connect failed: %r\n"); return -1; } /* open the data connection and close the control connection */ dfd = accept(cfd, newdir); close(cfd); if(dfd < 0){ fprint(2, "active mode connect failed: %r\n"); werrstr("ftp protocol botch"); return -1; } return dfd; } /* * Given a url, return a file descriptor on which caller can * read an ftp document. * The caller is responsible for processing redirection loops. */ int ftp(Url *url) { int n; int data; Ftp *d; int pfd[2]; char buf[2048]; if(url->type == 0) url->type = PLAIN; d = (Ftp*)emalloc(sizeof(Ftp)); d->u = url; d->ftpctl = nil; if(hello(d) == nil) return terminateftp(d); if(logon(d) < 0) return terminateftp(d); switch(url->type){ case PLAIN: case HTML: if(xfertype(d, "A") < 0) return terminateftp(d); break; default: if(xfertype(d, "I") < 0) return terminateftp(d); break; } /* first try passive mode, then active */ data = passive(d); if(data < 0){ if(d->ftpctl == nil) return -1; data = active(d); if(data < 0) return -1; } if(pipe(pfd) < 0) return -1; switch(rfork(RFFDG|RFPROC|RFNOWAIT)){ case -1: werrstr("Can't fork"); close(pfd[0]); close(pfd[1]); return terminateftp(d); case 0: close(pfd[0]); while((n=read(data, buf, sizeof(buf)))>0) write(pfd[1], buf, n); if(n<0) fprint(2, "ftp: %s: %r\n", url->fullname); _exits(0); default: close(pfd[1]); close(data); terminateftp(d); return pfd[0]; } return -1; } //GO.SYSIN DD VADIM /sys/src/cmd/mothra sum=`{sum < 836403055/ftp.c} if(~ 3818cb697569 $sum(1)^$sum(2)) echo if not{ echo 836403055/ftp.c checksum error extracting new file exit checksum } target=836403055/get echo -n '836403055/get (new): ' cat > 836403055/get >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' #!/bin/rc 9fs fornax cp /n/fornax/sys/src/cmd/mothra/*.[hc] /n/fornax/sys/src/cmd/mothra/mkfile . sed 's/brazil/plan9/' mkfile >junk mv junk mkfile //GO.SYSIN DD VADIM /sys/src/cmd/mothra sum=`{sum < 836403055/get} if(~ 75d5b8cd148 $sum(1)^$sum(2)) echo if not{ echo 836403055/get checksum error extracting new file exit checksum } target=836403055/rtext.h echo -n '836403055/rtext.h (new): ' cat > 836403055/rtext.h >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' /* * Rtext definitions */ #define PL_NOPBIT 4 #define PL_NARGBIT 12 #define PL_ARGMASK ((1< 836403055/version.c >[2]/dev/null <<'//GO.SYSIN DD VADIM /sys/src/cmd/mothra' char version[]="Jun-19-14:28:37-EDT-1996"; //GO.SYSIN DD VADIM /sys/src/cmd/mothra sum=`{sum < 836403055/version.c} if(~ a58ef89943 $sum(1)^$sum(2)) echo if not{ echo 836403055/version.c checksum error extracting new file exit checksum } echo obsolete files: /n/juke/plan_9/sys/src/cmd/mothra/urlcanon.c