From 8b80182964bde1fa84333674e454d41e1fa0c8ca Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 8 Dec 2000 22:39:54 +0000 Subject: [PATCH] Update. 2000-12-05 H.J. Lu * nss/Makefile (routines): Add getnssent and getnssent_r. * nss/nsswitch.h (__nss_setent): New internal NSS function. (__nss_endent): Likewise. (__nss_getent_r): Likewise. (__nss_getent): Likewise. * nss/getnssent_r.c: New file. * nss/getnssent.c: New file. * nss/getXXent.c (H_ERRNO_VAR): Updated. (GETFUNC_NAME): Updated to call __nss_getent (). * nss/getXXent_r.c (H_ERRNO_VAR_P): New. (STAYOPEN_TMPVAR): Updated. (STAYOPEN_VAR): Updated. (SETFUNC_NAME): Updated to call __nss_setent (). (ENDFUNC_NAME): Updated to call __nss_endent (). (INTERNAL (REENTRANT_GETNAME)): Updated to call __nss_getent_r (). --- ChangeLog | 18 +++++ nss/Makefile | 3 +- nss/getXXent.c | 40 ++------- nss/getXXent_r.c | 191 +++++++------------------------------------ nss/getnssent_r.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++ nss/nsswitch.h | 31 +++++++ 6 files changed, 285 insertions(+), 199 deletions(-) create mode 100644 nss/getnssent_r.c diff --git a/ChangeLog b/ChangeLog index 683f0b7044..a7ca357cf3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2000-12-05 H.J. Lu + + * nss/Makefile (routines): Add getnssent and getnssent_r. + * nss/nsswitch.h (__nss_setent): New internal NSS function. + (__nss_endent): Likewise. + (__nss_getent_r): Likewise. + (__nss_getent): Likewise. + * nss/getnssent_r.c: New file. + * nss/getnssent.c: New file. + * nss/getXXent.c (H_ERRNO_VAR): Updated. + (GETFUNC_NAME): Updated to call __nss_getent (). + * nss/getXXent_r.c (H_ERRNO_VAR_P): New. + (STAYOPEN_TMPVAR): Updated. + (STAYOPEN_VAR): Updated. + (SETFUNC_NAME): Updated to call __nss_setent (). + (ENDFUNC_NAME): Updated to call __nss_endent (). + (INTERNAL (REENTRANT_GETNAME)): Updated to call __nss_getent_r (). + 2000-12-08 Andreas Jaeger * nscd/dbg_log.h (dbg_log): Correct attribute. diff --git a/nss/Makefile b/nss/Makefile index 4edae25c2e..849680ef3a 100644 --- a/nss/Makefile +++ b/nss/Makefile @@ -27,7 +27,8 @@ distribute := nsswitch.h XXX-lookup.c getXXbyYY.c getXXbyYY_r.c \ nsswitch.conf digits_dots.c function.def # This is the trivial part which goes into libc itself. -routines = nsswitch $(addsuffix -lookup,$(databases)) +routines = nsswitch getnssent getnssent_r \ + $(addsuffix -lookup,$(databases)) # These are the databases that go through nss dispatch. # Caution: if you add a database here, you must add its real name diff --git a/nss/getXXent.c b/nss/getXXent.c index d2482157ff..0c8bcb4d4d 100644 --- a/nss/getXXent.c +++ b/nss/getXXent.c @@ -48,10 +48,10 @@ /* Sometimes we need to store error codes in the `h_errno' variable. */ #ifdef NEED_H_ERRNO # define H_ERRNO_PARM , int *h_errnop -# define H_ERRNO_VAR , &h_errno +# define H_ERRNO_VAR &h_errno #else # define H_ERRNO_PARM -# define H_ERRNO_VAR +# define H_ERRNO_VAR NULL #endif /* Prototype of the reentrant version. */ @@ -77,42 +77,14 @@ GETFUNC_NAME (void) /* Get lock. */ __libc_lock_lock (lock); - if (buffer == NULL) - { - buffer_size = BUFLEN; - buffer = malloc (buffer_size); - } + result = (LOOKUP_TYPE *) + __nss_getent ((getent_r_function) INTERNAL (REENTRANT_GETNAME), + (void **) &resbuf, &buffer, BUFLEN, &buffer_size, + H_ERRNO_VAR); - while (buffer != NULL - && INTERNAL (REENTRANT_GETNAME) (&resbuf, buffer, buffer_size, &result - H_ERRNO_VAR) == ERANGE -#ifdef NEED_H_ERRNO - && h_errno == NETDB_INTERNAL -#endif - ) - { - char *new_buf; - buffer_size += BUFLEN; - new_buf = realloc (buffer, buffer_size); - if (new_buf == NULL) - { - /* We are out of memory. Free the current buffer so that the - process gets a chance for a normal termination. */ - save = errno; - free (buffer); - __set_errno (save); - } - buffer = new_buf; - } - - if (buffer == NULL) - result = NULL; - - /* Release lock. Preserve error value. */ save = errno; __libc_lock_unlock (lock); __set_errno (save); - return result; } diff --git a/nss/getXXent_r.c b/nss/getXXent_r.c index f27683a420..64cae78e91 100644 --- a/nss/getXXent_r.c +++ b/nss/getXXent_r.c @@ -22,10 +22,6 @@ #include "nsswitch.h" -#ifdef NEED__RES -# include -#endif - /*******************************************************************\ |* Here we assume several symbols to be defined: *| |* *| @@ -73,31 +69,26 @@ #ifdef NEED_H_ERRNO # define H_ERRNO_PARM , int *h_errnop # define H_ERRNO_VAR , &h_errno +# define H_ERRNO_VAR_P &h_errno #else # define H_ERRNO_PARM # define H_ERRNO_VAR +# define H_ERRNO_VAR_P NULL #endif /* Some databases take the `stayopen' flag. */ #ifdef STAYOPEN # define STAYOPEN_TMP CONCAT2_1 (STAYOPEN, _tmp) -# define STAYOPEN_TMPVAR CONCAT2_1 (STAYOPEN_VAR, _tmp) +# define STAYOPEN_TMPVAR &CONCAT2_1 (STAYOPEN_VAR, _tmp) #else # define STAYOPEN void -# define STAYOPEN_VAR -# define STAYOPEN_TMPVAR +# define STAYOPEN_VAR 0 +# define STAYOPEN_TMPVAR NULL #endif -/* Prototype for the setXXXent functions we use here. */ -typedef enum nss_status (*set_function) (STAYOPEN); - -/* Prototype for the endXXXent functions we use here. */ -typedef enum nss_status (*end_function) (void); - -/* Prototype for the setXXXent functions we use here. */ -typedef enum nss_status (*get_function) (LOOKUP_TYPE *, char *, size_t, int * - H_ERRNO_PARM); - +#ifndef NEED__RES +# define NEED__RES 0 +#endif /* This handle for the NSS data base is shared between all set/get/endXXXent functions. */ @@ -119,103 +110,33 @@ __libc_lock_define_initialized (static, lock) /* The lookup function for the first entry of this service. */ extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp); - -/* 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 (void **fctp, const char *func_name, int all) -{ - int no_more; - if (startp == NULL) - { - no_more = DB_LOOKUP_FCT (&nip, func_name, 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, fctp); - } - return no_more; -} void SETFUNC_NAME (STAYOPEN) { - set_function fct; - int no_more; - -#ifdef NEED__RES - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) - { - __set_h_errno (NETDB_INTERNAL); - return; - } -#endif /* need _res */ + int save; __libc_lock_lock (lock); + __nss_setent (SETFUNC_NAME_STRING, DB_LOOKUP_FCT, &nip, &startp, + &last_nip, STAYOPEN_VAR, STAYOPEN_TMPVAR, NEED__RES); - /* Cycle through the services and run their `setXXent' functions until - we find an available service. */ - no_more = setup ((void **) &fct, SETFUNC_NAME_STRING, 1); - while (! no_more) - { - int is_last_nip = nip == last_nip; - enum nss_status status = DL_CALL_FCT (fct, (STAYOPEN_VAR)); - - no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct, - status, 0); - if (is_last_nip) - last_nip = nip; - } - -#ifdef STAYOPEN_TMP - STAYOPEN_TMPVAR = STAYOPEN_VAR; -#endif - + save = errno; __libc_lock_unlock (lock); + __set_errno (save); } void ENDFUNC_NAME (void) { - end_function fct; - int no_more; - -#ifdef NEED__RES - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) - { - __set_h_errno (NETDB_INTERNAL); - return; - } -#endif /* need _res */ + int save; __libc_lock_lock (lock); - - /* Cycle through all the services and run their endXXent functions. */ - no_more = setup ((void **) &fct, ENDFUNC_NAME_STRING, 1); - while (! no_more) - { - /* Ignore status, we force check in __NSS_NEXT. */ - DL_CALL_FCT (fct, ()); - - if (nip == last_nip) - /* We have processed all services which were used. */ - break; - - no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1); - } - last_nip = nip = NULL; - + __nss_endent (ENDFUNC_NAME_STRING, DB_LOOKUP_FCT, &nip, &startp, + &last_nip, NEED__RES); + save = errno; __libc_lock_unlock (lock); + __set_errno (save); } @@ -223,76 +144,18 @@ int INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM) { - get_function fct; - int no_more; - enum nss_status status; - -#ifdef NEED__RES - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) - { - __set_h_errno (NETDB_INTERNAL); - *result = NULL; - return errno; - } -#endif /* need _res */ - - /* Initialize status to return if no more functions are found. */ - status = NSS_STATUS_NOTFOUND; + int status; + int save; __libc_lock_lock (lock); - - /* 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 ((void **) &fct, GETFUNC_NAME_STRING, 0); - while (! no_more) - { - int is_last_nip = nip == last_nip; - - status = DL_CALL_FCT (fct, - (resbuf, buffer, buflen, &errno H_ERRNO_VAR)); - - /* The 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 -#ifdef NEED_H_ERRNO - && *h_errnop == NETDB_INTERNAL -#endif - && errno == ERANGE) - break; - - do - { - no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct, - status, 0); - - if (is_last_nip) - last_nip = nip; - - if (! no_more) - { - /* Call the `setXXent' function. This wasn't done before. */ - set_function sfct; - - no_more = __nss_lookup (&nip, SETFUNC_NAME_STRING, - (void **) &sfct); - - if (! no_more) - status = DL_CALL_FCT (sfct, (STAYOPEN_TMPVAR)); - else - status = NSS_STATUS_NOTFOUND; - } - } - while (! no_more && status != NSS_STATUS_SUCCESS); - } - + status = __nss_getent_r (GETFUNC_NAME_STRING, SETFUNC_NAME_STRING, + DB_LOOKUP_FCT, &nip, &startp, &last_nip, + STAYOPEN_TMPVAR, NEED__RES, resbuf, buffer, + buflen, (void **) result, H_ERRNO_VAR_P); + save = errno; __libc_lock_unlock (lock); - - *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL; - return status == NSS_STATUS_SUCCESS ? 0 : errno; + __set_errno (save); + return status; } diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c new file mode 100644 index 0000000000..fd8c81f201 --- /dev/null +++ b/nss/getnssent_r.c @@ -0,0 +1,201 @@ +/* Copyright (C) 2000 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#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, 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, 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) +{ + setent_function fct; + int no_more; + + if (res && (_res.options & RES_INIT) == 0 + && __res_ninit (&_res) == -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, (void **) &fct, 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, (*stayopen_tmp)); + else + status = DL_CALL_FCT (fct, (0)); + + no_more = __nss_next (nip, func_name, (void **) &fct, + 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) +{ + endent_function fct; + int no_more; + + if (res && (_res.options & RES_INIT) == 0 + && __res_ninit (&_res) == -1) + { + __set_h_errno (NETDB_INTERNAL); + return; + } + + /* Cycle through all the services and run their endXXent functions. */ + no_more = setup (func_name, lookup_fct, (void **) &fct, nip, startp, 1); + while (! no_more) + { + /* Ignore status, we force check in __NSS_NEXT. */ + DL_CALL_FCT (fct, ()); + + if (*nip == *last_nip) + /* We have processed all services which were used. */ + break; + + no_more = __nss_next (nip, func_name, (void **) &fct, 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) +{ + getent_function fct; + int no_more; + enum nss_status status; + + if (res && (_res.options & RES_INIT) == 0 + && __res_ninit (&_res) == -1) + { + __set_h_errno (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, (void **) &fct, nip, + startp, 0); + while (! no_more) + { + int is_last_nip = *nip == *last_nip; + + status = DL_CALL_FCT (fct, + (resbuf, buffer, buflen, &errno, &h_errno)); + + /* The 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 + { + no_more = __nss_next (nip, getent_func_name, (void **) &fct, + status, 0); + + if (is_last_nip) + *last_nip = *nip; + + if (! no_more) + { + /* Call the `setXXent' function. This wasn't done before. */ + setent_function sfct; + + no_more = __nss_lookup (nip, setent_func_name, + (void **) &sfct); + + if (! no_more) + { + if (stayopen_tmp) + status = DL_CALL_FCT (sfct, (*stayopen_tmp)); + else + status = DL_CALL_FCT (sfct, (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 : errno; +} diff --git a/nss/nsswitch.h b/nss/nsswitch.h index c3398d7a7e..76ea8e3c3c 100644 --- a/nss/nsswitch.h +++ b/nss/nsswitch.h @@ -130,4 +130,35 @@ int __nss_next (service_user **ni, const char *fct_name, void **fctp, and return a pointer to this function if successful. */ void *__nss_lookup_function (service_user *ni, const char *fct_name); + +typedef int (*db_lookup_function) (service_user **, const char *, + void **); +typedef enum nss_status (*setent_function) (int); +typedef enum nss_status (*endent_function) (void); +typedef enum nss_status (*getent_function) (void *, char *, size_t, + int *, int *); +typedef int (*getent_r_function) (void *, char *, size_t, + void **result, int *); + +extern void __nss_setent (const char *func_name, + db_lookup_function lookup_fct, + service_user **nip, service_user **startp, + service_user **last_nip, int stayon, + int *stayon_tmp, int res); +extern void __nss_endent (const char *func_name, + db_lookup_function lookup_fct, + service_user **nip, service_user **startp, + service_user **last_nip, int res); +extern 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 *stayon_tmp, + int res, + void *resbuf, char *buffer, size_t buflen, + void **result, int *h_errnop); +extern void *__nss_getent (getent_r_function func, + void **resbuf, char **buffer, size_t buflen, + size_t *buffer_size, int *h_errnop); + #endif /* nsswitch.h */