Formerly ../hurd/hurdpid.c.~9~
[kopensolaris-gnu/glibc.git] / resolv / res_init.c
1 /*
2  * ++Copyright++ 1985, 1989
3  * -
4  * Copyright (c) 1985, 1989 Regents of the University of California.
5  * All rights reserved.
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  * -
35  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
36  * 
37  * Permission to use, copy, modify, and distribute this software for any
38  * purpose with or without fee is hereby granted, provided that the above
39  * copyright notice and this permission notice appear in all copies, and that
40  * the name of Digital Equipment Corporation not be used in advertising or
41  * publicity pertaining to distribution of the document or software without
42  * specific, written prior permission.
43  * 
44  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
45  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
47  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
48  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
49  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
50  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51  * SOFTWARE.
52  * -
53  * --Copyright--
54  */
55
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "@(#)res_init.c  6.15 (Berkeley) 2/24/91";
58 static char rcsid[] = "$Id$";
59 #endif /* LIBC_SCCS and not lint */
60
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #include <arpa/nameser.h>
66 #include <resolv.h>
67 #include <stdio.h>
68 #include "../conf/portability.h"
69
70
71 /*
72  * Resolver state default settings
73  */
74
75 struct __res_state _res = {
76         RES_TIMEOUT,                    /* retransmition time interval */
77         4,                              /* number of times to retransmit */
78         RES_DEFAULT,                    /* options flags */
79         1,                              /* number of name servers */
80 };
81
82 /*
83  * Set up default settings.  If the configuration file exist, the values
84  * there will have precedence.  Otherwise, the server address is set to
85  * 127.0.0.1 and the default domain name comes from the gethostname().
86  *
87  * Previous resolver versions used INADDR_ANY rather than IN_LOOPBACKNET.
88  * This has bad side-effects in the kernel since 0.0.0.0 means "any interface"
89  * and the first one found may or may not be the loopback interface.
90  * If it is a point-to-point interface, then the SLIP or PPP or DDCMP state
91  * must be "up" in order for the packets to loop correctly.  This is deemed
92  * "bad".  
93  *
94  * The configuration file should only be used if you want to redefine your
95  * domain or run without a server on your machine.
96  *
97  * Return 0 if completes successfully, -1 on error
98  */
99 res_init()
100 {
101         register FILE *fp;
102         register char *cp, **pp;
103         register int n;
104         char buf[BUFSIZ];
105         int nserv = 0;    /* number of nameserver records read from file */
106         int haveenv = 0;
107         int havesearch = 0;
108
109         _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
110         _res.nsaddr.sin_family = AF_INET;
111         _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
112         _res.nscount = 1;
113         _res.pfcode = 0;
114
115         /* Allow user to override the local domain definition */
116         if ((cp = getenv("LOCALDOMAIN")) != NULL) {
117                 (void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
118                 if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
119                         *cp = '\0';
120                 haveenv++;
121         }
122
123         if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
124             /* read the config file */
125             while (fgets(buf, sizeof(buf), fp) != NULL) {
126                 /* skip comments */
127                 if ((*buf == ';') || (*buf == '#'))
128                         continue;
129                 /* read default domain name */
130                 if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
131                     if (haveenv)        /* skip if have from environ */
132                             continue;
133                     cp = buf + sizeof("domain") - 1;
134                     while (*cp == ' ' || *cp == '\t')
135                             cp++;
136                     if ((*cp == '\0') || (*cp == '\n'))
137                             continue;
138                     (void)strncpy(_res.defdname, cp,
139                                   sizeof(_res.defdname) - 1);
140                     if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
141                             *cp = '\0';
142                     havesearch = 0;
143                     continue;
144                 }
145                 /* set search list */
146                 if (!strncmp(buf, "search", sizeof("search") - 1)) {
147                     if (haveenv)        /* skip if have from environ */
148                             continue;
149                     cp = buf + sizeof("search") - 1;
150                     while (*cp == ' ' || *cp == '\t')
151                             cp++;
152                     if ((*cp == '\0') || (*cp == '\n'))
153                             continue;
154                     (void)strncpy(_res.defdname, cp,
155                                   sizeof(_res.defdname) - 1);
156                     if ((cp = strchr(_res.defdname, '\n')) != NULL)
157                             *cp = '\0';
158                     /*
159                      * Set search list to be blank-separated strings
160                      * on rest of line.
161                      */
162                     cp = _res.defdname;
163                     pp = _res.dnsrch;
164                     *pp++ = cp;
165                     for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
166                             if (*cp == ' ' || *cp == '\t') {
167                                     *cp = 0;
168                                     n = 1;
169                             } else if (n) {
170                                     *pp++ = cp;
171                                     n = 0;
172                             }
173                     }
174                     /* null terminate last domain if there are excess */
175                     while (*cp != '\0' && *cp != ' ' && *cp != '\t')
176                             cp++;
177                     *cp = '\0';
178                     *pp++ = 0;
179                     havesearch = 1;
180                     continue;
181                 }
182                 /* read nameservers to query */
183                 if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
184                    nserv < MAXNS) {
185                    struct in_addr a;
186
187                     cp = buf + sizeof("nameserver") - 1;
188                     while (*cp == ' ' || *cp == '\t')
189                         cp++;
190                     if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
191                         _res.nsaddr_list[nserv].sin_addr = a;
192                         _res.nsaddr_list[nserv].sin_family = AF_INET;
193                         _res.nsaddr_list[nserv].sin_port =
194                                 htons(NAMESERVER_PORT);
195                         nserv++;
196                     }
197                     continue;
198                 }
199             }
200             if (nserv > 1) 
201                 _res.nscount = nserv;
202             (void) fclose(fp);
203         }
204         if (_res.defdname[0] == 0) {
205                 if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
206                    (cp = strchr(buf, '.')))
207                         (void)strcpy(_res.defdname, cp + 1);
208         }
209
210         /* find components of local domain that might be searched */
211         if (havesearch == 0) {
212                 pp = _res.dnsrch;
213                 *pp++ = _res.defdname;
214                 for (cp = _res.defdname, n = 0; *cp; cp++)
215                         if (*cp == '.')
216                                 n++;
217                 cp = _res.defdname;
218                 for (;
219                      n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
220                      n--) {
221                         cp = strchr(cp, '.');
222                         *pp++ = ++cp;
223                 }
224                 *pp++ = 0;
225         }
226         _res.options |= RES_INIT;
227         return (0);
228 }