* nonlocal-shadow.c
* shadow database for nss_nonlocal proxy.
*
- * Copyright © 2007 Anders Kaseorg <andersk@mit.edu>
+ * Copyright © 2007–2010 Anders Kaseorg <andersk@mit.edu>
*
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
+ * This file is part of nss_nonlocal.
*
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
+ * nss_nonlocal 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * nss_nonlocal 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 nss_nonlocal; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
*/
#define _GNU_SOURCE
#include "nonlocal.h"
-static service_user *
-nss_shadow_nonlocal_database(void)
+static service_user *__nss_shadow_nonlocal_database;
+
+static int
+internal_function
+__nss_shadow_nonlocal_lookup(service_user **ni, const char *fct_name,
+ void **fctp)
{
- static service_user *nip = NULL;
- if (nip == NULL)
- __nss_database_lookup("shadow_nonlocal", NULL, "", &nip);
+ if (__nss_shadow_nonlocal_database == NULL
+ && __nss_database_lookup("shadow_nonlocal", NULL, NULL,
+ &__nss_shadow_nonlocal_database) < 0)
+ return -1;
- return nip;
+ *ni = __nss_shadow_nonlocal_database;
+
+ *fctp = __nss_lookup_function(*ni, fct_name);
+ return 0;
}
-static service_user *spent_nip = NULL;
+static service_user *spent_startp, *spent_nip;
static void *spent_fct_start;
static union {
enum nss_status (*l)(struct spwd *pwd, char *buffer, size_t buflen,
enum nss_status
_nss_nonlocal_setspent(int stayopen)
{
- static const char *fct_name = "setspent";
- static void *fct_start = NULL;
enum nss_status status;
- service_user *nip;
- union {
- enum nss_status (*l)(int stayopen);
- void *ptr;
- } fct;
-
- nip = nss_shadow_nonlocal_database();
- if (nip == NULL)
- return NSS_STATUS_UNAVAIL;
- if (fct_start == NULL)
- fct_start = __nss_lookup_function(nip, fct_name);
- fct.ptr = fct_start;
- do {
- if (fct.ptr == NULL)
- status = NSS_STATUS_UNAVAIL;
- else
- status = DL_CALL_FCT(fct.l, (stayopen));
- } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
+ const struct walk_nss w = {
+ .lookup = &__nss_shadow_nonlocal_lookup, .fct_name = "setspent",
+ .status = &status
+ };
+ const __typeof__(&_nss_nonlocal_setspent) self = NULL;
+#define args (stayopen)
+#include "walk_nss.h"
+#undef args
if (status != NSS_STATUS_SUCCESS)
return status;
- spent_nip = nip;
if (spent_fct_start == NULL)
- spent_fct_start = __nss_lookup_function(nip, spent_fct_name);
+ __nss_shadow_nonlocal_lookup(&spent_startp, spent_fct_name,
+ &spent_fct_start);
+ spent_nip = spent_startp;
spent_fct.ptr = spent_fct_start;
return NSS_STATUS_SUCCESS;
}
enum nss_status
_nss_nonlocal_endspent(void)
{
- static const char *fct_name = "endspent";
- static void *fct_start = NULL;
enum nss_status status;
- service_user *nip;
- union {
- enum nss_status (*l)(void);
- void *ptr;
- } fct;
+ const struct walk_nss w = {
+ .lookup = &__nss_shadow_nonlocal_lookup, .fct_name = "endspent",
+ .status = &status
+ };
+ const __typeof__(&_nss_nonlocal_endspent) self = NULL;
spent_nip = NULL;
- nip = nss_shadow_nonlocal_database();
- if (nip == NULL)
- return NSS_STATUS_UNAVAIL;
- if (fct_start == NULL)
- fct_start = __nss_lookup_function(nip, fct_name);
- fct.ptr = fct_start;
- do {
- if (fct.ptr == NULL)
- status = NSS_STATUS_UNAVAIL;
- else
- status = DL_CALL_FCT(fct.l, ());
- } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
+#define args ()
+#include "walk_nss.h"
+#undef args
return status;
}
_nss_nonlocal_getspnam_r(const char *name, struct spwd *pwd,
char *buffer, size_t buflen, int *errnop)
{
- static const char *fct_name = "getspnam_r";
- static void *fct_start = NULL;
enum nss_status status;
- service_user *nip;
- union {
- enum nss_status (*l)(const char *name, struct spwd *pwd,
- char *buffer, size_t buflen, int *errnop);
- void *ptr;
- } fct;
-
- nip = nss_shadow_nonlocal_database();
- if (nip == NULL)
- return NSS_STATUS_UNAVAIL;
- if (fct_start == NULL)
- fct_start = __nss_lookup_function(nip, fct_name);
- fct.ptr = fct_start;
- do {
- if (fct.ptr == NULL)
- status = NSS_STATUS_UNAVAIL;
- else
- status = DL_CALL_FCT(fct.l, (name, pwd, buffer, buflen, errnop));
- if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
- break;
- } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
+ const struct walk_nss w = {
+ .lookup = __nss_shadow_nonlocal_lookup, .fct_name = "getspnam_r",
+ .status = &status, .errnop = errnop
+ };
+ const __typeof__(&_nss_nonlocal_getspnam_r) self = NULL;
+#define args (name, pwd, buffer, buflen, errnop)
+#include "walk_nss.h"
+#undef args
if (status != NSS_STATUS_SUCCESS)
return status;