res_debug.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1985, 1990, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  * 
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *  This product includes software developed by the University of
  16.  *  California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  * 
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  34.  * 
  35.  * Permission to use, copy, modify, and distribute this software for any
  36.  * purpose with or without fee is hereby granted, provided that the above
  37.  * copyright notice and this permission notice appear in all copies, and that
  38.  * the name of Digital Equipment Corporation not be used in advertising or
  39.  * publicity pertaining to distribution of the document or software without
  40.  * specific, written prior permission.
  41.  * 
  42.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  43.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  44.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  45.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  46.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  47.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  48.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  49.  * SOFTWARE.
  50.  */
  51. #if defined(LIBC_SCCS) && !defined(lint)
  52. static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
  53. static char rcsid[] = "$Id$";
  54. #endif /* LIBC_SCCS and not lint */
  55. #include <pthread.h>
  56. #include <sys/param.h>
  57. #include <stdio.h>
  58. #include <string.h>
  59. #include <resolv.h>
  60. #include <arpa/inet.h>
  61. void __fp_query();
  62. char *__p_class(), *__p_time(), *__p_type();
  63. char *p_cdname(), *p_fqname(), *p_rr();
  64. static char *p_option __P_((u_long));
  65. char *_res_opcodes[] = {
  66. "QUERY",
  67. "IQUERY",
  68. "CQUERYM",
  69. "CQUERYU",
  70. "4",
  71. "5",
  72. "6",
  73. "7",
  74. "8",
  75. "UPDATEA",
  76. "UPDATED",
  77. "UPDATEDA",
  78. "UPDATEM",
  79. "UPDATEMA",
  80. "ZONEINIT",
  81. "ZONEREF",
  82. };
  83. char *_res_resultcodes[] = {
  84. "NOERROR",
  85. "FORMERR",
  86. "SERVFAIL",
  87. "NXDOMAIN",
  88. "NOTIMP",
  89. "REFUSED",
  90. "6",
  91. "7",
  92. "8",
  93. "9",
  94. "10",
  95. "11",
  96. "12",
  97. "13",
  98. "14",
  99. "NOCHANGE",
  100. };
  101. static char retbuf[16];
  102. static char *
  103. dewks(wks)
  104. int wks;
  105. {
  106. switch (wks) {
  107. case 5: return("rje");
  108. case 7: return("echo");
  109. case 9: return("discard");
  110. case 11: return("systat");
  111. case 13: return("daytime");
  112. case 15: return("netstat");
  113. case 17: return("qotd");
  114. case 19: return("chargen");
  115. case 20: return("ftp-data");
  116. case 21: return("ftp");
  117. case 23: return("telnet");
  118. case 25: return("smtp");
  119. case 37: return("time");
  120. case 39: return("rlp");
  121. case 42: return("name");
  122. case 43: return("whois");
  123. case 53: return("domain");
  124. case 57: return("apts");
  125. case 59: return("apfs");
  126. case 67: return("bootps");
  127. case 68: return("bootpc");
  128. case 69: return("tftp");
  129. case 77: return("rje");
  130. case 79: return("finger");
  131. case 87: return("link");
  132. case 95: return("supdup");
  133. case 100: return("newacct");
  134. case 101: return("hostnames");
  135. case 102: return("iso-tsap");
  136. case 103: return("x400");
  137. case 104: return("x400-snd");
  138. case 105: return("csnet-ns");
  139. case 109: return("pop-2");
  140. case 111: return("sunrpc");
  141. case 113: return("auth");
  142. case 115: return("sftp");
  143. case 117: return("uucp-path");
  144. case 119: return("nntp");
  145. case 121: return("erpc");
  146. case 123: return("ntp");
  147. case 133: return("statsrv");
  148. case 136: return("profile");
  149. case 144: return("NeWS");
  150. case 161: return("snmp");
  151. case 162: return("snmp-trap");
  152. case 170: return("print-srv");
  153. default: (void) sprintf(retbuf, "%d", wks); return(retbuf);
  154. }
  155. }
  156. static char *
  157. deproto(protonum)
  158. int protonum;
  159. {
  160. switch (protonum) {
  161. case 1: return("icmp");
  162. case 2: return("igmp");
  163. case 3: return("ggp");
  164. case 5: return("st");
  165. case 6: return("tcp");
  166. case 7: return("ucl");
  167. case 8: return("egp");
  168. case 9: return("igp");
  169. case 11: return("nvp-II");
  170. case 12: return("pup");
  171. case 16: return("chaos");
  172. case 17: return("udp");
  173. default: (void) sprintf(retbuf, "%d", protonum); return(retbuf);
  174. }
  175. }
  176. static char *
  177. do_rrset(msg, cp, cnt, pflag, file, hs)
  178. int cnt, pflag;
  179. char *cp,*msg, *hs;
  180. FILE *file;
  181. {
  182. int n;
  183. int sflag;
  184. /*
  185.  * Print  answer records
  186.  */
  187. sflag = (_res.pfcode & pflag);
  188. if (n = ntohs(cnt)) {
  189. if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
  190. fprintf(file, hs);
  191. while (--n >= 0) {
  192. cp = p_rr(cp, msg, file);
  193. if ((cp-msg) > PACKETSZ)
  194. return (NULL);
  195. }
  196. if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
  197. putc('n', file);
  198. }
  199. return(cp);
  200. }
  201. __p_query(msg)
  202. char *msg;
  203. {
  204. __fp_query(msg, stdout);
  205. }
  206. /*
  207.  * Print the current options.
  208.  * This is intended to be primarily a debugging routine.
  209.  */
  210. void
  211. __fp_resstat(statp, file)
  212. struct __res_state *statp;
  213. FILE *file;
  214. {
  215. int bit;
  216. fprintf(file, ";; res options:");
  217. if (!statp)
  218. statp = &_res;
  219. for (bit = 0;  bit < 32;  bit++) { /* XXX 32 - bad assumption! */
  220. if (statp->options & (1<<bit))
  221. fprintf(file, " %s", p_option(1<<bit));
  222. }
  223. putc('n', file);
  224. }
  225. /*
  226.  * Print the contents of a query.
  227.  * This is intended to be primarily a debugging routine.
  228.  */
  229. void
  230. __fp_query(msg,file)
  231. char *msg;
  232. FILE *file;
  233. {
  234. register char *cp;
  235. register HEADER *hp;
  236. register int n;
  237. /*
  238.  * Print header fields.
  239.  */
  240. hp = (HEADER *)msg;
  241. cp = msg + sizeof(HEADER);
  242. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
  243. fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
  244. _res_opcodes[hp->opcode],
  245. _res_resultcodes[hp->rcode],
  246. ntohs(hp->id));
  247. putc('n', file);
  248. }
  249. putc(';', file);
  250. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
  251. fprintf(file,"; flags:");
  252. if (hp->qr)
  253. fprintf(file," qr");
  254. if (hp->aa)
  255. fprintf(file," aa");
  256. if (hp->tc)
  257. fprintf(file," tc");
  258. if (hp->rd)
  259. fprintf(file," rd");
  260. if (hp->ra)
  261. fprintf(file," ra");
  262. if (hp->pr)
  263. fprintf(file," pr");
  264. }
  265. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
  266. fprintf(file,"; Ques: %d", ntohs(hp->qdcount));
  267. fprintf(file,", Ans: %d", ntohs(hp->ancount));
  268. fprintf(file,", Auth: %d", ntohs(hp->nscount));
  269. fprintf(file,", Addit: %d", ntohs(hp->arcount));
  270. }
  271. #if 1
  272. if ((!_res.pfcode) || (_res.pfcode & 
  273. (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
  274. putc('n',file);
  275. }
  276. #endif
  277. /*
  278.  * Print question records.
  279.  */
  280. if (n = ntohs(hp->qdcount)) {
  281. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
  282. fprintf(file,";; QUESTIONS:n");
  283. while (--n >= 0) {
  284. fprintf(file,";;t");
  285. cp = p_cdname(cp, msg, file);
  286. if (cp == NULL)
  287. return;
  288. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
  289. fprintf(file, ", type = %s",
  290. __p_type(_getshort(cp)));
  291. cp += sizeof(u_short);
  292. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
  293. fprintf(file, ", class = %sn",
  294. __p_class(_getshort(cp)));
  295. cp += sizeof(u_short);
  296. putc('n', file);
  297. }
  298. }
  299. /*
  300.  * Print authoritative answer records
  301.  */
  302. cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file,
  303.       ";; ANSWERS:n");
  304. if (cp == NULL)
  305. return;
  306. /*
  307.  * print name server records
  308.  */
  309. cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file,
  310.       ";; AUTHORITY RECORDS:n");
  311. if (!cp)
  312. return;
  313. /*
  314.  * print additional records
  315.  */
  316. cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file,
  317.       ";; ADDITIONAL RECORDS:n");
  318. if (!cp)
  319. return;
  320. }
  321. char *
  322. p_cdname(cp, msg, file)
  323. char *cp, *msg;
  324. FILE *file;
  325. {
  326. char name[MAXDNAME];
  327. int n;
  328. if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME,
  329.    (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
  330. return (NULL);
  331. if (name[0] == '')
  332. putc('.', file);
  333. else
  334. fputs(name, file);
  335. return (cp + n);
  336. }
  337. char *
  338. p_fqname(cp, msg, file)
  339. char *cp, *msg;
  340. FILE *file;
  341. {
  342. char name[MAXDNAME];
  343. int n, len;
  344. if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME,
  345.    (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
  346. return (NULL);
  347. if (name[0] == '') {
  348. putc('.', file);
  349. } else {
  350. fputs(name, file);
  351. if (name[strlen(name) - 1] != '.')
  352. putc('.', file);
  353. }
  354. return (cp + n);
  355. }
  356. /*
  357.  * Print resource record fields in human readable form.
  358.  *
  359.  * Removed calls to non-reentrant routines to simplify varifying
  360.  * POSIX thread-safe implementations. (mevans).
  361.  */
  362. char *
  363. p_rr(cp, msg, file)
  364. char *cp, *msg;
  365. FILE *file;
  366. {
  367. int type, class, dlen, n, c;
  368. struct in_addr inaddr;
  369. char *cp1, *cp2;
  370. u_long tmpttl, t;
  371. int lcnt;
  372. char buf[32];
  373. if ((cp = p_fqname(cp, msg, file)) == NULL)
  374. return (NULL); /* compression error */
  375. type = _getshort(cp);
  376. cp += sizeof(u_short);
  377. class = _getshort(cp);
  378. cp += sizeof(u_short);
  379. tmpttl = _getlong(cp);
  380. cp += sizeof(u_long);
  381. dlen = _getshort(cp);
  382. cp += sizeof(u_short);
  383. cp1 = cp;
  384. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
  385. fprintf(file, "t%lu", tmpttl);
  386. if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
  387. fprintf(file, "t%s", __p_class(class));
  388. fprintf(file, "t%s", __p_type(type));
  389. /*
  390.  * Print type specific data, if appropriate
  391.  */
  392. switch (type) {
  393. case T_A:
  394. switch (class) {
  395. case C_IN:
  396. case C_HS:
  397. bcopy(cp, (char *)&inaddr, sizeof(inaddr));
  398. if (dlen == 4) {
  399.   fprintf(file,"t%s",
  400.   inet_ntoa_r(inaddr, buf, sizeof(buf)));
  401.   cp += dlen;
  402. } else if (dlen == 7) {
  403. char *address;
  404. u_char protocol;
  405. u_short port;
  406. address = inet_ntoa_r(inaddr,
  407.       buf, sizeof(buf));
  408. cp += sizeof(inaddr);
  409. protocol = *(u_char*)cp;
  410. cp += sizeof(u_char);
  411. port = _getshort(cp);
  412. cp += sizeof(u_short);
  413. fprintf(file, "t%st; proto %d, port %d",
  414. address, protocol, port);
  415. }
  416. break;
  417. default:
  418. cp += dlen;
  419. }
  420. break;
  421. case T_CNAME:
  422. case T_MB:
  423. case T_MG:
  424. case T_MR:
  425. case T_NS:
  426. case T_PTR:
  427. putc('t', file);
  428. cp = p_fqname(cp, msg, file);
  429. break;
  430. case T_HINFO:
  431. if (n = *cp++) {
  432. fprintf(file,"t%.*s", n, cp);
  433. cp += n;
  434. }
  435. if (n = *cp++) {
  436. fprintf(file,"t%.*s", n, cp);
  437. cp += n;
  438. }
  439. break;
  440. case T_SOA:
  441. putc('t', file);
  442. cp = p_fqname(cp, msg, file); /* origin */
  443. putc(' ', file);
  444. cp = p_fqname(cp, msg, file); /* mail addr */
  445. fputs(" (n", file);
  446. t = _getlong(cp);  cp += sizeof(u_long);
  447. fprintf(file,"ttt%lut; serialn", t);
  448. t = _getlong(cp);  cp += sizeof(u_long);
  449. fprintf(file,"ttt%lut; refresh (%s)n", t, __p_time(t));
  450. t = _getlong(cp);  cp += sizeof(u_long);
  451. fprintf(file,"ttt%lut; retry (%s)n", t, __p_time(t));
  452. t = _getlong(cp);  cp += sizeof(u_long);
  453. fprintf(file,"ttt%lut; expire (%s)n", t, __p_time(t));
  454. t = _getlong(cp);  cp += sizeof(u_long);
  455. fprintf(file,"ttt%lu )t; minimum (%s)", t, __p_time(t));
  456. break;
  457. case T_MX:
  458. case T_AFSDB:
  459. fprintf(file,"t%d ", _getshort(cp));
  460. cp += sizeof(u_short);
  461. cp = p_fqname(cp, msg, file);
  462. break;
  463.    case T_TXT:
  464. (void) fputs("t"", file);
  465. cp2 = cp1 + dlen;
  466. while (cp < cp2) {
  467. if (n = (unsigned char) *cp++) {
  468. for (c = n; c > 0 && cp < cp2; c--)
  469. if (*cp == 'n') {
  470.     (void) putc('\', file);
  471.     (void) putc(*cp++, file);
  472. } else
  473.     (void) putc(*cp++, file);
  474. }
  475. }
  476. putc('"', file);
  477.    break;
  478. case T_MINFO:
  479. case T_RP:
  480. putc('t', file);
  481. cp = p_fqname(cp, msg, file);
  482. putc(' ', file);
  483. cp = p_fqname(cp, msg, file);
  484. break;
  485. case T_UINFO:
  486. putc('t', file);
  487. fputs(cp, file);
  488. cp += dlen;
  489. break;
  490. case T_UID:
  491. case T_GID:
  492. if (dlen == 4) {
  493. fprintf(file,"t%u", _getlong(cp));
  494. cp += sizeof(long);
  495. }
  496. break;
  497. case T_WKS:
  498. if (dlen < sizeof(u_long) + 1)
  499. break;
  500. bcopy(cp, (char *)&inaddr, sizeof(inaddr));
  501. cp += sizeof(u_long);
  502. fprintf(file, "t%s %s ( ",
  503. inet_ntoa_r(inaddr, buf, sizeof(buf)),
  504. deproto((int) *cp));
  505. cp += sizeof(u_char);
  506. n = 0;
  507. lcnt = 0;
  508. while (cp < cp1 + dlen) {
  509. c = *cp++;
  510. do {
  511.   if (c & 0200) {
  512. if (lcnt == 0) {
  513. fputs("nttt", file);
  514. lcnt = 5;
  515. }
  516. fputs(dewks(n), file);
  517. putc(' ', file);
  518. lcnt--;
  519. }
  520.   c <<= 1;
  521. } while (++n & 07);
  522. }
  523. putc(')', file);
  524. break;
  525. #ifdef ALLOW_T_UNSPEC
  526. case T_UNSPEC:
  527. {
  528. int NumBytes = 8;
  529. char *DataPtr;
  530. int i;
  531. if (dlen < NumBytes) NumBytes = dlen;
  532. fprintf(file, "tFirst %d bytes of hex data:",
  533. NumBytes);
  534. for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
  535. fprintf(file, " %x", *DataPtr);
  536. cp += dlen;
  537. }
  538. break;
  539. #endif /* ALLOW_T_UNSPEC */
  540. default:
  541. fprintf(file,"t?%d?", type);
  542. cp += dlen;
  543. }
  544. #if 0
  545. fprintf(file, "t; dlen=%d, ttl %sn", dlen, __p_time(tmpttl));
  546. #else
  547. putc('n', file);
  548. #endif
  549. if (cp - cp1 != dlen) {
  550. fprintf(file,";; packet size error (found %d, dlen was %d)n",
  551. cp - cp1, dlen);
  552. cp = NULL;
  553. }
  554. return (cp);
  555. }
  556. static char nbuf[40];
  557. /*
  558.  * Return a string for the type
  559.  */
  560. char *
  561. __p_type(type)
  562. int type;
  563. {
  564. switch (type) {
  565. case T_A:
  566. return("A");
  567. case T_NS: /* authoritative server */
  568. return("NS");
  569. case T_CNAME: /* canonical name */
  570. return("CNAME");
  571. case T_SOA: /* start of authority zone */
  572. return("SOA");
  573. case T_MB: /* mailbox domain name */
  574. return("MB");
  575. case T_MG: /* mail group member */
  576. return("MG");
  577. case T_MR: /* mail rename name */
  578. return("MR");
  579. case T_NULL: /* null resource record */
  580. return("NULL");
  581. case T_WKS: /* well known service */
  582. return("WKS");
  583. case T_PTR: /* domain name pointer */
  584. return("PTR");
  585. case T_HINFO: /* host information */
  586. return("HINFO");
  587. case T_MINFO: /* mailbox information */
  588. return("MINFO");
  589. case T_MX: /* mail routing info */
  590. return("MX");
  591. case T_TXT: /* text */
  592. return("TXT");
  593. case T_RP: /* responsible person */
  594. return("RP");
  595. case T_AFSDB: /* AFS cell database */
  596. return("AFSDB");
  597. case T_AXFR: /* zone transfer */
  598. return("AXFR");
  599. case T_MAILB: /* mail box */
  600. return("MAILB");
  601. case T_MAILA: /* mail address */
  602. return("MAILA");
  603. case T_ANY: /* matches any type */
  604. return("ANY");
  605. case T_UINFO:
  606. return("UINFO");
  607. case T_UID:
  608. return("UID");
  609. case T_GID:
  610. return("GID");
  611. #ifdef ALLOW_T_UNSPEC
  612. case T_UNSPEC:
  613. return("UNSPEC");
  614. #endif /* ALLOW_T_UNSPEC */
  615. default:
  616. (void)sprintf(nbuf, "%d", type);
  617. return(nbuf);
  618. }
  619. }
  620. /*
  621.  * Return a mnemonic for class
  622.  */
  623. char *
  624. __p_class(class)
  625. int class;
  626. {
  627. switch (class) {
  628. case C_IN: /* internet class */
  629. return("IN");
  630. case C_HS: /* hesiod class */
  631. return("HS");
  632. case C_ANY: /* matches any class */
  633. return("ANY");
  634. default:
  635. (void)sprintf(nbuf, "%d", class);
  636. return(nbuf);
  637. }
  638. }
  639. /*
  640.  * Return a mnemonic for an option
  641.  */
  642. static char *
  643. p_option(option)
  644. u_long option;
  645. {
  646. switch (option) {
  647. case RES_INIT: return "init";
  648. case RES_DEBUG: return "debug";
  649. case RES_AAONLY: return "aaonly";
  650. case RES_USEVC: return "usevc";
  651. case RES_PRIMARY: return "primry";
  652. case RES_IGNTC: return "igntc";
  653. case RES_RECURSE: return "recurs";
  654. case RES_DEFNAMES: return "defnam";
  655. case RES_STAYOPEN: return "styopn";
  656. case RES_DNSRCH: return "dnsrch";
  657. default: sprintf(nbuf, "?0x%x?", option); return nbuf;
  658. }
  659. }
  660. /*
  661.  * Return a mnemonic for a time to live
  662.  */
  663. char *
  664. __p_time(value)
  665. u_long value;
  666. {
  667. int secs, mins, hours, days;
  668. register char *p;
  669. if (value == 0) {
  670. strcpy(nbuf, "0 secs");
  671. return(nbuf);
  672. }
  673. secs = value % 60;
  674. value /= 60;
  675. mins = value % 60;
  676. value /= 60;
  677. hours = value % 24;
  678. value /= 24;
  679. days = value;
  680. value = 0;
  681. #define PLURALIZE(x) x, (x == 1) ? "" : "s"
  682. p = nbuf;
  683. if (days) {
  684. (void)sprintf(p, "%d day%s", PLURALIZE(days));
  685. while (*++p);
  686. }
  687. if (hours) {
  688. if (days)
  689. *p++ = ' ';
  690. (void)sprintf(p, "%d hour%s", PLURALIZE(hours));
  691. while (*++p);
  692. }
  693. if (mins) {
  694. if (days || hours)
  695. *p++ = ' ';
  696. (void)sprintf(p, "%d min%s", PLURALIZE(mins));
  697. while (*++p);
  698. }
  699. if (secs || ! (days || hours || mins)) {
  700. if (days || hours || mins)
  701. *p++ = ' ';
  702. (void)sprintf(p, "%d sec%s", PLURALIZE(secs));
  703. }
  704. return(nbuf);
  705. }