xref: /plan9/sys/src/cmd/samterm/plan9.c (revision 6b8bc68243dff965faa99f64fe710965ebee6f8f)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <keyboard.h>
7 #include <frame.h>
8 #include <plumb.h>
9 #include "flayer.h"
10 #include "samterm.h"
11 
12 static char exname[64];
13 
14 void
15 getscreen(int argc, char **argv)
16 {
17 	char *t;
18 
19 	USED(argc);
20 	USED(argv);
21 	if(initdraw(panic1, nil, "sam") < 0){
22 		fprint(2, "samterm: initimage: %r\n");
23 		threadexitsall("init");
24 	}
25 	t = getenv("tabstop");
26 	if(t != nil)
27 		maxtab = strtoul(t, nil, 0);
28 	draw(screen, screen->clipr, display->white, nil, ZP);
29 }
30 
31 int
32 screensize(int *w, int *h)
33 {
34 	int fd, n;
35 	char buf[5*12+1];
36 
37 	fd = open("/dev/screen", OREAD);
38 	if(fd < 0)
39 		return 0;
40 	n = read(fd, buf, sizeof(buf)-1);
41 	close(fd);
42 	if (n != sizeof(buf)-1)
43 		return 0;
44 	buf[n] = 0;
45 	if (h) {
46 		*h = atoi(buf+4*12)-atoi(buf+2*12);
47 		if (*h < 0)
48 			return 0;
49 	}
50 	if (w) {
51 		*w = atoi(buf+3*12)-atoi(buf+1*12);
52 		if (*w < 0)
53 			return 0;
54 	}
55 	return 1;
56 }
57 
58 int
59 snarfswap(char *fromsam, int nc, char **tosam)
60 {
61 	char *s1;
62 	int f, n, ss;
63 
64 	f = open("/dev/snarf", 0);
65 	if(f < 0)
66 		return -1;
67 	ss = SNARFSIZE;
68 	if(hversion < 2)
69 		ss = 4096;
70 	*tosam = s1 = alloc(ss);
71 	n = read(f, s1, ss-1);
72 	close(f);
73 	if(n < 0)
74 		n = 0;
75 	if (n == 0) {
76 		*tosam = 0;
77 		free(s1);
78 	} else
79 		s1[n] = 0;
80 	f = create("/dev/snarf", 1, 0666);
81 	if(f >= 0){
82 		write(f, fromsam, nc);
83 		close(f);
84 	}
85 	return n;
86 }
87 
88 void
89 dumperrmsg(int count, int type, int count0, int c)
90 {
91 	fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n",
92 		count, type, count0, c, rcvstring());
93 }
94 
95 void
96 removeextern(void)
97 {
98 	remove(exname);
99 }
100 
101 Readbuf	hostbuf[2];
102 Readbuf	plumbbuf[2];
103 
104 void
105 extproc(void *argv)
106 {
107 	Channel *c;
108 	int i, n, which, *fdp;
109 	void **arg;
110 
111 	arg = argv;
112 	c = arg[0];
113 	fdp = arg[1];
114 
115 	i = 0;
116 	for(;;){
117 		i = 1-i;	/* toggle */
118 		n = read(*fdp, plumbbuf[i].data, sizeof plumbbuf[i].data);
119 		if(n <= 0){
120 			fprint(2, "samterm: extern read error: %r\n");
121 			threadexits("extern");	/* not a fatal error */
122 		}
123 		plumbbuf[i].n = n;
124 		which = i;
125 		send(c, &which);
126 	}
127 }
128 
129 void
130 extstart(void)
131 {
132 	char buf[32];
133 	int fd;
134 	static int p[2];
135 	static void *arg[2];
136 
137 	if(pipe(p) < 0)
138 		return;
139 	sprint(exname, "/srv/sam.%s", getuser());
140 	fd = create(exname, 1, 0600);
141 	if(fd < 0){	/* assume existing guy is more important */
142     Err:
143 		close(p[0]);
144 		close(p[1]);
145 		return;
146 	}
147 	sprint(buf, "%d", p[0]);
148 	if(write(fd, buf, strlen(buf)) <= 0)
149 		goto Err;
150 	close(fd);
151 	/*
152 	 * leave p[0] open so if the file is removed the event
153 	 * library won't get an error
154 	 */
155 	plumbc = chancreate(sizeof(int), 0);
156 	arg[0] = plumbc;
157 	arg[1] = &p[1];
158 	proccreate(extproc, arg, 1024);
159 	atexit(removeextern);
160 }
161 
162 int
163 plumbformat(int i)
164 {
165 	Plumbmsg *m;
166 	char *addr, *data, *act;
167 	int n;
168 
169 	data = (char*)plumbbuf[i].data;
170 	m = plumbunpack(data, plumbbuf[i].n);
171 	if(m == nil)
172 		return 0;
173 	n = m->ndata;
174 	if(n == 0){
175 		plumbfree(m);
176 		return 0;
177 	}
178 	act = plumblookup(m->attr, "action");
179 	if(act!=nil && strcmp(act, "showfile")!=0){
180 		/* can't handle other cases yet */
181 		plumbfree(m);
182 		return 0;
183 	}
184 	addr = plumblookup(m->attr, "addr");
185 	if(addr){
186 		if(addr[0] == '\0')
187 			addr = nil;
188 		else
189 			addr = strdup(addr);	/* copy to safe storage; we'll overwrite data */
190 	}
191 	memmove(data, "B ", 2);	/* we know there's enough room for this */
192 	memmove(data+2, m->data, n);
193 	n += 2;
194 	if(data[n-1] != '\n')
195 		data[n++] = '\n';
196 	if(addr != nil){
197 		if(n+strlen(addr)+1+1 <= READBUFSIZE)
198 			n += sprint(data+n, "%s\n", addr);
199 		free(addr);
200 	}
201 	plumbbuf[i].n = n;
202 	plumbfree(m);
203 	return 1;
204 }
205 
206 void
207 plumbproc(void *argv)
208 {
209 	Channel *c;
210 	int i, n, which, *fdp;
211 	void **arg;
212 
213 	arg = argv;
214 	c = arg[0];
215 	fdp = arg[1];
216 
217 	i = 0;
218 	for(;;){
219 		i = 1-i;	/* toggle */
220 		n = read(*fdp, plumbbuf[i].data, READBUFSIZE);
221 		if(n <= 0){
222 			fprint(2, "samterm: plumb read error: %r\n");
223 			threadexits("plumb");	/* not a fatal error */
224 		}
225 		plumbbuf[i].n = n;
226 		if(plumbformat(i)){
227 			which = i;
228 			send(c, &which);
229 		}
230 	}
231 }
232 
233 int
234 plumbstart(void)
235 {
236 	static int fd;
237 	static void *arg[2];
238 
239 	plumbfd = plumbopen("send", OWRITE|OCEXEC);	/* not open is ok */
240 	fd = plumbopen("edit", OREAD|OCEXEC);
241 	if(fd < 0)
242 		return -1;
243 	plumbc = chancreate(sizeof(int), 0);
244 	if(plumbc == nil){
245 		close(fd);
246 		return -1;
247 	}
248 	arg[0] =plumbc;
249 	arg[1] = &fd;
250 	proccreate(plumbproc, arg, 4096);
251 	return 1;
252 }
253 
254 void
255 hostproc(void *arg)
256 {
257 	Channel *c;
258 	int i, n, which;
259 
260 	c = arg;
261 
262 	i = 0;
263 	for(;;){
264 		i = 1-i;	/* toggle */
265 		n = read(0, hostbuf[i].data, sizeof hostbuf[i].data);
266 		if(n <= 0){
267 			if(n==0){
268 				if(exiting)
269 					threadexits(nil);
270 				werrstr("unexpected eof");
271 			}
272 			fprint(2, "samterm: host read error: %r\n");
273 			threadexitsall("host");
274 		}
275 		hostbuf[i].n = n;
276 		which = i;
277 		send(c, &which);
278 	}
279 }
280 
281 void
282 hoststart(void)
283 {
284 	hostc = chancreate(sizeof(int), 0);
285 	proccreate(hostproc, hostc, 1024);
286 }
287