acme/win: remove old crap
This commit is contained in:
parent
169db43ad9
commit
6ddbe25d19
2 changed files with 0 additions and 797 deletions
|
@ -1,146 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <fcall.h>
|
||||
#include <thread.h>
|
||||
#include <9p.h>
|
||||
#include "dat.h"
|
||||
|
||||
Channel *fschan;
|
||||
Channel *writechan;
|
||||
|
||||
static File *devcons, *devnew;
|
||||
|
||||
static void
|
||||
fsread(Req *r)
|
||||
{
|
||||
Fsevent e;
|
||||
|
||||
if(r->fid->file == devnew){
|
||||
if(r->fid->aux==nil){
|
||||
respond(r, "phase error");
|
||||
return;
|
||||
}
|
||||
readstr(r, r->fid->aux);
|
||||
respond(r, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(r->fid->file == devcons);
|
||||
e.type = 'r';
|
||||
e.r = r;
|
||||
send(fschan, &e);
|
||||
}
|
||||
|
||||
static void
|
||||
fsflush(Req *r)
|
||||
{
|
||||
Fsevent e;
|
||||
|
||||
e.type = 'f';
|
||||
e.r = r;
|
||||
send(fschan, &e);
|
||||
}
|
||||
|
||||
static void
|
||||
fswrite(Req *r)
|
||||
{
|
||||
static Event *e[4];
|
||||
Event *ep;
|
||||
int i, j, nb, wid, pid;
|
||||
Rune rune;
|
||||
char *s;
|
||||
char tmp[UTFmax], *t;
|
||||
static int n, partial;
|
||||
|
||||
if(r->fid->file == devnew){
|
||||
if(r->fid->aux){
|
||||
respond(r, "already created a window");
|
||||
return;
|
||||
}
|
||||
s = emalloc(r->ifcall.count+1);
|
||||
memmove(s, r->ifcall.data, r->ifcall.count);
|
||||
s[r->ifcall.count] = 0;
|
||||
pid = strtol(s, &t, 0);
|
||||
if(*t==' ')
|
||||
t++;
|
||||
i = newpipewin(pid, t);
|
||||
free(s);
|
||||
s = emalloc(32);
|
||||
sprint(s, "%lud", (ulong)i);
|
||||
r->fid->aux = s;
|
||||
r->ofcall.count = r->ifcall.count;
|
||||
respond(r, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(r->fid->file == devcons);
|
||||
|
||||
if(e[0] == nil){
|
||||
for(i=0; i<nelem(e); i++){
|
||||
e[i] = emalloc(sizeof(Event));
|
||||
e[i]->c1 = 'S';
|
||||
}
|
||||
}
|
||||
|
||||
ep = e[n];
|
||||
n = (n+1)%nelem(e);
|
||||
assert(r->ifcall.count <= 8192); /* is this guaranteed by lib9p? */
|
||||
nb = r->ifcall.count;
|
||||
memmove(ep->b+partial, r->ifcall.data, nb);
|
||||
nb += partial;
|
||||
ep->b[nb] = '\0';
|
||||
if(strlen(ep->b) < nb){ /* nulls in data */
|
||||
t = ep->b;
|
||||
for(i=j=0; i<nb; i++)
|
||||
if(ep->b[i] != '\0')
|
||||
t[j++] = ep->b[i];
|
||||
nb = j;
|
||||
t[j] = '\0';
|
||||
}
|
||||
/* process bytes into runes, transferring terminal partial runes into next buffer */
|
||||
for(i=j=0; i<nb && fullrune(ep->b+i, nb-i); i+=wid,j++)
|
||||
wid = chartorune(&rune, ep->b+i);
|
||||
memmove(tmp, ep->b+i, nb-i);
|
||||
partial = nb-i;
|
||||
ep->nb = i;
|
||||
ep->nr = j;
|
||||
ep->b[i] = '\0';
|
||||
if(i != 0){
|
||||
sendp(win->cevent, ep);
|
||||
recvp(writechan);
|
||||
}
|
||||
partial = nb-i;
|
||||
memmove(e[n]->b, tmp, partial);
|
||||
r->ofcall.count = r->ifcall.count;
|
||||
respond(r, nil);
|
||||
}
|
||||
|
||||
void
|
||||
fsdestroyfid(Fid *fid)
|
||||
{
|
||||
if(fid->aux)
|
||||
free(fid->aux);
|
||||
}
|
||||
|
||||
Srv fs = {
|
||||
.read= fsread,
|
||||
.write= fswrite,
|
||||
.flush= fsflush,
|
||||
.destroyfid= fsdestroyfid,
|
||||
.leavefdsopen= 1,
|
||||
};
|
||||
|
||||
void
|
||||
mountcons(void)
|
||||
{
|
||||
fschan = chancreate(sizeof(Fsevent), 0);
|
||||
writechan = chancreate(sizeof(void*), 0);
|
||||
fs.tree = alloctree("win", "win", DMDIR|0555, nil);
|
||||
devcons = createfile(fs.tree->root, "cons", "win", 0666, nil);
|
||||
if(devcons == nil)
|
||||
sysfatal("creating /dev/cons: %r");
|
||||
devnew = createfile(fs.tree->root, "wnew", "win", 0666, nil);
|
||||
if(devnew == nil)
|
||||
sysfatal("creating /dev/wnew: %r");
|
||||
threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
|
||||
}
|
|
@ -1,651 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <thread.h>
|
||||
#include <fcall.h>
|
||||
#include <9p.h>
|
||||
#include <ctype.h>
|
||||
#include "dat.h"
|
||||
|
||||
void mainctl(void*);
|
||||
void startcmd(char *[], int*);
|
||||
void stdout2body(void*);
|
||||
|
||||
int debug;
|
||||
int notepg;
|
||||
int eraseinput;
|
||||
int dirty = 0;
|
||||
|
||||
Window *win; /* the main window */
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: win [command]\n");
|
||||
threadexitsall("usage");
|
||||
}
|
||||
|
||||
void
|
||||
threadmain(int argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
char *dir, *tag, *name;
|
||||
char buf[1024], **av;
|
||||
|
||||
quotefmtinstall();
|
||||
rfork(RFNAMEG);
|
||||
ARGBEGIN{
|
||||
case 'd':
|
||||
debug = 1;
|
||||
chatty9p++;
|
||||
break;
|
||||
case 'e':
|
||||
eraseinput = 1;
|
||||
break;
|
||||
case 'D':
|
||||
{extern int _threaddebuglevel;
|
||||
_threaddebuglevel = 1<<20;
|
||||
}
|
||||
}ARGEND
|
||||
|
||||
if(argc == 0){
|
||||
av = emalloc(3*sizeof(char*));
|
||||
av[0] = "rc";
|
||||
av[1] = "-i";
|
||||
name = getenv("sysname");
|
||||
}else{
|
||||
av = argv;
|
||||
name = utfrrune(av[0], '/');
|
||||
if(name)
|
||||
name++;
|
||||
else
|
||||
name = av[0];
|
||||
}
|
||||
|
||||
if(getwd(buf, sizeof buf) == 0)
|
||||
dir = "/";
|
||||
else
|
||||
dir = buf;
|
||||
dir = estrdup(dir);
|
||||
tag = estrdup(dir);
|
||||
tag = eappend(estrdup(tag), "/-", name);
|
||||
win = newwindow();
|
||||
snprint(buf, sizeof buf, "%d", win->id);
|
||||
putenv("winid", buf);
|
||||
winname(win, tag);
|
||||
wintagwrite(win, "Send Noscroll", 5+8);
|
||||
threadcreate(mainctl, win, STACK);
|
||||
mountcons();
|
||||
threadcreate(fsloop, nil, STACK);
|
||||
startpipe();
|
||||
startcmd(av, ¬epg);
|
||||
|
||||
strcpy(buf, "win");
|
||||
j = 3;
|
||||
for(i=0; i<argc && j+1+strlen(argv[i])+1<sizeof buf; i++){
|
||||
strcpy(buf+j, " ");
|
||||
strcpy(buf+j+1, argv[i]);
|
||||
j += 1+strlen(argv[i]);
|
||||
}
|
||||
|
||||
ctlprint(win->ctl, "scroll");
|
||||
winsetdump(win, dir, buf);
|
||||
}
|
||||
|
||||
int
|
||||
EQUAL(char *s, char *t)
|
||||
{
|
||||
while(tolower(*s) == tolower(*t++))
|
||||
if(*s++ == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
command(Window *w, char *s)
|
||||
{
|
||||
while(*s==' ' || *s=='\t' || *s=='\n')
|
||||
s++;
|
||||
if(strcmp(s, "Delete")==0){
|
||||
windel(w, 1);
|
||||
threadexitsall(nil);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(s, "Del")==0){
|
||||
if(windel(w, 0))
|
||||
threadexitsall(nil);
|
||||
return 1;
|
||||
}
|
||||
if(EQUAL(s, "scroll")){
|
||||
ctlprint(w->ctl, "scroll\nshow");
|
||||
return 1;
|
||||
}
|
||||
if(EQUAL(s, "noscroll")){
|
||||
ctlprint(w->ctl, "noscroll");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
utfncpy(char *to, char *from, int n)
|
||||
{
|
||||
char *end, *e;
|
||||
|
||||
e = to+n;
|
||||
if(to >= e)
|
||||
return 0;
|
||||
end = memccpy(to, from, '\0', e - to);
|
||||
if(end == nil){
|
||||
end = e;
|
||||
if(end[-1]&0x80){
|
||||
if(end-2>=to && (end[-2]&0xE0)==0xC0)
|
||||
return end-to;
|
||||
if(end-3>=to && (end[-3]&0xF0)==0xE0)
|
||||
return end-to;
|
||||
while(end>to && (*--end&0xC0)==0x80)
|
||||
;
|
||||
}
|
||||
}else
|
||||
end--;
|
||||
return end - to;
|
||||
}
|
||||
|
||||
/* sendinput and fsloop run in the same proc (can't interrupt each other). */
|
||||
static Req *q;
|
||||
static Req **eq;
|
||||
static int
|
||||
__sendinput(Window *w, ulong q0, ulong q1)
|
||||
{
|
||||
char *s, *t;
|
||||
int n, nb, eofchar;
|
||||
static int partial;
|
||||
static char tmp[UTFmax];
|
||||
Req *r;
|
||||
Rune rune;
|
||||
|
||||
if(!q)
|
||||
return 0;
|
||||
|
||||
r = q;
|
||||
n = 0;
|
||||
if(partial){
|
||||
Partial:
|
||||
nb = partial;
|
||||
if(nb > r->ifcall.count)
|
||||
nb = r->ifcall.count;
|
||||
memmove(r->ofcall.data, tmp, nb);
|
||||
if(nb!=partial)
|
||||
memmove(tmp, tmp+nb, partial-nb);
|
||||
partial -= nb;
|
||||
q = r->aux;
|
||||
if(q == nil)
|
||||
eq = &q;
|
||||
r->aux = nil;
|
||||
r->ofcall.count = nb;
|
||||
if(debug)
|
||||
fprint(2, "satisfy read with partial\n");
|
||||
respond(r, nil);
|
||||
return n;
|
||||
}
|
||||
if(q0==q1)
|
||||
return 0;
|
||||
s = emalloc((q1-q0)*UTFmax+1);
|
||||
n = winread(w, q0, q1, s);
|
||||
s[n] = '\0';
|
||||
t = strpbrk(s, "\n\004");
|
||||
if(t == nil){
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
r = q;
|
||||
eofchar = 0;
|
||||
if(*t == '\004'){
|
||||
eofchar = 1;
|
||||
*t = '\0';
|
||||
}else
|
||||
*++t = '\0';
|
||||
nb = utfncpy((char*)r->ofcall.data, s, r->ifcall.count);
|
||||
if(nb==0 && s<t && r->ifcall.count > 0){
|
||||
partial = utfncpy(tmp, s, UTFmax);
|
||||
assert(partial > 0);
|
||||
chartorune(&rune, tmp);
|
||||
partial = runelen(rune);
|
||||
free(s);
|
||||
n = 1;
|
||||
goto Partial;
|
||||
}
|
||||
n = utfnlen(r->ofcall.data, nb);
|
||||
if(nb==strlen(s) && eofchar)
|
||||
n++;
|
||||
r->ofcall.count = nb;
|
||||
q = r->aux;
|
||||
if(q == nil)
|
||||
eq = &q;
|
||||
r->aux = nil;
|
||||
if(debug)
|
||||
fprint(2, "read returns %lud-%lud: %.*q\n", q0, q0+n, n, r->ofcall.data);
|
||||
respond(r, nil);
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
_sendinput(Window *w, ulong q0, ulong *q1)
|
||||
{
|
||||
char buf[32];
|
||||
int n;
|
||||
|
||||
n = __sendinput(w, q0, *q1);
|
||||
if(!n || !eraseinput)
|
||||
return n;
|
||||
/* erase q0 to q0+n */
|
||||
sprint(buf, "#%lud,#%lud", q0, q0+n);
|
||||
winsetaddr(w, buf, 0);
|
||||
write(w->data, buf, 0);
|
||||
*q1 -= n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sendinput(Window *w, ulong q0, ulong *q1)
|
||||
{
|
||||
ulong n;
|
||||
Req *oq;
|
||||
|
||||
n = 0;
|
||||
do {
|
||||
oq = q;
|
||||
n += _sendinput(w, q0+n, q1);
|
||||
} while(q != oq);
|
||||
return n;
|
||||
}
|
||||
|
||||
Event esendinput;
|
||||
void
|
||||
fsloop(void*)
|
||||
{
|
||||
Fsevent e;
|
||||
Req **l, *r;
|
||||
|
||||
eq = &q;
|
||||
memset(&esendinput, 0, sizeof esendinput);
|
||||
esendinput.c1 = 'C';
|
||||
for(;;){
|
||||
while(recv(fschan, &e) == -1)
|
||||
;
|
||||
r = e.r;
|
||||
switch(e.type){
|
||||
case 'r':
|
||||
*eq = r;
|
||||
r->aux = nil;
|
||||
eq = &r->aux;
|
||||
/* call sendinput with hostpt and endpt */
|
||||
sendp(win->cevent, &esendinput);
|
||||
break;
|
||||
case 'f':
|
||||
for(l=&q; *l; l=&(*l)->aux){
|
||||
if(*l == r->oldreq){
|
||||
*l = (*l)->aux;
|
||||
if(*l == nil)
|
||||
eq = l;
|
||||
respond(r->oldreq, "interrupted");
|
||||
break;
|
||||
}
|
||||
}
|
||||
respond(r, nil);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sendit(char *s)
|
||||
{
|
||||
// char tmp[32];
|
||||
|
||||
write(win->body, s, strlen(s));
|
||||
/*
|
||||
* RSC: The problem here is that other procs can call sendit,
|
||||
* so we lose our single-threadedness if we call sendinput.
|
||||
* In fact, we don't even have the right queue memory,
|
||||
* I think that we'll get a write event from the body write above,
|
||||
* and we can do the sendinput then, from our single thread.
|
||||
*
|
||||
* I still need to figure out how to test this assertion for
|
||||
* programs that use /srv/win*
|
||||
*
|
||||
winselect(win, "$", 0);
|
||||
seek(win->addr, 0UL, 0);
|
||||
if(read(win->addr, tmp, 2*12) == 2*12)
|
||||
hostpt += sendinput(win, hostpt, atol(tmp), );
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
execevent(Window *w, Event *e, int (*command)(Window*, char*))
|
||||
{
|
||||
Event *ea, *e2;
|
||||
int n, na, len, needfree;
|
||||
char *s, *t;
|
||||
|
||||
ea = nil;
|
||||
e2 = nil;
|
||||
if(e->flag & 2)
|
||||
e2 = recvp(w->cevent);
|
||||
if(e->flag & 8){
|
||||
ea = recvp(w->cevent);
|
||||
na = ea->nb;
|
||||
recvp(w->cevent);
|
||||
}else
|
||||
na = 0;
|
||||
|
||||
needfree = 0;
|
||||
s = e->b;
|
||||
if(e->nb==0 && (e->flag&2)){
|
||||
s = e2->b;
|
||||
e->q0 = e2->q0;
|
||||
e->q1 = e2->q1;
|
||||
e->nb = e2->nb;
|
||||
}
|
||||
if(e->nb==0 && e->q0<e->q1){
|
||||
/* fetch data from window */
|
||||
s = emalloc((e->q1-e->q0)*UTFmax+2);
|
||||
n = winread(w, e->q0, e->q1, s);
|
||||
s[n] = '\0';
|
||||
needfree = 1;
|
||||
}else
|
||||
if(na){
|
||||
t = emalloc(strlen(s)+1+na+2);
|
||||
sprint(t, "%s %s", s, ea->b);
|
||||
if(needfree)
|
||||
free(s);
|
||||
s = t;
|
||||
needfree = 1;
|
||||
}
|
||||
|
||||
/* if it's a known command, do it */
|
||||
/* if it's a long message, it can't be for us anyway */
|
||||
if(!command(w, s) && s[0]!='\0'){ /* send it as typed text */
|
||||
/* if it's a built-in from the tag, send it back */
|
||||
if(e->flag & 1)
|
||||
fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
|
||||
else{ /* send text to main window */
|
||||
len = strlen(s);
|
||||
if(len>0 && s[len-1]!='\n' && s[len-1]!='\004'){
|
||||
if(!needfree){
|
||||
/* if(needfree), we left room for a newline before */
|
||||
t = emalloc(len+2);
|
||||
strcpy(t, s);
|
||||
s = t;
|
||||
needfree = 1;
|
||||
}
|
||||
s[len++] = '\n';
|
||||
s[len] = '\0';
|
||||
}
|
||||
sendit(s);
|
||||
}
|
||||
}
|
||||
if(needfree)
|
||||
free(s);
|
||||
}
|
||||
|
||||
int
|
||||
hasboundary(Rune *r, int nr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nr; i++)
|
||||
if(r[i]=='\n' || r[i]=='\004')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mainctl(void *v)
|
||||
{
|
||||
Window *w;
|
||||
Event *e;
|
||||
int delta, pendingS, pendingK;
|
||||
ulong hostpt, endpt;
|
||||
char tmp[32];
|
||||
|
||||
w = v;
|
||||
proccreate(wineventproc, w, STACK);
|
||||
|
||||
hostpt = 0;
|
||||
endpt = 0;
|
||||
winsetaddr(w, "0", 0);
|
||||
pendingS = 0;
|
||||
pendingK = 0;
|
||||
for(;;){
|
||||
if(debug)
|
||||
fprint(2, "input range %lud-%lud\n", hostpt, endpt);
|
||||
e = recvp(w->cevent);
|
||||
if(debug)
|
||||
fprint(2, "msg: %C %C %d %d %d %d %q\n",
|
||||
e->c1 ? e->c1 : ' ', e->c2 ? e->c2 : ' ', e->q0, e->q1, e->flag, e->nb, e->b);
|
||||
switch(e->c1){
|
||||
default:
|
||||
Unknown:
|
||||
fprint(2, "unknown message %c%c\n", e->c1, e->c2);
|
||||
break;
|
||||
|
||||
case 'C': /* input needed for /dev/cons */
|
||||
if(pendingS)
|
||||
pendingK = 1;
|
||||
else
|
||||
hostpt += sendinput(w, hostpt, &endpt);
|
||||
break;
|
||||
|
||||
case 'S': /* output to stdout */
|
||||
sprint(tmp, "#%lud", hostpt);
|
||||
winsetaddr(w, tmp, 0);
|
||||
write(w->data, e->b, e->nb);
|
||||
pendingS += utfnlen(e->b, e->nb);
|
||||
break;
|
||||
|
||||
case 'E': /* write to tag or body; body happens due to sendit */
|
||||
delta = e->q1-e->q0;
|
||||
if(e->c2=='I'){
|
||||
endpt += delta;
|
||||
if(e->q0 < hostpt)
|
||||
hostpt += delta;
|
||||
else
|
||||
hostpt += sendinput(w, hostpt, &endpt);
|
||||
break;
|
||||
}
|
||||
if(!islower(e->c2))
|
||||
fprint(2, "win msg: %C %C %d %d %d %d %q\n",
|
||||
e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b);
|
||||
break;
|
||||
|
||||
case 'F': /* generated by our actions (specifically case 'S' above) */
|
||||
delta = e->q1-e->q0;
|
||||
if(e->c2=='D'){
|
||||
/* we know about the delete by _sendinput */
|
||||
break;
|
||||
}
|
||||
if(e->c2=='I'){
|
||||
pendingS -= e->q1 - e->q0;
|
||||
if(pendingS < 0)
|
||||
fprint(2, "win: pendingS = %d\n", pendingS);
|
||||
if(e->q0 != hostpt)
|
||||
fprint(2, "win: insert at %d expected %lud\n", e->q0, hostpt);
|
||||
endpt += delta;
|
||||
hostpt += delta;
|
||||
sendp(writechan, nil);
|
||||
if(pendingS == 0 && pendingK){
|
||||
pendingK = 0;
|
||||
hostpt += sendinput(w, hostpt, &endpt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!islower(e->c2))
|
||||
fprint(2, "win msg: %C %C %d %d %d %d %q\n",
|
||||
e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b);
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
delta = e->q1-e->q0;
|
||||
switch(e->c2){
|
||||
case 'D':
|
||||
endpt -= delta;
|
||||
if(e->q1 < hostpt)
|
||||
hostpt -= delta;
|
||||
else if(e->q0 < hostpt)
|
||||
hostpt = e->q0;
|
||||
break;
|
||||
case 'I':
|
||||
delta = e->q1 - e->q0;
|
||||
endpt += delta;
|
||||
if(endpt < e->q1) /* just in case */
|
||||
endpt = e->q1;
|
||||
if(e->q0 < hostpt)
|
||||
hostpt += delta;
|
||||
if(e->nr>0 && e->r[e->nr-1]==0x7F){
|
||||
write(notepg, "interrupt", 9);
|
||||
hostpt = endpt;
|
||||
break;
|
||||
}
|
||||
if(e->q0 >= hostpt
|
||||
&& hasboundary(e->r, e->nr)){
|
||||
/*
|
||||
* If we are between the S message (which
|
||||
* we processed by inserting text in the
|
||||
* window) and the F message notifying us
|
||||
* that the text has been inserted, then our
|
||||
* impression of the hostpt and acme's
|
||||
* may be different. This could be seen if you
|
||||
* hit enter a bunch of times in a con
|
||||
* session. To work around the unreliability,
|
||||
* only send input if we don't have an S pending.
|
||||
* The same race occurs between when a character
|
||||
* is typed and when we get notice of it, but
|
||||
* since characters tend to be typed at the end
|
||||
* of the buffer, we don't run into it. There's
|
||||
* no workaround possible for this typing race,
|
||||
* since we can't tell when the user has typed
|
||||
* something but we just haven't been notified.
|
||||
*/
|
||||
if(pendingS)
|
||||
pendingK = 1;
|
||||
else
|
||||
hostpt += sendinput(w, hostpt, &endpt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M': /* mouse */
|
||||
delta = e->q1-e->q0;
|
||||
switch(e->c2){
|
||||
case 'x':
|
||||
case 'X':
|
||||
execevent(w, e, command);
|
||||
break;
|
||||
|
||||
case 'l': /* reflect all searches back to acme */
|
||||
case 'L':
|
||||
if(e->flag & 2)
|
||||
recvp(w->cevent);
|
||||
winwriteevent(w, e);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
endpt += delta;
|
||||
if(e->q0 < hostpt)
|
||||
hostpt += delta;
|
||||
else
|
||||
hostpt += sendinput(w, hostpt, &endpt);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
endpt -= delta;
|
||||
if(e->q1 < hostpt)
|
||||
hostpt -= delta;
|
||||
else if(e->q0 < hostpt)
|
||||
hostpt = e->q0;
|
||||
break;
|
||||
case 'd': /* modify away; we don't care */
|
||||
case 'i':
|
||||
break;
|
||||
|
||||
default:
|
||||
goto Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
NARGS = 100,
|
||||
NARGCHAR = 8*1024,
|
||||
EXECSTACK = STACK+(NARGS+1)*sizeof(char*)+NARGCHAR
|
||||
};
|
||||
|
||||
struct Exec
|
||||
{
|
||||
char **argv;
|
||||
Channel *cpid;
|
||||
};
|
||||
|
||||
int
|
||||
lookinbin(char *s)
|
||||
{
|
||||
if(s[0] == '/')
|
||||
return 0;
|
||||
if(s[0]=='.' && s[1]=='/')
|
||||
return 0;
|
||||
if(s[0]=='.' && s[1]=='.' && s[2]=='/')
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* adapted from mail. not entirely free of details from that environment */
|
||||
void
|
||||
execproc(void *v)
|
||||
{
|
||||
struct Exec *e;
|
||||
char *cmd, **av;
|
||||
Channel *cpid;
|
||||
|
||||
e = v;
|
||||
rfork(RFCFDG|RFNOTEG);
|
||||
av = e->argv;
|
||||
close(0);
|
||||
open("/dev/cons", OREAD);
|
||||
close(1);
|
||||
open("/dev/cons", OWRITE);
|
||||
dup(1, 2);
|
||||
cpid = e->cpid;
|
||||
free(e);
|
||||
procexec(cpid, av[0], av);
|
||||
if(lookinbin(av[0])){
|
||||
cmd = estrstrdup("/bin/", av[0]);
|
||||
procexec(cpid, cmd, av);
|
||||
}
|
||||
error("can't exec %s: %r", av[0]);
|
||||
}
|
||||
|
||||
void
|
||||
startcmd(char *argv[], int *notepg)
|
||||
{
|
||||
struct Exec *e;
|
||||
Channel *cpid;
|
||||
char buf[64];
|
||||
int pid;
|
||||
|
||||
e = emalloc(sizeof(struct Exec));
|
||||
e->argv = argv;
|
||||
cpid = chancreate(sizeof(ulong), 0);
|
||||
e->cpid = cpid;
|
||||
sprint(buf, "/mnt/wsys/%d", win->id);
|
||||
bind(buf, "/dev/acme", MREPL);
|
||||
proccreate(execproc, e, EXECSTACK);
|
||||
do
|
||||
pid = recvul(cpid);
|
||||
while(pid == -1);
|
||||
sprint(buf, "/proc/%d/notepg", pid);
|
||||
*notepg = open(buf, OWRITE);
|
||||
}
|
Loading…
Reference in a new issue