xref: /inferno-os/appl/cmd/ndb/dnsquery.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Dnsquery;
2
3#
4# Copyright © 2003 Vita Nuova Holdings LImited.  All rights reserved.
5#
6
7include "sys.m";
8	sys: Sys;
9
10include "draw.m";
11
12include "bufio.m";
13	bufio: Bufio;
14	Iobuf: import bufio;
15
16include "arg.m";
17
18Dnsquery: module
19{
20	init:	fn(nil: ref Draw->Context, nil: list of string);
21};
22
23usage()
24{
25	sys->fprint(sys->fildes(2), "usage: dnsquery [-x /net] [-s server] [address ...]\n");
26	raise "fail:usage";
27}
28
29init(nil: ref Draw->Context, args: list of string)
30{
31	sys = load Sys Sys->PATH;
32	bufio = load Bufio Bufio->PATH;
33	if(bufio == nil)
34		cantload(Bufio->PATH);
35
36	net := "/net";
37	server: string;
38	arg := load Arg Arg->PATH;
39	if(arg == nil)
40		cantload(Arg->PATH);
41	arg->init(args);
42	while((c := arg->opt()) != 0)
43		case c {
44		'x' =>
45			net = arg->arg();
46			if(net == nil)
47				usage();
48		's' =>
49			server = arg->arg();
50			if(server == nil)
51				usage();
52		* =>
53			usage();
54		}
55	args = arg->argv();
56	arg = nil;
57
58	if(server == nil)
59		server = net+"/dns";
60	if(args != nil){
61		for(; args != nil; args = tl args)
62			dnsquery(server, hd args);
63	}else{
64		f := bufio->fopen(sys->fildes(0), Sys->OREAD);
65		if(f == nil)
66			exit;
67		for(;;){
68			sys->print("> ");
69			s := f.gets('\n');
70			if(s == nil)
71				break;
72			dnsquery(server, s[0:len s-1]);
73		}
74	}
75}
76
77cantload(s: string)
78{
79	sys->fprint(sys->fildes(2), "dnsquery: can't load %s: %r\n", s);
80	raise "fail:load";
81}
82
83dnsquery(server: string, query: string)
84{
85	dns := sys->open(server, Sys->ORDWR);
86	if(dns == nil){
87		sys->fprint(sys->fildes(2), "dnsquery: can't open %s: %r\n", server);
88		raise "fail:open";
89	}
90	stdout := sys->fildes(1);
91	for(i := len query; --i >= 0 && query[i] != ' ';)
92		{}
93	if(i < 0){
94		i = len query;
95		case dbattr(query) {
96		"ip" =>
97			query += " ptr";
98		* =>
99			query += " ip";
100		}
101	}
102	if(query[i+1:] == "ptr"){
103		while(i > 0 && query[i-1] == ' ')
104			i--;
105		if(!hastail(query[0:i], ".in-addr.arpa") && !hastail(query[0:i], ".IN-ADDR.ARPA"))
106			query = addr2arpa(query[0:i])+" ptr";
107	}
108	b := array of byte query;
109	if(sys->write(dns, b, len b) > 0){
110		sys->seek(dns, big 0, Sys->SEEKSTART);
111		buf := array[256] of byte;
112		while((n := sys->read(dns, buf, len buf)) > 0)
113			sys->print("%s\n", string buf[0:n]);
114		if(n == 0)
115			return;
116	}
117	sys->print("!%r\n");
118}
119
120hastail(s: string, t: string): int
121{
122	if(len s >= len t && s[len s - len t:] == t)
123		return 1;
124	return 0;
125}
126
127addr2arpa(a: string): string
128{
129	(nf, flds) := sys->tokenize(a, ".");
130	rl: list of string;
131	for(; flds != nil; flds = tl flds)
132		rl = hd flds :: rl;
133	addr: string;
134	for(; rl != nil; rl = tl rl){
135		if(addr != nil)
136			addr[len addr] = '.';
137		addr += hd rl;
138	}
139	return addr+".in-addr.arpa";
140}
141
142dbattr(s: string): string
143{
144	digit := 0;
145	dot := 0;
146	alpha := 0;
147	hex := 0;
148	colon := 0;
149	for(i := 0; i < len s; i++){
150		case c := s[i] {
151		'0' to '9' =>
152			digit = 1;
153		'a' to 'f' or 'A' to 'F' =>
154			hex = 1;
155		'.' =>
156			dot = 1;
157		':' =>
158			colon = 1;
159		* =>
160			if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '-' || c == '&')
161				alpha = 1;
162		}
163	}
164	if(alpha){
165		if(dot)
166			return "dom";
167		return "sys";
168	}
169	if(colon)
170		return "ip";
171	if(dot){
172		if(!hex)
173			return "ip";
174		return "dom";
175	}
176	return "sys";
177}
178