rpms/autofs/devel autofs-5.0.2-add-ferror-check.patch, NONE, 1.1 autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch, NONE, 1.1 autofs-5.0.2-add-multiple-server-selection-option.patch, NONE, 1.1 autofs-5.0.2-autofs-5-typo.patch, NONE, 1.1 autofs-5.0.2-basedn-with-spaces.patch, NONE, 1.1 autofs-5.0.2-check-auto_master.patch, NONE, 1.1 autofs-5.0.2-check-mtab-updated.patch, NONE, 1.1 autofs-5.0.2-dynamic-logging-fixes.patch, NONE, 1.1 autofs-5.0.2-dynamic-logging-non-sasl.patch, NONE, 1.1 autofs-5.0.2-dynamic-logging.patch, NONE, 1.1 autofs-5.0.2-fix-recursive-loopback-mounts.patch, NONE, 1.1 autofs-5.0.2-large-groups.patch, NONE, 1.1 autofs-5.0.2-ldap-check-star.patch, NONE, 1.1 autofs-5.0.2-ldap-search-basedn-list.patch, NONE, 1.1 autofs-5.0.2-log-map-reload.patch, NONE, 1.1 autofs-5.0.2-negative-timeout-update.patch, NONE, 1.1 autofs-5.0.2-random-selection-fix.patch, NONE, 1.1 autofs-5.0.2-remove-unused-export-validation-code.patch, NONE, 1.1 autofs-5.0.2-report-failed-lookups.patch, NONE, 1.1 autofs-5.0.2-reread-config-on-hup.patch, NONE, 1.1 autofs-5.0.2-singleton-host-list.patch, NONE, 1.1 autofs-5.0.2-submount-deadlock.patch, NONE, 1.1 autofs-5.0.2-swallow-null-macro.patch, NONE, 1.1 autofs-5.0.2-timeout-option-parse-fix.patch, NONE, 1.1 autofs.spec, 1.223, 1.224

Ian Kent (iankent) fedora-extras-commits at redhat.com
Tue Nov 20 07:34:54 UTC 2007


Author: iankent

Update of /cvs/pkgs/rpms/autofs/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv22455

Modified Files:
	autofs.spec 
Added Files:
	autofs-5.0.2-add-ferror-check.patch 
	autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch 
	autofs-5.0.2-add-multiple-server-selection-option.patch 
	autofs-5.0.2-autofs-5-typo.patch 
	autofs-5.0.2-basedn-with-spaces.patch 
	autofs-5.0.2-check-auto_master.patch 
	autofs-5.0.2-check-mtab-updated.patch 
	autofs-5.0.2-dynamic-logging-fixes.patch 
	autofs-5.0.2-dynamic-logging-non-sasl.patch 
	autofs-5.0.2-dynamic-logging.patch 
	autofs-5.0.2-fix-recursive-loopback-mounts.patch 
	autofs-5.0.2-large-groups.patch 
	autofs-5.0.2-ldap-check-star.patch 
	autofs-5.0.2-ldap-search-basedn-list.patch 
	autofs-5.0.2-log-map-reload.patch 
	autofs-5.0.2-negative-timeout-update.patch 
	autofs-5.0.2-random-selection-fix.patch 
	autofs-5.0.2-remove-unused-export-validation-code.patch 
	autofs-5.0.2-report-failed-lookups.patch 
	autofs-5.0.2-reread-config-on-hup.patch 
	autofs-5.0.2-singleton-host-list.patch 
	autofs-5.0.2-submount-deadlock.patch 
	autofs-5.0.2-swallow-null-macro.patch 
	autofs-5.0.2-timeout-option-parse-fix.patch 
Log Message:
* Tue Nov 20 2007 Ian Kent <ikent at redhat.com> - 5.0.2-18
- fix schema selection in LDAP schema discovery.
- check for "*" when looking up wildcard in LDAP.
- fix couple of edge case parse fails of timeout option.
- add SEARCH_BASE configuration option.
- add random selection as a master map entry option.
- re-read config on HUP signal.
- add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options.
- fix deadlock in submount mount module.
- fix lack of ferror() checking when reading files.
- fix typo in autofs(5) man page.
- fix map entry expansion when undefined macro is present.
- remove unused export validation code.
- add dynamic logging (adapted from v4 patch from Jeff Moyer).
- fix recursive loopback mounts (Matthias Koenig).
- add map re-load to verbose logging.
- fix handling of LDAP base dns with spaces.
- handle MTAB_NOTUPDATED status return from mount.
- when default master map, auto.master, is used also check for auto_master.
- update negative mount timeout handling.
- fix large group handling (Ryan Thomas).
- fix for dynamic logging breaking non-sasl build (Guillaume Rousse).
- eliminate NULL proc ping for singleton host or local mounts.


autofs-5.0.2-add-ferror-check.patch:

--- NEW FILE autofs-5.0.2-add-ferror-check.patch ---
diff --git a/daemon/automount.c b/daemon/automount.c
index 930b13f..70a3b9d 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -978,7 +978,7 @@ static void *do_read_master(void *arg)
 	if (status)
 		fatal(status);
 
-	defaults_read_config();
+	defaults_read_config(1);
 
 	status = master_read_master(master, age, readall);
 
@@ -1465,7 +1465,7 @@ int main(int argc, char *argv[])
 
 	program = argv[0];
 
-	defaults_read_config();
+	defaults_read_config(0);
 
 	kpkt_len = get_kpkt_len();
 	timeout = defaults_get_timeout();
diff --git a/include/defaults.h b/include/defaults.h
index 46393d9..0e0e2a5 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -41,7 +41,7 @@
 struct ldap_schema;
 struct ldap_searchdn;
 
-unsigned int defaults_read_config(void);
+unsigned int defaults_read_config(unsigned int);
 const char *defaults_get_master_map(void);
 unsigned int defaults_get_timeout(void);
 unsigned int defaults_get_browse_mode(void);
diff --git a/lib/defaults.c b/lib/defaults.c
index bf1ceed..2cccf20 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -280,7 +280,7 @@ struct list_head *defaults_get_uris(void)
  * is valid bourne shell script without spaces around "="
  * and that it has valid values.
  */
-unsigned int defaults_read_config(void)
+unsigned int defaults_read_config(unsigned int to_syslog)
 {
 	FILE *f;
 	char buf[MAX_LINE_LEN];
@@ -312,9 +312,16 @@ unsigned int defaults_read_config(void)
 			;
 	}
 
-	if (!feof(f)) {
-		fprintf(stderr, "fgets returned error %d while reading %s\n",
-			ferror(f), DEFAULTS_CONFIG_FILE);
+	if (!feof(f) || ferror(f)) {
+		if (!to_syslog) {
+			fprintf(stderr,
+				"fgets returned error %d while reading %s\n",
+				ferror(f), DEFAULTS_CONFIG_FILE);
+		} else {
+			error(LOGOPT_ANY,
+			      "fgets returned error %d while reading %s",
+			      ferror(f), DEFAULTS_CONFIG_FILE);
+		}
 		fclose(f);
 		return 0;
 	}
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 6346602..31ee0fb 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -442,6 +442,11 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		if (!entry) {
 			if (feof(f))
 				break;
+			if (ferror(f)) {
+				warn(LOGOPT_ANY, MODPREFIX
+				     "error reading map %s", ctxt->mapname);
+				break;
+			}
 			continue;
 		}
 
@@ -683,6 +688,11 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 		if (!entry) {
 			if (feof(f))
 				break;
+			if (ferror(f)) {
+				warn(LOGOPT_ANY, MODPREFIX
+				      "error reading map %s", ctxt->mapname);
+				break;
+			}
 			continue;
 		}
 			
@@ -848,6 +858,12 @@ static int lookup_one(struct autofs_point *ap,
 
 		if (feof(f))
 			break;
+
+		if (ferror(f)) {
+			warn(LOGOPT_ANY, MODPREFIX
+			      "error reading map %s", ctxt->mapname);
+			break;
+		}		
 	}
 
 	fclose(f);
@@ -907,6 +923,12 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
 
 		if (feof(f))
 			break;
+
+		if (ferror(f)) {
+			warn(LOGOPT_ANY, MODPREFIX
+			      "error reading map %s", ctxt->mapname);
+			break;
+		}		
 	}
 
 	fclose(f);

autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch:

--- NEW FILE autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch ---
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index dfb3054..8719af9 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -193,10 +193,11 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt
 	LDAPMessage *result = NULL, *e;
 	struct ldap_searchdn *sdns = NULL;
 	char *attrs[2];
+	struct berval **value;
 	int scope;
 	int rv, l;
 
-	attrs[0] = LDAP_NO_ATTRS;
+	attrs[0] = (char *) key;
 	attrs[1] = NULL;
 
 	if (!ctxt->mapname && !ctxt->base) {
@@ -283,7 +284,8 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt
 	}
 
 	e = ldap_first_entry(ldap, result);
-	if (e) {
+	if (e && (value = ldap_get_values_len(ldap, e, key))) {
+		ldap_value_free_len(value);
 		dn = ldap_get_dn(ldap, e);
 		debug(logopt, MODPREFIX "found query dn %s", dn);
 	} else {

autofs-5.0.2-add-multiple-server-selection-option.patch:

--- NEW FILE autofs-5.0.2-add-multiple-server-selection-option.patch ---
diff --git a/include/defaults.h b/include/defaults.h
index 0984b1c..46393d9 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -26,7 +26,8 @@
 #define DEFAULT_BROWSE_MODE	1
 #define DEFAULT_LOGGING		0
 
-#define DEFAULT_LDAP_SERVER		NULL
+#define DEFAULT_LDAP_TIMEOUT		-1
+#define DEFAULT_LDAP_NETWORK_TIMEOUT	8
 
 #define DEFAULT_MAP_OBJ_CLASS		"nisMap"
 #define DEFAULT_ENTRY_OBJ_CLASS		"nisObject"
@@ -46,6 +47,10 @@ unsigned int defaults_get_timeout(void);
 unsigned int defaults_get_browse_mode(void);
 unsigned int defaults_get_logging(void);
 const char *defaults_get_ldap_server(void);
+unsigned int defaults_get_ldap_timeout(void);
+unsigned int defaults_get_ldap_network_timeout(void);
+struct list_head *defaults_get_uris(void);
+void defaults_free_uris(struct list_head *);
 struct ldap_schema *defaults_get_default_schema(void);
 struct ldap_schema *defaults_get_schema(void);
 struct ldap_searchdn *defaults_get_searchdns(void);
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index 1a924be..ca8d658 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -18,6 +18,11 @@ struct ldap_schema {
 	char *value_attr;
 };
 
+struct ldap_uri {
+	char *uri;
+	struct list_head list;
+};
+
 struct ldap_searchdn {
 	char *basedn;
 	struct ldap_searchdn *next;
@@ -30,6 +35,8 @@ struct lookup_context {
 	int port;
 	char *base;
 	char *qdn;
+	unsigned int timeout;
+	unsigned int network_timeout;
 
 	/* LDAP version 2 or 3 */
 	int version;
@@ -37,7 +44,17 @@ struct lookup_context {
 	/* LDAP lookup configuration */
 	struct ldap_schema *schema;
 
-	/* List of base dns for searching */
+	/*
+ 	 * List of servers and base dns for searching.
+ 	 * uri is the list of servers to attempt connection to and is
+ 	 * used only if server, above, is NULL. The head of the list
+ 	 * is the server which we are currently connected to.
+ 	 * cur_host tracks chnages to connected server, triggering
+ 	 * a scan of basedns when it changes.
+ 	 * sdns is the list of basdns to check, done in the order
+ 	 * given in configuration.
+ 	 */
+	struct list_head *uri;
 	char *cur_host;
 	struct ldap_searchdn *sdns;
 
@@ -77,7 +94,7 @@ struct lookup_context {
 #define LDAP_AUTH_AUTODETECT	0x0004
 
 /* lookup_ldap.c */
-LDAP *init_ldap_connection(struct lookup_context *ctxt);
+LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt);
 int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt);
 int authtype_requires_creds(const char *authtype);
 
diff --git a/lib/defaults.c b/lib/defaults.c
index 7da4631..bf1ceed 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -17,6 +17,7 @@
 #include <ctype.h>
 #include <string.h>
 
+#include "list.h"
 #include "defaults.h"
 #include "lookup_ldap.h"
 #include "log.h"
@@ -30,7 +31,9 @@
 #define ENV_NAME_BROWSE_MODE		"BROWSE_MODE"
 #define ENV_NAME_LOGGING		"LOGGING"
 
-#define ENV_LDAP_SERVER			"LDAP_SERVER"
+#define LDAP_URI			"LDAP_URI"
+#define ENV_LDAP_TIMEOUT		"LDAP_TIMEOUT"
+#define ENV_LDAP_NETWORK_TIMEOUT	"LDAP_NETWORK_TIMEOUT"
 
 #define SEARCH_BASE			"SEARCH_BASE"
 
@@ -44,7 +47,6 @@
 #define ENV_AUTH_CONF_FILE		"AUTH_CONF_FILE"
 
 static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME;
-static const char *default_ldap_server	   = DEFAULT_LDAP_SERVER;
 static const char *default_auth_conf_file  = DEFAULT_AUTH_CONF_FILE;
 
 static char *get_env_string(const char *name)
@@ -178,6 +180,99 @@ static int parse_line(char *line, char **res, char **value)
 	return 1;
 }
 
+void defaults_free_uris(struct list_head *list)
+{
+	struct list_head *next;
+	struct ldap_uri *uri;
+
+	if (list_empty(list)) {
+		free(list);
+		return;
+	}
+
+	next = list->next;
+	while (next != list) {
+		uri = list_entry(next, struct ldap_uri, list);
+		next = next->next;
+		list_del(&uri->list);
+		free(uri->uri);
+		free(uri);
+	}
+	free(list);
+
+	return;
+}
+
+static unsigned int add_uris(char *value, struct list_head *list)
+{
+	char *str, *tok, *ptr = NULL;
+	size_t len = strlen(value);
+
+	str = alloca(len);
+	if (!str)
+		return 0;
+	strcpy(str, value);
+
+	tok = strtok_r(str, " ", &ptr);
+	while (tok) {
+		struct ldap_uri *new;
+		char *uri;
+
+		new = malloc(sizeof(struct ldap_uri));
+		if (!new)
+			continue;
+
+		uri = strdup(tok);
+		if (!uri)
+			free(new);
+		else {
+			new->uri = uri;
+			list_add_tail(&new->list, list);
+		}
+
+		tok = strtok_r(NULL, " ", &ptr);
+	}
+
+	return 1;
+}
+
+struct list_head *defaults_get_uris(void)
+{
+	FILE *f;
+	char buf[MAX_LINE_LEN];
+	char *res;
+	struct list_head *list;
+
+	f = fopen(DEFAULTS_CONFIG_FILE, "r");
+	if (!f)
+		return NULL;
+
+	list = malloc(sizeof(struct list_head));
+	if (!list) {
+		fclose(f);
+		return NULL;
+	}
+	INIT_LIST_HEAD(list);
+
+	while ((res = fgets(buf, MAX_LINE_LEN, f))) {
+		char *key, *value;
+
+		if (!parse_line(res, &key, &value))
+			continue;
+
+		if (!strcasecmp(res, LDAP_URI))
+			add_uris(value, list);
+	}
+
+	if (list_empty(list)) {
+		free(list);
+		list = NULL;
+	}
+
+	fclose(f);
+	return list;
+}
+
 /*
  * Read config env variables and check they have been set.
  *
@@ -205,7 +300,8 @@ unsigned int defaults_read_config(void)
 		    check_set_config_value(key, ENV_NAME_TIMEOUT, value) ||
 		    check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) ||
 		    check_set_config_value(key, ENV_NAME_LOGGING, value) ||
-		    check_set_config_value(key, ENV_LDAP_SERVER, value) ||
+		    check_set_config_value(key, ENV_LDAP_TIMEOUT, value) ||
+		    check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value) ||
 		    check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) ||
 		    check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) ||
 		    check_set_config_value(key, ENV_NAME_MAP_ATTR, value) ||
@@ -284,15 +380,26 @@ unsigned int defaults_get_logging(void)
 	return logging;
 }
 
-const char *defaults_get_ldap_server(void)
+unsigned int defaults_get_ldap_timeout(void)
 {
-	char *server;
+	int res;
 
-	server = get_env_string(ENV_LDAP_SERVER);
-	if (!server)
-		return default_ldap_server;
+	res = get_env_number(ENV_LDAP_TIMEOUT);
+	if (res < 0)
+		res = DEFAULT_LDAP_TIMEOUT;
 
-	return (const char *) server;
+	return res;
+}
+
+unsigned int defaults_get_ldap_network_timeout(void)
+{
+	int res;
+
+	res = get_env_number(ENV_LDAP_NETWORK_TIMEOUT);
+	if (res < 0)
+		res = DEFAULT_LDAP_NETWORK_TIMEOUT;
+
+	return res;
 }
 
 struct ldap_schema *defaults_get_default_schema(void)
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 0cb2f07..68447e0 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -230,10 +230,27 @@ values must be set, any partial schema specification will be ignored.
 .P
 The configuration settings available are:
 .TP
+.B LDAP_TIMEOUT
+Set the network response timeout (default 8).
+Set timeout value for the synchronous API  calls. The default is the LDAP
+library default of an infinite timeout.
+.TP
+.B LDAP_NETWORK_TIMEOUT
+Set the network response timeout (default 8).
+.TP
+.B LDAP_URI
+A space seperated list of server uris of the form <proto>://<server>[/]
+where <proto> can be ldap or ldaps. The option can be given multiple times.
+Map entries that include a server name override this option and it is then
+not used. Default is an empty list in which case either the server given
+in a map entry or the LDAP configured default is used. This uri list is read at
+startup and whenever the daemon receives a HUP signal.
+.TP
 .B SEARCH_BASE
 The base dn to use when searching for amap base dn. This entry may be
 given multiple times and each will be checked for a map base dn in
-the order they occur in the configuration.
+the order they occur in the configuration. The search base list is read
+at startup and whenever the daemon recieves a HUP signal.
 .TP
 .B MAP_OBJECT_CLASS
 The map object class. In the \fBnisMap\fP schema this corresponds to the class
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 2baf8b8..4068561 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -49,6 +49,8 @@ static struct ldap_schema common_schema[] = {
 };
 static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema);
 
+static LDAP *auth_init(const char *, struct lookup_context *);
+
 int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
 {
 	int rv;
@@ -59,10 +61,18 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
 		rv = ldap_simple_bind_s(ldap, NULL, NULL);
 
 	if (rv != LDAP_SUCCESS) {
-		crit(LOGOPT_ANY,
-		     MODPREFIX "Unable to bind to the LDAP server: "
-		     "%s, error %s", ctxt->server ? "" : "(default)",
-		     ldap_err2string(rv));
+		if (!ctxt->uri) {
+			crit(LOGOPT_ANY,
+			     MODPREFIX "Unable to bind to the LDAP server: "
+			     "%s, error %s", ctxt->server ? "" : "(default)",
+			     ldap_err2string(rv));
+		} else {
+			struct ldap_uri *uri;
+			uri = list_entry(ctxt->uri->next, struct ldap_uri, list);
+			warn(LOGOPT_ANY,
+			     MODPREFIX "Unable to bind to the LDAP server: "
+			     "%s, error %s", uri->uri, ldap_err2string(rv));
+		}
 		return -1;
 	}
 
@@ -98,20 +108,21 @@ int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt)
 	return rv;
 }
 
-LDAP *init_ldap_connection(struct lookup_context *ctxt)
+LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 {
 	LDAP *ldap = NULL;
-	int timeout = 8;
+	struct timeval timeout     = { ctxt->timeout, 0 };
+	struct timeval net_timeout = { ctxt->network_timeout, 0 };
 	int rv;
 
 	ctxt->version = 3;
 
 	/* Initialize the LDAP context. */
-	rv = ldap_initialize(&ldap, ctxt->server);
+	rv = ldap_initialize(&ldap, uri);
 	if (rv != LDAP_OPT_SUCCESS) {
 		crit(LOGOPT_ANY,
 		     MODPREFIX "couldn't initialize LDAP connection to %s",
-		     ctxt->server ? ctxt->server : "default server");
+		     uri ? uri : "default server");
 		return NULL;
 	}
 
@@ -120,7 +131,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
 	if (rv != LDAP_OPT_SUCCESS) {
 		/* fall back to LDAPv2 */
 		ldap_unbind_ext(ldap, NULL, NULL);
-		rv = ldap_initialize(&ldap, ctxt->server);
+		rv = ldap_initialize(&ldap, uri);
 		if (rv != LDAP_OPT_SUCCESS) {
 			crit(LOGOPT_ANY, MODPREFIX "couldn't initialize LDAP");
 			return NULL;
@@ -128,12 +139,22 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
 		ctxt->version = 2;
 	}
 
-	/* Sane network connection timeout */
-	rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);
+
+	if (ctxt->timeout != -1) {
+		/* Set synchronous call timeout */
+		rv = ldap_set_option(ldap, LDAP_OPT_TIMEOUT, &timeout);
+		if (rv != LDAP_OPT_SUCCESS)
+			info(LOGOPT_ANY, MODPREFIX
+			     "failed to set synchronous call timeout to %d",
+			     timeout.tv_sec);
+	}
+
+	/* Sane network timeout */
+	rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &net_timeout);
 	if (rv != LDAP_OPT_SUCCESS)
 		info(LOGOPT_ANY,
 		     MODPREFIX "failed to set connection timeout to %d",
-		     timeout);
+		     net_timeout.tv_sec);
 
 #ifdef WITH_SASL
 	if (ctxt->use_tls) {
@@ -159,7 +180,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
 				return NULL;
 			}
 			ctxt->use_tls = LDAP_TLS_DONT_USE;
