Merge from vendor branch CVS:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / bind / irs / lcl_pr.c
1 /*
2  * Copyright (c) 1989, 1993, 1995
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
34 /*
35  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
36  * Portions Copyright (c) 1996,1999 by Internet Software Consortium.
37  *
38  * Permission to use, copy, modify, and distribute this software for any
39  * purpose with or without fee is hereby granted, provided that the above
40  * copyright notice and this permission notice appear in all copies.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
43  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
44  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
45  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
47  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
48  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
49  */
50
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid[] = "$Id: lcl_pr.c,v 1.1.2.1 2004/03/09 09:17:33 marka Exp $";
53 #endif /* LIBC_SCCS and not lint */
54
55 /* extern */
56
57 #include "port_before.h"
58
59 #include <sys/types.h>
60 #include <netinet/in.h>
61 #include <arpa/nameser.h>
62 #include <resolv.h>
63
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <string.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69
70 #include <irs.h>
71 #include <isc/memcluster.h>
72
73 #include "port_after.h"
74
75 #include "irs_p.h"
76 #include "lcl_p.h"
77
78 #ifndef _PATH_PROTOCOLS
79 #define _PATH_PROTOCOLS "/etc/protocols"
80 #endif
81 #define MAXALIASES      35
82
83 /* Types */
84
85 struct pvt {
86         FILE *          fp;
87         char            line[BUFSIZ+1];
88         struct protoent proto;
89         char *          proto_aliases[MAXALIASES];
90 };
91
92 /* Forward */
93
94 static void                     pr_close(struct irs_pr *);
95 static struct protoent *        pr_next(struct irs_pr *);
96 static struct protoent *        pr_byname(struct irs_pr *, const char *);
97 static struct protoent *        pr_bynumber(struct irs_pr *, int);
98 static void                     pr_rewind(struct irs_pr *);
99 static void                     pr_minimize(struct irs_pr *);
100
101 /* Portability. */
102
103 #ifndef SEEK_SET
104 # define SEEK_SET 0
105 #endif
106
107 /* Public */
108
109 struct irs_pr *
110 irs_lcl_pr(struct irs_acc *this) {
111         struct irs_pr *pr;
112         struct pvt *pvt;
113         
114         if (!(pr = memget(sizeof *pr))) {
115                 errno = ENOMEM;
116                 return (NULL);
117         }
118         if (!(pvt = memget(sizeof *pvt))) {
119                 memput(pr, sizeof *this);
120                 errno = ENOMEM;
121                 return (NULL);
122         }
123         memset(pvt, 0, sizeof *pvt);
124         pr->private = pvt;
125         pr->close = pr_close;
126         pr->byname = pr_byname;
127         pr->bynumber = pr_bynumber;
128         pr->next = pr_next;
129         pr->rewind = pr_rewind;
130         pr->minimize = pr_minimize;
131         pr->res_get = NULL;
132         pr->res_set = NULL;
133         return (pr);
134 }
135
136 /* Methods */
137
138 static void
139 pr_close(struct irs_pr *this) {
140         struct pvt *pvt = (struct pvt *)this->private;
141
142         if (pvt->fp)
143                 (void) fclose(pvt->fp);
144         memput(pvt, sizeof *pvt);
145         memput(this, sizeof *this);
146 }
147
148 static struct protoent *
149 pr_byname(struct irs_pr *this, const char *name) {
150                 
151         struct protoent *p;
152         char **cp;
153
154         pr_rewind(this);
155         while ((p = pr_next(this))) {
156                 if (!strcmp(p->p_name, name))
157                         goto found;
158                 for (cp = p->p_aliases; *cp; cp++)
159                         if (!strcmp(*cp, name))
160                                 goto found;
161         }
162  found:
163         return (p);
164 }
165
166 static struct protoent *
167 pr_bynumber(struct irs_pr *this, int proto) {
168         struct protoent *p;
169
170         pr_rewind(this);
171         while ((p = pr_next(this)))
172                 if (p->p_proto == proto)
173                         break;
174         return (p);
175 }
176
177 static void
178 pr_rewind(struct irs_pr *this) {
179         struct pvt *pvt = (struct pvt *)this->private;
180         
181         if (pvt->fp) {
182                 if (fseek(pvt->fp, 0L, SEEK_SET) == 0)
183                         return;
184                 (void)fclose(pvt->fp);
185         }
186         if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" )))
187                 return;
188         if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) {
189                 (void)fclose(pvt->fp);
190                 pvt->fp = NULL;
191         }
192 }
193
194 static struct protoent *
195 pr_next(struct irs_pr *this) {
196         struct pvt *pvt = (struct pvt *)this->private;
197         char *p, *cp, **q;
198         char *bufp, *ndbuf, *dbuf = NULL;
199         int c, bufsiz, offset;
200
201         if (!pvt->fp)
202                 pr_rewind(this);
203         if (!pvt->fp)
204                 return (NULL);
205         bufp = pvt->line;
206         bufsiz = BUFSIZ;
207         offset = 0;
208  again:
209         if ((p = fgets(bufp + offset, bufsiz - offset, pvt->fp)) == NULL) {
210                 if (dbuf)
211                         free(dbuf);
212                 return (NULL);
213         }
214         if (!strchr(p, '\n') && !feof(pvt->fp)) {
215 #define GROWBUF 1024
216                 /* allocate space for longer line */
217                 if (dbuf == NULL) {
218                         if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL)
219                                 strcpy(ndbuf, bufp);
220                 } else
221                         ndbuf = realloc(dbuf, bufsiz + GROWBUF);
222                 if (ndbuf) {
223                         dbuf = ndbuf;
224                         bufp = dbuf;
225                         bufsiz += GROWBUF;
226                         offset = strlen(dbuf);
227                 } else {
228                         /* allocation failed; skip this long line */
229                         while ((c = getc(pvt->fp)) != EOF)
230                                 if (c == '\n')
231                                         break;
232                         if (c != EOF)
233                                 ungetc(c, pvt->fp);
234                 }
235                 goto again;
236         }
237
238         p -= offset;
239         offset = 0;
240
241         if (*p == '#')
242                 goto again;
243         cp = strpbrk(p, "#\n");
244         if (cp != NULL)
245                 *cp = '\0';
246         pvt->proto.p_name = p;
247         cp = strpbrk(p, " \t");
248         if (cp == NULL)
249                 goto again;
250         *cp++ = '\0';
251         while (*cp == ' ' || *cp == '\t')
252                 cp++;
253         p = strpbrk(cp, " \t");
254         if (p != NULL)
255                 *p++ = '\0';
256         pvt->proto.p_proto = atoi(cp);
257         q = pvt->proto.p_aliases = pvt->proto_aliases;
258         if (p != NULL) {
259                 cp = p;
260                 while (cp && *cp) {
261                         if (*cp == ' ' || *cp == '\t') {
262                                 cp++;
263                                 continue;
264                         }
265                         if (q < &pvt->proto_aliases[MAXALIASES - 1])
266                                 *q++ = cp;
267                         cp = strpbrk(cp, " \t");
268                         if (cp != NULL)
269                                 *cp++ = '\0';
270                 }
271         }
272         *q = NULL;
273         return (&pvt->proto);
274 }
275
276 static void
277 pr_minimize(struct irs_pr *this) {
278         struct pvt *pvt = (struct pvt *)this->private;
279
280         if (pvt->fp != NULL) {
281                 (void)fclose(pvt->fp);
282                 pvt->fp = NULL;
283         }
284 }