e1cdcfdb17
split the acme win command into a winfs fileserver which handles /dev/cons emulation and a rc script responsible for launching the command. with these changes, the fd fiddling is not neccesary anymore and we can get rid of the leavefdsopen hack.
175 lines
2.7 KiB
C
175 lines
2.7 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <fcall.h>
|
|
#include <thread.h>
|
|
#include <9p.h>
|
|
#include "dat.h"
|
|
|
|
typedef struct Wpid Wpid;
|
|
struct Wpid
|
|
{
|
|
int pid;
|
|
Window *w;
|
|
Wpid *next;
|
|
};
|
|
|
|
void pipectl(void*);
|
|
|
|
int pipefd;
|
|
Wpid *wpid;
|
|
int snarffd = -1;
|
|
Channel *newpipechan;
|
|
|
|
int
|
|
newpipewin(int pid, char *p)
|
|
{
|
|
int id;
|
|
Window *w;
|
|
Wpid *wp;
|
|
|
|
w = newwindow();
|
|
winname(w, p);
|
|
wintagwrite(w, "Send ", 5);
|
|
wp = emalloc(sizeof(Wpid));
|
|
wp->pid = pid;
|
|
wp->w = w;
|
|
wp->next = wpid; /* BUG: this happens in fsread proc (we don't use wpid, so it's okay) */
|
|
wpid = wp;
|
|
id = w->id;
|
|
sendp(newpipechan, w);
|
|
return id;
|
|
}
|
|
|
|
int
|
|
pipecommand(Window *w, char *s)
|
|
{
|
|
ulong q0, q1;
|
|
char tmp[32], *t;
|
|
int n, k;
|
|
|
|
while(*s==' ' || *s=='\t' || *s=='\n')
|
|
s++;
|
|
if(strcmp(s, "Delete")==0){
|
|
windel(w, 1);
|
|
threadexits(nil);
|
|
return 1;
|
|
}
|
|
if(strcmp(s, "Del")==0){
|
|
if(windel(w, 0))
|
|
threadexits(nil);
|
|
return 1;
|
|
}
|
|
if(strcmp(s, "Send") == 0){
|
|
if(w->addr < 0)
|
|
w->addr = winopenfile(w, "addr");
|
|
ctlprint(w->ctl, "addr=dot\n");
|
|
seek(w->addr, 0UL, 0);
|
|
if(read(w->addr, tmp, 2*12) == 2*12){
|
|
q0 = atol(tmp+0*12);
|
|
q1 = atol(tmp+1*12);
|
|
if(q0 == q1){
|
|
t = nil;
|
|
k = 0;
|
|
if(snarffd >= 0){
|
|
seek(0, snarffd, 0);
|
|
for(;;){
|
|
t = realloc(t, k+8192+2);
|
|
if(t == nil)
|
|
error("alloc failed: %r\n");
|
|
n = read(snarffd, t+k, 8192);
|
|
if(n <= 0)
|
|
break;
|
|
k += n;
|
|
}
|
|
t[k] = 0;
|
|
}
|
|
}else{
|
|
t = emalloc((q1-q0)*UTFmax+2);
|
|
winread(w, q0, q1, t);
|
|
k = strlen(t);
|
|
}
|
|
if(t!=nil && t[0]!='\0'){
|
|
if(t[k-1]!='\n' && t[k-1]!='\004'){
|
|
t[k++] = '\n';
|
|
t[k] = '\0';
|
|
}
|
|
sendit(t);
|
|
}
|
|
free(t);
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
pipectl(void *v)
|
|
{
|
|
Window *w;
|
|
Event *e;
|
|
|
|
w = v;
|
|
proccreate(wineventproc, w, STACK);
|
|
|
|
windormant(w);
|
|
winsetaddr(w, "0", 0);
|
|
for(;;){
|
|
e = recvp(w->cevent);
|
|
switch(e->c1){
|
|
default:
|
|
Unknown:
|
|
fprint(2, "unknown message %c%c\n", e->c1, e->c2);
|
|
break;
|
|
|
|
case 'E': /* write to body; can't affect us */
|
|
break;
|
|
|
|
case 'F': /* generated by our actions; ignore */
|
|
break;
|
|
|
|
case 'K': /* ignore */
|
|
break;
|
|
|
|
case 'M':
|
|
switch(e->c2){
|
|
case 'x':
|
|
case 'X':
|
|
execevent(w, e, pipecommand);
|
|
break;
|
|
|
|
case 'l': /* reflect all searches back to acme */
|
|
case 'L':
|
|
if(e->flag & 2)
|
|
recvp(w->cevent);
|
|
winwriteevent(w, e);
|
|
break;
|
|
|
|
case 'I': /* modify away; we don't care */
|
|
case 'i':
|
|
case 'D':
|
|
case 'd':
|
|
break;
|
|
|
|
default:
|
|
goto Unknown;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
newpipethread(void*)
|
|
{
|
|
Window *w;
|
|
|
|
while(w = recvp(newpipechan))
|
|
threadcreate(pipectl, w, STACK);
|
|
}
|
|
|
|
void
|
|
startpipe(void)
|
|
{
|
|
newpipechan = chancreate(sizeof(Window*), 0);
|
|
threadcreate(newpipethread, nil, STACK);
|
|
snarffd = open("/dev/snarf", OREAD|OCEXEC);
|
|
}
|