1/*	$NetBSD$	*/
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1998-1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] = "Id: getservent_r.c,v 1.6 2006/08/01 01:14:16 marka Exp ";
22#endif /* LIBC_SCCS and not lint */
23
24#include <port_before.h>
25#if !defined(_REENTRANT) || !defined(DO_PTHREADS)
26	static int getservent_r_not_required = 0;
27#else
28#include <errno.h>
29#include <string.h>
30#include <stdio.h>
31#include <sys/types.h>
32#include <netinet/in.h>
33#include <netdb.h>
34#include <sys/param.h>
35#include <port_after.h>
36
37#ifdef SERV_R_RETURN
38
39static SERV_R_RETURN
40copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS);
41
42SERV_R_RETURN
43getservbyname_r(const char *name, const char *proto,
44		struct servent *sptr, SERV_R_ARGS) {
45	struct servent *se = getservbyname(name, proto);
46#ifdef SERV_R_SETANSWER
47	int n = 0;
48
49	if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
50		*answerp = NULL;
51	else
52		*answerp = sptr;
53
54	return (n);
55#else
56	if (se == NULL)
57		return (SERV_R_BAD);
58
59	return (copy_servent(se, sptr, SERV_R_COPY));
60#endif
61}
62
63SERV_R_RETURN
64getservbyport_r(int port, const char *proto,
65		struct servent *sptr, SERV_R_ARGS) {
66	struct servent *se = getservbyport(port, proto);
67#ifdef SERV_R_SETANSWER
68	int n = 0;
69
70	if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
71		*answerp = NULL;
72	else
73		*answerp = sptr;
74
75	return (n);
76#else
77	if (se == NULL)
78		return (SERV_R_BAD);
79
80	return (copy_servent(se, sptr, SERV_R_COPY));
81#endif
82}
83
84/*%
85 *	These assume a single context is in operation per thread.
86 *	If this is not the case we will need to call irs directly
87 *	rather than through the base functions.
88 */
89
90SERV_R_RETURN
91getservent_r(struct servent *sptr, SERV_R_ARGS) {
92	struct servent *se = getservent();
93#ifdef SERV_R_SETANSWER
94	int n = 0;
95
96	if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0)
97		*answerp = NULL;
98	else
99		*answerp = sptr;
100
101	return (n);
102#else
103	if (se == NULL)
104		return (SERV_R_BAD);
105
106	return (copy_servent(se, sptr, SERV_R_COPY));
107#endif
108}
109
110SERV_R_SET_RETURN
111#ifdef SERV_R_ENT_ARGS
112setservent_r(int stay_open, SERV_R_ENT_ARGS)
113#else
114setservent_r(int stay_open)
115#endif
116{
117#ifdef SERV_R_ENT_UNUSED
118	SERV_R_ENT_UNUSED;
119#endif
120	setservent(stay_open);
121#ifdef SERV_R_SET_RESULT
122	return (SERV_R_SET_RESULT);
123#endif
124}
125
126SERV_R_END_RETURN
127#ifdef SERV_R_ENT_ARGS
128endservent_r(SERV_R_ENT_ARGS)
129#else
130endservent_r()
131#endif
132{
133#ifdef SERV_R_ENT_UNUSED
134	SERV_R_ENT_UNUSED;
135#endif
136	endservent();
137	SERV_R_END_RESULT(SERV_R_OK);
138}
139
140/* Private */
141
142#ifndef SERVENT_DATA
143static SERV_R_RETURN
144copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) {
145	char *cp;
146	int i, n;
147	int numptr, len;
148
149	/* Find out the amount of space required to store the answer. */
150	numptr = 1; /*%< NULL ptr */
151	len = (char *)ALIGN(buf) - buf;
152	for (i = 0; se->s_aliases[i]; i++, numptr++) {
153		len += strlen(se->s_aliases[i]) + 1;
154	}
155	len += strlen(se->s_name) + 1;
156	len += strlen(se->s_proto) + 1;
157	len += numptr * sizeof(char*);
158
159	if (len > (int)buflen) {
160		errno = ERANGE;
161		return (SERV_R_BAD);
162	}
163
164	/* copy port value */
165	sptr->s_port = se->s_port;
166
167	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
168
169	/* copy official name */
170	n = strlen(se->s_name) + 1;
171	strcpy(cp, se->s_name);
172	sptr->s_name = cp;
173	cp += n;
174
175	/* copy aliases */
176	sptr->s_aliases = (char **)ALIGN(buf);
177	for (i = 0 ; se->s_aliases[i]; i++) {
178		n = strlen(se->s_aliases[i]) + 1;
179		strcpy(cp, se->s_aliases[i]);
180		sptr->s_aliases[i] = cp;
181		cp += n;
182	}
183	sptr->s_aliases[i] = NULL;
184
185	/* copy proto */
186	n = strlen(se->s_proto) + 1;
187	strcpy(cp, se->s_proto);
188	sptr->s_proto = cp;
189	cp += n;
190
191	return (SERV_R_OK);
192}
193#else /* !SERVENT_DATA */
194static int
195copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) {
196	char *cp, *eob;
197	int i, n;
198
199	/* copy port value */
200	sptr->s_port = se->s_port;
201
202	/* copy official name */
203	cp = sdptr->line;
204	eob = sdptr->line + sizeof(sdptr->line);
205	if ((n = strlen(se->s_name) + 1) < (eob - cp)) {
206		strcpy(cp, se->s_name);
207		sptr->s_name = cp;
208		cp += n;
209	} else {
210		return (-1);
211	}
212
213	/* copy aliases */
214	i = 0;
215	sptr->s_aliases = sdptr->serv_aliases;
216	while (se->s_aliases[i] && i < (_MAXALIASES-1)) {
217		if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) {
218			strcpy(cp, se->s_aliases[i]);
219			sptr->s_aliases[i] = cp;
220			cp += n;
221		} else {
222			break;
223		}
224		i++;
225	}
226	sptr->s_aliases[i] = NULL;
227
228	/* copy proto */
229	if ((n = strlen(se->s_proto) + 1) < (eob - cp)) {
230		strcpy(cp, se->s_proto);
231		sptr->s_proto = cp;
232		cp += n;
233	} else {
234		return (-1);
235	}
236
237	return (SERV_R_OK);
238}
239#endif /* !SERVENT_DATA */
240#else /*SERV_R_RETURN */
241	static int getservent_r_unknown_system = 0;
242#endif /*SERV_R_RETURN */
243#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
244/*! \file */
245