1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
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.
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.
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
17 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <libc-lock.h>
24 /*******************************************************************\
25 |* Here we assume several symbols to be defined: *|
27 |* LOOKUP_TYPE - the return type of the function *|
29 |* SETFUNC_NAME - name of the non-reentrant setXXXent function *|
31 |* GETFUNC_NAME - name of the non-reentrant getXXXent function *|
33 |* ENDFUNC_NAME - name of the non-reentrant endXXXent function *|
35 |* DATABASE_NAME - name of the database the function accesses *|
36 |* (e.g., host, services, ...) *|
38 |* Optionally the following vars can be defined: *|
40 |* STAYOPEN - variable declaration for setXXXent function *|
42 |* STAYOPEN_VAR - variable name for setXXXent function *|
44 |* NEED_H_ERRNO - an extra parameter will be passed to point to *|
45 |* the global `h_errno' variable. *|
47 \*******************************************************************/
49 /* To make the real sources a bit prettier. */
50 #define REENTRANT_GETNAME APPEND_R (GETFUNC_NAME)
51 #define APPEND_R(name) APPEND_R1 (name)
52 #define APPEND_R1(name) name##_r
53 #define INTERNAL(name) INTERNAL1 (name)
54 #define INTERNAL1(name) __##name
56 #define SETFUNC_NAME_STRING STRINGIZE (SETFUNC_NAME)
57 #define GETFUNC_NAME_STRING STRINGIZE (REENTRANT_GETNAME)
58 #define ENDFUNC_NAME_STRING STRINGIZE (ENDFUNC_NAME)
59 #define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
60 #define STRINGIZE(name) STRINGIZE1 (name)
61 #define STRINGIZE1(name) #name
63 #define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
64 #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
65 #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
67 /* Sometimes we need to store error codes in the `h_errno' variable. */
69 # define H_ERRNO_PARM , int *h_errnop
70 # define H_ERRNO_VAR , &h_errno
76 /* Some databases take the `stayopen' flag. */
82 /* Prototype for the setXXXent functions we use here. */
83 typedef int (*set_function) (STAYOPEN);
85 /* Prototype for the endXXXent functions we use here. */
86 typedef int (*end_function) (void);
88 /* Prototype for the setXXXent functions we use here. */
89 typedef int (*get_function) (LOOKUP_TYPE *, char *, int H_ERRNO_PARM);
92 /* This handle for the NSS data base is shared between all
93 set/get/endXXXent functions. */
94 static service_user *nip;
95 /* Remember the first service_entry, it's always the same. */
96 static service_user *startp;
98 /* Protect above variable against multiple uses at the same time. */
99 __libc_lock_define_initialized (static, lock)
101 /* The lookup function for the first entry of this service. */
102 extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp);
104 /* Set up NIP to run through the services. If ALL is zero, use NIP's
105 current location if it's not nil. Return nonzero if there are no
107 static enum nss_status
108 setup (void **fctp, const char *func_name, int all)
113 no_more = DB_LOOKUP_FCT (&nip, func_name, fctp);
114 startp = no_more ? (service_user *) -1 : nip;
116 else if (startp == (service_user *) -1)
117 /* No services at all. */
122 /* Reset to the beginning of the service list. */
124 /* Look up the first function. */
125 no_more = __nss_lookup (&nip, func_name, fctp);
131 SETFUNC_NAME (STAYOPEN)
137 if ((_res.options & RES_INIT) == 0 && res_init () == -1)
139 __set_h_errno (NETDB_INTERNAL);
142 #endif /* need _res */
144 __libc_lock_lock (lock);
146 /* Cycle through all the services and run their setXXent functions. */
147 no_more = setup ((void **) &fct, SETFUNC_NAME_STRING, 1);
150 /* Ignore status, we force check in __NSS_NEXT. */
151 (void) (*fct) (STAYOPEN_VAR);
153 no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct, 0, 1);
156 __libc_lock_unlock (lock);
167 if ((_res.options & RES_INIT) == 0 && res_init () == -1)
169 __set_h_errno (NETDB_INTERNAL);
172 #endif /* need _res */
174 __libc_lock_lock (lock);
176 /* Cycle through all the services and run their endXXent functions. */
177 no_more = setup ((void **) &fct, ENDFUNC_NAME_STRING, 1);
180 /* Ignore status, we force check in __NSS_NEXT. */
183 no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1);
186 __libc_lock_unlock (lock);
191 INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *result, char *buffer, int buflen
196 enum nss_status status;
199 if ((_res.options & RES_INIT) == 0 && res_init () == -1)
201 __set_h_errno (NETDB_INTERNAL);
204 #endif /* need _res */
206 /* Initialize status to return if no more functions are found. */
207 status = NSS_STATUS_NOTFOUND;
209 __libc_lock_lock (lock);
211 /* Run through available functions, starting with the same function last
212 run. We will repeat each function as long as it succeeds, and then go
213 on to the next service action. */
214 no_more = setup ((void **) &fct, GETFUNC_NAME_STRING, 0);
217 status = (*fct) (result, buffer, buflen H_ERRNO_VAR);
219 no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct,
223 __libc_lock_unlock (lock);
225 return status == NSS_STATUS_SUCCESS ? result : NULL;
227 #define do_weak_alias(n1, n2) weak_alias (n1, n2)
228 do_weak_alias (INTERNAL (REENTRANT_GETNAME), REENTRANT_GETNAME)