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 usage(void) 16 { 17 fprint(2, "usage: samterm [-a]\n"); 18 threadexitsall("usage"); 19 } 20 21 void 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 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 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 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 109 removeextern(void) 110 { 111 remove(exname); 112 } 113 114 Readbuf hostbuf[2]; 115 Readbuf plumbbuf[2]; 116 117 void 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 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 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 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 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 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 295 hoststart(void) 296 { 297 hostc = chancreate(sizeof(int), 0); 298 proccreate(hostproc, hostc, 1024); 299 } 300