1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 #include "dat.h" 7 8 typedef struct Wpid Wpid; 9 struct Wpid 10 { 11 int pid; 12 Window *w; 13 Wpid *next; 14 }; 15 16 void pipectl(void*); 17 18 int pipefd; 19 Wpid *wpid; 20 int snarffd; 21 Channel *newpipechan; 22 23 int 24 newpipewin(int pid, char *p) 25 { 26 int id; 27 Window *w; 28 Wpid *wp; 29 30 w = newwindow(); 31 winname(w, p); 32 wintagwrite(w, "Send ", 5); 33 wp = emalloc(sizeof(Wpid)); 34 wp->pid = pid; 35 wp->w = w; 36 wp->next = wpid; /* BUG: this happens in fsread proc (we don't use wpid, so it's okay) */ 37 wpid = wp; 38 id = w->id; 39 sendp(newpipechan, w); 40 return id; 41 } 42 43 int 44 pipecommand(Window *w, char *s) 45 { 46 ulong q0, q1; 47 char tmp[32], *t; 48 int n, k; 49 50 while(*s==' ' || *s=='\t' || *s=='\n') 51 s++; 52 if(strcmp(s, "Delete")==0){ 53 windel(w, 1); 54 threadexits(nil); 55 return 1; 56 } 57 if(strcmp(s, "Del")==0){ 58 if(windel(w, 0)) 59 threadexits(nil); 60 return 1; 61 } 62 if(strcmp(s, "Send") == 0){ 63 if(w->addr < 0) 64 w->addr = winopenfile(w, "addr"); 65 ctlprint(w->ctl, "addr=dot\n"); 66 seek(w->addr, 0UL, 0); 67 if(read(w->addr, tmp, 2*12) == 2*12){ 68 q0 = atol(tmp+0*12); 69 q1 = atol(tmp+1*12); 70 if(q0 == q1){ 71 t = nil; 72 k = 0; 73 if(snarffd > 0){ 74 seek(0, snarffd, 0); 75 for(;;){ 76 t = realloc(t, k+8192+2); 77 if(t == nil) 78 error("alloc failed: %r\n"); 79 n = read(snarffd, t+k, 8192); 80 if(n <= 0) 81 break; 82 k += n; 83 } 84 t[k] = 0; 85 } 86 }else{ 87 t = emalloc((q1-q0)*UTFmax+2); 88 winread(w, q0, q1, t); 89 k = strlen(t); 90 } 91 if(t!=nil && t[0]!='\0'){ 92 if(t[k-1]!='\n' && t[k-1]!='\004'){ 93 t[k++] = '\n'; 94 t[k] = '\0'; 95 } 96 sendit(t); 97 } 98 free(t); 99 } 100 return 1; 101 } 102 return 0; 103 } 104 105 void 106 pipectl(void *v) 107 { 108 Window *w; 109 Event *e; 110 111 w = v; 112 proccreate(wineventproc, w, STACK); 113 114 windormant(w); 115 winsetaddr(w, "0", 0); 116 for(;;){ 117 e = recvp(w->cevent); 118 switch(e->c1){ 119 default: 120 Unknown: 121 fprint(2, "unknown message %c%c\n", e->c1, e->c2); 122 break; 123 124 case 'E': /* write to body; can't affect us */ 125 break; 126 127 case 'F': /* generated by our actions; ignore */ 128 break; 129 130 case 'K': /* ignore */ 131 break; 132 133 case 'M': 134 switch(e->c2){ 135 case 'x': 136 case 'X': 137 execevent(w, e, pipecommand); 138 break; 139 140 case 'l': /* reflect all searches back to acme */ 141 case 'L': 142 if(e->flag & 2) 143 recvp(w->cevent); 144 winwriteevent(w, e); 145 break; 146 147 case 'I': /* modify away; we don't care */ 148 case 'i': 149 case 'D': 150 case 'd': 151 break; 152 153 default: 154 goto Unknown; 155 } 156 } 157 } 158 } 159 160 void 161 newpipethread(void*) 162 { 163 Window *w; 164 165 while(w = recvp(newpipechan)) 166 threadcreate(pipectl, w, STACK); 167 } 168 169 void 170 startpipe(void) 171 { 172 newpipechan = chancreate(sizeof(Window*), 0); 173 threadcreate(newpipethread, nil, STACK); 174 snarffd = open("/dev/snarf", OREAD|OCEXEC); 175 } 176