-			ldap = init_ldap_connection(ctxt);
+			ldap = init_ldap_connection(uri, ctxt);
 			if (ldap)
 				ctxt->use_tls = LDAP_TLS_INIT;
 			return ldap;
@@ -271,7 +292,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
 	e = ldap_first_entry(ldap, result);
 	if (e) {
 		dn = ldap_get_dn(ldap, e);
-		debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn);
+		debug(LOGOPT_NONE, MODPREFIX "found query dn %s", dn);
 	} else {
 		debug(LOGOPT_NONE,
 		      MODPREFIX "query succeeded, no matches for %s",
@@ -378,16 +399,11 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
 	return 0;
 }
 
-static LDAP *do_connect(struct lookup_context *ctxt)
+static int do_bind(LDAP *ldap, struct lookup_context *ctxt)
 {
-	LDAP *ldap;
 	char *host = NULL, *nhost;
 	int rv, need_base = 1;
 
-	ldap = init_ldap_connection(ctxt);
-	if (!ldap)
-		return NULL;
-
 #ifdef WITH_SASL
 	debug(LOGOPT_NONE, "auth_required: %d, sasl_mech %s",
 	      ctxt->auth_required, ctxt->sasl_mech);
@@ -407,23 +423,19 @@ static LDAP *do_connect(struct lookup_context *ctxt)
 	debug(LOGOPT_NONE, MODPREFIX "ldap anonymous bind returned %d", rv);
 #endif
 
-	if (rv != 0) {
-		unbind_ldap_connection(ldap, ctxt);
-		return NULL;
-	}
+	if (rv != 0)
+		return 0;
 
 	rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
         if (rv != LDAP_SUCCESS || !host) {
-		unbind_ldap_connection(ldap, ctxt);
 		debug(LOGOPT_ANY, "failed to get hostname for connection");
-		return NULL;
+		return 0;
 	}
 
 	nhost = strdup(host);
 	if (!nhost) {
-		unbind_ldap_connection(ldap, ctxt);
 		debug(LOGOPT_ANY, "failed to alloc context for hostname");
-		return NULL;
+		return 0;
 	}
 	ldap_memfree(host);
 
@@ -443,7 +455,7 @@ static LDAP *do_connect(struct lookup_context *ctxt)
 	}
 
 	if (!need_base)
-		return ldap;
+		return 1;
 
 	/*
 	 * If the schema isn't defined in the configuration then check for
@@ -452,20 +464,134 @@ static LDAP *do_connect(struct lookup_context *ctxt)
 	 */
 	if (!ctxt->schema) {
 		if (!find_query_dn(ldap, ctxt)) {
-			unbind_ldap_connection(ldap, ctxt);
 			error(LOGOPT_ANY,
 		      	      MODPREFIX "failed to find valid query dn");
-			return NULL;
+			return 0;
 		}
 	} else {
 		const char *class = ctxt->schema->map_class;
 		const char *key = ctxt->schema->map_attr;
 		if (!get_query_dn(ldap, ctxt, class, key)) {
-			unbind_ldap_connection(ldap, ctxt);
 			error(LOGOPT_ANY, MODPREFIX "failed to get query dn");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static LDAP *do_connect(const char *uri, struct lookup_context *ctxt)
+{
+	LDAP *ldap;
+
+	ldap = init_ldap_connection(uri, ctxt);
+	if (!ldap)
+		return NULL;
+
+	if (!do_bind(ldap, ctxt)) {
+		unbind_ldap_connection(ldap, ctxt);
+		return NULL;
+	}
+
+	return ldap;
+}
+
+static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt)
+{
+	LDAP *ldap;
+
+#ifdef WITH_SASL
+	/*
+	 * Determine which authentication mechanism to use if we require
+	 * authentication.
+	 */
+	if (ctxt->auth_required & LDAP_AUTH_REQUIRED) {
+		ldap = auth_init(uri, ctxt);
+		if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT)
+			warn(LOGOPT_NONE,
+			     "no authentication mechanisms auto detected.");
+		if (!ldap) {
+			error(LOGOPT_ANY, MODPREFIX
+			      "cannot initialize authentication setup");
 			return NULL;
 		}
+
+		if (!do_bind(ldap, ctxt)) {
+			unbind_ldap_connection(ldap, ctxt);
+			error(LOGOPT_ANY, MODPREFIX "cannot bind to server");
+			return NULL;
+		}
+
+		return ldap;
+	}
+#endif
+
+	ldap = do_connect(uri, ctxt);
+	if (!ldap) {
+		error(LOGOPT_ANY, MODPREFIX "cannot connect to server");
+		return NULL;
+	}
+
+	return ldap;
+}
+
+static LDAP *find_server(struct lookup_context *ctxt)
+{
+	LDAP *ldap = NULL;
+	struct ldap_uri *this;
+	struct list_head *p;
+	LIST_HEAD(tmp);
+
+	/* Try each uri in list, add connect fails to tmp list */
+	p = ctxt->uri->next;
+	while(p != ctxt->uri) {
+		this = list_entry(p, struct ldap_uri, list);
+		p = p->next;
+		debug(LOGOPT_ANY, "check uri %s", this->uri);
+		ldap = connect_to_server(this->uri, ctxt);
+		if (ldap) {
+			debug(LOGOPT_ANY, "connexted to uri %s", this->uri);
+			break;
+		}
+		list_del_init(&this->list);
+		list_add_tail(&this->list, &tmp);
 	}
+	/*
+	 * Successfuly connected uri (head of list) and untried uris are
+	 * in ctxt->uri list. Make list of remainder and failed uris with
+	 * failed uris at end and assign back to ctxt-uri.
+	 */
+	list_splice(ctxt->uri, &tmp);
+	INIT_LIST_HEAD(ctxt->uri);
+	list_splice(&tmp, ctxt->uri);
+
+	return ldap;
+}
+
+static LDAP *do_reconnect(struct lookup_context *ctxt)
+{
+	LDAP *ldap;
+
+	if (ctxt->server || !ctxt->uri) {
+		ldap = do_connect(ctxt->server, ctxt);
+		return ldap;
+	} else {
+		struct ldap_uri *this;
+		this = list_entry(ctxt->uri->next, struct ldap_uri, list);
+		ldap = do_connect(this->uri, ctxt);
+		if (ldap)
+			return ldap;
+		/* Failed to connect, put at end of list */
+		list_del_init(&this->list);
+		list_add_tail(&this->list, ctxt->uri);
+	}
+
+	autofs_sasl_done(ctxt);
+
+	/* Current server failed connect, try the rest */
+	ldap = find_server(ctxt);
+	if (!ldap)
+		error(LOGOPT_ANY, MODPREFIX "failed to find available server");
 
 	return ldap;
 }
@@ -760,10 +886,10 @@ out:
  *  information.  If there is no configuration file, then we fall back to
  *  trying all supported authentication mechanisms until one works.
  *
- *  Returns 0 on success, with authtype, user and secret filled in as
- *  appropriate.  Returns -1 on failre.
+ *  Returns ldap connection on success, with authtype, user and secret
+ *  filled in as appropriate.  Returns NULL on failre.
  */
-int auth_init(struct lookup_context *ctxt)
+static LDAP *auth_init(const char *uri, struct lookup_context *ctxt)
 {
 	int ret;
 	LDAP *ldap;
@@ -776,14 +902,11 @@ int auth_init(struct lookup_context *ctxt)
 	 */
 	ret = parse_ldap_config(ctxt);
 	if (ret)
-		return -1;
-
-	if (ctxt->auth_required & LDAP_AUTH_NOTREQUIRED)
-		return 0;
+		return NULL;
 
-	ldap = init_ldap_connection(ctxt);
+	ldap = init_ldap_connection(uri, ctxt);
 	if (!ldap)
-		return -1;
+		return NULL;
 
 	/*
 	 *  Initialize the sasl library.  It is okay if user and secret
@@ -794,18 +917,12 @@ int auth_init(struct lookup_context *ctxt)
 	 *  the credential cache and the client and service principals.
 	 */
 	ret = autofs_sasl_init(ldap, ctxt);
-	unbind_ldap_connection(ldap, ctxt);
 	if (ret) {
 		ctxt->sasl_mech = NULL;
-		if (ctxt->auth_required & LDAP_AUTH_AUTODETECT) {
-			warn(LOGOPT_NONE,
-			     "no authentication mechanisms auto detected.");
-			return 0;
-		}
-		return -1;
+		return NULL;
 	}
 
-	return 0;
+	return ldap;
 }
 #endif
 
@@ -1036,6 +1153,8 @@ static void free_context(struct lookup_context *ctxt)
 		free(ctxt->cur_host);
 	if (ctxt->base)
 		free(ctxt->base);
+	if (ctxt->uri)
+		defaults_free_uris(ctxt->uri);
 	if (ctxt->sdns)
 		defaults_free_searchdns(ctxt->sdns);
 	free(ctxt);
@@ -1043,6 +1162,30 @@ static void free_context(struct lookup_context *ctxt)
 	return;
 }
 
