1 /* Copyright (C) 2000-2017 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
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.
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
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
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
26 setup (const char *func_name
, db_lookup_function lookup_fct
,
27 void **fctp
, service_user
**nip
, service_user
**startp
, int all
)
32 no_more
= lookup_fct (nip
, func_name
, NULL
, fctp
);
33 *startp
= no_more
? (service_user
*) -1l : *nip
;
35 else if (*startp
== (service_user
*) -1l)
36 /* No services at all. */
41 /* Reset to the beginning of the service list. */
43 /* Look up the first function. */
44 no_more
= __nss_lookup (nip
, func_name
, NULL
, fctp
);
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
,
62 if (res
&& __res_maybe_init (&_res
, 0) == -1)
64 __set_h_errno (NETDB_INTERNAL
);
68 /* Cycle through the services and run their `setXXent' functions until
69 we find an available service. */
70 no_more
= setup (func_name
, lookup_fct
, &fct
.ptr
, nip
,
74 int is_last_nip
= *nip
== *last_nip
;
75 enum nss_status status
;
78 status
= DL_CALL_FCT (fct
.f
, (*stayopen_tmp
));
80 status
= DL_CALL_FCT (fct
.f
, (0));
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
)
92 no_more
= __nss_next2 (nip
, func_name
, NULL
, &fct
.ptr
, status
, 0);
99 *stayopen_tmp
= stayopen
;
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
)
115 if (res
&& __res_maybe_init (&_res
, 0) == -1)
117 __set_h_errno (NETDB_INTERNAL
);
121 /* Cycle through all the services and run their endXXent functions. */
122 no_more
= setup (func_name
, lookup_fct
, &fct
.ptr
, nip
, startp
, 1);
125 /* Ignore status, we force check in __NSS_NEXT. */
126 DL_CALL_FCT (fct
.f
, ());
128 if (*nip
== *last_nip
)
129 /* We have processed all services which were used. */
132 no_more
= __nss_next2 (nip
, func_name
, NULL
, &fct
.ptr
, 0, 1);
134 *last_nip
= *nip
= NULL
;
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
)
153 enum nss_status status
;
155 if (res
&& __res_maybe_init (&_res
, 0) == -1)
157 *h_errnop
= NETDB_INTERNAL
;
162 /* Initialize status to return if no more functions are found. */
163 status
= NSS_STATUS_NOTFOUND
;
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. */
168 no_more
= setup (getent_func_name
, lookup_fct
, &fct
.ptr
, nip
,
172 int is_last_nip
= *nip
== *last_nip
;
174 status
= DL_CALL_FCT (fct
.f
,
175 (resbuf
, buffer
, buflen
, &errno
, &h_errno
));
177 /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
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
)
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
)
199 no_more
= __nss_next2 (nip
, getent_func_name
, NULL
, &fct
.ptr
,
207 /* Call the `setXXent' function. This wasn't done before. */
214 no_more
= __nss_lookup (nip
, setent_func_name
, NULL
, &sfct
.ptr
);
219 status
= DL_CALL_FCT (sfct
.f
, (*stayopen_tmp
));
221 status
= DL_CALL_FCT (sfct
.f
, (0));
224 status
= NSS_STATUS_NOTFOUND
;
227 while (! no_more
&& status
!= NSS_STATUS_SUCCESS
);
230 *result
= status
== NSS_STATUS_SUCCESS
? resbuf
: NULL
;
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