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
newpipewin(int pid,char * p)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
pipecommand(Window * w,char * s)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
pipectl(void * v)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
newpipethread(void *)161 newpipethread(void*)
162 {
163 Window *w;
164
165 while(w = recvp(newpipechan))
166 threadcreate(pipectl, w, STACK);
167 }
168
169 void
startpipe(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