xref: /inferno-os/appl/cmd/styxmon.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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