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