xref: /inferno-os/appl/cmd/auxi/rdbgsrv.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement RDbgSrv;
2
3include "sys.m";
4	sys: Sys;
5include "draw.m";
6
7include "styx.m";
8	styx: Styx;
9	Rmsg, Tmsg: import styx;
10
11include "arg.m";
12	arg: Arg;
13
14RDbgSrv: module
15{
16	init: fn(nil: ref Draw->Context, argv: list of string);
17};
18
19debug:=	0;
20dev:=	"/dev/eia0";
21speed:=	38400;
22progname: string;
23rpid := 0;
24wpid := 0;
25
26usage()
27{
28	sys->fprint(stderr(), "Usage: rdbgsrv [-d n] [-s speed] [-f dev] mountpoint\n");
29	raise "fail: usage";
30}
31
32init(nil: ref Draw->Context, av: list of string)
33{
34	sys = load Sys Sys->PATH;
35	if(sys == nil)
36		return;
37	styx = load Styx Styx->PATH;
38	if(styx == nil){
39		sys->fprint(stderr(), "rdbgsrv: can't load %s; %r\n", Styx->PATH);
40		raise "fail:load";
41	}
42	arg = load Arg Arg->PATH;
43	if(arg == nil){
44		sys->fprint(stderr(), "rdbgsrv: can't load %s: %r\n", Arg->PATH);
45		raise "fail:load";
46	}
47
48	arg->init(av);
49	progname = arg->progname();
50	while(o := arg->opt())
51		case o {
52		'd' =>
53			d := arg->arg();
54			if(d == nil)
55				usage();
56			debug = int d;
57		's' =>
58			s := arg->arg();
59			if(s == nil)
60				usage();
61			speed = int s;
62		'f' =>
63			s := arg->arg();
64			if(s == nil)
65				usage();
66			dev = s;
67		'h' =>
68			usage();
69		}
70
71	mtpt := arg->arg();
72	if(mtpt == nil)
73		usage();
74
75	ctl := dev + "ctl";
76	cfd := sys->open(ctl, Sys->OWRITE);
77	if(cfd == nil){
78		sys->fprint(stderr(), "%s: can't open %s: %r\n", progname, ctl);
79		raise "fail: open eia\n";
80	}
81
82	sys->fprint(cfd, "b%d", speed);
83	sys->fprint(cfd, "l8");
84	sys->fprint(cfd, "pn");
85	sys->fprint(cfd, "s1");
86
87	(rfd, wfd) := start(dev);
88	if(rfd == nil){
89		sys->fprint(stderr(), "%s: failed to start protocol\n", progname);
90		raise "fail:proto start";
91	}
92
93	fds := array[2] of ref Sys->FD;
94
95	if(sys->pipe(fds) == -1){
96		sys->fprint(stderr(), "%s: pipe: %r\n", progname);
97		raise "fail:no pipe";
98	}
99
100	if(debug)
101		sys->fprint(stderr(), "%s: starting server\n", progname);
102
103	rc := chan of int;
104	spawn copymsg(fds[1], wfd, "->", rc);
105	rpid = <-rc;
106	spawn copymsg(rfd, fds[1], "<-", rc);
107	wpid = <-rc;
108
109	if(sys->mount(fds[0], nil, mtpt, Sys->MREPL, nil) == -1) {
110		fds[1] = nil;
111		sys->fprint(stderr(), "%s: can't mount on %s: %r\n", progname, mtpt);
112		quit("mount");
113	}
114}
115
116stderr(): ref Sys->FD
117{
118	return sys->fildes(2);
119}
120
121killpid(pid: int)
122{
123	fd := sys->open("#p/"+string pid+"/ctl", sys->OWRITE);
124	if(fd != nil)
125		sys->fprint(fd, "kill");
126}
127
128quit(err: string)
129{
130	killpid(rpid);
131	killpid(wpid);
132	if(err != nil)
133		raise "fail:"+err;
134	exit;
135}
136
137start(name:string): (ref Sys->FD, ref Sys->FD)
138{
139	rfd := sys->open(name, Sys->OREAD);
140	wfd := sys->open(name, Sys->OWRITE);
141	if(rfd == nil || wfd == nil)
142			return (nil, nil);
143	if(sys->fprint(wfd, "go") < 0)
144		return (nil, nil);
145	c := array[1] of byte;
146	state := 0;
147	for(;;) {
148		if(sys->read(rfd, c, 1) != 1)
149			return (nil, nil);
150		if(state == 0 && c[0] == byte 'o')
151			state = 1;
152		else if(state == 1 && c[0] == byte 'k')
153			break;
154		else
155			state = 0;
156	}
157	return (rfd, wfd);
158}
159
160copymsg(f: ref Sys->FD, t: ref Sys->FD, dir: string, pidc: chan of int)
161{
162	pidc <-= sys->pctl(0, nil);
163
164	{
165		for(;;) {
166			(msg, err) := styx->readmsg(f, 0);
167			if(msg == nil){
168				sys->fprint(stderr(), "%s: %s: read error: %s\n", progname, dir, err);
169				quit("error");
170			}
171			if(debug &1)
172				trace(dir, msg);
173			if(debug & 2)
174				dump(dir, msg, len msg);
175			if(sys->write(t, msg, len msg) != len msg){
176				sys->fprint(stderr(), "%s: %s: write error: %r\n", progname, dir);
177				quit("error");
178			}
179		}
180	}exception e{
181	"*" =>
182		sys->print("%s: %s: %s: exiting\n", progname, dir, e);
183		quit("exception");
184	}
185}
186
187trace(sourcept: string,  op: array of byte )
188{
189	if(styx->istmsg(op)){
190		(nil, m) := Tmsg.unpack(op);
191		if(m != nil)
192			sys->print("%s: %s\n", sourcept, m.text());
193		else
194			sys->print("%s: unknown\n", sourcept);
195	}else{
196		(nil, m) := Rmsg.unpack(op);
197		if(m != nil)
198			sys->print("%s: %s\n", sourcept, m.text());
199		else
200			sys->print("%s: unknown\n", sourcept);
201	}
202}
203
204dump(msg: string, buf: array of byte, n: int)
205{
206	sys->print("%s: [%d bytes]: ", msg, n);
207	s := "";
208	for(i:=0;i<n;i++) {
209		if((i % 20) == 0) {
210			sys->print(" %s\n", s);
211			s = "";
212		}
213		sys->print("%2.2x ", int buf[i]);
214		if(int buf[i] >= 32 && int buf[i] < 127)
215			s[len s] = int buf[i];
216		else
217			s += ".";
218	}
219	for(i %= 20; i < 20; i++)
220		sys->print("   ");
221	sys->print(" %s\n\n", s);
222}
223