ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/styxmon.b/
implement Styxmon;
include "sys.m";
sys: Sys;
include "draw.m";
include "styx.m";
styx: Styx;
Tmsg, Rmsg: import styx;
include "sh.m";
include "arg.m";
Styxmon: module {
init: fn(nil: ref Draw->Context, argv: list of string);
};
badmod(p: string)
{
sys->fprint(sys->fildes(2), "styxmon: cannot load %s: %r\n", p);
raise "fail:bad module";
}
showdata := 0;
init(ctxt: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
styx = load Styx Styx->PATH;
if(styx == nil)
badmod(Styx->PATH);
styx->init();
arg := load Arg Arg->PATH;
if(arg == nil)
badmod(Arg->PATH);
arg->init(argv);
arg->setusage("usage: styxmon [-d] cmd [arg...]");
while((opt := arg->opt()) != 0){
case opt{
'd' =>
showdata = 1;
* =>
arg->usage();
}
}
argv = arg->argv();
if(argv == nil)
arg->usage();
fd0 := sys->fildes(0);
fd1 := popen(ctxt, argv);
sync := chan of int;
spawn msgtx(fd0, fd1, sync, "tmsg");
<-sync;
spawn msgtx(fd1, fd0, sync, "rmsg");
<-sync;
}
msgtx(f0, f1: ref Sys->FD, sync: chan of int, what: string)
{
sys->pctl(Sys->NEWFD|Sys->NEWNS, 2 :: f0.fd :: f1.fd :: nil);
sync <-= 1;
f0 = sys->fildes(f0.fd);
f1 = sys->fildes(f1.fd);
stderr := sys->fildes(2);
for (;;) {
(d, err) := styx->readmsg(f0, 0);
if(d == nil){
if(err != nil)
sys->fprint(stderr, "styxmon: error from %s: %s\n", what, err);
else
sys->fprint(stderr, "styxmon: eof from %s\n", what);
exit;
}
if(styx->istmsg(d)){
(n, m) := Tmsg.unpack(d);
if(n != len d){
sys->fprint(stderr, "styxmon: %s message error (%d/%d)\n", what, n, len d);
}else{
sys->fprint(stderr, "%s\n", m.text());
}
}else{
(n, m) := Rmsg.unpack(d);
if(n != len d){
sys->fprint(stderr, "styxmon: %s message error (%d/%d)\n", what, n, len d);
if(m != nil)
sys->fprint(stderr, "err: %s\n", m.text());
}else{
sys->fprint(stderr, "%s\n", m.text());
}
}
sys->write(f1, d, len d);
}
}
popen(ctxt: ref Draw->Context, argv: list of string): ref Sys->FD
{
sync := chan of int;
fds := array[2] of ref Sys->FD;
sys->pipe(fds);
spawn runcmd(ctxt, argv, fds[0], sync);
<-sync;
return fds[1];
}
runcmd(ctxt: ref Draw->Context, argv: list of string, stdin: ref Sys->FD, sync: chan of int)
{
sys->pctl(Sys->FORKFD, nil);
sys->dup(stdin.fd, 0);
stdin = nil;
sync <-= 0;
sh := load Sh Sh->PATH;
sh->run(ctxt, argv);
}