# # Tools for registering and implementing # our network-gadgets # implement Netget; include "sys.m"; sys: Sys; fildes, write, open, read, pctl, fprint, sleep, tokenize, sprint, OREAD, FD: import sys; include "draw.m"; include "registries.m"; regs: Registries; Service, Registered, Attributes, Registry: import regs; include "env.m"; env: Env; getenv: import env; include "error.m"; err: Error; stderr, error, kill: import err; include "arg.m"; arg: Arg; usage: import arg; include "netget.m"; Tick: con 60 * 1000; procpid := -1; debug := 0; ndbstr: string; constndb: string; init(nil: ref Draw->Context, args: list of string) { xinit(); regdir : string; arg = load Arg Arg->PATH; arg->init(args); arg->setusage("netget [-d] [-r regdir] name spec"); while((opt := arg->opt()) != 0) { case opt{ 'r' => regdir = arg->earg(); 'd' => debug = 1; * => usage(); } } args = arg->argv(); nargs := len args; if (nargs == 0 || (nargs%2) != 0) usage(); l : list of (string, string); while(len args > 0){ l = (hd args, hd tl args) :: l; args = tl args; args = tl args; } e := announcelist(l, regdir); if (e != nil){ fprint(stderr, "netget: %s\n", e); raise("fail: errors"); } } xinit() { sys = load Sys Sys->PATH; err = load Error Error->PATH; err->init(); regs = load Registries Registries->PATH; env = load Env Env->PATH; if (regs == nil || env == nil) error("unable to load modules: %r"); regs->init(); } readall(n: string) : string { fd := open(n, OREAD); if (fd == nil) return nil; max : con int 1024; data := array[max] of byte; tot := nr := 0; do { nr = read(fd, data[tot:], len data - tot); if (nr > 0) tot += nr; } while(nr > 0 && tot < len data); s := string data[0:tot]; if (s[len s - 1] == '\n') s = s[0:len s - 1]; return s; } devread(n: string) : string { v := getenv(n); if (v == nil) v = readall("/dev/" + n); if (v == nil) v = "unknown"; return v; } locate(s: string): (string, string) { location := readall("/term/what/" + s + "/where"); if (location == nil) location = getenv("location"); if (location == nil) location = "none"; radius := readall("/term/what/" + s + "/radius"); if (radius == nil) radius = "0"; return (location, radius); } announceproc(sysname: string, rs: list of ref Registered) { procpid = pctl(0, nil); for(;;){ (location, radius) := locate(sysname); s := sprint("loc %s rad %s", location, radius); if (debug) fprint(stderr, "%s\n", s); for(l := rs; l != nil; l = tl l){ r := hd l; d := array of byte s; if (write(r.fd, d, len d) != len d) error(sprint("netget: announceproc: %r\n")); ndbstr = constndb + " " + s; } sleep(Tick); } if (debug) fprint(stderr, "netget: exiting\n"); } ndb(): string { return ndbstr; } buildattrs(args: list of string) : ref Attributes { a:= Attributes.new(nil); while(args != nil){ nam := hd args; args = tl args; if (args == nil) return nil; val := hd args; args = tl args; a.set(nam, val); } return a; } announcelist(ads: list of (string, string), regdir: string): string { reg : ref Registry; if (sys == nil) xinit(); if (regdir != nil) reg = Registry.new(regdir); else { reg = Registry.new(nil); if (reg == nil){ svc := ref Service("tcp!pc!registry", Attributes.new(("auth", "infpk1")::nil)); reg = Registry.connect(svc, devread("user"), nil); } } if (reg == nil) return sprint("announce: reg: %r"); sysname := devread("sysname"); user := devread("user"); (location, radius) := locate(sysname); arch := getenv("emuhost") + getenv("cputype"); regs : list of ref Registered; while(ads != nil){ (name, spec) := hd ads; (na, al) := tokenize(spec, " \t\n"); if (na < 0 || (na%2) != 0) return "bad attribute list"; attrs := buildattrs(al); if (attrs == nil) return "bad formed attribute list"; attrs.set("name", name); name = "o!" + sysname + "!" + name; path := attrs.get("path"); if (path == nil) return "path attribute not found"; path = "/terms/" + sysname + path; attrs.set("path", path); attrs.set("sys", sysname); attrs.set("user", user); attrs.set("loc", location); attrs.set("rad", radius); attrs.set("arch", arch); constndb = "path " + path + " sys " + sysname + " user " + user + " arch " + arch; (r, e) := reg.register(name, attrs, 0); if (debug) fprint(stderr, "netget: announcing %s\n", name); if (e != nil) return "announce: " + e; regs = r :: regs; ads = tl ads; } spawn announceproc(sysname, regs); return nil; } # eg. announce("nautilus!what", "addr blah user bloh foo x bar y"); announce(name: string, spec: string) : string { return announcelist( (name,spec)::nil, nil ); } terminate() { if (sys != nil) kill(procpid, "kill"); }