Sun Jan 28 17:25:38 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[glibc.git] / resolv / res_debug.c
blobb3dfcdf8f6c13c9fa7158fe2eaeb72d6478a7318
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 extern const char *_res_opcodes[];
80 extern const char *_res_resultcodes[];
82 /* XXX: we should use getservbyport() instead. */
83 static const char *
84 dewks(wks)
85 int wks;
87 static char nbuf[20];
89 switch (wks) {
90 case 5: return "rje";
91 case 7: return "echo";
92 case 9: return "discard";
93 case 11: return "systat";
94 case 13: return "daytime";
95 case 15: return "netstat";
96 case 17: return "qotd";
97 case 19: return "chargen";
98 case 20: return "ftp-data";
99 case 21: return "ftp";
100 case 23: return "telnet";
101 case 25: return "smtp";
102 case 37: return "time";
103 case 39: return "rlp";
104 case 42: return "name";
105 case 43: return "whois";
106 case 53: return "domain";
107 case 57: return "apts";
108 case 59: return "apfs";
109 case 67: return "bootps";
110 case 68: return "bootpc";
111 case 69: return "tftp";
112 case 77: return "rje";
113 case 79: return "finger";
114 case 87: return "link";
115 case 95: return "supdup";
116 case 100: return "newacct";
117 case 101: return "hostnames";
118 case 102: return "iso-tsap";
119 case 103: return "x400";
120 case 104: return "x400-snd";
121 case 105: return "csnet-ns";
122 case 109: return "pop-2";
123 case 111: return "sunrpc";
124 case 113: return "auth";
125 case 115: return "sftp";
126 case 117: return "uucp-path";
127 case 119: return "nntp";
128 case 121: return "erpc";
129 case 123: return "ntp";
130 case 133: return "statsrv";
131 case 136: return "profile";
132 case 144: return "NeWS";
133 case 161: return "snmp";
134 case 162: return "snmp-trap";
135 case 170: return "print-srv";
136 default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
140 /* XXX: we should use getprotobynumber() instead. */
141 static const char *
142 deproto(protonum)
143 int protonum;
145 static char nbuf[20];
147 switch (protonum) {
148 case 1: return "icmp";
149 case 2: return "igmp";
150 case 3: return "ggp";
151 case 5: return "st";
152 case 6: return "tcp";
153 case 7: return "ucl";
154 case 8: return "egp";
155 case 9: return "igp";
156 case 11: return "nvp-II";
157 case 12: return "pup";
158 case 16: return "chaos";
159 case 17: return "udp";
160 default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
164 static const u_char *
165 do_rrset(msg, len, cp, cnt, pflag, file, hs)
166 int cnt, pflag, len;
167 const u_char *cp, *msg;
168 const char *hs;
169 FILE *file;
171 int n;
172 int sflag;
175 * Print answer records.
177 sflag = (_res.pfcode & pflag);
178 if (n = ntohs(cnt)) {
179 if ((!_res.pfcode) ||
180 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
181 fprintf(file, hs);
182 while (--n >= 0) {
183 if ((!_res.pfcode) || sflag) {
184 cp = p_rr(cp, msg, file);
185 } else {
186 unsigned int dlen;
187 cp += __dn_skipname(cp, cp + MAXCDNAME);
188 cp += INT16SZ;
189 cp += INT16SZ;
190 cp += INT32SZ;
191 dlen = _getshort((u_char*)cp);
192 cp += INT16SZ;
193 cp += dlen;
195 if ((cp - msg) > len)
196 return (NULL);
198 if ((!_res.pfcode) ||
199 ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
200 putc('\n', file);
202 return (cp);
205 void
206 __p_query(msg)
207 const u_char *msg;
209 __fp_query(msg, stdout);
212 #ifdef ultrix
213 /* ultrix 4.0's packaging has some icky packaging. alias for it here.
214 * there is more junk of this kind over in res_comp.c.
216 void
217 p_query(msg)
218 const u_char *msg;
220 __p_query(msg);
222 #endif
225 * Print the current options.
226 * This is intended to be primarily a debugging routine.
228 void
229 __fp_resstat(statp, file)
230 struct __res_state *statp;
231 FILE *file;
233 register u_long mask;
235 fprintf(file, ";; res options:");
236 if (!statp)
237 statp = &_res;
238 for (mask = 1; mask != 0; mask <<= 1)
239 if (statp->options & mask)
240 fprintf(file, " %s", p_option(mask));
241 putc('\n', file);
245 * Print the contents of a query.
246 * This is intended to be primarily a debugging routine.
248 void
249 __fp_nquery(msg, len, file)
250 const u_char *msg;
251 int len;
252 FILE *file;
254 register const u_char *cp, *endMark;
255 register const HEADER *hp;
256 register int n;
258 if ((_res.options & RES_INIT) == 0 && res_init() == -1)
259 return;
261 #define TruncTest(x) if (x >= endMark) goto trunc
262 #define ErrorTest(x) if (x == NULL) goto error
265 * Print header fields.
267 hp = (HEADER *)msg;
268 cp = msg + HFIXEDSZ;
269 endMark = cp + len;
270 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
271 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
272 _res_opcodes[hp->opcode],
273 _res_resultcodes[hp->rcode],
274 ntohs(hp->id));
275 putc('\n', file);
277 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
278 putc(';', file);
279 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
280 fprintf(file, "; flags:");
281 if (hp->qr)
282 fprintf(file, " qr");
283 if (hp->aa)
284 fprintf(file, " aa");
285 if (hp->tc)
286 fprintf(file, " tc");
287 if (hp->rd)
288 fprintf(file, " rd");
289 if (hp->ra)
290 fprintf(file, " ra");
292 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
293 fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
294 fprintf(file, ", Ans: %d", ntohs(hp->ancount));
295 fprintf(file, ", Auth: %d", ntohs(hp->nscount));
296 fprintf(file, ", Addit: %d", ntohs(hp->arcount));
298 if ((!_res.pfcode) || (_res.pfcode &
299 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
300 putc('\n',file);
303 * Print question records.
305 if (n = ntohs(hp->qdcount)) {
306 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
307 fprintf(file, ";; QUESTIONS:\n");
308 while (--n >= 0) {
309 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
310 fprintf(file, ";;\t");
311 TruncTest(cp);
312 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
313 cp = p_cdnname(cp, msg, len, file);
314 else {
315 int n;
316 char name[MAXDNAME];
318 if ((n = dn_expand(msg, msg+len, cp, name,
319 sizeof name)) < 0)
320 cp = NULL;
321 else
322 cp += n;
324 ErrorTest(cp);
325 TruncTest(cp);
326 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
327 fprintf(file, ", type = %s",
328 __p_type(_getshort((u_char*)cp)));
329 cp += INT16SZ;
330 TruncTest(cp);
331 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
332 fprintf(file, ", class = %s\n",
333 __p_class(_getshort((u_char*)cp)));
334 cp += INT16SZ;
335 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
336 putc('\n', file);
340 * Print authoritative answer records
342 TruncTest(cp);
343 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
344 ";; ANSWERS:\n");
345 ErrorTest(cp);
348 * print name server records
350 TruncTest(cp);
351 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
352 ";; AUTHORITY RECORDS:\n");
353 ErrorTest(cp);
355 TruncTest(cp);
357 * print additional records
359 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
360 ";; ADDITIONAL RECORDS:\n");
361 ErrorTest(cp);
362 return;
363 trunc:
364 fprintf(file, "\n;; ...truncated\n");
365 return;
366 error:
367 fprintf(file, "\n;; ...malformed\n");
370 void
371 __fp_query(msg, file)
372 const u_char *msg;
373 FILE *file;
375 fp_nquery(msg, PACKETSZ, file);
378 const u_char *
379 __p_cdnname(cp, msg, len, file)
380 const u_char *cp, *msg;
381 int len;
382 FILE *file;
384 char name[MAXDNAME];
385 int n;
387 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
388 return (NULL);
389 if (name[0] == '\0')
390 putc('.', file);
391 else
392 fputs(name, file);
393 return (cp + n);
396 const u_char *
397 __p_cdname(cp, msg, file)
398 const u_char *cp, *msg;
399 FILE *file;
401 return (p_cdnname(cp, msg, PACKETSZ, file));
404 /* XXX: the rest of these functions need to become length-limited, too. (vix)
407 const u_char *
408 __p_fqname(cp, msg, file)
409 const u_char *cp, *msg;
410 FILE *file;
412 char name[MAXDNAME];
413 int n;
415 if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
416 return (NULL);
417 if (name[0] == '\0') {
418 putc('.', file);
419 } else {
420 fputs(name, file);
421 if (name[strlen(name) - 1] != '.')
422 putc('.', file);
424 return (cp + n);
428 * Print resource record fields in human readable form.
430 const u_char *
431 __p_rr(cp, msg, file)
432 const u_char *cp, *msg;
433 FILE *file;
435 int type, class, dlen, n, c;
436 struct in_addr inaddr;
437 const u_char *cp1, *cp2;
438 u_int32_t tmpttl, t;
439 int lcnt;
441 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
442 h_errno = NETDB_INTERNAL;
443 return (NULL);
445 if ((cp = p_fqname(cp, msg, file)) == NULL)
446 return (NULL); /* compression error */
447 type = _getshort((u_char*)cp);
448 cp += INT16SZ;
449 class = _getshort((u_char*)cp);
450 cp += INT16SZ;
451 tmpttl = _getlong((u_char*)cp);
452 cp += INT32SZ;
453 dlen = _getshort((u_char*)cp);
454 cp += INT16SZ;
455 cp1 = cp;
456 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
457 fprintf(file, "\t%lu", (u_long)tmpttl);
458 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
459 fprintf(file, "\t%s", __p_class(class));
460 fprintf(file, "\t%s", __p_type(type));
462 * Print type specific data, if appropriate
464 switch (type) {
465 case T_A:
466 switch (class) {
467 case C_IN:
468 case C_HS:
469 bcopy(cp, (char *)&inaddr, INADDRSZ);
470 if (dlen == 4) {
471 fprintf(file, "\t%s", inet_ntoa(inaddr));
472 cp += dlen;
473 } else if (dlen == 7) {
474 char *address;
475 u_char protocol;
476 u_short port;
478 address = inet_ntoa(inaddr);
479 cp += INADDRSZ;
480 protocol = *(u_char*)cp;
481 cp += sizeof(u_char);
482 port = _getshort((u_char*)cp);
483 cp += INT16SZ;
484 fprintf(file, "\t%s\t; proto %d, port %d",
485 address, protocol, port);
487 break;
488 default:
489 cp += dlen;
491 break;
492 case T_CNAME:
493 case T_MB:
494 case T_MG:
495 case T_MR:
496 case T_NS:
497 case T_PTR:
498 putc('\t', file);
499 if ((cp = p_fqname(cp, msg, file)) == NULL)
500 return (NULL);
501 break;
503 case T_HINFO:
504 case T_ISDN:
505 cp2 = cp + dlen;
506 if (n = *cp++) {
507 fprintf(file, "\t%.*s", n, cp);
508 cp += n;
510 if ((cp < cp2) && (n = *cp++)) {
511 fprintf(file, "\t%.*s", n, cp);
512 cp += n;
513 } else if (type == T_HINFO)
514 fprintf(file, "\n;; *** Warning *** OS-type missing");
515 break;
517 case T_SOA:
518 putc('\t', file);
519 if ((cp = p_fqname(cp, msg, file)) == NULL)
520 return (NULL);
521 putc(' ', file);
522 if ((cp = p_fqname(cp, msg, file)) == NULL)
523 return (NULL);
524 fputs(" (\n", file);
525 t = _getlong((u_char*)cp); cp += INT32SZ;
526 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
527 t = _getlong((u_char*)cp); cp += INT32SZ;
528 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
529 (u_long)t, __p_time(t));
530 t = _getlong((u_char*)cp); cp += INT32SZ;
531 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
532 (u_long)t, __p_time(t));
533 t = _getlong((u_char*)cp); cp += INT32SZ;
534 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
535 (u_long)t, __p_time(t));
536 t = _getlong((u_char*)cp); cp += INT32SZ;
537 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
538 (u_long)t, __p_time(t));
539 break;
541 case T_MX:
542 case T_AFSDB:
543 case T_RT:
544 fprintf(file, "\t%d ", _getshort((u_char*)cp));
545 cp += INT16SZ;
546 if ((cp = p_fqname(cp, msg, file)) == NULL)
547 return (NULL);
548 break;
550 case T_PX:
551 fprintf(file, "\t%d ", _getshort((u_char*)cp));
552 cp += INT16SZ;
553 if ((cp = p_fqname(cp, msg, file)) == NULL)
554 return (NULL);
555 putc(' ', file);
556 if ((cp = p_fqname(cp, msg, file)) == NULL)
557 return (NULL);
558 break;
560 case T_TXT:
561 case T_X25:
562 (void) fputs("\t\"", file);
563 cp2 = cp1 + dlen;
564 while (cp < cp2) {
565 if (n = (unsigned char) *cp++) {
566 for (c = n; c > 0 && cp < cp2; c--)
567 if ((*cp == '\n') || (*cp == '"')) {
568 (void) putc('\\', file);
569 (void) putc(*cp++, file);
570 } else
571 (void) putc(*cp++, file);
574 putc('"', file);
575 break;
577 case T_NSAP:
578 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
579 cp += dlen;
580 break;
582 case T_MINFO:
583 case T_RP:
584 putc('\t', file);
585 if ((cp = p_fqname(cp, msg, file)) == NULL)
586 return (NULL);
587 putc(' ', file);
588 if ((cp = p_fqname(cp, msg, file)) == NULL)
589 return (NULL);
590 break;
592 case T_UINFO:
593 putc('\t', file);
594 fputs((char *)cp, file);
595 cp += dlen;
596 break;
598 case T_UID:
599 case T_GID:
600 if (dlen == 4) {
601 fprintf(file, "\t%u", _getlong((u_char*)cp));
602 cp += INT32SZ;
604 break;
606 case T_WKS:
607 if (dlen < INT32SZ + 1)
608 break;
609 bcopy(cp, (char *)&inaddr, INADDRSZ);
610 cp += INT32SZ;
611 fprintf(file, "\t%s %s ( ",
612 inet_ntoa(inaddr),
613 deproto((int) *cp));
614 cp += sizeof(u_char);
615 n = 0;
616 lcnt = 0;
617 while (cp < cp1 + dlen) {
618 c = *cp++;
619 do {
620 if (c & 0200) {
621 if (lcnt == 0) {
622 fputs("\n\t\t\t", file);
623 lcnt = 5;
625 fputs(dewks(n), file);
626 putc(' ', file);
627 lcnt--;
629 c <<= 1;
630 } while (++n & 07);
632 putc(')', file);
633 break;
635 #ifdef ALLOW_T_UNSPEC
636 case T_UNSPEC:
638 int NumBytes = 8;
639 u_char *DataPtr;
640 int i;
642 if (dlen < NumBytes) NumBytes = dlen;
643 fprintf(file, "\tFirst %d bytes of hex data:",
644 NumBytes);
645 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
646 fprintf(file, " %x", *DataPtr);
647 cp += dlen;
649 break;
650 #endif /* ALLOW_T_UNSPEC */
652 default:
653 fprintf(file, "\t?%d?", type);
654 cp += dlen;
656 #if 0
657 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
658 #else
659 putc('\n', file);
660 #endif
661 if (cp - cp1 != dlen) {
662 fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
663 cp - cp1, dlen);
664 cp = NULL;
666 return (cp);
670 * Return a string for the type
672 const char *
673 __p_type(type)
674 int type;
676 static char nbuf[20];
678 switch (type) {
679 case T_A: return "A";
680 case T_NS: return "NS";
681 case T_CNAME: return "CNAME";
682 case T_SOA: return "SOA";
683 case T_MB: return "MB";
684 case T_MG: return "MG";
685 case T_MR: return "MR";
686 case T_NULL: return "NULL";
687 case T_WKS: return "WKS";
688 case T_PTR: return "PTR";
689 case T_HINFO: return "HINFO";
690 case T_MINFO: return "MINFO";
691 case T_MX: return "MX";
692 case T_TXT: return "TXT";
693 case T_RP: return "RP";
694 case T_AFSDB: return "AFSDB";
695 case T_X25: return "X25";
696 case T_ISDN: return "ISDN";
697 case T_RT: return "RT";
698 case T_NSAP: return "NSAP";
699 case T_NSAP_PTR: return "NSAP_PTR";
700 case T_SIG: return "SIG";
701 case T_KEY: return "KEY";
702 case T_PX: return "PX";
703 case T_GPOS: return "GPOS";
704 case T_AAAA: return "AAAA";
705 case T_LOC: return "LOC";
706 case T_AXFR: return "AXFR";
707 case T_MAILB: return "MAILB";
708 case T_MAILA: return "MAILA";
709 case T_ANY: return "ANY";
710 case T_UINFO: return "UINFO";
711 case T_UID: return "UID";
712 case T_GID: return "GID";
713 #ifdef ALLOW_T_UNSPEC
714 case T_UNSPEC: return "UNSPEC";
715 #endif /* ALLOW_T_UNSPEC */
716 default: (void)sprintf(nbuf, "%d", type); return (nbuf);
721 * Return a mnemonic for class
723 const char *
724 __p_class(class)
725 int class;
727 static char nbuf[20];
729 switch (class) {
730 case C_IN: return "IN";
731 case C_HS: return "HS";
732 case C_ANY: return "ANY";
733 default: (void)sprintf(nbuf, "%d", class); return (nbuf);
738 * Return a mnemonic for an option
740 const char *
741 __p_option(option)
742 u_long option;
744 static char nbuf[40];
746 switch (option) {
747 case RES_INIT: return "init";
748 case RES_DEBUG: return "debug";
749 case RES_AAONLY: return "aaonly(unimpl)";
750 case RES_USEVC: return "usevc";
751 case RES_PRIMARY: return "primry(unimpl)";
752 case RES_IGNTC: return "igntc";
753 case RES_RECURSE: return "recurs";
754 case RES_DEFNAMES: return "defnam";
755 case RES_STAYOPEN: return "styopn";
756 case RES_DNSRCH: return "dnsrch";
757 case RES_INSECURE1: return "insecure1";
758 case RES_INSECURE2: return "insecure2";
759 default: sprintf(nbuf, "?0x%lx?", (u_long)option);
760 return (nbuf);
765 * Return a mnemonic for a time to live
767 char *
768 __p_time(value)
769 u_int32_t value;
771 static char nbuf[40];
772 int secs, mins, hours, days;
773 register char *p;
775 if (value == 0) {
776 strcpy(nbuf, "0 secs");
777 return (nbuf);
780 secs = value % 60;
781 value /= 60;
782 mins = value % 60;
783 value /= 60;
784 hours = value % 24;
785 value /= 24;
786 days = value;
787 value = 0;
789 #define PLURALIZE(x) x, (x == 1) ? "" : "s"
790 p = nbuf;
791 if (days) {
792 (void)sprintf(p, "%d day%s", PLURALIZE(days));
793 while (*++p);
795 if (hours) {
796 if (days)
797 *p++ = ' ';
798 (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
799 while (*++p);
801 if (mins) {
802 if (days || hours)
803 *p++ = ' ';
804 (void)sprintf(p, "%d min%s", PLURALIZE(mins));
805 while (*++p);
807 if (secs || ! (days || hours || mins)) {
808 if (days || hours || mins)
809 *p++ = ' ';
810 (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
812 return (nbuf);