Blob


1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <errno.h>
5 #include <u.h>
6 #include <libc.h>
7 #include <draw.h>
8 #include <thread.h>
9 #include <mouse.h>
10 #include <cursor.h>
11 #include <keyboard.h>
12 #include <frame.h>
13 #include <plumb.h>
14 #include "flayer.h"
15 #include "samterm.h"
17 static char *exname;
19 #define STACK 16384
21 void
22 getscreen(int argc, char **argv)
23 {
24 char *t;
26 USED(argc);
27 USED(argv);
28 if(initdraw(panic1, nil, "sam") < 0){
29 fprint(2, "samterm: initdraw: %r\n");
30 threadexitsall("init");
31 }
32 t = getenv("tabstop");
33 if(t != nil)
34 maxtab = strtoul(t, nil, 0);
35 draw(screen, screen->clipr, display->white, nil, ZP);
36 }
38 int
39 screensize(int *w, int *h)
40 {
41 int fd, n;
42 char buf[5*12+1];
44 fd = open("/dev/screen", OREAD);
45 if(fd < 0)
46 return 0;
47 n = read(fd, buf, sizeof(buf)-1);
48 close(fd);
49 if (n != sizeof(buf)-1)
50 return 0;
51 buf[n] = 0;
52 if (h) {
53 *h = atoi(buf+4*12)-atoi(buf+2*12);
54 if (*h < 0)
55 return 0;
56 }
57 if (w) {
58 *w = atoi(buf+3*12)-atoi(buf+1*12);
59 if (*w < 0)
60 return 0;
61 }
62 return 1;
63 }
65 int
66 snarfswap(char *fromsam, int nc, char **tosam)
67 {
68 char *s;
70 s = getsnarf();
71 putsnarf(fromsam);
72 *tosam = s;
73 return s ? strlen(s) : 0;
74 }
76 void
77 dumperrmsg(int count, int type, int count0, int c)
78 {
79 fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n",
80 count, type, count0, c, rcvstring());
81 }
83 void
84 removeextern(void)
85 {
86 remove(exname);
87 }
89 Readbuf hostbuf[2];
90 Readbuf plumbbuf[2];
92 void
93 extproc(void *argv)
94 {
95 Channel *c;
96 int i, n, which, fd;
97 void **arg;
99 arg = argv;
100 c = arg[0];
101 fd = (int)arg[1];
103 threadfdnoblock(fd);
104 i = 0;
105 for(;;){
106 i = 1-i; /* toggle */
107 n = threadread(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
108 if(n <= 0){
109 fprint(2, "samterm: extern read error: %r\n");
110 threadexits("extern"); /* not a fatal error */
112 plumbbuf[i].n = n;
113 which = i;
114 send(c, &which);
118 void
119 extstart(void)
121 char *user, *disp;
122 int fd, flags;
123 static void *arg[2];
125 user = getenv("USER");
126 if(user == nil)
127 return;
128 disp = getenv("DISPLAY");
129 if(disp)
130 exname = smprint("/tmp/.sam.%s.%s", user, disp);
131 else
132 exname = smprint("/tmp/.sam.%s", user);
133 if(exname == nil){
134 fprint(2, "not posting for B: out of memory\n");
135 return;
138 if(mkfifo(exname, 0600) < 0){
139 struct stat st;
140 if(errno != EEXIST || stat(exname, &st) < 0)
141 return;
142 if(!S_ISFIFO(st.st_mode)){
143 removeextern();
144 if(mkfifo(exname, 0600) < 0)
145 return;
149 fd = open(exname, OREAD|O_NONBLOCK);
150 if(fd == -1){
151 removeextern();
152 return;
155 /*
156 * Turn off no-delay and provide ourselves as a lingering
157 * writer so as not to get end of file on read.
158 */
159 flags = fcntl(fd, F_GETFL, 0);
160 if(flags<0 || fcntl(fd, F_SETFL, flags&~O_NONBLOCK)<0
161 ||open(exname, OWRITE) < 0){
162 close(fd);
163 removeextern();
164 return;
167 plumbc = chancreate(sizeof(int), 0);
168 arg[0] = plumbc;
169 arg[1] = (void*)fd;
170 threadcreate(extproc, arg, STACK);
171 atexit(removeextern);
174 int
175 plumbformat(Plumbmsg *m, int i)
177 char *addr, *data, *act;
178 int n;
180 data = (char*)plumbbuf[i].data;
181 n = m->ndata;
182 if(n == 0 || 2+n+2 >= READBUFSIZE){
183 plumbfree(m);
184 return 0;
186 act = plumblookup(m->attr, "action");
187 if(act!=nil && strcmp(act, "showfile")!=0){
188 /* can't handle other cases yet */
189 plumbfree(m);
190 return 0;
192 addr = plumblookup(m->attr, "addr");
193 if(addr){
194 if(addr[0] == '\0')
195 addr = nil;
196 else
197 addr = strdup(addr); /* copy to safe storage; we'll overwrite data */
199 memmove(data, "B ", 2); /* we know there's enough room for this */
200 memmove(data+2, m->data, n);
201 n += 2;
202 if(data[n-1] != '\n')
203 data[n++] = '\n';
204 if(addr != nil){
205 if(n+strlen(addr)+1+1 <= READBUFSIZE)
206 n += sprint(data+n, "%s\n", addr);
207 free(addr);
209 plumbbuf[i].n = n;
210 plumbfree(m);
211 return 1;
214 void
215 plumbproc(void *argv)
217 Channel *c;
218 int i, *fdp;
219 void **arg;
220 Plumbmsg *m;
222 arg = argv;
223 c = arg[0];
224 fdp = arg[1];
226 i = 0;
227 threadfdnoblock(*fdp);
228 for(;;){
229 m = threadplumbrecv(*fdp);
230 if(m == nil){
231 fprint(2, "samterm: plumb read error: %r\n");
232 threadexits("plumb"); /* not a fatal error */
234 if(plumbformat(m, i)){
235 send(c, &i);
236 i = 1-i; /* toggle */
241 int
242 plumbstart(void)
244 static int fd;
245 static void *arg[2];
247 plumbfd = plumbopen("send", OWRITE|OCEXEC); /* not open is ok */
248 fd = plumbopen("edit", OREAD|OCEXEC);
249 if(fd < 0)
250 return -1;
251 plumbc = chancreate(sizeof(int), 0);
252 if(plumbc == nil){
253 close(fd);
254 return -1;
256 arg[0] = plumbc;
257 arg[1] = &fd;
258 threadcreate(plumbproc, arg, STACK);
259 return 1;
262 void
263 hostproc(void *arg)
265 Channel *c;
266 int i, n, which;
268 c = arg;
270 i = 0;
271 threadfdnoblock(hostfd[0]);
272 for(;;){
273 i = 1-i; /* toggle */
274 n = threadread(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
275 if(n <= 0){
276 fprint(2, "samterm: host read error: %r\n");
277 threadexitsall("host");
279 hostbuf[i].n = n;
280 which = i;
281 send(c, &which);
285 void
286 hoststart(void)
288 hostc = chancreate(sizeof(int), 0);
289 threadcreate(hostproc, hostc, STACK);