]> git.ipfire.org Git - thirdparty/glibc.git/blob - nss/getXXbyYY_r.c
8358e2f71d252599f3dda0926506c35de6b64b66
[thirdparty/glibc.git] / nss / getXXbyYY_r.c
1 /* Copyright (C) 1996,97,98,99,2000,2001,2002 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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <assert.h>
21 #include <errno.h>
22 #include "nsswitch.h"
23 #ifdef USE_NSCD
24 # include <nscd/nscd_proto.h>
25 #endif
26 #ifdef NEED__RES_HCONF
27 # include <resolv/res_hconf.h>
28 #endif
29 #ifdef NEED__RES
30 # include <resolv.h>
31 #endif
32 /*******************************************************************\
33 |* Here we assume several symbols to be defined: *|
34 |* *|
35 |* LOOKUP_TYPE - the return type of the function *|
36 |* *|
37 |* FUNCTION_NAME - name of the non-reentrant function *|
38 |* *|
39 |* DATABASE_NAME - name of the database the function accesses *|
40 |* (e.g., host, services, ...) *|
41 |* *|
42 |* ADD_PARAMS - additional parameter, can vary in number *|
43 |* *|
44 |* ADD_VARIABLES - names of additional parameter *|
45 |* *|
46 |* Optionally the following vars can be defined: *|
47 |* *|
48 |* NEED_H_ERRNO - an extra parameter will be passed to point to *|
49 |* the global `h_errno' variable. *|
50 |* *|
51 |* NEED__RES - the global _res variable might be used so we *|
52 |* will have to initialize it if necessary *|
53 |* *|
54 |* PREPROCESS - code run before anything else *|
55 |* *|
56 |* POSTPROCESS - code run after the lookup *|
57 |* *|
58 \*******************************************************************/
59
60 /* To make the real sources a bit prettier. */
61 #define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
62 #define APPEND_R(name) APPEND_R1 (name)
63 #define APPEND_R1(name) name##_r
64 #define INTERNAL(name) INTERNAL1 (name)
65 #define INTERNAL1(name) __##name
66 #define NEW(name) NEW1 (name)
67 #define NEW1(name) __new_##name
68
69 #ifdef USE_NSCD
70 # define NSCD_NAME ADD_NSCD (REENTRANT_NAME)
71 # define ADD_NSCD(name) ADD_NSCD1 (name)
72 # define ADD_NSCD1(name) __nscd_##name
73 # define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
74 # define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
75 # define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
76 #endif
77
78 #define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
79 #define REENTRANT_NAME_STRING STRINGIZE (REENTRANT_NAME)
80 #define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
81 #define STRINGIZE(name) STRINGIZE1 (name)
82 #define STRINGIZE1(name) #name
83
84 #ifndef DB_LOOKUP_FCT
85 # define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
86 # define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
87 # define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
88 #endif
89
90 /* Sometimes we need to store error codes in the `h_errno' variable. */
91 #ifdef NEED_H_ERRNO
92 # define H_ERRNO_PARM , int *h_errnop
93 # define H_ERRNO_VAR , h_errnop
94 # define H_ERRNO_VAR_P h_errnop
95 #else
96 # define H_ERRNO_PARM
97 # define H_ERRNO_VAR
98 # define H_ERRNO_VAR_P NULL
99 #endif
100
101 #ifndef HAVE_TYPE
102 # define TYPE_VAR_P NULL
103 # define FLAGS_VAR 0
104 #endif
105
106 #ifdef HAVE_AF
107 # define AF_VAR_P &af
108 #else
109 # define AF_VAR_P NULL
110 #endif
111
112 /* Type of the lookup function we need here. */
113 typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
114 size_t, int * H_ERRNO_PARM);
115
116 /* The lookup function for the first entry of this service. */
117 extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp)
118 internal_function;
119 libc_hidden_proto (DB_LOOKUP_FCT)
120
121 /* Interval in which we transfer retry to contact the NSCD. */
122 #define NSS_NSCD_RETRY 100
123
124
125 int
126 INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
127 size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
128 {
129 static service_user *startp;
130 static lookup_function start_fct;
131 service_user *nip;
132 lookup_function fct;
133 int no_more;
134 enum nss_status status = NSS_STATUS_UNAVAIL;
135 #ifdef USE_NSCD
136 int nscd_status;
137 #endif
138
139 #ifdef PREPROCESS
140 PREPROCESS;
141 #endif
142
143 #ifdef HANDLE_DIGITS_DOTS
144 switch (__nss_hostname_digits_dots (name, resbuf, &buffer, NULL,
145 buflen, result, &status,
146 TYPE_VAR_P, FLAGS_VAR, AF_VAR_P,
147 H_ERRNO_VAR_P))
148 {
149 case -1:
150 return errno;
151 case 1:
152 goto done;
153 }
154 #endif
155
156 #ifdef USE_NSCD
157 if (NOT_USENSCD_NAME && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
158 NOT_USENSCD_NAME = 0;
159
160 if (!NOT_USENSCD_NAME)
161 {
162 nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen
163 H_ERRNO_VAR);
164 if (nscd_status >= 0)
165 {
166 *result = nscd_status == 0 ? resbuf : NULL;
167 return nscd_status;
168 }
169 }
170 #endif
171
172 if (startp == NULL)
173 {
174 no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, (void **) &fct);
175 if (no_more)
176 startp = (service_user *) -1l;
177 else
178 {
179 startp = nip;
180 start_fct = fct;
181
182 #ifdef NEED__RES
183 /* The resolver code will really be used so we have to
184 initialize it. */
185 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
186 {
187 *h_errnop = NETDB_INTERNAL;
188 *result = NULL;
189 return errno;
190 }
191 #endif /* need _res */
192 #ifdef NEED__RES_HCONF
193 if (!_res_hconf.initialized)
194 _res_hconf_init ();
195 #endif /* need _res_hconf */
196 }
197 }
198 else
199 {
200 fct = start_fct;
201 no_more = (nip = startp) == (service_user *) -1l;
202 }
203
204 while (no_more == 0)
205 {
206 status = DL_CALL_FCT (fct, (ADD_VARIABLES, resbuf, buffer, buflen,
207 &errno H_ERRNO_VAR));
208
209 /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
210 provided buffer is too small. In this case we should give
211 the user the possibility to enlarge the buffer and we should
212 not simply go on with the next service (even if the TRYAGAIN
213 action tells us so). */
214 if (status == NSS_STATUS_TRYAGAIN
215 #ifdef NEED_H_ERRNO
216 && *h_errnop == NETDB_INTERNAL
217 #endif
218 && errno == ERANGE)
219 break;
220
221 no_more = __nss_next (&nip, REENTRANT_NAME_STRING,
222 (void **) &fct, status, 0);
223 }
224
225 #ifdef HANDLE_DIGITS_DOTS
226 done:
227 #endif
228 *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
229 #ifdef POSTPROCESS
230 POSTPROCESS;
231 #endif
232 return status == NSS_STATUS_SUCCESS ? 0 : errno;
233 }
234
235
236 #include <shlib-compat.h>
237 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1_2)
238 #define OLD(name) OLD1 (name)
239 #define OLD1(name) __old_##name
240
241 int
242 OLD (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
243 size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
244 {
245 int ret = INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, resbuf, buffer,
246 buflen, result H_ERRNO_VAR);
247
248 if (ret != 0)
249 ret = -1;
250
251 return ret;
252 }
253
254 #define do_symbol_version(real, name, version) \
255 compat_symbol (libc, real, name, version)
256 do_symbol_version (OLD (REENTRANT_NAME), REENTRANT_NAME, GLIBC_2_0);
257 #endif
258
259 /* As INTERNAL (REENTRANT_NAME) may be hidden, we need an alias
260 in between so that the REENTRANT_NAME@@GLIBC_2.1.2 is not
261 hidden too. */
262 strong_alias (INTERNAL (REENTRANT_NAME), NEW (REENTRANT_NAME));
263
264 #define do_default_symbol_version(real, name, version) \
265 versioned_symbol (libc, real, name, version)
266 do_default_symbol_version (NEW (REENTRANT_NAME),
267 REENTRANT_NAME, GLIBC_2_1_2);