amd64: declare initializecpu outside of SMP
[dragonfly.git] / contrib / bind-9.3 / bin / dig / nslookup.c
blob5ae64d0d594066336eabbba4cf7284033f4eaeb0
1 /*
2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: nslookup.c,v 1.90.2.4.2.12 2006/06/09 23:50:53 marka Exp $ */
20 #include <config.h>
22 #include <stdlib.h>
24 #include <isc/app.h>
25 #include <isc/buffer.h>
26 #include <isc/commandline.h>
27 #include <isc/event.h>
28 #include <isc/parseint.h>
29 #include <isc/string.h>
30 #include <isc/timer.h>
31 #include <isc/util.h>
32 #include <isc/task.h>
33 #include <isc/netaddr.h>
35 #include <dns/message.h>
36 #include <dns/name.h>
37 #include <dns/fixedname.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdataset.h>
41 #include <dns/rdatastruct.h>
42 #include <dns/rdatatype.h>
43 #include <dns/byaddr.h>
45 #include <dig/dig.h>
47 static isc_boolean_t short_form = ISC_TRUE,
48 tcpmode = ISC_FALSE,
49 identify = ISC_FALSE, stats = ISC_TRUE,
50 comments = ISC_TRUE, section_question = ISC_TRUE,
51 section_answer = ISC_TRUE, section_authority = ISC_TRUE,
52 section_additional = ISC_TRUE, recurse = ISC_TRUE,
53 aaonly = ISC_FALSE;
54 static isc_boolean_t in_use = ISC_FALSE;
55 static char defclass[MXRD] = "IN";
56 static char deftype[MXRD] = "A";
57 static isc_event_t *global_event = NULL;
59 static char domainopt[DNS_NAME_MAXTEXT];
61 static const char *rcodetext[] = {
62 "NOERROR",
63 "FORMERR",
64 "SERVFAIL",
65 "NXDOMAIN",
66 "NOTIMP",
67 "REFUSED",
68 "YXDOMAIN",
69 "YXRRSET",
70 "NXRRSET",
71 "NOTAUTH",
72 "NOTZONE",
73 "RESERVED11",
74 "RESERVED12",
75 "RESERVED13",
76 "RESERVED14",
77 "RESERVED15",
78 "BADVERS"
81 static const char *rtypetext[] = {
82 "rtype_0 = ", /* 0 */
83 "internet address = ", /* 1 */
84 "nameserver = ", /* 2 */
85 "md = ", /* 3 */
86 "mf = ", /* 4 */
87 "canonical name = ", /* 5 */
88 "soa = ", /* 6 */
89 "mb = ", /* 7 */
90 "mg = ", /* 8 */
91 "mr = ", /* 9 */
92 "rtype_10 = ", /* 10 */
93 "protocol = ", /* 11 */
94 "name = ", /* 12 */
95 "hinfo = ", /* 13 */
96 "minfo = ", /* 14 */
97 "mail exchanger = ", /* 15 */
98 "text = ", /* 16 */
99 "rp = ", /* 17 */
100 "afsdb = ", /* 18 */
101 "x25 address = ", /* 19 */
102 "isdn address = ", /* 20 */
103 "rt = ", /* 21 */
104 "nsap = ", /* 22 */
105 "nsap_ptr = ", /* 23 */
106 "signature = ", /* 24 */
107 "key = ", /* 25 */
108 "px = ", /* 26 */
109 "gpos = ", /* 27 */
110 "has AAAA address ", /* 28 */
111 "loc = ", /* 29 */
112 "next = ", /* 30 */
113 "rtype_31 = ", /* 31 */
114 "rtype_32 = ", /* 32 */
115 "service = ", /* 33 */
116 "rtype_34 = ", /* 34 */
117 "naptr = ", /* 35 */
118 "kx = ", /* 36 */
119 "cert = ", /* 37 */
120 "v6 address = ", /* 38 */
121 "dname = ", /* 39 */
122 "rtype_40 = ", /* 40 */
123 "optional = " /* 41 */
126 #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
128 static void flush_lookup_list(void);
129 static void getinput(isc_task_t *task, isc_event_t *event);
131 void
132 dighost_shutdown(void) {
133 isc_event_t *event = global_event;
135 flush_lookup_list();
136 debug("dighost_shutdown()");
138 if (!in_use) {
139 isc_app_shutdown();
140 return;
143 isc_task_send(global_task, &event);
146 static void
147 printsoa(dns_rdata_t *rdata) {
148 dns_rdata_soa_t soa;
149 isc_result_t result;
150 char namebuf[DNS_NAME_FORMATSIZE];
152 result = dns_rdata_tostruct(rdata, &soa, NULL);
153 check_result(result, "dns_rdata_tostruct");
155 dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
156 printf("\torigin = %s\n", namebuf);
157 dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
158 printf("\tmail addr = %s\n", namebuf);
159 printf("\tserial = %u\n", soa.serial);
160 printf("\trefresh = %u\n", soa.refresh);
161 printf("\tretry = %u\n", soa.retry);
162 printf("\texpire = %u\n", soa.expire);
163 printf("\tminimum = %u\n", soa.minimum);
164 dns_rdata_freestruct(&soa);
167 static void
168 printa(dns_rdata_t *rdata) {
169 isc_result_t result;
170 char text[sizeof("255.255.255.255")];
171 isc_buffer_t b;
173 isc_buffer_init(&b, text, sizeof(text));
174 result = dns_rdata_totext(rdata, NULL, &b);
175 check_result(result, "dns_rdata_totext");
176 printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
177 (char *)isc_buffer_base(&b));
179 #ifdef DIG_SIGCHASE
180 /* Just for compatibility : not use in host program */
181 isc_result_t
182 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
183 isc_buffer_t *target)
185 UNUSED(owner_name);
186 UNUSED(rdataset);
187 UNUSED(target);
188 return(ISC_FALSE);
190 #endif
191 static void
192 printrdata(dns_rdata_t *rdata) {
193 isc_result_t result;
194 isc_buffer_t *b = NULL;
195 unsigned int size = 1024;
196 isc_boolean_t done = ISC_FALSE;
198 if (rdata->type < N_KNOWN_RRTYPES)
199 printf("%s", rtypetext[rdata->type]);
200 else
201 printf("rdata_%d = ", rdata->type);
203 while (!done) {
204 result = isc_buffer_allocate(mctx, &b, size);
205 if (result != ISC_R_SUCCESS)
206 check_result(result, "isc_buffer_allocate");
207 result = dns_rdata_totext(rdata, NULL, b);
208 if (result == ISC_R_SUCCESS) {
209 printf("%.*s\n", (int)isc_buffer_usedlength(b),
210 (char *)isc_buffer_base(b));
211 done = ISC_TRUE;
212 } else if (result != ISC_R_NOSPACE)
213 check_result(result, "dns_rdata_totext");
214 isc_buffer_free(&b);
215 size *= 2;
219 static isc_result_t
220 printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
221 dns_section_t section) {
222 isc_result_t result, loopresult;
223 dns_name_t *name;
224 dns_rdataset_t *rdataset = NULL;
225 dns_rdata_t rdata = DNS_RDATA_INIT;
226 char namebuf[DNS_NAME_FORMATSIZE];
228 UNUSED(query);
229 UNUSED(headers);
231 debug("printsection()");
233 result = dns_message_firstname(msg, section);
234 if (result == ISC_R_NOMORE)
235 return (ISC_R_SUCCESS);
236 else if (result != ISC_R_SUCCESS)
237 return (result);
238 for (;;) {
239 name = NULL;
240 dns_message_currentname(msg, section,
241 &name);
242 for (rdataset = ISC_LIST_HEAD(name->list);
243 rdataset != NULL;
244 rdataset = ISC_LIST_NEXT(rdataset, link)) {
245 loopresult = dns_rdataset_first(rdataset);
246 while (loopresult == ISC_R_SUCCESS) {
247 dns_rdataset_current(rdataset, &rdata);
248 switch (rdata.type) {
249 case dns_rdatatype_a:
250 if (section != DNS_SECTION_ANSWER)
251 goto def_short_section;
252 dns_name_format(name, namebuf,
253 sizeof(namebuf));
254 printf("Name:\t%s\n", namebuf);
255 printa(&rdata);
256 break;
257 case dns_rdatatype_soa:
258 dns_name_format(name, namebuf,
259 sizeof(namebuf));
260 printf("%s\n", namebuf);
261 printsoa(&rdata);
262 break;
263 default:
264 def_short_section:
265 dns_name_format(name, namebuf,
266 sizeof(namebuf));
267 printf("%s\t", namebuf);
268 printrdata(&rdata);
269 break;
271 dns_rdata_reset(&rdata);
272 loopresult = dns_rdataset_next(rdataset);
275 result = dns_message_nextname(msg, section);
276 if (result == ISC_R_NOMORE)
277 break;
278 else if (result != ISC_R_SUCCESS) {
279 return (result);
282 return (ISC_R_SUCCESS);
285 static isc_result_t
286 detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
287 dns_section_t section) {
288 isc_result_t result, loopresult;
289 dns_name_t *name;
290 dns_rdataset_t *rdataset = NULL;
291 dns_rdata_t rdata = DNS_RDATA_INIT;
292 char namebuf[DNS_NAME_FORMATSIZE];
294 UNUSED(query);
296 debug("detailsection()");
298 if (headers) {
299 switch (section) {
300 case DNS_SECTION_QUESTION:
301 puts(" QUESTIONS:");
302 break;
303 case DNS_SECTION_ANSWER:
304 puts(" ANSWERS:");
305 break;
306 case DNS_SECTION_AUTHORITY:
307 puts(" AUTHORITY RECORDS:");
308 break;
309 case DNS_SECTION_ADDITIONAL:
310 puts(" ADDITIONAL RECORDS:");
311 break;
315 result = dns_message_firstname(msg, section);
316 if (result == ISC_R_NOMORE)
317 return (ISC_R_SUCCESS);
318 else if (result != ISC_R_SUCCESS)
319 return (result);
320 for (;;) {
321 name = NULL;
322 dns_message_currentname(msg, section,
323 &name);
324 for (rdataset = ISC_LIST_HEAD(name->list);
325 rdataset != NULL;
326 rdataset = ISC_LIST_NEXT(rdataset, link)) {
327 if (section == DNS_SECTION_QUESTION) {
328 dns_name_format(name, namebuf,
329 sizeof(namebuf));
330 printf("\t%s, ", namebuf);
331 dns_rdatatype_format(rdataset->type,
332 namebuf,
333 sizeof(namebuf));
334 printf("type = %s, ", namebuf);
335 dns_rdataclass_format(rdataset->rdclass,
336 namebuf,
337 sizeof(namebuf));
338 printf("class = %s\n", namebuf);
340 loopresult = dns_rdataset_first(rdataset);
341 while (loopresult == ISC_R_SUCCESS) {
342 dns_rdataset_current(rdataset, &rdata);
344 dns_name_format(name, namebuf,
345 sizeof(namebuf));
346 printf(" -> %s\n", namebuf);
348 switch (rdata.type) {
349 case dns_rdatatype_soa:
350 printsoa(&rdata);
351 break;
352 default:
353 printf("\t");
354 printrdata(&rdata);
356 dns_rdata_reset(&rdata);
357 loopresult = dns_rdataset_next(rdataset);
360 result = dns_message_nextname(msg, section);
361 if (result == ISC_R_NOMORE)
362 break;
363 else if (result != ISC_R_SUCCESS) {
364 return (result);
367 return (ISC_R_SUCCESS);
370 void
371 received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
373 UNUSED(bytes);
374 UNUSED(from);
375 UNUSED(query);
378 void
379 trying(char *frm, dig_lookup_t *lookup) {
380 UNUSED(frm);
381 UNUSED(lookup);
385 isc_result_t
386 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
387 char servtext[ISC_SOCKADDR_FORMATSIZE];
389 debug("printmessage()");
391 isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
392 printf("Server:\t\t%s\n", query->userarg);
393 printf("Address:\t%s\n", servtext);
395 puts("");
397 if (!short_form) {
398 isc_boolean_t headers = ISC_TRUE;
399 puts("------------");
400 /* detailheader(query, msg);*/
401 detailsection(query, msg, headers, DNS_SECTION_QUESTION);
402 detailsection(query, msg, headers, DNS_SECTION_ANSWER);
403 detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
404 detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
405 puts("------------");
408 if (msg->rcode != 0) {
409 char nametext[DNS_NAME_FORMATSIZE];
410 dns_name_format(query->lookup->name,
411 nametext, sizeof(nametext));
412 printf("** server can't find %s: %s\n", nametext,
413 rcodetext[msg->rcode]);
414 debug("returning with rcode == 0");
415 return (ISC_R_SUCCESS);
418 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
419 puts("Non-authoritative answer:");
420 if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
421 printsection(query, msg, headers, DNS_SECTION_ANSWER);
422 else
423 printf("*** Can't find %s: No answer\n",
424 query->lookup->textname);
426 if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
427 (query->lookup->rdtype != dns_rdatatype_a)) {
428 puts("\nAuthoritative answers can be found from:");
429 printsection(query, msg, headers,
430 DNS_SECTION_AUTHORITY);
431 printsection(query, msg, headers,
432 DNS_SECTION_ADDITIONAL);
434 return (ISC_R_SUCCESS);
437 static void
438 show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
439 dig_server_t *srv;
440 isc_sockaddr_t sockaddr;
441 dig_searchlist_t *listent;
443 srv = ISC_LIST_HEAD(server_list);
445 while (srv != NULL) {
446 char sockstr[ISC_SOCKADDR_FORMATSIZE];
448 get_address(srv->servername, port, &sockaddr);
449 isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
450 printf("Default server: %s\nAddress: %s\n",
451 srv->userarg, sockstr);
452 if (!full)
453 return;
454 srv = ISC_LIST_NEXT(srv, link);
456 if (serv_only)
457 return;
458 printf("\nSet options:\n");
459 printf(" %s\t\t\t%s\t\t%s\n",
460 tcpmode ? "vc" : "novc",
461 short_form ? "nodebug" : "debug",
462 debugging ? "d2" : "nod2");
463 printf(" %s\t\t%s\n",
464 usesearch ? "search" : "nosearch",
465 recurse ? "recurse" : "norecurse");
466 printf(" timeout = %d\t\tretry = %d\tport = %d\n",
467 timeout, tries, port);
468 printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
469 printf(" srchlist = ");
470 for (listent = ISC_LIST_HEAD(search_list);
471 listent != NULL;
472 listent = ISC_LIST_NEXT(listent, link)) {
473 printf("%s", listent->origin);
474 if (ISC_LIST_NEXT(listent, link) != NULL)
475 printf("/");
477 printf("\n");
480 static isc_boolean_t
481 testtype(char *typetext) {
482 isc_result_t result;
483 isc_textregion_t tr;
484 dns_rdatatype_t rdtype;
486 tr.base = typetext;
487 tr.length = strlen(typetext);
488 result = dns_rdatatype_fromtext(&rdtype, &tr);
489 if (result == ISC_R_SUCCESS)
490 return (ISC_TRUE);
491 else {
492 printf("unknown query type: %s\n", typetext);
493 return (ISC_FALSE);
497 static isc_boolean_t
498 testclass(char *typetext) {
499 isc_result_t result;
500 isc_textregion_t tr;
501 dns_rdataclass_t rdclass;
503 tr.base = typetext;
504 tr.length = strlen(typetext);
505 result = dns_rdataclass_fromtext(&rdclass, &tr);
506 if (result == ISC_R_SUCCESS)
507 return (ISC_TRUE);
508 else {
509 printf("unknown query class: %s\n", typetext);
510 return (ISC_FALSE);
514 static void
515 safecpy(char *dest, char *src, int size) {
516 strncpy(dest, src, size);
517 dest[size-1] = 0;
520 static isc_result_t
521 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
522 const char *desc) {
523 isc_uint32_t n;
524 isc_result_t result = isc_parse_uint32(&n, value, 10);
525 if (result == ISC_R_SUCCESS && n > max)
526 result = ISC_R_RANGE;
527 if (result != ISC_R_SUCCESS) {
528 printf("invalid %s '%s': %s\n", desc,
529 value, isc_result_totext(result));
530 return result;
532 *uip = n;
533 return (ISC_R_SUCCESS);
536 static void
537 set_port(const char *value) {
538 isc_uint32_t n;
539 isc_result_t result = parse_uint(&n, value, 65535, "port");
540 if (result == ISC_R_SUCCESS)
541 port = (isc_uint16_t) n;
544 static void
545 set_timeout(const char *value) {
546 isc_uint32_t n;
547 isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
548 if (result == ISC_R_SUCCESS)
549 timeout = n;
552 static void
553 set_tries(const char *value) {
554 isc_uint32_t n;
555 isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
556 if (result == ISC_R_SUCCESS)
557 tries = n;
560 static void
561 setoption(char *opt) {
562 if (strncasecmp(opt, "all", 4) == 0) {
563 show_settings(ISC_TRUE, ISC_FALSE);
564 } else if (strncasecmp(opt, "class=", 6) == 0) {
565 if (testclass(&opt[6]))
566 safecpy(defclass, &opt[6], sizeof(defclass));
567 } else if (strncasecmp(opt, "cl=", 3) == 0) {
568 if (testclass(&opt[3]))
569 safecpy(defclass, &opt[3], sizeof(defclass));
570 } else if (strncasecmp(opt, "type=", 5) == 0) {
571 if (testtype(&opt[5]))
572 safecpy(deftype, &opt[5], sizeof(deftype));
573 } else if (strncasecmp(opt, "ty=", 3) == 0) {
574 if (testtype(&opt[3]))
575 safecpy(deftype, &opt[3], sizeof(deftype));
576 } else if (strncasecmp(opt, "querytype=", 10) == 0) {
577 if (testtype(&opt[10]))
578 safecpy(deftype, &opt[10], sizeof(deftype));
579 } else if (strncasecmp(opt, "query=", 6) == 0) {
580 if (testtype(&opt[6]))
581 safecpy(deftype, &opt[6], sizeof(deftype));
582 } else if (strncasecmp(opt, "qu=", 3) == 0) {
583 if (testtype(&opt[3]))
584 safecpy(deftype, &opt[3], sizeof(deftype));
585 } else if (strncasecmp(opt, "q=", 2) == 0) {
586 if (testtype(&opt[2]))
587 safecpy(deftype, &opt[2], sizeof(deftype));
588 } else if (strncasecmp(opt, "domain=", 7) == 0) {
589 safecpy(domainopt, &opt[7], sizeof(domainopt));
590 set_search_domain(domainopt);
591 usesearch = ISC_TRUE;
592 } else if (strncasecmp(opt, "do=", 3) == 0) {
593 safecpy(domainopt, &opt[3], sizeof(domainopt));
594 set_search_domain(domainopt);
595 usesearch = ISC_TRUE;
596 } else if (strncasecmp(opt, "port=", 5) == 0) {
597 set_port(&opt[5]);
598 } else if (strncasecmp(opt, "po=", 3) == 0) {
599 set_port(&opt[3]);
600 } else if (strncasecmp(opt, "timeout=", 8) == 0) {
601 set_timeout(&opt[8]);
602 } else if (strncasecmp(opt, "t=", 2) == 0) {
603 set_timeout(&opt[2]);
604 } else if (strncasecmp(opt, "rec", 3) == 0) {
605 recurse = ISC_TRUE;
606 } else if (strncasecmp(opt, "norec", 5) == 0) {
607 recurse = ISC_FALSE;
608 } else if (strncasecmp(opt, "retry=", 6) == 0) {
609 set_tries(&opt[6]);
610 } else if (strncasecmp(opt, "ret=", 4) == 0) {
611 set_tries(&opt[4]);
612 } else if (strncasecmp(opt, "def", 3) == 0) {
613 usesearch = ISC_TRUE;
614 } else if (strncasecmp(opt, "nodef", 5) == 0) {
615 usesearch = ISC_FALSE;
616 } else if (strncasecmp(opt, "vc", 3) == 0) {
617 tcpmode = ISC_TRUE;
618 } else if (strncasecmp(opt, "novc", 5) == 0) {
619 tcpmode = ISC_FALSE;
620 } else if (strncasecmp(opt, "deb", 3) == 0) {
621 short_form = ISC_FALSE;
622 } else if (strncasecmp(opt, "nodeb", 5) == 0) {
623 short_form = ISC_TRUE;
624 } else if (strncasecmp(opt, "d2", 2) == 0) {
625 debugging = ISC_TRUE;
626 } else if (strncasecmp(opt, "nod2", 4) == 0) {
627 debugging = ISC_FALSE;
628 } else if (strncasecmp(opt, "search", 3) == 0) {
629 usesearch = ISC_TRUE;
630 } else if (strncasecmp(opt, "nosearch", 5) == 0) {
631 usesearch = ISC_FALSE;
632 } else if (strncasecmp(opt, "sil", 3) == 0) {
633 /* deprecation_msg = ISC_FALSE; */
634 } else {
635 printf("*** Invalid option: %s\n", opt);
639 static void
640 addlookup(char *opt) {
641 dig_lookup_t *lookup;
642 isc_result_t result;
643 isc_textregion_t tr;
644 dns_rdatatype_t rdtype;
645 dns_rdataclass_t rdclass;
646 char store[MXNAME];
648 debug("addlookup()");
649 tr.base = deftype;
650 tr.length = strlen(deftype);
651 result = dns_rdatatype_fromtext(&rdtype, &tr);
652 if (result != ISC_R_SUCCESS) {
653 printf("unknown query type: %s\n", deftype);
654 rdclass = dns_rdatatype_a;
656 tr.base = defclass;
657 tr.length = strlen(defclass);
658 result = dns_rdataclass_fromtext(&rdclass, &tr);
659 if (result != ISC_R_SUCCESS) {
660 printf("unknown query class: %s\n", defclass);
661 rdclass = dns_rdataclass_in;
663 lookup = make_empty_lookup();
664 if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
665 == ISC_R_SUCCESS) {
666 safecpy(lookup->textname, store, sizeof(lookup->textname));
667 lookup->rdtype = dns_rdatatype_ptr;
668 lookup->rdtypeset = ISC_TRUE;
669 } else {
670 safecpy(lookup->textname, opt, sizeof(lookup->textname));
671 lookup->rdtype = rdtype;
672 lookup->rdtypeset = ISC_TRUE;
674 lookup->rdclass = rdclass;
675 lookup->rdclassset = ISC_TRUE;
676 lookup->trace = ISC_FALSE;
677 lookup->trace_root = lookup->trace;
678 lookup->ns_search_only = ISC_FALSE;
679 lookup->identify = identify;
680 lookup->recurse = recurse;
681 lookup->aaonly = aaonly;
682 lookup->retries = tries;
683 lookup->udpsize = 0;
684 lookup->comments = comments;
685 lookup->tcp_mode = tcpmode;
686 lookup->stats = stats;
687 lookup->section_question = section_question;
688 lookup->section_answer = section_answer;
689 lookup->section_authority = section_authority;
690 lookup->section_additional = section_additional;
691 lookup->new_search = ISC_TRUE;
692 ISC_LIST_INIT(lookup->q);
693 ISC_LINK_INIT(lookup, link);
694 ISC_LIST_APPEND(lookup_list, lookup, link);
695 lookup->origin = NULL;
696 ISC_LIST_INIT(lookup->my_server_list);
697 debug("looking up %s", lookup->textname);
700 static void
701 get_next_command(void) {
702 char *buf;
703 char *ptr, *arg;
704 char *input;
706 fflush(stdout);
707 buf = isc_mem_allocate(mctx, COMMSIZE);
708 if (buf == NULL)
709 fatal("memory allocation failure");
710 fputs("> ", stderr);
711 fflush(stderr);
712 isc_app_block();
713 ptr = fgets(buf, COMMSIZE, stdin);
714 isc_app_unblock();
715 if (ptr == NULL) {
716 in_use = ISC_FALSE;
717 goto cleanup;
719 input = buf;
720 ptr = next_token(&input, " \t\r\n");
721 if (ptr == NULL)
722 goto cleanup;
723 arg = next_token(&input, " \t\r\n");
724 if ((strcasecmp(ptr, "set") == 0) &&
725 (arg != NULL))
726 setoption(arg);
727 else if ((strcasecmp(ptr, "server") == 0) ||
728 (strcasecmp(ptr, "lserver") == 0)) {
729 isc_app_block();
730 set_nameserver(arg);
731 isc_app_unblock();
732 show_settings(ISC_TRUE, ISC_TRUE);
733 } else if (strcasecmp(ptr, "exit") == 0) {
734 in_use = ISC_FALSE;
735 goto cleanup;
736 } else if (strcasecmp(ptr, "help") == 0 ||
737 strcasecmp(ptr, "?") == 0) {
738 printf("The '%s' command is not yet implemented.\n", ptr);
739 goto cleanup;
740 } else if (strcasecmp(ptr, "finger") == 0 ||
741 strcasecmp(ptr, "root") == 0 ||
742 strcasecmp(ptr, "ls") == 0 ||
743 strcasecmp(ptr, "view") == 0) {
744 printf("The '%s' command is not implemented.\n", ptr);
745 goto cleanup;
746 } else
747 addlookup(ptr);
748 cleanup:
749 isc_mem_free(mctx, buf);
752 static void
753 parse_args(int argc, char **argv) {
754 isc_boolean_t have_lookup = ISC_FALSE;
756 usesearch = ISC_TRUE;
757 for (argc--, argv++; argc > 0; argc--, argv++) {
758 debug("main parsing %s", argv[0]);
759 if (argv[0][0] == '-') {
760 if (argv[0][1] != 0)
761 setoption(&argv[0][1]);
762 else
763 have_lookup = ISC_TRUE;
764 } else {
765 if (!have_lookup) {
766 have_lookup = ISC_TRUE;
767 in_use = ISC_TRUE;
768 addlookup(argv[0]);
770 else
771 set_nameserver(argv[0]);
776 static void
777 flush_lookup_list(void) {
778 dig_lookup_t *l, *lp;
779 dig_query_t *q, *qp;
780 dig_server_t *s, *sp;
782 lookup_counter = 0;
783 l = ISC_LIST_HEAD(lookup_list);
784 while (l != NULL) {
785 q = ISC_LIST_HEAD(l->q);
786 while (q != NULL) {
787 if (q->sock != NULL) {
788 isc_socket_cancel(q->sock, NULL,
789 ISC_SOCKCANCEL_ALL);
790 isc_socket_detach(&q->sock);
792 if (ISC_LINK_LINKED(&q->recvbuf, link))
793 ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
794 link);
795 if (ISC_LINK_LINKED(&q->lengthbuf, link))
796 ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
797 link);
798 isc_buffer_invalidate(&q->recvbuf);
799 isc_buffer_invalidate(&q->lengthbuf);
800 qp = q;
801 q = ISC_LIST_NEXT(q, link);
802 ISC_LIST_DEQUEUE(l->q, qp, link);
803 isc_mem_free(mctx, qp);
805 s = ISC_LIST_HEAD(l->my_server_list);
806 while (s != NULL) {
807 sp = s;
808 s = ISC_LIST_NEXT(s, link);
809 ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
810 isc_mem_free(mctx, sp);
813 if (l->sendmsg != NULL)
814 dns_message_destroy(&l->sendmsg);
815 if (l->timer != NULL)
816 isc_timer_detach(&l->timer);
817 lp = l;
818 l = ISC_LIST_NEXT(l, link);
819 ISC_LIST_DEQUEUE(lookup_list, lp, link);
820 isc_mem_free(mctx, lp);
824 static void
825 getinput(isc_task_t *task, isc_event_t *event) {
826 UNUSED(task);
827 if (global_event == NULL)
828 global_event = event;
829 while (in_use) {
830 get_next_command();
831 if (ISC_LIST_HEAD(lookup_list) != NULL) {
832 start_lookup();
833 return;
836 isc_app_shutdown();
840 main(int argc, char **argv) {
841 isc_result_t result;
843 ISC_LIST_INIT(lookup_list);
844 ISC_LIST_INIT(server_list);
845 ISC_LIST_INIT(search_list);
847 result = isc_app_start();
848 check_result(result, "isc_app_start");
850 setup_libs();
851 progname = argv[0];
853 parse_args(argc, argv);
855 setup_system();
856 if (domainopt[0] != '\0')
857 set_search_domain(domainopt);
858 if (in_use)
859 result = isc_app_onrun(mctx, global_task, onrun_callback,
860 NULL);
861 else
862 result = isc_app_onrun(mctx, global_task, getinput, NULL);
863 check_result(result, "isc_app_onrun");
864 in_use = ISC_TF(!in_use);
866 (void)isc_app_run();
868 puts("");
869 debug("done, and starting to shut down");
870 if (global_event != NULL)
871 isc_event_free(&global_event);
872 cancel_all();
873 destroy_libs();
874 isc_app_finish();
876 return (0);