code: purgatorio

ref: ec35f468e0eba87c9f09cbbe5fa8af2591e6f914
dir: /appl/cmd/whois.b/

View raw version
implement Whois;

include "sys.m"; sys: Sys;
include "draw.m";
include "dial.m"; dial: Dial;
include "arg.m";

Whois: module {
	init: fn(nil: ref Draw->Context, args: list of string);
};

init(nil: ref Draw->Context, args: list of string) {
	sys = load Sys Sys->PATH;
	dial = load Dial Dial->PATH;
	arg := load Arg Arg->PATH;

	addr := "tcp!whois.iana.org!43";
	expect_refer := 5;

	arg->init(args);
	arg->setusage("whois [-a addr] [-n] host");
	while((opt := arg->opt()) != 0) {
		case opt {
		'a' =>
			addr = dial->netmkaddr(arg->earg(), "tcp", "43");
		'n' =>
			expect_refer = 0;
		* =>
			arg->usage();
		}
	}

	args = arg->argv();
	if(len args != 1)
		arg->usage();

	host := hd args;
	fd := whois(addr, host);

	buf := array[512] of byte;
	stdout := sys->fildes(1);
	while((i := sys->read(fd, buf, len buf)) > 0) {
		if(expect_refer) {
			ls := sys->tokenize(string buf[0:i], "\n").t1;
			newaddr: string = nil;
			while(ls != nil) {
				l := hd ls;
				(n, rs) := sys->tokenize(l, " \t");
				if(n == 2 && hd rs == "refer:") {
					newaddr = dial->netmkaddr(hd tl rs, "tcp", "43");
					break;
				} else if(n == 3 && hd rs == "Whois" && hd tl rs == "Server:") {
					newaddr = dial->netmkaddr(hd tl tl rs, "tcp", "43");
					break;
				}
				ls = tl ls;
			}
			if(newaddr != nil) {
				fd = whois(newaddr, host);
				expect_refer--;
				continue;
			}
		}
		sys->write(stdout, buf, i);
	}
	if(i < 0) {
		sys->fprint(sys->fildes(2), "whois: reading info: %r\n");
		raise "fail:errors";
	}
}

whois(addr: string, host: string): ref Sys->FD
{
	sys->print("[using server %s]\n", addr);
	conn := dial->dial(addr, nil);
	if(conn == nil) {
		sys->fprint(sys->fildes(2), "whois: dialing %s: %r\n", addr);
		raise "fail:errors";
	}

	fd := conn.dfd;
	i := sys->fprint(fd, "%s\r\n", host);
	if(i != len host + 2) {
		sys->fprint(sys->fildes(2), "whois: sending name: %r\n");
		raise "fail:errors";
	}

	return fd;
}