2 * Copyright (C) 2004-2015 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.
24 #include <isc/buffer.h>
25 #include <isc/commandline.h>
26 #include <isc/event.h>
27 #include <isc/parseint.h>
28 #include <isc/print.h>
29 #include <isc/string.h>
30 #include <isc/timer.h>
33 #include <isc/netaddr.h>
35 #include <dns/message.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>
47 #if defined(HAVE_READLINE)
48 #include <readline/readline.h>
49 #include <readline/history.h>
52 static isc_boolean_t short_form = ISC_TRUE,
54 identify = ISC_FALSE, stats = ISC_TRUE,
55 comments = ISC_TRUE, section_question = ISC_TRUE,
56 section_answer = ISC_TRUE, section_authority = ISC_TRUE,
57 section_additional = ISC_TRUE, recurse = ISC_TRUE,
58 aaonly = ISC_FALSE, nofail = ISC_TRUE;
60 static isc_boolean_t interactive;
62 static isc_boolean_t in_use = ISC_FALSE;
63 static char defclass[MXRD] = "IN";
64 static char deftype[MXRD] = "A";
65 static isc_event_t *global_event = NULL;
66 static int query_error = 1, print_error = 0;
68 static char domainopt[DNS_NAME_MAXTEXT];
70 static const char *rcodetext[] = {
90 static const char *rtypetext[] = {
92 "internet address = ", /* 1 */
93 "nameserver = ", /* 2 */
96 "canonical name = ", /* 5 */
101 "rtype_10 = ", /* 10 */
102 "protocol = ", /* 11 */
106 "mail exchanger = ", /* 15 */
110 "x25 address = ", /* 19 */
111 "isdn address = ", /* 20 */
114 "nsap_ptr = ", /* 23 */
115 "signature = ", /* 24 */
119 "has AAAA address ", /* 28 */
122 "rtype_31 = ", /* 31 */
123 "rtype_32 = ", /* 32 */
124 "service = ", /* 33 */
125 "rtype_34 = ", /* 34 */
129 "v6 address = ", /* 38 */
131 "rtype_40 = ", /* 40 */
132 "optional = " /* 41 */
135 #define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
137 static void flush_lookup_list(void);
138 static void getinput(isc_task_t *task, isc_event_t *event);
141 rcode_totext(dns_rcode_t rcode)
143 static char buf[sizeof("?65535")];
145 const char *consttext;
149 if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
150 snprintf(buf, sizeof(buf), "?%u", rcode);
151 totext.deconsttext = buf;
153 totext.consttext = rcodetext[rcode];
154 return totext.deconsttext;
158 dighost_shutdown(void) {
159 isc_event_t *event = global_event;
162 debug("dighost_shutdown()");
169 isc_task_send(global_task, &event);
173 printsoa(dns_rdata_t *rdata) {
176 char namebuf[DNS_NAME_FORMATSIZE];
178 result = dns_rdata_tostruct(rdata, &soa, NULL);
179 check_result(result, "dns_rdata_tostruct");
181 dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
182 printf("\torigin = %s\n", namebuf);
183 dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
184 printf("\tmail addr = %s\n", namebuf);
185 printf("\tserial = %u\n", soa.serial);
186 printf("\trefresh = %u\n", soa.refresh);
187 printf("\tretry = %u\n", soa.retry);
188 printf("\texpire = %u\n", soa.expire);
189 printf("\tminimum = %u\n", soa.minimum);
190 dns_rdata_freestruct(&soa);
194 printa(dns_rdata_t *rdata) {
196 char text[sizeof("255.255.255.255")];
199 isc_buffer_init(&b, text, sizeof(text));
200 result = dns_rdata_totext(rdata, NULL, &b);
201 check_result(result, "dns_rdata_totext");
202 printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
203 (char *)isc_buffer_base(&b));
206 /* Just for compatibility : not use in host program */
208 printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
209 isc_buffer_t *target)
218 printrdata(dns_rdata_t *rdata) {
220 isc_buffer_t *b = NULL;
221 unsigned int size = 1024;
222 isc_boolean_t done = ISC_FALSE;
224 if (rdata->type < N_KNOWN_RRTYPES)
225 printf("%s", rtypetext[rdata->type]);
227 printf("rdata_%d = ", rdata->type);
230 result = isc_buffer_allocate(mctx, &b, size);
231 if (result != ISC_R_SUCCESS)
232 check_result(result, "isc_buffer_allocate");
233 result = dns_rdata_totext(rdata, NULL, b);
234 if (result == ISC_R_SUCCESS) {
235 printf("%.*s\n", (int)isc_buffer_usedlength(b),
236 (char *)isc_buffer_base(b));
238 } else if (result != ISC_R_NOSPACE)
239 check_result(result, "dns_rdata_totext");
246 printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
247 dns_section_t section) {
248 isc_result_t result, loopresult;
250 dns_rdataset_t *rdataset = NULL;
251 dns_rdata_t rdata = DNS_RDATA_INIT;
252 char namebuf[DNS_NAME_FORMATSIZE];
257 debug("printsection()");
259 result = dns_message_firstname(msg, section);
260 if (result == ISC_R_NOMORE)
261 return (ISC_R_SUCCESS);
262 else if (result != ISC_R_SUCCESS)
266 dns_message_currentname(msg, section,
268 for (rdataset = ISC_LIST_HEAD(name->list);
270 rdataset = ISC_LIST_NEXT(rdataset, link)) {
271 loopresult = dns_rdataset_first(rdataset);
272 while (loopresult == ISC_R_SUCCESS) {
273 dns_rdataset_current(rdataset, &rdata);
274 switch (rdata.type) {
275 case dns_rdatatype_a:
276 if (section != DNS_SECTION_ANSWER)
277 goto def_short_section;
278 dns_name_format(name, namebuf,
280 printf("Name:\t%s\n", namebuf);
283 case dns_rdatatype_soa:
284 dns_name_format(name, namebuf,
286 printf("%s\n", namebuf);
291 dns_name_format(name, namebuf,
293 printf("%s\t", namebuf);
297 dns_rdata_reset(&rdata);
298 loopresult = dns_rdataset_next(rdataset);
301 result = dns_message_nextname(msg, section);
302 if (result == ISC_R_NOMORE)
304 else if (result != ISC_R_SUCCESS) {
308 return (ISC_R_SUCCESS);
312 detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
313 dns_section_t section) {
314 isc_result_t result, loopresult;
316 dns_rdataset_t *rdataset = NULL;
317 dns_rdata_t rdata = DNS_RDATA_INIT;
318 char namebuf[DNS_NAME_FORMATSIZE];
322 debug("detailsection()");
326 case DNS_SECTION_QUESTION:
329 case DNS_SECTION_ANSWER:
332 case DNS_SECTION_AUTHORITY:
333 puts(" AUTHORITY RECORDS:");
335 case DNS_SECTION_ADDITIONAL:
336 puts(" ADDITIONAL RECORDS:");
341 result = dns_message_firstname(msg, section);
342 if (result == ISC_R_NOMORE)
343 return (ISC_R_SUCCESS);
344 else if (result != ISC_R_SUCCESS)
348 dns_message_currentname(msg, section,
350 for (rdataset = ISC_LIST_HEAD(name->list);
352 rdataset = ISC_LIST_NEXT(rdataset, link)) {
353 if (section == DNS_SECTION_QUESTION) {
354 dns_name_format(name, namebuf,
356 printf("\t%s, ", namebuf);
357 dns_rdatatype_format(rdataset->type,
360 printf("type = %s, ", namebuf);
361 dns_rdataclass_format(rdataset->rdclass,
364 printf("class = %s\n", namebuf);
366 loopresult = dns_rdataset_first(rdataset);
367 while (loopresult == ISC_R_SUCCESS) {
368 dns_rdataset_current(rdataset, &rdata);
370 dns_name_format(name, namebuf,
372 printf(" -> %s\n", namebuf);
374 switch (rdata.type) {
375 case dns_rdatatype_soa:
382 dns_rdata_reset(&rdata);
383 printf("\tttl = %u\n", rdataset->ttl);
384 loopresult = dns_rdataset_next(rdataset);
387 result = dns_message_nextname(msg, section);
388 if (result == ISC_R_NOMORE)
390 else if (result != ISC_R_SUCCESS) {
394 return (ISC_R_SUCCESS);
398 received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
406 trying(char *frm, dig_lookup_t *lookup) {
413 printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
414 char servtext[ISC_SOCKADDR_FORMATSIZE];
416 /* I've we've gotten this far, we've reached a server. */
419 debug("printmessage()");
421 isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
422 printf("Server:\t\t%s\n", query->userarg);
423 printf("Address:\t%s\n", servtext);
428 puts("------------");
429 /* detailheader(query, msg);*/
430 detailsection(query, msg, ISC_TRUE, DNS_SECTION_QUESTION);
431 detailsection(query, msg, ISC_TRUE, DNS_SECTION_ANSWER);
432 detailsection(query, msg, ISC_TRUE, DNS_SECTION_AUTHORITY);
433 detailsection(query, msg, ISC_TRUE, DNS_SECTION_ADDITIONAL);
434 puts("------------");
437 if (msg->rcode != 0) {
438 char nametext[DNS_NAME_FORMATSIZE];
439 dns_name_format(query->lookup->name,
440 nametext, sizeof(nametext));
441 printf("** server can't find %s: %s\n",
442 nametext, rcode_totext(msg->rcode));
443 debug("returning with rcode == 0");
445 /* the lookup failed */
447 return (ISC_R_SUCCESS);
450 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
451 puts("Non-authoritative answer:");
452 if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
453 printsection(query, msg, headers, DNS_SECTION_ANSWER);
455 printf("*** Can't find %s: No answer\n",
456 query->lookup->textname);
458 if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
459 (query->lookup->rdtype != dns_rdatatype_a)) {
460 puts("\nAuthoritative answers can be found from:");
461 printsection(query, msg, headers,
462 DNS_SECTION_AUTHORITY);
463 printsection(query, msg, headers,
464 DNS_SECTION_ADDITIONAL);
466 return (ISC_R_SUCCESS);
470 show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
472 isc_sockaddr_t sockaddr;
473 dig_searchlist_t *listent;
476 srv = ISC_LIST_HEAD(server_list);
478 while (srv != NULL) {
479 char sockstr[ISC_SOCKADDR_FORMATSIZE];
481 result = get_address(srv->servername, port, &sockaddr);
482 check_result(result, "get_address");
484 isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
485 printf("Default server: %s\nAddress: %s\n",
486 srv->userarg, sockstr);
489 srv = ISC_LIST_NEXT(srv, link);
493 printf("\nSet options:\n");
494 printf(" %s\t\t\t%s\t\t%s\n",
495 tcpmode ? "vc" : "novc",
496 short_form ? "nodebug" : "debug",
497 debugging ? "d2" : "nod2");
498 printf(" %s\t\t%s\n",
499 usesearch ? "search" : "nosearch",
500 recurse ? "recurse" : "norecurse");
501 printf(" timeout = %d\t\tretry = %d\tport = %d\tndots = %d\n",
502 timeout, tries, port, ndots);
503 printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
504 printf(" srchlist = ");
505 for (listent = ISC_LIST_HEAD(search_list);
507 listent = ISC_LIST_NEXT(listent, link)) {
508 printf("%s", listent->origin);
509 if (ISC_LIST_NEXT(listent, link) != NULL)
516 testtype(char *typetext) {
519 dns_rdatatype_t rdtype;
522 tr.length = strlen(typetext);
523 result = dns_rdatatype_fromtext(&rdtype, &tr);
524 if (result == ISC_R_SUCCESS)
527 printf("unknown query type: %s\n", typetext);
533 testclass(char *typetext) {
536 dns_rdataclass_t rdclass;
539 tr.length = strlen(typetext);
540 result = dns_rdataclass_fromtext(&rdclass, &tr);
541 if (result == ISC_R_SUCCESS)
544 printf("unknown query class: %s\n", typetext);
550 set_port(const char *value) {
552 isc_result_t result = parse_uint(&n, value, 65535, "port");
553 if (result == ISC_R_SUCCESS)
554 port = (isc_uint16_t) n;
558 set_timeout(const char *value) {
560 isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
561 if (result == ISC_R_SUCCESS)
566 set_tries(const char *value) {
568 isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
569 if (result == ISC_R_SUCCESS)
574 set_ndots(const char *value) {
576 isc_result_t result = parse_uint(&n, value, 128, "ndots");
577 if (result == ISC_R_SUCCESS)
583 fputs("nslookup " VERSION "\n", stderr);
587 setoption(char *opt) {
588 if (strncasecmp(opt, "all", 3) == 0) {
589 show_settings(ISC_TRUE, ISC_FALSE);
590 } else if (strncasecmp(opt, "class=", 6) == 0) {
591 if (testclass(&opt[6]))
592 strlcpy(defclass, &opt[6], sizeof(defclass));
593 } else if (strncasecmp(opt, "cl=", 3) == 0) {
594 if (testclass(&opt[3]))
595 strlcpy(defclass, &opt[3], sizeof(defclass));
596 } else if (strncasecmp(opt, "type=", 5) == 0) {
597 if (testtype(&opt[5]))
598 strlcpy(deftype, &opt[5], sizeof(deftype));
599 } else if (strncasecmp(opt, "ty=", 3) == 0) {
600 if (testtype(&opt[3]))
601 strlcpy(deftype, &opt[3], sizeof(deftype));
602 } else if (strncasecmp(opt, "querytype=", 10) == 0) {
603 if (testtype(&opt[10]))
604 strlcpy(deftype, &opt[10], sizeof(deftype));
605 } else if (strncasecmp(opt, "query=", 6) == 0) {
606 if (testtype(&opt[6]))
607 strlcpy(deftype, &opt[6], sizeof(deftype));
608 } else if (strncasecmp(opt, "qu=", 3) == 0) {
609 if (testtype(&opt[3]))
610 strlcpy(deftype, &opt[3], sizeof(deftype));
611 } else if (strncasecmp(opt, "q=", 2) == 0) {
612 if (testtype(&opt[2]))
613 strlcpy(deftype, &opt[2], sizeof(deftype));
614 } else if (strncasecmp(opt, "domain=", 7) == 0) {
615 strlcpy(domainopt, &opt[7], sizeof(domainopt));
616 set_search_domain(domainopt);
617 usesearch = ISC_TRUE;
618 } else if (strncasecmp(opt, "do=", 3) == 0) {
619 strlcpy(domainopt, &opt[3], sizeof(domainopt));
620 set_search_domain(domainopt);
621 usesearch = ISC_TRUE;
622 } else if (strncasecmp(opt, "port=", 5) == 0) {
624 } else if (strncasecmp(opt, "po=", 3) == 0) {
626 } else if (strncasecmp(opt, "timeout=", 8) == 0) {
627 set_timeout(&opt[8]);
628 } else if (strncasecmp(opt, "t=", 2) == 0) {
629 set_timeout(&opt[2]);
630 } else if (strncasecmp(opt, "rec", 3) == 0) {
632 } else if (strncasecmp(opt, "norec", 5) == 0) {
634 } else if (strncasecmp(opt, "retry=", 6) == 0) {
636 } else if (strncasecmp(opt, "ret=", 4) == 0) {
638 } else if (strncasecmp(opt, "def", 3) == 0) {
639 usesearch = ISC_TRUE;
640 } else if (strncasecmp(opt, "nodef", 5) == 0) {
641 usesearch = ISC_FALSE;
642 } else if (strncasecmp(opt, "vc", 3) == 0) {
644 } else if (strncasecmp(opt, "novc", 5) == 0) {
646 } else if (strncasecmp(opt, "deb", 3) == 0) {
647 short_form = ISC_FALSE;
648 showsearch = ISC_TRUE;
649 } else if (strncasecmp(opt, "nodeb", 5) == 0) {
650 short_form = ISC_TRUE;
651 showsearch = ISC_FALSE;
652 } else if (strncasecmp(opt, "d2", 2) == 0) {
653 debugging = ISC_TRUE;
654 } else if (strncasecmp(opt, "nod2", 4) == 0) {
655 debugging = ISC_FALSE;
656 } else if (strncasecmp(opt, "search", 3) == 0) {
657 usesearch = ISC_TRUE;
658 } else if (strncasecmp(opt, "nosearch", 5) == 0) {
659 usesearch = ISC_FALSE;
660 } else if (strncasecmp(opt, "sil", 3) == 0) {
661 /* deprecation_msg = ISC_FALSE; */
662 } else if (strncasecmp(opt, "fail", 3) == 0) {
664 } else if (strncasecmp(opt, "nofail", 3) == 0) {
666 } else if (strncasecmp(opt, "ndots=", 6) == 0) {
669 printf("*** Invalid option: %s\n", opt);
674 addlookup(char *opt) {
675 dig_lookup_t *lookup;
678 dns_rdatatype_t rdtype;
679 dns_rdataclass_t rdclass;
682 debug("addlookup()");
684 tr.length = strlen(deftype);
685 result = dns_rdatatype_fromtext(&rdtype, &tr);
686 if (result != ISC_R_SUCCESS) {
687 printf("unknown query type: %s\n", deftype);
688 rdclass = dns_rdatatype_a;
691 tr.length = strlen(defclass);
692 result = dns_rdataclass_fromtext(&rdclass, &tr);
693 if (result != ISC_R_SUCCESS) {
694 printf("unknown query class: %s\n", defclass);
695 rdclass = dns_rdataclass_in;
697 lookup = make_empty_lookup();
698 if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
700 strlcpy(lookup->textname, store, sizeof(lookup->textname));
701 lookup->rdtype = dns_rdatatype_ptr;
702 lookup->rdtypeset = ISC_TRUE;
704 strlcpy(lookup->textname, opt, sizeof(lookup->textname));
705 lookup->rdtype = rdtype;
706 lookup->rdtypeset = ISC_TRUE;
708 lookup->rdclass = rdclass;
709 lookup->rdclassset = ISC_TRUE;
710 lookup->trace = ISC_FALSE;
711 lookup->trace_root = lookup->trace;
712 lookup->ns_search_only = ISC_FALSE;
713 lookup->identify = identify;
714 lookup->recurse = recurse;
715 lookup->aaonly = aaonly;
716 lookup->retries = tries;
718 lookup->comments = comments;
719 lookup->tcp_mode = tcpmode;
720 lookup->stats = stats;
721 lookup->section_question = section_question;
722 lookup->section_answer = section_answer;
723 lookup->section_authority = section_authority;
724 lookup->section_additional = section_additional;
725 lookup->new_search = ISC_TRUE;
727 lookup->servfail_stops = ISC_FALSE;
728 ISC_LIST_INIT(lookup->q);
729 ISC_LINK_INIT(lookup, link);
730 ISC_LIST_APPEND(lookup_list, lookup, link);
731 lookup->origin = NULL;
732 ISC_LIST_INIT(lookup->my_server_list);
733 debug("looking up %s", lookup->textname);
737 do_next_command(char *input) {
740 ptr = next_token(&input, " \t\r\n");
743 arg = next_token(&input, " \t\r\n");
744 if ((strcasecmp(ptr, "set") == 0) &&
747 else if ((strcasecmp(ptr, "server") == 0) ||
748 (strcasecmp(ptr, "lserver") == 0)) {
751 check_ra = ISC_FALSE;
753 show_settings(ISC_TRUE, ISC_TRUE);
754 } else if (strcasecmp(ptr, "exit") == 0) {
756 } else if (strcasecmp(ptr, "help") == 0 ||
757 strcasecmp(ptr, "?") == 0) {
758 printf("The '%s' command is not yet implemented.\n", ptr);
759 } else if (strcasecmp(ptr, "finger") == 0 ||
760 strcasecmp(ptr, "root") == 0 ||
761 strcasecmp(ptr, "ls") == 0 ||
762 strcasecmp(ptr, "view") == 0) {
763 printf("The '%s' command is not implemented.\n", ptr);
769 get_next_command(void) {
774 buf = isc_mem_allocate(mctx, COMMSIZE);
776 fatal("memory allocation failure");
780 ptr = readline("> ");
786 ptr = fgets(buf, COMMSIZE, stdin);
789 ptr = fgets(buf, COMMSIZE, stdin);
794 do_next_command(ptr);
799 isc_mem_free(mctx, buf);
803 parse_args(int argc, char **argv) {
804 isc_boolean_t have_lookup = ISC_FALSE;
806 usesearch = ISC_TRUE;
807 for (argc--, argv++; argc > 0; argc--, argv++) {
808 debug("main parsing %s", argv[0]);
809 if (argv[0][0] == '-') {
810 if (strncasecmp(argv[0], "-ver", 4) == 0) {
813 } else if (argv[0][1] != 0) {
814 setoption(&argv[0][1]);
816 have_lookup = ISC_TRUE;
819 have_lookup = ISC_TRUE;
823 set_nameserver(argv[0]);
824 check_ra = ISC_FALSE;
831 flush_lookup_list(void) {
832 dig_lookup_t *l, *lp;
834 dig_server_t *s, *sp;
837 l = ISC_LIST_HEAD(lookup_list);
839 q = ISC_LIST_HEAD(l->q);
841 if (q->sock != NULL) {
842 isc_socket_cancel(q->sock, NULL,
844 isc_socket_detach(&q->sock);
846 if (ISC_LINK_LINKED(&q->recvbuf, link))
847 ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
849 if (ISC_LINK_LINKED(&q->lengthbuf, link))
850 ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
852 isc_buffer_invalidate(&q->recvbuf);
853 isc_buffer_invalidate(&q->lengthbuf);
855 q = ISC_LIST_NEXT(q, link);
856 ISC_LIST_DEQUEUE(l->q, qp, link);
857 isc_mem_free(mctx, qp);
859 s = ISC_LIST_HEAD(l->my_server_list);
862 s = ISC_LIST_NEXT(s, link);
863 ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
864 isc_mem_free(mctx, sp);
867 if (l->sendmsg != NULL)
868 dns_message_destroy(&l->sendmsg);
869 if (l->timer != NULL)
870 isc_timer_detach(&l->timer);
872 l = ISC_LIST_NEXT(l, link);
873 ISC_LIST_DEQUEUE(lookup_list, lp, link);
874 isc_mem_free(mctx, lp);
879 getinput(isc_task_t *task, isc_event_t *event) {
881 if (global_event == NULL)
882 global_event = event;
885 if (ISC_LIST_HEAD(lookup_list) != NULL) {
894 main(int argc, char **argv) {
897 interactive = ISC_TF(isatty(0));
899 ISC_LIST_INIT(lookup_list);
900 ISC_LIST_INIT(server_list);
901 ISC_LIST_INIT(search_list);
905 result = isc_app_start();
906 check_result(result, "isc_app_start");
911 parse_args(argc, argv);
914 if (domainopt[0] != '\0')
915 set_search_domain(domainopt);
917 result = isc_app_onrun(mctx, global_task, onrun_callback,
920 result = isc_app_onrun(mctx, global_task, getinput, NULL);
921 check_result(result, "isc_app_onrun");
922 in_use = ISC_TF(!in_use);
927 debug("done, and starting to shut down");
928 if (global_event != NULL)
929 isc_event_free(&global_event);
934 return (query_error | print_error);