diff options
Diffstat (limited to 'acme/bin/source/win/pipe.c')
-rw-r--r-- | acme/bin/source/win/pipe.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/acme/bin/source/win/pipe.c b/acme/bin/source/win/pipe.c new file mode 100644 index 000000000..280f726c9 --- /dev/null +++ b/acme/bin/source/win/pipe.c @@ -0,0 +1,175 @@ +#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; +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); +} |