ref: a194837a08fbac1792c9db77f5298a9a999ef6fb
dir: /main.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <plumb.h> #include <ctype.h> #include "gemnine.h" void page(Response *r) { if(rfork(RFPROC|RFFDG|RFNOTEG|RFNOWAIT) == 0){ char tmp[32] = "/tmp/gem9XXXXXXXXXXX", *cmd; int f; mktemp(tmp); cmd = smprint("cat >%s; page %s; rm %s", tmp, tmp, tmp); dup(r->fd, 0); close(r->fd); dup((f = open("/dev/null", OWRITE)), 1); dup(f, 2); close(f); execl("/bin/rc", "rc", "-c", cmd, nil); } } void play(Response *r) { if(rfork(RFPROC|RFFDG|RFNOTEG|RFNOWAIT) == 0){ int wfd, f; char *wsys, tmp[64]; snprint(tmp, sizeof(tmp), "new -pid %d -dx %d -dy %d", getpid(), 640, 480); if ((wsys = getenv("wsys")) == nil) exits("no wsys"); if ((wfd = open(wsys, ORDWR|OCEXEC)) < 0 || mount(wfd, -1, "/mnt/wsys", MREPL, tmp) < 0 || bind("/mnt/wsys", "/dev", MBEFORE) < 0){ exits("wsys: %r"); } dup(r->fd, 0); close(r->fd); dup((f = open("/dev/null", OWRITE)), 1); dup(f, 2); execl("/bin/play", "play", nil); } } void main(int argc, char **argv) { Response *r; char *s, *t, *u; Url *url, *x; int len, wait, pl, fd; Plumbmsg *m; Biobuf out, body; wait = 0; ARGBEGIN{ case 'w': wait = 1; break; }ARGEND; if(!wait && argc < 1){ fprint(2, "usage: gemnine [-w] [URL]\n"); exits("usage"); } quotefmtinstall(); fmtinstall('U', Ufmt); fmtinstall('N', Nfmt); fmtinstall(']', Mfmt); fmtinstall('E', Efmt); fmtinstall('[', encodefmt); fmtinstall('H', encodefmt); Binit(&out, 1, OWRITE); pl = -1; nexturl: url = nil; if(wait){ if(pl >= 0 || (pl = plumbopen("gemini", OREAD)) >= 0){ if((m = plumbrecv(pl)) != nil){ url = urlparse(nil, estrdup(m->data)); plumbfree(m); }else{ exits(nil); } }else{ sysfatal("plumbopen: %r"); } }else{ url = urlparse(nil, estrdup(argv[0])); } nextreq: if((r = request(url)) != nil){ if(r->mime != nil && strncmp(r->mime, "text/", 5) != 0){ if(strncmp(r->mime, "image/", 6) == 0 || strcmp(r->mime, "application/pdf") == 0) page(r); else if(strncmp(r->mime, "audio/", 6) == 0) play(r); else fprint(2, "unsupported MIME %q\n", r->mime); }else if(r->prompt != nil){ if(wait) close(open("/dev/text", OWRITE|OTRUNC|OCEXEC)); if((fd = open("/dev/consctl", OWRITE|OCEXEC)) >= 0){ write(fd, "holdon", 6); print("%s\n", r->prompt); Binit(&body, 0, OREAD); t = nil; if((s = Brdstr(&body, 0, 1)) != nil) t = smprint("%s?%E", r->url->full, (Str2){s, "/:@ \n"}); Bterm(&body); free(s); if(t != nil){ freeresponse(r); freeurl(url); url = urlparse(nil, t); free(t); }else{ fprint(2, "%r\n"); } close(fd); goto nextreq; }else{ fprint(2, "%r\n"); } }else{ if(wait) close(open("/dev/text", OWRITE|OTRUNC|OCEXEC)); if(r->code < 20 || r->code >= 30){ if(r->code > 0) fprint(2, "%U: %d %s\n", url, r->code, (r->meta && r->meta[0]) ? r->meta : r->status); else fprint(2, "%U: %r\n", url); if(!wait) exits("failed"); }else{ Binit(&body, r->fd, OREAD); while((s = Brdstr(&body, '\n', 1)) != nil){ if((len = Blinelen(&body)) > 0) s[len] = 0; for(len--; len >= 0 && (s[len] == '\r' || s[len] == '\n'); len--) s[len] = 0; if(s[0] == '=' && s[1] == '>'){ u = s + 2; while(isspace(*u)) u++; if((t = strpbrk(u, " \t")) != nil) *t++ = 0; else t = ""; x = urlparse(r->url, u); Bprint(&out, "→ %U %s\n", x, t); freeurl(x); }else{ Bprint(&out, "%s\n", s); } free(s); } Bterm(&body); } } freeresponse(r); freeurl(url); }else{ fprint(2, "%U: %r\n", url); if(!wait) exits("failed"); } Bflush(&out); if(wait) goto nexturl; exits(nil); }