#include <u.h>#include <libc.h>#include <String.h>#include <regexp.h>#include <draw.h>#include <event.h>#include <keyboard.h>#include <panel.h>#include <bio.h>#include <plumb.h>#include "dat.h"#include "icons.h" void texthit(Panel *p, int b, Rtext *t);void message(char *s, ...); Image *backi;Image *fwdi;Image *reloadi;Panel *root;Panel *backp;Panel *fwdp;Panel *reloadp;Panel *entryp;Panel *urlp;Panel *textp;Panel *statusp;Panel *popup;char *url;Mouse *mouse;Hist *hist = nil;char *bdir; enum{ Msearch, Maddbookmark, Mbookmarks, Mexit,}; char *menu3[] = { "search", "add bookmark", "bookmarks", "exit", 0}; Link*mklink(char *addr, char *sel, int type){ Link *l; l = malloc(sizeof *l); if(l==nil) sysfatal("malloc: %r"); l->addr = strdup(addr); l->sel = sel!=nil ? strdup(sel) : nil; l->type = type; return l;} Link*clonelink(Link *l){ if(l==nil) return nil; return mklink(l->addr, l->sel, l->type);} intseltype(char c){ int t; t = -c; switch(c){ case '0': t = Ttext; break; case '1': t = Tmenu; break; case '2': t = Tns; break; case '3': t = Terror; break; case '4': t = Tbinhex; break; case '5': t = Tdos; break; case '6': t = Tuuencoded; break; case '7': t = Tsearch; break; case '8': t = Ttelnet; break; case '9': t = Tbinary; break; case '+': t = Tmirror; break; case 'g': t = Tgif; break; case 'I': t = Timage; break; case 'T': t = Tt3270; break; case 'd': t = Tdoc; break; case 'h': t = Thtml; break; case 'i': t = Tinfo; break; case 's': t = Tsound; break; case '.': t = Teof; break; default: break; } return t;} static char Typechar[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', 'g', 'I', 'T', 'd', 'h', 'i', 's', '.',}; static char *Typestr[] = { "FILE", "DIR", "NS", "ERR", "HEX", "DOS", "UU", "?", "TELNET", "BIN", "MIRROR", "GIF", "IMG", "T3270", "DOC", "HTML", "", "SND", "EOF",}; char*seltypestr(int type){ if(type<0) return smprint("UNKN:%c", (char) -type); return smprint("%6s", Typestr[type]);}; Gmenu*rendermenu(Link *l, Biobuf *bp){ char *s, *f[5], *t; Gmenu *m; Link *n; int type, c; m = malloc(sizeof *m); if(m==nil) sysfatal("malloc: %r"); m->link = clonelink(l); m->text = nil; plrtstr(&m->text, 1000000, 0, 0, font, strdup(" "), 0, 0); for(;;){ n = nil; s = Brdstr(bp, '\n', 0); if(s==nil || s[0]=='.') break; type = seltype(s[0]); c = getfields(s+1, f, 5, 0, "\t\r\n"); switch(type){ case Tinfo: break; case Thtml: n = mklink(strdup(f[1]+4), nil, Thtml); /* +4 skip URL: */ break; default: if(type < 0 && c < 3){ fprint(2, "skipping invalid menu line '%s'\n", s); continue; } n = mklink(netmkaddr(f[2], "tcp", f[3]), strdup(f[1]), type); break; } t = strdup(f[0]); plrtstr(&m->text, 1000000, 8, 0, font, seltypestr(type), PL_HEAD, 0); if(type == Tinfo || type < 0) plrtstr(&m->text, 8, 0, 0, font, t, 0, 0); else plrtstr(&m->text, 8, 0, 0, font, t, PL_HOT, n); } return m;} Gmenu*rendertext(Link *l, Biobuf *bp){ Gmenu *m; String *buf; int c, n; m = malloc(sizeof *m); if(m==nil) sysfatal("malloc: %r"); m->link = clonelink(l); m->text = nil; plrtstr(&m->text, 1000000, 0, 0, font, strdup(" "), 0, 0); n = 0; buf = s_new(); for(;;){ c = Bgetc(bp); if(c<0) break; else if(c=='\r' || c=='\n'){ if(c=='\r' && Bgetc(bp)!='\n') Bungetc(bp); if(n==1 && s_to_c(buf)[0]=='.') break; s_terminate(buf); plrtstr(&m->text, 1000000, 8, 0, font, strdup(s_to_c(buf)), 0, 0); s_reset(buf); n = 0; }else if(c=='\t'){ n += 4; s_append(buf, " "); }else{ n++; s_putc(buf, c); } } s_free(buf); return m;} Gmenu*render(Link *l){ int fd; Biobuf *bp; Gmenu *m; fd = dial(l->addr, 0, 0, 0); if(fd < 0){ message("unable to connect to %s: %r", l->addr); return nil; } fprint(fd, "%s\r\n", l->sel); bp = Bfdopen(fd, OREAD); if(bp==nil){ close(fd); sysfatal("bfdopen: %r"); } switch(l->type){ case Tmenu: m = rendermenu(l, bp); break; case Ttext: m = rendertext(l, bp); break; default: /* TODO error */ m = nil; break; } Bterm(bp); close(fd); return m;} void message(char *s, ...){ static char buf[1024]; char *out; va_list args; va_start(args, s); out = buf + vsnprint(buf, sizeof(buf), s, args); va_end(args); *out='\0'; plinitlabel(statusp, PACKN|FILLX, buf); pldraw(statusp, screen); flushimage(display, 1);} Link*urltolink(char *url){ char *a, *sel, *hostport, *p; int type; Link *l; a = strdup(url); hostport = a; if(strncmp(a, "gopher://", 9) == 0) hostport += 9; p = strchr(hostport, '/'); if(p){ *p++ = 0; type = *p ? seltype(*p++) : Tmenu; if(type < 0) return nil; sel = *p ? p : ""; }else{ type = Tmenu; sel = ""; } p = strchr(hostport, ':'); if(p){ *p++ = 0; l = mklink(netmkaddr(hostport, "tcp", p), sel, type); }else{ l = mklink(netmkaddr(hostport, "tcp", "70"), sel, type); } free(a); return l;} char*linktourl(Link *l){ char *f[3], *a, *s; int n; a = strdup(l->addr); n = getfields(a, f, 3, 0, "!"); if(n != 3) s = smprint("Url: gopher://%s/%d%s", l->addr, l->type, l->sel); else if(atoi(f[2])!=70) s = smprint("Url: gopher://%s:%s/%d%s", f[1], f[2], l->type, l->sel); else s = smprint("Url: gopher://%s/%d%s", f[1], l->type, l->sel); free(a); return s; } voidseturl(Link *l){ free(url); url = linktourl(l);} voidshow(Gmenu *m){ plinittextview(textp, PACKE|EXPAND, ZP, m->text, texthit); pldraw(textp, screen); plinitlabel(urlp, PACKN|FILLX, url); pldraw(urlp, screen); message("gopher!");} void freetext(Rtext *t){ Rtext *tt; Link *l; tt = t; for(; t!=0; t = t->next){ t->b=0; free(t->text); t->text = 0; if(l = t->user){ t->user = 0; free(l->addr); if(l->sel!=nil && l->sel[0]!=0) free(l->sel); free(l); } } plrtfree(tt);} voidfreehist(Hist *h){ Hist *n; Gmenu *m; for(n = h->n; h; h = n){ m = h->m; freetext(m->text); if(m->link!=nil){ free(m->link->addr); free(m->link->sel); free(m->link); } free(h); } } voidvisit(Link *l, int sethist){ Gmenu *m; Hist *h; seturl(l); message("loading %s...", url); m = render(l); if(m==nil) return; show(m); if(!sethist) return; h = malloc(sizeof *h); if(h == nil) sysfatal("malloc: %r");/* FIXME if(hist != nil && hist->n != nil) freehist(hist->n);*/ h->p = hist; h->n = nil; h->m = m; hist = h;} voidplumburl(char *u){ int fd; fd = plumbopen("send", OWRITE|OCEXEC); if(fd<0) return; plumbsendtext(fd, "gopher", nil, nil, u); close(fd);} voiddupfds(int fd, ...){ int mfd, n, i; va_list arg; Dir *dir; va_start(arg, fd); for(mfd = 0; fd >= 0; fd = va_arg(arg, int), mfd++) if(fd != mfd) if(dup(fd, mfd) < 0) sysfatal("dup: %r"); va_end(arg); if((fd = open("/fd", OREAD)) < 0) sysfatal("open: %r"); n = dirreadall(fd, &dir); for(i=0; i<n; i++){ if(strstr(dir[i].name, "ctl")) continue; fd = atoi(dir[i].name); if(fd >= mfd) close(fd); } free(dir);} voidpage(Link *l){ int fd; fd = dial(l->addr, 0, 0, 0); if(fd < 0) sysfatal("dial: %r"); fprint(fd, "%s\r\n", l->sel); switch(rfork(RFFDG|RFPROC|RFMEM|RFREND|RFNOWAIT|RFNOTEG)){ case -1: fprint(2, "Can't fork!"); break; case 0: dupfds(fd, 1, 2, -1); execl("/bin/rc", "rc", "-c", "page -w", nil); _exits(0); } close(fd);} void save(Link *l, char *name){ char buf[1024]; int ifd, ofd; ifd = dial(l->addr, 0, 0, 0); if(ifd < 0){ message("save: %s: %r", name); return; } fprint(ifd, "%s\r\n", l->sel); ofd=create(name, OWRITE, 0666); if(ofd < 0){ message("save: %s: %r", name); return; } switch(rfork(RFNOTEG|RFNAMEG|RFFDG|RFMEM|RFPROC|RFNOWAIT)){ case -1: message("Can't fork: %r"); break; case 0: dup(ifd, 0); close(ifd); dup(ofd, 1); close(ofd); snprint(buf, sizeof(buf), "{tput -p || cat} |[2] {aux/statusmsg -k %q >/dev/null || cat >/dev/null}", name); execl("/bin/rc", "rc", "-c", buf, nil); exits("exec"); } close(ifd); close(ofd);} voidsearch(void){ static char last[256]; char buf[256]; Reprog *re; Rtext *tp; int yoff; for(;;){Lines 1–500 of 946. Load more
#include <u.h> #include <libc.h> #include <String.h> #include <regexp.h> #include <draw.h> #include <event.h> #include <keyboard.h> #include <panel.h> #include <bio.h> #include <plumb.h> #include "dat.h" #include "icons.h" void texthit(Panel *p, int b, Rtext *t); void message(char *s, ...); Image *backi; Image *fwdi; Image *reloadi; Panel *root; Panel *backp; Panel *fwdp; Panel *reloadp; Panel *entryp; Panel *urlp; Panel *textp; Panel *statusp; Panel *popup; char *url; Mouse *mouse; Hist *hist = nil; char *bdir; enum { Msearch, Maddbookmark, Mbookmarks, Mexit, }; char *menu3[] = { "search", "add bookmark", "bookmarks", "exit", 0 }; Link* mklink(char *addr, char *sel, int type) { Link *l; l = malloc(sizeof *l); if(l==nil) sysfatal("malloc: %r"); l->addr = strdup(addr); l->sel = sel!=nil ? strdup(sel) : nil; l->type = type; return l; } Link* clonelink(Link *l) { if(l==nil) return nil; return mklink(l->addr, l->sel, l->type); } int seltype(char c) { int t; t = -c; switch(c){ case '0': t = Ttext; break; case '1': t = Tmenu; break; case '2': t = Tns; break; case '3': t = Terror; break; case '4': t = Tbinhex; break; case '5': t = Tdos; break; case '6': t = Tuuencoded; break; case '7': t = Tsearch; break; case '8': t = Ttelnet; break; case '9': t = Tbinary; break; case '+': t = Tmirror; break; case 'g': t = Tgif; break; case 'I': t = Timage; break; case 'T': t = Tt3270; break; case 'd': t = Tdoc; break; case 'h': t = Thtml; break; case 'i': t = Tinfo; break; case 's': t = Tsound; break; case '.': t = Teof; break; default: break; } return t; } static char Typechar[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', 'g', 'I', 'T', 'd', 'h', 'i', 's', '.', }; static char *Typestr[] = { "FILE", "DIR", "NS", "ERR", "HEX", "DOS", "UU", "?", "TELNET", "BIN", "MIRROR", "GIF", "IMG", "T3270", "DOC", "HTML", "", "SND", "EOF", }; char* seltypestr(int type) { if(type<0) return smprint("UNKN:%c", (char) -type); return smprint("%6s", Typestr[type]); }; Gmenu* rendermenu(Link *l, Biobuf *bp) { char *s, *f[5], *t; Gmenu *m; Link *n; int type, c; m = malloc(sizeof *m); if(m==nil) sysfatal("malloc: %r"); m->link = clonelink(l); m->text = nil; plrtstr(&m->text, 1000000, 0, 0, font, strdup(" "), 0, 0); for(;;){ n = nil; s = Brdstr(bp, '\n', 0); if(s==nil || s[0]=='.') break; type = seltype(s[0]); c = getfields(s+1, f, 5, 0, "\t\r\n"); switch(type){ case Tinfo: break; case Thtml: n = mklink(strdup(f[1]+4), nil, Thtml); /* +4 skip URL: */ break; default: if(type < 0 && c < 3){ fprint(2, "skipping invalid menu line '%s'\n", s); continue; } n = mklink(netmkaddr(f[2], "tcp", f[3]), strdup(f[1]), type); break; } t = strdup(f[0]); plrtstr(&m->text, 1000000, 8, 0, font, seltypestr(type), PL_HEAD, 0); if(type == Tinfo || type < 0) plrtstr(&m->text, 8, 0, 0, font, t, 0, 0); else plrtstr(&m->text, 8, 0, 0, font, t, PL_HOT, n); } return m; } Gmenu* rendertext(Link *l, Biobuf *bp) { Gmenu *m; String *buf; int c, n; m = malloc(sizeof *m); if(m==nil) sysfatal("malloc: %r"); m->link = clonelink(l); m->text = nil; plrtstr(&m->text, 1000000, 0, 0, font, strdup(" "), 0, 0); n = 0; buf = s_new(); for(;;){ c = Bgetc(bp); if(c<0) break; else if(c=='\r' || c=='\n'){ if(c=='\r' && Bgetc(bp)!='\n') Bungetc(bp); if(n==1 && s_to_c(buf)[0]=='.') break; s_terminate(buf); plrtstr(&m->text, 1000000, 8, 0, font, strdup(s_to_c(buf)), 0, 0); s_reset(buf); n = 0; }else if(c=='\t'){ n += 4; s_append(buf, " "); }else{ n++; s_putc(buf, c); } } s_free(buf); return m; } Gmenu* render(Link *l) { int fd; Biobuf *bp; Gmenu *m; fd = dial(l->addr, 0, 0, 0); if(fd < 0){ message("unable to connect to %s: %r", l->addr); return nil; } fprint(fd, "%s\r\n", l->sel); bp = Bfdopen(fd, OREAD); if(bp==nil){ close(fd); sysfatal("bfdopen: %r"); } switch(l->type){ case Tmenu: m = rendermenu(l, bp); break; case Ttext: m = rendertext(l, bp); break; default: /* TODO error */ m = nil; break; } Bterm(bp); close(fd); return m; } void message(char *s, ...) { static char buf[1024]; char *out; va_list args; va_start(args, s); out = buf + vsnprint(buf, sizeof(buf), s, args); va_end(args); *out='\0'; plinitlabel(statusp, PACKN|FILLX, buf); pldraw(statusp, screen); flushimage(display, 1); } Link* urltolink(char *url) { char *a, *sel, *hostport, *p; int type; Link *l; a = strdup(url); hostport = a; if(strncmp(a, "gopher://", 9) == 0) hostport += 9; p = strchr(hostport, '/'); if(p){ *p++ = 0; type = *p ? seltype(*p++) : Tmenu; if(type < 0) return nil; sel = *p ? p : ""; }else{ type = Tmenu; sel = ""; } p = strchr(hostport, ':'); if(p){ *p++ = 0; l = mklink(netmkaddr(hostport, "tcp", p), sel, type); }else{ l = mklink(netmkaddr(hostport, "tcp", "70"), sel, type); } free(a); return l; } char* linktourl(Link *l) { char *f[3], *a, *s; int n; a = strdup(l->addr); n = getfields(a, f, 3, 0, "!"); if(n != 3) s = smprint("Url: gopher://%s/%d%s", l->addr, l->type, l->sel); else if(atoi(f[2])!=70) s = smprint("Url: gopher://%s:%s/%d%s", f[1], f[2], l->type, l->sel); else s = smprint("Url: gopher://%s/%d%s", f[1], l->type, l->sel); free(a); return s; } void seturl(Link *l) { free(url); url = linktourl(l); } void show(Gmenu *m) { plinittextview(textp, PACKE|EXPAND, ZP, m->text, texthit); pldraw(textp, screen); plinitlabel(urlp, PACKN|FILLX, url); pldraw(urlp, screen); message("gopher!"); } void freetext(Rtext *t){ Rtext *tt; Link *l; tt = t; for(; t!=0; t = t->next){ t->b=0; free(t->text); t->text = 0; if(l = t->user){ t->user = 0; free(l->addr); if(l->sel!=nil && l->sel[0]!=0) free(l->sel); free(l); } } plrtfree(tt); } void freehist(Hist *h) { Hist *n; Gmenu *m; for(n = h->n; h; h = n){ m = h->m; freetext(m->text); if(m->link!=nil){ free(m->link->addr); free(m->link->sel); free(m->link); } free(h); } } void visit(Link *l, int sethist) { Gmenu *m; Hist *h; seturl(l); message("loading %s...", url); m = render(l); if(m==nil) return; show(m); if(!sethist) return; h = malloc(sizeof *h); if(h == nil) sysfatal("malloc: %r"); /* FIXME if(hist != nil && hist->n != nil) freehist(hist->n); */ h->p = hist; h->n = nil; h->m = m; hist = h; } void plumburl(char *u) { int fd; fd = plumbopen("send", OWRITE|OCEXEC); if(fd<0) return; plumbsendtext(fd, "gopher", nil, nil, u); close(fd); } void dupfds(int fd, ...) { int mfd, n, i; va_list arg; Dir *dir; va_start(arg, fd); for(mfd = 0; fd >= 0; fd = va_arg(arg, int), mfd++) if(fd != mfd) if(dup(fd, mfd) < 0) sysfatal("dup: %r"); va_end(arg); if((fd = open("/fd", OREAD)) < 0) sysfatal("open: %r"); n = dirreadall(fd, &dir); for(i=0; i<n; i++){ if(strstr(dir[i].name, "ctl")) continue; fd = atoi(dir[i].name); if(fd >= mfd) close(fd); } free(dir); } void page(Link *l) { int fd; fd = dial(l->addr, 0, 0, 0); if(fd < 0) sysfatal("dial: %r"); fprint(fd, "%s\r\n", l->sel); switch(rfork(RFFDG|RFPROC|RFMEM|RFREND|RFNOWAIT|RFNOTEG)){ case -1: fprint(2, "Can't fork!"); break; case 0: dupfds(fd, 1, 2, -1); execl("/bin/rc", "rc", "-c", "page -w", nil); _exits(0); } close(fd); } void save(Link *l, char *name){ char buf[1024]; int ifd, ofd; ifd = dial(l->addr, 0, 0, 0); if(ifd < 0){ message("save: %s: %r", name); return; } fprint(ifd, "%s\r\n", l->sel); ofd=create(name, OWRITE, 0666); if(ofd < 0){ message("save: %s: %r", name); return; } switch(rfork(RFNOTEG|RFNAMEG|RFFDG|RFMEM|RFPROC|RFNOWAIT)){ case -1: message("Can't fork: %r"); break; case 0: dup(ifd, 0); close(ifd); dup(ofd, 1); close(ofd); snprint(buf, sizeof(buf), "{tput -p || cat} |[2] {aux/statusmsg -k %q >/dev/null || cat >/dev/null}", name); execl("/bin/rc", "rc", "-c", buf, nil); exits("exec"); } close(ifd); close(ofd); } void search(void) { static char last[256]; char buf[256]; Reprog *re; Rtext *tp; int yoff; for(;;){