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