Plan 9 from Bell Labs’s /usr/web/sources/contrib/nemo/octopus/port/lib/netget.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#
# 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");
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.