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