#!/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
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
\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, "