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