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
54 #define SETFUNC_NAME_STRING STRINGIZE (SETFUNC_NAME)
55 #define GETFUNC_NAME_STRING STRINGIZE (REENTRANT_GETNAME)
56 #define ENDFUNC_NAME_STRING STRINGIZE (ENDFUNC_NAME)
57 #define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
58 #define STRINGIZE(name) STRINGIZE1 (name)
59 #define STRINGIZE1(name) #name
61 #define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
62 #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
63 #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
65 /* Sometimes we need to store error codes in the `h_errno' variable. */
67 # define H_ERRNO_PARM , int *h_errnop
68 # define H_ERRNO_VAR , &h_errno
74 /* Some databases take the `stayopen' flag. */
80 /* Prototype for the setXXXent functions we use here. */
81 typedef int (*set_function
) (STAYOPEN
);
83 /* Prototype for the endXXXent functions we use here. */
84 typedef int (*end_function
) (void);
86 /* Prototype for the setXXXent functions we use here. */
87 typedef int (*get_function
) (LOOKUP_TYPE
*, char *, int H_ERRNO_PARM
);
90 /* This handle for the NSS data base is shared between all
91 set/get/endXXXent functions. */
92 static service_user
*nip
;
93 /* Remember the first service_entry, it's always the same. */
94 static service_user
*startp
;
96 /* Protect above variable against multiple uses at the same time. */
97 __libc_lock_define_initialized (static, lock
);
99 /* The lookup function for the first entry of this service. */
100 extern int DB_LOOKUP_FCT (service_user
**nip
, const char *name
, void **fctp
);
102 /* Set up NIP to run through the services. If ALL is zero, use NIP's
103 current location if it's not nil. Return nonzero if there are no
105 static enum nss_status
106 setup (void **fctp
, const char *func_name
, int all
)
111 no_more
= DB_LOOKUP_FCT (&nip
, func_name
, fctp
);
112 startp
= no_more
? (service_user
*) -1 : nip
;
114 else if (startp
== (service_user
*) -1)
115 /* No services at all. */
120 /* Reset to the beginning of the service list. */
122 /* Look up the first function. */
123 no_more
= __nss_lookup (&nip
, func_name
, fctp
);
129 SETFUNC_NAME (STAYOPEN
)
135 if ((_res
.options
& RES_INIT
) == 0 && res_init () == -1)
137 h_errno
= NETDB_INTERNAL
;
140 #endif /* need _res */
142 __libc_lock_lock (lock
);
144 /* Cycle through all the services and run their setXXent functions. */
145 no_more
= setup ((void **) &fct
, SETFUNC_NAME_STRING
, 1);
148 /* Ignore status, we force check in __NSS_NEXT. */
149 (void) (*fct
) (STAYOPEN_VAR
);
151 no_more
= __nss_next (&nip
, SETFUNC_NAME_STRING
, (void **) &fct
, 0, 1);
154 __libc_lock_unlock (lock
);
165 if ((_res
.options
& RES_INIT
) == 0 && res_init () == -1)
167 h_errno
= NETDB_INTERNAL
;
170 #endif /* need _res */
172 __libc_lock_lock (lock
);
174 /* Cycle through all the services and run their endXXent functions. */
175 no_more
= setup ((void **) &fct
, ENDFUNC_NAME_STRING
, 1);
178 /* Ignore status, we force check in __NSS_NEXT. */
181 no_more
= __nss_next (&nip
, ENDFUNC_NAME_STRING
, (void **) &fct
, 0, 1);
184 __libc_lock_unlock (lock
);
189 REENTRANT_GETNAME (LOOKUP_TYPE
*result
, char *buffer
, int buflen H_ERRNO_PARM
)
193 enum nss_status status
;
196 if ((_res
.options
& RES_INIT
) == 0 && res_init () == -1)
198 h_errno
= NETDB_INTERNAL
;
201 #endif /* need _res */
203 /* Initialize status to return if no more functions are found. */
204 status
= NSS_STATUS_NOTFOUND
;
206 __libc_lock_lock (lock
);
208 /* Run through available functions, starting with the same function last
209 run. We will repeat each function as long as it succeeds, and then go
210 on to the next service action. */
211 no_more
= setup ((void **) &fct
, GETFUNC_NAME_STRING
, 0);
214 status
= (*fct
) (result
, buffer
, buflen H_ERRNO_VAR
);
216 no_more
= __nss_next (&nip
, GETFUNC_NAME_STRING
, (void **) &fct
,
220 __libc_lock_unlock (lock
);
222 return status
== NSS_STATUS_SUCCESS
? result
: NULL
;