(NEW, NEW1): Define.
[kopensolaris-gnu/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 #ifndef NSS_attribute_hidden
113 # define NSS_attribute_hidden
114 #endif
115
116 /* Type of the lookup function we need here.  */
117 typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
118                                             size_t, int * H_ERRNO_PARM);
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      internal_function NSS_attribute_hidden;
123
124 /* Interval in which we transfer retry to contact the NSCD.  */
125 #define NSS_NSCD_RETRY  100
126
127
128 int
129 INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
130                            size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
131 {
132   static service_user *startp;
133   static lookup_function start_fct;
134   service_user *nip;
135   lookup_function fct;
136   int no_more;
137   enum nss_status status = NSS_STATUS_UNAVAIL;
138 #ifdef USE_NSCD
139   int nscd_status;
140 #endif
141
142 #ifdef PREPROCESS
143   PREPROCESS;
144 #endif
145
146 #ifdef HANDLE_DIGITS_DOTS
147   switch (__nss_hostname_digits_dots (name, resbuf, &buffer, NULL,
148                                       buflen, result, &status,
149                                       TYPE_VAR_P, FLAGS_VAR, AF_VAR_P,
150                                       H_ERRNO_VAR_P))
151     {
152     case -1:
153       return errno;
154     case 1:
155       goto done;
156     }
157 #endif
158
159 #ifdef USE_NSCD
160   if (NOT_USENSCD_NAME && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
161     NOT_USENSCD_NAME = 0;
162
163   if (!NOT_USENSCD_NAME)
164     {
165       nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen
166                                H_ERRNO_VAR);
167       if (nscd_status >= 0)
168         {
169           *result = nscd_status == 0 ? resbuf : NULL;
170           return nscd_status;
171         }
172     }
173 #endif
174
175   if (startp == NULL)
176     {
177       no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, (void **) &fct);
178       if (no_more)
179         startp = (service_user *) -1l;
180       else
181         {
182           startp = nip;
183           start_fct = fct;
184
185 #ifdef NEED__RES
186           /* The resolver code will really be used so we have to
187              initialize it.  */
188           if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
189             {
190               *h_errnop = NETDB_INTERNAL;
191               *result = NULL;
192               return errno;
193             }
194 #endif /* need _res */
195 #ifdef NEED__RES_HCONF
196           if (!_res_hconf.initialized)
197             _res_hconf_init ();
198 #endif /* need _res_hconf */
199         }
200     }
201   else
202     {
203       fct = start_fct;
204       no_more = (nip = startp) == (service_user *) -1l;
205     }
206
207   while (no_more == 0)
208     {
209       status = DL_CALL_FCT (fct, (ADD_VARIABLES, resbuf, buffer, buflen,
210                                    &errno H_ERRNO_VAR));
211
212       /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
213          provided buffer is too small.  In this case we should give
214          the user the possibility to enlarge the buffer and we should
215          not simply go on with the next service (even if the TRYAGAIN
216          action tells us so).  */
217       if (status == NSS_STATUS_TRYAGAIN
218 #ifdef NEED_H_ERRNO
219           && *h_errnop == NETDB_INTERNAL
220 #endif
221           && errno == ERANGE)
222         break;
223
224       no_more = __nss_next (&nip, REENTRANT_NAME_STRING,
225                             (void **) &fct, status, 0);
226     }
227
228 #ifdef HANDLE_DIGITS_DOTS
229 done:
230 #endif
231   *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
232 #ifdef POSTPROCESS
233   POSTPROCESS;
234 #endif
235   return status == NSS_STATUS_SUCCESS ? 0 : errno;
236 }
237
238
239 #include <shlib-compat.h>
240 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1_2)
241 #define OLD(name) OLD1 (name)
242 #define OLD1(name) __old_##name
243
244 int
245 OLD (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
246                       size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
247 {
248   int ret = INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, resbuf, buffer,
249                                        buflen, result H_ERRNO_VAR);
250
251   if (ret != 0)
252     ret = -1;
253
254   return ret;
255 }
256
257 #define do_symbol_version(real, name, version) \
258   compat_symbol (libc, real, name, version)
259 do_symbol_version (OLD (REENTRANT_NAME), REENTRANT_NAME, GLIBC_2_0);
260 #endif
261
262 /* As INTERNAL (REENTRANT_NAME) may be hidden, we need an alias
263    in between so that the REENTRANT_NAME@@GLIBC_2.1.2 is not
264    hidden too.  */
265 strong_alias (INTERNAL (REENTRANT_NAME), NEW (REENTRANT_NAME));
266
267 #define do_default_symbol_version(real, name, version) \
268   versioned_symbol (libc, real, name, version)
269 do_default_symbol_version (NEW (REENTRANT_NAME),
270                            REENTRANT_NAME, GLIBC_2_1_2);