1 /*	$NetBSD: getservent_r.c,v 1.1.1.1 2009/04/12 15:33:44 christos Exp $	*/
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)
21 static 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 
39 static SERV_R_RETURN
40 copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS);
41 
42 SERV_R_RETURN
43 getservbyname_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 
63 SERV_R_RETURN
64 getservbyport_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 
90 SERV_R_RETURN
91 getservent_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 
110 SERV_R_SET_RETURN
111 #ifdef SERV_R_ENT_ARGS
112 setservent_r(int stay_open, SERV_R_ENT_ARGS)
113 #else
114 setservent_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 
126 SERV_R_END_RETURN
127 #ifdef SERV_R_ENT_ARGS
128 endservent_r(SERV_R_ENT_ARGS)
129 #else
130 endservent_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
143 static SERV_R_RETURN
144 copy_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 */
194 static int
195 copy_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