Thu Jul 25 00:25:54 Richard Henderson <rth@tamu.edu>
[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
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
60
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
64
65 /* Sometimes we need to store error codes in the `h_errno' variable.  */
66 #ifdef NEED_H_ERRNO
67 # define H_ERRNO_PARM , int *h_errnop
68 # define H_ERRNO_VAR , &h_errno
69 #else
70 # define H_ERRNO_PARM
71 # define H_ERRNO_VAR
72 #endif
73
74 /* Some databases take the `stayopen' flag.  */
75 #ifndef STAYOPEN
76 #define STAYOPEN void
77 #define STAYOPEN_VAR
78 #endif
79
80 /* Prototype for the setXXXent functions we use here.  */
81 typedef int (*set_function) (STAYOPEN);
82
83 /* Prototype for the endXXXent functions we use here.  */
84 typedef int (*end_function) (void);
85
86 /* Prototype for the setXXXent functions we use here.  */
87 typedef int (*get_function) (LOOKUP_TYPE *, char *, int H_ERRNO_PARM);
88
89
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;
95
96 /* Protect above variable against multiple uses at the same time.  */
97 __libc_lock_define_initialized (static, lock)
98
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);
101
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
104    services (left).  */
105 static enum nss_status
106 setup (void **fctp, const char *func_name, int all)
107 {
108   int no_more;
109   if (startp == NULL)
110     {
111       no_more = DB_LOOKUP_FCT (&nip, func_name, fctp);
112       startp = no_more ? (service_user *) -1 : nip;
113     }
114   else if (startp == (service_user *) -1)
115     /* No services at all.  */
116     return 1;
117   else
118     {
119       if (all || !nip)
120         /* Reset to the beginning of the service list.  */
121         nip = startp;
122       /* Look up the first function.  */
123       no_more = __nss_lookup (&nip, func_name, fctp);
124     }
125   return no_more;
126 }
127 \f
128 void
129 SETFUNC_NAME (STAYOPEN)
130 {
131   set_function fct;
132   int no_more;
133
134 #ifdef NEED__RES
135   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
136     {
137       h_errno = NETDB_INTERNAL;
138       return NULL;
139     }
140 #endif /* need _res */
141
142   __libc_lock_lock (lock);
143
144   /* Cycle through all the services and run their setXXent functions.  */
145   no_more = setup ((void **) &fct, SETFUNC_NAME_STRING, 1);
146   while (! no_more)
147     {
148       /* Ignore status, we force check in __NSS_NEXT.  */
149       (void) (*fct) (STAYOPEN_VAR);
150
151       no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct, 0, 1);
152     }
153
154   __libc_lock_unlock (lock);
155 }
156
157
158 void
159 ENDFUNC_NAME (void)
160 {
161   end_function fct;
162   int no_more;
163
164 #ifdef NEED__RES
165   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
166     {
167       h_errno = NETDB_INTERNAL;
168       return NULL;
169     }
170 #endif /* need _res */
171
172   __libc_lock_lock (lock);
173
174   /* Cycle through all the services and run their endXXent functions.  */
175   no_more = setup ((void **) &fct, ENDFUNC_NAME_STRING, 1);
176   while (! no_more)
177     {
178       /* Ignore status, we force check in __NSS_NEXT.  */
179       (void) (*fct) ();
180
181       no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1);
182     }
183
184   __libc_lock_unlock (lock);
185 }
186
187
188 LOOKUP_TYPE *
189 REENTRANT_GETNAME (LOOKUP_TYPE *result, char *buffer, int buflen H_ERRNO_PARM)
190 {
191   get_function fct;
192   int no_more;
193   enum nss_status status;
194
195 #ifdef NEED__RES
196   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
197     {
198       h_errno = NETDB_INTERNAL;
199       return NULL;
200     }
201 #endif /* need _res */
202
203   /* Initialize status to return if no more functions are found.  */
204   status = NSS_STATUS_NOTFOUND;
205
206   __libc_lock_lock (lock);
207
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);
212   while (! no_more)
213     {
214       status = (*fct) (result, buffer, buflen H_ERRNO_VAR);
215
216       no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct,
217                             status, 0);
218     }
219
220   __libc_lock_unlock (lock);
221
222   return status == NSS_STATUS_SUCCESS ? result : NULL;
223 }