ref: 666191d45413d79a7a462998ebfd300e12af6f13
dir: /aplenty.c/
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <bio.h>
#include <json.h>
#include <regexp.h>
QLock lwin;
char *rdir;
vlong caddr;
int debug;
void
hevride(int in, int ev, int out, int addr){
Biobuf *bev;
char *b, s[32], k; /* event buffer, kind */
long t, n, o; /* type, length, offset */
bev = Bfdopen(ev, OREAD);
while(b = Brdline(bev, '\n')){
Bseek(bev, Blinelen(bev), 1);
k = b[0]; b++;
t = atol(strtok(b, " \n"));
n = atol(strtok(nil, " \n"));
o = atol(b = strtok(nil, " \n"));
for(; *b != '\0'; b++); b++;
if(debug)
fprintf(stderr, "ride: %c %ld %ld %ld\n", k, t, n, o);
qlock(&lwin);
if(k == 'p'){
fprint(addr, "#%lld,$", caddr);
write(out, b, n);
}
if(k == 'o'){
b = malloc(n);
pread(in, b, n, o);
if(t == 14)
fprint(addr, "#%lld,$", caddr);
else
fprint(addr, "$");
write(out, b, n);
free(b);
}
write(addr, "$-/^/", 5);
pread(addr, s, 12, 0);
caddr = atol(strtok(s, " "));
qunlock(&lwin);
}
}
void
hevroot(int wid, int in, int out){
Biobuf *bin, *bxdata, *btag;
int fdctl, fdevent, fdaddr, fdbody;
char o, t; /* event origin, type */
long n, m, f, l; /* addr n, addr m, flag, len */
Rune *r; /* runes */
long c;
char *ln, s[256];
int i;
/* setup files */
snprintf(s, sizeof(s), "/mnt/acme/%i", wid);
chdir(s);
fdctl = open("ctl", OWRITE);
fdevent = open("event", OWRITE);
fdaddr = open("addr", ORDWR);
fdbody = open("body", OWRITE);
bin = Bfdopen(in, OREAD);
rerrstr(s, sizeof(s));
if(s[0] != 0)
exits(s);
/* initial prompt not setup by ride */
fprint(fdctl, "name %s/-aplenty\n", rdir);
fprint(fdbody, " ");
caddr = 0;
/* event handle loop: cf acme(4):/event */
r = malloc((2+4*12 + 256)*sizeof(*r));
while((o = Bgetc(bin)) != EOF){
t = Bgetc(bin);
n = atol(Brdline(bin, ' '));
m = atol(Brdline(bin, ' '));
f = atol(Brdline(bin, ' '));
l = atol(Brdline(bin, ' '));
for(i = 0; i < l+1; i++) /* trailing LF not counted by l */
Bgetrune(bin);
if(debug)
fprintf(stderr, "acme: %c%c%ld %ld %ld %ld\n", o, t, n , m, f, l);
qlock(&lwin);
/* trailing event text may be elided; read canonical source */
if(!strchr("Dd", t)){
if(strchr("ILX", t)){
fprint(fdaddr, "#%ld,#%ld", n, m);
bxdata = Bopen("xdata", OREAD);
for(i = 0, c = Bgetrune(bxdata); c >= 0; i++, c = Bgetrune(bxdata))
r[i] = c;
Bterm(bxdata);
} else if(strchr("ilx", t)) {
btag = Bopen("tag", OREAD);
for(i = 0, c = Bgetrune(btag); c >= 0; i++, c = Bgetrune(btag))
r[i] = c;
Bterm(btag);
}
}
/* Ride-triggered edits */
if(strchr("EF", o))
goto end;
/* XXX: Only execute first line if multiline input */
if(t == 'I' && n >= caddr || t == 'X'){
fprint(fdaddr, "#%lld,#%ld", caddr, m);
bxdata = Bopen("xdata", OREAD);
ln = Brdline(bxdata, '\n');
if(ln)
write(out, ln, Blinelen(bxdata));
Bterm(bxdata);
}
if(strchr("ID", t))
if((t == 'D') + m < caddr)
caddr += t == 'D' ? n-m : m-n;
if(f%2 == 0 && strchr("Lidlx", t))
fprint(fdevent, "%c%c%ld %ld\n", o, t, n, m);
end:
qunlock(&lwin);
}
}
char*
errmsg(char *err){
if(err == nil){
err = malloc(ERRMAX);
rerrstr(err, ERRMAX);
}
fprintf(stderr, "%s\n", err);
return err;
}
void
usage(void){
fprintf(stderr, "Usage: %s [-d] addr\n", argv0);
}
void
main(int argc, char **argv){
char *err, *addr, b[256], p[256];
int rid, rctl, rin, rout, revent; /* ride */
int wid, wctl, win, wout, waddr; /* root window */
ARGBEGIN{
case 'd': debug++; break;
case 'h': usage(); exits(nil);
}ARGEND
if(argc == 0)
addr = getenv("rideaddr");
else
addr = argv[0];
if(addr == nil){
usage();
exits(errmsg("no ride address"));
}
err = nil;
/* new ride connection */
if((rctl = open("/mnt/ride/clone", ORDWR)) < 0)
exits(errmsg(err));
sprintf(b, "connect %s\n", addr);
write(rctl, b, strlen(b));
pread(rctl, b, sizeof(b), 0);
sprintf(p, "\n");
rid = atoi(strtok(b, p));
rdir = smprint("/mnt/ride/%d", rid);
/* new acme window */
if((wctl = open("/mnt/acme/new/ctl", OREAD)) < 0)
exits(errmsg(err));
readn(wctl, b, 12);
wid = atoi(strtok(b, " "));
JSONfmtinstall();
rfork(RFNOTEG);
switch(rfork(RFPROC|RFMEM)){
case -1: err = "unable to start ride message handler"; break;
case 0:
snprintf(p, sizeof(p), "/mnt/ride/%i/text", rid);
rin = open(p, OREAD); /* establishes connection */
snprintf(p, sizeof(p), "/mnt/ride/%i/event", rid);
revent = open(p, OREAD);
snprintf(p, sizeof(p), "/mnt/acme/%i/data", wid);
wout = open(p, OWRITE);
snprintf(p, sizeof(p), "/mnt/acme/%i/addr", wid);
waddr = open(p, ORDWR);
hevride(rin, revent, wout, waddr);
exits(nil);
default: break;
}
switch(rfork(RFPROC|RFMEM)){
case -1: err = "unable to start root window event handler"; break;
case 0:
snprintf(p, sizeof(p), "/mnt/acme/%i/event", wid);
win = open(p, OREAD);
snprintf(p, sizeof(p), "/mnt/ride/%i/text", rid);
rout = open(p, OWRITE);
hevroot(wid, win, rout);
exits(nil);
default: break;
}
wait();
postnote(PNGROUP, getpid(), "exit");
exits(errmsg(err));
}