diff options
Diffstat (limited to 'REORG.TODO/nss/getnssent_r.c')
-rw-r--r-- | REORG.TODO/nss/getnssent_r.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/REORG.TODO/nss/getnssent_r.c b/REORG.TODO/nss/getnssent_r.c new file mode 100644 index 0000000000..5fdbf3be00 --- /dev/null +++ b/REORG.TODO/nss/getnssent_r.c @@ -0,0 +1,236 @@ +/* Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <netdb.h> +#include "nsswitch.h" + +/* Set up NIP to run through the services. If ALL is zero, use NIP's + current location if it's not nil. Return nonzero if there are no + services (left). */ +static int +setup (const char *func_name, db_lookup_function lookup_fct, + void **fctp, service_user **nip, service_user **startp, int all) +{ + int no_more; + if (*startp == NULL) + { + no_more = lookup_fct (nip, func_name, NULL, fctp); + *startp = no_more ? (service_user *) -1l : *nip; + } + else if (*startp == (service_user *) -1l) + /* No services at all. */ + return 1; + else + { + if (all || !*nip) + /* Reset to the beginning of the service list. */ + *nip = *startp; + /* Look up the first function. */ + no_more = __nss_lookup (nip, func_name, NULL, fctp); + } + return no_more; +} + +void +__nss_setent (const char *func_name, db_lookup_function lookup_fct, + service_user **nip, service_user **startp, + service_user **last_nip, int stayopen, int *stayopen_tmp, + int res) +{ + union + { + setent_function f; + void *ptr; + } fct; + int no_more; + + if (res && __res_maybe_init (&_res, 0) == -1) + { + __set_h_errno (NETDB_INTERNAL); + return; + } + + /* Cycle through the services and run their `setXXent' functions until + we find an available service. */ + no_more = setup (func_name, lookup_fct, &fct.ptr, nip, + startp, 1); + while (! no_more) + { + int is_last_nip = *nip == *last_nip; + enum nss_status status; + + if (stayopen_tmp) + status = DL_CALL_FCT (fct.f, (*stayopen_tmp)); + else + status = DL_CALL_FCT (fct.f, (0)); + + + /* This is a special-case. When [SUCCESS=merge] is in play, + _nss_next2() will skip to the next database. Due to the + implementation of that function, we can't know whether we're + in an enumeration or an individual lookup, which behaves + differently with regards to merging. We'll treat SUCCESS as + an indication to start the enumeration at this database. */ + if (nss_next_action (*nip, status) == NSS_ACTION_MERGE) + no_more = 1; + else + no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0); + + if (is_last_nip) + *last_nip = *nip; + } + + if (stayopen_tmp) + *stayopen_tmp = stayopen; +} + + +void +__nss_endent (const char *func_name, db_lookup_function lookup_fct, + service_user **nip, service_user **startp, + service_user **last_nip, int res) +{ + union + { + endent_function f; + void *ptr; + } fct; + int no_more; + + if (res && __res_maybe_init (&_res, 0) == -1) + { + __set_h_errno (NETDB_INTERNAL); + return; + } + + /* Cycle through all the services and run their endXXent functions. */ + no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1); + while (! no_more) + { + /* Ignore status, we force check in __NSS_NEXT. */ + DL_CALL_FCT (fct.f, ()); + + if (*nip == *last_nip) + /* We have processed all services which were used. */ + break; + + no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, 0, 1); + } + *last_nip = *nip = NULL; +} + + +int +__nss_getent_r (const char *getent_func_name, + const char *setent_func_name, + db_lookup_function lookup_fct, + service_user **nip, service_user **startp, + service_user **last_nip, int *stayopen_tmp, int res, + void *resbuf, char *buffer, size_t buflen, + void **result, int *h_errnop) +{ + union + { + getent_function f; + void *ptr; + } fct; + int no_more; + enum nss_status status; + + if (res && __res_maybe_init (&_res, 0) == -1) + { + *h_errnop = NETDB_INTERNAL; + *result = NULL; + return errno; + } + + /* Initialize status to return if no more functions are found. */ + status = NSS_STATUS_NOTFOUND; + + /* Run through available functions, starting with the same function last + run. We will repeat each function as long as it succeeds, and then go + on to the next service action. */ + no_more = setup (getent_func_name, lookup_fct, &fct.ptr, nip, + startp, 0); + while (! no_more) + { + int is_last_nip = *nip == *last_nip; + + status = DL_CALL_FCT (fct.f, + (resbuf, buffer, buflen, &errno, &h_errno)); + + /* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the + provided buffer is too small. In this case we should give + the user the possibility to enlarge the buffer and we should + not simply go on with the next service (even if the TRYAGAIN + action tells us so). */ + if (status == NSS_STATUS_TRYAGAIN + && (h_errnop == NULL || *h_errnop == NETDB_INTERNAL) + && errno == ERANGE) + break; + + do + { + /* This is a special-case. When [SUCCESS=merge] is in play, + _nss_next2() will skip to the next database. Due to the + implementation of that function, we can't know whether we're + in an enumeration or an individual lookup, which behaves + differently with regards to merging. We'll treat SUCCESS as + an indication to return the results here. */ + if (status == NSS_STATUS_SUCCESS + && nss_next_action (*nip, status) == NSS_ACTION_MERGE) + no_more = 1; + else + no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr, + status, 0); + + if (is_last_nip) + *last_nip = *nip; + + if (! no_more) + { + /* Call the `setXXent' function. This wasn't done before. */ + union + { + setent_function f; + void *ptr; + } sfct; + + no_more = __nss_lookup (nip, setent_func_name, NULL, &sfct.ptr); + + if (! no_more) + { + if (stayopen_tmp) + status = DL_CALL_FCT (sfct.f, (*stayopen_tmp)); + else + status = DL_CALL_FCT (sfct.f, (0)); + } + else + status = NSS_STATUS_NOTFOUND; + } + } + while (! no_more && status != NSS_STATUS_SUCCESS); + } + + *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL; + return (status == NSS_STATUS_SUCCESS ? 0 + : status != NSS_STATUS_TRYAGAIN ? ENOENT + /* h_errno functions only set errno if h_errno is NETDB_INTERNAL. */ + : (h_errnop == NULL || *h_errnop == NETDB_INTERNAL) ? errno + : EAGAIN); +} |