home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / ns2tab / part02 < prev    next >
Encoding:
Text File  |  1993-04-03  |  52.0 KB  |  2,029 lines

  1. Newsgroups: comp.sources.unix
  2. From: i3558@newsie.dc.dk (Soeren Michael Roug)
  3. Subject: v26i093: ns2tab - Increasing the usefullnes of the nameserver, Part02/03
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: i3558@newsie.dc.dk (Soeren Michael Roug)
  8. Posting-Number: Volume 26, Issue 93
  9. Archive-Name: ns2tab/part02
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 2 (of 3)."
  18. # Contents:  getinfo.c hash.c main.c
  19. # Wrapped by i3558@ulrik.dc.dk on Fri Mar 26 15:05:34 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'getinfo.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'getinfo.c'\"
  23. else
  24. echo shar: Extracting \"'getinfo.c'\" \(20155 characters\)
  25. sed "s/^X//" >'getinfo.c' <<'END_OF_FILE'
  26. X/*
  27. X * Copyright (c) 1985,1989 Regents of the University of California.
  28. X * All rights reserved.
  29. X *
  30. X * Redistribution and use in source and binary forms are permitted provided
  31. X * that: (1) source distributions retain this entire copyright notice and
  32. X * comment, and (2) distributions including binaries display the following
  33. X * acknowledgement:  ``This product includes software developed by the
  34. X * University of California, Berkeley and its contributors'' in the
  35. X * documentation or other materials provided with the distribution and in
  36. X * all advertising materials mentioning features or use of this software.
  37. X * Neither the name of the University nor the names of its contributors may
  38. X * be used to endorse or promote products derived from this software without
  39. X * specific prior written permission.
  40. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  41. X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  42. X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  43. X */
  44. X
  45. X#ifndef lint
  46. Xstatic char sccsid[] = "@(#)getinfo.c    5.22 (Berkeley) 6/1/90";
  47. X#endif /* not lint */
  48. X
  49. X/*
  50. X *******************************************************************************
  51. X *
  52. X *  getinfo.c --
  53. X *
  54. X *    Routines to create requests to name servers
  55. X *    and interpret the answers.
  56. X *
  57. X *    Adapted from 4.3BSD BIND gethostnamadr.c
  58. X *
  59. X *******************************************************************************
  60. X */
  61. X
  62. X#include <sys/types.h>
  63. X#include <sys/socket.h>
  64. X#include <netinet/in.h>
  65. X#include <stdio.h>
  66. X#include <ctype.h>
  67. X#include <arpa/nameser.h>
  68. X#include <arpa/inet.h>
  69. X#include <resolv.h>
  70. X#include "res.h"
  71. X
  72. Xextern char *_res_resultcodes[];
  73. Xextern char *res_skip();
  74. X
  75. X#define    MAXALIASES    35
  76. X#define MAXADDRS    35
  77. X#define MAXDOMAINS    35
  78. X#define MAXSERVERS    10
  79. X
  80. Xstatic char *addr_list[MAXADDRS + 1];
  81. X
  82. Xstatic char *host_aliases[MAXALIASES];
  83. Xstatic int   host_aliases_len[MAXALIASES];
  84. Xstatic char  hostbuf[BUFSIZ+1];
  85. X
  86. Xtypedef struct {
  87. X    char *name;
  88. X    char *domain[MAXDOMAINS];
  89. X    int   numDomains;
  90. X    char *address[MAXADDRS];
  91. X    int   numAddresses;
  92. X} ServerTable;
  93. X
  94. XServerTable server[MAXSERVERS];
  95. X
  96. Xtypedef union {
  97. X    HEADER qb1;
  98. X    char qb2[PACKETSZ];
  99. X} querybuf;
  100. X
  101. Xtypedef union {
  102. X    long al;
  103. X    char ac;
  104. X} align;
  105. X
  106. X#define GetShort(cp)    _getshort(cp); cp += sizeof(unsigned short);
  107. X
  108. X
  109. X/*
  110. X *******************************************************************************
  111. X *
  112. X *  GetAnswer --
  113. X *
  114. X *    Interprets an answer packet and retrieves the following
  115. X *    information:
  116. X *
  117. X *  Results:
  118. X *      SUCCESS         the info was retrieved.
  119. X *      NO_INFO         the packet did not contain an answer.
  120. X *    NONAUTH        non-authoritative information was found.
  121. X *      ERROR           the answer was malformed.
  122. X *      Other errors    returned in the packet header.
  123. X *
  124. X *******************************************************************************
  125. X */
  126. X
  127. Xstatic int
  128. XGetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer)
  129. X    struct in_addr    *nsAddrPtr;
  130. X    char        *msg;
  131. X    int            queryType;
  132. X    int            msglen;
  133. X    Boolean        iquery;
  134. X    register HostInfo    *hostPtr;
  135. X    Boolean        isServer;
  136. X{
  137. X    register HEADER    *headerPtr;
  138. X    register char    *cp;
  139. X    querybuf        answer;
  140. X    char        *eom, *bp, **aliasPtr;
  141. X    char        **addrPtr;
  142. X    char        *namePtr;
  143. X    char        *dnamePtr;
  144. X    int            type, qclass;
  145. X    int            qdcount, ancount, arcount, nscount, buflen;
  146. X    int            origClass;
  147. X    int            numAliases = 0;
  148. X    int            numAddresses = 0;
  149. X    int            n, i, j;
  150. X    int            len;
  151. X    int            dlen;
  152. X    int            status;
  153. X    int            numServers;
  154. X    Boolean        haveAnswer;
  155. X    Boolean        printedAnswers = FALSE;
  156. X
  157. X
  158. X    /*
  159. X     *  If the hostPtr was used before, free up the calloc'd areas.
  160. X     */
  161. X    FreeHostInfoPtr(hostPtr);
  162. X
  163. X    status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer,
  164. X                sizeof(answer), &n);
  165. X
  166. X    if (status != SUCCESS) {
  167. X        if (_res.options & RES_DEBUG2)
  168. X            printf("SendRequest failed\n");
  169. X        return (status);
  170. X    }
  171. X    eom = (char *) &answer + n;
  172. X
  173. X    headerPtr = (HEADER *) &answer;
  174. X
  175. X    if (headerPtr->rcode != NOERROR) {
  176. X    return (headerPtr->rcode);
  177. X    }
  178. X
  179. X    qdcount = ntohs(headerPtr->qdcount);
  180. X    ancount = ntohs(headerPtr->ancount);
  181. X    arcount = ntohs(headerPtr->arcount);
  182. X    nscount = ntohs(headerPtr->nscount);
  183. X
  184. X    /*
  185. X     * If there are no answer, n.s. or additional records
  186. X     * then return with an error.
  187. X     */
  188. X    if (ancount == 0 && nscount == 0 && arcount == 0) {
  189. X    return (NO_INFO);
  190. X    }
  191. X
  192. X
  193. X    bp       = hostbuf;
  194. X    buflen = sizeof(hostbuf);
  195. X    cp       = (char *) &answer + sizeof(HEADER);
  196. X
  197. X    /* Skip over question section. */
  198. X    while (qdcount-- > 0) {
  199. X    cp += dn_skipname(cp, eom) + QFIXEDSZ;
  200. X    }
  201. X
  202. X    aliasPtr    = host_aliases;
  203. X    addrPtr    = addr_list;
  204. X    haveAnswer    = FALSE;
  205. X
  206. X    /*
  207. X     * Scan through the answer resource records.
  208. X     * Answers for address query types are saved.
  209. X     * Other query type answers are just printed.
  210. X     */
  211. X    if (ancount != 0) {
  212. X    if (!isServer && !headerPtr->aa) {
  213. X        printf("Non-authoritative answer:\n");
  214. X    }
  215. X
  216. X    if (queryType != T_A && !(iquery && queryType == T_PTR)) {
  217. X        while (--ancount >= 0 && cp < eom) {
  218. X        if ((cp = Print_rr(cp, (char *)&answer, eom, stdout)) == NULL) {
  219. X            return(ERROR);
  220. X        }
  221. X        }
  222. X        printedAnswers = TRUE;
  223. X    } else {
  224. X        while (--ancount >= 0 && cp < eom) {
  225. X        if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) {
  226. X            return(ERROR);
  227. X        }
  228. X        cp   += n;
  229. X        type  = GetShort(cp);
  230. X        qclass = GetShort(cp);
  231. X        cp   += sizeof(u_long);    /* skip TTL */
  232. X        dlen  = GetShort(cp);
  233. X        if (type == T_CNAME) {
  234. X            /*
  235. X             * Found an alias.
  236. X             */
  237. X            cp += dlen;
  238. X            if (aliasPtr >= &host_aliases[MAXALIASES-1]) {
  239. X            continue;
  240. X            }
  241. X            *aliasPtr++ = bp;
  242. X            n = strlen(bp) + 1;
  243. X            host_aliases_len[numAliases] = n;
  244. X            numAliases++;
  245. X            bp += n;
  246. X            buflen -= n;
  247. X            continue;
  248. X        } else if (type == T_PTR) {
  249. X            /*
  250. X             *  Found a "pointer" to the real name.
  251. X             */
  252. X            if((n=dn_expand((char *)&answer, eom, cp, bp,buflen)) < 0) {
  253. X            cp += n;
  254. X            continue;
  255. X            }
  256. X            cp += n;
  257. X            len = strlen(bp) + 1;
  258. X            hostPtr->name = calloc(1, len);
  259. X            bcopy(bp, hostPtr->name, len);
  260. X            haveAnswer = TRUE;
  261. X            break;
  262. X        } else if (type != T_A) {
  263. X            cp += dlen;
  264. X            continue;
  265. X        }
  266. X        if (haveAnswer) {
  267. X            /*
  268. X             * If we've already got 1 address, we aren't interested
  269. X             * in addresses with a different length or class.
  270. X             */
  271. X            if (dlen != hostPtr->addrLen) {
  272. X            cp += dlen;
  273. X            continue;
  274. X            }
  275. X            if (qclass != origClass) {
  276. X            cp += dlen;
  277. X            continue;
  278. X            }
  279. X        } else {
  280. X            /*
  281. X             * First address: record its length and class so we
  282. X             * only save additonal ones with the same attributes.
  283. X             */
  284. X            hostPtr->addrLen = dlen;
  285. X            origClass = qclass;
  286. X            hostPtr->addrType = (qclass == C_IN) ? AF_INET : AF_UNSPEC;
  287. X            len = strlen(bp) + 1;
  288. X            hostPtr->name = calloc(1, len);
  289. X            bcopy(bp, hostPtr->name, len);
  290. X        }
  291. X        bp += (((u_long)bp) % sizeof(align));
  292. X
  293. X        if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) {
  294. X            if (_res.options & RES_DEBUG) {
  295. X            printf("Size (%d) too big\n", dlen);
  296. X            }
  297. X            break;
  298. X        }
  299. X        bcopy(cp, *addrPtr++ = bp, dlen);
  300. X        bp +=dlen;
  301. X        cp += dlen;
  302. X        numAddresses++;
  303. X        haveAnswer = TRUE;
  304. X        }
  305. X    }
  306. X    }
  307. X
  308. X    if ((queryType == T_A || queryType == T_PTR) && haveAnswer) {
  309. X
  310. X    /*
  311. X     *  Go through the alias and address lists and return them
  312. X     *  in the hostPtr variable.
  313. X     */
  314. X
  315. X    if (numAliases > 0) {
  316. X        hostPtr->aliases = (char **) calloc(1 + numAliases, sizeof(char *));
  317. X        for (i = 0; i < numAliases; i++) {
  318. X        hostPtr->aliases[i] = calloc(1, host_aliases_len[i]);
  319. X        bcopy(host_aliases[i], hostPtr->aliases[i],host_aliases_len[i]);
  320. X        }
  321. X        hostPtr->aliases[i] = NULL;
  322. X    }
  323. X    if (numAddresses > 0) {
  324. X        hostPtr->addrList = (char **)calloc(1+numAddresses, sizeof(char *));
  325. X        for (i = 0; i < numAddresses; i++) {
  326. X        hostPtr->addrList[i] = calloc(1, hostPtr->addrLen);
  327. X        bcopy(addr_list[i], hostPtr->addrList[i], hostPtr->addrLen);
  328. X        }
  329. X        hostPtr->addrList[i] = NULL;
  330. X    }
  331. X#ifdef verbose
  332. X    if (headerPtr->aa || nscount == 0) {
  333. X        hostPtr->servers = NULL;
  334. X        return (SUCCESS);
  335. X    }
  336. X#else
  337. X    hostPtr->servers = NULL;
  338. X    return (SUCCESS);
  339. X#endif
  340. X    }
  341. X
  342. X    /*
  343. X     * At this point, for the T_A query type, only empty answers remain.
  344. X     * For other query types, additional information might be found
  345. X     * in the additional resource records part.
  346. X     */
  347. X
  348. X    if (!headerPtr->aa && (queryType != T_A) && (nscount > 0 || arcount > 0)) {
  349. X    if (printedAnswers) {
  350. X        putchar('\n');
  351. X    }
  352. X    printf("Authoritative answers can be found from:\n");
  353. X    }
  354. X
  355. X    cp = res_skip((char *) &answer, 2, eom);
  356. X
  357. X    numServers = 0;
  358. X    if (queryType != T_A) {
  359. X    /*
  360. X     * If we don't need to save the record, just print it.
  361. X     */
  362. X    while (--nscount >= 0 && cp < eom) {
  363. X        if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) {
  364. X        return(ERROR);
  365. X        }
  366. X    }
  367. X    } else {
  368. X    while (--nscount >= 0 && cp < eom) {
  369. X        /*
  370. X         *  Go through the NS records and retrieve the names of hosts
  371. X         *  that serve the requested domain.
  372. X         */
  373. X
  374. X        if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
  375. X        return(ERROR);
  376. X        }
  377. X        cp += n;
  378. X        len = strlen(bp) + 1;
  379. X        dnamePtr = calloc(1, len);   /* domain name */
  380. X        bcopy(bp, dnamePtr, len);
  381. X
  382. X        type  = GetShort(cp);
  383. X        qclass = GetShort(cp);
  384. X        cp   += sizeof(u_long);    /* skip TTL */
  385. X        dlen  = GetShort(cp);
  386. X
  387. X        if (type != T_NS) {
  388. X        cp += dlen;
  389. X        } else {
  390. X        Boolean    found;
  391. X
  392. X        if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0){
  393. X            return(ERROR);
  394. X        }
  395. X        cp += n;
  396. X        len = strlen(bp) + 1;
  397. X        namePtr = calloc(1, len); /* server host name */
  398. X        bcopy(bp, namePtr, len);
  399. X
  400. X        /*
  401. X         * Store the information keyed by the server host name.
  402. X         */
  403. X        found = FALSE;
  404. X        for (j = 0; j < numServers; j++) {
  405. X            if (strcmp(namePtr, server[j].name) == 0) {
  406. X            found = TRUE;
  407. X            free(namePtr);
  408. X            break;
  409. X            }
  410. X        }
  411. X        if (found) {
  412. X            server[j].numDomains++;
  413. X            if (server[j].numDomains <= MAXDOMAINS) {
  414. X            server[j].domain[server[j].numDomains-1] = dnamePtr;
  415. X            }
  416. X        } else {
  417. X            if (numServers >= MAXSERVERS) {
  418. X            break;
  419. X            }
  420. X            server[numServers].name = namePtr;
  421. X            server[numServers].domain[0] = dnamePtr;
  422. X            server[numServers].numDomains = 1;
  423. X            server[numServers].numAddresses = 0;
  424. X            numServers++;
  425. X        }
  426. X        }
  427. X    }
  428. X    }
  429. X
  430. X    /*
  431. X     * Additional resource records contain addresses of servers.
  432. X     */
  433. X    cp = res_skip((char *) &answer, 3, eom);
  434. X
  435. X    if (queryType != T_A) {
  436. X    /*
  437. X     * If we don't need to save the record, just print it.
  438. X     */
  439. X    while (--arcount >= 0 && cp < eom) {
  440. X        if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) {
  441. X        return(ERROR);
  442. X        }
  443. X    }
  444. X    } else {
  445. X    while (--arcount >= 0 && cp < eom) {
  446. X        if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) {
  447. X        break;
  448. X        }
  449. X        cp   += n;
  450. X        type  = GetShort(cp);
  451. X        qclass = GetShort(cp);
  452. X        cp   += sizeof(u_long);    /* skip TTL */
  453. X        dlen  = GetShort(cp);
  454. X
  455. X        if (type != T_A)  {
  456. X        cp += dlen;
  457. X        continue;
  458. X        } else {
  459. X        for (j = 0; j < numServers; j++) {
  460. X            if (strcmp(bp, server[j].name) == 0) {
  461. X            server[j].numAddresses++;
  462. X            if (server[j].numAddresses <= MAXADDRS) {
  463. X                server[j].address[server[j].numAddresses-1] = 
  464. X                                    calloc(1,dlen);
  465. X                bcopy(cp,
  466. X                  server[j].address[server[j].numAddresses-1],dlen);
  467. X                break;
  468. X            }
  469. X            }
  470. X        }
  471. X        cp += dlen;
  472. X        }
  473. X    }
  474. X    }
  475. X
  476. X    /*
  477. X     * If we are returning name server info, transfer it to the hostPtr.
  478. X     */
  479. X    if (numServers > 0) {
  480. X    hostPtr->servers = (ServerInfo **)
  481. X                calloc(numServers+1, sizeof(ServerInfo *));
  482. X
  483. X    for (i = 0; i < numServers; i++) {
  484. X        hostPtr->servers[i] = (ServerInfo *) calloc(1, sizeof(ServerInfo));
  485. X        hostPtr->servers[i]->name = server[i].name;
  486. X
  487. X
  488. X        hostPtr->servers[i]->domains = (char **)
  489. X                calloc(server[i].numDomains+1,sizeof(char *));
  490. X        for (j = 0; j < server[i].numDomains; j++) {
  491. X        hostPtr->servers[i]->domains[j] = server[i].domain[j];
  492. X        }
  493. X        hostPtr->servers[i]->domains[j] = NULL;
  494. X
  495. X
  496. X        hostPtr->servers[i]->addrList = (char **)
  497. X                calloc(server[i].numAddresses+1,sizeof(char *));
  498. X        for (j = 0; j < server[i].numAddresses; j++) {
  499. X        hostPtr->servers[i]->addrList[j] = server[i].address[j];
  500. X        }
  501. X        hostPtr->servers[i]->addrList[j] = NULL;
  502. X
  503. X    }
  504. X    hostPtr->servers[i] = NULL;
  505. X    }
  506. X
  507. X    switch (queryType) {
  508. X    case T_A:
  509. X        return NONAUTH;
  510. X    case T_PTR:
  511. X        if (iquery)
  512. X            return NO_INFO;
  513. X        /* fall through */
  514. X    default:
  515. X        return SUCCESS;
  516. X    }
  517. X}
  518. X
  519. X/*
  520. X*******************************************************************************
  521. X*
  522. X*  GetHostInfo --
  523. X*
  524. X*    Retrieves host name, address and alias information
  525. X*    for a domain.
  526. X*
  527. X*    Algorithm from res_search().
  528. X*
  529. X*  Results:
  530. X*    ERROR        - res_mkquery failed.
  531. X*    + return values from GetAnswer()
  532. X*
  533. X*******************************************************************************
  534. X*/
  535. X
  536. Xint
  537. XGetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer)
  538. X    struct in_addr    *nsAddrPtr;
  539. X    int            queryClass;
  540. X    int            queryType;
  541. X    char        *name;
  542. X    HostInfo        *hostPtr;
  543. X    Boolean        isServer;
  544. X{
  545. X    int            n;
  546. X    register int    result;
  547. X    register char    *cp, **domain;
  548. X    extern char        *hostalias();
  549. X    Boolean        got_nodata = FALSE;
  550. X    unsigned long    ina;
  551. X
  552. X    /* Catch explicit addresses */
  553. X    if ((queryType == T_A) && IsAddr(name, &ina)) {
  554. X    hostPtr->name = calloc(strlen(name)+3, 1);
  555. X    (void)sprintf(hostPtr->name,"[%s]",name);
  556. X    hostPtr->aliases = NULL;
  557. X    hostPtr->servers = NULL;
  558. X    hostPtr->addrType = AF_INET;
  559. X    hostPtr->addrLen = sizeof(struct in_addr);
  560. X    hostPtr->addrList = (char **)calloc(2, sizeof(char *));
  561. X    hostPtr->addrList[0] = calloc(sizeof(long), sizeof(char));
  562. X    bcopy((char *)&ina, hostPtr->addrList[0], sizeof(ina));
  563. X    hostPtr->addrList[1] = NULL;
  564. X    return(SUCCESS);
  565. X    }
  566. X
  567. X    result = NXDOMAIN;
  568. X    for (cp = name, n = 0; *cp; cp++)
  569. X        if (*cp == '.')
  570. X            n++;
  571. X    if (n == 0 && (cp = hostalias(name))) {
  572. X        printf("Aliased to \"%s\"\n\n", cp);
  573. X        return (GetHostDomain(nsAddrPtr, queryClass, queryType,
  574. X            cp, (char *)NULL, hostPtr, isServer));
  575. X    }
  576. X    /*
  577. X     * We do at least one level of search if
  578. X     *    - there is no dot and RES_DEFNAME is set, or
  579. X     *    - there is at least one dot, there is no trailing dot,
  580. X     *      and RES_DNSRCH is set.
  581. X     */
  582. X    if ((n == 0 && _res.options & RES_DEFNAMES) ||
  583. X       (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
  584. X     for (domain = _res.dnsrch; *domain; domain++) {
  585. X        result = GetHostDomain(nsAddrPtr, queryClass, queryType,
  586. X            name, *domain, hostPtr, isServer);
  587. X        /*
  588. X         * If no server present, give up.
  589. X         * If name isn't found in this domain,
  590. X         * keep trying higher domains in the search list
  591. X         * (if that's enabled).
  592. X         * On a NO_INFO error, keep trying, otherwise
  593. X         * a wildcard entry of another type could keep us
  594. X         * from finding this entry higher in the domain.
  595. X         * If we get some other error (negative answer or
  596. X         * server failure), then stop searching up,
  597. X         * but try the input name below in case it's fully-qualified.
  598. X         */
  599. X        if (result == SUCCESS || result == NO_RESPONSE)
  600. X            return result;
  601. X        if (result == NO_INFO)
  602. X            got_nodata++;
  603. X        if ((result != NXDOMAIN && result != NO_INFO) ||
  604. X        (_res.options & RES_DNSRCH) == 0)
  605. X            break;
  606. X    }
  607. X    /*
  608. X     * If the search/default failed, try the name as fully-qualified,
  609. X     * but only if it contained at least one dot (even trailing).
  610. X     * This is purely a heuristic; we assume that any reasonable query
  611. X     * about a top-level domain (for servers, SOA, etc) will not use
  612. X     * res_search.
  613. X     */
  614. X    if (n && (result = GetHostDomain(nsAddrPtr, queryClass, queryType,
  615. X            name, (char *)NULL, hostPtr, isServer)) == SUCCESS)
  616. X        return result;
  617. X    if (got_nodata)
  618. X    result = NO_INFO;
  619. X    return (result);
  620. X}
  621. X
  622. X/*
  623. X * Perform a query on the concatenation of name and domain,
  624. X * removing a trailing dot from name if domain is NULL.
  625. X */
  626. XGetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer)
  627. X    struct in_addr    *nsAddrPtr;
  628. X    int            queryClass;
  629. X    int            queryType;
  630. X    char        *name, *domain;
  631. X    HostInfo        *hostPtr;
  632. X    Boolean        isServer;
  633. X{
  634. X    querybuf buf;
  635. X    char nbuf[2*MAXDNAME+2];
  636. X    char *longname = nbuf;
  637. X    int n;
  638. X
  639. X    if (domain == NULL) {
  640. X        /*
  641. X         * Check for trailing '.';
  642. X         * copy without '.' if present.
  643. X         */
  644. X        n = strlen(name) - 1;
  645. X        if (name[n] == '.' && n < sizeof(nbuf) - 1) {
  646. X            bcopy(name, nbuf, n);
  647. X            nbuf[n] = '\0';
  648. X        } else
  649. X            longname = name;
  650. X    } else {
  651. X        (void)sprintf(nbuf, "%.*s.%.*s",
  652. X            MAXDNAME, name, MAXDNAME, domain);
  653. X        longname = nbuf;
  654. X    }
  655. X    n = res_mkquery(QUERY, longname, queryClass, queryType,
  656. X            (char *)0, 0, (char *)0, (char *) &buf, sizeof(buf));
  657. X    if (n < 0) {
  658. X    if (_res.options & RES_DEBUG) {
  659. X        printf("Res_mkquery failed\n");
  660. X    }
  661. X    return (ERROR);
  662. X    }
  663. X
  664. X    n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, isServer);
  665. X
  666. X    /*
  667. X     * GetAnswer didn't find a name, so set it to the specified one.
  668. X     */
  669. X    if (n == NONAUTH) {
  670. X    if (hostPtr->name == NULL) {
  671. X        int len = strlen(longname) + 1;
  672. X        hostPtr->name = calloc(len, sizeof(char));
  673. X        bcopy(longname, hostPtr->name, len);
  674. X    }
  675. X    }
  676. X    return(n);
  677. X}
  678. X
  679. X
  680. X/*
  681. X*******************************************************************************
  682. X*
  683. X*  GetHostInfoByAddr --
  684. X*
  685. X*    Performs an inverse query to find the host name
  686. X*    that corresponds to the given address.
  687. X*
  688. X*  Results:
  689. X*    ERROR        - res_mkquery failed.
  690. X*    + return values from GetAnswer()
  691. X*
  692. X*******************************************************************************
  693. X*/
  694. X
  695. Xint
  696. XGetHostInfoByAddr(nsAddrPtr, address, hostPtr)
  697. X    struct in_addr    *nsAddrPtr;
  698. X    struct in_addr    *address;
  699. X    HostInfo        *hostPtr;
  700. X{
  701. X    int        n;
  702. X    querybuf    buf;
  703. X    char    qbuf[MAXDNAME];
  704. X    char    *p = (char *) &address->s_addr;
  705. X
  706. X    (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
  707. X        ((unsigned)p[3] & 0xff),
  708. X        ((unsigned)p[2] & 0xff),
  709. X        ((unsigned)p[1] & 0xff),
  710. X        ((unsigned)p[0] & 0xff));
  711. X    n = res_mkquery(QUERY, qbuf, C_IN, T_PTR,
  712. X        NULL,  0, NULL, (char *) &buf, sizeof(buf));
  713. X    if (n < 0) {
  714. X    if (_res.options & RES_DEBUG) {
  715. X        printf("res_mkquery() failed\n");
  716. X    }
  717. X    return (ERROR);
  718. X    }
  719. X    n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1);
  720. X    if (n == SUCCESS) {
  721. X    hostPtr->addrType = AF_INET;
  722. X    hostPtr->addrLen = 4;
  723. X    hostPtr->addrList = (char **)calloc(2, sizeof(char *));
  724. X    hostPtr->addrList[0] = calloc(sizeof(long), sizeof(char));
  725. X    bcopy((char *)p, hostPtr->addrList[0], sizeof(struct in_addr));
  726. X    hostPtr->addrList[1] = NULL;
  727. X    }
  728. X    return n;
  729. X}
  730. X
  731. X/*
  732. X*******************************************************************************
  733. X*
  734. X*  FreeHostInfoPtr --
  735. X*
  736. X*    Deallocates all the calloc'd areas for a HostInfo variable.
  737. X*
  738. X*******************************************************************************
  739. X*/
  740. X
  741. Xvoid
  742. XFreeHostInfoPtr(hostPtr)
  743. X    register HostInfo *hostPtr;
  744. X{
  745. X    int i, j;
  746. X
  747. X    if (hostPtr->name != NULL) {
  748. X    free(hostPtr->name);
  749. X    hostPtr->name = NULL;
  750. X    }
  751. X
  752. X    if (hostPtr->aliases != NULL) {
  753. X    i = 0;
  754. X    while (hostPtr->aliases[i] != NULL) {
  755. X        free(hostPtr->aliases[i]);
  756. X        i++;
  757. X    }
  758. X    free((char *)hostPtr->aliases);
  759. X    hostPtr->aliases = NULL;
  760. X    }
  761. X
  762. X    if (hostPtr->addrList != NULL) {
  763. X    i = 0;
  764. X    while (hostPtr->addrList[i] != NULL) {
  765. X        free(hostPtr->addrList[i]);
  766. X        i++;
  767. X    }
  768. X    free((char *)hostPtr->addrList);
  769. X    hostPtr->addrList = NULL;
  770. X    }
  771. X
  772. X    if (hostPtr->servers != NULL) {
  773. X    i = 0;
  774. X    while (hostPtr->servers[i] != NULL) {
  775. X
  776. X        if (hostPtr->servers[i]->name != NULL) {
  777. X        free(hostPtr->servers[i]->name);
  778. X        }
  779. X
  780. X        if (hostPtr->servers[i]->domains != NULL) {
  781. X        j = 0;
  782. X        while (hostPtr->servers[i]->domains[j] != NULL) {
  783. X            free(hostPtr->servers[i]->domains[j]);
  784. X            j++;
  785. X        }
  786. X        free((char *)hostPtr->servers[i]->domains);
  787. X        }
  788. X
  789. X        if (hostPtr->servers[i]->addrList != NULL) {
  790. X        j = 0;
  791. X        while (hostPtr->servers[i]->addrList[j] != NULL) {
  792. X            free(hostPtr->servers[i]->addrList[j]);
  793. X            j++;
  794. X        }
  795. X        free((char *)hostPtr->servers[i]->addrList);
  796. X        }
  797. X        free((char *)hostPtr->servers[i]);
  798. X        i++;
  799. X    }
  800. X    free((char *)hostPtr->servers);
  801. X    hostPtr->servers = NULL;
  802. X    }
  803. X}
  804. END_OF_FILE
  805. if test 20155 -ne `wc -c <'getinfo.c'`; then
  806.     echo shar: \"'getinfo.c'\" unpacked with wrong size!
  807. fi
  808. # end of 'getinfo.c'
  809. fi
  810. if test -f 'hash.c' -a "${1}" != "-c" ; then 
  811.   echo shar: Will not clobber existing file \"'hash.c'\"
  812. else
  813. echo shar: Extracting \"'hash.c'\" \(11587 characters\)
  814. sed "s/^X//" >'hash.c' <<'END_OF_FILE'
  815. X#include <stdio.h>
  816. X
  817. X/*
  818. X**
  819. X**    Copyright (c) 1987, Robert L. McQueer
  820. X**        All Rights Reserved
  821. X**
  822. X** Permission granted for use, modification and redistribution of this
  823. X** software provided that no use is made for commercial gain without the
  824. X** written consent of the author, that all copyright notices remain intact,
  825. X** and that all changes are clearly documented.  No warranty of any kind
  826. X** concerning any use which may be made of this software is offered or implied.
  827. X**
  828. X*/
  829. X
  830. X/*
  831. X** generic hash table routines.
  832. X**
  833. X**    htab_init - initialize a new hash table
  834. X**    htab_free - destroy a hash table, freeing associated memory
  835. X**    htab_clear - remove all hash table entries
  836. X**    htab_find - find entry
  837. X**    htab_del - delete entry
  838. X**    htab_enter - enter item into table
  839. X**    htab_list - scan hash table entries.
  840. X**
  841. X** Multiple hash tables may be used.  Caller may provide key comparison
  842. X** and hash routines, or use defaults.
  843. X*/
  844. X
  845. X/*
  846. X** HASHMAGIC define may be used to compile a version of these routines
  847. X** which will catch bad context blocks passed in by client routines
  848. X** through a magic number check.  If defined, HASHMAGIC should be the
  849. X** actual number to use for a magic number.  Configurable so that you
  850. X** may avoid the overhead of checking it all the time in these routines
  851. X** which may have high entry rates.
  852. X*/
  853. X
  854. X/*
  855. X** allocation: nodes are allocated starting with a block of ALLOCINIT,
  856. X** doubling the size for the next allocation as long as the size is strictly
  857. X** less than ALLOCLIMIT.  If you make ALLOCLIMIT a value encountered by
  858. X** successive doubling of ALLOCINIT, that will be the final size, otherwise the
  859. X** next doubling larger.
  860. X**
  861. X** The idea of this stunt is that we don't know whether the caller is going
  862. X** to make a lot of entries, or just a few.  So we start out allocating
  863. X** just a few nodes at a crack, and as the caller makes more and more
  864. X** entries, allocate bigger bunches.  For memory-restrictive environments
  865. X** like MS-DOS, one could set ALLOCLIMIT low & simply pay the penalty for
  866. X** lots of malloc calls.
  867. X*/
  868. X#define ALLOCINIT 25
  869. X#define ALLOCLIMIT 800
  870. X
  871. X#define MAGCHECK(T,N) if (T->magic != HASHMAGIC) fatal(Merr,N)
  872. X
  873. Xtypedef struct _htab
  874. X{
  875. X    struct _htab *next;
  876. X    char *key;
  877. X    char *data;
  878. X} HASHTAB;
  879. X
  880. Xtypedef struct _faddr
  881. X{
  882. X    struct _faddr *next;
  883. X} FADDR;
  884. X
  885. X/*
  886. X** fpool, tpool - tpool is the pool of available nodes.  Every time
  887. X** a new block is allocated, one FADDR is allocated along with it.
  888. X** The address allocated is coerced into the FADDR and placed on fpool
  889. X** to facilitate freeing.
  890. X*/
  891. X
  892. Xtypedef struct
  893. X{
  894. X#ifdef HASHMAGIC
  895. X    int magic;
  896. X#endif
  897. X    HASHTAB **tab;        /* hash table */
  898. X    HASHTAB *tpool;        /* available nodes */
  899. X    HASHTAB *srch;        /* current search pointer for htab_list */
  900. X    FADDR *fpool;        /* alloc pointers for htab_free */
  901. X    int (*afail)();        /* allocation error handler */
  902. X    int (*compare)();    /* comparison routine */
  903. X    int (*hashfunc)();    /* hash function */
  904. X    int size;        /* size of table (length of tab item) */
  905. X    int ablock;        /* current allocation block size */
  906. X    int srchidx;        /* current table index for htab_list */
  907. X} CONTEXT;
  908. X#ifdef __STDC__
  909. X#include <stdlib.h>
  910. X#else
  911. Xextern char *malloc();
  912. X#endif
  913. Xstatic HASHTAB * get_node(CONTEXT *);
  914. Xstatic int hash(register char *,int);
  915. Xstatic int def_afail();
  916. X
  917. X#ifdef HASHMAGIC
  918. Xstatic char *Merr = "Bad magic number in hash table context block, %s()";
  919. X#endif
  920. X
  921. X/*
  922. X** free hash table.  tab is pointer returned by htab_init.
  923. X*/
  924. Xhtab_free(void *tab)
  925. X{
  926. X    register FADDR *ptr, *next;
  927. X    int i;
  928. X    register CONTEXT *cb;
  929. X
  930. X    cb = (CONTEXT *) tab;
  931. X
  932. X#ifdef HASHMAGIC
  933. X    MAGCHECK(cb,"htab_free");
  934. X    ++(cb->magic);
  935. X#endif
  936. X
  937. X    for (ptr = cb->fpool; ptr != NULL; ptr = next)
  938. X    {
  939. X        next = ptr->next;
  940. X        free ((char *) ptr);
  941. X    }
  942. X
  943. X    free (tab);
  944. X}
  945. X
  946. X/*
  947. X** remove all hash table entries.  Does not free memory, simply restores
  948. X** empty table, as if one had called htab_delete on all the keys.  tab is
  949. X** pointer returned by htab_init.
  950. X*/
  951. Xhtab_clear(void *tab)
  952. X{
  953. X    register CONTEXT *cb;
  954. X    register HASHTAB **tptr;
  955. X    register HASHTAB *nptr;
  956. X    int i;
  957. X
  958. X    cb = (CONTEXT *) tab;
  959. X
  960. X#ifdef HASHMAGIC
  961. X    MAGCHECK(cb,"htab_clear");
  962. X#endif
  963. X
  964. X    tptr = cb->tab;
  965. X
  966. X    for (i=0; i < cb->size; ++i,++tptr)
  967. X    {
  968. X        nptr = *tptr;
  969. X        if (nptr == NULL)
  970. X            continue;
  971. X        while (nptr->next != NULL)
  972. X            nptr = nptr->next;
  973. X        nptr->next = cb->tpool;
  974. X        cb->tpool = *tptr;
  975. X        *tptr = NULL;
  976. X    }
  977. X
  978. X    /* force any open htab_list's to return empty */
  979. X    cb->srch = NULL;
  980. X    cb->srchidx = cb->size;
  981. X}
  982. X
  983. X/*
  984. X** initialize a hash table.  Returns a pointer to be used with other
  985. X** calls, NULL for failure.
  986. X**
  987. X** The hash table will be maintained as a linked list for each node,
  988. X** so any number of entries can be made to it, whatever the value for
  989. X** size (>100% density is perfectly OK).
  990. X**
  991. X**    size - size of table.  If hfunc is NULL, will be incremented
  992. X**        up to a prime size to suit the type of hash function
  993. X**        used by default.  Caller may find out the actual size
  994. X**        by calling next_prime().
  995. X**
  996. X**    allocfail - routine to call in case of memory allocation failure.
  997. X**        If NULL, allocation failure will make a call to fatal().
  998. X**
  999. X**    comp - routine used to compare keys.  returns 0 if equal, non-zero
  1000. X**        otherwise.  If NULL, strcmp() will be used.  Your own will
  1001. X**        have to be provided if your keys are something other than
  1002. X**        strings.  These routines will always call this with the
  1003. X**        comparison key as the first argument, and the one in the
  1004. X**        table already as a second argument.  This fact is most
  1005. X**        useful for making comparisons up to the length of the entered
  1006. X**        key, for instance.
  1007. X**
  1008. X**    hfunc - hash function.  called as (*hfunc)(key, size).  size argument
  1009. X**        may be ignored if function was written for a specific size.
  1010. X**        Must return an integer between 0 and size-1.  If NULL, the
  1011. X**        default hash function is the typical "string-divided-modulo
  1012. X**        -table-size" algorithm.
  1013. X*/
  1014. Xvoid *
  1015. Xhtab_init(size,allocfail,comp,hfunc)
  1016. Xint size;
  1017. Xint (*allocfail)();
  1018. Xint (*comp)();
  1019. Xint (*hfunc)();
  1020. X{
  1021. X    int def_afail();
  1022. X    int strcmp();
  1023. X    int i;
  1024. X    CONTEXT *cb;
  1025. X
  1026. X    if (allocfail == NULL)
  1027. X        allocfail = def_afail;
  1028. X
  1029. X    if (comp == NULL)
  1030. X        comp = strcmp;
  1031. X
  1032. X    if (hfunc == NULL)
  1033. X    {
  1034. X        size = next_prime(size);
  1035. X        hfunc = hash;
  1036. X    }
  1037. X
  1038. X    i = sizeof(CONTEXT) + size * sizeof(HASHTAB *);
  1039. X
  1040. X    if ((cb = (CONTEXT *) malloc(i)) == NULL)
  1041. X    {
  1042. X        (*allocfail)();
  1043. X        return (NULL);
  1044. X    }
  1045. X
  1046. X#ifdef HASHMAGIC
  1047. X    cb->magic = HASHMAGIC;
  1048. X#endif
  1049. X
  1050. X    cb->afail = allocfail;
  1051. X    cb->compare = comp;
  1052. X    cb->hashfunc = hfunc;
  1053. X    cb->size = size;
  1054. X    cb->tab = (HASHTAB **)(cb+1);
  1055. X
  1056. X    for (i=0; i < cb->size; ++i)
  1057. X        (cb->tab)[i] = NULL;
  1058. X    cb->tpool = NULL;
  1059. X    cb->fpool = NULL;
  1060. X    cb->ablock = ALLOCINIT;
  1061. X
  1062. X    /* safety, in case somebody calls htab_list wrong */
  1063. X    cb->srch = NULL;
  1064. X    cb->srchidx = size;
  1065. X
  1066. X    return ((char *) cb);
  1067. X}
  1068. X
  1069. X
  1070. X/*
  1071. X** find an entry in hash table.  The pointer returned is NULL for
  1072. X** failure, or the data pointer associated with the key in htab_enter.
  1073. X**
  1074. X**    tab - table pointer returned by htab_init.
  1075. X**    s - search key.
  1076. X*/
  1077. Xchar *
  1078. Xhtab_find(void *tab,void *s)
  1079. X{
  1080. X    register HASHTAB *ptr;
  1081. X    register CONTEXT *cb;
  1082. X
  1083. X    cb = (CONTEXT *) tab;
  1084. X
  1085. X#ifdef HASHMAGIC
  1086. X    MAGCHECK(cb,"htab_find");
  1087. X#endif
  1088. X
  1089. X    for (ptr = (cb->tab)[(*(cb->hashfunc))(s,cb->size)];
  1090. X                    ptr != NULL; ptr = ptr->next)
  1091. X    {
  1092. X        if ((*(cb->compare))(s,ptr->key) == 0)
  1093. X            return (ptr->data);
  1094. X    }
  1095. X
  1096. X    return (NULL);
  1097. X}
  1098. X
  1099. X/*
  1100. X** delete a hash table entry.  Returns 0 for success, <0 for no entry.
  1101. X**
  1102. X**    tab - table pointer returned by htab_init.
  1103. X**    s - search key.
  1104. X*/
  1105. Xhtab_del(void *tab,void *s)
  1106. X{
  1107. X    register HASHTAB *ptr;
  1108. X    register CONTEXT *cb;
  1109. X    register HASHTAB *pred;
  1110. X    int idx;
  1111. X
  1112. X    cb = (CONTEXT *) tab;
  1113. X
  1114. X#ifdef HASHMAGIC
  1115. X    MAGCHECK(cb,"htab_del");
  1116. X#endif
  1117. X
  1118. X    pred = NULL;
  1119. X    for (ptr = (cb->tab)[idx = (*(cb->hashfunc))(s,cb->size)];
  1120. X                        ptr != NULL; ptr = ptr->next)
  1121. X    {
  1122. X        if ((*(cb->compare))(s,ptr->key) == 0)
  1123. X            break;
  1124. X        pred = ptr;
  1125. X    }
  1126. X
  1127. X    if (ptr == NULL)
  1128. X        return (-1);
  1129. X
  1130. X    /*
  1131. X    ** if we're deleting the current search index in the middle
  1132. X    ** of an htab_list, go to next item.
  1133. X    */
  1134. X    if (ptr == cb->srch)
  1135. X        cb->srch = ptr->next;
  1136. X
  1137. X    if (pred == NULL)
  1138. X        (cb->tab)[idx] = ptr->next;
  1139. X    else
  1140. X        pred->next = ptr->next;
  1141. X    ptr->next = cb->tpool;
  1142. X    cb->tpool = ptr;
  1143. X
  1144. X    return (0);
  1145. X}
  1146. X
  1147. X/*
  1148. X** enter new item into hash table:
  1149. X**
  1150. X**    tab - table pointer from htab_init.
  1151. X**    s - key.
  1152. X**    data - data to associate with key.  In most cases, will probably
  1153. X**        actually be a pointer to some sort of structure known
  1154. X**        to the caller.
  1155. X**
  1156. X**    both s and data should point to storage valid for the entire life of
  1157. X**    the table.  htab_enter can not allocate copies of either of these
  1158. X**    things since it does not know their structure (if you provided 
  1159. X**    comparison & hash routines, the key may not actually be a string).
  1160. X**    htab_enter WILL allocate actual table nodes.  Returns 0 for success,
  1161. X**    -1 for failure.  Failure return is possible only if allocation
  1162. X**    failure occurs, and was not set up as fatal in htab_init().
  1163. X*/
  1164. Xhtab_enter(void *tab,void *s,void *data)
  1165. X{
  1166. X    register HASHTAB *ptr;
  1167. X    register CONTEXT *cb;
  1168. X    int i;
  1169. X
  1170. X    cb = (CONTEXT *) tab;
  1171. X
  1172. X#ifdef HASHMAGIC
  1173. X    MAGCHECK(cb,"htab_enter");
  1174. X#endif
  1175. X
  1176. X    if ((ptr = get_node(cb)) == NULL)
  1177. X        return (-1);
  1178. X
  1179. X    ptr->next = (cb->tab)[i = (*(cb->hashfunc))(s,cb->size)];
  1180. X    (cb->tab)[i] = ptr;
  1181. X    ptr->key = s;
  1182. X    ptr->data = data;
  1183. X    return (0);
  1184. X}
  1185. X
  1186. X/*
  1187. X** Routine to scan all hash table entries through successive calls.
  1188. X** Returns 1 if an entry found, 0 for no more entries.  Will not
  1189. X** be returned in any particular order comprehensible to the
  1190. X** calling program (hash table order).
  1191. X**
  1192. X**    tab - table pointer from htab_init
  1193. X**    first - 1 to start scan, 0 on succesive calls.
  1194. X**    data, key - returned data and key.
  1195. X**
  1196. X** Precautions have been taken to allow interleave of this routine with
  1197. X** htab_del and htab_clear, but the only interleave that truly makes
  1198. X** sense is to selectively htab_del() entries on some basis as they
  1199. X** come back from htab_list().  htab_enter()'s in mid list scan may be
  1200. X** done, but they may or may not show up on following calls, dependent
  1201. X** on where they were entered in relation to the current list pointer.
  1202. X**
  1203. X** This routine sets a global variable on all successful calls:
  1204. X**
  1205. X**    int Htab_Index; hash table index entry was found at.
  1206. X**
  1207. X** By examining this while scanning the list of entries, a caller may
  1208. X** obtain statistics on table distribution.  The value will increase
  1209. X** monotonically as the search proceeds, skipping across indices
  1210. X** with no entries.
  1211. X*/
  1212. X
  1213. Xint Htab_Index;
  1214. X
  1215. Xhtab_list(void *tab,int first,void **data,void **key)
  1216. X{
  1217. X    register CONTEXT *cb;
  1218. X
  1219. X    cb = (CONTEXT *) tab;
  1220. X
  1221. X#ifdef HASHMAGIC
  1222. X    MAGCHECK(cb,"htab_list");
  1223. X#endif
  1224. X
  1225. X    if (first)
  1226. X    {
  1227. X        cb->srch = NULL;
  1228. X        cb->srchidx = -1;
  1229. X    }
  1230. X
  1231. X    while (cb->srch == NULL)
  1232. X    {
  1233. X        ++(cb->srchidx);
  1234. X        if (cb->srchidx >= cb->size)
  1235. X            return (0);
  1236. X        cb->srch = (cb->tab)[cb->srchidx];
  1237. X    }
  1238. X
  1239. X    Htab_Index = cb->srchidx;
  1240. X
  1241. X    *data = (cb->srch)->data;
  1242. X    *key = (cb->srch)->key;
  1243. X
  1244. X    cb->srch = (cb->srch)->next;
  1245. X    return(1);
  1246. X}
  1247. X
  1248. Xstatic HASHTAB *
  1249. Xget_node(CONTEXT *cb)
  1250. X{
  1251. X    char *addr;
  1252. X    HASHTAB *ptr;
  1253. X    int i;
  1254. X
  1255. X    if (cb->tpool == NULL)
  1256. X    {
  1257. X        addr = malloc((cb->ablock)*sizeof(HASHTAB)+sizeof(FADDR));
  1258. X        if (addr == NULL)
  1259. X        {
  1260. X            (*(cb->afail))();
  1261. X            return (NULL);
  1262. X        }
  1263. X
  1264. X        ((FADDR *) addr)->next = cb->fpool;
  1265. X        cb->fpool = (FADDR *) addr;
  1266. X        addr += sizeof(FADDR);
  1267. X        cb->tpool = (HASHTAB *) addr;
  1268. X        for (i=1; i < cb->ablock; ++i)
  1269. X            (cb->tpool)[i-1].next = cb->tpool + i;
  1270. X        (cb->tpool)[i-1].next = NULL;
  1271. X
  1272. X        if (cb->ablock < ALLOCLIMIT)
  1273. X            cb->ablock *= 2;
  1274. X    }
  1275. X
  1276. X    ptr = cb->tpool;
  1277. X    cb->tpool = (cb->tpool)->next;
  1278. X    return (ptr);
  1279. X}
  1280. X
  1281. Xstatic int
  1282. Xhash(register char *s,int size)
  1283. X{
  1284. X    register long rem;
  1285. X
  1286. X    for (rem = 0; *s != '\0'; ++s)
  1287. X        rem = (rem * 128 + *s) % size;
  1288. X    return(rem);
  1289. X}
  1290. X
  1291. Xstatic int
  1292. Xdef_afail()
  1293. X{
  1294. X    fprintf(stderr,"Memory allocation failure in hash table routines\n");
  1295. X    exit(1);
  1296. X}
  1297. END_OF_FILE
  1298. if test 11587 -ne `wc -c <'hash.c'`; then
  1299.     echo shar: \"'hash.c'\" unpacked with wrong size!
  1300. fi
  1301. # end of 'hash.c'
  1302. fi
  1303. if test -f 'main.c' -a "${1}" != "-c" ; then 
  1304.   echo shar: Will not clobber existing file \"'main.c'\"
  1305. else
  1306. echo shar: Extracting \"'main.c'\" \(17249 characters\)
  1307. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  1308. X#ifndef lint
  1309. Xchar copyright[] =
  1310. X"@(#) Portions Copyright (c) 1985,1989\n\
  1311. XRegents of the University of California.\n\
  1312. X All rights reserved.\n";
  1313. X#endif /* not lint */
  1314. X
  1315. X/*
  1316. X *******************************************************************************
  1317. X *  
  1318. X *   main.c --
  1319. X *  
  1320. X *    Main routine and some action routines for the name server
  1321. X *    lookup program.
  1322. X *
  1323. X *    Andrew Cherenson
  1324. X *    U.C. Berkeley Computer Science Div.
  1325. X *    CS298-26, Fall 1985
  1326. X *  
  1327. X *******************************************************************************
  1328. X */
  1329. X
  1330. X#include <sys/types.h>
  1331. X#include <sys/param.h>
  1332. X#include <netdb.h>
  1333. X#include <sys/socket.h>
  1334. X#include <netinet/in.h>
  1335. X#include <stdio.h>
  1336. X#include <arpa/nameser.h>
  1337. X#include <arpa/inet.h>
  1338. X#include <resolv.h>
  1339. X#include <signal.h>
  1340. X#include <setjmp.h>
  1341. X#include <ctype.h>
  1342. X#include <stdlib.h>
  1343. X#include <string.h>
  1344. X#include "res.h"
  1345. X
  1346. X#ifdef ultrix
  1347. X#define nsaddr_list(i)  ns_list[(i)].addr
  1348. X#else
  1349. X#define nsaddr_list(i)  nsaddr_list[(i)]
  1350. X#endif
  1351. X/*
  1352. X *  Default Internet address of the current host.
  1353. X */
  1354. X
  1355. X#if BSD < 43
  1356. X#define LOCALHOST "127.0.0.1"
  1357. X#endif
  1358. X
  1359. X
  1360. X/*
  1361. X * Name of a top-level name server. Can be changed with 
  1362. X * the "set root" command.
  1363. X */
  1364. X
  1365. X#ifndef ROOT_SERVER
  1366. X#define        ROOT_SERVER "ns.nic.ddn.mil."
  1367. X#endif
  1368. Xchar        rootServerName[NAME_LEN] = ROOT_SERVER;
  1369. X
  1370. X
  1371. X/*
  1372. X *  Import the state information from the resolver library.
  1373. X */
  1374. X
  1375. Xextern struct state _res;
  1376. X
  1377. X
  1378. X/*
  1379. X *  Info about the most recently queried host.
  1380. X */
  1381. X
  1382. XHostInfo    curHostInfo;
  1383. X
  1384. X
  1385. X/*
  1386. X *  Info about the default name server.
  1387. X */
  1388. X
  1389. XHostInfo    *defaultPtr = NULL;
  1390. Xchar        defaultServer[NAME_LEN];
  1391. Xstruct in_addr    defaultAddr;
  1392. X
  1393. Xint hasprinted = 0;
  1394. Xint hasloaded = 0;
  1395. Xint explicitserver = 0;
  1396. Xchar *vdomain;
  1397. X/*
  1398. X *  Initial name server query type is Address.
  1399. X */
  1400. X
  1401. Xint        queryType = T_ANY;
  1402. Xint        queryClass = C_IN;
  1403. X
  1404. X/*
  1405. X * Stuff for Interrupt (control-C) signal handler.
  1406. X */
  1407. X
  1408. XFILE        *filePtr = stdout;
  1409. X
  1410. Xstatic void CvtAddrToPtr();
  1411. X
  1412. X
  1413. X/*
  1414. X *******************************************************************************
  1415. X *
  1416. X *  main --
  1417. X *
  1418. X *    Initializes the resolver library and determines the address
  1419. X *    of the initial name server.
  1420. X *
  1421. X *******************************************************************************
  1422. X */
  1423. X
  1424. Xmain(argc, argv)
  1425. X    int        argc;
  1426. X    char    **argv;
  1427. X{
  1428. X    char    *wantedHost = NULL;
  1429. X    int        result;
  1430. X    int        i;
  1431. X    extern int    h_errno;
  1432. X
  1433. X    /*
  1434. X     *  Initialize the resolver library routines.
  1435. X     */
  1436. X
  1437. X    if (res_init() == -1) {
  1438. X    fprintf(stderr,"*** Can't initialize resolver.\n");
  1439. X    exit(1);
  1440. X    }
  1441. X
  1442. X    /*
  1443. X     *  Allocate space for the default server's host info and
  1444. X     *  find the server's address and name. If the resolver library
  1445. X     *  already has some addresses for a potential name server,
  1446. X     *  then use them. Otherwise, see if the current host has a server.
  1447. X     *  Command line arguments may override the choice of initial server. 
  1448. X     */
  1449. X
  1450. X    defaultPtr = (HostInfo *) calloc(1, sizeof(HostInfo));
  1451. X
  1452. X    ++argv; --argc;        /* skip prog name */
  1453. X
  1454. X
  1455. X    if (_res.nscount == 0) {
  1456. X    LocalServer(defaultPtr);
  1457. X    } else {
  1458. X    for (i = 0; i < _res.nscount; i++) {
  1459. X        if (_res.nsaddr_list(i).sin_addr.s_addr == INADDR_ANY) {
  1460. X            LocalServer(defaultPtr);
  1461. X        break;
  1462. X        } else {
  1463. X        result = GetHostInfoByAddr(&(_res.nsaddr_list(i).sin_addr), 
  1464. X                    &(_res.nsaddr_list(i).sin_addr), 
  1465. X                    defaultPtr);
  1466. X        if (result != SUCCESS) {
  1467. X            fprintf(stderr,
  1468. X            "*** Can't find server name for address %s: %s\n", 
  1469. X               inet_ntoa(_res.nsaddr_list(i).sin_addr), 
  1470. X               DecodeError(result));
  1471. X        } else {
  1472. X            defaultAddr = _res.nsaddr_list(i).sin_addr;
  1473. X            break;
  1474. X        }
  1475. X        }
  1476. X    }
  1477. X
  1478. X    /*
  1479. X     *  If we have exhausted the list, tell the user about the
  1480. X     *  command line argument to specify an address.
  1481. X     */
  1482. X
  1483. X    if (i == _res.nscount) {
  1484. X        fprintf(stderr, "*** Default servers are not available\n");
  1485. X        exit(1);
  1486. X    }
  1487. X
  1488. X    }
  1489. X    strcpy(defaultServer, defaultPtr->name);
  1490. X
  1491. X
  1492. X#ifdef DEBUG
  1493. X#ifdef DEBUG2
  1494. X    _res.options |= RES_DEBUG2;
  1495. X#endif
  1496. X    _res.options |= RES_DEBUG;
  1497. X    _res.retry    = 2;
  1498. X#endif
  1499. X    
  1500. X    (void)InitTables();
  1501. X    vdomain = _res.defdname;
  1502. X
  1503. X    while (argc)
  1504. X    {
  1505. X    (void) DoCommand (*argv);
  1506. X    ++argv; --argc;
  1507. X    }
  1508. X    if(!hasprinted)
  1509. X    DoCommand("print");
  1510. X
  1511. X    exit(0);
  1512. X}
  1513. X
  1514. X
  1515. XLocalServer(defaultPtr)
  1516. X    HostInfo *defaultPtr;
  1517. X{
  1518. X    char    hostName[NAME_LEN];
  1519. X#if BSD < 43
  1520. X    int        result;
  1521. X#endif
  1522. X
  1523. X    gethostname(hostName, sizeof(hostName));
  1524. X
  1525. X#if BSD < 43
  1526. X    defaultAddr.s_addr = inet_addr(LOCALHOST);
  1527. X    result = GetHostInfoByName(&defaultAddr, C_IN, T_A, 
  1528. X        hostName, defaultPtr, 1);
  1529. X    if (result != SUCCESS) {
  1530. X    fprintf(stderr,
  1531. X    "*** Can't find initialize address for server %s: %s\n",
  1532. X            defaultServer, DecodeError(result));
  1533. X    exit(1);
  1534. X    }
  1535. X#else
  1536. X    defaultAddr.s_addr = htonl(INADDR_ANY);
  1537. X    (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, "0.0.0.0", defaultPtr, 1);
  1538. X    free(defaultPtr->name);
  1539. X    defaultPtr->name = calloc(1, sizeof(hostName)+1);
  1540. X    strcpy(defaultPtr->name, hostName);
  1541. X#endif
  1542. X}
  1543. X
  1544. X
  1545. X/*
  1546. X *******************************************************************************
  1547. X *
  1548. X *  Usage --
  1549. X *
  1550. X *    Lists the proper methods to run the program and exits.
  1551. X *
  1552. X *******************************************************************************
  1553. X */
  1554. X
  1555. XUsage()
  1556. X{
  1557. X    fprintf(stderr, "Usage:\n");
  1558. X    fprintf(stderr,
  1559. X"   ns2tab [style={aliases,elm,group,hosts,lelm,nrgroup,pwupd}] [domain=...]\n");
  1560. X    fprintf(stderr,
  1561. X"              [load] [print]\n");
  1562. X    exit(1);
  1563. X}
  1564. X
  1565. X/*
  1566. X *******************************************************************************
  1567. X *
  1568. X * IsAddr --
  1569. X *
  1570. X *    Returns TRUE if the string looks like an Internet address.
  1571. X *    A string with a trailing dot is not an address, even if it looks
  1572. X *    like one.
  1573. X *
  1574. X *    XXX doesn't treat 255.255.255.255 as an address.
  1575. X *
  1576. X *******************************************************************************
  1577. X */
  1578. X
  1579. XBoolean
  1580. XIsAddr(host, addrPtr)
  1581. X    char *host;
  1582. X    unsigned long *addrPtr;    /* If return TRUE, contains IP address */
  1583. X{
  1584. X    register char *cp;
  1585. X    unsigned long addr;
  1586. X
  1587. X    if (isdigit(host[0])) {
  1588. X        /* Make sure it has only digits and dots. */
  1589. X        for (cp = host; *cp; ++cp) {
  1590. X        if (!isdigit(*cp) && *cp != '.') 
  1591. X            return FALSE;
  1592. X        }
  1593. X        /* If it has a trailing dot, don't treat it as an address. */
  1594. X        if (*--cp != '.') { 
  1595. X        if ((addr = inet_addr(host)) != (unsigned long) -1) {
  1596. X            *addrPtr = addr;
  1597. X            return TRUE;
  1598. X#if 0
  1599. X        } else {
  1600. X            /* XXX Check for 255.255.255.255 case */
  1601. X#endif
  1602. X        }
  1603. X        }
  1604. X    }
  1605. X    return FALSE;
  1606. X}
  1607. X
  1608. X
  1609. X/*
  1610. X *******************************************************************************
  1611. X *
  1612. X *  DOCommand -- 
  1613. X *
  1614. X *    This routine is used to change the state information
  1615. X *    that affect the lookups. The command format is
  1616. X *       keyword[=value]
  1617. X *    Most keywords can be abbreviated. Parsing is very simplistic--
  1618. X *    A value must not be separated from its keyword by white space.
  1619. X *
  1620. X *    Valid keywords:        Meaning:
  1621. X *    [no]d2            turn on/off extra debugging mode.
  1622. X *    [no]debug        turn on/off debugging mode.
  1623. X *    [no]defname        use/don't use default domain name.
  1624. X *    [no]search        use/don't use domain search list.
  1625. X *    domain=NAME        set default domain name to NAME.
  1626. X *    [no]ignore        ignore/don't ignore trunc. errors.
  1627. X *    query=value        set default query type to value,
  1628. X *                value is one of the query types in RFC883
  1629. X *                without the leading T_.    (e.g., A, HINFO)
  1630. X *    [no]recurse        use/don't use recursive lookup.
  1631. X *    retry=#            set number of retries to #.
  1632. X *    root=NAME        change root server to NAME.
  1633. X *    time=#            set timeout length to #.
  1634. X *    [no]vc            use/don't use virtual circuit.
  1635. X *    port            TCP/UDP port to server.
  1636. X *
  1637. X *     Deprecated:
  1638. X *    [no]primary        use/don't use primary server.
  1639. X *
  1640. X *  Results:
  1641. X *    SUCCESS        the command was parsed correctly.
  1642. X *    ERROR        the command was not parsed correctly.
  1643. X *
  1644. X *******************************************************************************
  1645. X */
  1646. X
  1647. Xint
  1648. XDoCommand(option)
  1649. X    register char *option;
  1650. X{
  1651. X    char    type[NAME_LEN];
  1652. X    char    *ptr;
  1653. X    int        tmp;
  1654. X
  1655. X    if (*option == 0) {
  1656. X    fprintf(stderr, "*** Invalid flag\n");
  1657. X    return(ERROR);
  1658. X    } else {
  1659. X    if (strncmp(option, "out", 3) == 0) {
  1660. X        ptr = strchr(option, '=');
  1661. X        if (ptr != NULL) {
  1662. X        if(filePtr != stdout) fclose(filePtr);
  1663. X        if(!(filePtr = fopen(++ptr,"w")))
  1664. X           filePtr = stdout;
  1665. X        }
  1666. X    } else if (strncmp(option, "ser", 3) == 0) {
  1667. X        ptr = strchr(option, '=');
  1668. X        if (ptr != NULL) {
  1669. X        SetDefaultServer(++ptr,1);
  1670. X        explicitserver = 0;
  1671. X        }
  1672. X    } else if (strncmp(option, "expli", 3) == 0) {
  1673. X        ptr = strchr(option, '=');
  1674. X        if (ptr != NULL) {
  1675. X        SetDefaultServer(++ptr,1);
  1676. X        explicitserver = 1;
  1677. X        }
  1678. X    } else if (strncmp(option, "d2", 2) == 0) {    /* d2 (more debug) */
  1679. X        _res.options |= (RES_DEBUG | RES_DEBUG2);
  1680. X    } else if (strncmp(option, "nod2", 4) == 0) {
  1681. X        _res.options &= ~RES_DEBUG2;
  1682. X        printf("d2 mode disabled; still in debug mode\n");
  1683. X    } else if (strncmp(option, "def", 3) == 0) {    /* defname */
  1684. X        _res.options |= RES_DEFNAMES;
  1685. X    } else if (strncmp(option, "nodef", 5) == 0) {
  1686. X        _res.options &= ~RES_DEFNAMES;
  1687. X    } else if (strncmp(option, "domain", 3) == 0) {    /* domain */
  1688. X        ptr = strchr(option, '=');
  1689. X        if (ptr != NULL) {
  1690. X        sscanf(++ptr, "%s", _res.defdname);
  1691. X        res_re_init();
  1692. X        vdomain = _res.defdname;
  1693. X        hasloaded = 0;
  1694. X#if 0
  1695. X        DoCommand("load");
  1696. X#endif
  1697. X        }
  1698. X    } else if (strncmp(option, "suffix", 3) == 0) {    /* domain */
  1699. X        ptr = strchr(option, '=');
  1700. X        if (ptr != NULL) {
  1701. X        vdomain = ++ptr;
  1702. X        }
  1703. X    } else if (strncmp(option, "loa", 3) == 0) {    /* load! */
  1704. X        LoadHosts(_res.defdname);
  1705. X        hasloaded = 1;
  1706. X    } else if (strncmp(option, "prin", 4) == 0) {    /* print! */
  1707. X        if(!hasloaded)
  1708. X        DoCommand("load");
  1709. X        PrintStyle(filePtr);
  1710. X    } else if (strncmp(option, "sty", 3) == 0) {    /* style */
  1711. X        ptr = strchr(option, '=');
  1712. X        if (ptr != NULL)
  1713. X        {
  1714. X        SetStyle(++ptr);
  1715. X        } /* if */
  1716. X    } else if (strncmp(option, "deb", 1) == 0) {    /* debug */
  1717. X        _res.options |= RES_DEBUG;
  1718. X    } else if (strncmp(option, "nodeb", 5) == 0) {
  1719. X        _res.options &= ~(RES_DEBUG | RES_DEBUG2);
  1720. X    } else if (strncmp(option, "ig", 2) == 0) {    /* ignore */
  1721. X        _res.options |= RES_IGNTC;
  1722. X    } else if (strncmp(option, "noig", 4) == 0) {
  1723. X        _res.options &= ~RES_IGNTC;
  1724. X#ifdef deprecated
  1725. X    } else if (strncmp(option, "pri", 3) == 0) {    /* primary */
  1726. X        _res.options |= RES_PRIMARY;
  1727. X    } else if (strncmp(option, "nopri", 5) == 0) {
  1728. X        _res.options &= ~RES_PRIMARY;
  1729. X#endif
  1730. X    } else if (strncmp(option, "cl", 2) == 0) {    /* query class */
  1731. X        ptr = strchr(option, '=');
  1732. X        if (ptr != NULL) {
  1733. X        sscanf(++ptr, "%s", type);
  1734. X        queryClass = StringToClass(type, queryClass);
  1735. X        }
  1736. X    } else if (strncmp(option, "rec", 3) == 0) {    /* recurse */
  1737. X        _res.options |= RES_RECURSE;
  1738. X    } else if (strncmp(option, "norec", 5) == 0) {
  1739. X        _res.options &= ~RES_RECURSE;
  1740. X    } else if (strncmp(option, "ret", 3) == 0) {    /* retry */
  1741. X        ptr = strchr(option, '=');
  1742. X        if (ptr != NULL) {
  1743. X        sscanf(++ptr, "%d", &tmp);
  1744. X        if (tmp >= 0) {
  1745. X            _res.retry = tmp;
  1746. X        }
  1747. X        }
  1748. X    } else if (strncmp(option, "ro", 2) == 0) {    /* root */
  1749. X        ptr = strchr(option, '=');
  1750. X        if (ptr != NULL) {
  1751. X        sscanf(++ptr, "%s", rootServerName);
  1752. X        }
  1753. X    } else if (strncmp(option, "sea", 3) == 0) {    /* search list */
  1754. X        _res.options |= RES_DNSRCH;
  1755. X    } else if (strncmp(option, "nosea", 5) == 0) {
  1756. X        _res.options &= ~RES_DNSRCH;
  1757. X    } else if (strncmp(option, "srchl", 5) == 0) {    /* domain search list */
  1758. X        ptr = strchr(option, '=');
  1759. X        if (ptr != NULL) {
  1760. X        res_dnsrch(++ptr);
  1761. X        }
  1762. X    } else if (strncmp(option, "ti", 2) == 0) {    /* timeout */
  1763. X        ptr = strchr(option, '=');
  1764. X        if (ptr != NULL) {
  1765. X        sscanf(++ptr, "%d", &tmp);
  1766. X        if (tmp >= 0) {
  1767. X            _res.retrans = tmp;
  1768. X        }
  1769. X        }
  1770. X    } else {
  1771. X        fprintf(stderr, "*** Invalid option: %s\n",  option);
  1772. X        return(ERROR);
  1773. X    }
  1774. X    }
  1775. X    return(SUCCESS);
  1776. X}
  1777. X
  1778. X#ifndef MAXDFLSRCH 
  1779. X#define MAXDFLSRCH 3
  1780. X#endif
  1781. X/*
  1782. X * Fake a reinitialization when the domain is changed.
  1783. X */
  1784. Xres_re_init()
  1785. X{
  1786. X    register char *cp, **pp;
  1787. X    int n;
  1788. X
  1789. X    /* find components of local domain that might be searched */
  1790. X    pp = _res.dnsrch;
  1791. X    *pp++ = _res.defdname;
  1792. X    for (cp = _res.defdname, n = 0; *cp; cp++)
  1793. X    if (*cp == '.')
  1794. X        n++;
  1795. X    cp = _res.defdname;
  1796. X    for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) {
  1797. X    cp = strchr(cp, '.');
  1798. X    *pp++ = ++cp;
  1799. X    }
  1800. X    *pp = 0;
  1801. X    _res.options |= RES_INIT;
  1802. X}
  1803. X
  1804. X#define SRCHLIST_SEP '/'
  1805. X
  1806. Xres_dnsrch(cp)
  1807. X    register char *cp;
  1808. X{
  1809. X    register char **pp;
  1810. X    int n;
  1811. X
  1812. X    (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
  1813. X    if ((cp = strchr(_res.defdname, '\n')) != NULL)
  1814. X        *cp = '\0';
  1815. X    /*
  1816. X     * Set search list to be blank-separated strings
  1817. X     * on rest of line.
  1818. X     */
  1819. X    cp = _res.defdname;
  1820. X    pp = _res.dnsrch;
  1821. X    *pp++ = cp;
  1822. X    for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
  1823. X        if (*cp == SRCHLIST_SEP) {
  1824. X            *cp = '\0';
  1825. X            n = 1;
  1826. X        } else if (n) {
  1827. X            *pp++ = cp;
  1828. X            n = 0;
  1829. X        }
  1830. X    }
  1831. X    if ((cp = strchr(pp[-1], SRCHLIST_SEP)) != NULL) {
  1832. X    *cp = '\0';
  1833. X    }
  1834. X    *pp = NULL;
  1835. X}
  1836. X
  1837. X#undef SRCHLIST_SEP
  1838. X
  1839. X/*
  1840. X *******************************************************************************
  1841. X *
  1842. X * CvtAddrToPtr --
  1843. X *
  1844. X *    Convert a dotted-decimal Internet address into the standard
  1845. X *    PTR format (reversed address with .in-arpa. suffix).
  1846. X *
  1847. X *    Assumes the argument buffer is large enougth to hold the result.
  1848. X *
  1849. X *******************************************************************************
  1850. X */
  1851. X
  1852. Xstatic void
  1853. XCvtAddrToPtr(name)
  1854. X    char *name;
  1855. X{
  1856. X    char *p;
  1857. X    int ip[4];
  1858. X    struct in_addr addr;
  1859. X
  1860. X    if (IsAddr(name, &addr.s_addr)) {
  1861. X    p = inet_ntoa(addr);
  1862. X    if (sscanf(p, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) {
  1863. X        sprintf(name, "%d.%d.%d.%d.in-addr.arpa.", 
  1864. X        ip[3], ip[2], ip[1], ip[0]);
  1865. X    }
  1866. X    }
  1867. X}
  1868. X
  1869. X#if 0
  1870. Xint
  1871. XSetServer(serv)
  1872. X   char *serv;
  1873. X{
  1874. X    int i;
  1875. X    struct in_addr addr;
  1876. X    struct hostent *hp;
  1877. X
  1878. X    /*
  1879. X     * Use an explicit name server. If the hostname lookup fails,
  1880. X     * default to the server(s) in resolv.conf.
  1881. X     */ 
  1882. X
  1883. X    addr.s_addr = inet_addr(serv);
  1884. X    if (addr.s_addr != (unsigned long)-1) {
  1885. X    _res.nscount = 1;
  1886. X    _res.nsaddr.sin_addr = addr;
  1887. X    } else {
  1888. X    hp = gethostbyname(serv);
  1889. X    if (hp == NULL) {
  1890. X        fprintf(stderr, "*** Can't find server address for '%s': ", 
  1891. X            serv);
  1892. X        herror((char *)NULL);
  1893. X        fputc('\n', stderr);
  1894. X        return 0;
  1895. X    }
  1896. X    else
  1897. X    {
  1898. X#if BSD < 43
  1899. X        bcopy(hp->h_addr, (char *)&_res.nsaddr.sin_addr, hp->h_length);
  1900. X        _res.nscount = 1;
  1901. X#else
  1902. X        for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) {
  1903. X        bcopy(hp->h_addr_list[i], 
  1904. X            (char *)&_res.nsaddr_list(i).sin_addr, 
  1905. X            hp->h_length);
  1906. X        }
  1907. X        _res.nscount = i;
  1908. X#endif
  1909. X    } 
  1910. X    }
  1911. X    return 1;
  1912. X}
  1913. X#endif
  1914. X/*
  1915. X *******************************************************************************
  1916. X *
  1917. X *  SetDefaultServer --
  1918. X *
  1919. X *    Changes the default name server to the one specified by
  1920. X *    the first argument. The command "server name" uses the current 
  1921. X *    default server to lookup the info for "name". The command
  1922. X *    "lserver name" uses the original server to lookup "name".
  1923. X *
  1924. X *  Side effects:
  1925. X *    This routine will cause a core dump if the allocation requests fail.
  1926. X *
  1927. X *  Results:
  1928. X *    SUCCESS        The default server was changed successfully.
  1929. X *    NONAUTH        The server was changed but addresses of
  1930. X *            other servers who know about the requested server
  1931. X *            were returned.
  1932. X *    Errors        No info about the new server was found or
  1933. X *            requests to the current server timed-out.
  1934. X *
  1935. X *******************************************************************************
  1936. X */
  1937. X
  1938. Xint
  1939. XSetDefaultServer(string, local)
  1940. X    char    *string;
  1941. X    Boolean    local;
  1942. X{
  1943. X    register HostInfo    *newDefPtr;
  1944. X    struct in_addr    *servAddrPtr;
  1945. X    struct in_addr    addr;
  1946. X    char        newServer[NAME_LEN];
  1947. X    int            result;
  1948. X    int            i;
  1949. X
  1950. X    strcpy(newServer,string);
  1951. X    /*
  1952. X     * Allocate space for a HostInfo variable for the new server. Don't
  1953. X     * overwrite the old HostInfo struct because info about the new server
  1954. X     * might not be found and we need to have valid default server info.
  1955. X     */
  1956. X
  1957. X    newDefPtr = (HostInfo *) calloc(1, sizeof(HostInfo));
  1958. X
  1959. X
  1960. X    /*
  1961. X     *    A 'local' lookup uses the original server that the program was
  1962. X     *  initialized with.
  1963. X     *
  1964. X     *  Check to see if we have the address of the server or the
  1965. X     *  address of a server who knows about this domain.
  1966. X     *  XXX For now, just use the first address in the list.
  1967. X     */
  1968. X
  1969. X    if (local) {
  1970. X    servAddrPtr = &defaultAddr;
  1971. X    } else if (defaultPtr->addrList != NULL) {
  1972. X    servAddrPtr = (struct in_addr *) defaultPtr->addrList[0];
  1973. X    } else {
  1974. X    servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0];
  1975. X    }
  1976. X
  1977. X    result = ERROR;
  1978. X    if (IsAddr(newServer, &addr.s_addr)) {
  1979. X    result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr);
  1980. X    /* If we can't get the name, fall through... */
  1981. X    } 
  1982. X    if (result != SUCCESS && result != NONAUTH) {
  1983. X    result = GetHostInfoByName(servAddrPtr, C_IN, T_A, 
  1984. X            newServer, newDefPtr, 1);
  1985. X    }
  1986. X
  1987. X    if (result == SUCCESS || result == NONAUTH) {
  1988. X        /*
  1989. X         *  Found info about the new server. Free the resources for
  1990. X         *  the old server.
  1991. X         */
  1992. X
  1993. X        FreeHostInfoPtr(defaultPtr);
  1994. X        free((char *)defaultPtr);
  1995. X        defaultPtr = newDefPtr;
  1996. X        strcpy(defaultServer, defaultPtr->name);
  1997. X        return(SUCCESS);
  1998. X    } else {
  1999. X        fprintf(stderr, "*** Can't find address for server %s: %s\n",
  2000. X            newServer, DecodeError(result));
  2001. X        free((char *)newDefPtr);
  2002. X
  2003. X        return(result);
  2004. X    }
  2005. X}
  2006. END_OF_FILE
  2007. if test 17249 -ne `wc -c <'main.c'`; then
  2008.     echo shar: \"'main.c'\" unpacked with wrong size!
  2009. fi
  2010. # end of 'main.c'
  2011. fi
  2012. echo shar: End of archive 2 \(of 3\).
  2013. cp /dev/null ark2isdone
  2014. MISSING=""
  2015. for I in 1 2 3 ; do
  2016.     if test ! -f ark${I}isdone ; then
  2017.     MISSING="${MISSING} ${I}"
  2018.     fi
  2019. done
  2020. if test "${MISSING}" = "" ; then
  2021.     echo You have unpacked all 3 archives.
  2022.     rm -f ark[1-9]isdone
  2023. else
  2024.     echo You still need to unpack the following archives:
  2025.     echo "        " ${MISSING}
  2026. fi
  2027. ##  End of shell archive.
  2028. exit 0
  2029.