1implement Styxmon; 2 3include "sys.m"; 4 sys: Sys; 5include "draw.m"; 6include "styx.m"; 7 styx: Styx; 8 Tmsg, Rmsg: import styx; 9include "sh.m"; 10include "arg.m"; 11 12Styxmon: module { 13 init: fn(nil: ref Draw->Context, argv: list of string); 14}; 15 16badmod(p: string) 17{ 18 sys->fprint(sys->fildes(2), "styxmon: cannot load %s: %r\n", p); 19 raise "fail:bad module"; 20} 21 22showdata := 0; 23init(ctxt: ref Draw->Context, argv: list of string) 24{ 25 sys = load Sys Sys->PATH; 26 styx = load Styx Styx->PATH; 27 if(styx == nil) 28 badmod(Styx->PATH); 29 styx->init(); 30 arg := load Arg Arg->PATH; 31 if(arg == nil) 32 badmod(Arg->PATH); 33 arg->init(argv); 34 arg->setusage("usage: styxmon [-d] cmd [arg...]"); 35 while((opt := arg->opt()) != 0){ 36 case opt{ 37 'd' => 38 showdata = 1; 39 * => 40 arg->usage(); 41 } 42 } 43 argv = arg->argv(); 44 if(argv == nil) 45 arg->usage(); 46 fd0 := sys->fildes(0); 47 fd1 := popen(ctxt, argv); 48 sync := chan of int; 49 spawn msgtx(fd0, fd1, sync, "tmsg"); 50 <-sync; 51 spawn msgtx(fd1, fd0, sync, "rmsg"); 52 <-sync; 53} 54 55msgtx(f0, f1: ref Sys->FD, sync: chan of int, what: string) 56{ 57 sys->pctl(Sys->NEWFD|Sys->NEWNS, 2 :: f0.fd :: f1.fd :: nil); 58 sync <-= 1; 59 f0 = sys->fildes(f0.fd); 60 f1 = sys->fildes(f1.fd); 61 stderr := sys->fildes(2); 62 for (;;) { 63 (d, err) := styx->readmsg(f0, 0); 64 if(d == nil){ 65 if(err != nil) 66 sys->fprint(stderr, "styxmon: error from %s: %s\n", what, err); 67 else 68 sys->fprint(stderr, "styxmon: eof from %s\n", what); 69 exit; 70 } 71 if(styx->istmsg(d)){ 72 (n, m) := Tmsg.unpack(d); 73 if(n != len d){ 74 sys->fprint(stderr, "styxmon: %s message error (%d/%d)\n", what, n, len d); 75 }else{ 76 sys->fprint(stderr, "%s\n", m.text()); 77 } 78 }else{ 79 (n, m) := Rmsg.unpack(d); 80 if(n != len d){ 81 sys->fprint(stderr, "styxmon: %s message error (%d/%d)\n", what, n, len d); 82 if(m != nil) 83 sys->fprint(stderr, "err: %s\n", m.text()); 84 }else{ 85 sys->fprint(stderr, "%s\n", m.text()); 86 } 87 } 88 sys->write(f1, d, len d); 89 } 90} 91 92popen(ctxt: ref Draw->Context, argv: list of string): ref Sys->FD 93{ 94 sync := chan of int; 95 fds := array[2] of ref Sys->FD; 96 sys->pipe(fds); 97 spawn runcmd(ctxt, argv, fds[0], sync); 98 <-sync; 99 return fds[1]; 100} 101 102runcmd(ctxt: ref Draw->Context, argv: list of string, stdin: ref Sys->FD, sync: chan of int) 103{ 104 sys->pctl(Sys->FORKFD, nil); 105 sys->dup(stdin.fd, 0); 106 stdin = nil; 107 sync <-= 0; 108 sh := load Sh Sh->PATH; 109 sh->run(ctxt, argv); 110} 111