Sync usage with man page.
[netbsd-mini2440.git] / lib / libc / net / getservent_r.c
blobe6b4cf04569d5a6fabaeb9a540dab2449d7b5633
1 /* $NetBSD: getservent_r.c,v 1.8 2006/09/14 19:58:48 christos Exp $ */
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
34 #if 0
35 static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
36 #else
37 __RCSID("$NetBSD: getservent_r.c,v 1.8 2006/09/14 19:58:48 christos Exp $");
38 #endif
39 #endif /* LIBC_SCCS and not lint */
41 #include "namespace.h"
42 #include <netdb.h>
43 #include <errno.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <fcntl.h>
48 #include <db.h>
50 #include "servent.h"
52 #ifdef __weak_alias
53 __weak_alias(endservent_r,_endservent_r)
54 __weak_alias(getservent_r,_getservent_r)
55 __weak_alias(setservent_r,_setservent_r)
56 #endif
58 int
59 _servent_open(struct servent_data *sd)
61 sd->flags |= _SV_FIRST;
62 if (sd->db == NULL) {
63 if ((sd->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0,
64 DB_HASH, NULL)) != NULL)
65 sd->flags |= _SV_DB;
66 else
67 sd->db = fopen(_PATH_SERVICES, "r");
69 return sd->db ? 0 : -1;
72 void
73 _servent_close(struct servent_data *sd)
75 if (sd->db) {
76 if (sd->flags & _SV_DB) {
77 DB *db = sd->db;
78 (*db->close)(db);
79 } else
80 (void)fclose((FILE *)sd->db);
81 sd->db = NULL;
83 sd->flags &= ~_SV_STAYOPEN;
87 int
88 _servent_getline(struct servent_data *sd)
90 if (sd->line) {
91 free(sd->line);
92 sd->line = NULL;
95 if (sd->db == NULL)
96 return -1;
98 if (sd->flags & _SV_DB) {
99 DB *db = sd->db;
100 DBT key, data;
101 u_int flags = (sd->flags & _SV_FIRST) ? R_FIRST : R_NEXT;
103 while ((*db->seq)(db, &key, &data, flags) == 0) {
104 flags = R_NEXT;
105 switch (((u_char *)key.data)[0]) {
106 case (u_char)'\377':
107 case (u_char)'\376':
108 continue;
109 default:
110 break;
112 sd->line = strdup(data.data);
113 break;
115 } else {
116 if (sd->flags & _SV_FIRST)
117 (void)rewind((FILE *)sd->db);
118 sd->line = fparseln((FILE *)sd->db, NULL, NULL, NULL,
119 FPARSELN_UNESCALL);
121 sd->flags &= ~_SV_FIRST;
122 return sd->line == NULL ? -1 : 0;
126 struct servent *
127 _servent_parseline(struct servent_data *sd, struct servent *sp)
129 size_t i = 0;
130 int oerrno;
131 char *p, *cp, **q;
133 if (sd->line == NULL)
134 return NULL;
136 sp->s_name = p = sd->line;
137 p = strpbrk(p, " \t");
138 if (p == NULL)
139 return NULL;
140 *p++ = '\0';
141 while (*p == ' ' || *p == '\t')
142 p++;
143 cp = strpbrk(p, ",/");
144 if (cp == NULL)
145 return NULL;
146 *cp++ = '\0';
147 sp->s_port = htons((u_short)atoi(p));
148 sp->s_proto = cp;
149 if (sd->aliases == NULL) {
150 sd->maxaliases = 10;
151 sd->aliases = malloc(sd->maxaliases * sizeof(char *));
152 if (sd->aliases == NULL) {
153 oerrno = errno;
154 endservent_r(sd);
155 errno = oerrno;
156 return NULL;
159 q = sp->s_aliases = sd->aliases;
160 cp = strpbrk(cp, " \t");
161 if (cp != NULL)
162 *cp++ = '\0';
163 while (cp && *cp) {
164 if (*cp == ' ' || *cp == '\t') {
165 cp++;
166 continue;
168 if (i == sd->maxaliases - 2) {
169 sd->maxaliases *= 2;
170 q = realloc(q,
171 sd->maxaliases * sizeof(char *));
172 if (q == NULL) {
173 oerrno = errno;
174 endservent_r(sd);
175 errno = oerrno;
176 return NULL;
178 sp->s_aliases = sd->aliases = q;
180 q[i++] = cp;
181 cp = strpbrk(cp, " \t");
182 if (cp != NULL)
183 *cp++ = '\0';
185 q[i] = NULL;
186 return sp;
189 void
190 setservent_r(int f, struct servent_data *sd)
192 (void)_servent_open(sd);
193 sd->flags |= f ? _SV_STAYOPEN : 0;
196 void
197 endservent_r(struct servent_data *sd)
199 _servent_close(sd);
200 if (sd->aliases) {
201 free(sd->aliases);
202 sd->aliases = NULL;
203 sd->maxaliases = 0;
205 if (sd->line) {
206 free(sd->line);
207 sd->line = NULL;
211 struct servent *
212 getservent_r(struct servent *sp, struct servent_data *sd)
214 if (sd->db == NULL && _servent_open(sd) == -1)
215 return NULL;
217 for (;;) {
218 if (_servent_getline(sd) == -1)
219 return NULL;
220 if (_servent_parseline(sd, sp) == NULL)
221 continue;
222 return sp;