Update UD main archive 960805
[kopensolaris-gnu/glibc.git] / nss / getXXent_r.c
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.
4
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.
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 Library General Public License for more details.
14
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.  */
19
20 #include <libc-lock.h>
21
22 #include "nsswitch.h"
23
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 \*******************************************************************/
48
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
55
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
62
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
66
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
75
76 /* Some databases take the `stayopen' flag.  */
77 #ifndef STAYOPEN
78 #define STAYOPEN void
79 #define STAYOPEN_VAR
80 #endif
81
82 /* Prototype for the setXXXent functions we use here.  */
83 typedef int (*set_function) (STAYOPEN);
84
85 /* Prototype for the endXXXent functions we use here.  */
86 typedef int (*end_function) (void);
87
88 /* Prototype for the setXXXent functions we use here.  */
89 typedef int (*get_function) (LOOKUP_TYPE *, char *, int H_ERRNO_PARM);
90
91
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;
97
98 /* Protect above variable against multiple uses at the same time.  */
99 __libc_lock_define_initialized (static, lock)
100
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);
103
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)
109 {
110   int no_more;
111   if (startp == NULL)
112     {
113       no_more = DB_LOOKUP_FCT (&nip, func_name, fctp);
114       startp = no_more ? (service_user *) -1 : nip;
115     }
116   else if (startp == (service_user *) -1)
117     /* No services at all.  */
118     return 1;
119   else
120     {
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);
126     }
127   return no_more;
128 }
129 \f
130 void
131 SETFUNC_NAME (STAYOPEN)
132 {
133   set_function fct;
134   int no_more;
135
136 #ifdef NEED__RES
137   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
138     {
139       h_errno = NETDB_INTERNAL;
140       return NULL;
141     }
142 #endif /* need _res */
143
144   __libc_lock_lock (lock);
145
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)
149     {
150       /* Ignore status, we force check in __NSS_NEXT.  */
151       (void) (*fct) (STAYOPEN_VAR);
152
153       no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct, 0, 1);
154     }
155
156   __libc_lock_unlock (lock);
157 }
158
159
160 void
161 ENDFUNC_NAME (void)
162 {
163   end_function fct;
164   int no_more;
165
166 #ifdef NEED__RES
167   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
168     {
169       h_errno = NETDB_INTERNAL;
170       return NULL;
171     }
172 #endif /* need _res */
173
174   __libc_lock_lock (lock);
175
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)
179     {
180       /* Ignore status, we force check in __NSS_NEXT.  */
181       (void) (*fct) ();
182
183       no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1);
184     }
185
186   __libc_lock_unlock (lock);
187 }
188
189
190 LOOKUP_TYPE *
191 INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *result, char *buffer, int buflen
192                               H_ERRNO_PARM)
193 {
194   get_function fct;
195   int no_more;
196   enum nss_status status;
197
198 #ifdef NEED__RES
199   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
200     {
201       h_errno = NETDB_INTERNAL;
202       return NULL;
203     }
204 #endif /* need _res */
205
206   /* Initialize status to return if no more functions are found.  */
207   status = NSS_STATUS_NOTFOUND;
208
209   __libc_lock_lock (lock);
210
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)
216     {
217       status = (*fct) (result, buffer, buflen H_ERRNO_VAR);
218
219       no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct,
220                             status, 0);
221     }
222
223   __libc_lock_unlock (lock);
224
225   return status == NSS_STATUS_SUCCESS ? result : NULL;
226 }
227 #define do_weak_alias(n1, n2) weak_alias (n1, n2)
228 do_weak_alias (INTERNAL (REENTRANT_GETNAME), REENTRANT_GETNAME)