Date: Wed, 28 Jun 2006 13:07:18 GMT From: Michael Bushkov <bushman@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 100201 for review Message-ID: <200606281307.k5SD7INs006619@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=100201 Change 100201 by bushman@bushman_nss_ldap_cached on 2006/06/28 13:06:34 Some getusershell() further development. Affected files ... .. //depot/projects/soc2006/nss_ldap_cached/tests/getusershell_test/Makefile#2 edit .. //depot/projects/soc2006/nss_ldap_cached/tests/getusershell_test/getusershell_test.c#2 edit Differences ... ==== //depot/projects/soc2006/nss_ldap_cached/tests/getusershell_test/Makefile#2 (text+ko) ==== ==== //depot/projects/soc2006/nss_ldap_cached/tests/getusershell_test/getusershell_test.c#2 (text+ko) ==== @@ -1,3 +1,6 @@ +#define YP +#define HESIOD + #include "namespace.h" #include <sys/param.h> #include <sys/file.h> @@ -22,17 +25,40 @@ #include <rpcsvc/yp_prot.h> #endif #include "un-namespace.h" +#include "reentrant.h" +#include "nss_tls.h" #define DECORATED(x) __my_##x +static void usershell_endstate(void *); + +struct usershell_state { + char *buffer; + size_t bufsize; +}; + +NSS_TLS_HANDLING(usershell); + +static void usershell_endstate(void *st) +{ + if (st == NULL) + return; + + free(((struct usershell_state *)st)->buffer); + free(st); +} + + +static const ns_src defaultsrc[] = { + { NSSRC_FILES, NS_SUCCESS }, + { NULL, 0} +}; + /* * Local shells should NOT be added here. They should be added in * /etc/shells. */ -#define YP -#define HESIOD - static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; static const char *const *curshell; static StringList *sl; @@ -47,7 +73,7 @@ #ifdef YP struct nis_usershell_state { - char *yp_domain; + char yp_domain[MAXHOSTNAMELEN]; char *key; int keylen; }; @@ -56,8 +82,8 @@ #endif #ifdef HESIOD -struct dns_usershell_data { - long counter; +struct dns_usershell_state { + int counter; }; static void dns_usershell_endstate(void *); NSS_TLS_HANDLING(dns_usershell); @@ -72,7 +98,7 @@ if (st == NULL) return; - state = (files_usershell_state *)st; + state = (struct files_usershell_state *)st; if (state->fp != NULL) { fclose(state->fp); state->fp = NULL; @@ -90,8 +116,7 @@ if (st == NULL) return; - state = (nis_usershell_state *)st; - free(state->ypdomain); + state = (struct nis_usershell_state *)st; free(state->key); free(state); } @@ -101,6 +126,7 @@ static void dns_usershell_endstate(void *st) { + free(st); } #endif @@ -111,14 +137,14 @@ char *buffer; size_t buflen; int *errnop; - char * const *retval; + char **retval; char *cp, *sp; buffer = va_arg(ap, char *); buflen = va_arg(ap, size_t); errnop = va_arg(ap, int *); - retval = (char * const *)rv; + retval = (char **)rv; assert(buffer != NULL); assert(buflen != 0); @@ -128,11 +154,11 @@ if (*errnop != 0) return (NS_UNAVAIL); - if ((st->fp == NULL) && ((fp = fopen(_PATH_SHELLS, "r")) == NULL)) + if ((st->fp == NULL) && ((st->fp = fopen(_PATH_SHELLS, "r")) == NULL)) return NS_UNAVAIL; cp = buffer; - if (fgets(cp, buflen - 1, st->fp) != NULL) { + while (fgets(cp, buflen - 1, st->fp) != NULL) { while (*cp != '#' && *cp != '/' && *cp != '\0') cp++; if (*cp == '#' || *cp == '\0') @@ -142,15 +168,14 @@ cp++; *cp++ = '\0'; - retval = cp; + *retval = sp; return (NS_SUCCESS); - } else { - (void)fclose(st->fp); - st->fp = NULL; + } + + (void)fclose(st->fp); + st->fp = NULL; - return (NS_UNAVAIL); - } - + return (NS_UNAVAIL); } static int @@ -197,18 +222,14 @@ assert(buflen != 0); assert(rv != NULL); - *errnop = files_usershell_getstate(&st); + *errnop = nis_usershell_getstate(&st); if (*errnop != 0) return (NS_UNAVAIL); - if (st->ypdomain == NULL) { - switch (yp_get_default_domain(&st->ypdomain)) { - case 0: - break; - case YPERR_RESRC: - return NS_TRYAGAIN; - default: - return NS_UNAVAIL; + if (st->yp_domain[0] == '\0') { + if (getdomainname(st->yp_domain, sizeof st->yp_domain)) { + *errnop = errno; + return (NS_UNAVAIL); } } @@ -219,11 +240,11 @@ */ key = data = NULL; if (st->key == NULL) { - if (yp_first(ypdomain, "shells", &st->key, &st->keylen, &data, - &datalen)) + if (yp_first(st->yp_domain, "shells", &st->key, &st->keylen, + &data, &datalen)) return (NS_UNAVAIL); } else { - r = yp_next(ypdomain, "shells", st->key, st->keylen, + r = yp_next(st->yp_domain, "shells", st->key, st->keylen, &key, &keylen, &data, &datalen); /* @@ -238,7 +259,7 @@ free(key); free(data); *errnop = ERANGE; - return (NSRETURN); + return (NS_RETURN); } strncpy(buffer, data, datalen); @@ -251,60 +272,186 @@ static int __nis_setusershell(void *rv, void *cb_data, va_list ap) -[ -] +{ + struct nis_usershell_state *st; + int r; + + r = nis_usershell_getstate(&st); + if (r != 0) + return (NS_UNAVAIL); + + free(st->key); + st->key = NULL; + + return (NS_UNAVAIL); +} #endif #ifdef HESIOD static int __dns_getusershell_r(void *rv, void *cb_data, va_list ap) { + struct dns_usershell_state *st; + char *buffer; + size_t buflen; + int *errnop; + char * const *retval; + + char shellname[] = "shells-XXXXX"; + int hpi, r; + char **hp; + void *context; + size_t linesize; + + buffer = va_arg(ap, char *); + buflen = va_arg(ap, size_t); + errnop = va_arg(ap, int *); + retval = (char * const *)rv; + + assert(buffer != NULL); + assert(buflen != 0); + assert(rv != NULL); + + *errnop = dns_usershell_getstate(&st); + if (*errnop != 0) + return (NS_UNAVAIL); + + if (st->counter == -1) + return (NS_NOTFOUND); + + r = NS_UNAVAIL; + if (hesiod_init(&context) == -1) + return (r); + + snprintf(shellname, sizeof(shellname)-1, "shells-%d", st->counter++); + hp = hesiod_resolve(context, shellname, "shells"); + if (hp == NULL) { + st->counter = -1; + + if (errno == ENOENT) + r = NS_NOTFOUND; + else { + *errnop = errno; + r = NS_UNAVAIL; + } + } else { + linesize = strlcpy(buffer, hp[0], buflen); + hesiod_free_list(context, hp); + + if (linesize >= buflen) { + *errnop = ERANGE; + r = NS_RETURN; + } + } + + hesiod_end(context); + return (r); } static int __dns_setusershell(void *rv, void *cb_data, va_list ap) { + struct dns_usershell_state *st; + int r; + + r = dns_usershell_getstate(&st); + if (r != 0) + return (NS_UNAVAIL); + + st->counter = 0; + + return (NS_UNAVAIL); } #endif static int -getusershell_r(char * const *retval, char *buffer, size_t bufsize, int *error) +getusershell_r(char **retval, char *buffer, size_t bufsize) { + static const ns_dtab dtab[] = { + { NSSRC_FILES, __files_getusershell_r, NULL }, + { NSSRC_NIS, __nis_getusershell_r, NULL }, + { NSSRC_DNS, __dns_getusershell_r, NULL }, + { NULL, NULL, NULL } + }; + int rv, ret_errno; + + ret_errno = 0; + *retval = NULL; + rv = nsdispatch(retval, dtab, NSDB_SHELLS, "getusershell_r", + defaultsrc, buffer, bufsize, &ret_errno); + + if (rv == NS_SUCCESS) + return (0); + else + return (ret_errno); } static void __setusershell() { - static const ns_dtab dtab[] = { - NS_FILES_CB(_local_initshells, NULL) +/* static const ns_dtab dtab[] = { + NS_FILES_CB(_files_initshells, NULL) NS_DNS_CB(_dns_initshells, NULL) NS_NIS_CB(_nis_initshells, NULL) { 0 } - }; + };*/ } static void __endusershell() { + } /* * Get a list of shells from "shells" nsswitch database */ +enum constants +{ + USERSHELL_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ + USERSHELL_STORAGE_MAX = 1 << 20, /* 1 MByte */ +}; + char * DECORATED(getusershell)(void) { - char *ret; + int rv; + char *res; + struct usershell_state *st; + + rv = usershell_getstate(&st); + if (rv != 0) { + errno = rv; + return NULL; + } + + if (st->buffer == NULL) { + st->buffer = malloc(USERSHELL_STORAGE_INITIAL); + if (st->buffer == NULL) + return (NULL); + st->bufsize = USERSHELL_STORAGE_INITIAL; + } + do { + rv = getusershell_r(&res, st->buffer, st->bufsize); + if (res == NULL && rv == ERANGE) { + free(st->buffer); + if ((st->bufsize << 1) > USERSHELL_STORAGE_MAX) { + st->buffer = NULL; + errno = ERANGE; + return (NULL); + } + st->bufsize <<= 1; + st->buffer = malloc(st->bufsize); + if (st->buffer == NULL) + return (NULL); + } + } while (res == NULL && rv == ERANGE); + if (rv != 0) + errno = rv; - if (curshell == NULL) - curshell = initshells(); - /*LINTED*/ - ret = (char *)*curshell; - if (ret != NULL) - curshell++; - return (ret); + return (res); } void
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606281307.k5SD7INs006619>