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