Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <fcall.h>
5 #include <fs.h>
7 #define EVENTSIZE 256
8 #define STACK 32768
10 typedef struct Event Event;
11 typedef struct Q Q;
13 struct Event
14 {
15 int c1;
16 int c2;
17 int q0;
18 int q1;
19 int flag;
20 int nb;
21 int nr;
22 char b[EVENTSIZE*UTFmax+1];
23 Rune r[EVENTSIZE+1];
24 };
26 Event blank = {
27 'M',
28 'X',
29 0, 0, 0, 1, 1,
30 { ' ', 0 },
31 { ' ', 0 },
32 };
34 struct Q
35 {
36 QLock lk;
37 int p;
38 int k;
39 };
41 Q q;
43 int eventfd;
44 int addrfd;
45 int datafd;
46 int ctlfd;
47 int bodyfd;
49 char *typing;
50 int ntypeb;
51 int ntyper;
52 int ntypebreak;
53 int debug;
55 char **prog;
56 int p[2];
57 Channel *cpid;
58 int pid = -1;
60 void error(char*);
61 void stdinproc(void*);
62 void stdoutproc(void*);
63 void type(Event*, int, int, int);
64 void sende(Event*, int, int, int, int, int);
65 char *onestring(int, char**);
66 int delete(Event*);
67 void deltype(uint, uint);
68 void runproc(void*);
70 void
71 usage(void)
72 {
73 fprint(2, "usage: win cmd args...\n");
74 threadexitsall("usage");
75 }
77 int
78 nopipes(void *v, char *msg)
79 {
80 USED(v);
81 if(strcmp(msg, "sys: write on closed pipe") == 0)
82 return 1;
83 return 0;
84 }
86 void
87 threadmain(int argc, char **argv)
88 {
89 int fd, id;
90 char buf[256];
91 char buf1[128];
92 char *name;
93 Fsys *fs;
95 ARGBEGIN{
96 case 'd':
97 debug = 1;
98 break;
99 default:
100 usage();
101 }ARGEND
103 prog = argv;
105 if(argc > 0)
106 name = argv[0];
107 else
108 name = "gnot";
110 threadnotify(nopipes, 1);
111 if((fs = nsmount("acme", "")) < 0)
112 sysfatal("nsmount acme: %r");
113 ctlfd = fsopenfd(fs, "new/ctl", ORDWR|OCEXEC);
114 if(ctlfd < 0 || read(ctlfd, buf, 12) != 12)
115 sysfatal("ctl: %r");
116 id = atoi(buf);
117 sprint(buf, "%d/tag", id);
118 fd = fsopenfd(fs, buf, OWRITE|OCEXEC);
119 write(fd, " Send Delete", 12);
120 close(fd);
121 sprint(buf, "%d/event", id);
122 eventfd = fsopenfd(fs, buf, ORDWR|OCEXEC);
123 sprint(buf, "%d/addr", id);
124 addrfd = fsopenfd(fs, buf, ORDWR|OCEXEC);
125 sprint(buf, "%d/data", id);
126 datafd = fsopenfd(fs, buf, ORDWR|OCEXEC);
127 sprint(buf, "%d/body", id);
128 bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC);
129 if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0)
130 sysfatal("data files: %r");
131 fsunmount(fs);
133 if(pipe(p) < 0)
134 sysfatal("pipe: %r");
136 cpid = chancreate(sizeof(ulong), 1);
137 threadcreate(runproc, nil, STACK);
138 pid = recvul(cpid);
139 if(pid == -1)
140 sysfatal("exec failed");
142 getwd(buf1, sizeof buf1);
143 sprint(buf, "name %s/-%s\n0\n", buf1, name);
144 write(ctlfd, buf, strlen(buf));
145 sprint(buf, "dumpdir %s/\n", buf1);
146 write(ctlfd, buf, strlen(buf));
147 sprint(buf, "dump %s\n", onestring(argc, argv));
148 write(ctlfd, buf, strlen(buf));
150 // proccreate(stdoutproc, nil, STACK);
151 stdinproc(nil);
154 char *shell[] = { "rc", "-i", 0 };
155 void
156 runproc(void *v)
158 int fd[3];
159 char *sh;
161 USED(v);
163 fd[0] = p[1];
164 fd[1] = bodyfd;
165 fd[2] = bodyfd;
166 // fd[1] = p[1];
167 // fd[2] = p[1];
169 if(prog[0] == nil){
170 prog = shell;
171 if((sh = getenv("SHELL")) != nil)
172 shell[0] = sh;
174 threadexec(cpid, fd, prog[0], prog);
175 threadexits(nil);
178 void
179 error(char *s)
181 if(s)
182 fprint(2, "win: %s: %r\n", s);
183 else
184 s = "kill";
185 if(pid != -1)
186 postnote(PNGROUP, pid, "hangup");
187 threadexitsall(s);
190 char*
191 onestring(int argc, char **argv)
193 char *p;
194 int i, n;
195 static char buf[1024];
197 if(argc == 0)
198 return "";
199 p = buf;
200 for(i=0; i<argc; i++){
201 n = strlen(argv[i]);
202 if(p+n+1 >= buf+sizeof buf)
203 break;
204 memmove(p, argv[i], n);
205 p += n;
206 *p++ = ' ';
208 p[-1] = 0;
209 return buf;
212 int
213 getec(int efd)
215 static char buf[8192];
216 static char *bufp;
217 static int nbuf;
219 if(nbuf == 0){
220 nbuf = read(efd, buf, sizeof buf);
221 if(nbuf <= 0)
222 error(nil);
223 bufp = buf;
225 --nbuf;
226 return *bufp++;
229 int
230 geten(int efd)
232 int n, c;
234 n = 0;
235 while('0'<=(c=getec(efd)) && c<='9')
236 n = n*10+(c-'0');
237 if(c != ' ')
238 error("event number syntax");
239 return n;
242 int
243 geter(int efd, char *buf, int *nb)
245 Rune r;
246 int n;
248 r = getec(efd);
249 buf[0] = r;
250 n = 1;
251 if(r < Runeself)
252 goto Return;
253 while(!fullrune(buf, n))
254 buf[n++] = getec(efd);
255 chartorune(&r, buf);
256 Return:
257 *nb = n;
258 return r;
261 void
262 gete(int efd, Event *e)
264 int i, nb;
266 e->c1 = getec(efd);
267 e->c2 = getec(efd);
268 e->q0 = geten(efd);
269 e->q1 = geten(efd);
270 e->flag = geten(efd);
271 e->nr = geten(efd);
272 if(e->nr > EVENTSIZE)
273 error("event string too long");
274 e->nb = 0;
275 for(i=0; i<e->nr; i++){
276 e->r[i] = geter(efd, e->b+e->nb, &nb);
277 e->nb += nb;
279 e->r[e->nr] = 0;
280 e->b[e->nb] = 0;
281 if(getec(efd) != '\n')
282 error("event syntax 2");
285 int
286 nrunes(char *s, int nb)
288 int i, n;
289 Rune r;
291 n = 0;
292 for(i=0; i<nb; n++)
293 i += chartorune(&r, s+i);
294 return n;
297 void
298 stdinproc(void *v)
300 int cfd = ctlfd;
301 int efd = eventfd;
302 int dfd = datafd;
303 int afd = addrfd;
304 int fd0 = p[0];
305 Event e, e2, e3, e4;
307 USED(v);
309 for(;;){
310 if(debug)
311 fprint(2, "typing[%d,%d)\n", q.p, q.p+ntyper);
312 gete(efd, &e);
313 if(debug)
314 fprint(2, "msg %c%c q[%d,%d)... ", e.c1, e.c2, e.q0, e.q1);
315 qlock(&q.lk);
316 switch(e.c1){
317 default:
318 Unknown:
319 print("unknown message %c%c\n", e.c1, e.c2);
320 break;
322 case 'E': /* write to body; can't affect us */
323 if(debug)
324 fprint(2, "shift typing %d... ", e.q1-e.q0);
325 q.p += e.q1-e.q0;
326 break;
328 case 'F': /* generated by our actions; ignore */
329 break;
331 case 'K':
332 case 'M':
333 switch(e.c2){
334 case 'I':
335 if(e.q0 < q.p){
336 if(debug)
337 fprint(2, "shift typing %d... ", e.q1-e.q0);
338 q.p += e.q1-e.q0;
340 else if(e.q0 <= q.p+ntyper){
341 if(debug)
342 fprint(2, "type... ");
343 type(&e, fd0, afd, dfd);
345 break;
347 case 'D':
348 q.p -= delete(&e);
349 break;
351 case 'x':
352 case 'X':
353 if(e.flag & 2)
354 gete(efd, &e2);
355 if(e.flag & 8){
356 gete(efd, &e3);
357 gete(efd, &e4);
359 if(e.flag&1 || (e.c2=='x' && e.nr==0 && e2.nr==0)){
360 /* send it straight back */
361 fprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
362 break;
364 if(e.q0==e.q1 && (e.flag&2)){
365 e2.flag = e.flag;
366 e = e2;
368 if(e.flag & 8){
369 if(e.q1 != e.q0){
370 sende(&e, fd0, cfd, afd, dfd, 0);
371 sende(&blank, fd0, cfd, afd, dfd, 0);
373 sende(&e3, fd0, cfd, afd, dfd, 1);
374 }else if(e.q1 != e.q0)
375 sende(&e, fd0, cfd, afd, dfd, 1);
376 break;
378 case 'l':
379 case 'L':
380 /* just send it back */
381 if(e.flag & 2)
382 gete(efd, &e2);
383 fprint(efd, "%c%c%d %d\n", e.c1, e.c2, e.q0, e.q1);
384 break;
386 case 'd':
387 case 'i':
388 break;
390 default:
391 goto Unknown;
394 qunlock(&q.lk);
398 void
399 stdoutproc(void *v)
401 int fd1 = p[0];
402 int afd = addrfd;
403 int dfd = datafd;
404 int n, m, w, npart;
405 char *buf, *s, *t;
406 Rune r;
407 char x[16], hold[UTFmax];
409 USED(v);
410 threadnotify(nopipes, 1);
411 buf = malloc(8192+UTFmax+1);
412 npart = 0;
413 for(;;){
414 n = read(fd1, buf+npart, 8192);
415 if(n < 0)
416 error(nil);
417 if(n == 0)
418 continue;
420 /* squash NULs */
421 s = memchr(buf+npart, 0, n);
422 if(s){
423 for(t=s; s<buf+npart+n; s++)
424 if(*t = *s) /* assign = */
425 t++;
426 n = t-(buf+npart);
429 n += npart;
431 /* hold on to final partial rune */
432 npart = 0;
433 while(n>0 && (buf[n-1]&0xC0)){
434 --n;
435 npart++;
436 if((buf[n]&0xC0)!=0x80){
437 if(fullrune(buf+n, npart)){
438 w = chartorune(&r, buf+n);
439 n += w;
440 npart -= w;
442 break;
445 if(n > 0){
446 memmove(hold, buf+n, npart);
447 buf[n] = 0;
448 qlock(&q.lk);
449 m = sprint(x, "#%d", q.p);
450 if(write(afd, x, m) != m)
451 error("stdout writing address");
452 if(write(dfd, buf, n) != n)
453 error("stdout writing body");
454 q.p += nrunes(buf, n);
455 qunlock(&q.lk);
456 memmove(buf, hold, npart);
461 int
462 delete(Event *e)
464 uint q0, q1;
465 int deltap;
467 q0 = e->q0;
468 q1 = e->q1;
469 if(q1 <= q.p)
470 return e->q1-e->q0;
471 if(q0 >= q.p+ntyper)
472 return 0;
473 deltap = 0;
474 if(q0 < q.p){
475 deltap = q.p-q0;
476 q0 = 0;
477 }else
478 q0 -= q.p;
479 if(q1 > q.p+ntyper)
480 q1 = ntyper;
481 else
482 q1 -= q.p;
483 deltype(q0, q1);
484 return deltap;
487 void
488 addtype(int c, uint p0, char *b, int nb, int nr)
490 int i, w;
491 Rune r;
492 uint p;
493 char *b0;
495 for(i=0; i<nb; i+=w){
496 w = chartorune(&r, b+i);
497 if((r==0x7F||r==3) && c=='K'){
498 postnote(PNGROUP, pid, "interrupt");
499 /* toss all typing */
500 q.p += ntyper+nr;
501 ntypebreak = 0;
502 ntypeb = 0;
503 ntyper = 0;
504 /* buglet: more than one delete ignored */
505 return;
507 if(r=='\n' || r==0x04)
508 ntypebreak++;
510 typing = realloc(typing, ntypeb+nb);
511 if(typing == nil)
512 error("realloc");
513 if(p0 == ntyper)
514 memmove(typing+ntypeb, b, nb);
515 else{
516 b0 = typing;
517 for(p=0; p<p0 && b0<typing+ntypeb; p++){
518 w = chartorune(&r, b0+i);
519 b0 += w;
521 if(p != p0)
522 error("typing: findrune");
523 memmove(b0+nb, b0, (typing+ntypeb)-b0);
524 memmove(b0, b, nb);
526 ntypeb += nb;
527 ntyper += nr;
530 void
531 sendtype(int fd0)
533 int i, n, nr;
535 while(ntypebreak){
536 for(i=0; i<ntypeb; i++)
537 if(typing[i]=='\n' || typing[i]==0x04){
538 n = i + (typing[i] == '\n');
539 i++;
540 if(write(fd0, typing, n) != n)
541 error("sending to program");
542 nr = nrunes(typing, i);
543 q.p += nr;
544 ntyper -= nr;
545 ntypeb -= i;
546 memmove(typing, typing+i, ntypeb);
547 ntypebreak--;
548 goto cont2;
550 print("no breakchar\n");
551 ntypebreak = 0;
552 cont2:
556 void
557 deltype(uint p0, uint p1)
559 int w;
560 uint p, b0, b1;
561 Rune r;
563 /* advance to p0 */
564 b0 = 0;
565 for(p=0; p<p0 && b0<ntypeb; p++){
566 w = chartorune(&r, typing+b0);
567 b0 += w;
569 if(p != p0)
570 error("deltype 1");
571 /* advance to p1 */
572 b1 = b0;
573 for(; p<p1 && b1<ntypeb; p++){
574 w = chartorune(&r, typing+b1);
575 b1 += w;
576 if(r=='\n' || r==0x04)
577 ntypebreak--;
579 if(p != p1)
580 error("deltype 2");
581 memmove(typing+b0, typing+b1, ntypeb-b1);
582 ntypeb -= b1-b0;
583 ntyper -= p1-p0;
586 void
587 type(Event *e, int fd0, int afd, int dfd)
589 int m, n, nr;
590 char buf[128];
592 if(e->nr > 0)
593 addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr);
594 else{
595 m = e->q0;
596 while(m < e->q1){
597 n = sprint(buf, "#%d", m);
598 write(afd, buf, n);
599 n = read(dfd, buf, sizeof buf);
600 nr = nrunes(buf, n);
601 while(m+nr > e->q1){
602 do; while(n>0 && (buf[--n]&0xC0)==0x80);
603 --nr;
605 if(n == 0)
606 break;
607 addtype(e->c1, m-q.p, buf, n, nr);
608 m += nr;
611 sendtype(fd0);
614 void
615 sende(Event *e, int fd0, int cfd, int afd, int dfd, int donl)
617 int l, m, n, nr, lastc, end;
618 char abuf[16], buf[128];
620 end = q.p+ntyper;
621 l = sprint(abuf, "#%d", end);
622 write(afd, abuf, l);
623 if(e->nr > 0){
624 write(dfd, e->b, e->nb);
625 addtype(e->c1, ntyper, e->b, e->nb, e->nr);
626 lastc = e->r[e->nr-1];
627 }else{
628 m = e->q0;
629 lastc = 0;
630 while(m < e->q1){
631 n = sprint(buf, "#%d", m);
632 write(afd, buf, n);
633 n = read(dfd, buf, sizeof buf);
634 nr = nrunes(buf, n);
635 while(m+nr > e->q1){
636 do; while(n>0 && (buf[--n]&0xC0)==0x80);
637 --nr;
639 if(n == 0)
640 break;
641 l = sprint(abuf, "#%d", end);
642 write(afd, abuf, l);
643 write(dfd, buf, n);
644 addtype(e->c1, ntyper, buf, n, nr);
645 lastc = buf[n-1];
646 m += nr;
647 end += nr;
650 if(donl && lastc!='\n'){
651 write(dfd, "\n", 1);
652 addtype(e->c1, ntyper, "\n", 1, 1);
654 write(cfd, "dot=addr", 8);
655 sendtype(fd0);