]> sourceware.org Git - glibc.git/blob - nss/getXXent_r.c
Update.
[glibc.git] / nss / getXXent_r.c
1 /* Copyright (C) 1996,97,98,99,2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20 #include <errno.h>
21 #include <bits/libc-lock.h>
22
23 #include "nsswitch.h"
24
25 #ifdef NEED__RES
26 # include <resolv.h>
27 #endif
28
29 /*******************************************************************\
30 |* Here we assume several symbols to be defined: *|
31 |* *|
32 |* LOOKUP_TYPE - the return type of the function *|
33 |* *|
34 |* SETFUNC_NAME - name of the non-reentrant setXXXent function *|
35 |* *|
36 |* GETFUNC_NAME - name of the non-reentrant getXXXent function *|
37 |* *|
38 |* ENDFUNC_NAME - name of the non-reentrant endXXXent function *|
39 |* *|
40 |* DATABASE_NAME - name of the database the function accesses *|
41 |* (e.g., host, services, ...) *|
42 |* *|
43 |* Optionally the following vars can be defined: *|
44 |* *|
45 |* STAYOPEN - variable declaration for setXXXent function *|
46 |* *|
47 |* STAYOPEN_VAR - variable name for setXXXent function *|
48 |* *|
49 |* NEED_H_ERRNO - an extra parameter will be passed to point to *|
50 |* the global `h_errno' variable. *|
51 |* *|
52 \*******************************************************************/
53
54 /* To make the real sources a bit prettier. */
55 #define REENTRANT_GETNAME APPEND_R (GETFUNC_NAME)
56 #define APPEND_R(Name) CONCAT2_2 (Name, _r)
57 #define INTERNAL(Name) CONCAT2_2 (__, Name)
58 #define CONCAT2_1(Pre, Post) CONCAT2_2 (Pre, Post)
59 #define CONCAT2_2(Pre, Post) Pre##Post
60
61 #define SETFUNC_NAME_STRING STRINGIZE (SETFUNC_NAME)
62 #define GETFUNC_NAME_STRING STRINGIZE (REENTRANT_GETNAME)
63 #define ENDFUNC_NAME_STRING STRINGIZE (ENDFUNC_NAME)
64 #define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
65 #define STRINGIZE(Name) STRINGIZE1 (Name)
66 #define STRINGIZE1(Name) #Name
67
68 #define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
69 #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
70 #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
71
72 /* Sometimes we need to store error codes in the `h_errno' variable. */
73 #ifdef NEED_H_ERRNO
74 # define H_ERRNO_PARM , int *h_errnop
75 # define H_ERRNO_VAR , &h_errno
76 #else
77 # define H_ERRNO_PARM
78 # define H_ERRNO_VAR
79 #endif
80
81 /* Some databases take the `stayopen' flag. */
82 #ifdef STAYOPEN
83 # define STAYOPEN_TMP CONCAT2_1 (STAYOPEN, _tmp)
84 # define STAYOPEN_TMPVAR CONCAT2_1 (STAYOPEN_VAR, _tmp)
85 #else
86 # define STAYOPEN void
87 # define STAYOPEN_VAR
88 # define STAYOPEN_TMPVAR
89 #endif
90
91 /* Prototype for the setXXXent functions we use here. */
92 typedef enum nss_status (*set_function) (STAYOPEN);
93
94 /* Prototype for the endXXXent functions we use here. */
95 typedef enum nss_status (*end_function) (void);
96
97 /* Prototype for the setXXXent functions we use here. */
98 typedef enum nss_status (*get_function) (LOOKUP_TYPE *, char *, size_t, int *
99 H_ERRNO_PARM);
100
101
102 /* This handle for the NSS data base is shared between all
103 set/get/endXXXent functions. */
104 static service_user *nip;
105 /* Remember the last service used since the last call to `endXXent'. */
106 static service_user *last_nip;
107 /* Remember the first service_entry, it's always the same. */
108 static service_user *startp;
109
110 #ifdef STAYOPEN_TMP
111 /* We need to remember the last `stayopen' flag given by the user
112 since the `setent' function is only called for the first available
113 service. */
114 static STAYOPEN_TMP;
115 #endif
116
117 /* Protect above variable against multiple uses at the same time. */
118 __libc_lock_define_initialized (static, lock)
119
120 /* The lookup function for the first entry of this service. */
121 extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp);
122
123 /* Set up NIP to run through the services. If ALL is zero, use NIP's
124 current location if it's not nil. Return nonzero if there are no
125 services (left). */
126 static enum nss_status
127 setup (void **fctp, const char *func_name, int all)
128 {
129 int no_more;
130 if (startp == NULL)
131 {
132 no_more = DB_LOOKUP_FCT (&nip, func_name, fctp);
133 startp = no_more ? (service_user *) -1l : nip;
134 }
135 else if (startp == (service_user *) -1l)
136 /* No services at all. */
137 return 1;
138 else
139 {
140 if (all || !nip)
141 /* Reset to the beginning of the service list. */
142 nip = startp;
143 /* Look up the first function. */
144 no_more = __nss_lookup (&nip, func_name, fctp);
145 }
146 return no_more;
147 }
148 \f
149 void
150 SETFUNC_NAME (STAYOPEN)
151 {
152 set_function fct;
153 int no_more;
154
155 #ifdef NEED__RES
156 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
157 {
158 __set_h_errno (NETDB_INTERNAL);
159 return;
160 }
161 #endif /* need _res */
162
163 __libc_lock_lock (lock);
164
165 /* Cycle through the services and run their `setXXent' functions until
166 we find an available service. */
167 no_more = setup ((void **) &fct, SETFUNC_NAME_STRING, 1);
168 while (! no_more)
169 {
170 int is_last_nip = nip == last_nip;
171 enum nss_status status = DL_CALL_FCT (fct, (STAYOPEN_VAR));
172
173 no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct,
174 status, 0);
175 if (is_last_nip)
176 last_nip = nip;
177 }
178
179 #ifdef STAYOPEN_TMP
180 STAYOPEN_TMPVAR = STAYOPEN_VAR;
181 #endif
182
183 __libc_lock_unlock (lock);
184 }
185
186
187 void
188 ENDFUNC_NAME (void)
189 {
190 end_function fct;
191 int no_more;
192
193 #ifdef NEED__RES
194 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
195 {
196 __set_h_errno (NETDB_INTERNAL);
197 return;
198 }
199 #endif /* need _res */
200
201 __libc_lock_lock (lock);
202
203 /* Cycle through all the services and run their endXXent functions. */
204 no_more = setup ((void **) &fct, ENDFUNC_NAME_STRING, 1);
205 while (! no_more)
206 {
207 /* Ignore status, we force check in __NSS_NEXT. */
208 DL_CALL_FCT (fct, ());
209
210 if (nip == last_nip)
211 /* We have processed all services which were used. */
212 break;
213
214 no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1);
215 }
216 last_nip = nip = NULL;
217
218 __libc_lock_unlock (lock);
219 }
220
221
222 int
223 INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen,
224 LOOKUP_TYPE **result H_ERRNO_PARM)
225 {
226 get_function fct;
227 int no_more;
228 enum nss_status status;
229
230 #ifdef NEED__RES
231 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
232 {
233 __set_h_errno (NETDB_INTERNAL);
234 *result = NULL;
235 return errno;
236 }
237 #endif /* need _res */
238
239 /* Initialize status to return if no more functions are found. */
240 status = NSS_STATUS_NOTFOUND;
241
242 __libc_lock_lock (lock);
243
244 /* Run through available functions, starting with the same function last
245 run. We will repeat each function as long as it succeeds, and then go
246 on to the next service action. */
247 no_more = setup ((void **) &fct, GETFUNC_NAME_STRING, 0);
248 while (! no_more)
249 {
250 int is_last_nip = nip == last_nip;
251
252 status = DL_CALL_FCT (fct,
253 (resbuf, buffer, buflen, &errno H_ERRNO_VAR));
254
255 /* The the status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
256 provided buffer is too small. In this case we should give
257 the user the possibility to enlarge the buffer and we should
258 not simply go on with the next service (even if the TRYAGAIN
259 action tells us so). */
260 if (status == NSS_STATUS_TRYAGAIN
261 #ifdef NEED_H_ERRNO
262 && *h_errnop == NETDB_INTERNAL
263 #endif
264 && errno == ERANGE)
265 break;
266
267 do
268 {
269 no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct,
270 status, 0);
271
272 if (is_last_nip)
273 last_nip = nip;
274
275 if (! no_more)
276 {
277 /* Call the `setXXent' function. This wasn't done before. */
278 set_function sfct;
279
280 no_more = __nss_lookup (&nip, SETFUNC_NAME_STRING,
281 (void **) &sfct);
282
283 if (! no_more)
284 status = DL_CALL_FCT (sfct, (STAYOPEN_TMPVAR));
285 else
286 status = NSS_STATUS_NOTFOUND;
287 }
288 }
289 while (! no_more && status != NSS_STATUS_SUCCESS);
290 }
291
292 __libc_lock_unlock (lock);
293
294 *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
295 return status == NSS_STATUS_SUCCESS ? 0 : errno;
296 }
297
298
299 #include <shlib-compat.h>
300 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1_2)
301 #define OLD(name) OLD1 (name)
302 #define OLD1(name) __old_##name
303
304 int
305 OLD (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen,
306 LOOKUP_TYPE **result H_ERRNO_PARM)
307 {
308 int ret = INTERNAL (REENTRANT_GETNAME) (resbuf, buffer, buflen,
309 result H_ERRNO_VAR);
310
311 if (ret != 0)
312 ret = -1;
313
314 return ret;
315 }
316
317 #define do_symbol_version(real, name, version) \
318 compat_symbol (libc, real, name, version)
319 do_symbol_version (OLD (REENTRANT_GETNAME), REENTRANT_GETNAME, GLIBC_2_0);
320
321 #define do_default_symbol_version(real, name, version) \
322 versioned_symbol (libc, real, name, version)
323 do_default_symbol_version (INTERNAL (REENTRANT_GETNAME),
324 REENTRANT_GETNAME, GLIBC_2_1_2);
325 #else
326 #define do_weak_alias(n1, n2) weak_alias (n1, n2)
327 do_weak_alias (INTERNAL (REENTRANT_GETNAME), REENTRANT_GETNAME)
328 #endif
This page took 0.063806 seconds and 5 git commands to generate.