ref: e173b7ee0d3c26b54531c287d68aac00ec50f199
dir: /aplenty.c/
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <bio.h>
#include <json.h>
#include <regexp.h>
int debug;
vlong caddr;
void
handlerideevents(int in, int out, int text){
Biobuf *bin;
char *b, k; /* event buffer, kind */
long t, n, o; /* type, length, offset */
bin = Bfdopen(in, OREAD);
while(b = Brdline(bin, '\n')){
Bseek(bin, Blinelen(bin), 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 > 1)
fprintf(stderr, "ride: %c %ld %ld %ld %s\n", k, t, n, o);
if(k == 'p')
write(out, b, n);
if(k == 'o' && t != 14){ /* ignore echoed input */
b = malloc(n);
pread(text, b, n, o);
write(out, b, n);
free(b);
}
}
}
void
handlerootevents(int wid, int in, int out){
Biobuf *bin, *bxdata, *btag;
int 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);
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 */
write(fdbody, " ", 6);
/* 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 > 1)
fprintf(stderr, "acme: %c%c%ld %ld %ld %ld\n", o, t, n , m, f, l);
/* Ride-triggered edits */
if(o == 'E'){
write(fdaddr, "$-/^/", 5);
pread(fdaddr, s, 12, 0);
n = atol(strtok(s, " "));
caddr = n;
continue;
}
/* trailing text may be elided; read canonical source */
if(!strchr("Dd", t)){
fprint(fdaddr, "#%ld,#%ld", n, m);
if(strchr("ILX", t)){
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);
}
r[i] = t == 'X' ? '\n' : 0;
/* 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));
write(fdaddr, "$-/^/", 5);
pread(fdaddr, s, 12, 0);
n = atol(strtok(s, " "));
caddr = n;
}
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);
}
}
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, rtext; /* ride */
int wid, wctl, win, wout; /* root window */
if(argc < 1){
usage();
exits("requires address argument");
}
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));
/* connection id */
pread(rctl, b, sizeof(b), 0);
sprintf(p, "\n");
rid = atoi(strtok(b, p));
/* establish connection */
snprintf(p, sizeof(p), "/mnt/ride/%i/text", rid);
if((rout = open(p, OWRITE)) < 0)
exits(errmsg(err));
if((rtext = open(p, OREAD)) < 0)
exits(errmsg(err));
/* ride i/o files */
snprintf(p, sizeof(p), "/mnt/ride/%i/event", rid);
if((rin = open(p, OREAD)) < 0)
exits(errmsg(err));
/* new acme window */
if((wctl = open("/mnt/acme/new/ctl", OREAD)) < 0)
exits(errmsg(err));
readn(wctl, b, 12);
wid = atoi(strtok(b, " "));
/* window i/o files */
snprintf(p, sizeof(p), "/mnt/acme/%i/event", wid);
if((win = open(p, OREAD)) < 0)
exits(errmsg(err));
snprintf(p, sizeof(p), "/mnt/acme/%i/body", wid);
if((wout = open(p, OWRITE)) < 0)
exits(errmsg(err));
JSONfmtinstall();
rfork(RFNOTEG);
switch(rfork(RFPROC|RFMEM)){
case -1: err = "unable to start ride message handler"; break;
case 0:
handlerideevents(rin, wout, rtext);
exits(nil);
default: break;
}
switch(rfork(RFPROC|RFMEM)){
case -1: err = "unable to start root window event handler"; break;
case 0:
handlerootevents(wid, win, rout);
exits(nil);
default: break;
}
wait();
postnote(PNGROUP, getpid(), "exit");
exits(errmsg(err));
}