xref: /haiku/src/system/libnetwork/netresolv/net/getservent_r.c (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*	$NetBSD: getservent_r.c,v 1.11 2011/10/15 23:00:02 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1983, 1993
5  *	The Regents of the University of California.  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. 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.
18  *
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.
30  */
31 
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.11 2011/10/15 23:00:02 christos Exp $");
38 #endif
39 #endif /* LIBC_SCCS and not lint */
40 
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <netdb.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 
48 #include <FindDirectory.h>
49 
50 #include <libutil.h>
51 #include "servent.h"
52 
53 #ifdef __weak_alias
54 __weak_alias(endservent_r,_endservent_r)
55 __weak_alias(getservent_r,_getservent_r)
56 __weak_alias(setservent_r,_setservent_r)
57 #endif
58 
59 int
60 _servent_open(struct servent_data *sd)
61 {
62 	char buffer[256];
63 
64 	if (sd->flags & (_SV_CDB | _SV_PLAINFILE)) {
65 		sd->flags |= _SV_FIRST;
66 		return 0;
67 	}
68 
69 	free(sd->line);
70 	sd->line = NULL;
71 	free(sd->cdb_buf);
72 	sd->cdb_buf = NULL;
73 	sd->cdb_buf_len = 0;
74 	free(sd->aliases);
75 	sd->aliases = NULL;
76 	sd->maxaliases = 0;
77 	sd->flags |= _SV_FIRST;
78 
79 #if 0
80 	sd->cdb = cdbr_open(_PATH_SERVICES_CDB, CDBR_DEFAULT);
81 	if (sd->cdb != NULL) {
82 		sd->flags |= _SV_CDB;
83 		return 0;
84 	}
85 #endif
86 
87 	find_directory(B_SYSTEM_DATA_DIRECTORY, 0, false, buffer, sizeof(buffer));
88 	strlcat(buffer, "/network/ports", sizeof(buffer));
89 
90 	sd->plainfile = fopen(buffer, "re");
91 	if (sd->plainfile != NULL) {
92 		sd->flags |= _SV_PLAINFILE;
93 		return 0;
94 	}
95 	return -1;
96 }
97 
98 void
99 _servent_close(struct servent_data *sd)
100 {
101 #if 0
102 	if (sd->flags & _SV_CDB) {
103 		cdbr_close(sd->cdb);
104 		sd->cdb = NULL;
105 		sd->flags &= ~_SV_CDB;
106 	}
107 #endif
108 
109 	if (sd->flags & _SV_PLAINFILE) {
110 		(void)fclose(sd->plainfile);
111 		sd->plainfile = NULL;
112 		sd->flags &= ~_SV_PLAINFILE;
113 	}
114 	sd->flags &= ~_SV_STAYOPEN;
115 }
116 
117 
118 int
119 _servent_getline(struct servent_data *sd)
120 {
121 #if 0
122 	if (sd->flags & _SV_CDB)
123 		return -1;
124 #endif
125 
126 	if ((sd->flags & _SV_PLAINFILE) == 0)
127 		return -1;
128 
129 	free(sd->line);
130 	sd->line = NULL;
131 
132 	if (sd->flags & _SV_FIRST) {
133 		(void)rewind((FILE *)sd->plainfile);
134 		sd->flags &= ~_SV_FIRST;
135 	}
136 	sd->line = fparseln(sd->plainfile, NULL, NULL, NULL,
137 	    FPARSELN_UNESCALL);
138 	return sd->line == NULL ? -1 : 0;
139 }
140 
141 struct servent *
142 _servent_parseline(struct servent_data *sd, struct servent *sp)
143 {
144 	size_t i = 0;
145 	int oerrno;
146 	char *p, *cp, **q;
147 
148 	if (sd->line == NULL)
149 		return NULL;
150 
151 	sp->s_name = p = sd->line;
152 	p = strpbrk(p, " \t");
153 	if (p == NULL)
154 		return NULL;
155 	*p++ = '\0';
156 	while (*p == ' ' || *p == '\t')
157 		p++;
158 	cp = strpbrk(p, ",/");
159 	if (cp == NULL)
160 		return NULL;
161 	*cp++ = '\0';
162 	sp->s_port = htons((u_short)atoi(p));
163 	sp->s_proto = cp;
164 	if (sd->aliases == NULL) {
165 		sd->maxaliases = 10;
166 		sd->aliases = calloc(sd->maxaliases, sizeof(*sd->aliases));
167 		if (sd->aliases == NULL) {
168 			oerrno = errno;
169 			endservent_r(sd);
170 			errno = oerrno;
171 			return NULL;
172 		}
173 	}
174 	sp->s_aliases = sd->aliases;
175 	cp = strpbrk(cp, " \t");
176 	if (cp != NULL)
177 		*cp++ = '\0';
178 	while (cp && *cp) {
179 		if (*cp == ' ' || *cp == '\t') {
180 			cp++;
181 			continue;
182 		}
183 		if (i == sd->maxaliases - 2) {
184 			sd->maxaliases *= 2;
185 			q = realloc(sd->aliases, sd->maxaliases * sizeof(*q));
186 			if (q == NULL) {
187 				oerrno = errno;
188 				endservent_r(sd);
189 				errno = oerrno;
190 				return NULL;
191 			}
192 			sp->s_aliases = sd->aliases = q;
193 		}
194 		sp->s_aliases[i++] = cp;
195 		cp = strpbrk(cp, " \t");
196 		if (cp != NULL)
197 			*cp++ = '\0';
198 	}
199 	sp->s_aliases[i] = NULL;
200 	return sp;
201 }
202 
203 void
204 setservent_r(int f, struct servent_data *sd)
205 {
206 	(void)_servent_open(sd);
207 	sd->flags |= f ? _SV_STAYOPEN : 0;
208 }
209 
210 void
211 endservent_r(struct servent_data *sd)
212 {
213 	_servent_close(sd);
214 	free(sd->aliases);
215 	sd->aliases = NULL;
216 	sd->maxaliases = 0;
217 	free(sd->line);
218 	sd->line = NULL;
219 	free(sd->cdb_buf);
220 	sd->cdb_buf = NULL;
221 	sd->cdb_buf_len = 0;
222 }
223 
224 struct servent *
225 getservent_r(struct servent *sp, struct servent_data *sd)
226 {
227 
228 	if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0 &&
229 	    _servent_open(sd) == -1)
230 		return NULL;
231 
232 #if 0
233 	if (sd->flags & _SV_CDB) {
234 		const void *data;
235 		size_t len;
236 
237 		if (sd->flags & _SV_FIRST) {
238 			sd->cdb_index = 0;
239 			sd->flags &= ~_SV_FIRST;
240 		}
241 
242 		if (cdbr_get(sd->cdb, sd->cdb_index, &data, &len))
243 			return NULL;
244 		++sd->cdb_index;
245 		return _servent_parsedb(sd, sp, data, len);
246 	}
247 #endif
248 	if (sd->flags & _SV_PLAINFILE) {
249 		for (;;) {
250 			if (_servent_getline(sd) == -1)
251 				return NULL;
252 			if (_servent_parseline(sd, sp) == NULL)
253 				continue;
254 			return sp;
255 		}
256 	}
257 	return NULL;
258 }
259 
260 struct servent *
261 _servent_parsedb(struct servent_data *sd, struct servent *sp,
262     const uint8_t *data, size_t len)
263 {
264 	char **q;
265 	size_t i;
266 	int oerrno;
267 
268 	if ((sd->flags & _SV_STAYOPEN) == 0) {
269 		if (len > sd->cdb_buf_len) {
270 			void *tmp = realloc(sd->cdb_buf, len);
271 			if (tmp == NULL)
272 				goto fail;
273 			sd->cdb_buf = tmp;
274 			sd->cdb_buf_len = len;
275 		}
276 		memcpy(sd->cdb_buf, data, len);
277 		data = sd->cdb_buf;
278 	}
279 
280 	if (len < 2)
281 		goto fail;
282 	sp->s_port = *(uint16_t*)data;
283 	data += 2;
284 	len -= 2;
285 
286 	if (len == 0 || len < (size_t)data[0] + 2)
287 		goto fail;
288 	sp->s_proto = __UNCONST(data + 1);
289 
290 	if (sp->s_proto[data[0]] != '\0')
291 		goto fail;
292 
293 	len -= 2 + data[0];
294 	data += 2 + data[0];
295 
296 	if (len == 0)
297 		goto fail;
298 	if (len < (size_t)data[0] + 2)
299 		goto fail;
300 
301 	sp->s_name = __UNCONST(data + 1);
302 	len -= 2 + data[0];
303 	data += 2 + data[0];
304 
305 	if (sd->aliases == NULL) {
306 		sd->maxaliases = 10;
307 		sd->aliases = malloc(sd->maxaliases * sizeof(char *));
308 		if (sd->aliases == NULL)
309 			goto fail;
310 	}
311 	sp->s_aliases = sd->aliases;
312 	i = 0;
313 	while (len) {
314 		if (len < (size_t)data[0] + 2)
315 			goto fail;
316 		if (i == sd->maxaliases - 2) {
317 			sd->maxaliases *= 2;
318 			q = realloc(sd->aliases, sd->maxaliases * sizeof(*q));
319 			if (q == NULL)
320 				goto fail;
321 			sp->s_aliases = sd->aliases = q;
322 		}
323 		sp->s_aliases[i++] = __UNCONST(data + 1);
324 		len -= 2 + data[0];
325 		data += 2 + data[0];
326 	}
327 	sp->s_aliases[i] = NULL;
328 	return sp;
329 
330 fail:
331 	oerrno = errno;
332 	endservent_r(sd);
333 	errno = oerrno;
334 	return NULL;
335 }
336 
337