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: getprotoent_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 getprotoent_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 <port_after.h>
35
36#ifdef PROTO_R_RETURN
37
38static PROTO_R_RETURN
39copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS);
40
41PROTO_R_RETURN
42getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) {
43	struct protoent *pe = getprotobyname(name);
44#ifdef PROTO_R_SETANSWER
45	int n = 0;
46
47	if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
48		*answerp = NULL;
49	else
50		*answerp = pptr;
51
52	return (n);
53#else
54	if (pe == NULL)
55		return (PROTO_R_BAD);
56
57	return (copy_protoent(pe, pptr, PROTO_R_COPY));
58#endif
59}
60
61PROTO_R_RETURN
62getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) {
63	struct protoent *pe = getprotobynumber(proto);
64#ifdef PROTO_R_SETANSWER
65	int n = 0;
66
67	if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
68		*answerp = NULL;
69	else
70		*answerp = pptr;
71
72	return (n);
73#else
74	if (pe == NULL)
75		return (PROTO_R_BAD);
76
77	return (copy_protoent(pe, pptr, PROTO_R_COPY));
78#endif
79}
80
81/*%
82 *	These assume a single context is in operation per thread.
83 *	If this is not the case we will need to call irs directly
84 *	rather than through the base functions.
85 */
86
87PROTO_R_RETURN
88getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) {
89	struct protoent *pe = getprotoent();
90#ifdef PROTO_R_SETANSWER
91	int n = 0;
92
93	if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0)
94		*answerp = NULL;
95	else
96		*answerp = pptr;
97
98	return (n);
99#else
100	if (pe == NULL)
101		return (PROTO_R_BAD);
102
103	return (copy_protoent(pe, pptr, PROTO_R_COPY));
104#endif
105}
106
107PROTO_R_SET_RETURN
108#ifdef PROTO_R_ENT_ARGS
109setprotoent_r(int stay_open, PROTO_R_ENT_ARGS)
110#else
111setprotoent_r(int stay_open)
112#endif
113{
114#ifdef PROTO_R_ENT_UNUSED
115        PROTO_R_ENT_UNUSED;
116#endif
117	setprotoent(stay_open);
118#ifdef PROTO_R_SET_RESULT
119	return (PROTO_R_SET_RESULT);
120#endif
121}
122
123PROTO_R_END_RETURN
124#ifdef PROTO_R_ENT_ARGS
125endprotoent_r(PROTO_R_ENT_ARGS)
126#else
127endprotoent_r()
128#endif
129{
130#ifdef PROTO_R_ENT_UNUSED
131        PROTO_R_ENT_UNUSED;
132#endif
133	endprotoent();
134	PROTO_R_END_RESULT(PROTO_R_OK);
135}
136
137/* Private */
138
139#ifndef PROTOENT_DATA
140static PROTO_R_RETURN
141copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) {
142	char *cp;
143	int i, n;
144	int numptr, len;
145
146	/* Find out the amount of space required to store the answer. */
147	numptr = 1; /*%< NULL ptr */
148	len = (char *)ALIGN(buf) - buf;
149	for (i = 0; pe->p_aliases[i]; i++, numptr++) {
150		len += strlen(pe->p_aliases[i]) + 1;
151	}
152	len += strlen(pe->p_name) + 1;
153	len += numptr * sizeof(char*);
154
155	if (len > (int)buflen) {
156		errno = ERANGE;
157		return (PROTO_R_BAD);
158	}
159
160	/* copy protocol value*/
161	pptr->p_proto = pe->p_proto;
162
163	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
164
165	/* copy official name */
166	n = strlen(pe->p_name) + 1;
167	strcpy(cp, pe->p_name);
168	pptr->p_name = cp;
169	cp += n;
170
171	/* copy aliases */
172	pptr->p_aliases = (char **)ALIGN(buf);
173	for (i = 0 ; pe->p_aliases[i]; i++) {
174		n = strlen(pe->p_aliases[i]) + 1;
175		strcpy(cp, pe->p_aliases[i]);
176		pptr->p_aliases[i] = cp;
177		cp += n;
178	}
179	pptr->p_aliases[i] = NULL;
180
181	return (PROTO_R_OK);
182}
183#else /* !PROTOENT_DATA */
184static int
185copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) {
186	char *cp, *eob;
187	int i, n;
188
189	/* copy protocol value */
190	pptr->p_proto = pe->p_proto;
191
192	/* copy official name */
193	cp = pdptr->line;
194	eob = pdptr->line + sizeof(pdptr->line);
195	if ((n = strlen(pe->p_name) + 1) < (eob - cp)) {
196		strcpy(cp, pe->p_name);
197		pptr->p_name = cp;
198		cp += n;
199	} else {
200		return (-1);
201	}
202
203	/* copy aliases */
204	i = 0;
205	pptr->p_aliases = pdptr->proto_aliases;
206	while (pe->p_aliases[i] && i < (_MAXALIASES-1)) {
207		if ((n = strlen(pe->p_aliases[i]) + 1) < (eob - cp)) {
208			strcpy(cp, pe->p_aliases[i]);
209			pptr->p_aliases[i] = cp;
210			cp += n;
211		} else {
212			break;
213		}
214		i++;
215	}
216	pptr->p_aliases[i] = NULL;
217
218	return (PROTO_R_OK);
219}
220#endif /* PROTOENT_DATA */
221#else /* PROTO_R_RETURN */
222	static int getprotoent_r_unknown_system = 0;
223#endif /* PROTO_R_RETURN */
224#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
225/*! \file */
226