2 * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.117.334.5 2009/10/20 01:11:22 marka Exp $ */
25 #include <isc/buffer.h>
26 #include <isc/commandline.h>
27 #include <isc/event.h>
28 #include <isc/parseint.h>
29 #include <isc/print.h>
30 #include <isc/string.h>
31 #include <isc/timer.h>
34 #include <isc/netaddr.h>
36 #include <dns/message.h>
38 #include <dns/fixedname.h>
39 #include <dns/rdata.h>
40 #include <dns/rdataclass.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/rdatatype.h>
44 #include <dns/byaddr.h>
48 static isc_boolean_t short_form = ISC_TRUE,
50 identify = ISC_FALSE, stats = ISC_TRUE,
51 comments = ISC_TRUE, section_question = ISC_TRUE,
52 section_answer = ISC_TRUE, section_authority = ISC_TRUE,
53 section_additional = ISC_TRUE, recurse = ISC_TRUE,
54 aaonly = ISC_FALSE, nofail = ISC_TRUE;
56 static isc_boolean_t in_use = ISC_FALSE;
57 static char defclass[MXRD] = "IN";
58 static char deftype[MXRD] = "A";
59 static isc_event_t *global_event = NULL;
61 static char domainopt[DNS_NAME_MAXTEXT];
63 static const char *rcodetext[] = {
83 static const char *rtypetext[] = {
85 "internet address = ", /* 1 */
86 "nameserver = ", /* 2 */
89 "canonical name = ", /* 5 */
94 "rtype_10 = ", /* 10 */
95 "protocol = ", /* 11 */
99 "mail exchanger = ", /* 15 */
103 "x25 address = ", /* 19 */
104 "isdn address = ", /* 20 */
107 "nsap_ptr = ", /* 23 */
108 "signature = ", /* 24 */
112 "has AAAA address ", /* 28 */
115 "rtype_31 = ", /* 31 */
116 "rtype_32 = ", /* 32 */
117 "service = ", /* 33 */
118 "rtype_34 = ", /* 34 */
122 "v6 address = ", /* 38 */
124 "rtype_40 = ", /* 40 */
125 "optional = " /* 41 */
128 #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
130 static void flush_lookup_list(void);
131 static void getinput(isc_task_t *task, isc_event_t *event);
134 rcode_totext(dns_rcode_t rcode)
136 static char buf[sizeof("?65535")];
138 const char *consttext;
142 if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
143 snprintf(buf, sizeof(buf), "?%u", rcode);
144 totext.deconsttext = buf;
146 totext.consttext = rcodetext[rcode];
147 return totext.deconsttext;
151 dighost_shutdown(void) {
152 isc_event_t *event = global_event;
155 debug("dighost_shutdown()");
162 isc_task_send(global_task, &event);
166 printsoa(dns_rdata_t *rdata) {
169 char namebuf[DNS_NAME_FORMATSIZE];
171 result = dns_rdata_tostruct(rdata, &soa, NULL);
172 check_result(result, "dns_rdata_tostruct");
174 dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
175 printf("\torigin = %s\n", namebuf);
176 dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
177 printf("\tmail addr = %s\n", namebuf);
178 printf("\tserial = %u\n", soa.serial);
179 printf("\trefresh = %u\n", soa.refresh);
180 printf("\tretry = %u\n", soa.retry);
181 printf("\texpire = %u\n", soa.expire);
182 printf("\tminimum = %u\n", soa.minimum);
183 dns_rdata_freestruct(&soa);
187 printa(dns_rdata_t *rdata) {
189 char text[sizeof("255.255.255.255")];
192 isc_buffer_init(&b, text, sizeof(text));
193 result = dns_rdata_totext(rdata, NULL, &b);
194 check_result(result, "dns_rdata_totext");
195 printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
196 (char *)isc_buffer_base(&b));
199 /* Just for compatibility : not use in host program */
201 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
202 isc_buffer_t *target)
211 printrdata(dns_rdata_t *rdata) {
213 isc_buffer_t *b = NULL;
214 unsigned int size = 1024;
215 isc_boolean_t done = ISC_FALSE;
217 if (rdata->type < N_KNOWN_RRTYPES)
218 printf("%s", rtypetext[rdata->type]);
220 printf("rdata_%d = ", rdata->type);
223 result = isc_buffer_allocate(mctx, &b, size);
224 if (result != ISC_R_SUCCESS)
225 check_result(result, "isc_buffer_allocate");
226 result = dns_rdata_totext(rdata, NULL, b);
227 if (result == ISC_R_SUCCESS) {
228 printf("%.*s\n", (int)isc_buffer_usedlength(b),
229 (char *)isc_buffer_base(b));
231 } else if (result != ISC_R_NOSPACE)
232 check_result(result, "dns_rdata_totext");
239 printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
240 dns_section_t section) {
241 isc_result_t result, loopresult;
243 dns_rdataset_t *rdataset = NULL;
244 dns_rdata_t rdata = DNS_RDATA_INIT;
245 char namebuf[DNS_NAME_FORMATSIZE];
250 debug("printsection()");
252 result = dns_message_firstname(msg, section);
253 if (result == ISC_R_NOMORE)
254 return (ISC_R_SUCCESS);
255 else if (result != ISC_R_SUCCESS)
259 dns_message_currentname(msg, section,
261 for (rdataset = ISC_LIST_HEAD(name->list);
263 rdataset = ISC_LIST_NEXT(rdataset, link)) {
264 loopresult = dns_rdataset_first(rdataset);
265 while (loopresult == ISC_R_SUCCESS) {
266 dns_rdataset_current(rdataset, &rdata);
267 switch (rdata.type) {
268 case dns_rdatatype_a:
269 if (section != DNS_SECTION_ANSWER)
270 goto def_short_section;
271 dns_name_format(name, namebuf,
273 printf("Name:\t%s\n", namebuf);
276 case dns_rdatatype_soa:
277 dns_name_format(name, namebuf,
279 printf("%s\n", namebuf);
284 dns_name_format(name, namebuf,
286 printf("%s\t", namebuf);
290 dns_rdata_reset(&rdata);
291 loopresult = dns_rdataset_next(rdataset);
294 result = dns_message_nextname(msg, section);
295 if (result == ISC_R_NOMORE)
297 else if (result != ISC_R_SUCCESS) {
301 return (ISC_R_SUCCESS);
305 detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
306 dns_section_t section) {
307 isc_result_t result, loopresult;
309 dns_rdataset_t *rdataset = NULL;
310 dns_rdata_t rdata = DNS_RDATA_INIT;
311 char namebuf[DNS_NAME_FORMATSIZE];
315 debug("detailsection()");
319 case DNS_SECTION_QUESTION:
322 case DNS_SECTION_ANSWER:
325 case DNS_SECTION_AUTHORITY:
326 puts(" AUTHORITY RECORDS:");
328 case DNS_SECTION_ADDITIONAL:
329 puts(" ADDITIONAL RECORDS:");
334 result = dns_message_firstname(msg, section);
335 if (result == ISC_R_NOMORE)
336 return (ISC_R_SUCCESS);
337 else if (result != ISC_R_SUCCESS)
341 dns_message_currentname(msg, section,
343 for (rdataset = ISC_LIST_HEAD(name->list);
345 rdataset = ISC_LIST_NEXT(rdataset, link)) {
346 if (section == DNS_SECTION_QUESTION) {
347 dns_name_format(name, namebuf,
349 printf("\t%s, ", namebuf);
350 dns_rdatatype_format(rdataset->type,
353 printf("type = %s, ", namebuf);
354 dns_rdataclass_format(rdataset->rdclass,
357 printf("class = %s\n", namebuf);
359 loopresult = dns_rdataset_first(rdataset);
360 while (loopresult == ISC_R_SUCCESS) {
361 dns_rdataset_current(rdataset, &rdata);
363 dns_name_format(name, namebuf,
365 printf(" -> %s\n", namebuf);
367 switch (rdata.type) {
368 case dns_rdatatype_soa:
375 dns_rdata_reset(&rdata);
376 printf("\tttl = %u\n", rdataset->ttl);
377 loopresult = dns_rdataset_next(rdataset);
380 result = dns_message_nextname(msg, section);
381 if (result == ISC_R_NOMORE)
383 else if (result != ISC_R_SUCCESS) {
387 return (ISC_R_SUCCESS);
391 received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
399 trying(char *frm, dig_lookup_t *lookup) {
406 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
407 char servtext[ISC_SOCKADDR_FORMATSIZE];
409 debug("printmessage()");
411 isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
412 printf("Server:\t\t%s\n", query->userarg);
413 printf("Address:\t%s\n", servtext);
418 isc_boolean_t headers = ISC_TRUE;
419 puts("------------");
420 /* detailheader(query, msg);*/
421 detailsection(query, msg, headers, DNS_SECTION_QUESTION);
422 detailsection(query, msg, headers, DNS_SECTION_ANSWER);
423 detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
424 detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
425 puts("------------");
428 if (msg->rcode != 0) {
429 char nametext[DNS_NAME_FORMATSIZE];
430 dns_name_format(query->lookup->name,
431 nametext, sizeof(nametext));
432 printf("** server can't find %s: %s\n",
433 (msg->rcode != dns_rcode_nxdomain) ? nametext :
434 query->lookup->textname, rcode_totext(msg->rcode));
435 debug("returning with rcode == 0");
436 return (ISC_R_SUCCESS);
439 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
440 puts("Non-authoritative answer:");
441 if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
442 printsection(query, msg, headers, DNS_SECTION_ANSWER);
444 printf("*** Can't find %s: No answer\n",
445 query->lookup->textname);
447 if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
448 (query->lookup->rdtype != dns_rdatatype_a)) {
449 puts("\nAuthoritative answers can be found from:");
450 printsection(query, msg, headers,
451 DNS_SECTION_AUTHORITY);
452 printsection(query, msg, headers,
453 DNS_SECTION_ADDITIONAL);
455 return (ISC_R_SUCCESS);
459 show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
461 isc_sockaddr_t sockaddr;
462 dig_searchlist_t *listent;
465 srv = ISC_LIST_HEAD(server_list);
467 while (srv != NULL) {
468 char sockstr[ISC_SOCKADDR_FORMATSIZE];
470 result = get_address(srv->servername, port, &sockaddr);
471 check_result(result, "get_address");
473 isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
474 printf("Default server: %s\nAddress: %s\n",
475 srv->userarg, sockstr);
478 srv = ISC_LIST_NEXT(srv, link);
482 printf("\nSet options:\n");
483 printf(" %s\t\t\t%s\t\t%s\n",
484 tcpmode ? "vc" : "novc",
485 short_form ? "nodebug" : "debug",
486 debugging ? "d2" : "nod2");
487 printf(" %s\t\t%s\n",
488 usesearch ? "search" : "nosearch",
489 recurse ? "recurse" : "norecurse");
490 printf(" timeout = %d\t\tretry = %d\tport = %d\n",
491 timeout, tries, port);
492 printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
493 printf(" srchlist = ");
494 for (listent = ISC_LIST_HEAD(search_list);
496 listent = ISC_LIST_NEXT(listent, link)) {
497 printf("%s", listent->origin);
498 if (ISC_LIST_NEXT(listent, link) != NULL)
505 testtype(char *typetext) {
508 dns_rdatatype_t rdtype;
511 tr.length = strlen(typetext);
512 result = dns_rdatatype_fromtext(&rdtype, &tr);
513 if (result == ISC_R_SUCCESS)
516 printf("unknown query type: %s\n", typetext);
522 testclass(char *typetext) {
525 dns_rdataclass_t rdclass;
528 tr.length = strlen(typetext);
529 result = dns_rdataclass_fromtext(&rdclass, &tr);
530 if (result == ISC_R_SUCCESS)
533 printf("unknown query class: %s\n", typetext);
539 safecpy(char *dest, char *src, int size) {
540 strncpy(dest, src, size);
545 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
548 isc_result_t result = isc_parse_uint32(&n, value, 10);
549 if (result == ISC_R_SUCCESS && n > max)
550 result = ISC_R_RANGE;
551 if (result != ISC_R_SUCCESS) {
552 printf("invalid %s '%s': %s\n", desc,
553 value, isc_result_totext(result));
557 return (ISC_R_SUCCESS);
561 set_port(const char *value) {
563 isc_result_t result = parse_uint(&n, value, 65535, "port");
564 if (result == ISC_R_SUCCESS)
565 port = (isc_uint16_t) n;
569 set_timeout(const char *value) {
571 isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
572 if (result == ISC_R_SUCCESS)
577 set_tries(const char *value) {
579 isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
580 if (result == ISC_R_SUCCESS)
585 setoption(char *opt) {
586 if (strncasecmp(opt, "all", 4) == 0) {
587 show_settings(ISC_TRUE, ISC_FALSE);
588 } else if (strncasecmp(opt, "class=", 6) == 0) {
589 if (testclass(&opt[6]))
590 safecpy(defclass, &opt[6], sizeof(defclass));
591 } else if (strncasecmp(opt, "cl=", 3) == 0) {
592 if (testclass(&opt[3]))
593 safecpy(defclass, &opt[3], sizeof(defclass));
594 } else if (strncasecmp(opt, "type=", 5) == 0) {
595 if (testtype(&opt[5]))
596 safecpy(deftype, &opt[5], sizeof(deftype));
597 } else if (strncasecmp(opt, "ty=", 3) == 0) {
598 if (testtype(&opt[3]))
599 safecpy(deftype, &opt[3], sizeof(deftype));
600 } else if (strncasecmp(opt, "querytype=", 10) == 0) {
601 if (testtype(&opt[10]))
602 safecpy(deftype, &opt[10], sizeof(deftype));
603 } else if (strncasecmp(opt, "query=", 6) == 0) {
604 if (testtype(&opt[6]))
605 safecpy(deftype, &opt[6], sizeof(deftype));
606 } else if (strncasecmp(opt, "qu=", 3) == 0) {
607 if (testtype(&opt[3]))
608 safecpy(deftype, &opt[3], sizeof(deftype));
609 } else if (strncasecmp(opt, "q=", 2) == 0) {
610 if (testtype(&opt[2]))
611 safecpy(deftype, &opt[2], sizeof(deftype));
612 } else if (strncasecmp(opt, "domain=", 7) == 0) {
613 safecpy(domainopt, &opt[7], sizeof(domainopt));
614 set_search_domain(domainopt);
615 usesearch = ISC_TRUE;
616 } else if (strncasecmp(opt, "do=", 3) == 0) {
617 safecpy(domainopt, &opt[3], sizeof(domainopt));
618 set_search_domain(domainopt);
619 usesearch = ISC_TRUE;
620 } else if (strncasecmp(opt, "port=", 5) == 0) {
622 } else if (strncasecmp(opt, "po=", 3) == 0) {
624 } else if (strncasecmp(opt, "timeout=", 8) == 0) {
625 set_timeout(&opt[8]);
626 } else if (strncasecmp(opt, "t=", 2) == 0) {
627 set_timeout(&opt[2]);
628 } else if (strncasecmp(opt, "rec", 3) == 0) {
630 } else if (strncasecmp(opt, "norec", 5) == 0) {
632 } else if (strncasecmp(opt, "retry=", 6) == 0) {
634 } else if (strncasecmp(opt, "ret=", 4) == 0) {
636 } else if (strncasecmp(opt, "def", 3) == 0) {
637 usesearch = ISC_TRUE;
638 } else if (strncasecmp(opt, "nodef", 5) == 0) {
639 usesearch = ISC_FALSE;
640 } else if (strncasecmp(opt, "vc", 3) == 0) {
642 } else if (strncasecmp(opt, "novc", 5) == 0) {
644 } else if (strncasecmp(opt, "deb", 3) == 0) {
645 short_form = ISC_FALSE;
646 showsearch = ISC_TRUE;
647 } else if (strncasecmp(opt, "nodeb", 5) == 0) {
648 short_form = ISC_TRUE;
649 showsearch = ISC_FALSE;
650 } else if (strncasecmp(opt, "d2", 2) == 0) {
651 debugging = ISC_TRUE;
652 } else if (strncasecmp(opt, "nod2", 4) == 0) {
653 debugging = ISC_FALSE;
654 } else if (strncasecmp(opt, "search", 3) == 0) {
655 usesearch = ISC_TRUE;
656 } else if (strncasecmp(opt, "nosearch", 5) == 0) {
657 usesearch = ISC_FALSE;
658 } else if (strncasecmp(opt, "sil", 3) == 0) {
659 /* deprecation_msg = ISC_FALSE; */
660 } else if (strncasecmp(opt, "fail", 3) == 0) {
662 } else if (strncasecmp(opt, "nofail", 3) == 0) {
665 printf("*** Invalid option: %s\n", opt);
670 addlookup(char *opt) {
671 dig_lookup_t *lookup;
674 dns_rdatatype_t rdtype;
675 dns_rdataclass_t rdclass;
678 debug("addlookup()");
680 tr.length = strlen(deftype);
681 result = dns_rdatatype_fromtext(&rdtype, &tr);
682 if (result != ISC_R_SUCCESS) {
683 printf("unknown query type: %s\n", deftype);
684 rdclass = dns_rdatatype_a;
687 tr.length = strlen(defclass);
688 result = dns_rdataclass_fromtext(&rdclass, &tr);
689 if (result != ISC_R_SUCCESS) {
690 printf("unknown query class: %s\n", defclass);
691 rdclass = dns_rdataclass_in;
693 lookup = make_empty_lookup();
694 if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
696 safecpy(lookup->textname, store, sizeof(lookup->textname));
697 lookup->rdtype = dns_rdatatype_ptr;
698 lookup->rdtypeset = ISC_TRUE;
700 safecpy(lookup->textname, opt, sizeof(lookup->textname));
701 lookup->rdtype = rdtype;
702 lookup->rdtypeset = ISC_TRUE;
704 lookup->rdclass = rdclass;
705 lookup->rdclassset = ISC_TRUE;
706 lookup->trace = ISC_FALSE;
707 lookup->trace_root = lookup->trace;
708 lookup->ns_search_only = ISC_FALSE;
709 lookup->identify = identify;
710 lookup->recurse = recurse;
711 lookup->aaonly = aaonly;
712 lookup->retries = tries;
714 lookup->comments = comments;
715 lookup->tcp_mode = tcpmode;
716 lookup->stats = stats;
717 lookup->section_question = section_question;
718 lookup->section_answer = section_answer;
719 lookup->section_authority = section_authority;
720 lookup->section_additional = section_additional;
721 lookup->new_search = ISC_TRUE;
723 lookup->servfail_stops = ISC_FALSE;
724 ISC_LIST_INIT(lookup->q);
725 ISC_LINK_INIT(lookup, link);
726 ISC_LIST_APPEND(lookup_list, lookup, link);
727 lookup->origin = NULL;
728 ISC_LIST_INIT(lookup->my_server_list);
729 debug("looking up %s", lookup->textname);
733 get_next_command(void) {
739 buf = isc_mem_allocate(mctx, COMMSIZE);
741 fatal("memory allocation failure");
745 ptr = fgets(buf, COMMSIZE, stdin);
752 ptr = next_token(&input, " \t\r\n");
755 arg = next_token(&input, " \t\r\n");
756 if ((strcasecmp(ptr, "set") == 0) &&
759 else if ((strcasecmp(ptr, "server") == 0) ||
760 (strcasecmp(ptr, "lserver") == 0)) {
763 check_ra = ISC_FALSE;
765 show_settings(ISC_TRUE, ISC_TRUE);
766 } else if (strcasecmp(ptr, "exit") == 0) {
769 } else if (strcasecmp(ptr, "help") == 0 ||
770 strcasecmp(ptr, "?") == 0) {
771 printf("The '%s' command is not yet implemented.\n", ptr);
773 } else if (strcasecmp(ptr, "finger") == 0 ||
774 strcasecmp(ptr, "root") == 0 ||
775 strcasecmp(ptr, "ls") == 0 ||
776 strcasecmp(ptr, "view") == 0) {
777 printf("The '%s' command is not implemented.\n", ptr);
782 isc_mem_free(mctx, buf);
786 parse_args(int argc, char **argv) {
787 isc_boolean_t have_lookup = ISC_FALSE;
789 usesearch = ISC_TRUE;
790 for (argc--, argv++; argc > 0; argc--, argv++) {
791 debug("main parsing %s", argv[0]);
792 if (argv[0][0] == '-') {
794 setoption(&argv[0][1]);
796 have_lookup = ISC_TRUE;
799 have_lookup = ISC_TRUE;
803 set_nameserver(argv[0]);
804 check_ra = ISC_FALSE;
811 flush_lookup_list(void) {
812 dig_lookup_t *l, *lp;
814 dig_server_t *s, *sp;
817 l = ISC_LIST_HEAD(lookup_list);
819 q = ISC_LIST_HEAD(l->q);
821 if (q->sock != NULL) {
822 isc_socket_cancel(q->sock, NULL,
824 isc_socket_detach(&q->sock);
826 if (ISC_LINK_LINKED(&q->recvbuf, link))
827 ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
829 if (ISC_LINK_LINKED(&q->lengthbuf, link))
830 ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
832 isc_buffer_invalidate(&q->recvbuf);
833 isc_buffer_invalidate(&q->lengthbuf);
835 q = ISC_LIST_NEXT(q, link);
836 ISC_LIST_DEQUEUE(l->q, qp, link);
837 isc_mem_free(mctx, qp);
839 s = ISC_LIST_HEAD(l->my_server_list);
842 s = ISC_LIST_NEXT(s, link);
843 ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
844 isc_mem_free(mctx, sp);
847 if (l->sendmsg != NULL)
848 dns_message_destroy(&l->sendmsg);
849 if (l->timer != NULL)
850 isc_timer_detach(&l->timer);
852 l = ISC_LIST_NEXT(l, link);
853 ISC_LIST_DEQUEUE(lookup_list, lp, link);
854 isc_mem_free(mctx, lp);
859 getinput(isc_task_t *task, isc_event_t *event) {
861 if (global_event == NULL)
862 global_event = event;
865 if (ISC_LIST_HEAD(lookup_list) != NULL) {
874 main(int argc, char **argv) {
877 ISC_LIST_INIT(lookup_list);
878 ISC_LIST_INIT(server_list);
879 ISC_LIST_INIT(search_list);
883 result = isc_app_start();
884 check_result(result, "isc_app_start");
889 parse_args(argc, argv);
892 if (domainopt[0] != '\0')
893 set_search_domain(domainopt);
895 result = isc_app_onrun(mctx, global_task, onrun_callback,
898 result = isc_app_onrun(mctx, global_task, getinput, NULL);
899 check_result(result, "isc_app_onrun");
900 in_use = ISC_TF(!in_use);
905 debug("done, and starting to shut down");
906 if (global_event != NULL)
907 isc_event_free(&global_event);