diff options
Diffstat (limited to 'appl/cmd/ip/virgild.b')
| -rw-r--r-- | appl/cmd/ip/virgild.b | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/appl/cmd/ip/virgild.b b/appl/cmd/ip/virgild.b new file mode 100644 index 00000000..29ebba67 --- /dev/null +++ b/appl/cmd/ip/virgild.b @@ -0,0 +1,127 @@ +implement Virgild; + +include "sys.m"; +sys: Sys; + +include "draw.m"; + +include "ip.m"; + +Virgild: module +{ + init: fn(ctxt: ref Draw->Context, argv: list of string); +}; + +stderr: ref Sys->FD; + +Udphdrsize: con IP->OUdphdrlen; + +init(nil: ref Draw->Context, nil: list of string) +{ + sys = load Sys Sys->PATH; + + stderr = sys->fildes(2); + + sys->pctl(Sys->FORKNS|Sys->FORKFD, nil); + if(sys->chdir("/lib/ndb") < 0){ + sys->fprint(stderr, "virgild: no database\n"); + return; + } + + for(;;sys->sleep(10*1000)){ + fd := openlisten(); + if(fd == nil) + return; + + buf := array[512] of byte; + for(;;){ + n := sys->read(fd, buf, len buf); + if(n <= Udphdrsize){ + break; + } + if(n <= Udphdrsize+1) + continue; + + # dump any cruft after the question + for(i := Udphdrsize; i < n; i++){ + c := int buf[i]; + if(c == ' ' || c == 0 || c == '\n') + break; + } + + answer := query(string buf[Udphdrsize:i]); + if(answer == nil) + continue; + + # reply + r := array of byte answer; + if(len r > len buf - Udphdrsize) + continue; + buf[Udphdrsize:] = r; + sys->write(fd, buf, Udphdrsize+len r); + } + fd = nil; + } +} + +openlisten(): ref Sys->FD +{ + (ok, c) := sys->announce("udp!*!virgil"); + if(ok < 0){ + sys->fprint(stderr, "virgild: can't open port: %r\n"); + return nil; + } + + if(sys->fprint(c.cfd, "headers") <= 0){ + sys->fprint(stderr, "virgild: can't set headers: %r\n"); + return nil; + } + sys->fprint(c.cfd, "oldheaders"); + + c.dfd = sys->open(c.dir+"/data", Sys->ORDWR); + if(c.dfd == nil) { + sys->fprint(stderr, "virgild: can't open data file\n"); + return nil; + } + return c.dfd; +} + +# +# query is userid?question +# +# for now, we're ignoring userid +# +query(request: string): string +{ + (n, l) := sys->tokenize(request, "?"); + if(n < 2){ + sys->fprint(stderr, "virgild: bad request %s %d\n", request, n); + return nil; + } + + # + # until we have something better, ask cs + # to translate, make the request look cs-like + # + fd := sys->open("/net/cs", Sys->ORDWR); + if(fd == nil){ + sys->fprint(stderr, "virgild: can't open /net/cs - %r\n"); + return nil; + } + q := array of byte ("tcp!" + hd(tl l) + "!1000"); + if(sys->write(fd, q, len q) < 0){ + sys->fprint(stderr, "virgild: can't write /net/cs - %r: %s\n", string q); + return nil; + } + sys->seek(fd, big 0, 0); + buf := array[512-Udphdrsize-len request-1] of byte; + n = sys->read(fd, buf, len buf); + if(n <= 0){ + sys->fprint(stderr, "virgild: can't read /net/cs - %r\n"); + return nil; + } + + (nil, l) = sys->tokenize(string buf[0:n], " \t"); + (nil, l) = sys->tokenize(hd(tl l), "!"); + return request + "=" + hd l; +} |
