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