2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
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.
41 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
42 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
44 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
45 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
46 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
47 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 #if defined(LIBC_SCCS) && !defined(lint)
52 static const char rcsid[] = "$Id: lcl_sv.c,v 1.20 1999/10/07 20:44:03 vixie Exp $";
53 #endif /* LIBC_SCCS and not lint */
57 #include "port_before.h"
59 #include <sys/types.h>
60 #include <sys/socket.h>
61 #include <netinet/in.h>
62 #include <arpa/nameser.h>
76 #include <isc/memcluster.h>
78 #include "port_after.h"
84 # define SPRINTF(x) strlen(sprintf/**/x)
86 # define SPRINTF(x) ((size_t)sprintf x)
101 static void sv_close(struct irs_sv*);
102 static struct servent * sv_next(struct irs_sv *);
103 static struct servent * sv_byname(struct irs_sv *, const char *,
105 static struct servent * sv_byport(struct irs_sv *, int, const char *);
106 static void sv_rewind(struct irs_sv *);
107 static void sv_minimize(struct irs_sv *);
108 /*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *);
110 static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *);
122 irs_lcl_sv(struct irs_acc *this) {
126 if ((sv = memget(sizeof *sv)) == NULL) {
130 memset(sv, 0x5e, sizeof *sv);
131 if ((pvt = memget(sizeof *pvt)) == NULL) {
132 memput(sv, sizeof *sv);
136 memset(pvt, 0, sizeof *pvt);
138 sv->close = sv_close;
140 sv->byname = sv_byname;
141 sv->byport = sv_byport;
142 sv->rewind = sv_rewind;
143 sv->minimize = sv_minimize;
155 sv_close(struct irs_sv *this) {
156 struct pvt *pvt = (struct pvt *)this->private;
159 if (pvt->dbh != NULL)
160 (*pvt->dbh->close)(pvt->dbh);
164 memput(pvt, sizeof *pvt);
165 memput(this, sizeof *this);
168 static struct servent *
169 sv_byname(struct irs_sv *this, const char *name, const char *proto) {
171 struct pvt *pvt = (struct pvt *)this->private;
178 if (pvt->dbh != NULL) {
181 /* Note that (sizeof "/") == 2. */
182 if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0)
183 > sizeof pvt->sv.line)
185 key.data = pvt->sv.line;
186 key.size = SPRINTF((pvt->sv.line, "%s/%s", name,
187 proto ? proto : "")) + 1;
189 if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
191 } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
194 return (sv_db_rec(&pvt->sv, &key, &data));
199 while ((p = sv_next(this))) {
200 if (strcmp(name, p->s_name) == 0)
202 for (cp = p->s_aliases; *cp; cp++)
203 if (strcmp(name, *cp) == 0)
207 if (proto == NULL || strcmp(p->s_proto, proto) == 0)
213 static struct servent *
214 sv_byport(struct irs_sv *this, int port, const char *proto) {
216 struct pvt *pvt = (struct pvt *)this->private;
222 if (pvt->dbh != NULL) {
226 ports = (u_short *)pvt->sv.line;
230 key.size = sizeof(u_short) * 2;
231 if (proto && *proto) {
232 strncpy((char *)ports + key.size, proto,
234 key.size += strlen((char *)ports + key.size) + 1;
235 if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0)
238 if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR)
242 return (sv_db_rec(&pvt->sv, &key, &data));
245 while ((p = sv_next(this))) {
246 if (p->s_port != port)
248 if (proto == NULL || strcmp(p->s_proto, proto) == 0)
255 sv_rewind(struct irs_sv *this) {
256 struct pvt *pvt = (struct pvt *)this->private;
259 if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0)
261 (void)fclose(pvt->sv.fp);
266 if (pvt->dbh != NULL)
268 pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL);
269 if (pvt->dbh != NULL) {
270 if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) {
271 (*pvt->dbh->close)(pvt->dbh);
277 if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL)
279 if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) {
280 (void)fclose(pvt->sv.fp);
285 static struct servent *
286 sv_next(struct irs_sv *this) {
287 struct pvt *pvt = (struct pvt *)this->private;
290 if (pvt->dbh != NULL)
294 if (pvt->sv.fp != NULL)
300 if (pvt->dbh != NULL) {
303 while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){
305 if (((char *)key.data)[0])
307 return (sv_db_rec(&pvt->sv, &key, &data));
312 if (pvt->sv.fp == NULL)
314 return (irs_lclsv_fnxt(&pvt->sv));
318 sv_minimize(struct irs_sv *this) {
319 struct pvt *pvt = (struct pvt *)this->private;
322 if (pvt->dbh != NULL) {
323 (*pvt->dbh->close)(pvt->dbh);
327 if (pvt->sv.fp != NULL) {
328 (void)fclose(pvt->sv.fp);
336 irs_lclsv_fnxt(struct lcl_sv *sv) {
340 if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL)
345 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
347 if (*p == '\0' || *p == '#' || *p == '\n')
350 while (*p == ' ' || *p == '\t')
352 if (*p == '\0' || *p == '#' || *p == '\n')
354 sv->serv.s_port = htons((u_short)strtol(p, &cp, 10));
355 if (cp == p || (*cp != '/' && *cp != ','))
358 sv->serv.s_proto = p;
360 q = sv->serv.s_aliases = sv->serv_aliases;
362 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
365 while (*p == ' ' || *p == '\t') {
367 while (*p == ' ' || *p == '\t')
369 if (*p == '\0' || *p == '#' || *p == '\n')
371 if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1])
373 while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#')
385 static struct servent *
386 sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) {
391 p[data->size - 1] = '\0'; /* should be, but we depend on it */
393 if (((char *)key->data)[0] == '\0') {
394 if (key->size < sizeof(u_short)*2 || data->size < 2)
396 sv->serv.s_port = ((u_short *)key->data)[1];
398 if (n > sizeof(sv->line)) {
399 n = sizeof(sv->line);
401 memcpy(sv->line, p, n);
402 sv->serv.s_name = sv->line;
403 if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL)
404 *(sv->serv.s_proto)++ = '\0';
408 if (data->size < sizeof(u_short) + 1)
410 if (key->size > sizeof(sv->line))
411 key->size = sizeof(sv->line);
412 ((char *)key->data)[key->size - 1] = '\0';
413 memcpy(sv->line, key->data, key->size);
414 sv->serv.s_name = sv->line;
415 if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL)
416 *(sv->serv.s_proto)++ = '\0';
417 sv->serv.s_port = *(u_short *)data->data;
418 p += sizeof(u_short);
419 data->size -= sizeof(u_short);
421 q = sv->serv.s_aliases = sv->serv_aliases;
422 while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) {