]> sourceware.org Git - glibc.git/blame - nss/getXXbyYY_r.c
Update.
[glibc.git] / nss / getXXbyYY_r.c
CommitLineData
2cfe49db 1/* Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc.
2303f5fd
UD
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
5f0e6fc7 4
2303f5fd 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
5f0e6fc7 9
2303f5fd
UD
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
41bdb6e2 13 Lesser General Public License for more details.
5f0e6fc7 14
41bdb6e2
AJ
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. */
5f0e6fc7 19
344c67b6 20#include <assert.h>
d71b808a 21#include <errno.h>
b2ab1f5d 22#include <stdbool.h>
5f0e6fc7 23#include "nsswitch.h"
67479a70
UD
24#ifdef USE_NSCD
25# include <nscd/nscd_proto.h>
26#endif
5edb9387
UD
27#ifdef NEED__RES_HCONF
28# include <resolv/res_hconf.h>
29#endif
b43b13ac
UD
30#ifdef NEED__RES
31# include <resolv.h>
32#endif
5f0e6fc7
RM
33/*******************************************************************\
34|* Here we assume several symbols to be defined: *|
fb776f3e 35|* *|
5f0e6fc7 36|* LOOKUP_TYPE - the return type of the function *|
fb776f3e 37|* *|
5f0e6fc7 38|* FUNCTION_NAME - name of the non-reentrant function *|
fb776f3e 39|* *|
5f0e6fc7
RM
40|* DATABASE_NAME - name of the database the function accesses *|
41|* (e.g., host, services, ...) *|
fb776f3e 42|* *|
5f0e6fc7 43|* ADD_PARAMS - additional parameter, can vary in number *|
fb776f3e 44|* *|
5f0e6fc7 45|* ADD_VARIABLES - names of additional parameter *|
fb776f3e 46|* *|
5f0e6fc7 47|* Optionally the following vars can be defined: *|
fb776f3e 48|* *|
5f0e6fc7
RM
49|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
50|* the global `h_errno' variable. *|
fb776f3e 51|* *|
5f0e6fc7 52|* NEED__RES - the global _res variable might be used so we *|
fb776f3e
AJ
53|* will have to initialize it if necessary *|
54|* *|
ae81730f 55|* PREPROCESS - code run before anything else *|
fb776f3e 56|* *|
ae81730f 57|* POSTPROCESS - code run after the lookup *|
fb776f3e 58|* *|
5f0e6fc7
RM
59\*******************************************************************/
60
61/* To make the real sources a bit prettier. */
62#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
63#define APPEND_R(name) APPEND_R1 (name)
64#define APPEND_R1(name) name##_r
23396375
UD
65#define INTERNAL(name) INTERNAL1 (name)
66#define INTERNAL1(name) __##name
bff334e0
UD
67#define NEW(name) NEW1 (name)
68#define NEW1(name) __new_##name
5f0e6fc7 69
d67281a7
UD
70#ifdef USE_NSCD
71# define NSCD_NAME ADD_NSCD (REENTRANT_NAME)
72# define ADD_NSCD(name) ADD_NSCD1 (name)
73# define ADD_NSCD1(name) __nscd_##name
ac16e905
UD
74# define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
75# define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
76# define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
d67281a7
UD
77#endif
78
5f0e6fc7
RM
79#define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
80#define REENTRANT_NAME_STRING STRINGIZE (REENTRANT_NAME)
81#define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
82#define STRINGIZE(name) STRINGIZE1 (name)
83#define STRINGIZE1(name) #name
84
77fe0b9c
UD
85#ifndef DB_LOOKUP_FCT
86# define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
87# define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
88# define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
89#endif
5f0e6fc7
RM
90
91/* Sometimes we need to store error codes in the `h_errno' variable. */
92#ifdef NEED_H_ERRNO
93# define H_ERRNO_PARM , int *h_errnop
94# define H_ERRNO_VAR , h_errnop
a5fdf99b 95# define H_ERRNO_VAR_P h_errnop
5f0e6fc7
RM
96#else
97# define H_ERRNO_PARM
98# define H_ERRNO_VAR
a5fdf99b 99# define H_ERRNO_VAR_P NULL
5f0e6fc7
RM
100#endif
101
a5fdf99b
UD
102#ifndef HAVE_TYPE
103# define TYPE_VAR_P NULL
104# define FLAGS_VAR 0
105#endif
106
107#ifdef HAVE_AF
108# define AF_VAR_P &af
109#else
110# define AF_VAR_P NULL
111#endif
5f0e6fc7
RM
112
113/* Type of the lookup function we need here. */
899d423e
UD
114typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
115 size_t, int * H_ERRNO_PARM);
5f0e6fc7 116
5f0e6fc7 117/* The lookup function for the first entry of this service. */
dff07c4b 118extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp)
37ba7d66
UD
119 internal_function;
120libc_hidden_proto (DB_LOOKUP_FCT)
5f0e6fc7 121
ea278354
UD
122/* Interval in which we transfer retry to contact the NSCD. */
123#define NSS_NSCD_RETRY 100
5f0e6fc7
RM
124
125
ba1ffaa1
UD
126int
127INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
128 size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
5f0e6fc7 129{
c4563d2d 130 static service_user *startp;
5f0e6fc7
RM
131 static lookup_function start_fct;
132 service_user *nip;
fb776f3e
AJ
133 union
134 {
135 lookup_function l;
136 void *ptr;
137 } fct;
138
5f0e6fc7
RM
139 int no_more;
140 enum nss_status status = NSS_STATUS_UNAVAIL;
d67281a7
UD
141#ifdef USE_NSCD
142 int nscd_status;
143#endif
b2ab1f5d
UD
144#ifdef NEED_H_ERRNO
145 bool any_service = false;
146#endif
5f0e6fc7 147
ae81730f
UD
148#ifdef PREPROCESS
149 PREPROCESS;
150#endif
151
61c162b5 152#ifdef HANDLE_DIGITS_DOTS
a5fdf99b
UD
153 switch (__nss_hostname_digits_dots (name, resbuf, &buffer, NULL,
154 buflen, result, &status,
155 TYPE_VAR_P, FLAGS_VAR, AF_VAR_P,
156 H_ERRNO_VAR_P))
d17a729b 157 {
a5fdf99b 158 case -1:
1670698f 159 return errno;
a5fdf99b
UD
160 case 1:
161 goto done;
d17a729b 162 }
61c162b5
UD
163#endif
164
d67281a7 165#ifdef USE_NSCD
ef4d5b32 166 if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
ac16e905 167 NOT_USENSCD_NAME = 0;
ea278354 168
ac16e905 169 if (!NOT_USENSCD_NAME)
d67281a7 170 {
ea278354
UD
171 nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen
172 H_ERRNO_VAR);
1670698f 173 if (nscd_status >= 0)
ea278354
UD
174 {
175 *result = nscd_status == 0 ? resbuf : NULL;
176 return nscd_status;
177 }
d67281a7
UD
178 }
179#endif
180
5f0e6fc7
RM
181 if (startp == NULL)
182 {
fb776f3e 183 no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, &fct.ptr);
5f0e6fc7 184 if (no_more)
8a523922 185 startp = (service_user *) -1l;
5f0e6fc7
RM
186 else
187 {
188 startp = nip;
fb776f3e 189 start_fct = fct.l;
5f0e6fc7
RM
190
191#ifdef NEED__RES
192 /* The resolver code will really be used so we have to
193 initialize it. */
b43b13ac 194 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
5f0e6fc7 195 {
adc6ff7f 196 *h_errnop = NETDB_INTERNAL;
afd4eb37 197 *result = NULL;
1670698f 198 return errno;
5f0e6fc7
RM
199 }
200#endif /* need _res */
5edb9387
UD
201#ifdef NEED__RES_HCONF
202 if (!_res_hconf.initialized)
203 _res_hconf_init ();
204#endif /* need _res_hconf */
5f0e6fc7
RM
205 }
206 }
207 else
208 {
fb776f3e 209 fct.l = start_fct;
8a523922 210 no_more = (nip = startp) == (service_user *) -1l;
5f0e6fc7
RM
211 }
212
213 while (no_more == 0)
214 {
b2ab1f5d
UD
215#ifdef NEED_H_ERRNO
216 any_service = true;
217#endif
218
fb776f3e
AJ
219 status = DL_CALL_FCT (fct.l, (ADD_VARIABLES, resbuf, buffer, buflen,
220 &errno H_ERRNO_VAR));
5f0e6fc7 221
ea278354 222 /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
566efee2
UD
223 provided buffer is too small. In this case we should give
224 the user the possibility to enlarge the buffer and we should
225 not simply go on with the next service (even if the TRYAGAIN
226 action tells us so). */
227 if (status == NSS_STATUS_TRYAGAIN
228#ifdef NEED_H_ERRNO
229 && *h_errnop == NETDB_INTERNAL
230#endif
231 && errno == ERANGE)
232 break;
233
503054c0 234 no_more = __nss_next (&nip, REENTRANT_NAME_STRING,
fb776f3e 235 &fct.ptr, status, 0);
5f0e6fc7
RM
236 }
237
61c162b5
UD
238#ifdef HANDLE_DIGITS_DOTS
239done:
240#endif
ba1ffaa1 241 *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
b2ab1f5d
UD
242#ifdef NEED_H_ERRNO
243 if (status != NSS_STATUS_SUCCESS && ! any_service)
244 /* We were not able to use any service. */
245 *h_errnop = NO_RECOVERY;
246#endif
5edb9387
UD
247#ifdef POSTPROCESS
248 POSTPROCESS;
249#endif
2cfe49db 250 return (status != NSS_STATUS_TRYAGAIN ? 0
9bfce4bf
RM
251#ifdef NEED_H_ERRNO
252 /* These functions only set errno if h_errno is NETDB_INTERNAL. */
253 : *h_errnop != NETDB_INTERNAL ? EAGAIN
254#endif
255 : errno);
5f0e6fc7 256}
23396375 257
16710d58
RM
258
259#include <shlib-compat.h>
260#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1_2)
c2fa5b5a
UD
261#define OLD(name) OLD1 (name)
262#define OLD1(name) __old_##name
263
264int
265OLD (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
266 size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
267{
268 int ret = INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, resbuf, buffer,
fb776f3e 269 buflen, result H_ERRNO_VAR);
c2fa5b5a 270
2cfe49db 271 if (ret != 0 || result == NULL)
c2fa5b5a
UD
272 ret = -1;
273
274 return ret;
275}
276
277#define do_symbol_version(real, name, version) \
16710d58 278 compat_symbol (libc, real, name, version)
47963d10 279do_symbol_version (OLD (REENTRANT_NAME), REENTRANT_NAME, GLIBC_2_0);
deb7f0b4 280#endif
c2fa5b5a 281
bff334e0
UD
282/* As INTERNAL (REENTRANT_NAME) may be hidden, we need an alias
283 in between so that the REENTRANT_NAME@@GLIBC_2.1.2 is not
284 hidden too. */
285strong_alias (INTERNAL (REENTRANT_NAME), NEW (REENTRANT_NAME));
286
c2fa5b5a 287#define do_default_symbol_version(real, name, version) \
16710d58 288 versioned_symbol (libc, real, name, version)
bff334e0 289do_default_symbol_version (NEW (REENTRANT_NAME),
16710d58 290 REENTRANT_NAME, GLIBC_2_1_2);
This page took 0.266866 seconds and 5 git commands to generate.