1/*	$NetBSD: getnetgrent_r.c,v 1.1.1.2 2012/09/09 16:07:57 christos Exp $	*/
2
3/*
4 * Copyright (C) 2004, 2005, 2008  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998, 1999, 2001, 2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or 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 WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] = "Id: getnetgrent_r.c,v 1.14 2008/11/14 02:36:51 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 getnetgrent_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 <stdlib.h>
35#include <port_after.h>
36
37#ifdef NGR_R_RETURN
38#ifndef NGR_R_PRIVATE
39#define NGR_R_PRIVATE 0
40#endif
41
42static NGR_R_RETURN
43copy_protoent(NGR_R_CONST char **, NGR_R_CONST char **, NGR_R_CONST char **,
44	      const char *, const char *, const char *, NGR_R_COPY_ARGS);
45
46NGR_R_RETURN
47innetgr_r(const char *netgroup, const char *host, const char *user,
48	  const char *domain) {
49	char *ng, *ho, *us, *dom;
50
51	DE_CONST(netgroup, ng);
52	DE_CONST(host, ho);
53	DE_CONST(user, us);
54	DE_CONST(domain, dom);
55
56	return (innetgr(ng, ho, us, dom));
57}
58
59/*%
60 *	These assume a single context is in operation per thread.
61 *	If this is not the case we will need to call irs directly
62 *	rather than through the base functions.
63 */
64
65NGR_R_RETURN
66getnetgrent_r(NGR_R_CONST char **machinep, NGR_R_CONST char **userp,
67	      NGR_R_CONST char **domainp, NGR_R_ARGS)
68{
69	NGR_R_CONST char *mp, *up, *dp;
70	int res = getnetgrent(&mp, &up, &dp);
71
72	if (res != 1)
73		return (res);
74
75	return (copy_protoent(machinep, userp, domainp,
76				mp, up, dp, NGR_R_COPY));
77}
78
79#if NGR_R_PRIVATE == 2
80struct private {
81	char *buf;
82};
83
84#endif
85NGR_R_SET_RETURN
86#ifdef NGR_R_SET_ARGS
87setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS)
88#else
89setnetgrent_r(NGR_R_SET_CONST char *netgroup)
90#endif
91{
92#if NGR_R_PRIVATE == 2
93	struct private *p;
94#endif
95	char *tmp;
96#if defined(NGR_R_SET_ARGS) && NGR_R_PRIVATE == 0
97	UNUSED(buf);
98	UNUSED(buflen);
99#endif
100
101	DE_CONST(netgroup, tmp);
102	setnetgrent(tmp);
103
104#if NGR_R_PRIVATE == 1
105	*buf = NULL;
106#elif NGR_R_PRIVATE == 2
107	*buf = p = malloc(sizeof(struct private));
108	if (p == NULL)
109#ifdef NGR_R_SET_RESULT
110		return (NGR_R_BAD);
111#else
112		return;
113#endif
114	p->buf = NULL;
115#endif
116#ifdef NGR_R_SET_RESULT
117	return (NGR_R_SET_RESULT);
118#endif
119}
120
121NGR_R_END_RETURN
122#ifdef NGR_R_END_ARGS
123endnetgrent_r(NGR_R_END_ARGS)
124#else
125endnetgrent_r(void)
126#endif
127{
128#if NGR_R_PRIVATE == 2
129	struct private *p = buf;
130#endif
131#if defined(NGR_R_SET_ARGS) && NGR_R_PRIVATE == 0
132	UNUSED(buf);
133	UNUSED(buflen);
134#endif
135
136	endnetgrent();
137#if NGR_R_PRIVATE == 1
138	if (*buf != NULL)
139		free(*buf);
140	*buf = NULL;
141#elif NGR_R_PRIVATE == 2
142	if (p->buf != NULL)
143		free(p->buf);
144	free(p);
145#endif
146	NGR_R_END_RESULT(NGR_R_OK);
147}
148
149/* Private */
150
151static int
152copy_protoent(NGR_R_CONST char **machinep, NGR_R_CONST char **userp,
153	      NGR_R_CONST char **domainp, const char *mp, const char *up,
154	      const char *dp, NGR_R_COPY_ARGS)
155{
156#if NGR_R_PRIVATE == 2
157	struct private *p = buf;
158#endif
159	char *cp;
160	int n;
161	int len;
162
163	/* Find out the amount of space required to store the answer. */
164	len = 0;
165	if (mp != NULL) len += strlen(mp) + 1;
166	if (up != NULL) len += strlen(up) + 1;
167	if (dp != NULL) len += strlen(dp) + 1;
168
169#if NGR_R_PRIVATE == 1
170	if (*buf != NULL)
171		free(*buf);
172	*buf = malloc(len);
173	if (*buf == NULL)
174		return(NGR_R_BAD);
175	cp = *buf;
176#elif NGR_R_PRIVATE == 2
177	if (p->buf)
178		free(p->buf);
179	p->buf = malloc(len);
180	if (p->buf == NULL)
181		return(NGR_R_BAD);
182	cp = p->buf;
183#else
184	if (len > (int)buflen) {
185		errno = ERANGE;
186		return (NGR_R_BAD);
187	}
188	cp = buf;
189#endif
190
191	if (mp != NULL) {
192		n = strlen(mp) + 1;
193		strcpy(cp, mp);
194		*machinep = cp;
195		cp += n;
196	} else
197		*machinep = NULL;
198
199	if (up != NULL) {
200		n = strlen(up) + 1;
201		strcpy(cp, up);
202		*userp = cp;
203		cp += n;
204	} else
205		*userp = NULL;
206
207	if (dp != NULL) {
208		n = strlen(dp) + 1;
209		strcpy(cp, dp);
210		*domainp = cp;
211		cp += n;
212	} else
213		*domainp = NULL;
214
215	return (NGR_R_OK);
216}
217#else /* NGR_R_RETURN */
218	static int getnetgrent_r_unknown_system = 0;
219#endif /* NGR_R_RETURN */
220#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */
221/*! \file */
222