#include <u.h>#include <libc.h>#include <bio.h>#include <plumb.h>#include <ctype.h>#include "gemnine.h" static voidpage(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); }} static voidplay(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); }} static voidusage(void){ fprint(2, "usage: %s [-w] [URL]\n", argv0); exits("usage");} voidmain(int argc, char **argv){ Response *r; char *s, *t, *u, *tmp; Url *url, *x; int len, raw, wait, pl, fd; Plumbmsg *m; Biobuf out, body; char buf[8192]; wait = 0; ARGBEGIN{ case 'w': wait = 1; break; default: usage(); }ARGEND; if(!wait && argc < 1) usage(); raw = fd2path(1, buf, sizeof(buf)) == 0 && strcmp(buf, "/dev/cons") != 0; 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(!raw && 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 if(raw){ for(;;){ if((len = read(r->fd, buf, sizeof(buf))) == 0) break; if(len < 0) goto err; if(write(1, buf, len) <= 0) break; } }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); if((tmp = smprint("%U", x)) != nil && strcmp(tmp, t) == 0) Bprint(&out, "→ %s\n", tmp); else Bprint(&out, "→ %s %s\n", tmp, t); free(tmp); freeurl(x); }else{ Bprint(&out, "%s\n", s); } free(s); } Bterm(&body); } } freeresponse(r); freeurl(url); }else{err: fprint(2, "%U: %r\n", url); if(!wait) exits("failed"); } Bflush(&out); if(wait) goto nexturl; exits(nil);}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <plumb.h>
#include <ctype.h>
#include "gemnine.h"
static 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);
}
}
static 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);
}
}
static void
usage(void)
{
fprint(2, "usage: %s [-w] [URL]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
Response *r;
char *s, *t, *u, *tmp;
Url *url, *x;
int len, raw, wait, pl, fd;
Plumbmsg *m;
Biobuf out, body;
char buf[8192];
wait = 0;
ARGBEGIN{
case 'w':
wait = 1;
break;
default:
usage();
}ARGEND;
if(!wait && argc < 1)
usage();
raw = fd2path(1, buf, sizeof(buf)) == 0 && strcmp(buf, "/dev/cons") != 0;
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(!raw && 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 if(raw){
for(;;){
if((len = read(r->fd, buf, sizeof(buf))) == 0)
break;
if(len < 0)
goto err;
if(write(1, buf, len) <= 0)
break;
}
}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);
if((tmp = smprint("%U", x)) != nil && strcmp(tmp, t) == 0)
Bprint(&out, "→ %s\n", tmp);
else
Bprint(&out, "→ %s %s\n", tmp, t);
free(tmp);
freeurl(x);
}else{
Bprint(&out, "%s\n", s);
}
free(s);
}
Bterm(&body);
}
}
freeresponse(r);
freeurl(url);
}else{
err:
fprint(2, "%U: %r\n", url);
if(!wait)
exits("failed");
}
Bflush(&out);
if(wait)
goto nexturl;
exits(nil);
}