xref: /plan9/acme/bin/source/win/pipe.c (revision afb30c3eb94b92629560c385d0152410d412fdfb)
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