Sun Nov 5 16:09:13 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[glibc.git] / resolv / res_debug.c
blob602042e1986160fe844e1ac7514041dd8ce202ce
1 /*
2 * ++Copyright++ 1985, 1990, 1993
3 * -
4 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 * -
35 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
37 * Permission to use, copy, modify, and distribute this software for any
38 * purpose with or without fee is hereby granted, provided that the above
39 * copyright notice and this permission notice appear in all copies, and that
40 * the name of Digital Equipment Corporation not be used in advertising or
41 * publicity pertaining to distribution of the document or software without
42 * specific, written prior permission.
44 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
47 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 * SOFTWARE.
52 * -
53 * --Copyright--
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
58 static char rcsid[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
61 #include <sys/param.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #include <arpa/nameser.h>
66 #include <stdio.h>
67 #include <netdb.h>
68 #include <resolv.h>
69 #if defined(BSD) && (BSD >= 199103)
70 # include <string.h>
71 #else
72 # include "../conf/portability.h"
73 #endif
75 #if defined(USE_OPTIONS_H)
76 # include "../conf/options.h"
77 #endif
79 const char *_res_opcodes[] = {
80 "QUERY",
81 "IQUERY",
82 "CQUERYM",
83 "CQUERYU", /* experimental */
84 "NOTIFY", /* experimental */
85 "5",
86 "6",
87 "7",
88 "8",
89 "UPDATEA",
90 "UPDATED",
91 "UPDATEDA",
92 "UPDATEM",
93 "UPDATEMA",
94 "ZONEINIT",
95 "ZONEREF",
98 const char *_res_resultcodes[] = {
99 "NOERROR",
100 "FORMERR",
101 "SERVFAIL",
102 "NXDOMAIN",
103 "NOTIMP",
104 "REFUSED",
105 "6",
106 "7",
107 "8",
108 "9",
109 "10",
110 "11",
111 "12",
112 "13",
113 "14",
114 "NOCHANGE",
117 /* XXX: we should use getservbyport() instead. */
118 static const char *
119 dewks(wks)
120 int wks;
122 static char nbuf[20];
124 switch (wks) {
125 case 5: return "rje";
126 case 7: return "echo";
127 case 9: return "discard";
128 case 11: return "systat";
129 case 13: return "daytime";
130 case 15: return "netstat";
131 case 17: return "qotd";
132 case 19: return "chargen";
133 case 20: return "ftp-data";
134 case 21: return "ftp";
135 case 23: return "telnet";
136 case 25: return "smtp";
137 case 37: return "time";
138 case 39: return "rlp";
139 case 42: return "name";
140 case 43: return "whois";
141 case 53: return "domain";
142 case 57: return "apts";
143 case 59: return "apfs";
144 case 67: return "bootps";
145 case 68: return "bootpc";
146 case 69: return "tftp";
147 case 77: return "rje";
148 case 79: return "finger";
149 case 87: return "link";
150 case 95: return "supdup";
151 case 100: return "newacct";
152 case 101: return "hostnames";
153 case 102: return "iso-tsap";
154 case 103: return "x400";
155 case 104: return "x400-snd";
156 case 105: return "csnet-ns";
157 case 109: return "pop-2";
158 case 111: return "sunrpc";
159 case 113: return "auth";
160 case 115: return "sftp";
161 case 117: return "uucp-path";
162 case 119: return "nntp";
163 case 121: return "erpc";
164 case 123: return "ntp";
165 case 133: return "statsrv";
166 case 136: return "profile";
167 case 144: return "NeWS";
168 case 161: return "snmp";
169 case 162: return "snmp-trap";
170 case 170: return "print-srv";
171 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
175 /* XXX: we should use getprotobynumber() instead. */
176 static const char *
177 deproto(protonum)
178 int protonum;
180 static char nbuf[20];
182 switch (protonum) {
183 case 1: return "icmp";
184 case 2: return "igmp";
185 case 3: return "ggp";
186 case 5: return "st";
187 case 6: return "tcp";
188 case 7: return "ucl";
189 case 8: return "egp";
190 case 9: return "igp";
191 case 11: return "nvp-II";
192 case 12: return "pup";
193 case 16: return "chaos";
194 case 17: return "udp";
195 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
199 static const u_char *
200 do_rrset(msg, len, cp, cnt, pflag, file, hs)
201 int cnt, pflag, len;
202 const u_char *cp, *msg;
203 const char *hs;
204 FILE *file;
206 int n;
207 int sflag;
210 * Print answer records.
212 sflag = (_res.pfcode & pflag);
213 if (n = ntohs(cnt)) {
214 if ((!_res.pfcode) ||
215 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
216 fprintf(file, hs);
217 while (--n >= 0) {
218 if ((!_res.pfcode) || sflag) {
219 cp = p_rr(cp, msg, file);
220 } else {
221 unsigned int dlen;
222 cp += __dn_skipname(cp, cp + MAXCDNAME);
223 cp += INT16SZ;
224 cp += INT16SZ;
225 cp += INT32SZ;
226 dlen = _getshort((u_char*)cp);
227 cp += INT16SZ;
228 cp += dlen;
230 if ((cp - msg) > len)
231 return (NULL);
233 if ((!_res.pfcode) ||
234 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
235 putc('\n', file);
237 return (cp);
240 void
241 __p_query(msg)
242 const u_char *msg;
244 __fp_query(msg, stdout);
247 #ifdef ultrix
248 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
249 * there is more junk of this kind over in res_comp.c.
251 void
252 p_query(msg)
253 const u_char *msg;
255 __p_query(msg);
257 #endif
260 * Print the current options.
261 * This is intended to be primarily a debugging routine.
263 void
264 __fp_resstat(statp, file)
265 struct __res_state *statp;
266 FILE *file;
268 register u_long mask;
270 fprintf(file, ";; res options:");
271 if (!statp)
272 statp = &_res;
273 for (mask = 1; mask != 0; mask <<= 1)
274 if (statp->options & mask)
275 fprintf(file, " %s", p_option(mask));
276 putc('\n', file);
280 * Print the contents of a query.
281 * This is intended to be primarily a debugging routine.
283 void
284 __fp_nquery(msg, len, file)
285 const u_char *msg;
286 int len;
287 FILE *file;
289 register const u_char *cp, *endMark;
290 register const HEADER *hp;
291 register int n;
293 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
294 return;
296 #define TruncTest(x) if (x >= endMark) goto trunc
297 #define ErrorTest(x) if (x == NULL) goto error
300 * Print header fields.
302 hp = (HEADER *)msg;
303 cp = msg + HFIXEDSZ;
304 endMark = cp + len;
305 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
306 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
307 _res_opcodes[hp->opcode],
308 _res_resultcodes[hp->rcode],
309 ntohs(hp->id));
310 putc('\n', file);
312 putc(';', file);
313 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
314 fprintf(file, "; flags:");
315 if (hp->qr)
316 fprintf(file, " qr");
317 if (hp->aa)
318 fprintf(file, " aa");
319 if (hp->tc)
320 fprintf(file, " tc");
321 if (hp->rd)
322 fprintf(file, " rd");
323 if (hp->ra)
324 fprintf(file, " ra");
326 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
327 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
328 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
329 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
330 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
332 if ((!_res.pfcode) || (_res.pfcode &
333 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
334 putc('\n',file);
337 * Print question records.
339 if (n = ntohs(hp->qdcount)) {
340 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
341 fprintf(file, ";; QUESTIONS:\n");
342 while (--n >= 0) {
343 fprintf(file, ";;\t");
344 TruncTest(cp);
345 cp = p_cdnname(cp, msg, len, file);
346 ErrorTest(cp);
347 TruncTest(cp);
348 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
349 fprintf(file, ", type = %s",
350 __p_type(_getshort((u_char*)cp)));
351 cp += INT16SZ;
352 TruncTest(cp);
353 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
354 fprintf(file, ", class = %s\n",
355 __p_class(_getshort((u_char*)cp)));
356 cp += INT16SZ;
357 putc('\n', file);
361 * Print authoritative answer records
363 TruncTest(cp);
364 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
365 ";; ANSWERS:\n");
366 ErrorTest(cp);
369 * print name server records
371 TruncTest(cp);
372 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
373 ";; AUTHORITY RECORDS:\n");
374 ErrorTest(cp);
376 TruncTest(cp);
378 * print additional records
380 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
381 ";; ADDITIONAL RECORDS:\n");
382 ErrorTest(cp);
383 return;
384 trunc:
385 fprintf(file, "\n;; ...truncated\n");
386 return;
387 error:
388 fprintf(file, "\n;; ...malformed\n");
391 void
392 __fp_query(msg, file)
393 const u_char *msg;
394 FILE *file;
396 fp_nquery(msg, PACKETSZ, file);
399 const u_char *
400 __p_cdnname(cp, msg, len, file)
401 const u_char *cp, *msg;
402 int len;
403 FILE *file;
405 char name[MAXDNAME];
406 int n;
408 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
409 return (NULL);
410 if (name[0] == '\0')
411 putc('.', file);
412 else
413 fputs(name, file);
414 return (cp + n);
417 const u_char *
418 __p_cdname(cp, msg, file)
419 const u_char *cp, *msg;
420 FILE *file;
422 return (p_cdnname(cp, msg, PACKETSZ, file));
425 /* XXX: the rest of these functions need to become length-limited, too. (vix)
428 const u_char *
429 __p_fqname(cp, msg, file)
430 const u_char *cp, *msg;
431 FILE *file;
433 char name[MAXDNAME];
434 int n;
436 if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
437 return (NULL);
438 if (name[0] == '\0') {
439 putc('.', file);
440 } else {
441 fputs(name, file);
442 if (name[strlen(name) - 1] != '.')
443 putc('.', file);
445 return (cp + n);
449 * Print resource record fields in human readable form.
451 const u_char *
452 __p_rr(cp, msg, file)
453 const u_char *cp, *msg;
454 FILE *file;
456 int type, class, dlen, n, c;
457 struct in_addr inaddr;
458 const u_char *cp1, *cp2;
459 u_int32_t tmpttl, t;
460 int lcnt;
462 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
463 h_errno = NETDB_INTERNAL;
464 return (NULL);
466 if ((cp = p_fqname(cp, msg, file)) == NULL)
467 return (NULL); /* compression error */
468 type = _getshort((u_char*)cp);
469 cp += INT16SZ;
470 class = _getshort((u_char*)cp);
471 cp += INT16SZ;
472 tmpttl = _getlong((u_char*)cp);
473 cp += INT32SZ;
474 dlen = _getshort((u_char*)cp);
475 cp += INT16SZ;
476 cp1 = cp;
477 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
478 fprintf(file, "\t%lu", (u_long)tmpttl);
479 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
480 fprintf(file, "\t%s", __p_class(class));
481 fprintf(file, "\t%s", __p_type(type));
483 * Print type specific data, if appropriate
485 switch (type) {
486 case T_A:
487 switch (class) {
488 case C_IN:
489 case C_HS:
490 bcopy(cp, (char *)&inaddr, INADDRSZ);
491 if (dlen == 4) {
492 fprintf(file, "\t%s", inet_ntoa(inaddr));
493 cp += dlen;
494 } else if (dlen == 7) {
495 char *address;
496 u_char protocol;
497 u_short port;
499 address = inet_ntoa(inaddr);
500 cp += INADDRSZ;
501 protocol = *(u_char*)cp;
502 cp += sizeof(u_char);
503 port = _getshort((u_char*)cp);
504 cp += INT16SZ;
505 fprintf(file, "\t%s\t; proto %d, port %d",
506 address, protocol, port);
508 break;
509 default:
510 cp += dlen;
512 break;
513 case T_CNAME:
514 case T_MB:
515 case T_MG:
516 case T_MR:
517 case T_NS:
518 case T_PTR:
519 putc('\t', file);
520 if ((cp = p_fqname(cp, msg, file)) == NULL)
521 return (NULL);
522 break;
524 case T_HINFO:
525 case T_ISDN:
526 cp2 = cp + dlen;
527 if (n = *cp++) {
528 fprintf(file, "\t%.*s", n, cp);
529 cp += n;
531 if ((cp < cp2) && (n = *cp++)) {
532 fprintf(file, "\t%.*s", n, cp);
533 cp += n;
534 } else if (type == T_HINFO)
535 fprintf(file, "\n;; *** Warning *** OS-type missing");
536 break;
538 case T_SOA:
539 putc('\t', file);
540 if ((cp = p_fqname(cp, msg, file)) == NULL)
541 return (NULL);
542 putc(' ', file);
543 if ((cp = p_fqname(cp, msg, file)) == NULL)
544 return (NULL);
545 fputs(" (\n", file);
546 t = _getlong((u_char*)cp); cp += INT32SZ;
547 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
548 t = _getlong((u_char*)cp); cp += INT32SZ;
549 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
550 (u_long)t, __p_time(t));
551 t = _getlong((u_char*)cp); cp += INT32SZ;
552 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
553 (u_long)t, __p_time(t));
554 t = _getlong((u_char*)cp); cp += INT32SZ;
555 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
556 (u_long)t, __p_time(t));
557 t = _getlong((u_char*)cp); cp += INT32SZ;
558 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
559 (u_long)t, __p_time(t));
560 break;
562 case T_MX:
563 case T_AFSDB:
564 case T_RT:
565 fprintf(file, "\t%d ", _getshort((u_char*)cp));
566 cp += INT16SZ;
567 if ((cp = p_fqname(cp, msg, file)) == NULL)
568 return (NULL);
569 break;
571 case T_PX:
572 fprintf(file, "\t%d ", _getshort((u_char*)cp));
573 cp += INT16SZ;
574 if ((cp = p_fqname(cp, msg, file)) == NULL)
575 return (NULL);
576 putc(' ', file);
577 if ((cp = p_fqname(cp, msg, file)) == NULL)
578 return (NULL);
579 break;
581 case T_TXT:
582 case T_X25:
583 (void) fputs("\t\"", file);
584 cp2 = cp1 + dlen;
585 while (cp < cp2) {
586 if (n = (unsigned char) *cp++) {
587 for (c = n; c > 0 && cp < cp2; c--)
588 if ((*cp == '\n') || (*cp == '"')) {
589 (void) putc('\\', file);
590 (void) putc(*cp++, file);
591 } else
592 (void) putc(*cp++, file);
595 putc('"', file);
596 break;
598 case T_NSAP:
599 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
600 cp += dlen;
601 break;
603 case T_MINFO:
604 case T_RP:
605 putc('\t', file);
606 if ((cp = p_fqname(cp, msg, file)) == NULL)
607 return (NULL);
608 putc(' ', file);
609 if ((cp = p_fqname(cp, msg, file)) == NULL)
610 return (NULL);
611 break;
613 case T_UINFO:
614 putc('\t', file);
615 fputs((char *)cp, file);
616 cp += dlen;
617 break;
619 case T_UID:
620 case T_GID:
621 if (dlen == 4) {
622 fprintf(file, "\t%u", _getlong((u_char*)cp));
623 cp += INT32SZ;
625 break;
627 case T_WKS:
628 if (dlen < INT32SZ + 1)
629 break;
630 bcopy(cp, (char *)&inaddr, INADDRSZ);
631 cp += INT32SZ;
632 fprintf(file, "\t%s %s ( ",
633 inet_ntoa(inaddr),
634 deproto((int) *cp));
635 cp += sizeof(u_char);
636 n = 0;
637 lcnt = 0;
638 while (cp < cp1 + dlen) {
639 c = *cp++;
640 do {
641 if (c & 0200) {
642 if (lcnt == 0) {
643 fputs("\n\t\t\t", file);
644 lcnt = 5;
646 fputs(dewks(n), file);
647 putc(' ', file);
648 lcnt--;
650 c <<= 1;
651 } while (++n & 07);
653 putc(')', file);
654 break;
656 #ifdef ALLOW_T_UNSPEC
657 case T_UNSPEC:
659 int NumBytes = 8;
660 u_char *DataPtr;
661 int i;
663 if (dlen < NumBytes) NumBytes = dlen;
664 fprintf(file, "\tFirst %d bytes of hex data:",
665 NumBytes);
666 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
667 fprintf(file, " %x", *DataPtr);
668 cp += dlen;
670 break;
671 #endif /* ALLOW_T_UNSPEC */
673 default:
674 fprintf(file, "\t?%d?", type);
675 cp += dlen;
677 #if 0
678 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
679 #else
680 putc('\n', file);
681 #endif
682 if (cp - cp1 != dlen) {
683 fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
684 cp - cp1, dlen);
685 cp = NULL;
687 return (cp);
691 * Return a string for the type
693 const char *
694 __p_type(type)
695 int type;
697 static char nbuf[20];
699 switch (type) {
700 case T_A: return "A";
701 case T_NS: return "NS";
702 case T_CNAME: return "CNAME";
703 case T_SOA: return "SOA";
704 case T_MB: return "MB";
705 case T_MG: return "MG";
706 case T_MR: return "MR";
707 case T_NULL: return "NULL";
708 case T_WKS: return "WKS";
709 case T_PTR: return "PTR";
710 case T_HINFO: return "HINFO";
711 case T_MINFO: return "MINFO";
712 case T_MX: return "MX";
713 case T_TXT: return "TXT";
714 case T_RP: return "RP";
715 case T_AFSDB: return "AFSDB";
716 case T_X25: return "X25";
717 case T_ISDN: return "ISDN";
718 case T_RT: return "RT";
719 case T_NSAP: return "NSAP";
720 case T_NSAP_PTR: return "NSAP_PTR";
721 case T_SIG: return "SIG";
722 case T_KEY: return "KEY";
723 case T_PX: return "PX";
724 case T_GPOS: return "GPOS";
725 case T_AAAA: return "AAAA";
726 case T_LOC: return "LOC";
727 case T_AXFR: return "AXFR";
728 case T_MAILB: return "MAILB";
729 case T_MAILA: return "MAILA";
730 case T_ANY: return "ANY";
731 case T_UINFO: return "UINFO";
732 case T_UID: return "UID";
733 case T_GID: return "GID";
734 #ifdef ALLOW_T_UNSPEC
735 case T_UNSPEC: return "UNSPEC";
736 #endif /* ALLOW_T_UNSPEC */
737 default: (void)sprintf(nbuf, "%d", type); return (nbuf);
742 * Return a mnemonic for class
744 const char *
745 __p_class(class)
746 int class;
748 static char nbuf[20];
750 switch (class) {
751 case C_IN: return "IN";
752 case C_HS: return "HS";
753 case C_ANY: return "ANY";
754 default: (void)sprintf(nbuf, "%d", class); return (nbuf);
759 * Return a mnemonic for an option
761 const char *
762 __p_option(option)
763 u_long option;
765 static char nbuf[40];
767 switch (option) {
768 case RES_INIT: return "init";
769 case RES_DEBUG: return "debug";
770 case RES_AAONLY: return "aaonly(unimpl)";
771 case RES_USEVC: return "usevc";
772 case RES_PRIMARY: return "primry(unimpl)";
773 case RES_IGNTC: return "igntc";
774 case RES_RECURSE: return "recurs";
775 case RES_DEFNAMES: return "defnam";
776 case RES_STAYOPEN: return "styopn";
777 case RES_DNSRCH: return "dnsrch";
778 case RES_INSECURE1: return "insecure1";
779 case RES_INSECURE2: return "insecure2";
780 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
781 return (nbuf);
786 * Return a mnemonic for a time to live
788 char *
789 __p_time(value)
790 u_int32_t value;
792 static char nbuf[40];
793 int secs, mins, hours, days;
794 register char *p;
796 if (value == 0) {
797 strcpy(nbuf, "0 secs");
798 return (nbuf);
801 secs = value % 60;
802 value /= 60;
803 mins = value % 60;
804 value /= 60;
805 hours = value % 24;
806 value /= 24;
807 days = value;
808 value = 0;
810 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
811 p = nbuf;
812 if (days) {
813 (void)sprintf(p, "%d day%s", PLURALIZE(days));
814 while (*++p);
816 if (hours) {
817 if (days)
818 *p++ = ' ';
819 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
820 while (*++p);
822 if (mins) {
823 if (days || hours)
824 *p++ = ' ';
825 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
826 while (*++p);
828 if (secs || ! (days || hours || mins)) {
829 if (days || hours || mins)
830 *p++ = ' ';
831 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
833 return (nbuf);