+static void validate_uris(struct list_head *list)
+{
+	struct list_head *next;
+
+	next = list->next;
+	while (next != list) {
+		struct ldap_uri *this;
+
+		this = list_entry(next, struct ldap_uri, list);
+		next = next->next;
+
+		/* At least we get some basic validation */
+		if (!ldap_is_ldap_url(this->uri)) {
+			warn(LOGOPT_ANY,
+			     "removed invalid uri from list, %s", this->uri);
+			list_del(&this->list);
+			free(this->uri);
+			free(this);
+		}
+	}
+
+	return;			
+}
+
 /*
  * This initializes a context (persistent non-global data) for queries to
  * this module.  Return zero if we succeed.
@@ -1051,7 +1194,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 {
 	struct lookup_context *ctxt;
 	char buf[MAX_ERR_BUF];
-	int ret;
 	LDAP *ldap = NULL;
 
 	*context = NULL;
@@ -1079,33 +1221,42 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		return 1;
 	}
 
-#ifdef WITH_SASL
-	/*
-	 * Determine which authentication mechanism to use.  We sanity-
-	 * check by binding to the server temporarily.
-	 */
-	ret = auth_init(ctxt);
-	if (ret && (ctxt->auth_required & LDAP_AUTH_REQUIRED)) {
-		error(LOGOPT_ANY, MODPREFIX
-		      "cannot initialize authentication setup");
-		free_context(ctxt);
-		return 1;
+	ctxt->timeout = defaults_get_ldap_timeout();
+	ctxt->network_timeout = defaults_get_ldap_network_timeout();
+
+	if (!ctxt->server) {
+		struct list_head *uris = defaults_get_uris();
+		if (uris) {
+			validate_uris(uris);
+			if (!list_empty(uris))
+				ctxt->uri = uris;
+			else 
+				free(uris);
+		}
 	}
-#endif
 
-	ldap = do_connect(ctxt);
-	if (!ldap) {
-		error(LOGOPT_ANY, MODPREFIX "cannot connect to server");
-		free_context(ctxt);
-		return 1;
+	if (ctxt->server || !ctxt->uri) {
+		ldap = connect_to_server(ctxt->server, ctxt);
+		if (!ldap) {
+			free_context(ctxt);
+			return 1;
+		}
+	} else {
+		ldap = find_server(ctxt);
+		if (!ldap) {
+			free_context(ctxt);
+			error(LOGOPT_ANY, MODPREFIX
+			     "failed to find available server");
+			return 1;
+		}
 	}
 	unbind_ldap_connection(ldap, ctxt);
 
 	/* Open the parser, if we can. */
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parse) {
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
 		free_context(ctxt);
+		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
 		return 1;
 	}
 	*context = ctxt;
@@ -1153,7 +1304,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	query[l] = '\0';
 
 	/* Initialize the LDAP context. */
-	ldap = do_connect(ctxt);
+	ldap = do_reconnect(ctxt);
 	if (!ldap)
 		return NSS_STATUS_UNAVAIL;
 
@@ -1305,7 +1456,7 @@ static int read_one_map(struct autofs_point *ap,
 	query[l] = '\0';
 
 	/* Initialize the LDAP context. */
-	ldap = do_connect(ctxt);
+	ldap = do_reconnect(ctxt);
 	if (!ldap)
 		return NSS_STATUS_UNAVAIL;
 
@@ -1536,6 +1687,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 	if (ret != NSS_STATUS_SUCCESS) {
 		switch (rv) {
 		case LDAP_SIZELIMIT_EXCEEDED:
+			crit(ap->logopt, MODPREFIX
+			     "Unable to download entire LDAP map for: %s",
+			     ap->path);
 		case LDAP_UNWILLING_TO_PERFORM:
 			pthread_setcancelstate(cur_state, NULL);
 			return NSS_STATUS_UNAVAIL;
@@ -1612,7 +1766,7 @@ static int lookup_one(struct autofs_point *ap,
 	query[ql] = '\0';
 
 	/* Initialize the LDAP context. */
-	ldap = do_connect(ctxt);
+	ldap = do_reconnect(ctxt);
 	if (!ldap)
 		return CHE_FAIL;
 
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index 2b1e20a..f01ee5f 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -23,6 +23,25 @@ BROWSE_MODE="no"
 #
 # Define base dn for map dn lookup.
 #
+# Define server URIs
+#
+# LDAP_URI - space seperated list of server uris of the form
+# 	     <proto>://<server>[/] where <proto> can be ldap
+# 	     or ldaps. The option can be given multiple times.
+# 	     Map entries that include a server name override
+# 	     this option.
+#
+#LDAP_URI=""
+#
+# LDAP__TIMEOUT - timeout value for the synchronous API  calls
+#		  (default is LDAP library default).
+#
+#LDAP_TIMEOUT=-1
+#
+# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8).
+#
+#LDAP_NETWORK_TIMEOUT=8
+#
 # SEARCH_BASE - base dn to use for searching for map search dn.
 # 		Multiple entries can be given and they are checked
 # 		in the order they occur here.
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 2b1e20a..028341c 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -21,6 +21,25 @@ BROWSE_MODE="no"
 #
 #LOGGING="none"
 #
+# Define server URIs
+#
+# LDAP_URI - space seperated list of server uris of the form
+# 	     <proto>://<server>[/] where <proto> can be ldap
+# 	     or ldaps. The option can be given multiple times.
+# 	     Map entries that include a server name override
+# 	     this option.
+#
+#LDAP_URI=""
+#
+# LDAP__TIMEOUT - timeout value for the synchronous API  calls
+#		  (default is LDAP library default).
+#
+#LDAP_TIMEOUT=-1
+#
+# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8).
+#
+#LDAP_NETWORK_TIMEOUT=8
+#
 # Define base dn for map dn lookup.
 #
 # SEARCH_BASE - base dn to use for searching for map search dn.

autofs-5.0.2-autofs-5-typo.patch:

--- NEW FILE autofs-5.0.2-autofs-5-typo.patch ---
diff --git a/man/autofs.5 b/man/autofs.5
index eb15c2a..5a01791 100644
--- a/man/autofs.5
+++ b/man/autofs.5
@@ -128,7 +128,7 @@ entry looks like this:
 .RS +.2i
 .ta 1.0i
 .nf
-*	server:i/export/home/&
+*	server:/export/home/&
 .fi
 .RE
 .sp

autofs-5.0.2-basedn-with-spaces.patch:

--- NEW FILE autofs-5.0.2-basedn-with-spaces.patch ---
diff -Nurp autofs-5.0.2.orig/lib/master_tok.l autofs-5.0.2/lib/master_tok.l
--- autofs-5.0.2.orig/lib/master_tok.l	2007-11-20 15:37:48.000000000 +0900
+++ autofs-5.0.2/lib/master_tok.l	2007-11-20 15:38:21.000000000 +0900
@@ -108,7 +108,8 @@ AT_DC		([dD][[cC])
 AT_O		([oO])
 AT_C		([cC])
 DNATTRSTR	{AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}
-DNNAMESTR	([[:alnum:]_.\-]+)
+DNNAMESTR1	([[:alnum:]_.\- ]+)
+DNNAMESTR2	([[:alnum:]_.\-]+)
 
 INTMAP		(-hosts|-null)
 MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
@@ -281,7 +282,12 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--
 		return EQUAL;
 	}
 
-	{DNNAMESTR} {
+	{DNNAMESTR1}/"," {
+		strcpy(master_lval.strtype, master_text);
+		return DNNAME;
+	}
+
+	{DNNAMESTR2} {
 		strcpy(master_lval.strtype, master_text);
 		return DNNAME;
 	}
@@ -378,7 +384,13 @@ void master_set_scan_buffer(const char *
 {
 	line = buffer;
 	line_pos = &line[0];
-	line_lim = line + strlen(buffer);
+	/*
+	 * Ensure buffer is 1 greater than string and is zeroed before
+	 * the parse so we can fit the extra NULL which allows us to
+	 * explicitly match an end of line within the buffer (ie. the
+	 * need for 2 NULLS when parsing in memeory buffers).
+	 */
+	line_lim = line + strlen(buffer) + 1;
 }
 
 #define min(a,b) (((a) < (b)) ? (a) : (b))
diff -Nurp autofs-5.0.2.orig/modules/lookup_file.c autofs-5.0.2/modules/lookup_file.c
--- autofs-5.0.2.orig/modules/lookup_file.c	2007-11-20 15:37:48.000000000 +0900
+++ autofs-5.0.2/modules/lookup_file.c	2007-11-20 15:38:18.000000000 +0900
@@ -479,7 +479,7 @@ int lookup_read_master(struct master *ma
 
 			master->name = save_name;
 		} else {
-			blen = path_len + 1 + ent_len + 1;
+			blen = path_len + 1 + ent_len + 2;
 			buffer = malloc(blen);
 			if (!buffer) {
 				error(logopt,
diff -Nurp autofs-5.0.2.orig/modules/lookup_ldap.c autofs-5.0.2/modules/lookup_ldap.c
--- autofs-5.0.2.orig/modules/lookup_ldap.c	2007-11-20 15:37:48.000000000 +0900
+++ autofs-5.0.2/modules/lookup_ldap.c	2007-11-20 15:38:18.000000000 +0900
@@ -1368,7 +1368,7 @@ int lookup_read_master(struct master *ma
 			goto next;
 		}
 
-		blen = strlen(*keyValue) + 1 + strlen(*values) + 1;
+		blen = strlen(*keyValue) + 1 + strlen(*values) + 2;
 		if (blen > PARSE_MAX_BUF) {
 			error(logopt, MODPREFIX "map entry too long");
 			ldap_value_free(values);
diff -Nurp autofs-5.0.2.orig/modules/lookup_nisplus.c autofs-5.0.2/modules/lookup_nisplus.c
--- autofs-5.0.2.orig/modules/lookup_nisplus.c	2007-11-20 15:37:48.000000000 +0900
+++ autofs-5.0.2/modules/lookup_nisplus.c	2007-11-20 15:38:18.000000000 +0900
@@ -90,7 +90,7 @@ int lookup_read_master(struct master *ma
 	char *path, *ent;
 	char *buffer;
 	char buf[MAX_ERR_BUF];
-	int cur_state;
+	int cur_state, len;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
@@ -138,11 +138,13 @@ int lookup_read_master(struct master *ma
 
 		ent = ENTRY_VAL(this, 1);
 
-		buffer = malloc(ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 1);
+		len = ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 2;
+		buffer = malloc(len);
 		if (!buffer) {
 			logerr(MODPREFIX "could not malloc parse buffer");
 			continue;
 		}
+		memset(buffer, 0, len);
 
 		strcat(buffer, path);
 		strcat(buffer, " ");
diff -Nurp autofs-5.0.2.orig/modules/lookup_yp.c autofs-5.0.2/modules/lookup_yp.c
--- autofs-5.0.2.orig/modules/lookup_yp.c	2007-11-20 15:37:48.000000000 +0900
+++ autofs-5.0.2/modules/lookup_yp.c	2007-11-20 15:38:18.000000000 +0900
@@ -178,7 +178,7 @@ int yp_all_master_callback(int status, c
 	*(ypkey + ypkeylen) = '\0';
 	*(val + vallen) = '\0';
 
-	len = ypkeylen + 1 + vallen + 1;
+	len = ypkeylen + 1 + vallen + 2;
 
 	buffer = alloca(len);
 	if (!buffer) {

autofs-5.0.2-check-auto_master.patch:

--- NEW FILE autofs-5.0.2-check-auto_master.patch ---
diff --git a/daemon/lookup.c b/daemon/lookup.c
index fd99cf2..0be10d3 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -222,6 +222,28 @@ int lookup_nss_read_master(struct master *master, time_t age)
 		      "reading master %s %s", this->source, master->name);
 
 		result = read_master_map(master, this->source, age);
+
+		/*
+		 * If the name of the master map hasn't been explicitly
+		 * configured and we're not reading an included master map
+		 * then we're using auto.master as the default. Many setups
+		 * also use auto_master as the default master map so we
+		 * check for this map when auto.master isn't found.
+		 */
+		if (result != NSS_STATUS_SUCCESS &&
+		    !master->depth && !defaults_master_set()) {
+			char *tmp = strchr(master->name, '.');
+			if (tmp) {
+				debug(logopt,
+				      "%s not found, replacing '.' with '_'",
+				       master->name);
+				*tmp = '_';
+				result = read_master_map(master, this->source, age);
+				if (result != NSS_STATUS_SUCCESS)
+					*tmp = '.';
+			}
+		}
+
 		if (result == NSS_STATUS_UNKNOWN) {
 			debug(logopt, "no map - continuing to next source");
 			continue;
diff --git a/include/defaults.h b/include/defaults.h
index 0e0e2a5..e296478 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -43,6 +43,7 @@ struct ldap_searchdn;
 
 unsigned int defaults_read_config(unsigned int);
 const char *defaults_get_master_map(void);
+int defaults_master_set(void);
 unsigned int defaults_get_timeout(void);
 unsigned int defaults_get_browse_mode(void);
 unsigned int defaults_get_logging(void);
diff --git a/lib/defaults.c b/lib/defaults.c
index 94885e8..f494103 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -350,6 +350,15 @@ const char *defaults_get_master_map(void)
 	return (const char *) master;
 }
 
+int defaults_master_set(void)
+{
+	char *val = getenv(ENV_NAME_MASTER_MAP);
+	if (!val)
+		return 0;
+
+	return 1;
+}
+
 unsigned int defaults_get_timeout(void)
 {
 	long timeout;

autofs-5.0.2-check-mtab-updated.patch:

--- NEW FILE autofs-5.0.2-check-mtab-updated.patch ---
diff -up autofs-5.0.2/include/automount.h.check-mtab-updated autofs-5.0.2/include/automount.h
--- autofs-5.0.2/include/automount.h.check-mtab-updated	2007-11-20 16:10:13.000000000 +0900
+++ autofs-5.0.2/include/automount.h	2007-11-20 16:10:36.000000000 +0900
@@ -78,6 +78,7 @@ int load_autofs4_module(void);
 #define MOUNTED_LOCK	_PATH_MOUNTED "~"	/* mounts' lock file */
 #define MTAB_NOTUPDATED 0x1000			/* mtab succeded but not updated */
 #define NOT_MOUNTED     0x0100			/* path notmounted */
+#define MNT_FORCE_FAIL -1
 #define _PROC_MOUNTS	"/proc/mounts"
 
 /* Constants for lookup modules */
diff -up autofs-5.0.2/modules/mount_bind.c.check-mtab-updated autofs-5.0.2/modules/mount_bind.c
--- autofs-5.0.2/modules/mount_bind.c.check-mtab-updated	2007-11-20 16:10:58.000000000 +0900
+++ autofs-5.0.2/modules/mount_bind.c	2007-11-20 16:11:49.000000000 +0900
@@ -147,7 +147,7 @@ int mount_mount(struct autofs_point *ap,
 			if ((!ap->ghost && name_len) || !existed)
 				rmdir_path(ap, fullpath, ap->dev);
 
-			return 1;
+			return err;
 		} else {
 			debug(ap->logopt,
 			      MODPREFIX "mounted %s type %s on %s",
diff -up autofs-5.0.2/modules/mount_nfs.c.check-mtab-updated autofs-5.0.2/modules/mount_nfs.c
--- autofs-5.0.2/modules/mount_nfs.c.check-mtab-updated	2007-11-20 16:11:08.000000000 +0900
+++ autofs-5.0.2/modules/mount_nfs.c	2007-11-20 16:12:44.000000000 +0900
@@ -233,6 +233,10 @@ int mount_mount(struct autofs_point *ap,
 				return 0;
 			}
 
+			/* Failed to update mtab, don't try any more */
+			if (err == MNT_FORCE_FAIL)
+				goto forced_fail;
+
 			/* No hostname, can't be NFS */
 			if (!this->name) {
 				this = this->next;
@@ -275,6 +279,7 @@ int mount_mount(struct autofs_point *ap,
 		this = this->next;
 	}
 
+forced_fail:
 	free_host_list(&hosts);
 	ap->ghost = save_ghost;
 
diff -up autofs-5.0.2/daemon/spawn.c.check-mtab-updated autofs-5.0.2/daemon/spawn.c
--- autofs-5.0.2/daemon/spawn.c.check-mtab-updated	2007-11-20 16:06:45.000000000 +0900
+++ autofs-5.0.2/daemon/spawn.c	2007-11-20 16:06:45.000000000 +0900
@@ -25,6 +25,7 @@
 #include <time.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/mount.h>
 
 #include "automount.h"
 
@@ -268,9 +269,11 @@ int spawn_mount(unsigned logopt, ...)
 	char **argv, **p;
 	char prog[] = PATH_MOUNT;
 	char arg0[] = PATH_MOUNT;
+	/* In case we need to use the fake option to mount */
+	char arg_fake[] = "-f";
 	unsigned int options;
 	unsigned int retries = MTAB_LOCK_RETRIES;
-	int ret;
+	int ret, printed = 0;
 
 	/* If we use mount locking we can't validate the location */
 #ifdef ENABLE_MOUNT_LOCKING
@@ -283,7 +286,8 @@ int spawn_mount(unsigned logopt, ...)
 	for (argc = 1; va_arg(arg, char *); argc++);
 	va_end(arg);
 
-	if (!(argv = alloca(sizeof(char *) * argc + 1)))
+	/* Alloc 1 extra slot in case we need to use the "-f" option */
+	if (!(argv = alloca(sizeof(char *) * argc + 2)))
 		return -1;
 
 	argv[0] = arg0;
@@ -304,11 +308,52 @@ int spawn_mount(unsigned logopt, ...)
 
 	while (retries--) {
 		ret = do_spawn(logopt, options, prog, (const char **) argv);
-		if (ret & MTAB_NOTUPDATED)
+		if (ret & MTAB_NOTUPDATED) {
+			struct timespec tm = {3, 0};
+
+			/*
+			 * If the mount succeeded but the mtab was not
+			 * updated, then retry the mount with the -f (fake)
+			 * option to just update the mtab.
+			 */
+			if (!printed) {
+				debug(logopt, "mount failed with error code 16"
+				      ", retrying with the -f option");
+				printed = 1;
+			}
+
+			/*
+			 * Move the last two args so do_spawn() can find the
+			 * mount target.
+			 */
+			if (!argv[argc]) {
+				argv[argc + 1] = NULL;
+				argv[argc] = argv[argc - 1];
+				argv[argc - 1] = argv[argc - 2];
+				argv[argc - 2] = arg_fake;
+			}
+
+			nanosleep(&tm, NULL);
+
 			continue;
+		}
 		break;
 	}
 
+	/* This is not a fatal error */
+	if (ret == MTAB_NOTUPDATED) {
+		/*
+		 * Version 5 requires that /etc/mtab be in sync with
+		 * /proc/mounts. If we're unable to update matb after
+		 * retrying then we have no choice but umount the mount
+		 * and return a fail.
+		 */
+		warn(logopt,
+		     "Unable to update the mtab file, forcing mount fail!");
+		umount(argv[argc]);
+		ret = MNT_FORCE_FAIL;
+	}
+
 	return ret;
 }
 
@@ -328,9 +373,11 @@ int spawn_bind_mount(unsigned logopt, ..
 	char prog[] = PATH_MOUNT;
 	char arg0[] = PATH_MOUNT;
 	char bind[] = "--bind";
+	/* In case we need to use the fake option to mount */
+	char arg_fake[] = "-f";
 	unsigned int options;
 	unsigned int retries = MTAB_LOCK_RETRIES;
-	int ret;
+	int ret, printed = 0;
 
 	/* If we use mount locking we can't validate the location */
 #ifdef ENABLE_MOUNT_LOCKING
@@ -339,8 +386,12 @@ int spawn_bind_mount(unsigned logopt, ..
 	options = SPAWN_OPT_ACCESS;
 #endif
 
+	/*
+	 * Alloc 2 extra slots, one for the bind option and one in case
+	 * we need to use the "-f" option
+	 */
 	va_start(arg, logopt);
-	for (argc = 1; va_arg(arg, char *); argc++);
+	for (argc = 2; va_arg(arg, char *); argc++);
 	va_end(arg);
 
 	if (!(argv = alloca(sizeof(char *) * argc + 2)))
@@ -356,11 +407,52 @@ int spawn_bind_mount(unsigned logopt, ..
 
 	while (retries--) {
 		ret = do_spawn(logopt, options, prog, (const char **) argv);
-		if (ret & MTAB_NOTUPDATED)
+		if (ret & MTAB_NOTUPDATED) {
+			struct timespec tm = {3, 0};
+
+			/*
+			 * If the mount succeeded but the mtab was not
+			 * updated, then retry the mount with the -f (fake)
+			 * option to just update the mtab.
+			 */
+			if (!printed) {
+				debug(logopt, "mount failed with error code 16"
+				      ", retrying with the -f option");
+				printed = 1;
+			}
+
+			/*
+			 * Move the last two args so do_spawn() can find the
+			 * mount target.
+			 */
+			if (!argv[argc]) {
+				argv[argc + 1] = NULL;
+				argv[argc] = argv[argc - 1];
+				argv[argc - 1] = argv[argc - 2];
+				argv[argc - 2] = arg_fake;
+			}
+
+			nanosleep(&tm, NULL);
+
 			continue;
+		}
 		break;
 	}
 
+	/* This is not a fatal error */
+	if (ret == MTAB_NOTUPDATED) {
+		/*
+		 * Version 5 requires that /etc/mtab be in sync with
+		 * /proc/mounts. If we're unable to update matb after
+		 * retrying then we have no choice but umount the mount
+		 * and return a fail.
+		 */
+		warn(logopt,
+		     "Unable to update the mtab file, forcing mount fail!");
+		umount(argv[argc]);
+		ret = MNT_FORCE_FAIL;
+	}
+
 	return ret;
 }
 
@@ -373,7 +465,7 @@ int spawn_umount(unsigned logopt, ...)
 	char arg0[] = PATH_UMOUNT;
 	unsigned int options;
 	unsigned int retries = MTAB_LOCK_RETRIES;
-	int ret;
+	int ret, printed = 0;
 
 #ifdef ENABLE_MOUNT_LOCKING
 	options = SPAWN_OPT_LOCK;
@@ -397,9 +489,37 @@ int spawn_umount(unsigned logopt, ...)
 
 	while (retries--) {
 		ret = do_spawn(logopt, options, prog, (const char **) argv);
-		if (ret & MTAB_NOTUPDATED)
-			continue;
-		break;
+		if (ret & MTAB_NOTUPDATED) {
+			/*
+			 * If the mount succeeded but the mtab was not
+			 * updated, then retry the umount just to update
+			 * the mtab.
+			 */
+			if (!printed) {
+				debug(logopt, "mount failed with error code 16"
+				      ", retrying with the -f option");
+				printed = 1;
+			}
+		} else {
+			/*
+			 * umount does not support the "fake" option.  Thus,
+			 * if we got a return value of MTAB_NOTUPDATED the
+			 * first time, that means the umount actually
+			 * succeeded.  Then, a following umount will fail
+			 * due to the fact that nothing was mounted on the
+			 * mount point. So, report this as success.
+			 */
+			if (retries < MTAB_LOCK_RETRIES - 1)
+				ret = 0;
+			break;
+		}
+	}
+
+	/* This is not a fatal error */
+	if (ret == MTAB_NOTUPDATED) {
+		warn(logopt, "Unable to update the mtab file, /proc/mounts "
+		     "and /etc/mtab will differ");
+		ret = 0;
 	}
 
 	return ret;

autofs-5.0.2-dynamic-logging-fixes.patch:

--- NEW FILE autofs-5.0.2-dynamic-logging-fixes.patch ---
diff --git a/Makefile.conf.in b/Makefile.conf.in
index ea5fe1d..09c3129 100644
--- a/Makefile.conf.in
+++ b/Makefile.conf.in
@@ -71,6 +71,9 @@ autofsconfdir = @confdir@
 # Location for autofs maps
 autofsmapdir = @mapdir@
 
+# Location for autofs fifos
+autofsfifodir = @fifodir@
+
 # Where to install the automount program
 sbindir = @sbindir@
 
diff --git a/aclocal.m4 b/aclocal.m4
index ffeb232..118ef0d 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -120,6 +120,22 @@ AC_DEFUN(AF_MAP_D,
   done
 fi])
 
+dnl --------------------------------------------------------------------------
+dnl AF_FIFO_D
+dnl
+dnl Check the location of the autofs fifos directory
+dnl --------------------------------------------------------------------------
+AC_DEFUN(AF_FIFO_D,
+[if test -z "$fifodir"; then
+  for fifo_d in /var/run /tmp; do
+    if test -z "$fifodir"; then
+      if test -d "$fifo_d"; then
+        fifodir="$fifo_d"
+      fi
+    fi
+  done
+fi])
+
 dnl ----------------------------------- ##                   -*- Autoconf -*-
 dnl Check if --with-dmalloc was given.  ##
 dnl From Franc,ois Pinard               ##
diff --git a/configure b/configure
index 3508224..0360086 100755
--- a/configure
+++ b/configure
@@ -654,6 +654,7 @@ target_alias
 initdir
 confdir
 mapdir
+fifodir
 DMALLOCLIB
 MOUNT
 HAVE_MOUNT
@@ -1293,6 +1294,7 @@ Optional Packages:
   --with-path=PATH	  look in PATH for binaries needed by the automounter
   --with-confdir=DIR	  use DIR for autofs configuration files
   --with-mapdir=PATH	  look in PATH for mount maps used by the automounter
+  --with-fifodir=PATH	   use PATH as the directory for fifos used by the automounter
   --with-dmalloc          use dmalloc, as in
 			  http://www.dmalloc.com/dmalloc.tar.gz
   --with-hesiod=DIR	  enable Hesiod support (libs and includes in DIR)
@@ -1844,6 +1846,36 @@ echo "${ECHO_T}$mapdir" >&6; }
 
 
 #
+# The user can specify --with-fifodir=PATH to specify where autofs fifos go
+#
+if test -z "$fifodir"; then
+  for fifo_d in /var/run /tmp; do
+    if test -z "$fifodir"; then
+      if test -d "$fifo_d"; then
+        fifodir="$fifo_d"
+      fi
+    fi
+  done
+fi
+
+# Check whether --with-fifodir was given.
+if test "${with_fifodir+set}" = set; then
+  withval=$with_fifodir; if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no"
+	then
+		:
+	else
+		fifodir="${withval}"
+	fi
+
+fi
+
+{ echo "$as_me:$LINENO: checking for autofs fifos directory" >&5
+echo $ECHO_N "checking for autofs fifos directory... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $fifodir" >&5
+echo "${ECHO_T}$fifodir" >&6; }
+
+
+#
 # Optional include dmalloc
 #
 { echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5
@@ -6074,6 +6106,7 @@ target_alias!$target_alias$ac_delim
 initdir!$initdir$ac_delim
 confdir!$confdir$ac_delim
 mapdir!$mapdir$ac_delim
+fifodir!$fifodir$ac_delim
 DMALLOCLIB!$DMALLOCLIB$ac_delim
 MOUNT!$MOUNT$ac_delim
 HAVE_MOUNT!$HAVE_MOUNT$ac_delim
@@ -6124,7 +6157,7 @@ LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 89; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.in b/configure.in
index 8cddf90..a83b3f1 100644
--- a/configure.in
+++ b/configure.in
@@ -79,6 +79,23 @@ AC_MSG_RESULT([$mapdir])
 AC_SUBST(mapdir)
 
 #
+# The user can specify --with-fifodir=PATH to specify where autofs fifos go
+#
+AF_FIFO_D()
+AC_ARG_WITH(fifodir,
+[  --with-fifodir=PATH	   use PATH as the directory for fifos used by the automounter],
+	if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no"
+	then
+		:
+	else
+		fifodir="${withval}"
+	fi
+)
+AC_MSG_CHECKING([for autofs fifos directory])
+AC_MSG_RESULT([$fifodir])
+AC_SUBST(fifodir)
+
+#
 # Optional include dmalloc
 #
 AM_WITH_DMALLOC()
diff --git a/daemon/Makefile b/daemon/Makefile
index 4ee70eb..528a684 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -16,6 +16,7 @@ CFLAGS += -rdynamic $(DAEMON_CFLAGS) -D_GNU_SOURCE -I../include
 CFLAGS += -DAUTOFS_LIB_DIR=\"$(autofslibdir)\" 
 CFLAGS += -DAUTOFS_MAP_DIR=\"$(autofsmapdir)\"
 CFLAGS += -DAUTOFS_CONF_DIR=\"$(autofsconfdir)\"
+CFLAGS += -DAUTOFS_FIFO_DIR=\"$(autofsfifodir)\"
 CFLAGS += -DVERSION_STRING=\"$(version)\"
 LDFLAGS += -rdynamic
 LIBS = -ldl
diff --git a/daemon/automount.c b/daemon/automount.c
index 7e7d1e6..a12b6da 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -50,6 +50,9 @@ const char *libdir = AUTOFS_LIB_DIR;	/* Location of library modules */
 const char *mapdir = AUTOFS_MAP_DIR;	/* Location of mount maps */
 const char *confdir = AUTOFS_CONF_DIR;	/* Location of autofs config file */
 
+/* autofs fifo name prefix */
+const char *fifodir = AUTOFS_FIFO_DIR "/autofs.fifo";
+
 const char *global_options;		/* Global option, from command line */
 
 static char *pid_file = NULL;		/* File in which to keep pid */
@@ -650,14 +653,13 @@ static int fullread(int fd, void *ptr, size_t len)
 static char *automount_path_to_fifo(unsigned logopt, const char *path)
 {
 	char *fifo_name, *p;
-	int  name_len = strlen(path) + strlen(AUTOFS_LOGPRI_FIFO) + 1;
+	int  name_len = strlen(path) + strlen(fifodir) + 1;
 	int ret;
 
 	fifo_name = malloc(name_len);
 	if (!fifo_name)
 		return NULL;
-	ret = snprintf(fifo_name, name_len, "%s%s",
-		       AUTOFS_LOGPRI_FIFO, path);
+	ret = snprintf(fifo_name, name_len, "%s%s", fifodir, path);
 	if (ret >= name_len) {
 		info(logopt,
 		     "fifo path for \"%s\" truncated to \"%s\".  This may "
@@ -670,7 +672,7 @@ static char *automount_path_to_fifo(unsigned logopt, const char *path)
 	 *  create the fifo name, we will just replace instances of '/' with
 	 *  '-'. 
 	 */
-	p = fifo_name + strlen(AUTOFS_LOGPRI_FIFO);
+	p = fifo_name + strlen(fifodir);
 	while (*p != '\0') {
 		if (*p == '/')
 			*p = '-';
@@ -685,8 +687,9 @@ static char *automount_path_to_fifo(unsigned logopt, const char *path)
 static int create_logpri_fifo(struct autofs_point *ap)
 {
 	int ret = -1;
-	int fd;
+	int fd, cl_flags;
 	char *fifo_name;
+	char buf[MAX_ERR_BUF];
 
 	fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
 	if (!fifo_name) {
@@ -704,18 +707,27 @@ static int create_logpri_fifo(struct autofs_point *ap)
 
 	ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR);
 	if (ret != 0) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		crit(ap->logopt,
-		     "mkfifo for %s returned %d", fifo_name, errno);
+		     "mkfifo for %s failed: %s", fifo_name, estr);
 		goto out_free;
 	}
 
 	fd = open(fifo_name, O_RDWR|O_NONBLOCK);
 	if (fd < 0) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		crit(ap->logopt,
-		     "Failed to open %s, errno %d", fifo_name, errno);
+		     "Failed to open %s: %s", fifo_name, estr);
+		unlink(fifo_name);
+		ret = -1;
 		goto out_free;
 	}
 
+	if ((cl_flags = fcntl(fd, F_GETFD, 0)) != -1) {
+		cl_flags |= FD_CLOEXEC;
+		fcntl(fd, F_SETFD, cl_flags);
+	}
+
 	ap->logpri_fifo = fd;
 
 out_free:
@@ -728,6 +740,10 @@ static int destroy_logpri_fifo(struct autofs_point *ap)
 	int ret = -1;
 	int fd = ap->logpri_fifo;
 	char *fifo_name;
+	char buf[MAX_ERR_BUF];
+
+	if (fd == -1)
+		return 0;
 
 	fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
 	if (!fifo_name) {
@@ -739,8 +755,9 @@ static int destroy_logpri_fifo(struct autofs_point *ap)
 
 	ret = close(fd);
 	if (ret != 0) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		warn(ap->logopt,
-		     "close for fifo %s returned %d", fifo_name, errno);
+		     "close for fifo %s: %s", fifo_name, estr);
 	}
 
 	ret = unlink(fifo_name);
@@ -760,11 +777,13 @@ static void handle_fifo_message(struct autofs_point *ap, int fd)
 	char buffer[PIPE_BUF];
 	char *end;
 	long pri;
+	char buf[MAX_ERR_BUF];
 
 	memset(buffer, 0, sizeof(buffer));
 	ret = read(fd, &buffer, sizeof(buffer));
 	if (ret < 0) {
-		warn(ap->logopt, "read on fifo returned error %d", errno);
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		warn(ap->logopt, "read on fifo returned error: %s", estr);
 		return;
 	}
 
@@ -846,16 +865,18 @@ static int set_log_priority(const char *path, int priority)
 	 */
 	fd = open(fifo_name, O_WRONLY|O_NONBLOCK);
 	if (fd < 0) {
-		fprintf(stderr, "%s: open of %s failed with %d\n",
-			__FUNCTION__, fifo_name, errno);
+		fprintf(stderr, "%s: open of %s failed with %s\n",
+			__FUNCTION__, fifo_name, strerror(errno));
+		fprintf(stderr, "%s: perhaps the fifo wasn't setup,"
+			" please check your log for more information\n", __FUNCTION__);
 		free(fifo_name);
 		return -1;
 	}
 
 	if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
 		fprintf(stderr, "Failed to change logging priority.  ");
-		fprintf(stderr, "write to fifo failed with errno %d.\n",
-			errno);
+		fprintf(stderr, "write to fifo failed: %s.\n",
+			strerror(errno));
 		close(fd);
 		free(fifo_name);
 		return -1;
@@ -870,6 +891,7 @@ static int set_log_priority(const char *path, int priority)
 static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt)
 {
 	struct pollfd fds[3];
+	int pollfds = 3;
 	char buf[MAX_ERR_BUF];
 
 	fds[0].fd = ap->pipefd;
@@ -878,9 +900,11 @@ static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt)
 	fds[1].events = POLLIN;
 	fds[2].fd = ap->logpri_fifo;
 	fds[2].events = POLLIN;
+	if (fds[2].fd  == -1)
+		pollfds--;
 
 	for (;;) {
-		if (poll(fds, 3, -1) == -1) {
+		if (poll(fds, pollfds, -1) == -1) {
 			char *estr;
 			if (errno == EINTR)
 				continue;
@@ -930,7 +954,7 @@ static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt)
 		if (fds[0].revents & POLLIN)
 			return fullread(ap->pipefd, pkt, kpkt_len);
 
-		if (fds[2].revents & POLLIN) {
+		if (fds[2].fd != -1 && fds[2].revents & POLLIN) {
 			debug(ap->logopt, "message pending on control fifo.");
 			handle_fifo_message(ap, fds[2].fd);
 		}
@@ -983,7 +1007,6 @@ static int autofs_init_ap(struct autofs_point *ap)
 		crit(ap->logopt,
 		     "failed to create commumication pipe for autofs path %s",
 		     ap->path);
-		free(ap->path);
 		return -1;
 	}
 
@@ -1006,7 +1029,6 @@ static int autofs_init_ap(struct autofs_point *ap)
 		     "failed create state pipe for autofs path %s", ap->path);
 		close(ap->pipefd);
 		close(ap->kpipefd);	/* Close kernel pipe end */
-		free(ap->path);
 		return -1;
 	}
 
@@ -1021,15 +1043,8 @@ static int autofs_init_ap(struct autofs_point *ap)
 	}
 
 	if (create_logpri_fifo(ap) < 0) {
-		crit(ap->logopt,
-		     "failed to create FIFO for path %s\n", ap->path);
-		destroy_logpri_fifo(ap);
-		close(ap->pipefd);
-		close(ap->kpipefd);
-		free(ap->path);
-		close(ap->state_pipe[0]);
-		close(ap->state_pipe[1]);
-		return -1;
+		logmsg("could not create FIFO for path %s\n", ap->path);
+		logmsg("dynamic log level changes not available for %s", ap->path);
 	}
 
 	return 0;
diff --git a/include/automount.h b/include/automount.h
index 37a3c0a..b0d1a9c 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -223,8 +223,6 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev);
 #define MAPENT_MAX_LEN 4095
 #define PARSE_MAX_BUF	KEY_MAX_LEN + MAPENT_MAX_LEN + 2
 
-#define AUTOFS_LOGPRI_FIFO "/tmp/autofs.fifo"
-
 int lookup_nss_read_master(struct master *master, time_t age);
 int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age);
 int lookup_enumerate(struct autofs_point *ap,
diff --git a/lib/master.c b/lib/master.c
index 2e24ad0..2188bca 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -56,6 +56,7 @@ int master_add_autofs_point(struct master_mapent *entry,
 
 	ap->state_pipe[0] = -1;
 	ap->state_pipe[1] = -1;
+	ap->logpri_fifo = -1;
 
 	ap->path = strdup(entry->path);
 	if (!ap->path) {

autofs-5.0.2-dynamic-logging-non-sasl.patch:

--- NEW FILE autofs-5.0.2-dynamic-logging-non-sasl.patch ---
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index bad48bb..93a1b40 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -579,7 +579,9 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 		list_add_tail(&this->list, ctxt->uri);
 	}
 
+#ifdef WITH_SASL
 	autofs_sasl_done(ctxt);
+#endif
 
 	/* Current server failed connect, try the rest */
 	ldap = find_server(logopt, ctxt);

autofs-5.0.2-dynamic-logging.patch:

--- NEW FILE autofs-5.0.2-dynamic-logging.patch ---
diff --git a/daemon/automount.c b/daemon/automount.c
index 70a3b9d..9ec6923 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -173,7 +173,7 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 		 */
 		memset(&st, 0, sizeof(st));
 		if (lstat(buf, &st) != 0) {
-			crit(ap->logopt, "lstat of %s failed.", buf);
+			crit(ap->logopt, "lstat of %s failed", buf);
 			return -1;
 		}
 
@@ -234,14 +234,15 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
 /* Like ftw, except fn gets called twice: before a directory is
    entered, and after.  If the before call returns 0, the directory
    isn't entered. */
-static int walk_tree(const char *base, int (*fn) (const char *file,
+static int walk_tree(const char *base, int (*fn) (unsigned logopt,
+						  const char *file,
 						  const struct stat * st,
-						  int, void *), int incl, void *arg)
+						  int, void *), int incl, unsigned logopt, void *arg)
 {
 	char buf[PATH_MAX + 1];
 	struct stat st;
 
-	if (lstat(base, &st) != -1 && (fn) (base, &st, 0, arg)) {
+	if (lstat(base, &st) != -1 && (fn) (logopt, base, &st, 0, arg)) {
 		if (S_ISDIR(st.st_mode)) {
 			struct dirent **de;
 			int n;
@@ -269,18 +270,18 @@ static int walk_tree(const char *base, int (*fn) (const char *file,
 					return -1;
 				}
 
-				walk_tree(buf, fn, 1, arg);
+				walk_tree(buf, fn, 1, logopt, arg);
 				free(de[n]);
 			}
 			free(de);
 		}
 		if (incl)
-			(fn) (base, &st, 1, arg);
+			(fn) (logopt, base, &st, 1, arg);
 	}
 	return 0;
 }
 
-static int rm_unwanted_fn(const char *file, const struct stat *st, int when, void *arg)
+static int rm_unwanted_fn(unsigned logopt, const char *file, const struct stat *st, int when, void *arg)
 {
 	dev_t dev = *(dev_t *) arg;
 	char buf[MAX_ERR_BUF];
@@ -293,41 +294,38 @@ static int rm_unwanted_fn(const char *file, const struct stat *st, int when, voi
 	}
 
 	if (lstat(file, &newst)) {
-		crit(LOGOPT_ANY,
-		     "unable to stat file, possible race condition");
+		crit(logopt, "unable to stat file, possible race condition");
 		return 0;
 	}
 
 	if (newst.st_dev != dev) {
-		crit(LOGOPT_ANY,
-		     "file %s has the wrong device, possible race condition",
+		crit(logopt, "file %s has the wrong device, possible race condition",
 		     file);
 		return 0;
 	}
 
 	if (S_ISDIR(newst.st_mode)) {
-		debug(LOGOPT_ANY, "removing directory %s", file);
+		debug(logopt, "removing directory %s", file);
 		if (rmdir(file)) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			warn(LOGOPT_ANY,
+			warn(logopt,
 			      "unable to remove directory %s: %s", file, estr);
 			return 0;
 		}
 	} else if (S_ISREG(newst.st_mode)) {
-		crit(LOGOPT_ANY,
-		     "attempting to remove files from a mounted "
+		crit(logopt, "attempting to remove files from a mounted "
 		     "directory. file %s", file);
 		return 0;
 	} else if (S_ISLNK(newst.st_mode)) {
-		debug(LOGOPT_ANY, "removing symlink %s", file);
+		debug(logopt, "removing symlink %s", file);
 		unlink(file);
 	}
 	return 1;
 }
 
-void rm_unwanted(const char *path, int incl, dev_t dev)
+void rm_unwanted(unsigned logopt, const char *path, int incl, dev_t dev)
 {
-	walk_tree(path, rm_unwanted_fn, incl, &dev);
+	walk_tree(path, rm_unwanted_fn, incl, logopt, &dev);
 }
 
 struct counter_args {
@@ -335,7 +333,7 @@ struct counter_args {
 	dev_t dev;
 };
 
-static int counter_fn(const char *file, const struct stat *st, int when, void *arg)
+static int counter_fn(unsigned logopt, const char *file, const struct stat *st, int when, void *arg)
 {
 	struct counter_args *counter = (struct counter_args *) arg;
 
@@ -349,14 +347,14 @@ static int counter_fn(const char *file, const struct stat *st, int when, void *a
 }
 
 /* Count mounted filesystems and symlinks */
-int count_mounts(const char *path, dev_t dev)
+int count_mounts(unsigned logopt, const char *path, dev_t dev)
 {
 	struct counter_args counter;
 
 	counter.count = 0;
 	counter.dev = dev;
 	
-	if (walk_tree(path, counter_fn, 0, &counter) == -1)
+	if (walk_tree(path, counter_fn, 0, logopt, &counter) == -1)
 		return -1;
 
 	return counter.count;
@@ -368,9 +366,9 @@ static void check_rm_dirs(struct autofs_point *ap, const char *path, int incl)
 	    (ap->state == ST_SHUTDOWN_PENDING ||
 	     ap->state == ST_SHUTDOWN_FORCE ||
 	     ap->state == ST_SHUTDOWN))
-		rm_unwanted(path, incl, ap->dev);
+		rm_unwanted(ap->logopt, path, incl, ap->dev);
 	else if (ap->ghost && (ap->type == LKP_INDIRECT))
-		rm_unwanted(path, 0, ap->dev);
+		rm_unwanted(ap->logopt, path, 0, ap->dev);
 }
 
 /* Try to purge cache entries kept around due to existing mounts */
@@ -466,7 +464,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
 		cache_multi_lock(me->parent);
 		if (umount_multi_triggers(ap, root, me, base)) {
 			warn(ap->logopt,
-			     "could not umount some offsets under %s", path);
+			     "some offset mounts still present under %s", path);
 			left++;
 		}
 		cache_multi_unlock(me->parent);
@@ -483,7 +481,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
 	 * it already to ensure it's ok to remove any offset triggers.
 	 */
 	if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
-		msg("unmounting dir = %s", path);
+		info(ap->logopt, "unmounting dir = %s", path);
 		if (umount_ent(ap, path)) {
 			warn(ap->logopt, "could not umount dir %s", path);
 			left++;
@@ -576,35 +574,35 @@ int umount_autofs(struct autofs_point *ap, int force)
 	return ret;
 }
 
-int send_ready(int ioctlfd, unsigned int wait_queue_token)
+int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token)
 {
 	char buf[MAX_ERR_BUF];
 
 	if (wait_queue_token == 0)
 		return 0;
 
-	debug(LOGOPT_NONE, "token = %d", wait_queue_token);
+	debug(logopt, "token = %d", wait_queue_token);
 
 	if (ioctl(ioctlfd, AUTOFS_IOC_READY, wait_queue_token) < 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "AUTOFS_IOC_READY: error %s", estr);
+		logerr("AUTOFS_IOC_READY: error %s", estr);
 		return 1;
 	}
 	return 0;
 }
 
-int send_fail(int ioctlfd, unsigned int wait_queue_token)
+int send_fail(unsigned logopt, int ioctlfd, unsigned int wait_queue_token)
 {
 	char buf[MAX_ERR_BUF];
 
 	if (wait_queue_token == 0)
 		return 0;
 
-	debug(LOGOPT_NONE, "token = %d", wait_queue_token);
+	debug(logopt, "token = %d", wait_queue_token);
 
 	if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, wait_queue_token) < 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "AUTOFS_IOC_FAIL: error %s", estr);
+		logerr("AUTOFS_IOC_FAIL: error %s", estr);
[...5813 lines suppressed...]
@@ -472,7 +472,7 @@ static char *concat_options(char *left, char *right)
 
 	if (ret == NULL) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return NULL;
 	}
 
@@ -637,8 +637,7 @@ static int check_is_multi(const char *mapent)
 	int not_first_chunk = 0;
 
 	if (!p) {
-		crit(LOGOPT_ANY,
-		     MODPREFIX "unexpected NULL map entry pointer");
+		logerr(MODPREFIX "unexpected NULL map entry pointer");
 		return 0;
 	}
 
@@ -1021,7 +1020,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 	pmapent = alloca(mapent_len + 1);
 	if (!pmapent) {	
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		ctxt->subst = removestdenv(ctxt->subst);
 		macro_unlock();
 		pthread_setcancelstate(cur_state, NULL);
@@ -1041,7 +1040,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 	options = strdup(ctxt->optstr ? ctxt->optstr : "");
 	if (!options) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "strdup: %s", estr);
+		logerr(MODPREFIX "strdup: %s", estr);
 		return 1;
 	}
 	optlen = strlen(options);
@@ -1119,7 +1118,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 			if (!m_root) {
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 				free(options);
-				error(ap->logopt, MODPREFIX "alloca: %s", estr);
+				logerr(MODPREFIX "alloca: %s", estr);
 				return 1;
 			}
 			strcpy(m_root, name);
@@ -1129,7 +1128,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 			if (!m_root) {
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 				free(options);
-				error(ap->logopt, MODPREFIX "alloca: %s", estr);
+				logerr(MODPREFIX "alloca: %s", estr);
 				return 1;
 			}
 			strcpy(m_root, ap->path);
diff --git a/modules/replicated.c b/modules/replicated.c
index e15587c..14b20a9 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -113,7 +113,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 	sock = socket(AF_INET, SOCK_DGRAM, 0);
 	if (sock < 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "socket creation failed: %s", estr);
+		logerr("socket creation failed: %s", estr);
 		return PROXIMITY_ERROR;
 	}
 
@@ -127,7 +127,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 	ret = ioctl(sock, SIOCGIFCONF, &ifc);
 	if (ret == -1) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "ioctl: %s", estr);
+		logerr("ioctl: %s", estr);
 		close(sock);
 		return PROXIMITY_ERROR;
 	}
@@ -176,7 +176,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
 			ret = ioctl(sock, SIOCGIFNETMASK, &nmptr);
 			if (ret == -1) {
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				error(LOGOPT_ANY, "ioctl: %s", estr);
+				logerr("ioctl: %s", estr);
 				close(sock);
 				return PROXIMITY_ERROR;
 			}
@@ -387,7 +387,7 @@ static unsigned short get_port_option(const char *options)
 	return (unsigned short) port;
 }
 
-static unsigned int get_nfs_info(struct host *host,
+static unsigned int get_nfs_info(unsigned logopt, struct host *host,
 			 struct conn_info *pm_info, struct conn_info *rpc_info,
 			 const char *proto, unsigned int version,
 			 const char *options, unsigned int random_selection)
@@ -533,7 +533,7 @@ done_ver:
 	return supported;
 }
 
-static int get_vers_and_cost(struct host *host,
+static int get_vers_and_cost(unsigned logopt, struct host *host,
 			     unsigned int version, const char *options,
 			     unsigned int random_selection)
 {
@@ -559,7 +559,7 @@ static int get_vers_and_cost(struct host *host,
 	vers &= version;
 
 	if (version & UDP_REQUESTED) {
-		supported = get_nfs_info(host,
+		supported = get_nfs_info(logopt, host,
 					&pm_info, &rpc_info, "udp", vers,
 					options, random_selection);
 		if (supported) {
@@ -569,7 +569,7 @@ static int get_vers_and_cost(struct host *host,
 	}
 
 	if (version & TCP_REQUESTED) {
-		supported = get_nfs_info(host,
+		supported = get_nfs_info(logopt, host,
 					 &pm_info, &rpc_info, "tcp", vers,
 					 options, random_selection);
 		if (supported) {
@@ -581,7 +581,7 @@ static int get_vers_and_cost(struct host *host,
 	return ret;
 }
 
-static int get_supported_ver_and_cost(struct host *host,
+static int get_supported_ver_and_cost(unsigned logopt, struct host *host,
 				      unsigned int version, const char *options,
 				      unsigned int random_selection)
 {
@@ -636,7 +636,7 @@ static int get_supported_ver_and_cost(struct host *host,
 		vers = NFS4_VERSION;
 		break;
 	default:
-		crit(LOGOPT_ANY, "called with invalid version: 0x%x\n", version);
+		crit(logopt, "called with invalid version: 0x%x\n", version);
 		return 0;
 	}
 
@@ -701,7 +701,7 @@ done:
 	return 0;
 }
 
-int prune_host_list(struct host **list,
+int prune_host_list(unsigned logopt, struct host **list,
 		    unsigned int vers, const char *options,
 		    unsigned int random_selection)
 {
@@ -742,7 +742,7 @@ int prune_host_list(struct host **list,
 			break;
 
 		if (this->name) {
-			status = get_vers_and_cost(this, vers,
+			status = get_vers_and_cost(logopt, this, vers,
 						   options, random_selection);
 			if (!status) {
 				if (this == first) {
@@ -833,7 +833,7 @@ int prune_host_list(struct host **list,
 			remove_host(list, this);
 			add_host(&new, this);
 		} else {
-			status = get_supported_ver_and_cost(this,
+			status = get_supported_ver_and_cost(logopt, this,
 						selected_version, options,
 						random_selection);
 			if (status) {
@@ -886,11 +886,9 @@ static int add_host_addrs(struct host **list, const char *host, unsigned int wei
 			buf, MAX_IFC_BUF, &result, &ghn_errno);
 	if (ret || !result) {
 		if (ghn_errno == -1)
-			error(LOGOPT_ANY,
-			      "host %s: lookup failure %d", host, errno);
+			logmsg("host %s: lookup failure %d", host, errno);
 		else
-			error(LOGOPT_ANY,
-			      "host %s: lookup failure %d", host, ghn_errno);
+			logmsg("host %s: lookup failure %d", host, ghn_errno);
 		return 0;
 	}
 
@@ -965,7 +963,7 @@ static int add_local_path(struct host **hosts, const char *path)
 	return 1;
 }
 
-int parse_location(struct host **hosts, const char *list)
+int parse_location(unsigned logopt, struct host **hosts, const char *list)
 {
 	char *str, *p, *delim;
 	unsigned int empty = 1;
@@ -1072,8 +1070,7 @@ void dump_host_list(struct host *hosts)
 
 	this = hosts;
 	while (this) {
-		debug(LOGOPT_ANY,
-		      "name %s path %s version %x proximity %u weight %u cost %u",
+		logmsg("name %s path %s version %x proximity %u weight %u cost %u",
 		      this->name, this->path, this->version,
 		      this->proximity, this->weight, this->cost);
 		this = this->next;

autofs-5.0.2-fix-recursive-loopback-mounts.patch:

--- NEW FILE autofs-5.0.2-fix-recursive-loopback-mounts.patch ---
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 3d5ea56..ab3274c 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -290,7 +290,16 @@ int spawn_mount(unsigned logopt, ...)
 
 	va_start(arg, logopt);
 	p = argv + 1;
-	while ((*p++ = va_arg(arg, char *)));
+	while ((*p = va_arg(arg, char *))) {
+		if (options == SPAWN_OPT_NONE && !strcmp(*p, "-o")) {
+			*(++p) = va_arg(arg, char *);
+			if (!*p)
+				break;
+			if (strstr(*p, "loop"))
+				options = SPAWN_OPT_ACCESS;
+		}
+		p++;
+	}
 	va_end(arg);
 
 	while (retries--) {

autofs-5.0.2-large-groups.patch:

--- NEW FILE autofs-5.0.2-large-groups.patch ---
diff --git a/daemon/direct.c b/daemon/direct.c
index 4ab4204..88e59ab 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -1218,11 +1218,11 @@ static void *do_mount_direct(void *arg)
 	struct passwd *ppw = &pw;
 	struct passwd **pppw = &ppw;
 	struct group gr;
-	struct group *pgr = &gr;
-	struct group **ppgr = &pgr;
+	struct group *pgr;
+	struct group **ppgr;
 	char *pw_tmp, *gr_tmp;
 	struct thread_stdenv_vars *tsv;
-	int tmplen;
+	int tmplen, grplen;
 	struct stat st;
 	int status, state;
 
@@ -1326,7 +1326,7 @@ static void *do_mount_direct(void *arg)
 
 	/* Try to get group info */
 
-	tmplen = sysconf(_SC_GETGR_R_SIZE_MAX);
+	grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
 	if (tmplen < 0) {
 		error(ap->logopt, "failed to get buffer size for getgrgid_r");
 		free(tsv->user);
@@ -1335,16 +1335,28 @@ static void *do_mount_direct(void *arg)
 		goto cont;
 	}
 
-	gr_tmp = malloc(tmplen + 1);
-	if (!gr_tmp) {
-		error(ap->logopt, "failed to malloc buffer for getgrgid_r");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		goto cont;
+	gr_tmp = NULL;
+	tmplen = grplen;
+	while (1) {
+		char *tmp = realloc(gr_tmp, tmplen + 1);
+		if (!tmp) {
+			error(ap->logopt, "failed to malloc buffer for getgrgid_r");
+			if (gr_tmp)
+				free(gr_tmp);
+			free(tsv->user);
+			free(tsv->home);
+			free(tsv);
+			goto cont;
+		}
+		gr_tmp = tmp;
+		pgr = &gr;
+		ppgr = &pgr;
+		status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
+		if (status != ERANGE)
+			break;
+		tmplen += grplen;
 	}
 
-	status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
 	if (status || !pgr) {
 		error(ap->logopt, "failed to get group info from getgrgid_r");
 		free(tsv->user);
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 5c422c8..f6b93d0 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -666,11 +666,11 @@ static void *do_mount_indirect(void *arg)
 	struct passwd *ppw = &pw;
 	struct passwd **pppw = &ppw;
 	struct group gr;
-	struct group *pgr = &gr;
-	struct group **ppgr = &pgr;
+	struct group *pgr;
+	struct group **ppgr;
 	char *pw_tmp, *gr_tmp;
 	struct thread_stdenv_vars *tsv;
-	int len, tmplen, status, state;
+	int len, tmplen, grplen, status, state;
 
 	mt = (struct pending_args *) arg;
 
@@ -771,7 +771,7 @@ static void *do_mount_indirect(void *arg)
 
 	/* Try to get group info */
 
-	tmplen = sysconf(_SC_GETGR_R_SIZE_MAX);
+	grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
 	if (tmplen < 0) {
 		error(ap->logopt, "failed to get buffer size for getgrgid_r");
 		free(tsv->user);
@@ -780,16 +780,28 @@ static void *do_mount_indirect(void *arg)
 		goto cont;
 	}
 
-	gr_tmp = malloc(tmplen + 1);
-	if (!gr_tmp) {
-		error(ap->logopt, "failed to malloc buffer for getgrgid_r");
-		free(tsv->user);
-		free(tsv->home);
-		free(tsv);
-		goto cont;
+	gr_tmp = NULL;
+	tmplen = grplen;
+	while (1) {
+		char *tmp = realloc(gr_tmp, tmplen + 1);
+		if (!tmp) {
+			error(ap->logopt, "failed to malloc buffer for getgrgid_r");
+			if (gr_tmp)
+				free(gr_tmp);
+			free(tsv->user);
+			free(tsv->home);
+			free(tsv);
+			goto cont;
+		}
+		gr_tmp = tmp;
+		pgr = &gr;
+		ppgr = &pgr;
+		status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
+		if (status != ERANGE)
+			break;
+		tmplen += grplen;
 	}
 
-	status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
 	if (status || !pgr) {
 		error(ap->logopt, "failed to get group info from getgrgid_r");
 		free(tsv->user);

autofs-5.0.2-ldap-check-star.patch:

--- NEW FILE autofs-5.0.2-ldap-check-star.patch ---
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index d5e666b..a7b315e 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1500,7 +1500,7 @@ static int lookup_one(struct autofs_point *ap,
 		*qKey = '/';
 
 	/* Build a query string. */
-	l = strlen(class) + 2*strlen(entry) + strlen(qKey) + 29;
+	l = strlen(class) + 3*strlen(entry) + strlen(qKey) + 35;
 
 	query = alloca(l);
 	if (query == NULL) {
@@ -1514,7 +1514,7 @@ static int lookup_one(struct autofs_point *ap,
 	 * whose entry is equal to qKey.
 	 */
 	ql = sprintf(query,
-	      "(&(objectclass=%s)(|(%s=%s)(%s=/)))", class, entry, qKey, entry);
+	      "(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))", class, entry, qKey, entry, entry);
 	if (ql >= l) {
 		error(ap->logopt,
 		      MODPREFIX "error forming query string");

autofs-5.0.2-ldap-search-basedn-list.patch:

--- NEW FILE autofs-5.0.2-ldap-search-basedn-list.patch ---
diff -up autofs-5.0.2/redhat/autofs.sysconfig.in.ldap-search-basedn-list autofs-5.0.2/redhat/autofs.sysconfig.in
--- autofs-5.0.2/redhat/autofs.sysconfig.in.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/redhat/autofs.sysconfig.in	2007-11-20 14:08:26.000000000 +0900
@@ -21,6 +21,14 @@ BROWSE_MODE="no"
 #
 #LOGGING="none"
 #
+# Define base dn for map dn lookup.
+#
+# SEARCH_BASE - base dn to use for searching for map search dn.
+# 		Multiple entries can be given and they are checked
+# 		in the order they occur here.
+#
+#SEARCH_BASE=""
+#
 # Define the LDAP schema to used for lookups
 #
 # If no schema is set autofs will check each of the schemas
diff -up autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list autofs-5.0.2/include/lookup_ldap.h
--- autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/include/lookup_ldap.h	2007-11-20 14:08:26.000000000 +0900
@@ -18,6 +18,11 @@ struct ldap_schema {
 	char *value_attr;
 };
 
+struct ldap_searchdn {
+	char *basedn;
+	struct ldap_searchdn *next;
+};
+
 struct lookup_context {
 	char *mapname;
 
@@ -32,6 +37,10 @@ struct lookup_context {
 	/* LDAP lookup configuration */
 	struct ldap_schema *schema;
 
+	/* List of base dns for searching */
+	char *cur_host;
+	struct ldap_searchdn *sdns;
+
 	/* TLS and SASL authentication information */
 	char        *auth_conf;
 	unsigned     use_tls;
diff -up autofs-5.0.2/include/defaults.h.ldap-search-basedn-list autofs-5.0.2/include/defaults.h
--- autofs-5.0.2/include/defaults.h.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/include/defaults.h	2007-11-20 14:08:26.000000000 +0900
@@ -37,6 +37,9 @@
 #define DEFAULT_APPEND_OPTIONS		1
 #define DEFAULT_AUTH_CONF_FILE		AUTOFS_MAP_DIR "/autofs_ldap_auth.conf"
 
+struct ldap_schema;
+struct ldap_searchdn;
+
 unsigned int defaults_read_config(void);
 const char *defaults_get_master_map(void);
 unsigned int defaults_get_timeout(void);
@@ -45,6 +48,8 @@ unsigned int defaults_get_logging(void);
 const char *defaults_get_ldap_server(void);
 struct ldap_schema *defaults_get_default_schema(void);
 struct ldap_schema *defaults_get_schema(void);
+struct ldap_searchdn *defaults_get_searchdns(void);
+void defaults_free_searchdns(struct ldap_searchdn *);
 unsigned int defaults_get_append_options(void);
 const char *defaults_get_auth_conf_file(void);
 
diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2/modules/lookup_ldap.c
--- autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/modules/lookup_ldap.c	2007-11-20 14:09:58.000000000 +0900
@@ -171,10 +171,207 @@ LDAP *init_ldap_connection(struct lookup
 	return ldap;
 }
 
+static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
+{
+	char buf[PARSE_MAX_BUF];
+	char *query, *dn;
+	LDAPMessage *result = NULL, *e;
+	struct ldap_searchdn *sdns = NULL;
+	char *attrs[2];
+	int scope;
+	int rv, l;
+
+	attrs[0] = LDAP_NO_ATTRS;
+	attrs[1] = NULL;
+
+	if (!ctxt->mapname && !ctxt->base) {
+		error(LOGOPT_ANY, MODPREFIX "no master map to lookup");
+		return 0;
+	}
+
+	/* Build a query string. */
+	l = strlen("(objectclass=)") + strlen(class) + 1;
+	if (ctxt->mapname)
+		l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))");
+
+	query = alloca(l);
+	if (query == NULL) {
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		return NSS_STATUS_UNAVAIL;
+	}
+
+	/*
+	 * If we have a master mapname construct a query using it
+	 * otherwise assume the base dn will catch it.
+	 */
+	if (ctxt->mapname) {
+		if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class,
+		     key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) {
+			debug(LOGOPT_NONE,
+			      MODPREFIX "error forming query string");
+			return 0;
+		}
+		scope = LDAP_SCOPE_SUBTREE;
+	} else {
+		if (sprintf(query, "(objectclass=%s)", class) >= l) {
+			debug(LOGOPT_NONE,
+			      MODPREFIX "error forming query string");
+			return 0;
+		}
+		scope = LDAP_SCOPE_SUBTREE;
+	}
+	query[l] = '\0';
+
+	if (!ctxt->base) {
+		sdns = defaults_get_searchdns();
+		if (sdns)
+			ctxt->sdns = sdns;
+	}
+
+	if (!sdns)
+		rv = ldap_search_s(ldap, ctxt->base,
+				   scope, query, attrs, 0, &result);
+	else {
+		struct ldap_searchdn *this = sdns;
+
+		debug(LOGOPT_NONE, MODPREFIX
+			      "check search base list");
+
+		while (this) {
+			rv = ldap_search_s(ldap, this->basedn,
+					   scope, query, attrs, 0, &result);
+
+			if ((rv == LDAP_SUCCESS) && result) {
+				debug(LOGOPT_NONE, MODPREFIX
+				      "found search base under %s",
+				      this->basedn);
+				break;
+			}
+
+			this = this->next;
+
+			if (result) {
+				ldap_msgfree(result);
+				result = NULL;
+			}
+		}
+	}
+
+	if ((rv != LDAP_SUCCESS) || !result) {
+		error(LOGOPT_NONE,
+		      MODPREFIX "query failed for %s: %s",
+		      query, ldap_err2string(rv));
+		return 0;
+	}
+
+	e = ldap_first_entry(ldap, result);
+	if (e) {
+		dn = ldap_get_dn(ldap, e);
+		debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn);
+		ldap_msgfree(result);
+	} else {
+		debug(LOGOPT_NONE,
+		      MODPREFIX "query succeeded, no matches for %s",
+		      query);
+		ldap_msgfree(result);
+		return 0;
+	}
+
+	ctxt->qdn = dn;
+
+	return 1;
+}
+
+static struct ldap_schema *alloc_common_schema(struct ldap_schema *s)
+{
+	struct ldap_schema *schema;
+	char *mc, *ma, *ec, *ea, *va;
+
+	mc = strdup(s->map_class);
+	if (!mc)
+		return NULL;
+
+	ma = strdup(s->map_attr);
+	if (!ma) {
+		free(mc);
+		return NULL;
+	}
+
+	ec = strdup(s->entry_class);
+	if (!ec) {
+		free(mc);
+		free(ma);
+		return NULL;
+	}
+
+	ea = strdup(s->entry_attr);
+	if (!ea) {
+		free(mc);
+		free(ma);
+		free(ec);
+		return NULL;
+	}
+
+	va = strdup(s->value_attr);
+	if (!va) {
+		free(mc);
+		free(ma);
+		free(ec);
+		free(ea);
+		return NULL;
+	}
+
+	schema = malloc(sizeof(struct ldap_schema));
+	if (!schema) {
+		free(mc);
+		free(ma);
+		free(ec);
+		free(ea);
+		free(va);
+		return NULL;
+	}
+
+	schema->map_class = mc;
+	schema->map_attr = ma;
+	schema->entry_class = ec;
+	schema->entry_attr = ea;
+	schema->value_attr = va;
+
+	return schema;
+}
+
+static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
+{
+	struct ldap_schema *schema;
+	unsigned int i;
+
+	if (ctxt->schema)
+		return 0;
+
+	for (i = 0; i < common_schema_count; i++) {
+		const char *class = common_schema[i].map_class;
+		const char *key = common_schema[i].map_attr;
+		if (get_query_dn(ldap, ctxt, class, key)) {
+			schema = alloc_common_schema(&common_schema[i]);
+			if (!schema) {
+				error(LOGOPT_ANY,
+				      MODPREFIX "failed to allocate schema");
+				return 0;
+			}
+			ctxt->schema = schema;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static LDAP *do_connect(struct lookup_context *ctxt)
 {
 	LDAP *ldap;
-	int rv;
+	char *host = NULL, *nhost;
+	int rv, need_base = 1;
 
 	ldap = init_ldap_connection(ctxt);
 	if (!ldap)
@@ -204,6 +401,61 @@ static LDAP *do_connect(struct lookup_co
 		return NULL;
 	}
 
+	rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
+        if (rv != LDAP_SUCCESS || !host) {
+		unbind_ldap_connection(ldap, ctxt);
+		debug(LOGOPT_ANY, "failed to get hostname for connection");
+		return NULL;
+	}
+
+	nhost = strdup(host);
+	if (!nhost) {
+		unbind_ldap_connection(ldap, ctxt);
+		debug(LOGOPT_ANY, "failed to alloc context for hostname");
+		return NULL;
+	}
+	ldap_memfree(host);
+
+	if (!ctxt->cur_host) {
+		ctxt->cur_host = nhost;
+		/* Check if schema defined in conf first time only */
+		ctxt->schema = defaults_get_schema();
+	} else {
+		/* If connection host has changed update */
+		if (strcmp(ctxt->cur_host, nhost)) {
+			free(ctxt->cur_host);
+			ctxt->cur_host = nhost;
+		} else {
+			free(nhost);
+			need_base = 0;
+		}
+	}
+
+	if (!need_base)
+		return ldap;
+
+	/*
+	 * If the schema isn't defined in the configuration then check for
+	 * presence of a map dn with a the common schema. Then calculate the
+	 * base dn for searches.
+	 */
+	if (!ctxt->schema) {
+		if (!find_query_dn(ldap, ctxt)) {
+			unbind_ldap_connection(ldap, ctxt);
+			error(LOGOPT_ANY,
+		      	      MODPREFIX "failed to find valid query dn");
+			return NULL;
+		}
+	} else {
+		const char *class = ctxt->schema->map_class;
+		const char *key = ctxt->schema->map_attr;
+		if (!get_query_dn(ldap, ctxt, class, key)) {
+			unbind_ldap_connection(ldap, ctxt);
+			error(LOGOPT_ANY, MODPREFIX "failed to get query dn");
+			return NULL;
+		}
+	}
+
 	return ldap;
 }
 
@@ -769,177 +1021,17 @@ static void free_context(struct lookup_c
 		ldap_memfree(ctxt->qdn);
 	if (ctxt->server)
 		free(ctxt->server);
+	if (ctxt->cur_host)
+		free(ctxt->cur_host);
 	if (ctxt->base)
 		free(ctxt->base);
+	if (ctxt->sdns)
+		defaults_free_searchdns(ctxt->sdns);
 	free(ctxt);
 
 	return;
 }
 
-static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
-{
-	char buf[PARSE_MAX_BUF];
-	char *query, *dn;
-	LDAPMessage *result, *e;
-	char *attrs[2];
-	struct berval **value;
-	int scope;
-	int rv, l;
-
-	attrs[0] = (char *) key;
-	attrs[1] = NULL;
-
-	if (!ctxt->mapname && !ctxt->base) {
-		error(LOGOPT_ANY, MODPREFIX "no master map to lookup");
-		return 0;
-	}
-
-	/* Build a query string. */
-	l = strlen("(objectclass=)") + strlen(class) + 1;
-	if (ctxt->mapname)
-		l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))");
-
-	query = alloca(l);
-	if (query == NULL) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
-		return NSS_STATUS_UNAVAIL;
-	}
-
-	/*
-	 * If we have a master mapname construct a query using it
-	 * otherwise assume the base dn will catch it.
-	 */
-	if (ctxt->mapname) {
-		if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class,
-		     key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) {
-			debug(LOGOPT_NONE,
-			      MODPREFIX "error forming query string");
-			return 0;
-		}
-		scope = LDAP_SCOPE_SUBTREE;
-	} else {
-		if (sprintf(query, "(objectclass=%s)", class) >= l) {
-			debug(LOGOPT_NONE,
-			      MODPREFIX "error forming query string");
-			return 0;
-		}
-		scope = LDAP_SCOPE_SUBTREE;
-	}
-	query[l] = '\0';
-
-	rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result);
-
-	if ((rv != LDAP_SUCCESS) || !result) {
-		error(LOGOPT_NONE,
-		      MODPREFIX "query failed for %s: %s",
-		      query, ldap_err2string(rv));
-		return 0;
-	}
-
-	e = ldap_first_entry(ldap, result);
-	if (e && (value = ldap_get_values_len(ldap, e, key))) {
-		ldap_value_free_len(value);
-		dn = ldap_get_dn(ldap, e);
-		debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn);
-		ldap_msgfree(result);
-	} else {
-		debug(LOGOPT_NONE,
-		      MODPREFIX "query succeeded, no matches for %s",
-		      query);
-		ldap_msgfree(result);
-		return 0;
-	}
-
-	ctxt->qdn = dn;
-
-	return 1;
-}
-
-static struct ldap_schema *alloc_common_schema(struct ldap_schema *s)
-{
-	struct ldap_schema *schema;
-	char *mc, *ma, *ec, *ea, *va;
-
-	mc = strdup(s->map_class);
-	if (!mc)
-		return NULL;
-
-	ma = strdup(s->map_attr);
-	if (!ma) {
-		free(mc);
-		return NULL;
-	}
-
-	ec = strdup(s->entry_class);
-	if (!ec) {
-		free(mc);
-		free(ma);
-		return NULL;
-	}
-
-	ea = strdup(s->entry_attr);
-	if (!ea) {
-		free(mc);
-		free(ma);
-		free(ec);
-		return NULL;
-	}
-
-	va = strdup(s->value_attr);
-	if (!va) {
-		free(mc);
-		free(ma);
-		free(ec);
-		free(ea);
-		return NULL;
-	}
-
-	schema = malloc(sizeof(struct ldap_schema));
-	if (!schema) {
-		free(mc);
-		free(ma);
-		free(ec);
-		free(ea);
-		free(va);
-		return NULL;
-	}
-
-	schema->map_class = mc;
-	schema->map_attr = ma;
-	schema->entry_class = ec;
-	schema->entry_attr = ea;
-	schema->value_attr = va;
-
-	return schema;
-}
-
-static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
-{
-	struct ldap_schema *schema;
-	unsigned int i;
-
-	if (ctxt->schema)
-		return 0;
-
-	for (i = 0; i < common_schema_count; i++) {
-		const char *class = common_schema[i].map_class;
-		const char *key = common_schema[i].map_attr;
-		if (get_query_dn(ldap, ctxt, class, key)) {
-			schema = alloc_common_schema(&common_schema[i]);
-			if (!schema) {
-				error(LOGOPT_ANY,
-				      MODPREFIX "failed to allocate schema");
-				return 0;
-			}
-			ctxt->schema = schema;
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
 /*
  * This initializes a context (persistent non-global data) for queries to
  * this module.  Return zero if we succeed.
@@ -996,31 +1088,6 @@ int lookup_init(const char *mapfmt, int 
 		free_context(ctxt);
 		return 1;
 	}
-
-	/*
-	 * Get default schema for queries.
-	 * If the schema isn't defined in the configuration then check for
-	 * presence of a map dn in the common schemas.
-	 */
-	ctxt->schema = defaults_get_schema();
-	if (!ctxt->schema) {
-		if (!find_query_dn(ldap, ctxt)) {
-			unbind_ldap_connection(ldap, ctxt);
-			error(LOGOPT_ANY,
-			      MODPREFIX "failed to find valid query dn");
-			free_context(ctxt);
-			return 1;
-		}
-	} else {
-		const char *class = ctxt->schema->map_class;
-		const char *key = ctxt->schema->map_attr;
-		if (!get_query_dn(ldap, ctxt, class, key)) {
-			unbind_ldap_connection(ldap, ctxt);
-			error(LOGOPT_ANY, MODPREFIX "failed to get query dn");
-			free_context(ctxt);
-			return 1;
-		}
-	}
 	unbind_ldap_connection(ldap, ctxt);
 
 	/* Open the parser, if we can. */
diff -up autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list autofs-5.0.2/samples/autofs.conf.default.in
--- autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/samples/autofs.conf.default.in	2007-11-20 14:08:26.000000000 +0900
@@ -21,6 +21,14 @@ BROWSE_MODE="no"
 #
 #LOGGING="none"
 #
+# Define base dn for map dn lookup.
+#
+# SEARCH_BASE - base dn to use for searching for map search dn.
+# 		Multiple entries can be given and they are checked
+# 		in the order they occur here.
+#
+#SEARCH_BASE=""
+#
 # Define the LDAP schema to used for lookups
 #
 # If no schema is set autofs will check each of the schemas
diff -up autofs-5.0.2/lib/defaults.c.ldap-search-basedn-list autofs-5.0.2/lib/defaults.c
--- autofs-5.0.2/lib/defaults.c.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/lib/defaults.c	2007-11-20 14:08:26.000000000 +0900
@@ -32,6 +32,8 @@
 
 #define ENV_LDAP_SERVER			"LDAP_SERVER"
 
+#define SEARCH_BASE			"SEARCH_BASE"
+
 #define ENV_NAME_MAP_OBJ_CLASS		"MAP_OBJECT_CLASS"
 #define ENV_NAME_ENTRY_OBJ_CLASS	"ENTRY_OBJECT_CLASS"
 #define ENV_NAME_MAP_ATTR		"MAP_ATTRIBUTE"
@@ -130,6 +132,52 @@ static int check_set_config_value(const 
 	return 0;
 }
 
+static int parse_line(char *line, char **res, char **value)
+{
+	char *key, *val, *trailer;
+	int len;
+
+	key = line;
+
+	if (*key == '#' || !isalpha(*key))
+		return 0;
+
+	while (*key && *key == ' ')
+		key++;
+
+	if (!key)
+		return 0;
+
+	if (!(val = strchr(key, '=')))
+		return 0;
+
+	*val++ = '\0';
+
+	while (*val && (*val == '"' || isblank(*val)))
+		val++;
+
+	len = strlen(val);
+
+	if (val[len - 1] == '\n') {
+		val[len - 1] = '\0';
+		len--;
+	}
+
+	trailer = strchr(val, '#');
+	if (!trailer)
+		trailer = val + len - 1;
+	else
+		trailer--;
+
+	while (*trailer && (*trailer == '"' || isblank(*trailer)))
+		*(trailer--) = '\0';;
+
+	*res = key;
+	*value = val;
+
+	return 1;
+}
+
 /*
  * Read config env variables and check they have been set.
  *
@@ -141,61 +189,30 @@ unsigned int defaults_read_config(void)
 {
 	FILE *f;
 	char buf[MAX_LINE_LEN];
-	char *res, *value;
+	char *res;
 
 	f = fopen(DEFAULTS_CONFIG_FILE, "r");
 	if (!f)
 		return 0;
 
 	while ((res = fgets(buf, MAX_LINE_LEN, f))) {
-		char *trailer;
-		int len;
-
-		if (*res == '#' || !isalpha(*res))
-			continue;
-
-		while (*res && *res == ' ')
-			res++;
-
-		if (!res)
-			continue;
+		char *key, *value;
 
-		if (!(value = strchr(res, '=')))
+		if (!parse_line(res, &key, &value))
 			continue;
 
-		*value++ = '\0';
-
-		while (*value && (*value == '"' || isblank(*value)))
-			value++;
-
-		len = strlen(value);
-
-		if (value[len - 1] == '\n') {
-			value[len - 1] = '\0';
-			len--;
-		}
-
-		trailer = strchr(value, '#');
-		if (!trailer)
-			trailer = value + len - 1;
-		else
-			trailer--;
-
-		while (*trailer && (*trailer == '"' || isblank(*trailer)))
-			*(trailer--) = '\0';;
-
-		if (check_set_config_value(res, ENV_NAME_MASTER_MAP, value) ||
-		    check_set_config_value(res, ENV_NAME_TIMEOUT, value) ||
-		    check_set_config_value(res, ENV_NAME_BROWSE_MODE, value) ||
-		    check_set_config_value(res, ENV_NAME_LOGGING, value) ||
-		    check_set_config_value(res, ENV_LDAP_SERVER, value) ||
-		    check_set_config_value(res, ENV_NAME_MAP_OBJ_CLASS, value) ||
-		    check_set_config_value(res, ENV_NAME_ENTRY_OBJ_CLASS, value) ||
-		    check_set_config_value(res, ENV_NAME_MAP_ATTR, value) ||
-		    check_set_config_value(res, ENV_NAME_ENTRY_ATTR, value) ||
-		    check_set_config_value(res, ENV_NAME_VALUE_ATTR, value) ||
-		    check_set_config_value(res, ENV_APPEND_OPTIONS, value) ||
-		    check_set_config_value(res, ENV_AUTH_CONF_FILE, value))
+		if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value) ||
+		    check_set_config_value(key, ENV_NAME_TIMEOUT, value) ||
+		    check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) ||
+		    check_set_config_value(key, ENV_NAME_LOGGING, value) ||
+		    check_set_config_value(key, ENV_LDAP_SERVER, value) ||
+		    check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) ||
+		    check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) ||
+		    check_set_config_value(key, ENV_NAME_MAP_ATTR, value) ||
+		    check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value) ||
+		    check_set_config_value(key, ENV_NAME_VALUE_ATTR, value) ||
+		    check_set_config_value(key, ENV_APPEND_OPTIONS, value) ||
+		    check_set_config_value(key, ENV_AUTH_CONF_FILE, value))
 			;
 	}
 
@@ -336,6 +353,86 @@ struct ldap_schema *defaults_get_default
 	return schema;
 }
 
+static struct ldap_searchdn *alloc_searchdn(const char *value)
+{
+	struct ldap_searchdn *sdn;
+	char *val;
+
+	sdn = malloc(sizeof(struct ldap_searchdn));
+	if (!sdn)
+		return NULL;
+
+	val = strdup(value);
+	if (!val) {
+		free(sdn);
+		return NULL;
+	}
+
+	sdn->basedn = val;
+	sdn->next = NULL;
+
+	return sdn;
+}
+
+void defaults_free_searchdns(struct ldap_searchdn *sdn)
+{
+	struct ldap_searchdn *this = sdn;
+	struct ldap_searchdn *next;
+
+	next = this;
+	while (this) {
+		next = this->next;
+		free(this->basedn);
+		free(this);
+		this = next;
+	}
+
+	return;
+}
+
+struct ldap_searchdn *defaults_get_searchdns(void)
+{
+	FILE *f;
+	char buf[MAX_LINE_LEN];
+	char *res;
+	struct ldap_searchdn *sdn, *last;
+
+	f = fopen(DEFAULTS_CONFIG_FILE, "r");
+	if (!f)
+		return NULL;
+
+	sdn = last = NULL;
+
+	while ((res = fgets(buf, MAX_LINE_LEN, f))) {
+		char *key, *value;
+
+		if (!parse_line(res, &key, &value))
+			continue;
+
+		if (!strcasecmp(key, SEARCH_BASE)) {
+			struct ldap_searchdn *new = alloc_searchdn(value);
+
+			if (!new) {
+				defaults_free_searchdns(sdn);
+				return NULL;
+			}
+
+			if (!last)
+				last = new;
+			else {
+				last->next = new;
+				last = new;
+			}
+
+			if (!sdn)
+				sdn = new;
+		}
+	}
+
+	fclose(f);
+	return sdn;
+}
+
 struct ldap_schema *defaults_get_schema(void)
 {
 	struct ldap_schema *schema;
diff -up autofs-5.0.2/man/auto.master.5.in.ldap-search-basedn-list autofs-5.0.2/man/auto.master.5.in
--- autofs-5.0.2/man/auto.master.5.in.ldap-search-basedn-list	2007-11-20 14:07:52.000000000 +0900
+++ autofs-5.0.2/man/auto.master.5.in	2007-11-20 14:08:26.000000000 +0900
@@ -224,6 +224,11 @@ values must be set, any partial schema s
 .P
 The configuration settings available are:
 .TP
+.B SEARCH_BASE
+The base dn to use when searching for amap base dn. This entry may be
+given multiple times and each will be checked for a map base dn in
+the order they occur in the configuration.
+.TP
 .B MAP_OBJECT_CLASS
 The map object class. In the \fBnisMap\fP schema this corresponds to the class
 \fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class

autofs-5.0.2-log-map-reload.patch:

--- NEW FILE autofs-5.0.2-log-map-reload.patch ---
diff --git a/daemon/automount.c b/daemon/automount.c
index 9ec6923..7e7d1e6 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1278,6 +1278,8 @@ static void *do_read_master(void *arg)
 
 	defaults_read_config(1);
 
+	info(logopt, "re-reading master map %s", master->name);
+
 	status = master_read_master(master, age, readall);
 
 	master->reading = 0;
diff --git a/daemon/state.c b/daemon/state.c
index a2da762..cf07aac 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -376,6 +376,8 @@ static void *do_readmap(void *arg)
 
 	pthread_cleanup_push(do_readmap_cleanup, ra);
 
+	info(ap->logopt, "re-reading map for %s", ap->path);
+
 	status = lookup_nss_read_map(ap, NULL, now);
 	if (!status)
 		pthread_exit(NULL);

autofs-5.0.2-negative-timeout-update.patch:

--- NEW FILE autofs-5.0.2-negative-timeout-update.patch ---
diff --git a/daemon/automount.c b/daemon/automount.c
index a12b6da..7becad5 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -58,6 +58,8 @@ const char *global_options;		/* Global option, from command line */
 static char *pid_file = NULL;		/* File in which to keep pid */
 unsigned int global_random_selection;	/* use random policy when selecting
 					 * which multi-mount host to mount */
+long global_negative_timeout = -1;
+
 static int start_pipefd[2];
 static int st_stat = 0;
 static int *pst_stat = &st_stat;
@@ -1671,6 +1673,8 @@ static void usage(void)
 		"	-f --foreground do not fork into background\n"
 		"	-r --random-multimount-selection\n"
 		"			use ramdom replicated server selection\n"
+		"	-n --negative-timeout n\n"
+		"			set the timeout for failed key lookups.\n"
 		"	-O --global-options\n"
 		"			specify global mount options\n"
 		"	-l --set-log-priority priority path [path,...]\n"
@@ -1810,6 +1814,7 @@ int main(int argc, char *argv[])
 		{"define", 1, 0, 'D'},
 		{"foreground", 0, 0, 'f'},
 		{"random-multimount-selection", 0, 0, 'r'},
+		{"negative-timeout", 1, 0, 'n'},
 		{"global-options", 1, 0, 'O'},
 		{"version", 0, 0, 'V'},
 		{"set-log-priority", 1, 0, 'l'},
@@ -1833,7 +1838,7 @@ int main(int argc, char *argv[])
 	foreground = 0;
 
 	opterr = 0;
-	while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:", long_options, NULL)) != EOF) {
+	while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:n:", long_options, NULL)) != EOF) {
 		switch (opt) {
 		case 'h':
 			usage();
@@ -1871,6 +1876,10 @@ int main(int argc, char *argv[])
 			global_random_selection = 1;
 			break;
 
+		case 'n':
+			global_negative_timeout = getnumopt(optarg, opt);
+			break;
+
 		case 'O':
 			if (!have_global_options) {
 				global_options = strdup(optarg);
diff --git a/include/automount.h b/include/automount.h
index b0d1a9c..4887da6 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -442,6 +442,7 @@ struct autofs_point {
 	unsigned int type;		/* Type of map direct or indirect */
 	time_t exp_timeout;		/* Timeout for expiring mounts */
 	time_t exp_runfreq;		/* Frequency for polling for timeouts */
+	time_t negative_timeout;	/* timeout in secs for failed mounts */
 	unsigned ghost;			/* Enable/disable gohsted directories */
 	unsigned logopt;		/* Per map logging */
 	pthread_t exp_thread;		/* Thread that is expiring */
diff --git a/include/defaults.h b/include/defaults.h
index e296478..6e4f52a 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -22,9 +22,10 @@
 
 #define DEFAULT_MASTER_MAP_NAME	"auto.master"
 
-#define DEFAULT_TIMEOUT		600
-#define DEFAULT_BROWSE_MODE	1
-#define DEFAULT_LOGGING		0
+#define DEFAULT_TIMEOUT			600
+#define DEFAULT_NEGATIVE_TIMEOUT	60
+#define DEFAULT_BROWSE_MODE		1
+#define DEFAULT_LOGGING			0
 
 #define DEFAULT_LDAP_TIMEOUT		-1
 #define DEFAULT_LDAP_NETWORK_TIMEOUT	8
@@ -45,6 +46,7 @@ unsigned int defaults_read_config(unsigned int);
 const char *defaults_get_master_map(void);
 int defaults_master_set(void);
 unsigned int defaults_get_timeout(void);
+unsigned int defaults_get_negative_timeout(void);
 unsigned int defaults_get_browse_mode(void);
 unsigned int defaults_get_logging(void);
 const char *defaults_get_ldap_server(void);
diff --git a/lib/defaults.c b/lib/defaults.c
index f494103..8149549 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -28,6 +28,7 @@
 #define ENV_NAME_MASTER_MAP		"MASTER_MAP_NAME"
 
 #define ENV_NAME_TIMEOUT		"TIMEOUT"
+#define ENV_NAME_NEGATIVE_TIMEOUT	"NEGATIVE_TIMEOUT"
 #define ENV_NAME_BROWSE_MODE		"BROWSE_MODE"
 #define ENV_NAME_LOGGING		"LOGGING"
 
@@ -308,6 +309,7 @@ unsigned int defaults_read_config(unsigned int to_syslog)
 
 		if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value, to_syslog) ||
 		    check_set_config_value(key, ENV_NAME_TIMEOUT, value, to_syslog) ||
+		    check_set_config_value(key, ENV_NAME_NEGATIVE_TIMEOUT, value, to_syslog) ||
 		    check_set_config_value(key, ENV_NAME_BROWSE_MODE, value, to_syslog) ||
 		    check_set_config_value(key, ENV_NAME_LOGGING, value, to_syslog) ||
 		    check_set_config_value(key, ENV_LDAP_TIMEOUT, value, to_syslog) ||
@@ -370,6 +372,17 @@ unsigned int defaults_get_timeout(void)
 	return (unsigned int) timeout;
 }
 
+unsigned int defaults_get_negative_timeout(void)
+{
+	long n_timeout;
+
+	n_timeout = get_env_number(ENV_NAME_NEGATIVE_TIMEOUT);
+	if (n_timeout <= 0)
+		n_timeout = DEFAULT_NEGATIVE_TIMEOUT;
+
+	return (unsigned int) n_timeout;
+}
+
 unsigned int defaults_get_browse_mode(void)
 {
 	int res;
diff --git a/lib/master.c b/lib/master.c
index 2188bca..c001d20 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -30,6 +30,8 @@
 /* The root of the map entry tree */
 struct master *master_list = NULL;
 
+extern long global_negative_timeout;
+
 /* Attribute to create detached thread */
 extern pthread_attr_t thread_attr;
 
@@ -68,6 +70,14 @@ int master_add_autofs_point(struct master_mapent *entry,
 	ap->exp_thread = 0;
 	ap->readmap_thread = 0;
 	ap->exp_timeout = timeout;
+	/*
+	 * Program command line option overrides config.
+	 * We can't use 0 negative timeout so use default.
+	 */
+	if (global_negative_timeout <= 0)
+		ap->negative_timeout = defaults_get_negative_timeout();
+	else
+		ap->negative_timeout = global_negative_timeout;
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 	ap->ghost = ghost;
 
diff --git a/lib/master_parse.y b/lib/master_parse.y
index a767f9e..b450122 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -55,6 +55,7 @@ static char *path;
 static char *type;
 static char *format;
 static long timeout;
+static long negative_timeout;
 static unsigned ghost;
 extern unsigned global_random_selection;
 static unsigned random_selection;
@@ -95,7 +96,8 @@ static int master_fprintf(FILE *, char *, ...);
 
 %token COMMENT
 %token MAP
-%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM
+%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE
+%token OPT_DEBUG OPT_RANDOM
 %token COLON COMMA NL DDASH
 %type <strtype> map
 %type <strtype> options
@@ -542,6 +544,7 @@ option: daemon_option
 	;
 
 daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
+	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
 	| OPT_NOGHOST	{ ghost = 0; }
 	| OPT_GHOST	{ ghost = 1; }
 	| OPT_VERBOSE	{ verbose = 1; }
@@ -603,6 +606,7 @@ static void local_init_vars(void)
 	verbose = 0;
 	debug = 0;
 	timeout = -1;
+	negative_timeout = 0;
 	ghost = defaults_get_browse_mode();
 	random_selection = global_random_selection;
 	tmp_argv = NULL;
@@ -793,6 +797,8 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 		}
 	}
 	entry->ap->random_selection = random_selection;
+	if (negative_timeout)
+		entry->ap->negative_timeout = negative_timeout;
 
 /*
 	source = master_find_map_source(entry, type, format,
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 36aa785..d908047 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -118,6 +118,7 @@ MTYPE		((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?(
 
 
 OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
+OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
 
 %%
 
@@ -321,6 +322,8 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 
 	{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
 
+	{OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
+
 	{NUMBER} {
 		master_lval.longtype = atol(master_text);
 		return(NUMBER);
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 68447e0..d488960 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -152,6 +152,11 @@ Enables the use of ramdom selection when choosing a host from a
 list of replicated servers. This option is applied to this mount
 only, overriding the global setting that may be specified on the
 command line.
+.TP
+.I "\-n, \-\-negative\-timeout <seconds>"
+Set the timeout for caching failed key lookups. This option can be
+used to override the global default given either on the command line
+or in the configuration.
 .SH GENERAL SYSTEM DEFAULTS CONFIGURATION
 .P
 The default value of several general settings may be changed in the
@@ -164,6 +169,11 @@ They are:
 .B TIMEOUT
 sets the default mount timeout (program default 600).
 .TP
+.B NEGATIVE_TIMEOUT
+Set the default timeout for caching failed key lookups (program default
+60). If the equivalent command line option is given it will override this
+setting.
+.TP
 .B BROWSE_MODE
 Maps are browsable by default (program default "yes").
 .TP
diff --git a/man/automount.8 b/man/automount.8
index 5cd63c7..59ad50e 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -34,6 +34,9 @@ Set the global minimum timeout, in seconds, until directories
 are unmounted. The default is 10 minutes. Setting the timeout
 to zero disables umounts completely.
 .TP
+.I "\-n <seconds>, \-\-negative\-timeout <seconds>"
+Set the default timeout for caching failed key lookups. The default is 60 seconds.
+.TP
 .I "\-v, \-\-verbose"
 Enables logging of general status and progress messages for all
 autofs managed mounts.
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index c093415..1007de4 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -1126,7 +1126,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 				rv = cache_update(mc, source, key, NULL, now);
 			if (rv != CHE_FAIL) {
 				me = cache_lookup_distinct(mc, key);
-				me->status = now + NEGATIVE_TIMEOUT;
+				me->status = now + ap->negative_timeout;
 			}
 			cache_unlock(mc);
 		}
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index d746e42..1ef420e 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -138,7 +138,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	cache_readlock(mc);
 	me = cache_lookup_distinct(mc, name);
-	if (!me) {
+	if (me && me->status >= time(NULL)) {
+		cache_unlock(mc);
+		return NSS_STATUS_NOTFOUND;
+	} else if (!me) {
 		cache_unlock(mc);
 		/*
 		 * We haven't read the list of hosts into the
@@ -192,10 +195,22 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		ret = ctxt->parse->parse_mount(ap, name, name_len,
 				 mapent, ctxt->parse->context);
 
-		if (!ret)
-			return NSS_STATUS_SUCCESS;
-
-		return NSS_STATUS_TRYAGAIN;
+		if (ret) {
+			time_t now = time(NULL);
+			int rv = CHE_OK;
+
+			cache_writelock(mc);
+			me = cache_lookup_distinct(mc, name);
+			if (!me)
+				rv = cache_update(mc, source, name, NULL, now);
+			if (rv != CHE_FAIL) {
+				me = cache_lookup_distinct(mc, name);
+				me->status = now + ap->negative_timeout;
+			}
+			cache_unlock(mc);
+			return NSS_STATUS_TRYAGAIN;
+		}
+		return NSS_STATUS_SUCCESS;
 	}
 done:
 	/*
@@ -267,8 +282,21 @@ done:
 				 mapent, ctxt->parse->context);
 	free(mapent);
 
-	if (ret)
+	if (ret) {
+		time_t now = time(NULL);
+		int rv = CHE_OK;
+
+		cache_writelock(mc);
+		me = cache_lookup_distinct(mc, name);
+		if (!me)
+			rv = cache_update(mc, source, name, NULL, now);
+		if (rv != CHE_FAIL) {
+			me = cache_lookup_distinct(mc, name);
+			me->status = now + ap->negative_timeout;
+		}
+		cache_unlock(mc);
 		return NSS_STATUS_TRYAGAIN;
+	}
 
 	return NSS_STATUS_SUCCESS;
 }
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 8719af9..4dea3b2 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -2125,7 +2125,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 				rv = cache_update(mc, source, key, NULL, now);
 			if (rv != CHE_FAIL) {
 				me = cache_lookup_distinct(mc, key);
-				me->status = now + NEGATIVE_TIMEOUT;
+				me->status = now + ap->negative_timeout;
 			}
 			cache_unlock(mc);
 		}
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index bcdaeeb..e948c14 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -547,7 +547,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 				rv = cache_update(mc, source, key, NULL, now);
 			if (rv != CHE_FAIL) {
 				me = cache_lookup_distinct(mc, key);
-				me->status = time(NULL) + NEGATIVE_TIMEOUT;
+				me->status = time(NULL) + ap->negative_timeout;
 			}
 			cache_unlock(mc);
 		}
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
index e28168e..7c266d6 100644
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -134,7 +134,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	/* Catch installed direct offset triggers */
 	cache_readlock(mc);
 	me = cache_lookup_distinct(mc, name);
-	if (!me) {
+	if (me && me->status >= time(NULL)) {
+		cache_unlock(mc);
+		return NSS_STATUS_NOTFOUND;
+	} else if (!me) {
 		cache_unlock(mc);
 		/*
 		 * If there's a '/' in the name and the offset is not in
@@ -147,15 +150,33 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		}
 	} else {
 		cache_unlock(mc);
+
 		/* Otherwise we found a valid offset so try mount it */
 		debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
 
-		master_source_current_wait(ap->entry);
-		ap->entry->current = source;
-
-		ret = ctxt->parse->parse_mount(ap, name, name_len,
-				      me->mapent, ctxt->parse->context);
-		goto out_free;
+		/*
+		 * If this is a request for an offset mount (whose entry
+		 * must be present in the cache to be valid) or the entry
+		 * is newer than the negative timeout value then just
+		 * try and mount it. Otherwise try and remove it and
+		 * proceed with the program map lookup.
+		 */
+		if (strchr(name, '/') ||
+		    me->age + ap->negative_timeout > time(NULL)) {
+			master_source_current_wait(ap->entry);
+			ap->entry->current = source;
+			ret = ctxt->parse->parse_mount(ap, name,
+				 name_len, me->mapent, ctxt->parse->context);
+			goto out_free;
+		} else {
+			if (me->multi) {
+				warn(ap->logopt, MODPREFIX
+				     "unexpected lookup for active multi-mount"
+				     " key %s, returning fail", name);
+				return NSS_STATUS_UNAVAIL;
+			}
+			cache_delete(mc, name);
+		}
 	}
 
 	mapent = (char *) malloc(MAPENT_MAX_LEN + 1);
@@ -356,8 +377,21 @@ out_free:
 	if (mapent)
 		free(mapent);
 
-	if (ret)
+	if (ret) {
+		time_t now = time(NULL);
+		int rv = CHE_OK;
+
+		cache_writelock(mc);
+		me = cache_lookup_distinct(mc, name);
+		if (!me)
+			rv = cache_update(mc, source, name, NULL, now);
+		if (rv != CHE_FAIL) {
+			me = cache_lookup_distinct(mc, name);
+			me->status = now + ap->negative_timeout;
+		}
+		cache_unlock(mc);
 		return NSS_STATUS_UNAVAIL;
+	}
 
 	return NSS_STATUS_SUCCESS;
 }
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 7ba6940..6c20145 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -639,7 +639,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 				rv = cache_update(mc, source, key, NULL, now);
 			if (rv != CHE_FAIL) {
 				me = cache_lookup_distinct(mc, key);
-				me->status = now + NEGATIVE_TIMEOUT;
+				me->status = now + ap->negative_timeout;
 			}
 			cache_unlock(mc);
 		}
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index f01ee5f..636763a 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -9,6 +9,11 @@
 #
 TIMEOUT=300
 #
+# NEGATIVE_TIMEOUT - set the default negative timeout for
+# 		     failed mount attempts (default 60).
+#
+#NEGATIVE_TIMEOUT=60
+#
 # BROWSE_MODE - maps are browsable by default.
 #
 BROWSE_MODE="no"
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 028341c..086ba4f 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -9,6 +9,11 @@
 #
 TIMEOUT=300
 #
+# NEGATIVE_TIMEOUT - set the default negative timeout for
+# 		     failed mount attempts (default 60).
+#
+#NEGATIVE_TIMEOUT=60
+#
 # BROWSE_MODE - maps are browsable by default.
 #
 BROWSE_MODE="no"

autofs-5.0.2-random-selection-fix.patch:

--- NEW FILE autofs-5.0.2-random-selection-fix.patch ---
diff -up autofs-5.0.2/include/replicated.h.random-selection-fix autofs-5.0.2/include/replicated.h
--- autofs-5.0.2/include/replicated.h.random-selection-fix	2007-06-18 15:18:08.000000000 +0800
+++ autofs-5.0.2/include/replicated.h	2007-11-20 14:55:28.000000000 +0900
@@ -63,7 +63,7 @@ struct host {
 void seed_random(void);
 void free_host_list(struct host **);
 int parse_location(struct host **, const char *);
-int prune_host_list(struct host **, unsigned int, const char *);
+int prune_host_list(struct host **, unsigned int, const char *, unsigned int);
 void dump_host_list(struct host *);
 
 #endif
diff -up autofs-5.0.2/include/automount.h.random-selection-fix autofs-5.0.2/include/automount.h
--- autofs-5.0.2/include/automount.h.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/include/automount.h	2007-11-20 14:55:28.000000000 +0900
@@ -448,6 +448,8 @@ struct autofs_point {
 	enum states state;		/* Current state */
 	int state_pipe[2];		/* State change router pipe */
 	unsigned dir_created;		/* Directory created for this mount? */
+	unsigned random_selection;	/* Use random policy when selecting a
+					 * host from which to mount */
 	struct autofs_point *parent;	/* Owner of mounts list for submount */
 	pthread_mutex_t mounts_mutex;	/* Protect mount lists */
 	pthread_cond_t mounts_cond;	/* Submounts condition variable */
diff -up autofs-5.0.2/modules/mount_nfs.c.random-selection-fix autofs-5.0.2/modules/mount_nfs.c
--- autofs-5.0.2/modules/mount_nfs.c.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/modules/mount_nfs.c	2007-11-20 14:55:28.000000000 +0900
@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap,
 		warn(ap->logopt, MODPREFIX "no hosts available");
 		return 1;
 	}
-	prune_host_list(&hosts, vers, nfsoptions);
+	prune_host_list(&hosts, vers, nfsoptions, ap->random_selection);
 
 	if (!hosts) {
 		warn(ap->logopt, MODPREFIX "no hosts available");
diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/modules/replicated.c
--- autofs-5.0.2/modules/replicated.c.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/modules/replicated.c	2007-11-20 14:55:28.000000000 +0900
@@ -74,8 +74,6 @@
 #define max(x, y)	(x >= y ? x : y)
 #define mmax(x, y, z)	(max(x, y) == x ? max(x, z) : max(y, z))
 
-extern unsigned int random_selection;
-
 void seed_random(void)
 {
 	int fd;
@@ -392,7 +390,7 @@ static unsigned short get_port_option(co
 static unsigned int get_nfs_info(struct host *host,
 			 struct conn_info *pm_info, struct conn_info *rpc_info,
 			 const char *proto, unsigned int version,
-			 const char *options)
+			 const char *options, unsigned int random_selection)
 {
 	char *have_port_opt = options ? strstr(options, "port=") : NULL;
 	struct pmap parms;
@@ -535,7 +533,9 @@ done_ver:
 	return supported;
 }
 
-static int get_vers_and_cost(struct host *host, unsigned int version, const char *options)
+static int get_vers_and_cost(struct host *host,
+			     unsigned int version, const char *options,
+			     unsigned int random_selection)
 {
 	struct conn_info pm_info, rpc_info;
 	time_t timeout = RPC_TIMEOUT;
@@ -559,7 +559,9 @@ static int get_vers_and_cost(struct host
 	vers &= version;
 
 	if (version & UDP_REQUESTED) {
-		supported = get_nfs_info(host, &pm_info, &rpc_info, "udp", vers, options);
+		supported = get_nfs_info(host,
+					&pm_info, &rpc_info, "udp", vers,
+					options, random_selection);
 		if (supported) {
 			ret = 1;
 			host->version |= (supported << 8);
@@ -567,7 +569,9 @@ static int get_vers_and_cost(struct host
 	}
 
 	if (version & TCP_REQUESTED) {
-		supported = get_nfs_info(host, &pm_info, &rpc_info, "tcp", vers, options);
+		supported = get_nfs_info(host,
+					 &pm_info, &rpc_info, "tcp", vers,
+					 options, random_selection);
 		if (supported) {
 			ret = 1;
 			host->version |= supported;
@@ -577,7 +581,9 @@ static int get_vers_and_cost(struct host
 	return ret;
 }
 
-static int get_supported_ver_and_cost(struct host *host, unsigned int version, const char *options)
+static int get_supported_ver_and_cost(struct host *host,
+				      unsigned int version, const char *options,
+				      unsigned int random_selection)
 {
 	char *have_port_opt = options ? strstr(options, "port=") : NULL;
 	struct conn_info pm_info, rpc_info;
@@ -695,7 +701,9 @@ done:
 	return 0;
 }
 
-int prune_host_list(struct host **list, unsigned int vers, const char *options)
+int prune_host_list(struct host **list,
+		    unsigned int vers, const char *options,
+		    unsigned int random_selection)
 {
 	struct host *this, *last, *first;
 	struct host *new = NULL;
@@ -734,7 +742,8 @@ int prune_host_list(struct host **list, 
 			break;
 
 		if (this->name) {
-			status = get_vers_and_cost(this, vers, options);
+			status = get_vers_and_cost(this, vers,
+						   options, random_selection);
 			if (!status) {
 				if (this == first) {
 					first = next;
@@ -824,7 +833,9 @@ int prune_host_list(struct host **list, 
 			remove_host(list, this);
 			add_host(&new, this);
 		} else {
-			status = get_supported_ver_and_cost(this, selected_version, options);
+			status = get_supported_ver_and_cost(this,
+						selected_version, options,
+						random_selection);
 			if (status) {
 				this->version = selected_version;
 				remove_host(list, this);
diff -up autofs-5.0.2/daemon/automount.c.random-selection-fix autofs-5.0.2/daemon/automount.c
--- autofs-5.0.2/daemon/automount.c.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/daemon/automount.c	2007-11-20 14:55:28.000000000 +0900
@@ -52,9 +52,9 @@ const char *confdir = AUTOFS_CONF_DIR;	/
 
 const char *global_options;		/* Global option, from command line */
 
-static char *pid_file = NULL;	/* File in which to keep pid */
-unsigned int random_selection;	/* use random policy when selecting
-				 * which multi-mount host to mount */
+static char *pid_file = NULL;		/* File in which to keep pid */
+unsigned int global_random_selection;	/* use random policy when selecting
+					 * which multi-mount host to mount */
 static int start_pipefd[2];
 static int st_stat = 0;
 static int *pst_stat = &st_stat;
@@ -1469,7 +1469,7 @@ int main(int argc, char *argv[])
 	timeout = defaults_get_timeout();
 	ghost = defaults_get_browse_mode();
 	logging = defaults_get_logging();
-	random_selection = 0;
+	global_random_selection = 0;
 	global_options = NULL;
 	have_global_options = 0;
 	foreground = 0;
@@ -1510,7 +1510,7 @@ int main(int argc, char *argv[])
 			exit(0);
 
 		case 'r':
-			random_selection = 1;
+			global_random_selection = 1;
 			break;
 
 		case 'O':
diff -up autofs-5.0.2/lib/master_tok.l.random-selection-fix autofs-5.0.2/lib/master_tok.l
--- autofs-5.0.2/lib/master_tok.l.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/lib/master_tok.l	2007-11-20 14:55:28.000000000 +0900
@@ -324,6 +324,7 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--
 	-g|--ghost|-?browse	{ return(OPT_GHOST); }
 	-v|--verbose		{ return(OPT_VERBOSE); }
 	-d|--debug		{ return(OPT_DEBUG); }
+	-r|--random-multimount-selection { return(OPT_RANDOM); }
 
 	{OPTWS}","{OPTWS}	{ return(COMMA); }
 
diff -up autofs-5.0.2/lib/master_parse.y.random-selection-fix autofs-5.0.2/lib/master_parse.y
--- autofs-5.0.2/lib/master_parse.y.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/lib/master_parse.y	2007-11-20 14:55:28.000000000 +0900
@@ -56,6 +56,8 @@ static char *type;
 static char *format;
 static long timeout;
 static unsigned ghost;
+extern unsigned global_random_selection;
+static unsigned random_selection;
 static char **tmp_argv;
 static int tmp_argc;
 static char **local_argv;
@@ -93,7 +95,7 @@ static int master_fprintf(FILE *, char *
 
 %token COMMENT
 %token MAP
-%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG
+%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM
 %token COLON COMMA NL DDASH
 %type <strtype> map
 %type <strtype> options
@@ -174,6 +176,7 @@ line:
 	| PATH COLON { master_notify($1); YYABORT; }
 	| PATH OPTION { master_notify($2); YYABORT; }
 	| PATH NILL { master_notify($2); YYABORT; }
+	| PATH OPT_RANDOM { master_notify($1); YYABORT; }
 	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
 	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
 	| PATH OPT_GHOST { master_notify($1); YYABORT; }
@@ -543,6 +546,7 @@ daemon_option: OPT_TIMEOUT NUMBER { time
 	| OPT_GHOST	{ ghost = 1; }
 	| OPT_VERBOSE	{ verbose = 1; }
 	| OPT_DEBUG	{ debug = 1; }
+	| OPT_RANDOM	{ random_selection = 1; }
 	;
 
 mount_option: OPTION
@@ -600,6 +604,7 @@ static void local_init_vars(void)
 	debug = 0;
 	timeout = -1;
 	ghost = defaults_get_browse_mode();
+	random_selection = global_random_selection;
 	tmp_argv = NULL;
 	tmp_argc = 0;
 	local_argv = NULL;
@@ -790,6 +795,7 @@ int master_parse_entry(const char *buffe
 		}
 		set_mnt_logging(ap);
 	}
+	entry->ap->random_selection = random_selection;
 
 /*
 	source = master_find_map_source(entry, type, format,
diff -up autofs-5.0.2/man/auto.master.5.in.random-selection-fix autofs-5.0.2/man/auto.master.5.in
--- autofs-5.0.2/man/auto.master.5.in.random-selection-fix	2007-11-20 14:55:28.000000000 +0900
+++ autofs-5.0.2/man/auto.master.5.in	2007-11-20 14:55:28.000000000 +0900
@@ -146,6 +146,12 @@ to prevent symlinking of local NFS mount
 prevent bind mounting of local NFS filesystems as well. If you need to
 prevent bind mounting for only specific entrys in a map then this
 can be done by adding the "port=" mount option to the given entries.
+.TP
+.I "\-r, \-\-random-multimount-selection"
+Enables the use of ramdom selection when choosing a host from a
+list of replicated servers. This option is applied to this mount
+only, overriding the global setting that may be specified on the
+command line.
 .SH GENERAL SYSTEM DEFAULTS CONFIGURATION
 .P
 The default value of several general settings may be changed in the

autofs-5.0.2-remove-unused-export-validation-code.patch:

--- NEW FILE autofs-5.0.2-remove-unused-export-validation-code.patch ---
diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
index 831d456..d79a94f 100644
--- a/lib/rpc_subs.c
+++ b/lib/rpc_subs.c
@@ -52,10 +52,7 @@
 /* Get numeric value of the n bits starting at position p */
 #define getbits(x, p, n)      ((x >> (p + 1 - n)) & ~(~0 << n))
 
-static char *domain = NULL;
-
 inline void dump_core(void);
-static pthread_mutex_t networks_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 /*
  * Create a UDP RPC client
@@ -764,573 +761,6 @@ void rpc_exports_free(exports list)
 	return;
 }
 
-static int masked_match(const char *addr, const char *mask)
-{
-	char buf[MAX_IFC_BUF], *ptr;
-	struct sockaddr_in saddr;
-	struct sockaddr_in6 saddr6;
-	struct ifconf ifc;
-	struct ifreq *ifr;
-	int sock, cl_flags, ret, i, is_ipv4, is_ipv6;
-	unsigned int msize;
-
-	sock = socket(AF_INET, SOCK_DGRAM, 0);
-	if (sock < 0) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "socket creation failed: %s", estr);
-		return 0;
-	}
-
-	if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(sock, F_SETFD, cl_flags);
-	}
-
-	ifc.ifc_len = sizeof(buf);
-	ifc.ifc_req = (struct ifreq *) buf;
-	ret = ioctl(sock, SIOCGIFCONF, &ifc);
-	if (ret == -1) {
-		close(sock);
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "ioctl: %s", estr);
-		return 0;
-	}
-
-	is_ipv4 = is_ipv6 = 0;
-	is_ipv4 = inet_pton(AF_INET, addr, &saddr.sin_addr);
-	if (!is_ipv4)
-		is_ipv6 = inet_pton(AF_INET6, addr, &saddr6.sin6_addr);
-
-	if (strchr(mask, '.')) {
-		struct sockaddr_in maddr;
-		uint32_t ma;
-		int i = 0;
-
-		ret = inet_aton(mask, &maddr.sin_addr);
-		if (!ret) {
-			close(sock);
-			return 0;
-		}
-
-		ma = ntohl((uint32_t) maddr.sin_addr.s_addr);
-		while (!(ma & 1)) {
-			i++;
-			ma = ma >> 1;
-		}
-
-		msize = i;
-	} else
-		msize = atoi(mask);
-
-	i = 0;
-	ptr = (char *) &ifc.ifc_buf[0];
-
-	while (ptr < buf + ifc.ifc_len) {
-		ifr = (struct ifreq *) ptr;
-
-		switch (ifr->ifr_addr.sa_family) {
-		case AF_INET:
-		{
-			struct sockaddr_in *if_addr;
-			uint32_t m, ia, ha;
-
-			if (!is_ipv4 || msize > 32)
-				break;
-
-			m = -1;
-			m = m << (32 - msize);
-			ha = ntohl((uint32_t) saddr.sin_addr.s_addr);
-
-			if_addr = (struct sockaddr_in *) &ifr->ifr_addr;
-			ia = ntohl((uint32_t) if_addr->sin_addr.s_addr);
-
-			if ((ia & m) == (ha & m)) {
-				close(sock);
-				return 1;
-			}
-			break;
-		}
-
-		/* glibc rpc only understands IPv4 atm */
-		case AF_INET6:
-			break;
-
-		default:
-			break;
-		}
-
-		i++;
-		ptr = (char *) &ifc.ifc_req[i];
-	}
-
-	close(sock);
-	return 0;
-}
-
-/*
- * This function has been adapted from the match_patern function
- * found in OpenSSH and is used in accordance with the copyright
- * notice found their.
- *
- * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland.
- */
-/*
- * Returns true if the given string matches the pattern (which
- * may contain ? and * as wildcards), and zero if it does not
- * match.
- */
-static int pattern_match(const char *s, const char *pattern)
-{
-	for (;;) {
-		/* If at end of pattern, accept if also at end of string. */
-		if (!*pattern)
-			return !*s;
-
-		if (*pattern == '*') {
-			/* Skip the asterisk. */
-			pattern++;
-
-			/* If at end of pattern, accept immediately. */
-			if (!*pattern)
-				return 1;
-
-			/* If next character in pattern is known, optimize. */
-			if (*pattern != '?' && *pattern != '*') {
-				/*
-				 * Look instances of the next character in
-				 * pattern, and try to match starting from
-				 * those.
-				 */
-				for (; *s; s++)
-					if (*s == *pattern &&
-					    pattern_match(s + 1, pattern + 1))
-						return 1;
-
-				/* Failed. */
-				return 0;
-			}
-			/*
-			 * Move ahead one character at a time and try to
-			 * match at each position.
-			 */
-			for (; *s; s++)
-				if (pattern_match(s, pattern))
-					return 1;
-			/* Failed. */
-			return 0;
-		}
-		/*
-		 * There must be at least one more character in the string.
-		 * If we are at the end, fail.
-		 */
-		if (!*s)
-			return 0;
-
-		/* Check if the next character of the string is acceptable. */
-		if (*pattern != '?' && *pattern != *s)
-			return 0;
-
-		/* Move to the next character, both in string and in pattern. */
-		s++;
-		pattern++;
-	}
-	/* NOTREACHED */
-}
-
-static int name_match(const char *name, const char *pattern)
-{
-	int ret;
-
-	if (strchr(pattern, '*') || strchr(pattern, '?'))
-		ret = pattern_match(name, pattern);
-	else {
-		ret = !memcmp(name, pattern, strlen(pattern));
-		/* Name could still be a netgroup (Solaris) */
-		if (!ret)
-			ret = innetgr(pattern, name, NULL, domain);
-	}
-
-	return ret;
-}
-
-static int fqdn_match(const char *pattern)
-{
-	char buf[MAX_IFC_BUF], *ptr;
-	struct ifconf ifc;
-	struct ifreq *ifr;
-	int sock, cl_flags, ret, i;
-	char fqdn[NI_MAXHOST + 1];
-
-	sock = socket(AF_INET, SOCK_DGRAM, 0);
-	if (sock < 0) {
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "socket creation failed: %s", estr);
-		return 0;
-	}
-
-	if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(sock, F_SETFD, cl_flags);
-	}
-
-	ifc.ifc_len = sizeof(buf);
-	ifc.ifc_req = (struct ifreq *) buf;
-	ret = ioctl(sock, SIOCGIFCONF, &ifc);
-	if (ret == -1) {
-		close(sock);
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "ioctl: %s", estr);
-		return 0;
-	}
-
-	i = 0;
-	ptr = (char *) &ifc.ifc_buf[0];
-
-	while (ptr < buf + ifc.ifc_len) {
-		ifr = (struct ifreq *) ptr;
-
-		switch (ifr->ifr_addr.sa_family) {
-		case AF_INET:
-		{
-			socklen_t slen = sizeof(struct sockaddr);
-
-			ret = getnameinfo(&ifr->ifr_addr, slen, fqdn,
-					  NI_MAXHOST, NULL, 0, NI_NAMEREQD);
-			if (!ret) {
-				ret = name_match(fqdn, pattern);
-				if (ret) {
-					close(sock);
-					return 1;
-				}
-			}
-			break;
-		}
-
-		/* glibc rpc only understands IPv4 atm */
-		case AF_INET6:
-			break;
-
-		default:
-			break;
-		}
-
-		i++;
-		ptr = (char *) &ifc.ifc_req[i];
-	}
-
-	close(sock);
-	return 0;
-}
-
-static int string_match(const char *myname, const char *pattern)
-{
-	struct addrinfo hints, *ni;
-	int ret;
-
-	/* Try simple name match first */
-	ret = name_match(myname, pattern);
-	if (ret)
-		goto done;
-
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_flags = AI_CANONNAME;
-	hints.ai_family = 0;
-	hints.ai_socktype = 0;
-
-	/* See if our canonical name matches */
-	if (getaddrinfo(myname, NULL, &hints, &ni) == 0) {
-		ret = name_match(ni->ai_canonname, pattern);
-		freeaddrinfo(ni);
-	} else
-		warn(LOGOPT_ANY, "name lookup failed: %s", gai_strerror(ret));
-	if (ret)
-		goto done;
-
-	/* Lastly see if the name of an interfaces matches */
-	ret = fqdn_match(pattern);
-done:
-	return ret;
-}
-
-static unsigned int inet_get_net_len(uint32_t net)
-{
-	int i;
-
-	for (i = 0; i < 32; i += 8) {
-		if (getbits(net, i + 7, 8))
-			break;
-	}
-
-	return (unsigned int) 32 - i;
-}
-
-static char *inet_fill_net(const char *net_num, char *net)
-{
-	char *np;
-	unsigned int dots = 3;
-
-	if (strlen(net_num) > INET_ADDRSTRLEN)
-		return NULL;
-
-	if (!isdigit(*net_num))
-		return NULL;
-
-	*net = '\0';
-	strcpy(net, net_num);
-
-	np = net;
-	while (*np++) {
-		if (*np == '.') {
-			np++;
-			dots--;
-			if (!*np && dots)
-				strcat(net, "0");
-			continue;
-		}
-
-		if ((*np && !isdigit(*np)) || dots < 0) {
-			*net = '\0';
-			return NULL;
-		}
-	}
-
-	while (dots--)
-		strcat(net, ".0");
-
-	return net;
-}
-
-static int match_network(const char *network)
-{
-	struct netent *pnent, nent;
-	const char *pcnet;
-	char *net, cnet[MAX_NETWORK_LEN], mask[4], *pmask;
-	unsigned int size;
-	size_t l_network = strlen(network) + 1;
-	int status;
-
-	if (l_network > MAX_NETWORK_LEN) {
-		error(LOGOPT_ANY,
-		      "match string \"%s\" too long", network);
-		return 0;
-	}
-
-	net = alloca(l_network);
-	if (!net)
-		return 0;
-	memset(net, 0, l_network);
-	strcpy(net, network);
-
-	if ((pmask = strchr(net, '/')))
-		*pmask++ = '\0';
-
-	status = pthread_mutex_lock(&networks_mutex);
-	if (status)
-		fatal(status);
-
-	pnent = getnetbyname(net);
-	if (pnent)
-		memcpy(&nent, pnent, sizeof(struct netent));
-
-	status = pthread_mutex_unlock(&networks_mutex);
-	if (status)
-		fatal(status);
-
-	if (pnent) {
-		uint32_t n_net;
-
-		switch (nent.n_addrtype) {
-		case AF_INET:
-			n_net = ntohl(nent.n_net);
-			pcnet = inet_ntop(AF_INET, &n_net, cnet, INET_ADDRSTRLEN);
-			if (!pcnet)
-				return 0;
-
-			if (!pmask) {
-				size = inet_get_net_len(nent.n_net);
-				if (!size)
-					return 0;
-			}
-			break;
-
-		case AF_INET6:
-			return 0;
-
-		default:
-			return 0;
-		}
-	} else {
-		int ret;
-
-		if (strchr(net, ':')) {
-			return 0;
-		} else {
-			struct in_addr addr;
-
-			pcnet = inet_fill_net(net, cnet);
-			if (!pcnet)
-				return 0;
-
-			ret = inet_pton(AF_INET, pcnet, &addr);
-			if (ret <= 0)
-				return 0;
-
-			if (!pmask) {
-				uint32_t nl_addr = htonl(addr.s_addr);
-				size = inet_get_net_len(nl_addr);
-				if (!size)
-					return 0;
-			}
-		}
-	}
-
-	if (!pmask) {
-		if (sprintf(mask, "%u", size) <= 0)
-			return 0;
-		pmask = mask;
-	}
-
-	debug(LOGOPT_ANY, "pcnet %s pmask %s", pcnet, pmask);
-
-	return masked_match(pcnet, pmask);
-}
-
-/*
- * Two export formats need to be understood to cater for different
- * NFS server exports.
- *
- * (host|wildcard|network[/mask]|@netgroup)
- *
- *     A host name which can be cannonical.
- *     A wildcard host name containing "*" and "?" with the usual meaning.
- *     A network in numbers and dots form with optional mask given as
- *     either a length or as numbers and dots.
- *     A netgroup identified by the prefix "@".
- *
- * [-](host|domain suffix|netgroup|@network[/mask])
- *
- *     A host name which can be cannonical.
- *     A domain suffix identified by a leading "." which will match all
- *     hosts in the given domain.
- *     A netgroup.
- *     A network identified by the prefix "@" given in numbers and dots
- *     form or as a network name with optional mask given as either a
- *     length or as numbers and dots.
- *     A "-" prefix can be appended to indicate access is denied.
- */
-static int host_match(char *pattern)
-{
-	unsigned int negate = (*pattern == '-');
-	const char *m_pattern = (negate ? pattern + 1 : pattern);
-	char myname[MAXHOSTNAMELEN + 1] = "\0";
-	int ret = 0;
-
-	if (gethostname(myname, MAXHOSTNAMELEN))
-		return 0;
-
-	if (yp_get_default_domain(&domain))
-		domain = NULL;
-
-	if (*m_pattern == '@') {
-		/*
-		 * The pattern begins with an "@" so it's a network
-		 * spec or it's a netgroup.
-		 */
-		ret = match_network(m_pattern + 1);
-		if (!ret)
-			ret = innetgr(m_pattern + 1, myname, NULL, domain);
-	} else if (*m_pattern == '.') {
-		size_t m_len = strlen(m_pattern);
-		char *has_dot = strchr(myname, '.');
-		/*
-		 * The pattern starts with a "." so it's a domain spec
-		 * of some sort.
-		 *
-		 * If the host name contains a dot then it must be either
-		 * a cannonical name or a simple NIS name.domain. So
-		 * perform a string match. Otherwise, append the domain
-		 * pattern to our simple name and try a wildcard pattern
-		 * match against the interfaces.
-		 */
-		if (has_dot) {
-			if (strlen(has_dot) == m_len)
-				ret = !memcmp(has_dot, m_pattern, m_len);
-		} else {
-			char *w_pattern = alloca(m_len + 2);
-			if (w_pattern) {
-				strcpy(w_pattern, "*");
-				strcat(w_pattern, m_pattern);
-				ret = fqdn_match(w_pattern);
-			}
-		}
-	} else if (!strcmp(m_pattern, "gss/krb5")) {
-		/* Leave this to the GSS layer */
-		return 1;
-	} else {
-		/*
-		 * Otherwise it's a network name or host name 
-		 */
-		ret = match_network(m_pattern);
-		if (!ret)
-			/* if not then try to match host name */
-			ret = string_match(myname, m_pattern);
-	}
-
-	if (negate && ret)
-		ret = -1;
-
-	return ret;
-}
-
-static int rpc_export_allowed(groups grouplist)
-{
-	groups grp = grouplist;
-
-	/* NULL group list => everyone */
-	if (!grp)
-		return 1;
-
-	while (grp) {
-		int allowed = host_match(grp->gr_name);
-		/* Explicitly denied access */
-		if (allowed == -1)
-			return 0;
-		else if (allowed)
-			return 1;
-		grp = grp->gr_next;
-	}
-	return 0;
-}
-
-exports rpc_exports_prune(exports list)
-{
-	exports head = list;
-	exports exp;
-	exports last;
-	int res;
-
-	exp = list;
-	last = NULL;
-	while (exp) {
-		res = rpc_export_allowed(exp->ex_groups);
-		if (!res) {
-			if (last == NULL) {
-				head = exp->ex_next;
-				rpc_export_free(exp);
-				exp = head;
-			} else {
-				last->ex_next = exp->ex_next;
-				rpc_export_free(exp);
-				exp = last->ex_next;
-			}
-			continue;
-		}
-		last = exp;
-		exp = exp->ex_next;
-	}
-	return head;
-}
-
 exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option)
 {
 	struct conn_info info;
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index 1f8fa15..d711611 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -45,7 +45,6 @@ struct lookup_context {
 int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
 
 exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option);
-exports rpc_exports_prune(exports list);
 void rpc_exports_free(exports list);
 
 int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context)
@@ -207,9 +206,6 @@ done:
 
 	exp = rpc_get_exports(name, 10, 0, RPC_CLOSE_NOLINGER);
 
-	/* Check exports for obvious ones we don't have access to */
-	/*exp = rpc_exports_prune(exp);*/
-
 	mapent = NULL;
 	while (exp) {
 		if (mapent) {

autofs-5.0.2-report-failed-lookups.patch:

--- NEW FILE autofs-5.0.2-report-failed-lookups.patch ---
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 1007de4..23ea07d 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -1088,8 +1088,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 			if (status == NSS_STATUS_COMPLETED)
 				return NSS_STATUS_SUCCESS;
 
-			debug(ap->logopt,
-			      MODPREFIX "check indirect map lookup failed");
+			error(ap->logopt,
+			      MODPREFIX "key \"%s\" not found in map",
+			      name);
 
 			return NSS_STATUS_NOTFOUND;
 		}
@@ -1130,7 +1131,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 			}
 			cache_unlock(mc);
 		}
-	}
+	} else
+		error(ap->logopt,
+		      MODPREFIX "key \"%s\" not found in map.", name);
 
 	if (ret)
 		return NSS_STATUS_TRYAGAIN;
diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c
index 649e24c..737a47e 100644
--- a/modules/lookup_hesiod.c
+++ b/modules/lookup_hesiod.c
@@ -129,8 +129,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	if (!hes_result || !hes_result[0]) {
 		/* Note: it is not clear to me how to distinguish between
 		 * the "no search results" case and other failures.  --JM */
-		warn(ap->logopt,
-		     MODPREFIX "entry \"%s\" not found in map", name);
+		error(ap->logopt,
+		      MODPREFIX "key \"%s\" not found in map", name);
 		status = pthread_mutex_unlock(&hesiod_mutex);
 		if (status)
 			fatal(status);
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 4dea3b2..bad48bb 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -2089,8 +2089,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
 		free(lkp_key);
 		if (status) {
-			debug(ap->logopt,
-			      MODPREFIX "check indirect map failure");
+			error(ap->logopt,
+			      MODPREFIX "key \"%s\" not found in map",
+			      name);
 			return status;
 		}
 	}
@@ -2129,7 +2130,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 			}
 			cache_unlock(mc);
 		}
-	}
+	} else
+		error(ap->logopt,
+		      MODPREFIX "key \"%s\" not found in map", name);
 
 	if (ret)
 		return NSS_STATUS_TRYAGAIN;
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index e948c14..bb1ca42 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -512,8 +512,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 		status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
 		if (status) {
-			debug(ap->logopt,
-			      MODPREFIX "check indirect map failure");
+			error(ap->logopt,
+			      MODPREFIX "key \"%s\" not found in map",
+			      name);
 			return status;
 		}
 	}
@@ -551,7 +552,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 			}
 			cache_unlock(mc);
 		}
-	}
+	} else
+		error(ap->logopt,
+		      MODPREFIX "key \"%s\" not found in map", name);
 
 	if (ret)
 		return NSS_STATUS_NOTFOUND;
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 6c20145..e8ca8e8 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -604,8 +604,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
 		free(lkp_key);
 		if (status) {
-			debug(ap->logopt,
-			      MODPREFIX "check indirect map lookup failed");
+			error(ap->logopt,
+			      MODPREFIX "key \"%s\" not found in map",
+			      name);
 			return status;
 		}
 	}
@@ -643,7 +644,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 			}
 			cache_unlock(mc);
 		}
-	}
+	 } else
+		error(ap->logopt,
+		      MODPREFIX "key \"%s\" not found in map", name);
 
 	if (ret)
 		return NSS_STATUS_TRYAGAIN;

autofs-5.0.2-reread-config-on-hup.patch:

--- NEW FILE autofs-5.0.2-reread-config-on-hup.patch ---
diff -up autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup autofs-5.0.2/modules/cyrus-sasl.c
--- autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup	2007-11-20 15:00:13.000000000 +0900
+++ autofs-5.0.2/modules/cyrus-sasl.c	2007-11-20 15:00:13.000000000 +0900
@@ -528,6 +528,7 @@ sasl_do_kinit(struct lookup_context *ctx
 	return 0;
 
 out_cleanup_unparse:
+	krb5cc_in_use--;
 	krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name);
 out_cleanup_cc:
 	status = pthread_mutex_lock(&krb5cc_mutex);
diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/modules/lookup_ldap.c
--- autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup	2007-11-20 15:00:13.000000000 +0900
+++ autofs-5.0.2/modules/lookup_ldap.c	2007-11-20 15:00:13.000000000 +0900
@@ -174,7 +174,7 @@ LDAP *init_ldap_connection(struct lookup
 static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
 {
 	char buf[PARSE_MAX_BUF];
-	char *query, *dn;
+	char *query, *dn, *qdn;
 	LDAPMessage *result = NULL, *e;
 	struct ldap_searchdn *sdns = NULL;
 	char *attrs[2];
@@ -225,15 +225,18 @@ static int get_query_dn(LDAP *ldap, stru
 
 	if (!ctxt->base) {
 		sdns = defaults_get_searchdns();
-		if (sdns)
+		if (sdns) {
+			if (ctxt->sdns)
+				defaults_free_searchdns(ctxt->sdns);
 			ctxt->sdns = sdns;
+		}
 	}
 
-	if (!sdns)
+	if (!ctxt->sdns)
 		rv = ldap_search_s(ldap, ctxt->base,
 				   scope, query, attrs, 0, &result);
 	else {
-		struct ldap_searchdn *this = sdns;
+		struct ldap_searchdn *this = ctxt->sdns;
 
 		debug(LOGOPT_NONE, MODPREFIX
 			      "check search base list");
@@ -269,7 +272,6 @@ static int get_query_dn(LDAP *ldap, stru
 	if (e) {
 		dn = ldap_get_dn(ldap, e);
 		debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn);
-		ldap_msgfree(result);
 	} else {
 		debug(LOGOPT_NONE,
 		      MODPREFIX "query succeeded, no matches for %s",
@@ -278,7 +280,16 @@ static int get_query_dn(LDAP *ldap, stru
 		return 0;
 	}
 
-	ctxt->qdn = dn;
+	qdn = strdup(dn);
+	ldap_memfree(dn);
+	ldap_msgfree(result);
+	if (!qdn)
+		return 0;
+
+	if (ctxt->qdn)
+		free(ctxt->qdn);
+
+	ctxt->qdn = qdn;
 
 	return 1;
 }
@@ -1018,7 +1029,7 @@ static void free_context(struct lookup_c
 	if (ctxt->mapname)
 		free(ctxt->mapname);
 	if (ctxt->qdn)
-		ldap_memfree(ctxt->qdn);
+		free(ctxt->qdn);
 	if (ctxt->server)
 		free(ctxt->server);
 	if (ctxt->cur_host)
@@ -1600,14 +1611,14 @@ static int lookup_one(struct autofs_poin
 	}
 	query[ql] = '\0';
 
-	debug(ap->logopt,
-	      MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
-
 	/* Initialize the LDAP context. */
 	ldap = do_connect(ctxt);
 	if (!ldap)
 		return CHE_FAIL;
 
+	debug(ap->logopt,
+	      MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
+
 	rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result);
 
 	if ((rv != LDAP_SUCCESS) || !result) {
diff -up autofs-5.0.2/daemon/automount.c.reread-config-on-hup autofs-5.0.2/daemon/automount.c
--- autofs-5.0.2/daemon/automount.c.reread-config-on-hup	2007-11-20 15:00:13.000000000 +0900
+++ autofs-5.0.2/daemon/automount.c	2007-11-20 15:00:13.000000000 +0900
@@ -978,6 +978,8 @@ static void *do_read_master(void *arg)
 	if (status)
 		fatal(status);
 
+	defaults_read_config();
+
 	status = master_read_master(master, age, readall);
 
 	master->reading = 0;
diff -up autofs-5.0.2/lib/master.c.reread-config-on-hup autofs-5.0.2/lib/master.c
--- autofs-5.0.2/lib/master.c.reread-config-on-hup	2007-11-20 15:00:13.000000000 +0900
+++ autofs-5.0.2/lib/master.c	2007-11-20 15:00:13.000000000 +0900
@@ -1170,6 +1170,10 @@ int master_mount_mounts(struct master *m
 			continue;
 		}
 
+		master_source_writelock(this);
+		lookup_close_lookup(ap);
+		master_source_unlock(this);
+
 		cache_readlock(nc);
 		ne = cache_lookup_distinct(nc, this->path);
 		if (ne && this->age > ne->age) {

autofs-5.0.2-singleton-host-list.patch:

--- NEW FILE autofs-5.0.2-singleton-host-list.patch ---
diff --git a/modules/replicated.c b/modules/replicated.c
index 14b20a9..90b2925 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -725,19 +725,21 @@ int prune_host_list(unsigned logopt, struct host **list,
 	while (this && this->proximity == PROXIMITY_LOCAL)
 		this = this->next;
 
-	proximity = PROXIMITY_LOCAL;
-	if (this)
-		proximity = this->proximity;
+	/*
+	 * Check for either a list containing only proximity local hosts
+	 * or a single host entry whose proximity isn't local. If so
+	 * return immediately as we don't want to add probe latency for
+	 * the common case of a single filesystem mount request.
+	 */
+	if (!this || !this->next)
+		return 1;
 
+	proximity = this->proximity;
+	first = this;
 	this = first;
 	while (this) {
 		struct host *next = this->next;
 
-		if (this->proximity == PROXIMITY_LOCAL) {
-			this = next;
-			continue;
-		}
-
 		if (this->proximity != proximity)
 			break;
 
@@ -758,10 +760,6 @@ int prune_host_list(unsigned logopt, struct host **list,
 
 	last = this;
 
-	/* If there are only local entries on the list, just return it. */
-	if (!first)
-		return 0;
-
 	/* Select NFS version of highest number of closest servers */
 
 	v4_tcp_count = v3_tcp_count = v2_tcp_count = 0;

autofs-5.0.2-submount-deadlock.patch:

--- NEW FILE autofs-5.0.2-submount-deadlock.patch ---
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index f8d8ed2..c45b91b 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -215,6 +215,8 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
 		return 1;
 	}
 
+	mounts_mutex_lock(ap);
+
 	status = pthread_mutex_lock(&suc.mutex);
 	if (status) {
 		crit(ap->logopt,
@@ -227,8 +229,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
 	suc.done = 0;
 	suc.status = 0;
 
-	mounts_mutex_lock(ap);
-
 	if (pthread_create(&thid, NULL, handle_mounts, nap)) {
 		crit(ap->logopt,
 		     MODPREFIX

autofs-5.0.2-swallow-null-macro.patch:

--- NEW FILE autofs-5.0.2-swallow-null-macro.patch ---
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 5e14c75..079bda6 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -186,8 +186,7 @@ int expandsunent(const char *src, char *dst, const char *key,
 						dst += l;
 					}
 					len += l;
-				} else
-					return 0;
+				}
 				src = p + 1;
 			} else {
 				p = src;
@@ -201,8 +200,7 @@ int expandsunent(const char *src, char *dst, const char *key,
 						dst += l;
 					}
 					len += l;
-				} else
-					return 0;
+				}
 				src = p;
 			}
 			break;

autofs-5.0.2-timeout-option-parse-fix.patch:

--- NEW FILE autofs-5.0.2-timeout-option-parse-fix.patch ---
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 013a15a..2735223 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -313,7 +313,7 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 		return(DDASH);
 	}
 
-	{OPTTOUT} { return(OPT_TIMEOUT); }
+	{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
 
 	{NUMBER} {
 		master_lval.longtype = atol(master_text);


Index: autofs.spec
===================================================================
RCS file: /cvs/pkgs/rpms/autofs/devel/autofs.spec,v
retrieving revision 1.223
retrieving revision 1.224
diff -u -r1.223 -r1.224
--- autofs.spec	24 Sep 2007 06:58:44 -0000	1.223
+++ autofs.spec	20 Nov 2007 07:34:21 -0000	1.224
@@ -4,7 +4,7 @@
 Summary: A tool for automatically mounting and unmounting filesystems
 Name: autofs
 Version: 5.0.2
-Release: 16
+Release: 18
 Epoch: 1
 License: GPL
 Group: System Environment/Daemons
@@ -31,6 +31,30 @@
 Patch18: autofs-5.0.2-ldap-schema-discovery-config-update.patch
 Patch19: autofs-5.0.2-libxml2-workaround.patch
 Patch20: autofs-5.0.2-foreground-logging.patch
+Patch21: autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch
+Patch22: autofs-5.0.2-ldap-check-star.patch
+Patch23: autofs-5.0.2-timeout-option-parse-fix.patch
+Patch24: autofs-5.0.2-ldap-search-basedn-list.patch
+Patch25: autofs-5.0.2-random-selection-fix.patch
+Patch26: autofs-5.0.2-reread-config-on-hup.patch
+Patch27: autofs-5.0.2-add-multiple-server-selection-option.patch
+Patch28: autofs-5.0.2-submount-deadlock.patch
+Patch29: autofs-5.0.2-add-ferror-check.patch
+Patch30: autofs-5.0.2-autofs-5-typo.patch
+Patch31: autofs-5.0.2-swallow-null-macro.patch
+Patch32: autofs-5.0.2-remove-unused-export-validation-code.patch
+Patch33: autofs-5.0.2-dynamic-logging.patch
+Patch34: autofs-5.0.2-fix-recursive-loopback-mounts.patch
+Patch35: autofs-5.0.2-log-map-reload.patch
+Patch36: autofs-5.0.2-dynamic-logging-fixes.patch
+Patch37: autofs-5.0.2-basedn-with-spaces.patch
+Patch38: autofs-5.0.2-check-mtab-updated.patch
+Patch39: autofs-5.0.2-check-auto_master.patch
+Patch40: autofs-5.0.2-negative-timeout-update.patch
+Patch41: autofs-5.0.2-large-groups.patch
+Patch42: autofs-5.0.2-report-failed-lookups.patch
+Patch43: autofs-5.0.2-dynamic-logging-non-sasl.patch
+Patch44: autofs-5.0.2-singleton-host-list.patch
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs
 Conflicts: kernel < 2.6.17
@@ -93,6 +117,30 @@
 %patch18 -p1
 %patch19 -p1
 %patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
+%patch31 -p1
+%patch32 -p1
+%patch33 -p1
+%patch34 -p1
+%patch35 -p1
+%patch36 -p1
+%patch37 -p1
+%patch38 -p1
+%patch39 -p1
+%patch40 -p1
+%patch41 -p1
+%patch42 -p1
+%patch43 -p1
+%patch44 -p1
 
 %build
 #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir}
@@ -145,6 +193,30 @@
 %{_libdir}/autofs/
 
 %changelog
+* Tue Nov 20 2007 Ian Kent <ikent at redhat.com> - 5.0.2-18
+- fix schema selection in LDAP schema discovery.
+- check for "*" when looking up wildcard in LDAP.
+- fix couple of edge case parse fails of timeout option.
+- add SEARCH_BASE configuration option.
+- add random selection as a master map entry option.
+- re-read config on HUP signal.
+- add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options.
+- fix deadlock in submount mount module.
+- fix lack of ferror() checking when reading files.
+- fix typo in autofs(5) man page.
+- fix map entry expansion when undefined macro is present.
+- remove unused export validation code.
+- add dynamic logging (adapted from v4 patch from Jeff Moyer).
+- fix recursive loopback mounts (Matthias Koenig).
+- add map re-load to verbose logging.
+- fix handling of LDAP base dns with spaces.
+- handle MTAB_NOTUPDATED status return from mount.
+- when default master map, auto.master, is used also check for auto_master.
+- update negative mount timeout handling.
+- fix large group handling (Ryan Thomas).
+- fix for dynamic logging breaking non-sasl build (Guillaume Rousse).
+- eliminate NULL proc ping for singleton host or local mounts.
+
 * Mon Sep 24 2007 Ian Kent <ikent at redhat.com> - 5.0.2-16
 - add descriptive comments to config about LDAP schema discovery.
 - work around segfault at exit caused by libxml2.




More information about the fedora-extras-commits mailing list