ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/ndb/dnsquery.b/
implement Dnsquery;
#
# Copyright © 2003 Vita Nuova Holdings LImited. All rights reserved.
#
include "sys.m";
sys: Sys;
include "draw.m";
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "arg.m";
Dnsquery: module
{
init: fn(nil: ref Draw->Context, nil: list of string);
};
usage()
{
sys->fprint(sys->fildes(2), "usage: dnsquery [-x /net] [-s server] [address ...]\n");
raise "fail:usage";
}
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
if(bufio == nil)
cantload(Bufio->PATH);
net := "/net";
server: string;
arg := load Arg Arg->PATH;
if(arg == nil)
cantload(Arg->PATH);
arg->init(args);
while((c := arg->opt()) != 0)
case c {
'x' =>
net = arg->arg();
if(net == nil)
usage();
's' =>
server = arg->arg();
if(server == nil)
usage();
* =>
usage();
}
args = arg->argv();
arg = nil;
if(server == nil)
server = net+"/dns";
if(args != nil){
for(; args != nil; args = tl args)
dnsquery(server, hd args);
}else{
f := bufio->fopen(sys->fildes(0), Sys->OREAD);
if(f == nil)
exit;
for(;;){
sys->print("> ");
s := f.gets('\n');
if(s == nil)
break;
dnsquery(server, s[0:len s-1]);
}
}
}
cantload(s: string)
{
sys->fprint(sys->fildes(2), "dnsquery: can't load %s: %r\n", s);
raise "fail:load";
}
dnsquery(server: string, query: string)
{
dns := sys->open(server, Sys->ORDWR);
if(dns == nil){
sys->fprint(sys->fildes(2), "dnsquery: can't open %s: %r\n", server);
raise "fail:open";
}
stdout := sys->fildes(1);
for(i := len query; --i >= 0 && query[i] != ' ';)
{}
if(i < 0){
i = len query;
case dbattr(query) {
"ip" =>
query += " ptr";
* =>
query += " ip";
}
}
if(query[i+1:] == "ptr"){
while(i > 0 && query[i-1] == ' ')
i--;
if(!hastail(query[0:i], ".in-addr.arpa") && !hastail(query[0:i], ".IN-ADDR.ARPA"))
query = addr2arpa(query[0:i])+" ptr";
}
b := array of byte query;
if(sys->write(dns, b, len b) > 0){
sys->seek(dns, big 0, Sys->SEEKSTART);
buf := array[256] of byte;
while((n := sys->read(dns, buf, len buf)) > 0)
sys->print("%s\n", string buf[0:n]);
if(n == 0)
return;
}
sys->print("!%r\n");
}
hastail(s: string, t: string): int
{
if(len s >= len t && s[len s - len t:] == t)
return 1;
return 0;
}
addr2arpa(a: string): string
{
(nf, flds) := sys->tokenize(a, ".");
rl: list of string;
for(; flds != nil; flds = tl flds)
rl = hd flds :: rl;
addr: string;
for(; rl != nil; rl = tl rl){
if(addr != nil)
addr[len addr] = '.';
addr += hd rl;
}
return addr+".in-addr.arpa";
}
dbattr(s: string): string
{
digit := 0;
dot := 0;
alpha := 0;
hex := 0;
colon := 0;
for(i := 0; i < len s; i++){
case c := s[i] {
'0' to '9' =>
digit = 1;
'a' to 'f' or 'A' to 'F' =>
hex = 1;
'.' =>
dot = 1;
':' =>
colon = 1;
* =>
if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '-' || c == '&')
alpha = 1;
}
}
if(alpha){
if(dot)
return "dom";
return "sys";
}
if(colon)
return "ip";
if(dot){
if(!hex)
return "ip";
return "dom";
}
return "sys";
}