update from main archive 961016
[glibc.git] / nss / getXXent_r.c
blob6bff863e07eadab702ec828ec7a3f2ae05370e39
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>
22 #include "nsswitch.h"
24 /*******************************************************************\
25 |* Here we assume several symbols to be defined: *|
26 |* *|
27 |* LOOKUP_TYPE - the return type of the function *|
28 |* *|
29 |* SETFUNC_NAME - name of the non-reentrant setXXXent function *|
30 |* *|
31 |* GETFUNC_NAME - name of the non-reentrant getXXXent function *|
32 |* *|
33 |* ENDFUNC_NAME - name of the non-reentrant endXXXent function *|
34 |* *|
35 |* DATABASE_NAME - name of the database the function accesses *|
36 |* (e.g., host, services, ...) *|
37 |* *|
38 |* Optionally the following vars can be defined: *|
39 |* *|
40 |* STAYOPEN - variable declaration for setXXXent function *|
41 |* *|
42 |* STAYOPEN_VAR - variable name for setXXXent function *|
43 |* *|
44 |* NEED_H_ERRNO - an extra parameter will be passed to point to *|
45 |* the global `h_errno' variable. *|
46 |* *|
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. */
68 #ifdef NEED_H_ERRNO
69 # define H_ERRNO_PARM , int *h_errnop
70 # define H_ERRNO_VAR , &h_errno
71 #else
72 # define H_ERRNO_PARM
73 # define H_ERRNO_VAR
74 #endif
76 /* Some databases take the `stayopen' flag. */
77 #ifndef STAYOPEN
78 #define STAYOPEN void
79 #define STAYOPEN_VAR
80 #endif
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
106 services (left). */
107 static enum nss_status
108 setup (void **fctp, const char *func_name, int all)
110 int no_more;
111 if (startp == NULL)
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. */
118 return 1;
119 else
121 if (all || !nip)
122 /* Reset to the beginning of the service list. */
123 nip = startp;
124 /* Look up the first function. */
125 no_more = __nss_lookup (&nip, func_name, fctp);
127 return no_more;
130 void
131 SETFUNC_NAME (STAYOPEN)
133 set_function fct;
134 int no_more;
136 #ifdef NEED__RES
137 if ((_res.options & RES_INIT) == 0 && res_init () == -1)
139 __set_h_errno (NETDB_INTERNAL);
140 return NULL;
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);
148 while (! no_more)
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);
160 void
161 ENDFUNC_NAME (void)
163 end_function fct;
164 int no_more;
166 #ifdef NEED__RES
167 if ((_res.options & RES_INIT) == 0 && res_init () == -1)
169 __set_h_errno (NETDB_INTERNAL);
170 return NULL;
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);
178 while (! no_more)
180 /* Ignore status, we force check in __NSS_NEXT. */
181 (void) (*fct) ();
183 no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1);
186 __libc_lock_unlock (lock);
190 LOOKUP_TYPE *
191 INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *result, char *buffer, int buflen
192 H_ERRNO_PARM)
194 get_function fct;
195 int no_more;
196 enum nss_status status;
198 #ifdef NEED__RES
199 if ((_res.options & RES_INIT) == 0 && res_init () == -1)
201 __set_h_errno (NETDB_INTERNAL);
202 return NULL;
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);
215 while (! no_more)
217 status = (*fct) (result, buffer, buflen H_ERRNO_VAR);
219 no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct,
220 status, 0);
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)