]> git.ipfire.org Git - thirdparty/glibc.git/blame - nss/getnssent_r.c
[powerpc] No need to enter "Ignore Exceptions Mode"
[thirdparty/glibc.git] / nss / getnssent_r.c
CommitLineData
04277e02 1/* Copyright (C) 2000-2019 Free Software Foundation, Inc.
8b801829
UD
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8b801829
UD
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
8b801829 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
8b801829
UD
17
18#include <errno.h>
19#include <netdb.h>
20#include "nsswitch.h"
352f4ff9 21#include <resolv/resolv_context.h>
8b801829
UD
22
23/* Set up NIP to run through the services. If ALL is zero, use NIP's
24 current location if it's not nil. Return nonzero if there are no
25 services (left). */
26static int
27setup (const char *func_name, db_lookup_function lookup_fct,
28 void **fctp, service_user **nip, service_user **startp, int all)
29{
30 int no_more;
31 if (*startp == NULL)
32 {
384ca551 33 no_more = lookup_fct (nip, func_name, NULL, fctp);
8b801829
UD
34 *startp = no_more ? (service_user *) -1l : *nip;
35 }
36 else if (*startp == (service_user *) -1l)
37 /* No services at all. */
38 return 1;
39 else
40 {
41 if (all || !*nip)
42 /* Reset to the beginning of the service list. */
43 *nip = *startp;
44 /* Look up the first function. */
384ca551 45 no_more = __nss_lookup (nip, func_name, NULL, fctp);
8b801829
UD
46 }
47 return no_more;
48}
49\f
50void
51__nss_setent (const char *func_name, db_lookup_function lookup_fct,
52 service_user **nip, service_user **startp,
53 service_user **last_nip, int stayopen, int *stayopen_tmp,
54 int res)
55{
fb776f3e
AJ
56 union
57 {
58 setent_function f;
59 void *ptr;
60 } fct;
8b801829
UD
61 int no_more;
62
352f4ff9
FW
63 struct resolv_context *res_ctx = NULL;
64 if (res)
8b801829 65 {
352f4ff9
FW
66 res_ctx = __resolv_context_get ();
67 if (res_ctx == NULL)
68 {
69 __set_h_errno (NETDB_INTERNAL);
70 return;
71 }
8b801829
UD
72 }
73
74 /* Cycle through the services and run their `setXXent' functions until
75 we find an available service. */
fb776f3e 76 no_more = setup (func_name, lookup_fct, &fct.ptr, nip,
8b801829
UD
77 startp, 1);
78 while (! no_more)
79 {
80 int is_last_nip = *nip == *last_nip;
81 enum nss_status status;
8fea756a 82
8b801829 83 if (stayopen_tmp)
fb776f3e 84 status = DL_CALL_FCT (fct.f, (*stayopen_tmp));
8b801829 85 else
fb776f3e 86 status = DL_CALL_FCT (fct.f, (0));
8b801829 87
ced8f893
SG
88
89 /* This is a special-case. When [SUCCESS=merge] is in play,
90 _nss_next2() will skip to the next database. Due to the
91 implementation of that function, we can't know whether we're
92 in an enumeration or an individual lookup, which behaves
93 differently with regards to merging. We'll treat SUCCESS as
94 an indication to start the enumeration at this database. */
95 if (nss_next_action (*nip, status) == NSS_ACTION_MERGE)
96 no_more = 1;
97 else
98 no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
99
8b801829
UD
100 if (is_last_nip)
101 *last_nip = *nip;
102 }
103
352f4ff9
FW
104 __resolv_context_put (res_ctx);
105
8b801829
UD
106 if (stayopen_tmp)
107 *stayopen_tmp = stayopen;
108}
109
110
111void
112__nss_endent (const char *func_name, db_lookup_function lookup_fct,
113 service_user **nip, service_user **startp,
114 service_user **last_nip, int res)
115{
fb776f3e
AJ
116 union
117 {
118 endent_function f;
119 void *ptr;
120 } fct;
8b801829
UD
121 int no_more;
122
352f4ff9
FW
123 struct resolv_context *res_ctx = NULL;
124 if (res)
8b801829 125 {
352f4ff9
FW
126 res_ctx = __resolv_context_get ();
127 if (res_ctx == NULL)
128 {
129 __set_h_errno (NETDB_INTERNAL);
130 return;
131 }
8b801829
UD
132 }
133
134 /* Cycle through all the services and run their endXXent functions. */
fb776f3e 135 no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1);
8b801829
UD
136 while (! no_more)
137 {
138 /* Ignore status, we force check in __NSS_NEXT. */
fb776f3e 139 DL_CALL_FCT (fct.f, ());
8b801829
UD
140
141 if (*nip == *last_nip)
142 /* We have processed all services which were used. */
143 break;
144
384ca551 145 no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, 0, 1);
8b801829
UD
146 }
147 *last_nip = *nip = NULL;
352f4ff9
FW
148
149 __resolv_context_put (res_ctx);
8b801829
UD
150}
151
152
153int
154__nss_getent_r (const char *getent_func_name,
155 const char *setent_func_name,
156 db_lookup_function lookup_fct,
157 service_user **nip, service_user **startp,
158 service_user **last_nip, int *stayopen_tmp, int res,
159 void *resbuf, char *buffer, size_t buflen,
160 void **result, int *h_errnop)
161{
fb776f3e
AJ
162 union
163 {
164 getent_function f;
165 void *ptr;
166 } fct;
8b801829
UD
167 int no_more;
168 enum nss_status status;
169
352f4ff9
FW
170 struct resolv_context *res_ctx = NULL;
171 if (res)
8b801829 172 {
352f4ff9
FW
173 res_ctx = __resolv_context_get ();
174 if (res_ctx == NULL)
175 {
176 *h_errnop = NETDB_INTERNAL;
177 *result = NULL;
178 return errno;
179 }
8b801829
UD
180 }
181
182 /* Initialize status to return if no more functions are found. */
183 status = NSS_STATUS_NOTFOUND;
184
185 /* Run through available functions, starting with the same function last
186 run. We will repeat each function as long as it succeeds, and then go
187 on to the next service action. */
fb776f3e 188 no_more = setup (getent_func_name, lookup_fct, &fct.ptr, nip,
8b801829
UD
189 startp, 0);
190 while (! no_more)
191 {
192 int is_last_nip = *nip == *last_nip;
193
fb776f3e
AJ
194 status = DL_CALL_FCT (fct.f,
195 (resbuf, buffer, buflen, &errno, &h_errno));
8b801829 196
ded5b9b7 197 /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
8b801829
UD
198 provided buffer is too small. In this case we should give
199 the user the possibility to enlarge the buffer and we should
200 not simply go on with the next service (even if the TRYAGAIN
201 action tells us so). */
202 if (status == NSS_STATUS_TRYAGAIN
203 && (h_errnop == NULL || *h_errnop == NETDB_INTERNAL)
204 && errno == ERANGE)
205 break;
206
207 do
208 {
ced8f893
SG
209 /* This is a special-case. When [SUCCESS=merge] is in play,
210 _nss_next2() will skip to the next database. Due to the
211 implementation of that function, we can't know whether we're
212 in an enumeration or an individual lookup, which behaves
213 differently with regards to merging. We'll treat SUCCESS as
214 an indication to return the results here. */
215 if (status == NSS_STATUS_SUCCESS
216 && nss_next_action (*nip, status) == NSS_ACTION_MERGE)
217 no_more = 1;
218 else
219 no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
220 status, 0);
8b801829
UD
221
222 if (is_last_nip)
223 *last_nip = *nip;
224
225 if (! no_more)
226 {
227 /* Call the `setXXent' function. This wasn't done before. */
fb776f3e
AJ
228 union
229 {
230 setent_function f;
231 void *ptr;
232 } sfct;
8b801829 233
384ca551 234 no_more = __nss_lookup (nip, setent_func_name, NULL, &sfct.ptr);
8b801829
UD
235
236 if (! no_more)
237 {
238 if (stayopen_tmp)
fb776f3e 239 status = DL_CALL_FCT (sfct.f, (*stayopen_tmp));
8b801829 240 else
fb776f3e 241 status = DL_CALL_FCT (sfct.f, (0));
8b801829
UD
242 }
243 else
244 status = NSS_STATUS_NOTFOUND;
245 }
246 }
247 while (! no_more && status != NSS_STATUS_SUCCESS);
248 }
249
352f4ff9
FW
250 __resolv_context_put (res_ctx);
251
8b801829 252 *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
9bfce4bf
RM
253 return (status == NSS_STATUS_SUCCESS ? 0
254 : status != NSS_STATUS_TRYAGAIN ? ENOENT
255 /* h_errno functions only set errno if h_errno is NETDB_INTERNAL. */
256 : (h_errnop == NULL || *h_errnop == NETDB_INTERNAL) ? errno
257 : EAGAIN);
8b801829 258}