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