Blob


1 #include <u.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <errno.h>
6 #include <u.h>
7 #include <libc.h>
8 #include <draw.h>
9 #include <thread.h>
10 #include <mouse.h>
11 #include <cursor.h>
12 #include <keyboard.h>
13 #include <frame.h>
14 #define Tversion Tversion9p
15 #define Twrite Twrite9p
16 #include <fcall.h>
17 #undef Tversion
18 #undef Twrite
19 #include <9pclient.h>
20 #include <plumb.h>
21 #include "flayer.h"
22 #include "samterm.h"
24 static char *exname;
26 #define STACK 16384
28 void
29 getscreen(int argc, char **argv)
30 {
31 int i;
32 char *t;
34 /* not exactly right */
35 for(i=0; i<argc-1; i++){
36 if(strcmp(argv[i], "-W") == 0)
37 winsize = argv[i+1];
38 }
40 if(initdraw(panic1, nil, "sam") < 0){
41 fprint(2, "samterm: initdraw: %r\n");
42 threadexitsall("init");
43 }
44 t = getenv("tabstop");
45 if(t != nil)
46 maxtab = strtoul(t, nil, 0);
47 draw(screen, screen->clipr, display->white, nil, ZP);
48 }
50 int
51 screensize(int *w, int *h)
52 {
53 int fd, n;
54 char buf[5*12+1];
56 fd = open("/dev/screen", OREAD);
57 if(fd < 0)
58 return 0;
59 n = read(fd, buf, sizeof(buf)-1);
60 close(fd);
61 if (n != sizeof(buf)-1)
62 return 0;
63 buf[n] = 0;
64 if (h) {
65 *h = atoi(buf+4*12)-atoi(buf+2*12);
66 if (*h < 0)
67 return 0;
68 }
69 if (w) {
70 *w = atoi(buf+3*12)-atoi(buf+1*12);
71 if (*w < 0)
72 return 0;
73 }
74 return 1;
75 }
77 int
78 snarfswap(char *fromsam, int nc, char **tosam)
79 {
80 char *s;
82 s = getsnarf();
83 putsnarf(fromsam);
84 *tosam = s;
85 return s ? strlen(s) : 0;
86 }
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 }
95 void
96 removeextern(void)
97 {
98 remove(exname);
99 }
101 Readbuf hostbuf[2];
102 Readbuf plumbbuf[2];
104 void
105 extproc(void *argv)
107 Channel *c;
108 int i, n, which, fd;
109 void **arg;
111 arg = argv;
112 c = arg[0];
113 fd = (int)arg[1];
115 i = 0;
116 for(;;){
117 i = 1-i; /* toggle */
118 n = read(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
119 if(0) fprint(2, "ext %d\n", n);
120 if(n <= 0){
121 fprint(2, "samterm: extern read error: %r\n");
122 threadexits("extern"); /* not a fatal error */
124 plumbbuf[i].n = n;
125 which = i;
126 send(c, &which);
130 void
131 extstart(void)
133 char *user, *disp;
134 int fd, flags;
135 static void *arg[2];
137 user = getenv("USER");
138 if(user == nil)
139 return;
140 disp = getenv("DISPLAY");
141 if(disp)
142 exname = smprint("/tmp/.sam.%s.%s", user, disp);
143 else
144 exname = smprint("/tmp/.sam.%s", user);
145 if(exname == nil){
146 fprint(2, "not posting for B: out of memory\n");
147 return;
150 if(mkfifo(exname, 0600) < 0){
151 struct stat st;
152 if(errno != EEXIST || stat(exname, &st) < 0)
153 return;
154 if(!S_ISFIFO(st.st_mode)){
155 removeextern();
156 if(mkfifo(exname, 0600) < 0)
157 return;
161 fd = open(exname, OREAD|ONONBLOCK);
162 if(fd == -1){
163 removeextern();
164 return;
167 /*
168 * Turn off no-delay and provide ourselves as a lingering
169 * writer so as not to get end of file on read.
170 */
171 flags = fcntl(fd, F_GETFL, 0);
172 if(flags<0 || fcntl(fd, F_SETFL, flags&~O_NONBLOCK)<0
173 ||open(exname, OWRITE) < 0){
174 close(fd);
175 removeextern();
176 return;
179 plumbc = chancreate(sizeof(int), 0);
180 chansetname(plumbc, "plumbc");
181 arg[0] = plumbc;
182 arg[1] = (void*)fd;
183 proccreate(extproc, arg, STACK);
184 atexit(removeextern);
187 int
188 plumbformat(Plumbmsg *m, int i)
190 char *addr, *data, *act;
191 int n;
193 data = (char*)plumbbuf[i].data;
194 n = m->ndata;
195 if(n == 0 || 2+n+2 >= READBUFSIZE){
196 plumbfree(m);
197 return 0;
199 act = plumblookup(m->attr, "action");
200 if(act!=nil && strcmp(act, "showfile")!=0){
201 /* can't handle other cases yet */
202 plumbfree(m);
203 return 0;
205 addr = plumblookup(m->attr, "addr");
206 if(addr){
207 if(addr[0] == '\0')
208 addr = nil;
209 else
210 addr = strdup(addr); /* copy to safe storage; we'll overwrite data */
212 memmove(data, "B ", 2); /* we know there's enough room for this */
213 memmove(data+2, m->data, n);
214 n += 2;
215 if(data[n-1] != '\n')
216 data[n++] = '\n';
217 if(addr != nil){
218 if(n+strlen(addr)+1+1 <= READBUFSIZE)
219 n += sprint(data+n, "%s\n", addr);
220 free(addr);
222 plumbbuf[i].n = n;
223 plumbfree(m);
224 return 1;
227 void
228 plumbproc(void *arg)
230 CFid *fid;
231 int i;
232 Plumbmsg *m;
234 fid = arg;
235 i = 0;
236 for(;;){
237 m = plumbrecvfid(fid);
238 if(m == nil){
239 fprint(2, "samterm: plumb read error: %r\n");
240 threadexits("plumb"); /* not a fatal error */
242 if(plumbformat(m, i)){
243 send(plumbc, &i);
244 i = 1-i; /* toggle */
249 int
250 plumbstart(void)
252 CFid *fid;
254 plumbfd = plumbopen("send", OWRITE|OCEXEC); /* not open is ok */
255 fid = plumbopenfid("edit", OREAD|OCEXEC);
256 if(fid == nil)
257 return -1;
258 plumbc = chancreate(sizeof(int), 0);
259 chansetname(plumbc, "plumbc");
260 if(plumbc == nil){
261 fsclose(fid);
262 return -1;
264 threadcreate(plumbproc, fid, STACK);
265 return 1;
268 void
269 hostproc(void *arg)
271 Channel *c;
272 int i, n, which;
274 c = arg;
276 i = 0;
277 for(;;){
278 i = 1-i; /* toggle */
279 n = read(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
280 if(0) fprint(2, "hostproc %d\n", n);
281 if(n <= 0){
282 fprint(2, "samterm: host read error: %r\n");
283 threadexitsall("host");
285 hostbuf[i].n = n;
286 which = i;
287 if(0) fprint(2, "hostproc send %d\n", which);
288 send(c, &which);
292 void
293 hoststart(void)
295 hostc = chancreate(sizeof(int), 0);
296 chansetname(hostc, "hostc");
297 proccreate(hostproc, hostc, STACK);