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