PERFORCE change 100201 for review
Michael Bushkov
bushman at FreeBSD.org
Wed Jun 28 13:08:52 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=100201
Change 100201 by bushman at 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
More information about the p4-projects
mailing list