File autofs-5.0.2-upstream-patches-20071215 of Package autofs5

diff --git a/CHANGELOG b/CHANGELOG
index 172d0cd..6931791 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+??/??/2007 autofs-5.0.3
+-----------------------
+- include krb5.h in lookup_ldap.h (some openssl doesn't implicitly include it).
+
 18/06/2007 autofs-5.0.2
 -----------------------
 - fix return check for getpwuid_r and getgrgid_r.
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index e1c5b4e..0a9deca 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -7,6 +7,7 @@
 #include <openssl/err.h>
 #include <sasl/sasl.h>
 #include <libxml/tree.h>
+#include <krb5.h>
 #endif
 
 struct lookup_context {
diff --git a/CHANGELOG b/CHANGELOG
index 6931791..91903e9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 ??/??/2007 autofs-5.0.3
 -----------------------
 - include krb5.h in lookup_ldap.h (some openssl doesn't implicitly include it).
+- correct initialization of local var in parse_server_string.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 06506a0..de8d515 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -549,7 +549,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 	const char *ptr, *name;
 	int l, al_len;
 
-	*proto = '\0';
+	memset(proto, 0, 9);
 	ptr = url;
 
 	debug(LOGOPT_NONE,
@@ -620,7 +620,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 	} else if (strchr(ptr, ':') != NULL) {
 		char *q = NULL;
 
-		/* Isolate the server(s). Include the port spec */
+		/* Isolate the server. Include the port spec */
 		q = strchr(ptr, ':');
 		if (isdigit(*q))
 			while (isdigit(*q))
@@ -633,7 +633,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 		}
 
 		l = q - ptr;
-		if (proto) {
+		if (*proto) {
 			al_len = l + strlen(proto) + 2;
 			tmp = malloc(al_len);
 		} else {
diff --git a/CHANGELOG b/CHANGELOG
index 91903e9..6b16b0f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,7 @@
 -----------------------
 - include krb5.h in lookup_ldap.h (some openssl doesn't implicitly include it).
 - correct initialization of local var in parse_server_string.
+- add missing "multi" map support.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 06fcecc..70b9e02 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -456,8 +456,12 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
 		}
 
 		if (map->type) {
-			debug(ap->logopt,
-			      "reading map %s %s", map->type, map->argv[0]);
+			if (!strncmp(map->type, "multi", 5))
+				debug(ap->logopt, "reading multi map");
+			else
+				debug(ap->logopt,
+				      "reading map %s %s",
+				       map->type, map->argv[0]);
 			result = do_read_map(ap, map, age);
 			map = map->next;
 			continue;
diff --git a/include/automount.h b/include/automount.h
index 85e6e9c..106ed0a 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -192,6 +192,7 @@ char *cache_get_offset(const char *prefix, char *offset, int start, struct list_
 /* Utility functions */
 
 char **add_argv(int argc, char **argv, char *str);
+char **append_argv(int argc1, char **argv1, int argc2, char **argv2);
 const char **copy_argv(int argc, const char **argv);
 int compare_argv(int argc1, const char **argv1, int argc2, const char **argv2);
 int free_argv(int argc, const char **argv);
diff --git a/lib/args.c b/lib/args.c
index 9e35388..fbfb004 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -62,6 +62,45 @@ char **add_argv(int argc, char **argv, char *str)
 	return vector;
 }
 
+char **append_argv(int argc1, char **argv1, int argc2, char **argv2)
+{
+	char **vector;
+	size_t vector_size;
+	int len, i, j;
+
+	len = argc1 + argc2;
+	vector_size = (len + 1) * sizeof(char *);
+	vector = (char **) realloc(argv1, vector_size);
+	if (!vector) {
+		free_argv(argc1, (const char **) argv1);
+		free_argv(argc2, (const char **) argv2);
+		return NULL;
+	}
+
+	for (i = argc1, j = 0; i <= len; i++, j++) {
+		if (argv2[j]) {
+			vector[i] = strdup(argv2[j]);
+			if (!vector[i]) {
+				error(LOGOPT_ANY, "failed to strdup arg");
+				break;
+			}
+		} else
+			vector[i] = NULL;
+	}
+
+	if (i < len) {
+		free_argv(len, (const char **) vector);
+		free_argv(argc2, (const char **) argv2);
+		return NULL;
+	}
+
+	vector[len] = NULL;
+
+	free_argv(argc2, (const char **) argv2);
+
+	return vector;
+}
+
 const char **copy_argv(int argc, const char **argv)
 {
 	char **vector;
diff --git a/lib/master_parse.y b/lib/master_parse.y
index 8d2be02..f9cba05 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <ctype.h>
 #include <sys/ioctl.h>
 
 #include "automount.h"
@@ -44,6 +45,7 @@ extern void master_set_scan_buffer(const char *);
 static char *master_strdup(char *);
 static void local_init_vars(void);
 static void local_free_vars(void);
+static int add_multi_mapstr(void);
 
 static int master_error(const char *s);
 static int master_notify(const char *s);
@@ -53,6 +55,8 @@ static char *type;
 static char *format;
 static long timeout;
 static unsigned ghost;
+static char **tmp_argv;
+static int tmp_argc;
 static char **local_argv;
 static int local_argc;
 
@@ -89,7 +93,7 @@ static int master_fprintf(FILE *, char *, ...);
 %token COMMENT
 %token MAP
 %token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG
-%token COLON COMMA NL
+%token COLON COMMA NL DDASH
 %type <strtype> map
 %type <strtype> options
 %type <strtype> dn
@@ -103,6 +107,7 @@ static int master_fprintf(FILE *, char *, ...);
 %token <strtype> NILL
 %token <strtype> SPACE
 %token <strtype> EQUAL
+%token <strtype> MULTITYPE
 %token <strtype> MAPTYPE
 %token <strtype> DNSERVER
 %token <strtype> DNATTR
@@ -126,7 +131,7 @@ file: {
 	;
 
 line:
-	| PATH map
+	| PATH mapspec
 	{
 		path = master_strdup($1);
 		if (!path) {
@@ -134,14 +139,49 @@ line:
 			YYABORT;
 		}
 	}
-	| PATH map options
+	| PATH MULTITYPE maplist
 	{
+		char *tmp;
+
+		tmp = strchr($2, ':');
+		if (tmp)
+			*tmp = '\0';
+		else {
+			int len = strlen($2);
+			while (len-- && isblank($2[len]))
+				$2[len] = '\0';
+			if (len < 4) {
+				master_notify($2);
+				local_free_vars();
+				YYABORT;
+			}
+		}
+
 		path = master_strdup($1);
 		if (!path) {
+			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
-	} 
+
+		if ((tmp = strchr($2, ',')))
+			*tmp++ = '\0';
+
+		type = master_strdup($2);
+		if (!type) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+		if (tmp) {
+			format = master_strdup(tmp);
+			if (!format) {
+				master_error("memory allocation error");
+				local_free_vars();
+				YYABORT;
+			}
+		}
+	}
 	| PATH COLON { master_notify($1); YYABORT; }
 	| PATH OPTION { master_notify($2); YYABORT; }
 	| PATH NILL { master_notify($2); YYABORT; }
@@ -157,25 +197,89 @@ line:
 	| COMMENT { YYABORT; }
 	;
 
-map:	PATH
+mapspec: map
+	{
+		local_argc = tmp_argc;
+		local_argv = tmp_argv;
+		tmp_argc = 0;
+		tmp_argv = NULL;
+	}
+	| map options
+	{
+		local_argc = tmp_argc;
+		local_argv = tmp_argv;
+		tmp_argc = 0;
+		tmp_argv = NULL;
+	}
+	;
+
+maplist: map
+	{
+		if (!add_multi_mapstr()) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| map options
+	{
+		if (!add_multi_mapstr()) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| maplist DDASH map
 	{
 		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $1);
+		local_argv = add_argv(local_argc, local_argv, "--");
 		if (!local_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
+		if (!add_multi_mapstr()) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
 	}
-	| MAPNAME
+	| maplist DDASH map options
 	{
 		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $1);
+		local_argv = add_argv(local_argc, local_argv, "--");
 		if (!local_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
+		if (!add_multi_mapstr()) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	;
+
+map:	PATH
+	{
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| MAPNAME
+	{
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
 	}
 	| MAPHOSTS
 	{
@@ -200,9 +304,9 @@ map:	PATH
 			local_free_vars();
 			YYABORT;
 		}
-		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $1);
-		if (!local_argv) {
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
@@ -227,9 +331,9 @@ map:	PATH
 				YYABORT;
 			}
 		}
-		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $3);
-		if (!local_argv) {
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
@@ -254,9 +358,9 @@ map:	PATH
 				YYABORT;
 			}
 		}
-		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $3);
-		if (!local_argv) {
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
@@ -281,25 +385,25 @@ map:	PATH
 				YYABORT;
 			}
 		}
-		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $3);
-		if (!local_argv) {
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
 		/* Add back the type for lookup_ldap.c to handle ldaps */
-		if (*local_argv[0]) {
-			tmp = malloc(strlen(type) + strlen(local_argv[0]) + 2);
+		if (*tmp_argv[0]) {
+			tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
 			if (!tmp) {
 				local_free_vars();
 				YYABORT;
 			}
 			strcpy(tmp, type);
 			strcat(tmp, ":");
-			strcat(tmp, local_argv[0]);
-			free(local_argv[0]);
-			local_argv[0] = tmp;
+			strcat(tmp, tmp_argv[0]);
+			free(tmp_argv[0]);
+			tmp_argv[0] = tmp;
 		}
 	}
 	;
@@ -441,9 +545,9 @@ daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
 
 mount_option: OPTION
 	{
-		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, $1);
-		if (!local_argv) {
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
@@ -494,6 +598,8 @@ static void local_init_vars(void)
 	debug = 0;
 	timeout = -1;
 	ghost = defaults_get_browse_mode();
+	tmp_argv = NULL;
+	tmp_argc = 0;
 	local_argv = NULL;
 	local_argc = 0;
 }
@@ -509,8 +615,62 @@ static void local_free_vars(void)
 	if (format)
 		free(format);
 
-	if (local_argv)
+	if (local_argv) {
 		free_argv(local_argc, (const char **) local_argv);
+		local_argv = NULL;
+		local_argc = 0;
+	}
+
+	if (tmp_argv) {
+		free_argv(tmp_argc, (const char **) tmp_argv);
+		tmp_argv = NULL;
+		tmp_argc = 0;
+	}
+}
+
+static int add_multi_mapstr(void)
+{
+	/* We need the individual map types for a multi map */
+	if (!type) {
+		if (tmp_argc > 0 && *tmp_argv[0] == '/')
+			type = strdup("file");
+		else
+			return 0;
+	}
+
+	if (format) {
+		char *tmp = realloc(type, strlen(type) + strlen(format) + 2);
+		if (!tmp)
+			return 0;
+		type = tmp;
+		strcat(type, ",");
+		strcat(type, format);
+		free(format);
+		format = NULL;
+	}
+
+	local_argc++;
+	local_argv = add_argv(local_argc, local_argv, type);
+	if (!local_argv) {
+		free(type);
+		type = NULL;
+		return 0;
+	}
+
+	local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
+	if (!local_argv) {
+		free(type);
+		type = NULL;
+		return 0;
+	}
+	local_argc += tmp_argc;
+
+	tmp_argc = 0;
+	tmp_argv = NULL;
+	free(type);
+	type = NULL;
+
+	return 1;
 }
 
 void master_init_scan(void)
diff --git a/lib/master_tok.l b/lib/master_tok.l
index ee2a4eb..0548de1 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -27,6 +27,7 @@ static void master_echo(void);	/* forward definition */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include "master_parse.tab.h"
 
 /*
@@ -110,7 +111,9 @@ DNATTRSTR	{AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}
 DNNAMESTR	([[:alnum:]_.\-]+)
 
 INTMAP		(-hosts|-null)
-MTYPE           ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?)
+MULTI		((multi)(,(sun|hesiod))?[\:]?{OPTWS})
+MULTISEP	([\-]{2}[[:blank:]]+)
+MTYPE		((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?)
 
 
 OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
@@ -184,11 +187,18 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 <MAPSTR>{
 	{OPTWS}\\\n{OPTWS} {}
 
+	{MULTI} {
+		strcpy(master_lval.strtype, master_text);
+		return(MULTITYPE);
+	}
+
 	{MTYPE}/":" {
 		strcpy(master_lval.strtype, master_text);
 		return(MAPTYPE);
 	}
 
+	{MULTISEP} { return(DDASH); }
+
 	":"	{ return(COLON); }
 
 	"-hosts" {
@@ -298,6 +308,11 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 <OPTSTR>{
 	{OPTWS}\\\n{OPTWS} {}
 
+	{MULTISEP} {
+		BEGIN(MAPSTR);
+		return(DDASH);
+	}
+
 	{OPTTOUT} { return(OPT_TIMEOUT); }
 
 	{NUMBER} {
diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c
index 00ab28e..38ca36c 100644
--- a/modules/lookup_multi.c
+++ b/modules/lookup_multi.c
@@ -45,7 +45,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 	struct lookup_context *ctxt;
 	char buf[MAX_ERR_BUF];
 	char *map, *mapfmt;
-	int i, j, an;
+	int i, an;
 	char *estr;
 
 	ctxt = malloc(sizeof(struct lookup_context));
@@ -73,7 +73,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 
 	memcpy(ctxt->argl, argv, (argc + 1) * sizeof(const char *));
 
-	for (i = j = an = 0; ctxt->argl[an]; an++) {
+	for (i = an = 0; ctxt->argl[an]; an++) {
 		if (ctxt->m[i].argc == 0) {
 			ctxt->m[i].argv = &ctxt->argl[an];
 		}
@@ -100,9 +100,12 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 		if (!(ctxt->m[i].mod = open_lookup(map, MODPREFIX,
 						   mapfmt ? mapfmt : my_mapfmt,
 						   ctxt->m[i].argc - 1,
-						   ctxt->m[i].argv + 1)))
+						   ctxt->m[i].argv + 1))) {
 			error(LOGOPT_ANY, MODPREFIX "error opening module");
+			free(map);
 			goto error_out;
+		}
+		free(map);
 	}
 
 	*context = ctxt;
diff --git a/CHANGELOG b/CHANGELOG
index 6b16b0f..d66b8fc 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,7 @@
 - include krb5.h in lookup_ldap.h (some openssl doesn't implicitly include it).
 - correct initialization of local var in parse_server_string.
 - add missing "multi" map support.
+- add multi nsswitch lookup.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/lib/master_parse.y b/lib/master_parse.y
index f9cba05..ab2895d 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -45,6 +45,7 @@ extern void master_set_scan_buffer(const char *);
 static char *master_strdup(char *);
 static void local_init_vars(void);
 static void local_free_vars(void);
+static void trim_maptype(char *);
 static int add_multi_mapstr(void);
 
 static int master_error(const char *s);
@@ -141,21 +142,9 @@ line:
 	}
 	| PATH MULTITYPE maplist
 	{
-		char *tmp;
-
-		tmp = strchr($2, ':');
-		if (tmp)
-			*tmp = '\0';
-		else {
-			int len = strlen($2);
-			while (len-- && isblank($2[len]))
-				$2[len] = '\0';
-			if (len < 4) {
-				master_notify($2);
-				local_free_vars();
-				YYABORT;
-			}
-		}
+		char *tmp = NULL;
+
+		trim_maptype($2);
 
 		path = master_strdup($1);
 		if (!path) {
@@ -312,81 +301,93 @@ map:	PATH
 			YYABORT;
 		}
 	}
-	| MAPTYPE COLON PATH
+	| MAPTYPE PATH
 	{
 		char *tmp = NULL;
 
+		trim_maptype($1);
+
 		if ((tmp = strchr($1, ',')))
 			*tmp++ = '\0';
 
 		type = master_strdup($1);
 		if (!type) {
+			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
 		if (tmp) {
 			format = master_strdup(tmp);
 			if (!format) {
+				master_error("memory allocation error");
 				local_free_vars();
 				YYABORT;
 			}
 		}
 		tmp_argc++;
-		tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
 		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
 	}
-	| MAPTYPE COLON MAPNAME
+	| MAPTYPE MAPNAME
 	{
 		char *tmp = NULL;
 
+		trim_maptype($1);
+
 		if ((tmp = strchr($1, ',')))
 			*tmp++ = '\0';
 
 		type = master_strdup($1);
 		if (!type) {
+			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
 		if (tmp) {
 			format = master_strdup(tmp);
 			if (!format) {
+				master_error("memory allocation error");
 				local_free_vars();
 				YYABORT;
 			}
 		}
 		tmp_argc++;
-		tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
 		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
 	}
-	| MAPTYPE COLON dn
+	| MAPTYPE dn
 	{
 		char *tmp = NULL;
 
+		trim_maptype($1);
+
 		if ((tmp = strchr($1, ',')))
 			*tmp++ = '\0';
 
 		type = master_strdup($1);
 		if (!type) {
+			master_error("memory allocation error");
 			local_free_vars();
 			YYABORT;
 		}
 		if (tmp) {
 			format = master_strdup(tmp);
 			if (!format) {
+				master_error("memory allocation error");
 				local_free_vars();
 				YYABORT;
 			}
 		}
 		tmp_argc++;
-		tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $2);
 		if (!tmp_argv) {
 			master_error("memory allocation error");
 			local_free_vars();
@@ -396,6 +397,7 @@ map:	PATH
 		if (*tmp_argv[0]) {
 			tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
 			if (!tmp) {
+				master_error("memory allocation error");
 				local_free_vars();
 				YYABORT;
 			}
@@ -628,33 +630,47 @@ static void local_free_vars(void)
 	}
 }
 
-static int add_multi_mapstr(void)
+static void trim_maptype(char *type)
 {
-	/* We need the individual map types for a multi map */
-	if (!type) {
-		if (tmp_argc > 0 && *tmp_argv[0] == '/')
-			type = strdup("file");
-		else
-			return 0;
+	char *tmp;
+
+	tmp = strchr(type, ':');
+	if (tmp)
+		*tmp = '\0';
+	else {
+		int len = strlen(type);
+		while (len-- && isblank(type[len]))
+			type[len] = '\0';
 	}
+	return;
+}
+
+static int add_multi_mapstr(void)
+{
+	if (type) {
+		/* If type given and format is non-null add it back */
+		if (format) {
+			int len = strlen(type) + strlen(format) + 2;
+			char *tmp = realloc(type, len);
+			if (!tmp)
+				return 0;
+			type = tmp;
+			strcat(type, ",");
+			strcat(type, format);
+			free(format);
+			format = NULL;
+		}
 
-	if (format) {
-		char *tmp = realloc(type, strlen(type) + strlen(format) + 2);
-		if (!tmp)
+		local_argc++;
+		local_argv = add_argv(local_argc, local_argv, type);
+		if (!local_argv) {
+			free(type);
+			type = NULL;
 			return 0;
-		type = tmp;
-		strcat(type, ",");
-		strcat(type, format);
-		free(format);
-		format = NULL;
-	}
+		}
 
-	local_argc++;
-	local_argv = add_argv(local_argc, local_argv, type);
-	if (!local_argv) {
 		free(type);
 		type = NULL;
-		return 0;
 	}
 
 	local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
@@ -667,8 +683,6 @@ static int add_multi_mapstr(void)
 
 	tmp_argc = 0;
 	tmp_argv = NULL;
-	free(type);
-	type = NULL;
 
 	return 1;
 }
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 0548de1..9bfeefa 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -111,9 +111,9 @@ DNATTRSTR	{AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}
 DNNAMESTR	([[:alnum:]_.\-]+)
 
 INTMAP		(-hosts|-null)
-MULTI		((multi)(,(sun|hesiod))?[\:]?{OPTWS})
+MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
 MULTISEP	([\-]{2}[[:blank:]]+)
-MTYPE		((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?)
+MTYPE		((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?(:{OPTWS}|{WS}))
 
 
 OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
@@ -192,7 +192,7 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 		return(MULTITYPE);
 	}
 
-	{MTYPE}/":" {
+	{MTYPE} {
 		strcpy(master_lval.strtype, master_text);
 		return(MAPTYPE);
 	}
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 0e36a6f..98afaa9 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -103,6 +103,10 @@ entries are used for maps.
 .B ldap \fPor\fB ldaps
 The map is stored in an LDAP directory. If \fBldaps\fP is used the
 appropriate certificate must be configured in the LDAP client.
+.TP
+.B multi
+This map type allows the specification of multiple maps separated
+by "--". These maps are searched in order to resolve key lookups.
 .RE
 .TP
 \fBformat\fP
diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c
index 38ca36c..8fa94ae 100644
--- a/modules/lookup_multi.c
+++ b/modules/lookup_multi.c
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/stat.h>
 
 #define MODULE_LOOKUP
 #include "automount.h"
@@ -28,7 +29,7 @@
 
 struct module_info {
 	int argc;
-	const char *const *argv;
+	const char **argv;
 	struct lookup_mod *mod;
 };
 
@@ -40,11 +41,105 @@ struct lookup_context {
 
 int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
 
+static struct lookup_mod *nss_open_lookup(const char *format, int argc, const char **argv)
+{
+	struct list_head nsslist;
+	struct list_head *head, *p;
+	struct lookup_mod *mod;
+	char buf[MAX_ERR_BUF], *estr;
+
+	if (!argv || !argv[0])
+		return NULL;
+
+	if (*argv[0] == '/')
+		return open_lookup("file", MODPREFIX, format, argc, argv);
+
+	if (!strncmp(argv[0], "file", 4) ||
+	    !strncmp(argv[0], "yp", 2) ||
+	    !strncmp(argv[0], "nisplus", 7) ||
+	    !strncmp(argv[0], "nis", 3) ||
+	    !strncmp(argv[0], "ldaps", 5) ||
+	    !strncmp(argv[0], "ldap", 4)) {
+		const char *fmt = strchr(argv[0], ',');
+		if (fmt)
+			fmt++;
+		else
+			fmt = format;
+		return open_lookup(argv[0], MODPREFIX, fmt, argc -1, argv + 1);
+	}
+
+	INIT_LIST_HEAD(&nsslist);
+
+	if (nsswitch_parse(&nsslist)) {
+		if (!list_empty(&nsslist))
+			free_sources(&nsslist);
+		error(LOGOPT_ANY, "can't to read name service switch config.");
+		return NULL;
+	}
+
+	head = &nsslist;
+	list_for_each(p, head) {
+		struct nss_source *this;
+
+		this = list_entry(p, struct nss_source, list);
+
+		if (!strcmp(this->source, "files")) {
+			char src_file[] = "file";
+			char src_prog[] = "program";
+			struct stat st;
+			char *type, *path, *save_argv0;
+
+			path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(argv[0]) + 2);
+			if (!path) {
+				estr = strerror_r(errno, buf, MAX_ERR_BUF);
+				crit(LOGOPT_ANY, MODPREFIX "error: %s", estr);
+				free_sources(&nsslist);
+				return NULL;
+			}
+			strcpy(path, AUTOFS_MAP_DIR);
+			strcat(path, "/");
+			strcat(path, argv[0]);
+
+			if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) {
+				free(path);
+				continue;
+			}
+
+			if (st.st_mode & __S_IEXEC)
+				type = src_prog;
+			else
+				type = src_file;
+
+			save_argv0 = (char *) argv[0];
+			argv[0] = path;
+
+			mod = open_lookup(type, MODPREFIX, format, argc, argv);
+			if (mod) {
+				free_sources(&nsslist);
+				free(save_argv0);
+				return mod;
+			}
+
+			argv[0] = save_argv0;
+			free(path);
+		}
+
+		mod = open_lookup(this->source, MODPREFIX, format, argc, argv);
+		if (mod) {
+			free_sources(&nsslist);
+			return mod;
+		}
+	}
+	free_sources(&nsslist);
+
+	return NULL;
+}
+
 int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void **context)
 {
 	struct lookup_context *ctxt;
 	char buf[MAX_ERR_BUF];
-	char *map, *mapfmt;
+	char **args;
 	int i, an;
 	char *estr;
 
@@ -73,39 +168,42 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 
 	memcpy(ctxt->argl, argv, (argc + 1) * sizeof(const char *));
 
+	args = NULL;
 	for (i = an = 0; ctxt->argl[an]; an++) {
 		if (ctxt->m[i].argc == 0) {
-			ctxt->m[i].argv = &ctxt->argl[an];
+			args = (char **) &ctxt->argl[an];
 		}
 		if (!strcmp(ctxt->argl[an], "--")) {
 			ctxt->argl[an] = NULL;
+			if (!args) {
+				crit(LOGOPT_ANY,
+				     MODPREFIX "error assigning map args");
+				goto error_out;
+			}
+			ctxt->m[i].argv = copy_argv(ctxt->m[i].argc, (const char **) args);
+			if (!ctxt->m[i].argv)
+				goto nomem;
+			args = NULL;
 			i++;
 		} else {
 			ctxt->m[i].argc++;
 		}
 	}
 
-	for (i = 0; i < ctxt->n; i++) {
-		if (!ctxt->m[i].argv[0]) {
-			crit(LOGOPT_ANY, MODPREFIX "missing module name");
-			goto error_out;
-		}
-		map = strdup(ctxt->m[i].argv[0]);
-		if (!map)
+	/* catch the last one */
+	if (args) {
+		ctxt->m[i].argv = copy_argv(ctxt->m[i].argc, (const char **) args);
+		if (!ctxt->m[i].argv)
 			goto nomem;
+	}
 
-		if ((mapfmt = strchr(map, ',')))
-			*(mapfmt++) = '\0';
-
-		if (!(ctxt->m[i].mod = open_lookup(map, MODPREFIX,
-						   mapfmt ? mapfmt : my_mapfmt,
-						   ctxt->m[i].argc - 1,
-						   ctxt->m[i].argv + 1))) {
+	for (i = 0; i < ctxt->n; i++) {
+		ctxt->m[i].mod = nss_open_lookup(my_mapfmt,
+				 ctxt->m[i].argc, ctxt->m[i].argv);
+		if (!ctxt->m[i].mod) {
 			error(LOGOPT_ANY, MODPREFIX "error opening module");
-			free(map);
 			goto error_out;
 		}
-		free(map);
 	}
 
 	*context = ctxt;
@@ -116,9 +214,12 @@ nomem:
 	crit(LOGOPT_ANY, MODPREFIX "error: %s", estr);
 error_out:
 	if (ctxt) {
-		for (i = 0; i < ctxt->n; i++)
+		for (i = 0; i < ctxt->n; i++) {
 			if (ctxt->m[i].mod)
 				close_lookup(ctxt->m[i].mod);
+			if (ctxt->m[i].argv)
+				free_argv(ctxt->m[i].argc, ctxt->m[i].argv);
+		}
 		if (ctxt->m)
 			free(ctxt->m);
 		if (ctxt->argl)
@@ -188,6 +289,8 @@ int lookup_done(void *context)
 	for (i = 0; i < ctxt->n; i++) {
 		if (ctxt->m[i].mod)
 			rv = rv || close_lookup(ctxt->m[i].mod);
+		if (ctxt->m[i].argv)
+			free_argv(ctxt->m[i].argc, ctxt->m[i].argv);
 	}
 	free(ctxt->argl);
 	free(ctxt->m);
diff --git a/CHANGELOG b/CHANGELOG
index d66b8fc..8df22ae 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,8 @@
 - correct initialization of local var in parse_server_string.
 - add missing "multi" map support.
 - add multi nsswitch lookup.
+- change random multiple server selection option name to be consistent
+  with existing downstream version 4 naming.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 3e40428..294c511 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1367,7 +1367,7 @@ static void usage(void)
 		"	-d --debug	log debuging info\n"
 		"	-D --define	define global macro variable\n"
 		/*"	-f --foreground do not fork into background\n" */
-		"	-r --random-replicated-selection\n"
+		"	-r --random-multimount-selection\n"
 		"			use ramdom replicated server selection\n"
 		"	-O --global-options\n"
 		"			specify global mount options\n"
@@ -1469,7 +1469,7 @@ int main(int argc, char *argv[])
 		{"debug", 0, 0, 'd'},
 		{"define", 1, 0, 'D'},
 		{"foreground", 0, 0, 'f'},
-		{"random-selection", 0, 0, 'r'},
+		{"random-multimount-selection", 0, 0, 'r'},
 		{"global-options", 1, 0, 'O'},
 		{"version", 0, 0, 'V'},
 		{0, 0, 0, 0}
diff --git a/man/automount.8 b/man/automount.8
index b01be83..fc1846a 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -47,7 +47,7 @@ Define a global macro substitution variable. Global definitions
 are over-ridden macro definitions of the same name specified in
 mount entries.
 .TP
-.I "\-r, \-\-random-replicated-selection"
+.I "\-r, \-\-random-multimount-selection"
 Enables the use of ramdom selection when choosing a host from a
 list of replicated servers.
 .TP
diff --git a/CHANGELOG b/CHANGELOG
index 8df22ae..2ce58b4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,7 @@
 - add multi nsswitch lookup.
 - change random multiple server selection option name to be consistent
   with existing downstream version 4 naming.
+- fix mount point directory creation for bind mounts.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 294c511..9809b9c 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -104,11 +104,14 @@ static int do_mkdir(const char *parent, const char *path, mode_t mode)
 		status = statfs(parent, &fs);
 	if ((status != -1 && fs.f_type == (__SWORD_TYPE) AUTOFS_SUPER_MAGIC) ||
 	    contained_in_local_fs(path)) {
-		if (mkdir(path, mode) == -1)
+		if (mkdir(path, mode) == -1) {
+			errno = EACCES;
 			return 0;
+		}
 		return 1;
 	}
 
+	errno = EACCES;
 	return 0;
 }
 
diff --git a/daemon/direct.c b/daemon/direct.c
index 179e74b..9a39a6f 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -604,6 +604,14 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 		}
 		ioctlfd = me->ioctlfd;
 	} else {
+		/* offset isn't mounted, return success and try to recover */
+		if (!is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
+			debug(ap->logopt,
+			      "offset %s unexpectedly not mounted",
+			      me->key);
+			return 0;
+		}
+
 		ioctlfd = open(me->key, O_RDONLY);
 		if (ioctlfd != -1) {
 			if ((cl_flags = fcntl(ioctlfd, F_GETFD, 0)) != -1) {
@@ -689,11 +697,19 @@ force_umount:
 	} else
 		msg("umounted offset mount %s", me->key);
 
+	if (!rv && me->dir_created) {
+		if  (rmdir(me->key) == -1) {
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			warn(ap->logopt, "failed to remove dir %s: %s",
+			     me->key, estr);
+		}
+	}
 	return rv;
 }
 
-int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, int is_autofs_fs)
+int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 {
+	char buf[MAX_ERR_BUF];
 	struct mnt_params *mp;
 	time_t timeout = ap->exp_timeout;
 	struct stat st;
@@ -740,36 +756,38 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, int is_autof
 			return 0;
 	}
 
-	if (is_autofs_fs) {
-		/* In case the directory doesn't exist, try to mkdir it */
-		if (mkdir_path(me->key, 0555) < 0) {
-			if (errno != EEXIST) {
-				crit(ap->logopt,
-				     "failed to create mount directory %s %d",
-				     me->key, errno);
-				return -1;
-			}
+	/* In case the directory doesn't exist, try to mkdir it */
+	if (mkdir_path(me->key, 0555) < 0) {
+		if (errno == EEXIST) {
 			/* 
 			 * If we recieve an error, and it's EEXIST
 			 * we know the directory was not created.
 			 */
 			me->dir_created = 0;
+		} else if (errno == EACCES) {
+			/*
+			 * We require the mount point directory to exist when
+			 * installing multi-mount triggers into a host
+			 * filesystem.
+			 *
+			 * If it doesn't exist it is not a valid part of the
+			 * mount heirachy.
+			 */
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			debug(ap->logopt,
+			     "can't create mount directory: %s, %s",
+			     me->key, estr);
+			return -1;
 		} else {
-			/* No errors so the directory was successfully created */
-			me->dir_created = 1;
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+			crit(ap->logopt,
+			     "failed to create mount directory: %s, %s",
+			     me->key, estr);
+			return -1;
 		}
 	} else {
-		me->dir_created = 0;
-
-		/*
-		 * We require the mount point directory to exist when
-		 * installing multi-mount triggers into a host filesystem.
-		 *
-		 * If it doesn't exist it is not a valid part of the
-		 * mount heirachy so we silently succeed here.
-		 */
-		if (stat(me->key, &st) == -1 && errno == ENOENT)
-			return 0;
+		/* No errors so the directory was successfully created */
+		me->dir_created = 1;
 	}
 
 	debug(ap->logopt,
@@ -832,10 +850,8 @@ out_close:
 out_umount:
 	umount(me->key);
 out_err:
-	if (is_autofs_fs) {
-		if (stat(me->key, &st) == 0 && me->dir_created)
-			 rmdir_path(ap, me->key, st.st_dev);
-	}
+	if (stat(me->key, &st) == 0 && me->dir_created)
+		 rmdir_path(ap, me->key, st.st_dev);
 
 	return -1;
 }
diff --git a/include/automount.h b/include/automount.h
index 106ed0a..d9e4ecd 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -470,7 +470,7 @@ void *expire_proc_direct(void *);
 int expire_offsets_direct(struct autofs_point *ap, struct mapent *me, int now);
 int mount_autofs_indirect(struct autofs_point *ap);
 int mount_autofs_direct(struct autofs_point *ap);
-int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, int is_autofs_fs);
+int mount_autofs_offset(struct autofs_point *ap, struct mapent *me);
 void submount_signal_parent(struct autofs_point *ap, unsigned int success);
 int umount_autofs(struct autofs_point *ap, int force);
 int umount_autofs_indirect(struct autofs_point *ap);
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index 0c45905..ad19f34 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -388,10 +388,8 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me,
 	struct mapent *oe;
 	struct list_head *pos = NULL;
 	unsigned int fs_path_len;
-	struct statfs fs;
-	struct stat st;
-	unsigned int mounted, is_autofs_fs;
-	int ret, start;
+	unsigned int mounted;
+	int start;
 
 	fs_path_len = strlen(root) + strlen(base);
 	if (fs_path_len > PATH_MAX)
@@ -399,15 +397,6 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me,
 
 	strcpy(path, root);
 	strcat(path, base);
-	ret = statfs(path, &fs);
-	if (ret == -1) {
-		/* There's no mount yet - it must be autofs */
-		if (errno == ENOENT)
-			is_autofs_fs = 1;
-		else
-			return -1;
-	} else
-		is_autofs_fs = fs.f_type == (__SWORD_TYPE) AUTOFS_SUPER_MAGIC ? 1 : 0;
 
 	mounted = 0;
 	start = strlen(root);
@@ -424,20 +413,9 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me,
 		if (!oe)
 			goto cont;
 
-		/*
-		 * If the host filesystem is not an autofs fs
-		 * we require the mount point directory exist
-		 * and that permissions are OK.
-		 */
-		if (!is_autofs_fs) {
-			ret = stat(oe->key, &st);
-			if (ret == -1)
-				goto cont;
-		}
-
 		debug(ap->logopt, "mount offset %s", oe->key);
 
-		if (mount_autofs_offset(ap, oe, is_autofs_fs) < 0)
+		if (mount_autofs_offset(ap, oe) < 0)
 			warn(ap->logopt, "failed to mount offset");
 		else
 			mounted++;
diff --git a/CHANGELOG b/CHANGELOG
index 2ce58b4..903e619 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@
 - change random multiple server selection option name to be consistent
   with existing downstream version 4 naming.
 - fix mount point directory creation for bind mounts.
+- add quoting for exports gathered by hosts map.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index a9a4c75..1f8fa15 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -215,7 +215,7 @@ done:
 		if (mapent) {
 			int len = strlen(mapent) + 1;
 
-			len += strlen(name) + 2*strlen(exp->ex_dir) + 3;
+			len += strlen(name) + 2*(strlen(exp->ex_dir) + 2) + 3;
 			mapent = realloc(mapent, len);
 			if (!mapent) {
 				char *estr;
@@ -224,10 +224,11 @@ done:
 				rpc_exports_free(exp);
 				return NSS_STATUS_UNAVAIL;
 			}
-			strcat(mapent, " ");
+			strcat(mapent, " \"");
 			strcat(mapent, exp->ex_dir);
+			strcat(mapent, "\"");
 		} else {
-			int len = 2*strlen(exp->ex_dir) + strlen(name) + 3;
+			int len = 2*(strlen(exp->ex_dir) + 2) + strlen(name) + 3;
 
 			mapent = malloc(len);
 			if (!mapent) {
@@ -237,12 +238,15 @@ done:
 				rpc_exports_free(exp);
 				return NSS_STATUS_UNAVAIL;
 			}
-			strcpy(mapent, exp->ex_dir);
+			strcpy(mapent, "\"");
+			strcat(mapent, exp->ex_dir);
+			strcat(mapent, "\"");
 		}
-		strcat(mapent, " ");
+		strcat(mapent, " \"");
 		strcat(mapent, name);
 		strcat(mapent, ":");
 		strcat(mapent, exp->ex_dir);
+		strcat(mapent, "\"");
 
 		exp = exp->ex_next;
 	}
@@ -260,13 +264,9 @@ done:
 	cache_update(mc, source, name, mapent, now);
 	cache_unlock(mc);
 
-	debug(LOGOPT_ANY, "source wait");
-
 	master_source_current_wait(ap->entry);
 	ap->entry->current = source;
 
-	debug(LOGOPT_ANY, "do parse_mount");
-
 	ret = ctxt->parse->parse_mount(ap, name, name_len,
 				 mapent, ctxt->parse->context);
 	free(mapent);
diff --git a/CHANGELOG b/CHANGELOG
index 903e619..bc4d8fd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,7 @@
   with existing downstream version 4 naming.
 - fix mount point directory creation for bind mounts.
 - add quoting for exports gathered by hosts map.
+- fix wait time resolution in alarm and state queue handlers.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/state.c b/daemon/state.c
index 6c373c8..39f4497 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -894,6 +894,7 @@ static void *st_queue_handler(void *arg)
 	struct list_head *head;
 	struct list_head *p;
 	struct timespec wait;
+	struct timeval now;
 	int status, ret;
 
 	st_mutex_lock();
@@ -904,8 +905,9 @@ static void *st_queue_handler(void *arg)
 		 * entry is added.
 		 */
 		head = &state_queue;
-		wait.tv_sec = time(NULL) + 1;
-		wait.tv_nsec = 0;
+		gettimeofday(&now, NULL);
+		wait.tv_sec = now.tv_sec + 1;
+		wait.tv_nsec = now.tv_usec * 1000;
 
 		while (list_empty(head)) {
 			status = pthread_cond_timedwait(&cond, &mutex, &wait);
@@ -939,8 +941,9 @@ static void *st_queue_handler(void *arg)
 		}
 
 		while (1) {
-			wait.tv_sec = time(NULL) + 1;
-			wait.tv_nsec = 0;
+			gettimeofday(&now, NULL);
+			wait.tv_sec = now.tv_sec + 1;
+			wait.tv_nsec = now.tv_usec * 1000;
 
 			signaled = 0;
 			while (!signaled) {
diff --git a/lib/alarm.c b/lib/alarm.c
index c6c4ba3..90bf7aa 100755
--- a/lib/alarm.c
+++ b/lib/alarm.c
@@ -192,12 +192,14 @@ static void *alarm_handler(void *arg)
 		now = time(NULL);
 
 		if (first->time > now) {
+			struct timeval usecs;
 			/* 
 			 * Wait for alarm to trigger or a new alarm 
 			 * to be added.
 			 */
+			gettimeofday(&usecs, NULL);
 			expire.tv_sec = first->time;
-			expire.tv_nsec = 0;
+			expire.tv_nsec = usecs.tv_usec * 1000;
 
 			status = pthread_cond_timedwait(&cond, &mutex, &expire);
 			if (status && status != ETIMEDOUT)
diff --git a/CHANGELOG b/CHANGELOG
index bc4d8fd..1bf4b27 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,7 @@
 - fix mount point directory creation for bind mounts.
 - add quoting for exports gathered by hosts map.
 - fix wait time resolution in alarm and state queue handlers.
+- fix handling of quoted slash alone.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index ad19f34..3627f44 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -297,7 +297,8 @@ char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned i
 		return NULL;
 	}
 
-	if (origlen > 1 && *(cp - 1) == '/')
+	/* Remove trailing / but watch out for a quoted / alone */
+	if (strlen(cp) > 1 && origlen > 1 && *(cp - 1) == '/')
 		*(cp - 1) = '\0';
 
 	return s_path;
diff --git a/CHANGELOG b/CHANGELOG
index 1bf4b27..678e764 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@
 - add quoting for exports gathered by hosts map.
 - fix wait time resolution in alarm and state queue handlers.
 - fix handling of quoted slash alone.
+- fix parse confusion between attribute and attribute value.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 9bfeefa..ff69a24 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -272,7 +272,7 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 		return DNSERVER;
 	}
 
-	{DNATTRSTR} {
+	{DNATTRSTR}/"=" {
 		strcpy(master_lval.strtype, master_text);
 		return DNATTR;
 	}
diff --git a/CHANGELOG b/CHANGELOG
index 678e764..aa5d1c1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,7 @@
 - fix wait time resolution in alarm and state queue handlers.
 - fix handling of quoted slash alone.
 - fix parse confusion between attribute and attribute value.
+- fix version passed to get_supported_ver_and_cost.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/replicated.c b/modules/replicated.c
index de1b40c..0764d4a 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -607,12 +607,31 @@ static int get_supported_ver_and_cost(struct host *host, unsigned int version, c
 
 	parms.pm_prog = NFS_PROGRAM;
 
+	/*
+	 *  The version passed in is the version as defined in
+	 *  include/replicated.h.  However, the version we want to send
+	 *  off to the rpc calls should match the program version of NFS.
+	 *  So, we do the conversion here.
+	 */
 	if (version & UDP_SELECTED_MASK) {
 		proto = "udp";
-		vers = (version << 8);
-	} else {
+		version >>= 8;
+	} else
 		proto = "tcp";
-		vers = version;
+
+	switch (version) {
+	case NFS2_SUPPORTED:
+		vers = NFS2_VERSION;
+		break;
+	case NFS3_SUPPORTED:
+		vers = NFS3_VERSION;
+		break;
+	case NFS4_SUPPORTED:
+		vers = NFS4_VERSION;
+		break;
+	default:
+		crit(LOGOPT_ANY, "called with invalid version: 0x%x\n", version);
+		return 0;
 	}
 
 	rpc_info.proto = getprotobyname(proto);
diff --git a/CHANGELOG b/CHANGELOG
index aa5d1c1..98d082c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -12,6 +12,7 @@
 - fix handling of quoted slash alone.
 - fix parse confusion between attribute and attribute value.
 - fix version passed to get_supported_ver_and_cost.
+- mark map instances stale so they aren't "cleaned" during updates.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 70b9e02..4f2b318 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -325,6 +325,7 @@ static int read_file_source_instance(struct autofs_point *ap, struct map_source
 		instance->recurse = map->recurse;
 		instance->depth = map->depth;
 	}
+	instance->stale = map->stale;
 
 	return do_read_map(ap, instance, age);
 }
@@ -346,6 +347,7 @@ static int read_source_instance(struct autofs_point *ap, struct map_source *map,
 		instance->recurse = map->recurse;
 		instance->depth = map->depth;
 	}
+	instance->stale = map->stale;
 
 	return do_read_map(ap, instance, age);
 }
diff --git a/CHANGELOG b/CHANGELOG
index 98d082c..20562bd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,6 +13,7 @@
 - fix parse confusion between attribute and attribute value.
 - fix version passed to get_supported_ver_and_cost.
 - mark map instances stale so they aren't "cleaned" during updates.
+- fix large file compile time option.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/Makefile.rules b/Makefile.rules
index b1d1a49..30716dc 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -44,7 +44,7 @@ CXXFLAGS  = $(CFLAGS)
 LD        = ld
 SOLDFLAGS = -shared
 
-CFLAGS += -D_REENTRANT
+CFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64
 LDFLAGS += -lpthread
 
 ifdef DMALLOCLIB
diff --git a/CHANGELOG b/CHANGELOG
index 20562bd..da8c599 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,7 @@
 - fix version passed to get_supported_ver_and_cost.
 - mark map instances stale so they aren't "cleaned" during updates.
 - fix large file compile time option.
+- don't fail on empty master map.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/lib/master.c b/lib/master.c
index 4d31959..9f24f7e 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -803,7 +803,7 @@ int master_read_master(struct master *master, time_t age, int readall)
 	if (list_empty(&master->mounts)) {
 		master_mutex_unlock();
 		error(LOGOPT_ANY, "no mounts in table");
-		return 0;
+		return 1;
 	}
 
 	master_mutex_unlock();
diff --git a/CHANGELOG b/CHANGELOG
index da8c599..c6ab15f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,7 @@
 - mark map instances stale so they aren't "cleaned" during updates.
 - fix large file compile time option.
 - don't fail on empty master map.
+- add support for the "%" hack for case insensitive attribute schemas.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index de8d515..a412797 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1210,50 +1210,68 @@ static int read_one_map(struct autofs_point *ap,
 		}
 
 		/*
-		 * By definition keys must be unique within
-		 * each map entry
+		 * By definition keys should be unique within each map entry,
+		 * but as always there are exceptions.
 		 */
 		k_val = NULL;
 		k_len = 0;
 
 		/*
-		 * Keys must be unique so, in general, there shouldn't be
+		 * Keys should be unique so, in general, there shouldn't be
 		 * more than one attribute value. We make an exception for
 		 * wildcard entries as people may have values for '*' or
 		 * '/' for compaibility reasons. We use the '/' as the
 		 * wildcard in LDAP but allow '*' as well to allow for
 		 * people using older schemas that allow '*' as a key
-		 * value.
+		 * value. Another case where there can be multiple key
+		 * values is when people have used the "%" hack to specify
+		 * case matching ctriteria in a caase insensitive attribute.
 		 */
 		count = ldap_count_values_len(bvKey);
-		if (count > 2) {
-			error(ap->logopt,
-			      MODPREFIX
-			      "key %.*s has duplicate entries - ignoring",
-			      bvKey[0]->bv_len, bvKey[0]->bv_val);
-			goto next;
-		} else if (count == 2) {
+		if (count > 1) {
 			unsigned int i;
 
 			/* Check for the "/" and "*" and use as "/" if found */
 			for (i = 0; i < count; i++) {
-				/* check for wildcard */
-				if (bvKey[i]->bv_len != 1)
+				bvKey[i]->bv_val[bvKey[i]->bv_len] = '\0';
+
+				/*
+				 * If multiple entries are present they could
+				 * be the result of people using the "%" hack so
+				 * ignore them.
+				 */
+				if (strchr(bvKey[i]->bv_val, '%'))
 					continue;
-				if (*bvKey[i]->bv_val != '/' &&
-				    *bvKey[i]->bv_val != '*')
-					continue;
-				/* always use '/' internally */
-				*bvKey[i]->bv_val = '/';
+
+				/* check for wildcard */
+				if (bvKey[i]->bv_len == 1 &&
+				    (*bvKey[i]->bv_val == '/' ||
+				     *bvKey[i]->bv_val == '*')) {
+					/* always use '/' internally */
+					*bvKey[i]->bv_val = '/';
+					k_val = bvKey[i]->bv_val;
+					k_len = 1;
+					break;
+				}
+
+				/*
+				 * We have a result from LDAP so this is a
+				 * valid entry. Set the result to the LDAP
+				 * key that isn't a wildcard and doesn't have
+				 * any "%" hack values present. This should be
+				 * the case insensitive match string for the
+				 * nis schema, the default value.
+				 */
 				k_val = bvKey[i]->bv_val;
-				k_len = 1;
+				k_len = bvKey[i]->bv_len;
+
 				break;
 			}
 
 			if (!k_val) {
 				error(ap->logopt,
 				      MODPREFIX
-				      "key %.*s has duplicate entries - ignoring",
+				      "invalid entry %.*s - ignoring",
 				      bvKey[0]->bv_len, bvKey[0]->bv_val);
 				goto next;
 			}
@@ -1495,7 +1513,10 @@ static int lookup_one(struct autofs_point *ap,
 			continue;
 		}
 
-		/* By definition keys must be unique within each map entry */
+		/*
+		 * By definition keys should be unique within each map entry,
+		 * but as always there are exceptions.
+		 */
 		k_val = NULL;
 		k_len = 0;
 
@@ -1506,37 +1527,53 @@ static int lookup_one(struct autofs_point *ap,
 		 * '/' for compaibility reasons. We use the '/' as the
 		 * wildcard in LDAP but allow '*' as well to allow for
 		 * people using older schemas that allow '*' as a key
-		 * value.
+		 * value. Another case where there can be multiple key
+		 * values is when people have used the "%" hack to specify
+		 * case matching ctriteria in a caase insensitive attribute.
 		 */
 		count = ldap_count_values_len(bvKey);
-		if (count > 2) {
-			error(ap->logopt,
-			      MODPREFIX
-			      "key %.*s has duplicate entries - ignoring",
-			      bvKey[0]->bv_len, bvKey[0]->bv_val);
-			goto next;
-		} else if (count == 2) {
+		if (count > 1) {
 			unsigned int i;
 
 			/* Check for the "/" and "*" and use as "/" if found */
 			for (i = 0; i < count; i++) {
-				/* check for wildcard */
-				if (bvKey[i]->bv_len != 1)
-					continue;
-				if (*bvKey[i]->bv_val != '/' &&
-				    *bvKey[i]->bv_val != '*')
+				bvKey[i]->bv_val[bvKey[i]->bv_len] = '\0';
+
+				/*
+				 * If multiple entries are present they could
+				 * be the result of people using the "%" hack so
+				 * ignore them.
+				 */
+				if (strchr(bvKey[i]->bv_val, '%'))
 					continue;
-				/* always use '/' internally */
-				*bvKey[i]->bv_val = '/';
-				k_val = bvKey[i]->bv_val;
-				k_len = 1;
+
+				/* check for wildcard */
+				if (bvKey[i]->bv_len == 1 &&
+				    (*bvKey[i]->bv_val == '/' ||
+				     *bvKey[i]->bv_val == '*')) {
+					/* always use '/' internally */
+					*bvKey[i]->bv_val = '/';
+					k_val = bvKey[i]->bv_val;
+					k_len = 1;
+					break;
+				}
+
+				/*
+				 * The key was matched by LDAP so this is a
+				 * valid entry. Set the result key to the
+				 * lookup key to provide the mixed case
+				 * matching provided by the "%" hack.
+				 */
+				k_val = qKey;
+				k_len = strlen(qKey);
+
 				break;
 			}
 
 			if (!k_val) {
 				error(ap->logopt,
-					MODPREFIX "key %.*s has duplicate entries",
-					bvKey[0]->bv_len, bvKey[0]->bv_val);
+					MODPREFIX "no valid key found for %.*s",
+					qKey_len, qKey);
 				ret = CHE_FAIL;
 				goto next;
 			}
diff --git a/CHANGELOG b/CHANGELOG
index c6ab15f..5aee44c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -16,6 +16,7 @@
 - fix large file compile time option.
 - don't fail on empty master map.
 - add support for the "%" hack for case insensitive attribute schemas.
+- fix "nosymlink" option handling and add desription to man page.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 98afaa9..69c796e 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -138,6 +138,14 @@ Treat errors when mounting file systems as fatal. This is important when
 multiple file systems should be mounted (`multimounts'). If this option
 is given, no file system is mounted at all if at least one file system
 can't be mounted.
+.TP
+.I "nosymlink"
+This is an autofs specific option that is a pseudo mount option and
+so is given without a leading dash. Historically this option was used
+to prevent symlinking of local NFS mounts. Nowadays it can be used to
+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.
 .SH GENERAL SYSTEM DEFAULTS CONFIGURATION
 .P
 The default value of several general settings may be changed in the
diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index 25f72b9..e7a9a8a 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -214,7 +214,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 			port_opt = strstr(nfsoptions, "port=");
 
 		/* Port option specified, don't try to bind */
-		if (!port_opt && this->proximity == PROXIMITY_LOCAL) {
+		if (!nosymlink && !port_opt && this->proximity == PROXIMITY_LOCAL) {
 			/* Local host -- do a "bind" */
 			const char *bind_options = ro ? "ro" : "";
 
diff --git a/CHANGELOG b/CHANGELOG
index 5aee44c..9c99966 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,7 @@
 - don't fail on empty master map.
 - add support for the "%" hack for case insensitive attribute schemas.
 - fix "nosymlink" option handling and add desription to man page.
+- fix don't fail on empty master map.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 9809b9c..7b79f02 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -61,6 +61,8 @@ static size_t kpkt_len;
 
 /* Attribute to create detached thread */
 pthread_attr_t thread_attr;
+/* Attribute to create normal thread */
+pthread_attr_t thread_attr_nodetach;
 
 struct master_readmap_cond mrc = {
 	PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
@@ -914,7 +916,7 @@ static void *do_notify_state(void *arg)
 	return NULL;
 }
 
-static int do_signals(struct master *master, int sig)
+static pthread_t do_signals(struct master *master, int sig)
 {
 	pthread_t thid;
 	int r_sig = sig;
@@ -924,7 +926,7 @@ static int do_signals(struct master *master, int sig)
 	if (status)
 		fatal(status);
 
-	status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig);
+	status = pthread_create(&thid, &thread_attr_nodetach, do_notify_state, &r_sig);
 	if (status) {
 		error(master->default_logging,
 		      "mount state notify thread create failed");
@@ -948,7 +950,7 @@ static int do_signals(struct master *master, int sig)
 
 	pthread_cleanup_pop(1);
 
-	return 1;
+	return thid;
 }
 
 static void *do_read_master(void *arg)
@@ -1038,6 +1040,7 @@ static int do_hup_signal(struct master *master, time_t age)
 /* Deal with all the signal-driven events in the state machine */
 static void *statemachine(void *arg)
 {
+	pthread_t thid = 0;
 	sigset_t signalset;
 	int sig;
 
@@ -1048,15 +1051,17 @@ static void *statemachine(void *arg)
 	while (1) {
 		sigwait(&signalset, &sig);
 
-
-		if (master_list_empty(master_list))
-			return NULL;
-
 		switch (sig) {
 		case SIGTERM:
 		case SIGUSR2:
 		case SIGUSR1:
-			do_signals(master_list, sig);
+			thid = do_signals(master_list, sig);
+			if (thid) {
+				pthread_join(thid, NULL);
+				if (master_list_empty(master_list))
+					return NULL;
+				thid = 0;
+			}
 			break;
 
 		case SIGHUP:
@@ -1171,10 +1176,6 @@ static void handle_mounts_cleanup(void *arg)
 
 	msg("shut down path %s", path);
 
-	/* If we are the last tell the state machine to shutdown */
-	if (!submount && master_list_empty(master_list))
-		kill(getpid(), SIGTERM);
-
 	return;
 }
 
@@ -1644,6 +1645,14 @@ int main(int argc, char *argv[])
 	}
 #endif
 
+	if (pthread_attr_init(&thread_attr_nodetach)) {
+		crit(LOGOPT_ANY,
+		     "%s: failed to init thread attribute struct!",
+		     program);
+		close(start_pipefd[1]);
+		exit(1);
+	}
+
 	msg("Starting automounter version %s, master map %s",
 		version, master_list->name);
 	msg("using kernel protocol version %d.%02d",
diff --git a/lib/master.c b/lib/master.c
index 9f24f7e..da05bb6 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -802,7 +802,7 @@ int master_read_master(struct master *master, time_t age, int readall)
 
 	if (list_empty(&master->mounts)) {
 		master_mutex_unlock();
-		error(LOGOPT_ANY, "no mounts in table");
+		warn(LOGOPT_ANY, "no mounts in table");
 		return 1;
 	}
 
diff --git a/CHANGELOG b/CHANGELOG
index 9c99966..92013ce 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -18,6 +18,7 @@
 - add support for the "%" hack for case insensitive attribute schemas.
 - fix "nosymlink" option handling and add desription to man page.
 - fix don't fail on empty master map.
+- if there's no "automount" entry in nsswitch.conf use "files" source.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/lib/nss_parse.y b/lib/nss_parse.y
index 4f67f08..e559696 100644
--- a/lib/nss_parse.y
+++ b/lib/nss_parse.y
@@ -45,6 +45,8 @@ struct nss_action act[NSS_STATUS_MAX];
 #define YYLTYPE_IS_TRIVIAL 0
 #endif
 
+unsigned int nss_automount_found;
+
 extern int nss_lineno;
 extern int nss_lex(void);
 extern FILE *nss_in;
@@ -183,10 +185,16 @@ int nsswitch_parse(struct list_head *list)
 
 	nss_in = nsswitch;
 
+	nss_automount_found = 0;
 	nss_list = list;
 	status = nss_parse();
 	nss_list = NULL;
 
+	/* No "automount" nsswitch entry, use "files" */
+	if (!nss_automount_found)
+		if (add_source(list, "files"))
+			status = 0;
+
 	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
 
diff --git a/lib/nss_tok.l b/lib/nss_tok.l
index 71d83b0..f96b47f 100644
--- a/lib/nss_tok.l
+++ b/lib/nss_tok.l
@@ -56,6 +56,8 @@ int nss_wrap(void);
 #define YY_MAIN 0
 #endif
 
+extern unsigned int nss_automount_found;
+
 %}
 
 %option nounput
@@ -85,6 +87,7 @@ other		[[:alnum:]@$%^&*()-+_":;?,<>./'{}~`]+
 %%
 
 ^{automount}: {
+	nss_automount_found = 1;
 	BEGIN(AUTOMOUNT);
 }
 
diff --git a/CHANGELOG b/CHANGELOG
index 92013ce..c36017a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -19,6 +19,7 @@
 - fix "nosymlink" option handling and add desription to man page.
 - fix don't fail on empty master map.
 - if there's no "automount" entry in nsswitch.conf use "files" source.
+- add LDAP schema discovery if no schema is configured.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/include/defaults.h b/include/defaults.h
index ef58467..9aec11a 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -43,11 +43,8 @@ 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);
-const char *defaults_get_map_obj_class(void);
-const char *defaults_get_entry_obj_class(void);
-const char *defaults_get_map_attr(void);
-const char *defaults_get_entry_attr(void);
-const char *defaults_get_value_attr(void);
+struct ldap_schema *defaults_get_default_schema(void);
+struct ldap_schema *defaults_get_schema(void);
 unsigned int defaults_get_append_options(void);
 const char *defaults_get_auth_conf_file(void);
 
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index 0a9deca..1378b9e 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -10,6 +10,14 @@
 #include <krb5.h>
 #endif
 
+struct ldap_schema {
+	char *map_class;
+	char *map_attr;
+	char *entry_class;
+	char *entry_attr;
+	char *value_attr;
+};
+
 struct lookup_context {
 	char *mapname;
 
@@ -22,11 +30,7 @@ struct lookup_context {
 	int version;
 
 	/* LDAP lookup configuration */
-	char *map_obj_class;
-	char *entry_obj_class;
-	char *map_attr;
-	char *entry_attr;
-	char *value_attr;
+	struct ldap_schema *schema;
 
 	/* TLS and SASL authentication information */
 	char        *auth_conf;
diff --git a/lib/defaults.c b/lib/defaults.c
index 4b4acba..b146f13 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -18,6 +18,7 @@
 #include <string.h>
 
 #include "defaults.h"
+#include "lookup_ldap.h"
 #include "log.h"
 
 #define DEFAULTS_CONFIG_FILE		AUTOFS_CONF_DIR "/autofs"
@@ -41,16 +42,8 @@
 #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_map_obj_class	= DEFAULT_MAP_OBJ_CLASS;
-static const char *default_entry_obj_class	= DEFAULT_ENTRY_OBJ_CLASS;
-static const char *default_map_attr		= DEFAULT_MAP_ATTR;
-static const char *default_entry_attr		= DEFAULT_ENTRY_ATTR;
-static const char *default_value_attr		= DEFAULT_VALUE_ATTR;
-
-static const char *default_auth_conf_file = DEFAULT_AUTH_CONF_FILE;
+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)
 {
@@ -285,59 +278,120 @@ const char *defaults_get_ldap_server(void)
 	return (const char *) server;
 }
 
-const char *defaults_get_map_obj_class(void)
+struct ldap_schema *defaults_get_default_schema(void)
 {
-	char *moc;
+	struct ldap_schema *schema;
+	char *mc, *ma, *ec, *ea, *va;
 
-	moc = get_env_string(ENV_NAME_MAP_OBJ_CLASS);
-	if (!moc)
-		return strdup(default_map_obj_class);
+	mc = strdup(DEFAULT_MAP_OBJ_CLASS);
+	if (!mc)
+		return NULL;
 
-	return (const char *) moc;
-}
+	ma = strdup(DEFAULT_MAP_ATTR);
+	if (!ma) {
+		free(mc);
+		return NULL;
+	}
 
-const char *defaults_get_entry_obj_class(void)
-{
-	char *eoc;
+	ec = strdup(DEFAULT_ENTRY_OBJ_CLASS);
+	if (!ec) {
+		free(mc);
+		free(ma);
+		return NULL;
+	}
 
-	eoc = get_env_string(ENV_NAME_ENTRY_OBJ_CLASS);
-	if (!eoc)
-		return strdup(default_entry_obj_class);
+	ea = strdup(DEFAULT_ENTRY_ATTR);
+	if (!ea) {
+		free(mc);
+		free(ma);
+		free(ec);
+		return NULL;
+	}
 
-	return (const char *) eoc;
-}
+	va = strdup(DEFAULT_VALUE_ATTR);
+	if (!va) {
+		free(mc);
+		free(ma);
+		free(ec);
+		free(ea);
+		return NULL;
+	}
 
-const char *defaults_get_map_attr(void)
-{
-	char *ma;
+	schema = malloc(sizeof(struct ldap_schema));
+	if (!schema) {
+		free(mc);
+		free(ma);
+		free(ec);
+		free(ea);
+		free(va);
+		return NULL;
+	}
 
-	ma = get_env_string(ENV_NAME_MAP_ATTR);
-	if (!ma)
-		return strdup(default_map_attr);
+	schema->map_class = mc;
+	schema->map_attr = ma;
+	schema->entry_class = ec;
+	schema->entry_attr = ea;
+	schema->value_attr = va;
 
-	return (const char *) ma;
+	return schema;
 }
 
-const char *defaults_get_entry_attr(void)
+struct ldap_schema *defaults_get_schema(void)
 {
-	char *ea;
+	struct ldap_schema *schema;
+	char *mc, *ma, *ec, *ea, *va;
 
-	ea = get_env_string(ENV_NAME_ENTRY_ATTR);
-	if (!ea)
-		return strdup(default_entry_attr);
+	mc = get_env_string(ENV_NAME_MAP_OBJ_CLASS);
+	if (!mc)
+		return NULL;
 
-	return (const char *) ea;
-}
+	ma = get_env_string(ENV_NAME_MAP_ATTR);
+	if (!ma) {
+		free(mc);
+		return NULL;
+	}
 
-const char *defaults_get_value_attr(void)
-{
-	char *va;
+	ec = get_env_string(ENV_NAME_ENTRY_OBJ_CLASS);
+	if (!ec) {
+		free(mc);
+		free(ma);
+		return NULL;
+	}
+
+	ea = get_env_string(ENV_NAME_ENTRY_ATTR);
+	if (!ea) {
+		free(mc);
+		free(ma);
+		free(ec);
+		return NULL;
+	}
 
 	va = get_env_string(ENV_NAME_VALUE_ATTR);
-	if (!va)
-		return strdup(default_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 (const char *) va;
+	return schema;
 }
 
 unsigned int defaults_get_append_options(void)
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 69c796e..249c9a7 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -191,17 +191,25 @@ The old style
 is also understood. Alternatively, the type can be obtained from the Name Service Switch
 configuration, in which case the map name alone must be given.
 .P
-The default LDAP schema is the NIS schema described in RFC 2307.
-Entries in the nisMap schema are \fBnisObject\fP objects in
+If no schema is set in the autofs configuration then autofs will check
+each of the commonly used schema for a valid entry and if one is found
+it will used for subsequent lookups.
+.P
+There are three common schemas in use:
+.TP
+.I nisMap
+Entries in the \fBnisMap\fP schema are \fBnisObject\fP objects in
 the specified subtree, where the \fBcn\fP attribute is the key
 (the wildcard key is "/"), and the \fBnisMapEntry\fP attribute
 contains the information used by the automounter.
-.P
-Entries in the automountMap schema are \fBautomount\fP objects in
-the specified subtree, where the \fBcn\fP or \fBautomountKey\fP attribute
-(depending on local usage) is the key (the wildcard key is "/"), and the
-\fBautomountInformation\fP attribute contains the information used by the
-automounter.
+.TP
+.I automountMap
+The \fBautomountMap\fP schema has two variations that differ in the attribute
+used for the map key. Entries in the automountMap schema are \fBautomount\fP
+objects in the specified subtree, where the \fBcn\fP or \fBautomountKey\fP
+attribute (depending on local usage) is the key (the wildcard key is "/"),
+and the \fBautomountInformation\fP attribute contains the information used
+by the automounter. Note that the \fBcn\fP attribute is case insensitive.
 .P
 The object classes and attributes used for accessing automount maps in
 LDAP can be changed by setting entries in the autofs configuration
@@ -209,61 +217,44 @@ located in
 .nh
 .BR @@autofsconfdir@@/autofs .
 .hy
+.TP
+.B NOTE:
+If a schema is given in the configuration then all the schema configuration
+values must be set, any partial schema specification will be ignored.
 .P
 The configuration settings available are:
 .TP
-\fBMAP_OBJECT_CLASS\fP
-The map object class. Its Default value is "nisMap". In the
-.nh
-automountMap
-.hy
-schema this corresponds to the class
-.nh
-.BR automountMap .
-.hy
+.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
+\fBautomountMap\fP.
 .TP
 .B ENTRY_OBJECT_CLASS
-The map entry object class. Its default value is \fBnisObject\fP.
-In the automountMap schema this corresponds to the class
-.nh
-.BR automount .
-.hy
+The map entry object class. In the \fBnisMap\fP schema this corresponds
+to the class \fBnisObject\fP and in the \fBautomountMap\fP schema it
+corresponds to the class \fBautomount\fP.
 .TP
 .B MAP_ATTRIBUTE
 The attribute used to identify the name of the map to which this
-entry belongs. Its default value is
-.nh
-.BR nisMapName .
-.hy
-In the
-.nh
-automountMap
-.hy
-schema this corresponds to the attributes \fBou\fP or
-.nh
-.BR automountMapName .
-.hy
+entry belongs.  In the \fBnisMap\fP schema this corresponds to the attribute
+\fBnisMapName\fP and in the \fBautomountMap\fP schema it corresponds to the
+attribute \fBou\fP or \fBautomountMapName\fP.
 .TP
 .B ENTRY_ATTRIBUTE
-The attribute used to identify a map key. Its default value is
-In the
-.nh
-automountMap
-.hy
-schema this corresponds to the attribute
-.nh
-.BR automountKey .
-.hy
+The attribute used to identify a map key. In the \fBnisMap\fP schema this
+corresponds to the attribute \fBcn\fP and in the \fBautomountMap\fP schema
+it corresponds to the attribute \fBautomountKey\fP.
 .TP
 .B VALUE_ATTRIBUTE
-The attribute used to identify the value of the map entry. Its default
-value is
-.nh
-.BR BnisMapEntry .
-.hy
-In the automountMap schema this corresponds to the attribute
-.nh
-.BR automountInformation .
+The attribute used to identify the value of the map entry. In the \fBnisMap\fP
+schema this corresponds to the attribute \fBnisMapEntry\fP and in the \fBautomountMap\fP
+schema it corresponds to the attribute \fBautomountInformation\fP.
+.TP
+.B NOTE:
+It is essential that entries use class and attribute in a consistent
+manner for correct operation of autofs. For example mixing \fBcn\fP and
+\fBautomountKey\fP attributes in \fBautomount\fP schema map entries won't
+work as expected.
 .SH LDAP AUTHENTICATION, ENCRYPTED AND CERTIFIED CONNECTIONS
 LDAP authenticated binds, TLS encrypted connections and certification
 may be used by setting appropriate values in the autofs authentication
diff --git a/man/automount.8 b/man/automount.8
index fc1846a..da67a5c 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -102,6 +102,8 @@ started they will be recoverd unless they are no longer present in
 the map in which case they need to umounted manually.
 .SH "SEE ALSO"
 .BR autofs (5),
+.BR autofs (8),
+.BR auto.master (5),
 .BR mount (8).
 .SH BUGS
 Don't know, I've fixed everything I know about.
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index a412797..d5e666b 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -42,6 +42,13 @@
 
 int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
 
+static struct ldap_schema common_schema[] = {
+	{"nisMap", "nisMapName", "nisObject", "cn", "nisMapEntry"},
+	{"automountMap", "ou", "automount", "cn", "automountInformation"},
+	{"automountMap", "automountMapName", "automount", "automountKey", "automountInformation"},
+};
+static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema);
+
 int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
 {
 	int rv;
@@ -738,54 +745,15 @@ done:
 	return 1;
 }
 
-static int get_default_schema(struct lookup_context *ctxt)
-{
-	ctxt->map_obj_class = (char *) defaults_get_map_obj_class();
-	if (!ctxt->map_obj_class)
-		return 0;
-
-	ctxt->entry_obj_class = (char *) defaults_get_entry_obj_class();
-	if (!ctxt->entry_obj_class)
-		goto free_moc;
-
-	ctxt->map_attr = (char *) defaults_get_map_attr();
-	if (!ctxt->map_attr)
-		goto free_eoc;
-
-	ctxt->entry_attr = (char *) defaults_get_entry_attr();
-	if (!ctxt->entry_attr)
-		goto free_ma;
-
-	ctxt->value_attr = (char *) defaults_get_value_attr();
-	if (!ctxt->value_attr)
-		goto free_ea;
-
-	return 1;
-
-free_ea:
-	free(ctxt->entry_attr);
-free_ma:
-	free(ctxt->map_attr);
-free_eoc:
-	free(ctxt->entry_obj_class);
-free_moc:
-	free(ctxt->map_obj_class);
-
-	ctxt->map_obj_class = NULL;
-	ctxt->entry_obj_class = NULL;
-	ctxt->map_attr = NULL;
-	ctxt->entry_attr = NULL;
-
-	return 0;
-}
-
 static void free_context(struct lookup_context *ctxt)
 {
-	if (ctxt->map_obj_class) {
-		free(ctxt->map_obj_class);
-		free(ctxt->entry_obj_class);
-		free(ctxt->map_attr);
-		free(ctxt->entry_attr);
+	if (ctxt->schema) {
+		free(ctxt->schema->map_class);
+		free(ctxt->schema->map_attr);
+		free(ctxt->schema->entry_class);
+		free(ctxt->schema->entry_attr);
+		free(ctxt->schema->value_attr);
+		free(ctxt->schema);
 	}
 	if (ctxt->auth_conf)
 		free(ctxt->auth_conf);
@@ -808,19 +776,15 @@ static void free_context(struct lookup_context *ctxt)
 	return;
 }
 
-static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt)
+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 *class, *key;
 	char *attrs[2];
 	int scope;
 	int rv, l;
 
-	class = ctxt->map_obj_class;
-	key = ctxt->map_attr;
-
 	attrs[0] = LDAP_NO_ATTRS;
 	attrs[1] = NULL;
 
@@ -890,6 +854,90 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt)
 	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.
@@ -926,13 +974,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		return 1;
 	}
 
-	/* Get default schema for queries */
-	if (!get_default_schema(ctxt)) {
-		error(LOGOPT_ANY, MODPREFIX "cannot set default schema");
-		free_context(ctxt);
-		return 1;
-	}
-
 #ifdef WITH_SASL
 	/*
 	 * Determine which authentication mechanism to use.  We sanity-
@@ -954,13 +995,22 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		return 1;
 	}
 
-	ret = get_query_dn(ldap, ctxt);
-	unbind_ldap_connection(ldap, ctxt);
-	if (!ret) {
-		error(LOGOPT_ANY, MODPREFIX "failed to get query dn");
-		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;
+		}
 	}
+	unbind_ldap_connection(ldap, ctxt);
 
 	/* Open the parser, if we can. */
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
@@ -990,9 +1040,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	int scope = LDAP_SCOPE_SUBTREE;
 	LDAP *ldap;
 
-	class = ctxt->entry_obj_class;
-	entry = ctxt->entry_attr;
-	info = ctxt->value_attr;
+	class = ctxt->schema->entry_class;
+	entry = ctxt->schema->entry_attr;
+	info = ctxt->schema->value_attr;
 
 	attrs[0] = entry;
 	attrs[1] = info;
@@ -1141,9 +1191,9 @@ static int read_one_map(struct autofs_point *ap,
 
 	mc = source->mc;
 
-	class = ctxt->entry_obj_class;
-	entry = ctxt->entry_attr;
-	info = ctxt->value_attr;
+	class = ctxt->schema->entry_class;
+	entry = ctxt->schema->entry_attr;
+	info = ctxt->schema->value_attr;
 
 	attrs[0] = entry;
 	attrs[1] = info;
@@ -1438,9 +1488,9 @@ static int lookup_one(struct autofs_point *ap,
 		return CHE_FAIL;
 	}
 
-	class = ctxt->entry_obj_class;
-	entry = ctxt->entry_attr;
-	info = ctxt->value_attr;
+	class = ctxt->schema->entry_class;
+	entry = ctxt->schema->entry_attr;
+	info = ctxt->schema->value_attr;
 
 	attrs[0] = entry;
 	attrs[1] = info;
diff --git a/CHANGELOG b/CHANGELOG
index c36017a..0e9dc51 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -20,6 +20,7 @@
 - fix don't fail on empty master map.
 - if there's no "automount" entry in nsswitch.conf use "files" source.
 - add LDAP schema discovery if no schema is configured.
+- add random selection as a master map entry option.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 7b79f02..4b6584a 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -49,9 +49,9 @@ const char *confdir = AUTOFS_CONF_DIR;	/* Location of autofs config file */
 
 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;
@@ -1490,7 +1490,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;
@@ -1531,7 +1531,7 @@ int main(int argc, char *argv[])
 			exit(0);
 
 		case 'r':
-			random_selection = 1;
+			global_random_selection = 1;
 			break;
 
 		case 'O':
diff --git a/include/automount.h b/include/automount.h
index d9e4ecd..d55ba5c 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -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 --git a/include/replicated.h b/include/replicated.h
index c77cda6..3afe9f7 100644
--- a/include/replicated.h
+++ b/include/replicated.h
@@ -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 --git a/lib/master_parse.y b/lib/master_parse.y
index ab2895d..70b48be 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -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 { timeout = $2; }
 	| 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 *buffer, unsigned int default_timeout, unsigne
 		}
 		set_mnt_logging(ap);
 	}
+	entry->ap->random_selection = random_selection;
 
 /*
 	source = master_find_map_source(entry, type, format,
diff --git a/lib/master_tok.l b/lib/master_tok.l
index ff69a24..013a15a 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -324,6 +324,7 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{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 --git a/man/auto.master.5.in b/man/auto.master.5.in
index 249c9a7..ab5ab1e 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -146,6 +146,12 @@ to prevent symlinking of local NFS mounts. Nowadays it can be used to
 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
diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index e7a9a8a..e4480c5 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 		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 --git a/modules/replicated.c b/modules/replicated.c
index 0764d4a..e15587c 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -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(const char *options)
 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 *host, unsigned int version, const char
 	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 *host, unsigned int version, const char
 	}
 
 	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 *host, unsigned int version, const char
 	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, unsigned int vers, const char *options)
 			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, unsigned int vers, const char *options)
 			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 --git a/CHANGELOG b/CHANGELOG
index 0e9dc51..054d4df 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -21,6 +21,7 @@
 - if there's no "automount" entry in nsswitch.conf use "files" source.
 - add LDAP schema discovery if no schema is configured.
 - add random selection as a master map entry option.
+- fix couple of edge case parse fails of timeout option.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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);
diff --git a/CHANGELOG b/CHANGELOG
index 054d4df..ef549cf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,6 +22,7 @@
 - add LDAP schema discovery if no schema is configured.
 - add random selection as a master map entry option.
 - fix couple of edge case parse fails of timeout option.
+- check for "*" when looking up wildcard in LDAP.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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");
diff --git a/CHANGELOG b/CHANGELOG
index ef549cf..08afa7c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -23,6 +23,7 @@
 - add random selection as a master map entry option.
 - fix couple of edge case parse fails of timeout option.
 - check for "*" when looking up wildcard in LDAP.
+- fix LDAP schema discovery.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index a7b315e..9c18ca1 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1009,6 +1009,15 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 			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);
 
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index 8299b55..85f4e34 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -21,9 +21,12 @@ BROWSE_MODE="no"
 #
 #LOGGING="none"
 #
-# Define the default LDAP schema to use for lookups
+# Define the LDAP schema to used for lookups
 #
-# System default
+# If no schema is set autofs will check each of the schemas
+# below in the order given to try and locate an appropriate
+# basdn for lookups. If you want to minimize the number of
+# queries to the server set the values here.
 #
 #MAP_OBJECT_CLASS="nisMap"
 #ENTRY_OBJECT_CLASS="nisObject"
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 8299b55..85f4e34 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -21,9 +21,12 @@ BROWSE_MODE="no"
 #
 #LOGGING="none"
 #
-# Define the default LDAP schema to use for lookups
+# Define the LDAP schema to used for lookups
 #
-# System default
+# If no schema is set autofs will check each of the schemas
+# below in the order given to try and locate an appropriate
+# basdn for lookups. If you want to minimize the number of
+# queries to the server set the values here.
 #
 #MAP_OBJECT_CLASS="nisMap"
 #ENTRY_OBJECT_CLASS="nisObject"
diff --git a/CHANGELOG b/CHANGELOG
index 08afa7c..c208b31 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -24,6 +24,7 @@
 - fix couple of edge case parse fails of timeout option.
 - check for "*" when looking up wildcard in LDAP.
 - fix LDAP schema discovery.
+- add SEARCH_BASE configuration option.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/include/defaults.h b/include/defaults.h
index 9aec11a..0984b1c 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -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 --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index 1378b9e..1a924be 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -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 --git a/lib/defaults.c b/lib/defaults.c
index b146f13..c2f86c0 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -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 char *res, const char *name, const char
 	return 0;
 }
 
+static int parse_line(char *line, char **res, char **value)
+{
+	volatile 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_schema(void)
 	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 --git a/man/auto.master.5.in b/man/auto.master.5.in
index ab5ab1e..0cb2f07 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -230,6 +230,11 @@ values must be set, any partial schema specification will be ignored.
 .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
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 9c18ca1..da52e71 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -171,10 +171,207 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
 	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_context *ctxt)
 		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,175 +1021,17 @@ static void free_context(struct lookup_context *ctxt)
 		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];
-	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';
-
-	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) {
-		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.
@@ -994,31 +1088,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		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 --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index 85f4e34..2b1e20a 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -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 --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 85f4e34..2b1e20a 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -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 --git a/CHANGELOG b/CHANGELOG
index c208b31..a2a782d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -25,6 +25,7 @@
 - check for "*" when looking up wildcard in LDAP.
 - fix LDAP schema discovery.
 - add SEARCH_BASE configuration option.
+- work around segv at exit due to libxml2 tsd usage.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/aclocal.m4 b/aclocal.m4
index d0d8346..ffeb232 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -167,6 +167,19 @@ else
   HAVE_LIBXML=1
   XML_LIBS=`$XML_CONFIG --libs`
   XML_FLAGS=`$XML_CONFIG --cflags`
+  XML_VER=`$XML_CONFIG --version`
+  XML_MAJOR=`echo $XML_VER|cut -d\. -f1`
+  if test $XML_MAJOR -le 2
+  then
+    XML_MINOR=`echo $XML_VER|cut -d\. -f2`
+    if test $XML_MINOR -le 6
+    then
+      XML_REV=`echo $XML_VER|cut -d\. -f3`
+      if test $XML_REV -le 99; then
+        AC_DEFINE(LIBXML2_WORKAROUND,1, [Use libxml2 tsd usage workaround])
+      fi
+    fi
+  fi
 fi])
 
 dnl --------------------------------------------------------------------------
diff --git a/configure b/configure
index b723d74..3508224 100755
--- a/configure
+++ b/configure
@@ -2498,6 +2498,23 @@ echo "${ECHO_T}yes" >&6; }
   HAVE_LIBXML=1
   XML_LIBS=`$XML_CONFIG --libs`
   XML_FLAGS=`$XML_CONFIG --cflags`
+  XML_VER=`$XML_CONFIG --version`
+  XML_MAJOR=`echo $XML_VER|cut -d\. -f1`
+  if test $XML_MAJOR -le 2
+  then
+    XML_MINOR=`echo $XML_VER|cut -d\. -f2`
+    if test $XML_MINOR -le 6
+    then
+      XML_REV=`echo $XML_VER|cut -d\. -f3`
+      if test $XML_REV -le 99; then
+
+cat >>confdefs.h <<\_ACEOF
+#define LIBXML2_WORKAROUND 1
+_ACEOF
+
+      fi
+    fi
+  fi
 fi
 
 #
diff --git a/daemon/automount.c b/daemon/automount.c
index 4b6584a..aeeb7cb 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -40,6 +40,9 @@
 #include <sys/utsname.h>
 
 #include "automount.h"
+#ifdef LIBXML2_WORKAROUND
+#include <dlfcn.h>
+#endif
 
 const char *program;		/* Initialized with argv[0] */
 const char *version = VERSION_STRING;	/* Program version */
@@ -1681,6 +1684,11 @@ int main(int argc, char *argv[])
 		close(start_pipefd[1]);
 		exit(1);
 	}
+
+#ifdef LIBXML2_WORKAROUND
+	void *dh = dlopen("libxml2.so", RTLD_NOW);
+#endif
+
 	if (!master_read_master(master_list, age, 0)) {
 		master_kill(master_list);
 		*pst_stat = 3;
@@ -1702,5 +1710,9 @@ int main(int argc, char *argv[])
 	}
 	closelog();
 
+#ifdef LIBXML2_WORKAROUND
+	if (dh)
+		dlclose(dh);
+#endif
 	exit(0);
 }
diff --git a/include/config.h.in b/include/config.h.in
index 942694c..9669872 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -60,6 +60,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Use libxml2 tsd usage workaround */
+#undef LIBXML2_WORKAROUND
+
 /* Define to the address where bug reports for this package should be sent. */
 #undef PACKAGE_BUGREPORT
 
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index da52e71..49a9a9b 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1998,9 +1998,6 @@ int lookup_done(void *context)
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	int rv = close_parse(ctxt->parse);
 #ifdef WITH_SASL
-	EVP_cleanup();
-	ERR_free_strings();
-
 	autofs_sasl_done(ctxt);
 #endif
 	free_context(ctxt);
diff --git a/CHANGELOG b/CHANGELOG
index a2a782d..9a2a8c1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -26,6 +26,7 @@
 - fix LDAP schema discovery.
 - add SEARCH_BASE configuration option.
 - work around segv at exit due to libxml2 tsd usage.
+- re-read config on HUP signal.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index e9cae4e..3d6a703 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -986,6 +986,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 --git a/lib/master.c b/lib/master.c
index da05bb6..637ce04 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -1169,6 +1169,10 @@ int master_mount_mounts(struct master *master, time_t age, int readall)
 			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) {
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
index 8821f84..9aac792 100644
--- a/modules/cyrus-sasl.c
+++ b/modules/cyrus-sasl.c
@@ -528,6 +528,7 @@ sasl_do_kinit(struct lookup_context *ctxt)
 	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 --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 49a9a9b..2baf8b8 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -174,7 +174,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt)
 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, struct lookup_context *ctxt, const char *cla
 
 	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, struct lookup_context *ctxt, const char *cla
 	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, struct lookup_context *ctxt, const char *cla
 		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_context *ctxt)
 	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_point *ap,
 	}
 	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 --git a/CHANGELOG b/CHANGELOG
index 9a2a8c1..933b1a1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -27,6 +27,7 @@
 - add SEARCH_BASE configuration option.
 - work around segv at exit due to libxml2 tsd usage.
 - re-read config on HUP signal.
+- add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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.
diff --git a/CHANGELOG b/CHANGELOG
index 933b1a1..0340940 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -28,6 +28,7 @@
 - work around segv at exit due to libxml2 tsd usage.
 - re-read config on HUP signal.
 - add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options.
+- fix forground logging and add option to man page.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 58f1901..51f6a8b 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -58,14 +58,13 @@ unsigned int global_random_selection;	/* use random policy when selecting
 static int start_pipefd[2];
 static int st_stat = 0;
 static int *pst_stat = &st_stat;
+static pthread_t state_mach_thid;
 
 /* Pre-calculated kernel packet length */
 static size_t kpkt_len;
 
 /* Attribute to create detached thread */
 pthread_attr_t thread_attr;
-/* Attribute to create normal thread */
-pthread_attr_t thread_attr_nodetach;
 
 struct master_readmap_cond mrc = {
 	PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
@@ -75,9 +74,6 @@ struct startup_cond suc = {
 
 pthread_key_t key_thread_stdenv_vars;
 
-/* re-entrant syslog default context data */
-#define AUTOFS_SYSLOG_CONTEXT {-1, 0, 0, LOG_PID, (const char *)0, LOG_DAEMON, 0xff};
-
 #define MAX_OPEN_FILES		10240
 
 static int umount_all(struct autofs_point *ap, int force);
@@ -792,7 +788,6 @@ static void become_daemon(unsigned foreground)
 {
 	FILE *pidfp;
 	char buf[MAX_ERR_BUF];
-	unsigned to_stderr = 0;
 	pid_t pid;
 
 	/* Don't BUSY any directories unnecessarily */
@@ -809,7 +804,9 @@ static void become_daemon(unsigned foreground)
 	}
 
 	/* Detach from foreground process */
-	if (!foreground) {
+	if (foreground)
+		log_to_stderr();
+	else {
 		pid = fork();
 		if (pid > 0) {
 			int r;
@@ -834,13 +831,8 @@ static void become_daemon(unsigned foreground)
 			fprintf(stderr, "setsid: %s", estr);
 			exit(1);
 		}
-	}
-
-	/* Setup logging */
-	if (to_stderr)
-		log_to_stderr();
-	else
 		log_to_syslog();
+	}
 
 	/* Write pid file if requested */
 	if (pid_file) {
@@ -929,7 +921,7 @@ static pthread_t do_signals(struct master *master, int sig)
 	if (status)
 		fatal(status);
 
-	status = pthread_create(&thid, &thread_attr_nodetach, do_notify_state, &r_sig);
+	status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig);
 	if (status) {
 		error(master->default_logging,
 		      "mount state notify thread create failed");
@@ -1045,7 +1037,6 @@ static int do_hup_signal(struct master *master, time_t age)
 /* Deal with all the signal-driven events in the state machine */
 static void *statemachine(void *arg)
 {
-	pthread_t thid = 0;
 	sigset_t signalset;
 	int sig;
 
@@ -1058,15 +1049,12 @@ static void *statemachine(void *arg)
 
 		switch (sig) {
 		case SIGTERM:
+		case SIGINT:
 		case SIGUSR2:
+			if (master_list_empty(master_list))
+				return NULL;
 		case SIGUSR1:
-			thid = do_signals(master_list, sig);
-			if (thid) {
-				pthread_join(thid, NULL);
-				if (master_list_empty(master_list))
-					return NULL;
-				thid = 0;
-			}
+			do_signals(master_list, sig);
 			break;
 
 		case SIGHUP:
@@ -1181,6 +1169,10 @@ static void handle_mounts_cleanup(void *arg)
 
 	msg("shut down path %s", path);
 
+	/* If we are the last tell the state machine to shutdown */
+	if (!submount && master_list_empty(master_list))
+		pthread_kill(state_mach_thid, SIGTERM);
+	
 	return;
 }
 
@@ -1375,7 +1367,7 @@ static void usage(void)
 		"	-v --verbose	be verbose\n"
 		"	-d --debug	log debuging info\n"
 		"	-D --define	define global macro variable\n"
-		/*"	-f --foreground do not fork into background\n" */
+		"	-f --foreground do not fork into background\n"
 		"	-r --random-multimount-selection\n"
 		"			use ramdom replicated server selection\n"
 		"	-O --global-options\n"
@@ -1650,14 +1642,6 @@ int main(int argc, char *argv[])
 	}
 #endif
 
-	if (pthread_attr_init(&thread_attr_nodetach)) {
-		crit(LOGOPT_ANY,
-		     "%s: failed to init thread attribute struct!",
-		     program);
-		close(start_pipefd[1]);
-		exit(1);
-	}
-
 	msg("Starting automounter version %s, master map %s",
 		version, master_list->name);
 	msg("using kernel protocol version %d.%02d",
@@ -1702,6 +1686,7 @@ int main(int argc, char *argv[])
 	res = write(start_pipefd[1], pst_stat, sizeof(pst_stat));
 	close(start_pipefd[1]);
 
+	state_mach_thid = pthread_self();
 	statemachine(NULL);
 
 	master_kill(master_list);
diff --git a/lib/log.c b/lib/log.c
index e639e60..b747e12 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -27,9 +27,6 @@
 
 #include "automount.h"
 
-/* re-entrant syslog default context data */
-#define AUTOFS_SYSLOG_CONTEXT {-1, 0, 0, LOG_PID, (const char *) 0, LOG_DAEMON, 0xff};
-
 /*
 struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
 struct syslog_data *slc = &syslog_context;
@@ -134,30 +131,40 @@ static void syslog_debug(unsigned int logopt, const char *msg, ...)
 	va_end(ap);
 }
 
+static void to_stderr(unsigned int logopt, const char *msg, ...)
+{
+	va_list ap;
+	va_start(ap, msg);
+	vfprintf(stderr, msg, ap);
+	fputc('\n',stderr);
+	va_end(ap);
+}
+
 void set_mnt_logging(struct autofs_point *ap)
 {
 	unsigned int opt_verbose = ap->logopt & LOGOPT_VERBOSE;
 	unsigned int opt_debug = ap->logopt & LOGOPT_DEBUG;
 
-	if (opt_debug)
-		log_debug = syslog_debug;
+	if (opt_debug) {
+		if (logging_to_syslog)
+			log_debug = syslog_debug;
+		else
+			log_debug = to_stderr;
+	}
 
 	if (opt_verbose || opt_debug) {
-		log_info = syslog_info;
-		log_notice = syslog_notice;
-		log_warn = syslog_warn;
+		if (logging_to_syslog) {
+			log_info = syslog_info;
+			log_notice = syslog_notice;
+			log_warn = syslog_warn;
+		} else {
+			log_info = to_stderr;
+			log_notice = to_stderr;
+			log_warn = to_stderr;
+		}
 	}
 }
 
-static void to_stderr(unsigned int logopt, const char *msg, ...)
-{
-	va_list ap;
-	va_start(ap, msg);
-	vfprintf(stderr, msg, ap);
-	fputc('\n',stderr);
-	va_end(ap);
-}
-
 void log_to_syslog(void)
 {
 	char buf[MAX_ERR_BUF];
diff --git a/lib/master.c b/lib/master.c
index 637ce04..abc3bc2 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -954,6 +954,7 @@ void master_notify_state_change(struct master *master, int sig)
 
 		switch (sig) {
 		case SIGTERM:
+		case SIGINT:
 			if (ap->state != ST_SHUTDOWN_PENDING &&
 			    ap->state != ST_SHUTDOWN_FORCE) {
 				next = ST_SHUTDOWN_PENDING;
diff --git a/man/automount.8 b/man/automount.8
index da67a5c..e203a3e 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -47,6 +47,9 @@ Define a global macro substitution variable. Global definitions
 are over-ridden macro definitions of the same name specified in
 mount entries.
 .TP
+.I "\-f, \-\-foreground"
+Run the daemon in the forground and log to stderr instead of syslog."
+.TP
 .I "\-r, \-\-random-multimount-selection"
 Enables the use of ramdom selection when choosing a host from a
 list of replicated servers.
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
index 9aac792..68e5dd7 100644
--- a/modules/cyrus-sasl.c
+++ b/modules/cyrus-sasl.c
@@ -197,7 +197,7 @@ get_server_SASL_mechanisms(LDAP *ld)
 	if (mechanisms == NULL) {
 		/* Well, that was a waste of time. */
 		msg("No SASL authentication mechanisms are supported"
-		    " by the LDAP server.\n");
+		    " by the LDAP server.");
 		return NULL;
 	}
 
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 4068561..c0f228b 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -857,17 +857,17 @@ int parse_ldap_config(struct lookup_context *ctxt)
 	ctxt->client_princ = client_princ;
 
 	debug(LOGOPT_NONE,
-	      "ldap authentication configured with the following options:\n");
+	      "ldap authentication configured with the following options:");
 	debug(LOGOPT_NONE,
 	      "use_tls: %u, "
 	      "tls_required: %u, "
 	      "auth_required: %u, "
-	      "sasl_mech: %s\n",
+	      "sasl_mech: %s",
 	      use_tls, tls_required, auth_required, authtype);
 	debug(LOGOPT_NONE,
 	      "user: %s, "
 	      "secret: %s, "
-	      "client principal: %s\n",
+	      "client principal: %s",
 	      user, secret ? "specified" : "unspecified",
 	      client_princ);
 
diff --git a/CHANGELOG b/CHANGELOG
index 0340940..ddfa6f1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -29,6 +29,7 @@
 - re-read config on HUP signal.
 - add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options.
 - fix forground logging and add option to man page.
+- remove unjustified, nasty comment about krb5 package.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 51f6a8b..930b13f 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1263,22 +1263,6 @@ void *handle_mounts(void *arg)
 	}
 
 	pthread_cleanup_pop(1);
-
-	/*
-	 * A cowboy .. me!
-	 * That noise yu ear aint spuurs sonny!!
-	 *
-	 * The libkrb5support destructor called indirectly through
-	 * libgssapi_krb5 which is used bt libkrb5 (somehow) must run
-	 * to completion before the last thread using it exits so
-	 * that it's per thread data keys are deleted or we get a
-	 * little segfault at exit. So much for dlclose being
-	 * syncronous.
-	 *
-	 * So, the solution is a recipe for disaster.
-	 * Hope we don't get a really busy system!
-	 */
-	/*sleep(1);*/
 	sched_yield();
 
 	return NULL;
diff --git a/CHANGELOG b/CHANGELOG
index ddfa6f1..2db9b39 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -30,6 +30,7 @@
 - add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options.
 - fix forground logging and add option to man page.
 - remove unjustified, nasty comment about krb5 package.
+- fix deadlock in submount mount module.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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
diff --git a/CHANGELOG b/CHANGELOG
index 2db9b39..dd08880 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,7 @@
 - fix forground logging and add option to man page.
 - remove unjustified, nasty comment about krb5 package.
 - fix deadlock in submount mount module.
+- fix lack of ferror() checking when reading files.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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);
diff --git a/CHANGELOG b/CHANGELOG
index dd08880..fdd07d1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -32,6 +32,7 @@
 - remove unjustified, nasty comment about krb5 package.
 - fix deadlock in submount mount module.
 - fix lack of ferror() checking when reading files.
+- fix typo in autofs(5) man page.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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
diff --git a/CHANGELOG b/CHANGELOG
index fdd07d1..fe7ae00 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -33,6 +33,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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;
diff --git a/CHANGELOG b/CHANGELOG
index fe7ae00..ca171a4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -34,6 +34,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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@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) {
diff --git a/CHANGELOG b/CHANGELOG
index ca171a4..a7ac9fb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -35,6 +35,7 @@
 - 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).
 
 18/06/2007 autofs-5.0.2
 -----------------------
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);
 		return 1;
 	}
 	return 0;
@@ -649,23 +647,245 @@ static int fullread(int fd, void *ptr, size_t len)
 	return 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 ret;
+
+	fifo_name = malloc(name_len);
+	if (!fifo_name)
+		return NULL;
+	ret = snprintf(fifo_name, name_len, "%s%s",
+		       AUTOFS_LOGPRI_FIFO, path);
+	if (ret >= name_len) {
+		info(logopt,
+		     "fifo path for \"%s\" truncated to \"%s\".  This may "
+		     "lead to --set-log-priority commands being sent to the "
+		     "wrong automount daemon.", path, fifo_name);
+	}
+
+	/*
+	 *  An automount path can be made up of subdirectories.  So, to
+	 *  create the fifo name, we will just replace instances of '/' with
+	 *  '-'. 
+	 */
+	p = fifo_name + strlen(AUTOFS_LOGPRI_FIFO);
+	while (*p != '\0') {
+		if (*p == '/')
+			*p = '-';
+		p++;
+	}
+
+	debug(logopt, "fifo name %s",fifo_name);
+
+	return fifo_name;
+}
+
+static int create_logpri_fifo(struct autofs_point *ap)
+{
+	int ret = -1;
+	int fd;
+	char *fifo_name;
+
+	fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
+	if (!fifo_name) {
+		crit(ap->logopt, "Failed to allocate memory!");
+		goto out_free; /* free(NULL) is okay */
+	}
+
+	ret = unlink(fifo_name);
+	if (ret != 0 && errno != ENOENT) {
+		crit(ap->logopt,
+		     "Failed to unlink FIFO. Is the automount daemon "
+		     "already running?");
+		goto out_free;
+	}
+
+	ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR);
+	if (ret != 0) {
+		crit(ap->logopt,
+		     "mkfifo for %s returned %d", fifo_name, errno);
+		goto out_free;
+	}
+
+	fd = open(fifo_name, O_RDWR|O_NONBLOCK);
+	if (fd < 0) {
+		crit(ap->logopt,
+		     "Failed to open %s, errno %d", fifo_name, errno);
+		goto out_free;
+	}
+
+	ap->logpri_fifo = fd;
+
+out_free:
+	free(fifo_name);
+	return ret;
+}
+
+static int destroy_logpri_fifo(struct autofs_point *ap)
+{
+	int ret = -1;
+	int fd = ap->logpri_fifo;
+	char *fifo_name;
+
+	fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
+	if (!fifo_name) {
+		crit(ap->logopt, "Failed to allocate memory!");
+		goto out_free; /* free(NULL) is okay */
+	}
+
+	ap->logpri_fifo = -1;
+
+	ret = close(fd);
+	if (ret != 0) {
+		warn(ap->logopt,
+		     "close for fifo %s returned %d", fifo_name, errno);
+	}
+
+	ret = unlink(fifo_name);
+	if (ret != 0) {
+		warn(ap->logopt,
+		     "Failed to unlink FIFO. Was the fifo created OK?");
+	}
+
+out_free:
+	free(fifo_name);
+	return ret;
+}
+
+static void handle_fifo_message(struct autofs_point *ap, int fd)
+{
+	int ret;
+	char buffer[PIPE_BUF];
+	char *end;
+	long pri;
+
+	memset(buffer, 0, sizeof(buffer));
+	ret = read(fd, &buffer, sizeof(buffer));
+	if (ret < 0) {
+		warn(ap->logopt, "read on fifo returned error %d", errno);
+		return;
+	}
+
+	if (ret != 2) {
+		debug(ap->logopt, "expected 2 bytes, received %d.", ret);
+		return;
+	}
+
+	errno = 0;
+	pri = strtol(buffer, &end, 10);
+	if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) {
+		debug(ap->logopt, "strtol reported an %s.  Failed to set "
+		      "log priority.", pri == LONG_MIN ? "underflow" : "overflow");
+		return;
+	}
+	if ((pri == 0 && errno == EINVAL) || end == buffer) {
+		debug(ap->logopt, "priority is expected to be an integer "
+		      "in the range 0-7 inclusive.");
+		return;
+	}
+
+	if (pri > LOG_DEBUG || pri < LOG_EMERG) {
+		debug(ap->logopt, "invalid log priority (%ld) received "
+		      "on fifo", pri);
+		return;
+	}
+
+	/*
+	 * OK, the message passed all of the sanity checks.  The
+	 * automounter actually only supports three log priorities.
+	 * Everything is logged at log level debug, deamon messages
+	 * and everything except debug messages are logged with the
+	 * verbose setting and only error and critical messages are
+	 * logged when debugging isn't enabled.
+	 */
+	if (pri >= LOG_WARNING) {
+		if (pri == LOG_DEBUG) {
+			set_log_debug_ap(ap);
+			info(ap->logopt, "Debug logging set for %s", ap->path);
+		} else {
+			set_log_verbose_ap(ap);
+			info(ap->logopt, "Verbose logging set for %s", ap->path);
+		}
+	} else {
+		if (ap->logopt & LOGOPT_ANY)
+			info(ap->logopt, "Basic logging set for %s", ap->path);
+		set_log_norm_ap(ap);
+	}
+}
+
+static int set_log_priority(const char *path, int priority)
+{
+	int fd;
+	char *fifo_name;
+	char buf[2];
+
+	if (priority > LOG_DEBUG || priority < LOG_EMERG) {
+		fprintf(stderr, "Log priority %d is invalid.\n", priority);
+		fprintf(stderr, "Please spcify a number in the range 0-7.\n");
+		return -1;
+	}
+
+	/*
+	 * This is an ascii based protocol, so we want the string
+	 * representation of the integer log priority.
+	 */
+	snprintf(buf, sizeof(buf), "%d", priority);
+
+	fifo_name = automount_path_to_fifo(LOGOPT_NONE, path);
+	if (!fifo_name) {
+		fprintf(stderr, "%s: Failed to allocate memory!\n",
+			__FUNCTION__);
+		return -1;
+	}
+
+	/*
+	 * Specify O_NONBLOCK so that the open will fail if there is no
+	 * daemon reading from the other side of the FIFO.
+	 */
+	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);
+		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);
+		close(fd);
+		free(fifo_name);
+		return -1;
+	}
+	close(fd);
+	free(fifo_name);
+	fprintf(stdout, "Successfully set log priority for %s.\n", path);
+
+	return 0;
+}
+
 static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt)
 {
-	struct pollfd fds[2];
+	struct pollfd fds[3];
 	char buf[MAX_ERR_BUF];
 
 	fds[0].fd = ap->pipefd;
 	fds[0].events = POLLIN;
 	fds[1].fd = ap->state_pipe[0];
 	fds[1].events = POLLIN;
+	fds[2].fd = ap->logpri_fifo;
+	fds[2].events = POLLIN;
 
 	for (;;) {
-		if (poll(fds, 2, -1) == -1) {
+		if (poll(fds, 3, -1) == -1) {
 			char *estr;
 			if (errno == EINTR)
 				continue;
 			estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			error(ap->logopt, "poll failed: %s", estr);
+			logerr("poll failed: %s", estr);
 			return -1;
 		}
 
@@ -709,6 +929,11 @@ 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) {
+			debug(ap->logopt, "message pending on control fifo.");
+			handle_fifo_message(ap, fds[2].fd);
+		}
 	}
 }
 
@@ -730,21 +955,93 @@ int do_expire(struct autofs_point *ap, const char *name, int namelen)
 		return 1;
 	}
 
-	msg("expiring path %s", buf);
+	info(ap->logopt, "expiring path %s", buf);
 
 	ret = umount_multi(ap, buf, 1);
 	if (ret == 0)
-		msg("expired %s", buf);
+		info(ap->logopt, "expired %s", buf);
 	else
 		warn(ap->logopt, "couldn't complete expire of %s", buf);
 
 	return ret;
 }
 
+static int autofs_init_ap(struct autofs_point *ap)
+{
+	int pipefd[2], cl_flags;
+
+	if ((ap->state != ST_INIT)) {
+		/* This can happen if an autofs process is already running*/
+		error(ap->logopt, "bad state %d", ap->state);
+		return -1;
+	}
+
+	ap->pipefd = ap->kpipefd = ap->ioctlfd = -1;
+
+	/* Pipe for kernel communications */
+	if (pipe(pipefd) < 0) {
+		crit(ap->logopt,
+		     "failed to create commumication pipe for autofs path %s",
+		     ap->path);
+		free(ap->path);
+		return -1;
+	}
+
+	ap->pipefd = pipefd[0];
+	ap->kpipefd = pipefd[1];
+
+	if ((cl_flags = fcntl(ap->pipefd, F_GETFD, 0)) != -1) {
+		cl_flags |= FD_CLOEXEC;
+		fcntl(ap->pipefd, F_SETFD, cl_flags);
+	}
+
+	if ((cl_flags = fcntl(ap->kpipefd, F_GETFD, 0)) != -1) {
+		cl_flags |= FD_CLOEXEC;
+		fcntl(ap->kpipefd, F_SETFD, cl_flags);
+	}
+
+	/* Pipe state changes from signal handler to main loop */
+	if (pipe(ap->state_pipe) < 0) {
+		crit(ap->logopt,
+		     "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;
+	}
+
+	if ((cl_flags = fcntl(ap->state_pipe[0], F_GETFD, 0)) != -1) {
+		cl_flags |= FD_CLOEXEC;
+		fcntl(ap->state_pipe[0], F_SETFD, cl_flags);
+	}
+
+	if ((cl_flags = fcntl(ap->state_pipe[1], F_GETFD, 0)) != -1) {
+		cl_flags |= FD_CLOEXEC;
+		fcntl(ap->state_pipe[1], F_SETFD, cl_flags);
+	}
+
+	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;
+	}
+
+	return 0;
+}
+
 static int mount_autofs(struct autofs_point *ap)
 {
 	int status = 0;
 
+	if (autofs_init_ap(ap) != 0)
+		return -1;
+
 	if (ap->type == LKP_DIRECT)
 		status = mount_autofs_direct(ap);
 	else
@@ -841,9 +1138,8 @@ static void become_daemon(unsigned foreground)
 			fclose(pidfp);
 		} else {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			warn(LOGOPT_ANY,
-			     "failed to write pid file %s: %s",
-			     pid_file, estr);
+			logerr("failed to write pid file %s: %s",
+			       pid_file, estr);
 			pid_file = NULL;
 		}
 	}
@@ -889,12 +1185,12 @@ static void *do_notify_state(void *arg)
 
 	master = mrc.master;
 
-	debug(master->default_logging, "signal %d", sig);
+	debug(master->logopt, "signal %d", sig);
 
 	mrc.signaled = 1;
 	status = pthread_cond_signal(&mrc.cond);
 	if (status) {
-		error(master->default_logging,
+		error(master->logopt,
 		      "failed to signal state notify condition");
 		status = pthread_mutex_unlock(&mrc.mutex);
 		if (status)
@@ -923,7 +1219,7 @@ static pthread_t do_signals(struct master *master, int sig)
 
 	status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig);
 	if (status) {
-		error(master->default_logging,
+		error(master->logopt,
 		      "mount state notify thread create failed");
 		status = pthread_mutex_unlock(&mrc.mutex);
 		if (status)
@@ -951,6 +1247,7 @@ static pthread_t do_signals(struct master *master, int sig)
 static void *do_read_master(void *arg)
 {
 	struct master *master;
+	unsigned int logopt;
 	time_t age;
 	int readall = 1;
 	int status;
@@ -961,11 +1258,12 @@ static void *do_read_master(void *arg)
 
 	master = mrc.master;
 	age = mrc.age;
+	logopt = master->logopt;
 
 	mrc.signaled = 1;
 	status = pthread_cond_signal(&mrc.cond);
 	if (status) {
-		error(master->default_logging,
+		error(logopt,
 		      "failed to signal master read map condition");
 		master->reading = 0;
 		status = pthread_mutex_unlock(&mrc.mutex);
@@ -989,6 +1287,7 @@ static void *do_read_master(void *arg)
 
 static int do_hup_signal(struct master *master, time_t age)
 {
+	unsigned int logopt = master->logopt;
 	pthread_t thid;
 	int status;
 
@@ -1007,7 +1306,7 @@ static int do_hup_signal(struct master *master, time_t age)
 
 	status = pthread_create(&thid, &thread_attr, do_read_master, NULL);
 	if (status) {
-		error(master->default_logging,
+		error(logopt,
 		      "master read map thread create failed");
 		master->reading = 0;
 		status = pthread_mutex_unlock(&mrc.mutex);
@@ -1062,8 +1361,7 @@ static void *statemachine(void *arg)
 			break;
 
 		default:
-			error(master_list->default_logging,
-			      "got unexpected signal %d!", sig);
+			logerr("got unexpected signal %d!", sig);
 			continue;
 		}
 	}
@@ -1134,10 +1432,11 @@ static void handle_mounts_cleanup(void *arg)
 	struct autofs_point *ap;
 	char path[PATH_MAX + 1];
 	char buf[MAX_ERR_BUF];
-	unsigned int clean = 0, submount;
+	unsigned int clean = 0, submount, logopt;
 
 	ap = (struct autofs_point *) arg;
 
+	logopt = ap->logopt;
 	submount = ap->submount;
 
 	strcpy(path, ap->path);
@@ -1152,6 +1451,7 @@ static void handle_mounts_cleanup(void *arg)
 
 	umount_autofs(ap, 1);
 
+	destroy_logpri_fifo(ap);
 	master_signal_submount(ap, MASTER_SUBMNT_JOIN);
 	master_remove_mapent(ap->entry);
 	master_free_mapent_sources(ap->entry, 1);
@@ -1162,12 +1462,12 @@ static void handle_mounts_cleanup(void *arg)
 	if (clean) {
 		if (rmdir(path) == -1) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			warn(LOGOPT_NONE, "failed to remove dir %s: %s",
+			warn(logopt, "failed to remove dir %s: %s",
 			     path, estr);
 		}
 	}
 
-	msg("shut down path %s", path);
+	info(logopt, "shut down path %s", path);
 
 	/* If we are the last tell the state machine to shutdown */
 	if (!submount && master_list_empty(master_list))
@@ -1190,7 +1490,7 @@ void *handle_mounts(void *arg)
 
 	status = pthread_mutex_lock(&suc.mutex);
 	if (status) {
-		crit(ap->logopt, "failed to lock startup condition mutex!");
+		logerr("failed to lock startup condition mutex!");
 		fatal(status);
 	}
 
@@ -1204,7 +1504,7 @@ void *handle_mounts(void *arg)
 	}
 
 	if (ap->ghost && ap->type != LKP_DIRECT)
-		msg("ghosting enabled");
+		info(ap->logopt, "ghosting enabled");
 
 	suc.status = 0;
 	pthread_cleanup_pop(1);
@@ -1356,6 +1656,8 @@ static void usage(void)
 		"			use ramdom replicated server selection\n"
 		"	-O --global-options\n"
 		"			specify global mount options\n"
+		"	-l --set-log-priority priority path [path,...]\n"
+		"			set daemon log verbosity\n"
 		"	-V --version	print version, build config and exit\n"
 		, program);
 }
@@ -1437,9 +1739,45 @@ static void show_build_info(void)
 	return;
 }
 
+typedef struct _code {
+	char	*c_name;
+	int	c_val;
+} CODE;
+
+CODE prioritynames[] = {
+	{ "alert",	LOG_ALERT },
+	{ "crit",	LOG_CRIT },
+	{ "debug",	LOG_DEBUG },
+	{ "emerg",	LOG_EMERG },
+	{ "err",	LOG_ERR },
+	{ "error",	LOG_ERR },		/* DEPRECATED */
+	{ "info",	LOG_INFO },
+	{ "notice",	LOG_NOTICE },
+	{ "panic", 	LOG_EMERG },		/* DEPRECATED */
+	{ "warn",	LOG_WARNING },		/* DEPRECATED */
+	{ "warning",	LOG_WARNING },
+	{ NULL,		-1 },
+};
+
+static int convert_log_priority(char *priority_name)
+{
+	CODE *priority_mapping;
+
+	for (priority_mapping = prioritynames;
+	     priority_mapping->c_name != NULL;
+	     priority_mapping++) {
+
+		if (!strcasecmp(priority_name, priority_mapping->c_name))
+			return priority_mapping->c_val;
+	}
+
+	return -1;
+}
+
 int main(int argc, char *argv[])
 {
 	int res, opt, status;
+	int logpri = -1;
 	unsigned ghost, logging;
 	unsigned foreground, have_global_options;
 	time_t timeout;
@@ -1457,6 +1795,7 @@ int main(int argc, char *argv[])
 		{"random-multimount-selection", 0, 0, 'r'},
 		{"global-options", 1, 0, 'O'},
 		{"version", 0, 0, 'V'},
+		{"set-log-priority", 1, 0, 'l'},
 		{0, 0, 0, 0}
 	};
 
@@ -1477,7 +1816,7 @@ int main(int argc, char *argv[])
 	foreground = 0;
 
 	opterr = 0;
-	while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:", long_options, NULL)) != EOF) {
+	while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:", long_options, NULL)) != EOF) {
 		switch (opt) {
 		case 'h':
 			usage();
@@ -1525,6 +1864,23 @@ int main(int argc, char *argv[])
 				program);
 			break;
 
+		case 'l':
+			if (isalpha(*optarg)) {
+				logpri = convert_log_priority(optarg);
+				if (logpri < 0) {
+					fprintf(stderr, "Invalid log priority:"
+						" %s\n", optarg);
+					exit(1);
+				}
+			} else if (isdigit(*optarg)) {
+				logpri = getnumopt(optarg, opt);
+			} else {
+				fprintf(stderr, "non-alphanumeric character "
+					"found in log priority.  Aborting.\n");
+				exit(1);
+			}
+			break;
+
 		case '?':
 		case ':':
 			printf("%s: Ambiguous or unknown options\n", program);
@@ -1548,6 +1904,26 @@ int main(int argc, char *argv[])
 	argv += optind;
 	argc -= optind;
 
+	if (logpri >= 0) {
+		int exit_code = 0;
+		int i;
+
+		/*
+		 * The remaining argv elements are the paths for which
+		 * log priorities must be changed.
+		 */
+		for (i = 0; i < argc; i++) {
+			if (set_log_priority(argv[i], logpri) < 0)
+				exit_code = 1;
+		}
+		if (argc < 1) {
+			fprintf(stderr,
+				"--set-log-priority requires a path.\n");
+			exit_code = 1;
+		}
+		exit(exit_code);
+	}
+
 	if (is_automount_running() > 0) {
 		fprintf(stderr, "%s: program is already running.\n",
 			program);
@@ -1572,7 +1948,7 @@ int main(int argc, char *argv[])
 	rlim.rlim_max = MAX_OPEN_FILES;
 	res = setrlimit(RLIMIT_NOFILE, &rlim);
 	if (res)
-		warn(LOGOPT_NONE,
+		warn(logging,
 		     "can't increase open file limit - continuing");
 
 #if ENABLE_CORES
@@ -1580,7 +1956,7 @@ int main(int argc, char *argv[])
 	rlim.rlim_max = RLIM_INFINITY;
 	res = setrlimit(RLIMIT_CORE, &rlim);
 	if (res)
-		warn(LOGOPT_NONE,
+		warn(logging,
 		     "can't increase core file limit - continuing");
 #endif
 
@@ -1592,15 +1968,14 @@ int main(int argc, char *argv[])
 		master_list = master_new(argv[0], timeout, ghost);
 
 	if (!master_list) {
-		crit(LOGOPT_ANY, "%s: can't create master map %s",
+		logerr("%s: can't create master map %s",
 			program, argv[0]);
 		close(start_pipefd[1]);
 		exit(1);
 	}
 
 	if (pthread_attr_init(&thread_attr)) {
-		crit(LOGOPT_ANY,
-		     "%s: failed to init thread attribute struct!",
+		logerr("%s: failed to init thread attribute struct!",
 		     program);
 		close(start_pipefd[1]);
 		exit(1);
@@ -1608,8 +1983,7 @@ int main(int argc, char *argv[])
 
 	if (pthread_attr_setdetachstate(
 			&thread_attr, PTHREAD_CREATE_DETACHED)) {
-		crit(LOGOPT_ANY,
-		     "%s: failed to set detached thread attribute!",
+		logerr("%s: failed to set detached thread attribute!",
 		     program);
 		close(start_pipefd[1]);
 		exit(1);
@@ -1618,38 +1992,37 @@ int main(int argc, char *argv[])
 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
 	if (pthread_attr_setstacksize(
 			&thread_attr, PTHREAD_STACK_MIN*64)) {
-		crit(LOGOPT_ANY,
-		     "%s: failed to set stack size thread attribute!",
-		     program);
+		logerr("%s: failed to set stack size thread attribute!",
+		       program);
 		close(start_pipefd[1]);
 		exit(1);
 	}
 #endif
 
-	msg("Starting automounter version %s, master map %s",
+	info(logging, "Starting automounter version %s, master map %s",
 		version, master_list->name);
-	msg("using kernel protocol version %d.%02d",
+	info(logging, "using kernel protocol version %d.%02d",
 		get_kver_major(), get_kver_minor());
 
 	status = pthread_key_create(&key_thread_stdenv_vars,
 				key_thread_stdenv_vars_destroy);
 	if (status) {
-		crit(LOGOPT_ANY,
-		     "failed to create thread data key for std env vars!");
+		logerr("%s: failed to create thread data key for std env vars!",
+		       program);
 		master_kill(master_list);
 		close(start_pipefd[1]);
 		exit(1);
 	}
 
 	if (!alarm_start_handler()) {
-		crit(LOGOPT_ANY, "failed to create alarm handler thread!");
+		logerr("%s: failed to create alarm handler thread!", program);
 		master_kill(master_list);
 		close(start_pipefd[1]);
 		exit(1);
 	}
 
 	if (!st_start_handler()) {
-		crit(LOGOPT_ANY, "failed to create FSM handler thread!");
+		logerr("%s: failed to create FSM handler thread!", program);
 		master_kill(master_list);
 		close(start_pipefd[1]);
 		exit(1);
@@ -1685,5 +2058,7 @@ int main(int argc, char *argv[])
 	if (dh)
 		dlclose(dh);
 #endif
+	info(logging, "autofs stopped");
+
 	exit(0);
 }
diff --git a/daemon/direct.c b/daemon/direct.c
index 9a39a6f..4ab4204 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -86,61 +86,6 @@ static void mnts_cleanup(void *arg)
 	return;
 }
 
-static int autofs_init_direct(struct autofs_point *ap)
-{
-	int pipefd[2], cl_flags;
-
-	if ((ap->state != ST_INIT)) {
-		/* This can happen if an autofs process is already running*/
-		error(ap->logopt, "bad state %d", ap->state);
-		return -1;
-	}
-
-	ap->pipefd = ap->kpipefd = ap->ioctlfd = -1;
-
-	/* Pipe for kernel communications */
-	if (pipe(pipefd) < 0) {
-		crit(ap->logopt,
-		     "failed to create commumication pipe for autofs path %s",
-		     ap->path);
-		return -1;
-	}
-
-	ap->pipefd = pipefd[0];
-	ap->kpipefd = pipefd[1];
-
-	if ((cl_flags = fcntl(ap->pipefd, F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->pipefd, F_SETFD, cl_flags);
-	}
-
-	if ((cl_flags = fcntl(ap->kpipefd, F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->kpipefd, F_SETFD, cl_flags);
-	}
-
-	/* Pipe state changes from signal handler to main loop */
-	if (pipe(ap->state_pipe) < 0) {
-		crit(ap->logopt, "failed create state pipe for autofs path %s",
-		     ap->path);
-		close(ap->pipefd);
-		close(ap->kpipefd);
-		return -1;
-	}
-
-	if ((cl_flags = fcntl(ap->state_pipe[0], F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->state_pipe[0], F_SETFD, cl_flags);
-	}
-
-	if ((cl_flags = fcntl(ap->state_pipe[1], F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->state_pipe[1], F_SETFD, cl_flags);
-	}
-
-	return 0;
-}
-
 int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
 {
 	char buf[MAX_ERR_BUF];
@@ -241,10 +186,10 @@ int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, stru
 
 force_umount:
 	if (rv != 0) {
-		msg("forcing umount of direct mount %s", me->key);
+		info(ap->logopt, "forcing umount of direct mount %s", me->key);
 		rv = umount2(me->key, MNT_DETACH);
 	} else
-		msg("umounted direct mount %s", me->key);
+		info(ap->logopt, "umounted direct mount %s", me->key);
 
 	if (!rv && me->dir_created) {
 		if  (rmdir(me->key) == -1) {
@@ -326,7 +271,7 @@ static int unlink_mount_tree(struct autofs_point *ap, struct list_head *list)
 			continue;
 
 		if (strcmp(mnt->fs_type, "autofs"))
-			rv = spawn_umount(log_debug, "-l", mnt->path, NULL);
+			rv = spawn_umount(ap->logopt, "-l", mnt->path, NULL);
 		else
 			rv = umount2(mnt->path, MNT_DETACH);
 		if (rv == -1) {
@@ -475,13 +420,15 @@ int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struc
 	ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
 
 	if (ap->exp_timeout)
-		msg("mounted direct mount on %s "
+		info(ap->logopt,
+		    "mounted direct mount on %s "
 		    "with timeout %u, freq %u seconds", me->key,
 		    (unsigned int) ap->exp_timeout,
 		    (unsigned int) ap->exp_runfreq);
 	else
-		msg("mounted direct mount on %s with timeouts disabled",
-		    me->key);
+		info(ap->logopt,
+		     "mounted direct mount on %s with timeouts disabled",
+		     me->key);
 
 	ret = fstat(ioctlfd, &st);
 	if (ret == -1) {
@@ -522,9 +469,6 @@ int mount_autofs_direct(struct autofs_point *ap)
 		return -1;
 	}
 
-	if (autofs_init_direct(ap))
-		return -1;
-
 	/* TODO: check map type */
 	if (lookup_nss_read_map(ap, NULL, now))
 		lookup_prune_cache(ap, now);
@@ -607,7 +551,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 		/* offset isn't mounted, return success and try to recover */
 		if (!is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
 			debug(ap->logopt,
-			      "offset %s unexpectedly not mounted",
+			      "offset %s not mounted",
 			      me->key);
 			return 0;
 		}
@@ -627,7 +571,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 		rv = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status);
 		if (rv) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			error(ap->logopt, "ioctl failed: %s", estr);
+			logerr("ioctl failed: %s", estr);
 			return 1;
 		} else if (!status) {
 			if (ap->state != ST_SHUTDOWN_FORCE) {
@@ -692,10 +636,10 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
 
 force_umount:
 	if (rv != 0) {
-		msg("forcing umount of offset mount %s", me->key);
+		info(ap->logopt, "forcing umount of offset mount %s", me->key);
 		rv = umount2(me->key, MNT_DETACH);
 	} else
-		msg("umounted offset mount %s", me->key);
+		info(ap->logopt, "umounted offset mount %s", me->key);
 
 	if (!rv && me->dir_created) {
 		if  (rmdir(me->key) == -1) {
@@ -868,7 +812,7 @@ static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsig
 		return 0;
 	}
 
-	retries = (count_mounts(path, st.st_dev) + 1) * EXPIRE_RETRIES;
+	retries = (count_mounts(logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
 
 	while (retries--) {
 		struct timespec tm = {0, 100000000};
@@ -1018,7 +962,7 @@ void *expire_proc_direct(void *arg)
 
 			if (me->ioctlfd != -1 && 
 			    fstat(ioctlfd, &st) != -1 &&
-			    !count_mounts(next->path, st.st_dev)) {
+			    !count_mounts(ap->logopt, next->path, st.st_dev)) {
 				close(ioctlfd);
 				me->ioctlfd = -1;
 			}
@@ -1049,6 +993,9 @@ void *expire_proc_direct(void *arg)
 	}
 	pthread_cleanup_pop(1);
 
+	if (left)
+		info(ap->logopt, "%d remaining in %s", left, ap->path);
+
 	ec.status = left;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
@@ -1072,7 +1019,7 @@ static void pending_cond_destroy(void *arg)
 static void expire_send_fail(void *arg)
 {
 	struct pending_args *mt = arg;
-	send_fail(mt->ioctlfd, mt->wait_queue_token);
+	send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 }
 
 static void free_pending_args(void *arg)
@@ -1124,14 +1071,14 @@ static void *do_expire_direct(void *arg)
 	status = do_expire(ap, mt->name, len);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 	if (status)
-		send_fail(mt->ioctlfd, mt->wait_queue_token);
+		send_fail(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 	else {
 		struct mapent *me;
 		cache_readlock(mt->mc);
 		me = cache_lookup_distinct(mt->mc, mt->name);
 		me->ioctlfd = -1;
 		cache_unlock(mt->mc);
-		send_ready(mt->ioctlfd, mt->wait_queue_token);
+		send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 		close(mt->ioctlfd);
 	}
 	pthread_setcancelstate(state, NULL);
@@ -1194,7 +1141,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
 	if (!mt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		error(ap->logopt, "malloc: %s", estr);
-		send_fail(me->ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, me->ioctlfd, pkt->wait_queue_token);
 		cache_unlock(mc);
 		pthread_setcancelstate(state, NULL);
 		return 1;
@@ -1223,7 +1170,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
 	status = pthread_create(&thid, &thread_attr, do_expire_direct, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
-		send_fail(mt->ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, mt->ioctlfd, pkt->wait_queue_token);
 		cache_unlock(mc);
 		expire_mutex_unlock(NULL);
 		pending_cond_destroy(mt);
@@ -1252,7 +1199,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
 static void mount_send_fail(void *arg)
 {
 	struct pending_args *mt = arg;
-	send_fail(mt->ioctlfd, mt->wait_queue_token);
+	send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 	close(mt->ioctlfd);
 }
 
@@ -1319,7 +1266,7 @@ static void *do_mount_direct(void *arg)
 
 	pthread_setcancelstate(state, NULL);
 
-	msg("attempting to mount entry %s", mt->name);
+	info(ap->logopt, "attempting to mount entry %s", mt->name);
 
 	/*
 	 * Setup thread specific data values for macro
@@ -1445,16 +1392,16 @@ cont:
 		cache_unlock(mt->mc);
 		if (set_fd) {
 			me->ioctlfd = mt->ioctlfd;
-			send_ready(mt->ioctlfd, mt->wait_queue_token);
+			send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 		} else {
-			send_ready(mt->ioctlfd, mt->wait_queue_token);
+			send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 			close(mt->ioctlfd);
 		}
-		msg("mounted %s", mt->name);
+		info(ap->logopt, "mounted %s", mt->name);
 	} else {
-		send_fail(mt->ioctlfd, mt->wait_queue_token);
+		send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token);
 		close(mt->ioctlfd);
-		msg("failed to mount %s", mt->name);
+		info(ap->logopt, "failed to mount %s", mt->name);
 	}
 	pthread_setcancelstate(state, NULL);
 
@@ -1505,7 +1452,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
 		 * Shouldn't happen as the kernel is telling us
 		 * someone has walked on our mount point.
 		 */
-		crit(ap->logopt, "can't find map entry for (%lu,%lu)",
+		logerr("can't find map entry for (%lu,%lu)",
 		    (unsigned long) pkt->dev, (unsigned long) pkt->ino);
 		pthread_setcancelstate(state, NULL);
 		return 1;
@@ -1538,7 +1485,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
 	if (ap->state == ST_SHUTDOWN_PENDING ||
 	    ap->state == ST_SHUTDOWN_FORCE ||
 	    ap->state == ST_SHUTDOWN) {
-		send_fail(ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
 		close(ioctlfd);
 		cache_unlock(mc);
 		pthread_setcancelstate(state, NULL);
@@ -1549,7 +1496,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
 	if (!mt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		error(ap->logopt, "malloc: %s", estr);
-		send_fail(ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
 		close(ioctlfd);
 		cache_unlock(mc);
 		pthread_setcancelstate(state, NULL);
@@ -1578,7 +1525,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
 	status = pthread_create(&thid, &thread_attr, do_mount_direct, mt);
 	if (status) {
 		error(ap->logopt, "missing mount thread create failed");
-		send_fail(ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
 		close(ioctlfd);
 		cache_unlock(mc);
 		mount_mutex_unlock(NULL);
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 02e7045..5c422c8 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -43,63 +43,6 @@ extern pthread_attr_t thread_attr;
 static pthread_mutex_t ma_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-static int autofs_init_indirect(struct autofs_point *ap)
-{
-	int pipefd[2], cl_flags;
-
-	if ((ap->state != ST_INIT)) {
-		/* This can happen if an autofs process is already running*/
-		error(ap->logopt, "bad state %d", ap->state);
-		return -1;
-	}
-
-	ap->pipefd = ap->kpipefd = ap->ioctlfd = -1;
-
-	/* Pipe for kernel communications */
-	if (pipe(pipefd) < 0) {
-		crit(ap->logopt,
-		     "failed to create commumication pipe for autofs path %s",
-		     ap->path);
-		free(ap->path);
-		return -1;
-	}
-
-	ap->pipefd = pipefd[0];
-	ap->kpipefd = pipefd[1];
-
-	if ((cl_flags = fcntl(ap->pipefd, F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->pipefd, F_SETFD, cl_flags);
-	}
-
-	if ((cl_flags = fcntl(ap->kpipefd, F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->kpipefd, F_SETFD, cl_flags);
-	}
-
-	/* Pipe state changes from signal handler to main loop */
-	if (pipe(ap->state_pipe) < 0) {
-		crit(ap->logopt,
-		     "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;
-	}
-
-	if ((cl_flags = fcntl(ap->state_pipe[0], F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->state_pipe[0], F_SETFD, cl_flags);
-	}
-
-	if ((cl_flags = fcntl(ap->state_pipe[1], F_GETFD, 0)) != -1) {
-		cl_flags |= FD_CLOEXEC;
-		fcntl(ap->state_pipe[1], F_SETFD, cl_flags);
-	}
-
-	return 0;
-}
-
 static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts)
 {
 	struct mnt_list *this;
@@ -118,7 +61,7 @@ static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts)
 		}
 
 		if (strcmp(this->fs_type, "autofs"))
-			rv = spawn_umount(log_debug, "-l", this->path, NULL);
+			rv = spawn_umount(ap->logopt, "-l", this->path, NULL);
 		else
 			rv = umount2(this->path, MNT_DETACH);
 		if (rv == -1) {
@@ -222,12 +165,14 @@ static int do_mount_autofs_indirect(struct autofs_point *ap)
 	ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
 
 	if (ap->exp_timeout)
-		msg("mounted indirect mount on %s "
+		info(ap->logopt,
+		    "mounted indirect mount on %s "
 		    "with timeout %u, freq %u seconds", ap->path,
-	 	   (unsigned int) ap->exp_timeout,
-		   (unsigned int) ap->exp_runfreq);
+	 	    (unsigned int) ap->exp_timeout,
+		    (unsigned int) ap->exp_runfreq);
 	else
-		msg("mounted indirect mount on %s with timeouts disabled",
+		info(ap->logopt,
+		    "mounted indirect mount on %s with timeouts disabled",
 		    ap->path);
 
 	fstat(ap->ioctlfd, &st);
@@ -257,9 +202,6 @@ int mount_autofs_indirect(struct autofs_point *ap)
 	int status;
 	int map;
 
-        if (autofs_init_indirect(ap))
-		return -1;
-
 	/* TODO: read map, determine map type is OK */
 	if (lookup_nss_read_map(ap, NULL, now))
 		lookup_prune_cache(ap, now);
@@ -309,7 +251,7 @@ int umount_autofs_indirect(struct autofs_point *ap)
 	rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret);
 	if (rv == -1) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, "ioctl failed: %s", estr);
+		logerr("ioctl failed: %s", estr);
 		return 1;
 	} else if (!ret) {
 		error(ap->logopt, "ask umount returned busy %s", ap->path);
@@ -370,9 +312,9 @@ force_umount:
 		     "forcing umount of indirect mount %s", ap->path);
 		rv = umount2(ap->path, MNT_DETACH);
 	} else {
-		msg("umounted indirect mount %s", ap->path);
+		info(ap->logopt, "umounted indirect mount %s", ap->path);
 		if (ap->submount)
-			rm_unwanted(ap->path, 1, ap->dev);
+			rm_unwanted(ap->logopt, ap->path, 1, ap->dev);
 	}
 
 	return rv;
@@ -390,7 +332,7 @@ static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *pat
 		return 0;
 	}
 
-	retries = (count_mounts(path, st.st_dev) + 1) * EXPIRE_RETRIES;
+	retries = (count_mounts(ap->logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
 
 	while (retries--) {
 		struct timespec tm = {0, 100000000};
@@ -559,13 +501,7 @@ void *expire_proc_indirect(void *arg)
 	 * words) the umounts are done by the time we reach here
 	 */
 	if (count)
-		debug(ap->logopt, "%d remaining in %s", count, ap->path);
-
-	/* If we are trying to shutdown make sure we can umount */
-	if (!ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
-		if (!ret)
-			msg("mount still busy %s", ap->path);
-	}
+		info(ap->logopt, "%d remaining in %s", count, ap->path);
 
 	ec.status = left;
 
@@ -590,7 +526,7 @@ static void pending_cond_destroy(void *arg)
 static void expire_send_fail(void *arg)
 {
 	struct pending_args *mt = arg;
-	send_fail(mt->ap->ioctlfd, mt->wait_queue_token);
+	send_fail(mt->ap->logopt, mt->ap->ioctlfd, mt->wait_queue_token);
 }
 
 static void free_pending_args(void *arg)
@@ -634,9 +570,9 @@ static void *do_expire_indirect(void *arg)
 	status = do_expire(mt->ap, mt->name, mt->len);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 	if (status)
-		send_fail(ap->ioctlfd, mt->wait_queue_token);
+		send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
 	else
-		send_ready(ap->ioctlfd, mt->wait_queue_token);
+		send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
 	pthread_setcancelstate(state, NULL);
 
 	pthread_cleanup_pop(0);
@@ -661,8 +597,8 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_
 	mt = malloc(sizeof(struct pending_args));
 	if (!mt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, "malloc: %s", estr);
-		send_fail(ap->ioctlfd, pkt->wait_queue_token);
+		logerr("malloc: %s", estr);
+		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
 		pthread_setcancelstate(state, NULL);
 		return 1;
 	}
@@ -684,7 +620,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_
 	status = pthread_create(&thid, &thread_attr, do_expire_indirect, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
-		send_fail(ap->ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
 		expire_mutex_unlock(NULL);
 		pending_cond_destroy(mt);
 		free_pending_args(mt);
@@ -710,7 +646,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_
 static void mount_send_fail(void *arg)
 {
 	struct pending_args *mt = arg;
-	send_fail(mt->ap->ioctlfd, mt->wait_queue_token);
+	send_fail(mt->ap->logopt, mt->ap->ioctlfd, mt->wait_queue_token);
 }
 
 static void mount_mutex_unlock(void *arg)
@@ -775,7 +711,7 @@ static void *do_mount_indirect(void *arg)
 
 	pthread_setcancelstate(state, NULL);
 
-	msg("attempting to mount entry %s", buf);
+	info(ap->logopt, "attempting to mount entry %s", buf);
 
 	/*
 	 * Setup thread specific data values for macro
@@ -887,11 +823,11 @@ cont:
 	status = lookup_nss_mount(ap, NULL, mt->name, mt->len);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 	if (status) {
-		send_ready(ap->ioctlfd, mt->wait_queue_token);
-		msg("mounted %s", buf);
+		send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
+		info(ap->logopt, "mounted %s", buf);
 	} else {
-		send_fail(ap->ioctlfd, mt->wait_queue_token);
-		msg("failed to mount %s", buf);
+		send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
+		info(ap->logopt, "failed to mount %s", buf);
 	}
 	pthread_setcancelstate(state, NULL);
 
@@ -918,7 +854,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin
 	if (ap->state == ST_SHUTDOWN_PENDING ||
 	    ap->state == ST_SHUTDOWN_FORCE ||
 	    ap->state == ST_SHUTDOWN) {
-		send_fail(ap->ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
 		pthread_setcancelstate(state, NULL);
 		return 0;
 	}
@@ -926,8 +862,8 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin
 	mt = malloc(sizeof(struct pending_args));
 	if (!mt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, "malloc: %s", estr);
-		send_fail(ap->ioctlfd, pkt->wait_queue_token);
+		logerr("malloc: %s", estr);
+		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
 		pthread_setcancelstate(state, NULL);
 		return 1;
 	}
@@ -953,7 +889,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin
 	status = pthread_create(&thid, &thread_attr, do_mount_indirect, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
-		send_fail(ap->ioctlfd, pkt->wait_queue_token);
+		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
 		mount_mutex_unlock(NULL);
 		pending_cond_destroy(mt);
 		free_pending_args(mt);
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 4f2b318..fd99cf2 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -103,6 +103,7 @@ static int do_read_master(struct master *master, char *type, time_t age)
 
 static int read_master_map(struct master *master, char *type, time_t age)
 {
+	unsigned int logopt = master->logopt;
 	char *path, *save_name;
 	int result;
 
@@ -117,7 +118,7 @@ static int read_master_map(struct master *master, char *type, time_t age)
 	 */
 
 	if (strchr(master->name, '/')) {
-		error(LOGOPT_ANY, "relative path invalid in files map name");
+		error(logopt, "relative path invalid in files map name");
 		return NSS_STATUS_NOTFOUND;
 	}
 
@@ -142,6 +143,7 @@ static int read_master_map(struct master *master, char *type, time_t age)
 
 int lookup_nss_read_master(struct master *master, time_t age)
 {
+	unsigned int logopt = master->logopt;
 	struct list_head nsslist;
 	struct list_head *head, *p;
 	int result = NSS_STATUS_UNKNOWN;
@@ -149,12 +151,10 @@ int lookup_nss_read_master(struct master *master, time_t age)
 	/* If it starts with a '/' it has to be a file or LDAP map */
 	if (*master->name == '/') {
 		if (*(master->name + 1) == '/') {
-			debug(LOGOPT_NONE,
-			      "reading master ldap %s", master->name);
+			debug(logopt, "reading master ldap %s", master->name);
 			result = do_read_master(master, "ldap", age);
 		} else {
-			debug(LOGOPT_NONE,
-			      "reading master file %s", master->name);
+			debug(logopt, "reading master file %s", master->name);
 			result = do_read_master(master, "file", age);
 		}
 
@@ -184,13 +184,11 @@ int lookup_nss_read_master(struct master *master, time_t age)
 				 */
 				if (strncmp(name, "ldap", 4)) {
 					master->name = tmp + 1;
-					debug(LOGOPT_NONE,
-					      "reading master %s %s",
+					debug(logopt, "reading master %s %s",
 					      source, master->name);
 				} else {
 					master->name = name;
-					debug(LOGOPT_NONE,
-					      "reading master %s %s",
+					debug(logopt, "reading master %s %s",
 					      source, tmp + 1);
 				}
 
@@ -208,7 +206,7 @@ int lookup_nss_read_master(struct master *master, time_t age)
 	if (result) {
 		if (!list_empty(&nsslist))
 			free_sources(&nsslist);
-		error(LOGOPT_ANY, "can't to read name service switch config.");
+		error(logopt, "can't to read name service switch config.");
 		return 0;
 	}
 
@@ -220,13 +218,12 @@ int lookup_nss_read_master(struct master *master, time_t age)
 
 		this = list_entry(p, struct nss_source, list);
 
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      "reading master %s %s", this->source, master->name);
 
 		result = read_master_map(master, this->source, age);
 		if (result == NSS_STATUS_UNKNOWN) {
-			debug(LOGOPT_NONE,
-			      "no map - continuing to next source");
+			debug(logopt, "no map - continuing to next source");
 			continue;
 		}
 
@@ -1008,9 +1005,10 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age)
 				if (this->ioctlfd == -1)
 					status = cache_delete(mc, key);
 				if (status != CHE_FAIL) {
-					if (ap->type == LKP_INDIRECT)
-						rmdir_path(ap, path, ap->dev);
-					else
+					if (ap->type == LKP_INDIRECT) {
+						if (ap->ghost)
+							rmdir_path(ap, path, ap->dev);
+					} else
 						rmdir_path(ap, path, this->dev);
 				}
 			}
diff --git a/daemon/module.c b/daemon/module.c
index e83c929..36eca00 100644
--- a/daemon/module.c
+++ b/daemon/module.c
@@ -33,7 +33,7 @@ int load_autofs4_module(void)
 	 */
 	fp = fopen("/proc/filesystems", "r");
 	if (!fp) {
-		error(LOGOPT_ANY, "cannot open /proc/filesystems\n");
+		logerr("cannot open /proc/filesystems\n");
 		return 0;
 	}
 
@@ -45,7 +45,7 @@ int load_autofs4_module(void)
 	}
 	fclose(fp);
 
-	ret = spawnl(log_debug, PATH_MODPROBE, PATH_MODPROBE,
+	ret = spawnl(LOGOPT_NONE, PATH_MODPROBE, PATH_MODPROBE,
 				"-q", FS_MODULE_NAME, NULL);
 	if (ret)
 		return 0;
@@ -72,7 +72,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
 	if (!mod) {
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, "%s%s", err_prefix, estr);
+			logerr("%s%s", err_prefix, estr);
 		}
 		return NULL;
 	}
@@ -83,7 +83,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
 		free(mod);
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, "%s%s", err_prefix, estr);
+			logerr("%s%s", err_prefix, estr);
 		}
 		return NULL;
 	}
@@ -91,7 +91,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
 
 	if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
 		if (err_prefix)
-			crit(LOGOPT_ANY, "%scannot open lookup module %s (%s)",
+			logerr("%scannot open lookup module %s (%s)",
 			       err_prefix, name, dlerror());
 		free(mod);
 		return NULL;
@@ -100,8 +100,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
 	if (!(ver = (int *) dlsym(dh, "lookup_version"))
 	    || *ver != AUTOFS_LOOKUP_VERSION) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%slookup module %s version mismatch",
+			logerr("%slookup module %s version mismatch",
 			     err_prefix, name);
 		dlclose(dh);
 		free(mod);
@@ -114,7 +113,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
 	    !(mod->lookup_mount = (lookup_mount_t) dlsym(dh, "lookup_mount")) ||
 	    !(mod->lookup_done = (lookup_done_t) dlsym(dh, "lookup_done"))) {
 		if (err_prefix)
-			crit(LOGOPT_ANY, "%slookup module %s corrupt", err_prefix, name);
+			logerr("%slookup module %s corrupt", err_prefix, name);
 		dlclose(dh);
 		free(mod);
 		return NULL;
@@ -156,7 +155,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
 	if (!mod) {
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, "%s%s", err_prefix, estr);
+			logerr("%s%s", err_prefix, estr);
 		}
 		return NULL;
 	}
@@ -167,7 +166,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
 		free(mod);
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, "%s%s", err_prefix, estr);
+			logerr("%s%s", err_prefix, estr);
 		}
 		return NULL;
 	}
@@ -175,8 +174,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
 
 	if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%scannot open parse module %s (%s)",
+			logerr("%scannot open parse module %s (%s)",
 			     err_prefix, name, dlerror());
 		free(mod);
 		return NULL;
@@ -185,8 +183,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
 	if (!(ver = (int *) dlsym(dh, "parse_version"))
 	    || *ver != AUTOFS_PARSE_VERSION) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%sparse module %s version mismatch",
+			logerr("%sparse module %s version mismatch",
 			     err_prefix, name);
 		dlclose(dh);
 		free(mod);
@@ -197,8 +194,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
 	    !(mod->parse_mount = (parse_mount_t) dlsym(dh, "parse_mount")) ||
 	    !(mod->parse_done = (parse_done_t) dlsym(dh, "parse_done"))) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%sparse module %s corrupt",
+			logerr("%sparse module %s corrupt",
 			     err_prefix, name);
 		dlclose(dh);
 		free(mod);
@@ -240,7 +236,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
 	if (!mod) {
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, "%s%s", err_prefix, estr);
+			logerr("%s%s", err_prefix, estr);
 		}
 		return NULL;
 	}
@@ -251,7 +247,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
 		free(mod);
 		if (err_prefix) {
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, "%s%s", err_prefix, estr);
+			logerr("%s%s", err_prefix, estr);
 		}
 		return NULL;
 	}
@@ -259,8 +255,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
 
 	if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%scannot open mount module %s (%s)",
+			logerr("%scannot open mount module %s (%s)",
 			     err_prefix, name, dlerror());
 		free(mod);
 		return NULL;
@@ -269,8 +264,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
 	if (!(ver = (int *) dlsym(dh, "mount_version"))
 	    || *ver != AUTOFS_MOUNT_VERSION) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%smount module %s version mismatch",
+			logerr("%smount module %s version mismatch",
 			     err_prefix, name);
 		dlclose(dh);
 		free(mod);
@@ -281,8 +275,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
 	    !(mod->mount_mount = (mount_mount_t) dlsym(dh, "mount_mount")) ||
 	    !(mod->mount_done = (mount_done_t) dlsym(dh, "mount_done"))) {
 		if (err_prefix)
-			crit(LOGOPT_ANY,
-			     "%smount module %s corrupt",
+			logerr("%smount module %s corrupt",
 			     err_prefix, name);
 		dlclose(dh);
 		free(mod);
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 271d37e..3d5ea56 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -88,7 +88,7 @@ void reset_signals(void)
 
 #define ERRBUFSIZ 2047		/* Max length of error string excl \0 */
 
-static int do_spawn(logger *log, unsigned int options, const char *prog, const char *const *argv)
+static int do_spawn(unsigned logopt, unsigned int options, const char *prog, const char *const *argv)
 {
 	pid_t f;
 	int ret, status, pipefd[2];
@@ -195,7 +195,7 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c
 				while (errp && (p = memchr(sp, '\n', errp))) {
 					*p++ = '\0';
 					if (sp[0])	/* Don't output empty lines */
-						log(LOGOPT_ANY, ">> %s", sp);
+						warn(logopt, ">> %s", sp);
 					errp -= (p - sp);
 					sp = p;
 				}
@@ -206,7 +206,7 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c
 				if (errp >= ERRBUFSIZ) {
 					/* Line too long, split */
 					errbuf[errp] = '\0';
-					log(LOGOPT_ANY, ">> %s", errbuf);
+					warn(logopt, ">> %s", errbuf);
 					errp = 0;
 				}
 			}
@@ -217,7 +217,7 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c
 		if (errp > 0) {
 			/* End of file without \n */
 			errbuf[errp] = '\0';
-			log(LOGOPT_ANY, ">> %s", errbuf);
+			warn(logopt, ">> %s", errbuf);
 		}
 
 		if (waitpid(f, &ret, 0) != f)
@@ -235,12 +235,12 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c
 	}
 }
 
-int spawnv(logger *log, const char *prog, const char *const *argv)
+int spawnv(unsigned logopt, const char *prog, const char *const *argv)
 {
-	return do_spawn(log, SPAWN_OPT_NONE, prog, argv);
+	return do_spawn(logopt, SPAWN_OPT_NONE, prog, argv);
 }
 
-int spawnl(logger *log, const char *prog, ...)
+int spawnl(unsigned logopt, const char *prog, ...)
 {
 	va_list arg;
 	int argc;
@@ -258,10 +258,10 @@ int spawnl(logger *log, const char *prog, ...)
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
-	return do_spawn(log, SPAWN_OPT_NONE, prog, (const char **) argv);
+	return do_spawn(logopt, SPAWN_OPT_NONE, prog, (const char **) argv);
 }
 
-int spawn_mount(logger *log, ...)
+int spawn_mount(unsigned logopt, ...)
 {
 	va_list arg;
 	int argc;
@@ -279,7 +279,7 @@ int spawn_mount(logger *log, ...)
 	options = SPAWN_OPT_NONE;
 #endif
 
-	va_start(arg, log);
+	va_start(arg, logopt);
 	for (argc = 1; va_arg(arg, char *); argc++);
 	va_end(arg);
 
@@ -288,13 +288,13 @@ int spawn_mount(logger *log, ...)
 
 	argv[0] = arg0;
 
-	va_start(arg, log);
+	va_start(arg, logopt);
 	p = argv + 1;
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
 	while (retries--) {
-		ret = do_spawn(log, options, prog, (const char **) argv);
+		ret = do_spawn(logopt, options, prog, (const char **) argv);
 		if (ret & MTAB_NOTUPDATED)
 			continue;
 		break;
@@ -311,7 +311,7 @@ int spawn_mount(logger *log, ...)
  * NOTE: If mount locking is enabled this type of recursive mount cannot
  *	 work.
  */
-int spawn_bind_mount(logger *log, ...)
+int spawn_bind_mount(unsigned logopt, ...)
 {
 	va_list arg;
 	int argc;
@@ -330,7 +330,7 @@ int spawn_bind_mount(logger *log, ...)
 	options = SPAWN_OPT_ACCESS;
 #endif
 
-	va_start(arg, log);
+	va_start(arg, logopt);
 	for (argc = 1; va_arg(arg, char *); argc++);
 	va_end(arg);
 
@@ -340,13 +340,13 @@ int spawn_bind_mount(logger *log, ...)
 	argv[0] = arg0;
 	argv[1] = bind;
 
-	va_start(arg, log);
+	va_start(arg, logopt);
 	p = argv + 2;
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
 	while (retries--) {
-		ret = do_spawn(log, options, prog, (const char **) argv);
+		ret = do_spawn(logopt, options, prog, (const char **) argv);
 		if (ret & MTAB_NOTUPDATED)
 			continue;
 		break;
@@ -355,7 +355,7 @@ int spawn_bind_mount(logger *log, ...)
 	return ret;
 }
 
-int spawn_umount(logger *log, ...)
+int spawn_umount(unsigned logopt, ...)
 {
 	va_list arg;
 	int argc;
@@ -372,7 +372,7 @@ int spawn_umount(logger *log, ...)
 	options = SPAWN_OPT_NONE;
 #endif
 
-	va_start(arg, log);
+	va_start(arg, logopt);
 	for (argc = 1; va_arg(arg, char *); argc++);
 	va_end(arg);
 
@@ -381,13 +381,13 @@ int spawn_umount(logger *log, ...)
 
 	argv[0] = arg0;
 
-	va_start(arg, log);
+	va_start(arg, logopt);
 	p = argv + 1;
 	while ((*p++ = va_arg(arg, char *)));
 	va_end(arg);
 
 	while (retries--) {
-		ret = do_spawn(log, options, prog, (const char **) argv);
+		ret = do_spawn(logopt, options, prog, (const char **) argv);
 		if (ret & MTAB_NOTUPDATED)
 			continue;
 		break;
diff --git a/daemon/state.c b/daemon/state.c
index 39f4497..a2da762 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -58,22 +58,20 @@ void dump_state_queue(void)
 	struct list_head *head = &state_queue;
 	struct list_head *p, *q;
 
-	debug(LOGOPT_ANY, "dumping queue");
+	logmsg("dumping queue");
 
 	list_for_each(p, head) {
 		struct state_queue *entry;
 
 		entry = list_entry(p, struct state_queue, list);
-		debug(LOGOPT_ANY,
-		      "queue list head path %s state %d busy %d",
+		logmsg("queue list head path %s state %d busy %d",
 		      entry->ap->path, entry->state, entry->busy);
 
 		list_for_each(q, &entry->pending) {
 			struct state_queue *this;
 
 			this = list_entry(q, struct state_queue, pending);
-			debug(LOGOPT_ANY,
-			      "queue list entry path %s state %d busy %d",
+			logmsg("queue list entry path %s state %d busy %d",
 			      this->ap->path, this->state, this->busy);
 		}
 	}
@@ -85,7 +83,7 @@ void nextstate(int statefd, enum states next)
 
 	if (write(statefd, &next, sizeof(next)) != sizeof(next)) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(LOGOPT_ANY, "write failed %s", estr);
+		logerr("write failed %s", estr);
 	}
 }
 
diff --git a/include/automount.h b/include/automount.h
index d55ba5c..37a3c0a 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -131,6 +131,7 @@ struct mapent_cache {
 	unsigned int size;
 	pthread_mutex_t ino_index_mutex;
 	struct list_head *ino_index;
+	struct autofs_point *ap;
 	struct map_source *map;
 	struct mapent **hash;
 };
@@ -164,7 +165,7 @@ void cache_readlock(struct mapent_cache *mc);
 void cache_writelock(struct mapent_cache *mc);
 int cache_try_writelock(struct mapent_cache *mc);
 void cache_unlock(struct mapent_cache *mc);
-struct mapent_cache *cache_init(struct map_source *map);
+struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map);
 struct mapent_cache *cache_init_null_cache(struct master *master);
 int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino);
 /* void cache_set_ino(struct mapent *me, dev_t dev, ino_t ino); */
@@ -200,11 +201,11 @@ int free_argv(int argc, const char **argv);
 inline void dump_core(void);
 int aquire_lock(void);
 void release_lock(void);
-int spawnl(logger *log, const char *prog, ...);
-int spawnv(logger *log, const char *prog, const char *const *argv);
-int spawn_mount(logger *log, ...);
-int spawn_bind_mount(logger *log, ...);
-int spawn_umount(logger *log, ...);
+int spawnl(unsigned logopt, const char *prog, ...);
+int spawnv(unsigned logopt, const char *prog, const char *const *argv);
+int spawn_mount(unsigned logopt, ...);
+int spawn_bind_mount(unsigned logopt, ...);
+int spawn_umount(unsigned logopt, ...);
 void reset_signals(void);
 int do_mount(struct autofs_point *ap, const char *root, const char *name,
 	     int name_len, const char *what, const char *fstype,
@@ -222,6 +223,8 @@ 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,
@@ -435,6 +438,7 @@ struct autofs_point {
 	int pipefd;			/* File descriptor for pipe */
 	int kpipefd;			/* Kernel end descriptor for pipe */
 	int ioctlfd;			/* File descriptor for ioctls */
+	int logpri_fifo;		/* FIFO used for changing log levels */
 	dev_t dev;			/* "Device" number assigned by kernel */
 	struct master_mapent *entry;	/* Master map entry for this mount */
 	unsigned int type;		/* Type of map direct or indirect */
@@ -464,8 +468,8 @@ struct autofs_point {
 
 void *handle_mounts(void *arg);
 int umount_multi(struct autofs_point *ap, const char *path, int incl);
-int send_ready(int ioctlfd, unsigned int wait_queue_token);
-int send_fail(int ioctlfd, unsigned int wait_queue_token);
+int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token);
+int send_fail(unsigned logopt, int ioctlfd, unsigned int wait_queue_token);
 int do_expire(struct autofs_point *ap, const char *name, int namelen);
 void *expire_proc_indirect(void *);
 void *expire_proc_direct(void *);
@@ -483,8 +487,8 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_
 int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_direct_t *pkt);
 int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missing_indirect_t *pkt);
 int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_direct_t *pkt);
-void rm_unwanted(const char *path, int incl, dev_t dev);
-int count_mounts(const char *path, dev_t dev);
+void rm_unwanted(unsigned logopt, const char *path, int incl, dev_t dev);
+int count_mounts(unsigned logopt, const char *path, dev_t dev);
 
 #define state_mutex_lock(ap) \
 do { \
diff --git a/include/log.h b/include/log.h
index 3276cca..6a4a942 100644
--- a/include/log.h
+++ b/include/log.h
@@ -20,6 +20,7 @@
 /* Define logging functions */
 
 #define LOGOPT_NONE	0x0000
+#define LOGOPT_ERROR	0x0000
 #define LOGOPT_DEBUG	0x0001
 #define LOGOPT_VERBOSE	0x0002
 #define LOGOPT_ANY	(LOGOPT_DEBUG | LOGOPT_VERBOSE)
@@ -29,34 +30,33 @@ struct autofs_point;
 extern void set_log_norm(void);
 extern void set_log_verbose(void);
 extern void set_log_debug(void);
-extern void set_mnt_logging(struct autofs_point *);
+extern void set_log_norm_ap(struct autofs_point *ap);
+extern void set_log_verbose_ap(struct autofs_point *ap);
+extern void set_log_debug_ap(struct autofs_point *ap);
+extern void set_mnt_logging(unsigned global_logopt);
 
 extern void log_to_syslog(void);
 extern void log_to_stderr(void);
  
-typedef void logger(unsigned int logopt, const char* msg, ...);
-
-extern void (*log_info)(unsigned int, const char* msg, ...);
-extern void (*log_notice)(unsigned int, const char* msg, ...);
-extern void (*log_warn)(unsigned int, const char* msg, ...);
-extern void (*log_error)(unsigned int, const char* msg, ...);
-extern void (*log_crit)(unsigned int, const char* msg, ...);
-extern void (*log_debug)(unsigned int, const char* msg, ...);
-
-#define msg(msg, args...)	\
-	do { log_info(LOGOPT_NONE, msg, ##args); } while (0)
+extern void log_info(unsigned int, const char* msg, ...);
+extern void log_notice(unsigned int, const char* msg, ...);
+extern void log_warn(unsigned int, const char* msg, ...);
+extern void log_error(unsigned, const char* msg, ...);
+extern void log_crit(unsigned, const char* msg, ...);
+extern void log_debug(unsigned int, const char* msg, ...);
+extern void logmsg(const char* msg, ...);
 
 #define debug(opt, msg, args...)	\
 	do { log_debug(opt, "%s: " msg,  __FUNCTION__, ##args); } while (0)
 
-#define info(opt, msg, args...)	\
-	do { log_info(opt, "%s: " msg,  __FUNCTION__, ##args); } while (0)
+#define info(opt, msg, args...)		\
+	do { log_info(opt, msg,  ##args); } while (0)
 
 #define notice(opt, msg, args...)	\
-	do { log_notice(opt, "%s: " msg,  __FUNCTION__, ##args); } while (0)
+	do { log_notice(opt, msg, ##args); } while (0)
 
-#define warn(opt, msg, args...)	\
-	do { log_warn(opt, "%s: " msg,  __FUNCTION__, ##args); } while (0)
+#define warn(opt, msg, args...)		\
+	do { log_warn(opt, msg, ##args); } while (0)
 
 #define error(opt, msg, args...)	\
 	do { log_error(opt, "%s: " msg,  __FUNCTION__, ##args); } while (0)
@@ -64,17 +64,18 @@ extern void (*log_debug)(unsigned int, const char* msg, ...);
 #define crit(opt, msg, args...)	\
 	do { log_crit(opt, "%s: " msg,  __FUNCTION__, ##args); } while (0)
 
+#define logerr(msg, args...)	\
+	do { logmsg("%s:%d: " msg, __FUNCTION__, __LINE__, ##args); } while (0)
+
 #define fatal(status)						    \
 	do {							    \
 		if (status == EDEADLK) {			    \
-			log_crit(LOGOPT_ANY,			    \
-				 "%s: deadlock detected "	    \
+			logmsg("deadlock detected "		    \
 				 "at line %d in %s, dumping core.", \
-				 __FUNCTION__, __LINE__, __FILE__); \
+				  __LINE__, __FILE__);		    \
 			dump_core();				    \
 		}						    \
-		log_crit(LOGOPT_ANY,				    \
-			 "unexpected pthreads error: %d at %d "	    \
+		logmsg("unexpected pthreads error: %d at %d "	    \
 			 "in %s", status, __LINE__, __FILE__);	    \
 		abort();					    \
 	} while(0)
@@ -83,7 +84,7 @@ extern void (*log_debug)(unsigned int, const char* msg, ...);
 #define assert(x)							\
 do {									\
 	if (!(x)) {							\
-		log_crit(LOGOPT_ANY, __FILE__				\
+		logmsg(__FILE__					\
 			 ":%d: assertion failed: " #x, __LINE__);	\
 	}								\
 } while(0)
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index ca8d658..5b5c475 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -94,13 +94,13 @@ struct lookup_context {
 #define LDAP_AUTH_AUTODETECT	0x0004
 
 /* lookup_ldap.c */
-LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt);
-int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt);
+LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt);
+int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt);
 int authtype_requires_creds(const char *authtype);
 
 /* cyrus-sasl.c */
-int autofs_sasl_init(LDAP *ldap, struct lookup_context *ctxt);
-int autofs_sasl_bind(LDAP *ldap, struct lookup_context *ctxt);
+int autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt);
+int autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt);
 void autofs_sasl_unbind(struct lookup_context *ctxt);
 void autofs_sasl_done(struct lookup_context *ctxt);
 #endif
diff --git a/include/master.h b/include/master.h
index 8470bb1..5f10d1f 100644
--- a/include/master.h
+++ b/include/master.h
@@ -62,6 +62,7 @@ struct master {
 	unsigned int default_ghost;
 	unsigned int default_logging;
 	unsigned int default_timeout;
+	unsigned int logopt;
 	struct mapent_cache *nc;
 	struct list_head mounts;
 };
@@ -106,6 +107,7 @@ int master_notify_submount(struct autofs_point *, const char *path, enum states)
 void master_signal_submount(struct autofs_point *, unsigned int);
 void master_notify_state_change(struct master *, int);
 int master_mount_mounts(struct master *, time_t, int);
+extern inline unsigned int master_get_logopt(void);
 int master_list_empty(struct master *);
 int master_kill(struct master *);
 
diff --git a/include/replicated.h b/include/replicated.h
index 3afe9f7..672f853 100644
--- a/include/replicated.h
+++ b/include/replicated.h
@@ -62,8 +62,8 @@ 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 *, unsigned int);
+int parse_location(unsigned, struct host **, const char *);
+int prune_host_list(unsigned, struct host **, unsigned int, const char *, unsigned int);
 void dump_host_list(struct host *);
 
 #endif
diff --git a/lib/alarm.c b/lib/alarm.c
index 90bf7aa..6a70ed1 100755
--- a/lib/alarm.c
+++ b/lib/alarm.c
@@ -51,7 +51,7 @@ void dump_alarms(void)
 		struct alarm *this;
 
 		this = list_entry(p, struct alarm, list);
-		msg("alarm time = %d", this->time);
+		logmsg("alarm time = %d", this->time);
 	}
 	pthread_mutex_unlock(&mutex);
 }
diff --git a/lib/args.c b/lib/args.c
index fbfb004..9616598 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -37,7 +37,7 @@ char **add_argv(int argc, char **argv, char *str)
 		if (argv[i]) {
 			vector[i] = strdup(argv[i]);
 			if (!vector[i]) {
-				error(LOGOPT_ANY, "failed to strdup arg");
+				logerr("failed to strdup arg");
 				break;
 			}
 		} else
@@ -81,7 +81,7 @@ char **append_argv(int argc1, char **argv1, int argc2, char **argv2)
 		if (argv2[j]) {
 			vector[i] = strdup(argv2[j]);
 			if (!vector[i]) {
-				error(LOGOPT_ANY, "failed to strdup arg");
+				logerr("failed to strdup arg");
 				break;
 			}
 		} else
@@ -116,7 +116,7 @@ const char **copy_argv(int argc, const char **argv)
 		if (argv[i]) {
 			vector[i] = strdup(argv[i]);
 			if (!vector[i]) {
-				error(LOGOPT_ANY, "failed to strdup arg");
+				logerr("failed to strdup arg");
 				break;
 			}
 		} else
diff --git a/lib/cache.c b/lib/cache.c
index 06bb461..55586a3 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -34,7 +34,7 @@ void cache_dump_multi(struct list_head *list)
 
 	list_for_each(p, list) {
 		me = list_entry(p, struct mapent, multi_list);
-		msg("key=%s", me->key);
+		logmsg("key=%s", me->key);
 	}
 }
 
@@ -48,7 +48,7 @@ void cache_dump_cache(struct mapent_cache *mc)
 		if (me == NULL)
 			continue;
 		while (me) {
-			msg("me->key=%s me->multi=%p dev=%ld ino=%ld",
+			logmsg("me->key=%s me->multi=%p dev=%ld ino=%ld",
 				me->key, me->multi, me->dev, me->ino);
 			me = me->next;
 		}
@@ -61,7 +61,7 @@ void cache_readlock(struct mapent_cache *mc)
 
 	status = pthread_rwlock_rdlock(&mc->rwlock);
 	if (status) {
-		error(LOGOPT_ANY, "mapent cache rwlock lock failed");
+		logmsg("mapent cache rwlock lock failed");
 		fatal(status);
 	}
 	return;
@@ -73,7 +73,7 @@ void cache_writelock(struct mapent_cache *mc)
 
 	status = pthread_rwlock_wrlock(&mc->rwlock);
 	if (status) {
-		error(LOGOPT_ANY, "mapent cache rwlock lock failed");
+		logmsg("mapent cache rwlock lock failed");
 		fatal(status);
 	}
 	return;
@@ -85,7 +85,7 @@ int cache_try_writelock(struct mapent_cache *mc)
 
 	status = pthread_rwlock_trywrlock(&mc->rwlock);
 	if (status) {
-		debug(LOGOPT_ANY, "mapent cache rwlock busy");
+		logmsg("mapent cache rwlock busy");
 		return 0;
 	}
 	return 1;
@@ -97,7 +97,7 @@ void cache_unlock(struct mapent_cache *mc)
 
 	status = pthread_rwlock_unlock(&mc->rwlock);
 	if (status) {
-		error(LOGOPT_ANY, "mapent cache rwlock unlock failed");
+		logmsg("mapent cache rwlock unlock failed");
 		fatal(status);
 	}
 	return;
@@ -120,7 +120,7 @@ void cache_multi_lock(struct mapent *me)
 
 	status = pthread_mutex_lock(&me->multi_mutex);
 	if (status) {
-		error(LOGOPT_ANY, "mapent cache multi mutex lock failed");
+		logmsg("mapent cache multi mutex lock failed");
 		fatal(status);
 	}
 	return;
@@ -135,7 +135,7 @@ void cache_multi_unlock(struct mapent *me)
 
 	status = pthread_mutex_unlock(&me->multi_mutex);
 	if (status) {
-		error(LOGOPT_ANY, "mapent cache multi mutex unlock failed");
+		logmsg("mapent cache multi mutex unlock failed");
 		fatal(status);
 	}
 	return;
@@ -164,7 +164,7 @@ static inline void ino_index_unlock(struct mapent_cache *mc)
 	return;
 }
 
-struct mapent_cache *cache_init(struct map_source *map)
+struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map)
 {
 	struct mapent_cache *mc;
 	unsigned int i;
@@ -207,6 +207,7 @@ struct mapent_cache *cache_init(struct map_source *map)
 		INIT_LIST_HEAD(&mc->ino_index[i]);
 	}
 
+	mc->ap = ap;
 	mc->map = map;
 
 	cache_unlock(mc);
@@ -257,6 +258,9 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
 		INIT_LIST_HEAD(&mc->ino_index[i]);
 	}
 
+	mc->ap = NULL;
+	mc->map = NULL;
+
 	cache_unlock(mc);
 
 	return mc;
@@ -608,6 +612,7 @@ static void cache_add_ordered_offset(struct mapent *me, struct list_head *head)
 /* cache must be write locked by caller */
 int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age)
 {
+	unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt();
 	struct mapent *me, *owner;
 	int ret = CHE_OK;
 
@@ -621,7 +626,7 @@ int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key,
 
 	ret = cache_add(mc, owner->source, key, mapent, age);
 	if (ret == CHE_FAIL) {
-		warn(LOGOPT_ANY, "failed to add key %s to cache", key);
+		warn(logopt, "failed to add key %s to cache", key);
 		return CHE_FAIL;
 	}
 
@@ -689,6 +694,7 @@ int cache_set_parents(struct mapent *mm)
 /* cache must be write locked by caller */
 int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age)
 {
+	unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt();
 	struct mapent *me = NULL;
 	char *pent;
 	int ret = CHE_OK;
@@ -697,7 +703,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
 	if (!me || (*me->key == '*' && *key != '*')) {
 		ret = cache_add(mc, ms, key, mapent, age);
 		if (!ret) {
-			debug(LOGOPT_NONE, "failed for %s", key);
+			debug(logopt, "failed for %s", key);
 			return CHE_FAIL;
 		}
 		ret = CHE_UPDATED;
@@ -796,6 +802,7 @@ done:
 /* cache must be write locked by caller */
 int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
 {
+	unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt();
 	struct mapent *me;
 	struct mapent *this;
 	struct list_head *head, *next;
@@ -816,7 +823,7 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
 		this = list_entry(next, struct mapent, multi_list);
 		next = next->next;
 		if (this->ioctlfd != -1) {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      "active offset mount key %s", this->key);
 			return CHE_FAIL;
 		}
@@ -829,10 +836,10 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key)
 		next = next->next;
 		list_del_init(&this->multi_list);
 		this->multi = NULL;
-		debug(LOGOPT_NONE, "deleting offset key %s", this->key);
+		debug(logopt, "deleting offset key %s", this->key);
 		status = cache_delete(mc, this->key);
 		if (status == CHE_FAIL) {
-			warn(LOGOPT_ANY,
+			warn(logopt,
 			     "failed to delete offset %s", this->key);
 			this->multi = me;
 			/* TODO: add list back in */
diff --git a/lib/defaults.c b/lib/defaults.c
index 2cccf20..94885e8 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -105,17 +105,22 @@ static int get_env_yesno(const char *name)
  * We've changed the key names so we need to check for the
  * config key and it's old name for backward conpatibility.
 */
-static int check_set_config_value(const char *res, const char *name, const char *value)
+static int check_set_config_value(const char *res, const char *name, const char *value, unsigned to_syslog)
 {
 	char *old_name;
 	int ret;
 
 	if (!strcasecmp(res, name)) {
 		ret = setenv(name, value, 0);
-		if (ret)
-			fprintf(stderr,
-			        "can't set config value for %s, "
-				"error %d", name, ret);
+		if (ret) {
+			if (!to_syslog)
+				fprintf(stderr,
+				        "can't set config value for %s, "
+					"error %d\n", name, ret);
+			else
+				logmsg("can't set config value for %s, "
+				      "error %d", name, ret);
+		}
 		return 1;
 	}
 
@@ -125,10 +130,15 @@ static int check_set_config_value(const char *res, const char *name, const char
 
 	if (!strcasecmp(res, old_name)) {
 		ret = setenv(name, value, 0);
-		if (ret)
-			fprintf(stderr,
-			        "can't set config value for %s, "
-				"error %d", name, ret);
+		if (ret) {
+			if (!to_syslog)
+				fprintf(stderr,
+				        "can't set config value for %s, "
+					"error %d\n", name, ret);
+			else
+				logmsg("can't set config value for %s, "
+				      "error %d\n", name, ret);
+		}
 		return 1;
 	}
 	return 0;
@@ -296,19 +306,19 @@ unsigned int defaults_read_config(unsigned int to_syslog)
 		if (!parse_line(res, &key, &value))
 			continue;
 
-		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_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) ||
-		    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))
+		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_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) ||
+		    check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value, to_syslog) ||
+		    check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value, to_syslog) ||
+		    check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value, to_syslog) ||
+		    check_set_config_value(key, ENV_NAME_MAP_ATTR, value, to_syslog) ||
+		    check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value, to_syslog) ||
+		    check_set_config_value(key, ENV_NAME_VALUE_ATTR, value, to_syslog) ||
+		    check_set_config_value(key, ENV_APPEND_OPTIONS, value, to_syslog) ||
+		    check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog))
 			;
 	}
 
@@ -318,8 +328,7 @@ unsigned int defaults_read_config(unsigned int to_syslog)
 				"fgets returned error %d while reading %s\n",
 				ferror(f), DEFAULTS_CONFIG_FILE);
 		} else {
-			error(LOGOPT_ANY,
-			      "fgets returned error %d while reading %s",
+			logmsg("fgets returned error %d while reading %s",
 			      ferror(f), DEFAULTS_CONFIG_FILE);
 		}
 		fclose(f);
diff --git a/lib/log.c b/lib/log.c
index b747e12..65e8ad2 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -27,11 +27,6 @@
 
 #include "automount.h"
 
-/*
-struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT;
-struct syslog_data *slc = &syslog_context;
-*/
-
 static unsigned int syslog_open = 0;
 static unsigned int logging_to_syslog = 0;
 
@@ -39,32 +34,44 @@ static unsigned int logging_to_syslog = 0;
 static unsigned int do_verbose = 0;		/* Verbose feedback option */
 static unsigned int do_debug = 0;		/* Full debug output */
 
-static void null(unsigned int logopt, const char *msg, ...) { }
-
-void (*log_info)(unsigned int logopt, const char* msg, ...) = null;
-void (*log_notice)(unsigned int logopt, const char* msg, ...) = null;
-void (*log_warn)(unsigned int logopt, const char* msg, ...) = null;
-void (*log_error)(unsigned int logopt, const char* msg, ...) = null;
-void (*log_crit)(unsigned int logopt, const char* msg, ...) = null;
-void (*log_debug)(unsigned int logopt, const char* msg, ...) = null;
-
 void set_log_norm(void)
 {
 	do_verbose = 0;
 	do_debug = 0;
+	return;
 }
 
 void set_log_verbose(void)
 {
 	do_verbose = 1;
+	return;
 }
 
 void set_log_debug(void)
 {
 	do_debug = 1;
+	return;
+}
+
+void set_log_norm_ap(struct autofs_point *ap)
+{
+	ap->logopt = LOGOPT_ERROR;
+	return;
+}
+
+void set_log_verbose_ap(struct autofs_point *ap)
+{
+	ap->logopt = LOGOPT_VERBOSE;
+	return;
+}
+
+void set_log_debug_ap(struct autofs_point *ap)
+{
+	ap->logopt = LOGOPT_DEBUG;
+	return;
 }
 
-static void syslog_info(unsigned int logopt, const char *msg, ...)
+void log_info(unsigned int logopt, const char *msg, ...)
 {
 	unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE);
 	va_list ap;
@@ -73,11 +80,18 @@ static void syslog_info(unsigned int logopt, const char *msg, ...)
 		return;
 
 	va_start(ap, msg);
-	vsyslog(LOG_INFO, msg, ap);
+	if (logging_to_syslog)
+		vsyslog(LOG_INFO, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
+	}
 	va_end(ap);
+
+	return;
 }
 
-static void syslog_notice(unsigned int logopt, const char *msg, ...)
+void log_notice(unsigned int logopt, const char *msg, ...)
 {
 	unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE);
 	va_list ap;
@@ -86,11 +100,18 @@ static void syslog_notice(unsigned int logopt, const char *msg, ...)
 		return;
 
 	va_start(ap, msg);
-	vsyslog(LOG_NOTICE, msg, ap);
+	if (logging_to_syslog)
+		vsyslog(LOG_NOTICE, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
+	}
 	va_end(ap);
+
+	return;
 }
 
-static void syslog_warn(unsigned int logopt, const char *msg, ...)
+void log_warn(unsigned int logopt, const char *msg, ...)
 {
 	unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE);
 	va_list ap;
@@ -99,70 +120,79 @@ static void syslog_warn(unsigned int logopt, const char *msg, ...)
 		return;
 
 	va_start(ap, msg);
-	vsyslog(LOG_WARNING, msg, ap);
+	if (logging_to_syslog)
+		vsyslog(LOG_WARNING, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
+	}
 	va_end(ap);
+
+	return;
 }
 
-static void syslog_err(unsigned int logopt, const char *msg, ...)
+void log_error(unsigned logopt, const char *msg, ...)
 {
 	va_list ap;
+
 	va_start(ap, msg);
-	vsyslog(LOG_ERR, msg, ap);
+	if (logging_to_syslog)
+		vsyslog(LOG_ERR, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
+	}
 	va_end(ap);
+	return;
 }
 
-static void syslog_crit(unsigned int logopt, const char *msg, ...)
+void log_crit(unsigned logopt, const char *msg, ...)
 {
 	va_list ap;
+
 	va_start(ap, msg);
-	vsyslog(LOG_CRIT, msg, ap);
+	if (logging_to_syslog)
+		vsyslog(LOG_CRIT, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
+	}
 	va_end(ap);
+	return;
 }
 
-static void syslog_debug(unsigned int logopt, const char *msg, ...)
+void log_debug(unsigned int logopt, const char *msg, ...)
 {
+	unsigned int opt_log = logopt & LOGOPT_DEBUG;
 	va_list ap;
 
-	if (!do_debug && !(logopt & LOGOPT_DEBUG))
+	if (!do_debug && !opt_log)
 		return;
 
 	va_start(ap, msg);
-	vsyslog(LOG_DEBUG, msg, ap);
+	if (logging_to_syslog)
+		vsyslog(LOG_WARNING, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
+	}
 	va_end(ap);
+
+	return;
 }
 
-static void to_stderr(unsigned int logopt, const char *msg, ...)
+void logmsg(const char *msg, ...)
 {
 	va_list ap;
 	va_start(ap, msg);
-	vfprintf(stderr, msg, ap);
-	fputc('\n',stderr);
-	va_end(ap);
-}
-
-void set_mnt_logging(struct autofs_point *ap)
-{
-	unsigned int opt_verbose = ap->logopt & LOGOPT_VERBOSE;
-	unsigned int opt_debug = ap->logopt & LOGOPT_DEBUG;
-
-	if (opt_debug) {
-		if (logging_to_syslog)
-			log_debug = syslog_debug;
-		else
-			log_debug = to_stderr;
-	}
-
-	if (opt_verbose || opt_debug) {
-		if (logging_to_syslog) {
-			log_info = syslog_info;
-			log_notice = syslog_notice;
-			log_warn = syslog_warn;
-		} else {
-			log_info = to_stderr;
-			log_notice = to_stderr;
-			log_warn = to_stderr;
-		}
+	if (logging_to_syslog)
+		vsyslog(LOG_CRIT, msg, ap);
+	else {
+		vfprintf(stderr, msg, ap);
+		fputc('\n', stderr);
 	}
+	va_end(ap);
+	return;
 }
 
 void log_to_syslog(void)
@@ -175,31 +205,13 @@ void log_to_syslog(void)
 		openlog("automount", LOG_PID, LOG_DAEMON);
 	}
 
-	if (do_debug)
-		log_debug = syslog_debug;
-	else
-		log_debug = null;
-
-	if (do_verbose || do_debug) {
-		log_info = syslog_info;
-		log_notice = syslog_notice;
-		log_warn = syslog_warn;
-	} else {
-		log_info = null;
-		log_notice = null;
-		log_warn = null;
-	}
-
-	log_error = syslog_err;
-	log_crit = syslog_crit;
-
 	logging_to_syslog = 1;
 
 	/* Redirect all our file descriptors to /dev/null */
 	nullfd = open("/dev/null", O_RDWR);
 	if (nullfd < 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		syslog_crit(LOGOPT_ANY, "cannot open /dev/null: %s", estr);
+		fprintf(stderr, "cannot open /dev/null: %s", estr);
 		exit(1);
 	}
 
@@ -207,13 +219,15 @@ void log_to_syslog(void)
 	    dup2(nullfd, STDOUT_FILENO) < 0 ||
 	    dup2(nullfd, STDERR_FILENO) < 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		syslog_crit(LOGOPT_ANY,
-			    "redirecting file descriptors failed: %s", estr);
+		fprintf(stderr,
+			"redirecting file descriptors failed: %s", estr);
 		exit(1);
 	}
 
 	if (nullfd > 2)
 		close(nullfd);
+
+	return;
 }
 
 void log_to_stderr(void)
@@ -223,23 +237,7 @@ void log_to_stderr(void)
 		closelog();
 	}
 
-	if (do_debug)
-		log_debug = to_stderr;
-	else
-		log_debug = null;
-
-	if (do_verbose || do_debug) {
-		log_info = to_stderr;
-		log_notice = to_stderr;
-		log_warn = to_stderr;
-	} else {
-		log_info = null;
-		log_notice = null;
-		log_warn = null;
-	}
-
-	log_error = to_stderr;
-	log_crit = to_stderr;
-
 	logging_to_syslog = 0;
+
+	return;
 }
diff --git a/lib/macros.c b/lib/macros.c
index 936ae06..fa6db8e 100644
--- a/lib/macros.c
+++ b/lib/macros.c
@@ -50,8 +50,7 @@ void dump_table(struct substvar *table)
 		fatal(status);
 
 	while (lv) {
-		debug(LOGOPT_NONE,
-		      "lv->def %s lv->val %s lv->next %p",
+		logmsg("lv->def %s lv->val %s lv->next %p",
 		      lv->def, lv->val, lv->next);
 		lv = lv->next;
 	}
diff --git a/lib/master.c b/lib/master.c
index abc3bc2..2e24ad0 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -524,8 +524,7 @@ void master_source_writelock(struct master_mapent *entry)
 
 	status = pthread_rwlock_wrlock(&entry->source_lock);
 	if (status) {
-		error(LOGOPT_ANY,
-		      "master_mapent source write lock failed");
+		logmsg("master_mapent source write lock failed");
 		fatal(status);
 	}
 	return;
@@ -537,8 +536,7 @@ void master_source_readlock(struct master_mapent *entry)
 
 	status = pthread_rwlock_rdlock(&entry->source_lock);
 	if (status) {
-		error(LOGOPT_ANY,
-		      "master_mapent source read lock failed");
+		logmsg("master_mapent source read lock failed");
 		fatal(status);
 	}
 	return;
@@ -550,8 +548,7 @@ void master_source_unlock(struct master_mapent *entry)
 
 	status = pthread_rwlock_unlock(&entry->source_lock);
 	if (status) {
-		error(LOGOPT_ANY,
-		      "master_mapent source unlock failed");
+		logmsg("master_mapent source unlock failed");
 		fatal(status);
 	}
 	return;
@@ -572,7 +569,7 @@ void master_source_current_wait(struct master_mapent *entry)
 
 	status = pthread_mutex_lock(&entry->current_mutex);
 	if (status) {
-		error(LOGOPT_ANY, "entry current source lock failed");
+		logmsg("entry current source lock failed");
 		fatal(status);
 	}
 
@@ -580,8 +577,7 @@ void master_source_current_wait(struct master_mapent *entry)
 		status = pthread_cond_wait(
 				&entry->current_cond, &entry->current_mutex);
 		if (status) {
-			error(LOGOPT_ANY,
-			      "entry current source condition wait failed");
+			logmsg("entry current source condition wait failed");
 			fatal(status);
 		}
 	}
@@ -595,14 +591,13 @@ void master_source_current_signal(struct master_mapent *entry)
 
 	status = pthread_cond_signal(&entry->current_cond);
 	if (status) {
-		error(LOGOPT_ANY,
-		      "entry current source condition signal failed");
+		logmsg("entry current source condition signal failed");
 		fatal(status);
 	}
 
 	status = pthread_mutex_unlock(&entry->current_mutex);
 	if (status) {
-		error(LOGOPT_ANY, "entry current source unlock failed");
+		logmsg("entry current source unlock failed");
 		fatal(status);
 	}
 
@@ -770,6 +765,7 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g
 	master->default_ghost = ghost;
 	master->default_timeout = timeout;
 	master->default_logging = defaults_get_logging();
+	master->logopt = master->default_logging;
 
 	INIT_LIST_HEAD(&master->mounts);
 
@@ -778,11 +774,12 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g
 
 int master_read_master(struct master *master, time_t age, int readall)
 {
+	unsigned int logopt = master->logopt;
 	struct mapent_cache *nc;
 
 	nc = cache_init_null_cache(master);
 	if (!nc) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      "failed to init null map cache for %s", master->name);
 		return 0;
 	}
@@ -791,7 +788,7 @@ int master_read_master(struct master *master, time_t age, int readall)
 	master_init_scan();
 
 	if (!lookup_nss_read_master(master, age)) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      "can't read master map %s", master->name);
 		return 0;
 	}
@@ -802,7 +799,7 @@ int master_read_master(struct master *master, time_t age, int readall)
 
 	if (list_empty(&master->mounts)) {
 		master_mutex_unlock();
-		warn(LOGOPT_ANY, "no mounts in table");
+		warn(logopt, "no mounts in table");
 		return 1;
 	}
 
@@ -934,6 +931,7 @@ void master_notify_state_change(struct master *master, int sig)
 	struct autofs_point *ap;
 	struct list_head *p;
 	int state_pipe, cur_state;
+	unsigned int logopt;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	master_mutex_lock();
@@ -944,6 +942,7 @@ void master_notify_state_change(struct master *master, int sig)
 		entry = list_entry(p, struct master_mapent, list);
 
 		ap = entry->ap;
+		logopt = ap->logopt;
 
 		state_mutex_lock(ap);
 
@@ -978,7 +977,7 @@ void master_notify_state_change(struct master *master, int sig)
 		}
 next:
 		if (next != ST_INVAL)
-			debug(ap->logopt,
+			debug(logopt,
 			      "sig %d switching %s from %d to %d",
 			      sig, ap->path, ap->state, next);
 
@@ -1230,6 +1229,11 @@ int master_list_empty(struct master *master)
 	return res;
 }
 
+inline unsigned int master_get_logopt(void)
+{
+	return master_list ? master_list->logopt : LOGOPT_NONE;
+}
+
 int master_kill(struct master *master)
 {
 	if (!list_empty(&master->mounts))
@@ -1251,6 +1255,6 @@ void dump_master(struct master *master)
 	head = &master->mounts;
 	list_for_each(p, head) {
 		struct master_mapent *this = list_entry(p, struct master_mapent, list);
-		debug(LOGOPT_ANY, "path %s", this->path);
+		logmsg("path %s", this->path);
 	}
 }
diff --git a/lib/master_parse.y b/lib/master_parse.y
index 70b48be..a767f9e 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -585,13 +585,13 @@ static char *master_strdup(char *str)
 
 static int master_error(const char *s)
 {
-	error(LOGOPT_ANY, "%s while parsing map.", s);
+	logmsg("%s while parsing map.", s);
 	return 0;
 }
 
 static int master_notify(const char *s)
 {
-	warn(LOGOPT_ANY, "syntax error in map near [ %s ]", s);
+	logmsg("syntax error in map near [ %s ]", s);
 	return(0);
 }
 
@@ -704,6 +704,7 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 	struct master_mapent *entry, *new;
 	struct map_source *source;
 	unsigned int logopt = logging;
+	unsigned int m_logopt = master->logopt;
 	int ret;
 
 	local_init_vars();
@@ -758,8 +759,8 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 	} else {
 		if (entry->age && entry->age == age) {
 			if (strcmp(path, "/-")) {
-				warn(LOGOPT_VERBOSE,
-				     "ignoring duplicate indirect mount %s",
+				info(m_logopt,
+				    "ignoring duplicate indirect mount %s",
 				     path);
 				local_free_vars();
 				return 0;
@@ -770,13 +771,12 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 	if (!entry->ap) {
 		ret = master_add_autofs_point(entry, timeout, logopt, ghost, 0);
 		if (!ret) {
-			error(LOGOPT_ANY, "failed to add autofs_point");
+			error(m_logopt, "failed to add autofs_point");
 			if (new)
 				master_free_mapent(new);
 			local_free_vars();
 			return 0;
 		}
-		set_mnt_logging(entry->ap);
 	} else {
 		struct autofs_point *ap = entry->ap;
 		time_t tout = timeout;
@@ -786,14 +786,11 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 		 * use the ghost, log and timeout of the first
 		 */
 		if (entry->age < age) {
-			ap->ghost = ghost;
-			ap->logopt = logopt;
 			ap->exp_timeout = timeout;
 			ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO;
 			if (ap->ioctlfd != -1 && ap->type == LKP_INDIRECT)
 				ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout);
 		}
-		set_mnt_logging(ap);
 	}
 	entry->ap->random_selection = random_selection;
 
@@ -809,7 +806,7 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 	source = master_add_map_source(entry, type, format, age, 
 					local_argc, (const char **) local_argv);
 	if (!source) {
-		error(LOGOPT_ANY, "failed to add source");
+		error(m_logopt, "failed to add source");
 		if (new)
 			master_free_mapent(new);
 		local_free_vars();
@@ -817,9 +814,9 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne
 	}
 
 	if (!source->mc) {
-		source->mc = cache_init(source);
+		source->mc = cache_init(entry->ap, source);
 		if (!source->mc) {
-			error(LOGOPT_ANY, "failed to init source cache");
+			error(m_logopt, "failed to init source cache");
 			if (new)
 				master_free_mapent(new);
 			local_free_vars();
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 2735223..00cd223 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -368,7 +368,7 @@ int master_wrap(void)
 
 static void master_echo(void)
 {
-	debug(LOGOPT_NONE, "%s", master_text);
+	logmsg("%s", master_text);
 	return;
 }
 
diff --git a/lib/mounts.c b/lib/mounts.c
index 0e428e8..425a65a 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -126,7 +126,7 @@ char *make_options_string(char *path, int pipefd, char *extra)
 
 	options = malloc(MAX_OPTIONS_LEN + 1);
 	if (!options) {
-		crit(LOGOPT_ANY, "can't malloc options string");
+		logerr("can't malloc options string");
 		return NULL;
 	}
 
@@ -141,13 +141,12 @@ char *make_options_string(char *path, int pipefd, char *extra)
 			AUTOFS_MAX_PROTO_VERSION);
 
 	if (len >= MAX_OPTIONS_LEN) {
-		crit(LOGOPT_ANY, "buffer to small for options - truncated");
+		logerr("buffer to small for options - truncated");
 		len = MAX_OPTIONS_LEN - 1;
 	}
 
 	if (len < 0) {
-		crit(LOGOPT_ANY,
-		     "failed to malloc autofs mount options for %s", path);
+		logerr("failed to malloc autofs mount options for %s", path);
 		free(options);
 		return NULL;
 	}
@@ -163,7 +162,7 @@ char *make_mnt_name_string(char *path)
 
 	mnt_name = malloc(MAX_MNT_NAME_LEN + 1);
 	if (!mnt_name) {
-		crit(LOGOPT_ANY, "can't malloc mnt_name string");
+		logerr("can't malloc mnt_name string");
 		return NULL;
 	}
 
@@ -171,13 +170,12 @@ char *make_mnt_name_string(char *path)
 			mnt_name_template, (unsigned) getpid());
 
 	if (len >= MAX_MNT_NAME_LEN) {
-		crit(LOGOPT_ANY, "buffer to small for mnt_name - truncated");
+		logerr("buffer to small for mnt_name - truncated");
 		len = MAX_MNT_NAME_LEN - 1;
 	}
 
 	if (len < 0) {
-		crit(LOGOPT_ANY,
-		     "failed setting up mnt_name for autofs path %s", path);
+		logerr("failed setting up mnt_name for autofs path %s", path);
 		free(mnt_name);
 		return NULL;
 	}
@@ -207,7 +205,7 @@ struct mnt_list *get_mnt_list(const char *table, const char *path, int include)
 	tab = setmntent(table, "r");
 	if (!tab) {
 		char *estr = strerror_r(errno, buf, PATH_MAX - 1);
-		error(LOGOPT_ANY, "setmntent: %s", estr);
+		logerr("setmntent: %s", estr);
 		return NULL;
 	}
 
@@ -398,7 +396,7 @@ int is_mounted(const char *table, const char *path, unsigned int type)
 	tab = setmntent(table, "r");
 	if (!tab) {
 		char *estr = strerror_r(errno, buf, PATH_MAX - 1);
-		error(LOGOPT_ANY, "setmntent: %s", estr);
+		logerr("setmntent: %s", estr);
 		return 0;
 	}
 
@@ -443,7 +441,7 @@ int has_fstab_option(const char *opt)
 	tab = setmntent(_PATH_MNTTAB, "r");
 	if (!tab) {
 		char *estr = strerror_r(errno, buf, PATH_MAX - 1);
-		error(LOGOPT_ANY, "setmntent: %s", estr);
+		logerr("setmntent: %s", estr);
 		return 0;
 	}
 
@@ -471,7 +469,7 @@ char *find_mnt_ino(const char *table, dev_t dev, ino_t ino)
 	tab = setmntent(table, "r");
 	if (!tab) {
 		char *estr = strerror_r(errno, buf, (size_t) PATH_MAX - 1);
-		error(LOGOPT_ANY, "setmntent: %s", estr);
+		logerr("setmntent: %s", estr);
 		return 0;
 	}
 
@@ -667,7 +665,7 @@ struct mnt_list *tree_make_mnt_tree(const char *table, const char *path)
 	tab = setmntent(table, "r");
 	if (!tab) {
 		char *estr = strerror_r(errno, buf, PATH_MAX - 1);
-		error(LOGOPT_ANY, "setmntent: %s", estr);
+		logerr("setmntent: %s", estr);
 		return NULL;
 	}
 
diff --git a/lib/nss_parse.y b/lib/nss_parse.y
index e559696..90b7d25 100644
--- a/lib/nss_parse.y
+++ b/lib/nss_parse.y
@@ -127,13 +127,13 @@ status_exp: STATUS EQUAL ACTION
 
 static int nss_ignore(const char *s)
 {
-	msg("ignored invalid nsswitch config near [ %s ]", s);
+	logmsg("ignored invalid nsswitch config near [ %s ]", s);
 	return(0);
 }
 
 static int nss_error(const char *s)
 {
-	msg("syntax error in nsswitch config near [ %s ]\n", s);
+	logmsg("syntax error in nsswitch config near [ %s ]\n", s);
 	return(0);
 }
 
@@ -167,7 +167,7 @@ int nsswitch_parse(struct list_head *list)
 
 	nsswitch = fopen(NSSWITCH_FILE, "r");
 	if (!nsswitch) {
-		error(LOGOPT_ANY, "couldn't open %s\n", NSSWITCH_FILE);
+		logerr("couldn't open %s\n", NSSWITCH_FILE);
 		return 1;
 	}
 
diff --git a/lib/nss_tok.l b/lib/nss_tok.l
index f96b47f..c435b63 100644
--- a/lib/nss_tok.l
+++ b/lib/nss_tok.l
@@ -135,6 +135,6 @@ int nss_wrap(void)
 
 static void nss_echo(void)
 {
-	msg("%s", nss_text);
+	logmsg("%s", nss_text);
 	return;
 }
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
index 3627f44..5422fef 100644
--- a/lib/parse_subs.c
+++ b/lib/parse_subs.c
@@ -337,9 +337,9 @@ int umount_ent(struct autofs_point *ap, const char *path)
 	 * and EBADSLT relates to CD changer not responding.
 	 */
 	if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
-		rv = spawn_umount(log_debug, path, NULL);
+		rv = spawn_umount(ap->logopt, path, NULL);
 	} else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
-		rv = spawn_umount(log_debug, path, NULL);
+		rv = spawn_umount(ap->logopt, path, NULL);
 	}
 
 	/* We are doing a forced shutcwdown down so unlink busy mounts */
@@ -356,8 +356,8 @@ int umount_ent(struct autofs_point *ap, const char *path)
 		}
 
 		if (ap->state == ST_SHUTDOWN_FORCE) {
-			msg("forcing umount of %s", path);
-			rv = spawn_umount(log_debug, "-l", path, NULL);
+			info(ap->logopt, "forcing umount of %s", path);
+			rv = spawn_umount(ap->logopt, "-l", path, NULL);
 		}
 
 		/*
@@ -503,7 +503,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me
 		 * the offset triggers back.
 		 */
 		if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
-			msg("unmounting dir = %s", root);
+			info(ap->logopt, "unmounting dir = %s", root);
 			if (umount_ent(ap, root)) {
 				if (!mount_multi_triggers(ap, root, me, "/"))
 					warn(ap->logopt,
diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c
index d79a94f..5797639 100644
--- a/lib/rpc_subs.c
+++ b/lib/rpc_subs.c
@@ -96,7 +96,7 @@ static CLIENT *create_udp_client(struct conn_info *info)
 	if (ret || !result) {
 		int err = ghn_errno == -1 ? errno : ghn_errno;
 		char *estr = strerror_r(err, buf, HOST_ENT_BUF_SIZE);
-		error(LOGOPT_ANY, "hostname lookup failed: %s", estr);
+		logerr("hostname lookup failed: %s", estr);
 		goto out_close;
 	}
 	memcpy(&raddr.sin_addr.s_addr, php->h_addr, php->h_length);
@@ -305,7 +305,7 @@ static CLIENT *create_tcp_client(struct conn_info *info)
 	if (ret || !result) {
 		int err = ghn_errno == -1 ? errno : ghn_errno;
 		char *estr =  strerror_r(err, buf, HOST_ENT_BUF_SIZE);
-		error(LOGOPT_ANY, "hostname lookup failed: %s", estr);
+		logerr("hostname lookup failed: %s", estr);
 		goto out_close;
 	}
 	memcpy(&addr.sin_addr.s_addr, php->h_addr, php->h_length);
diff --git a/man/automount.8 b/man/automount.8
index e203a3e..5cd63c7 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -62,6 +62,22 @@ setting.
 .TP
 .I "\-V, \-\-version"
 Display the version number, then exit.
+.TP
+.I "\-l, \-\-set-log-priority priority path [path,...]"
+Set the daemon log priority to the specified value.  Valid values include
+the numbers 0-7, or the strings emerg, alert, crit, err, warning, notice,
+info, or debug. Log level debug will log everything, log levels info, warn
+(or warning), or notice with enable the daemon verbose logging. Any other
+level will set basic logging. Note that enabling debug or verbose
+logging in the autofs global configuration will override dynamic log level
+changes. For example, if verbose logging is set in the configuration then
+attempting to set logging to basic logging, by using alert, crit, err
+or emerg won't stop the verbose logging. However, setting logging to debug
+will lead to everything (debug logging) being logged witch can then also
+be disabled, returning the daemon to verbose logging.
+.P
+The \fIpath\fP argument corresponds to the automounted
+path name as specified in the master map.
 .SH ARGUMENTS
 \fBautomount\fP takes one optional argument, the name of the master map to
 use.
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
index 68e5dd7..18733f3 100644
--- a/modules/cyrus-sasl.c
+++ b/modules/cyrus-sasl.c
@@ -96,18 +96,18 @@ sasl_log_func(void *context, int level, const char *message)
 	switch (level) {
 	case SASL_LOG_ERR:
 	case SASL_LOG_FAIL:
-		error(LOGOPT_ANY, "%s", message);
+		logerr("%s", message);
 		break;
 	case SASL_LOG_WARN:
-		warn(LOGOPT_ANY, "%s", message);
+		logmsg("%s", message);
 		break;
 	case SASL_LOG_NOTE:
-		info(LOGOPT_ANY, "%s", message);
+		logmsg("%s", message);
 		break;
 	case SASL_LOG_DEBUG:
 	case SASL_LOG_TRACE:
 	case SASL_LOG_PASS:
-		debug(LOGOPT_NONE, "%s", message);
+		debug(LOGOPT_DEBUG, "%s", message);
 		break;
 	default:
 		break;
@@ -129,7 +129,7 @@ getuser_func(void *context, int id, const char **result, unsigned *len)
 			*len = strlen(sasl_auth_id);
 		break;
 	default:
-		error(LOGOPT_ANY, "unknown id in request: %d", id);
+		error(LOGOPT_VERBOSE, "unknown id in request: %d", id);
 		return SASL_FAIL;
 	}
 
@@ -166,7 +166,7 @@ getpass_func(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret)
  *                the returned data.
  */
 char **
-get_server_SASL_mechanisms(LDAP *ld)
+get_server_SASL_mechanisms(unsigned logopt, LDAP *ld)
 {
 	int ret;
 	const char *saslattrlist[] = {"supportedSASLmechanisms", NULL};
@@ -178,7 +178,7 @@ get_server_SASL_mechanisms(LDAP *ld)
 				NULL, NULL,
 				NULL, LDAP_NO_LIMIT, &results);
 	if (ret != LDAP_SUCCESS) {
-		error(LOGOPT_ANY, "%s", ldap_err2string(ret));
+		error(logopt, "%s", ldap_err2string(ret));
 		return NULL;
 	}
 
@@ -186,7 +186,7 @@ get_server_SASL_mechanisms(LDAP *ld)
 	if (entry == NULL) {
 		/* No root DSE. (!) */
 		ldap_msgfree(results);
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      "a lookup of \"supportedSASLmechanisms\" returned "
 		      "no results.");
 		return NULL;
@@ -196,7 +196,7 @@ get_server_SASL_mechanisms(LDAP *ld)
 	ldap_msgfree(results);
 	if (mechanisms == NULL) {
 		/* Well, that was a waste of time. */
-		msg("No SASL authentication mechanisms are supported"
+		info(logopt, "No SASL authentication mechanisms are supported"
 		    " by the LDAP server.");
 		return NULL;
 	}
@@ -208,7 +208,7 @@ get_server_SASL_mechanisms(LDAP *ld)
  *  Returns 0 upon successful connect, -1 on failure.
  */
 int
-do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
+do_sasl_bind(unsigned logopt, LDAP *ld, sasl_conn_t *conn, const char **clientout,
 	     unsigned int *clientoutlen, const char *auth_mech, int sasl_result)
 {
 	int ret, msgid, bind_result;
@@ -226,7 +226,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 				     &client_cred : NULL,
 				     NULL, NULL, &msgid);
 		if (ret != LDAP_SUCCESS) {
-			crit(LOGOPT_ANY,
+			crit(logopt,
 			     "Error sending sasl_bind request to "
 			     "the server: %s", ldap_err2string(ret));
 			return -1;
@@ -236,7 +236,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 		results = NULL;
 		ret = ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, &results);
 		if (ret != LDAP_RES_BIND) {
-			crit(LOGOPT_ANY,
+			crit(logopt,
 			     "Error while waiting for response to "
 			     "sasl_bind request: %s", ldap_err2string(ret));
 			return -1;
@@ -264,7 +264,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 			ret = ldap_get_option(ld, LDAP_OPT_RESULT_CODE,
 					      &bind_result);
 			if (ret != LDAP_SUCCESS) {
-				crit(LOGOPT_ANY,
+				crit(logopt,
 				     "Error retrieving response to sasl_bind "
 				     "request: %s", ldap_err2string(ret));
 				ret = -1;
@@ -277,7 +277,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 				bind_result = ret;
 				break;
 			default:
-				warn(LOGOPT_ANY,
+				warn(logopt,
 				     "Error parsing response to sasl_bind "
 				     "request: %s.", ldap_err2string(ret));
 				break;
@@ -299,7 +299,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 		expected_data = sasl_result == SASL_CONTINUE;
 
 		if (have_data && !expected_data) {
-			warn(LOGOPT_ANY,
+			warn(logopt,
 			     "The LDAP server sent data in response to our "
 			     "bind request, but indicated that the bind was "
 			     "complete. LDAP SASL bind with mechansim %s "
@@ -308,7 +308,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 			break;
 		}
 		if (expected_data && !have_data) {
-			warn(LOGOPT_ANY,
+			warn(logopt,
 			     "The LDAP server indicated that the LDAP SASL "
 			     "bind was incomplete, but did not provide the "
 			     "required data to proceed. LDAP SASL bind with "
@@ -340,7 +340,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
 			 */
 			if ((*clientoutlen > 0) &&
 			    (bind_result != LDAP_SASL_BIND_IN_PROGRESS)) {
-				warn(LOGOPT_ANY,
+				warn(logopt,
 				     "We have data for the server, "
 				     "but it thinks we are done!");
 				/* XXX should print out debug data here */
@@ -372,7 +372,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout,
  *  Upon failure, -1 is returned.
  */
 int
-sasl_do_kinit(struct lookup_context *ctxt)
+sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 {
 	krb5_error_code ret;
 	krb5_principal tgs_princ, krb5_client_princ = ctxt->krb5_client_princ;
@@ -384,33 +384,33 @@ sasl_do_kinit(struct lookup_context *ctxt)
 		return 0;
 	ctxt->kinit_done = 1;
 
-	debug(LOGOPT_NONE,
+	debug(logopt,
 	      "initializing kerberos ticket: client principal %s ",
 	      ctxt->client_princ ? "" : "autofsclient");
 
 	ret = krb5_init_context(&ctxt->krb5ctxt);
 	if (ret) {
-		error(LOGOPT_ANY, "krb5_init_context failed with %d", ret);
+		error(logopt, "krb5_init_context failed with %d", ret);
 		return -1;
 	}
 
 	ret = krb5_cc_resolve(ctxt->krb5ctxt, krb5ccval, &ctxt->krb5_ccache);
 	if (ret) {
-		error(LOGOPT_ANY, "krb5_cc_resolve failed with error %d",
+		error(logopt, "krb5_cc_resolve failed with error %d",
 		      ret);
 		krb5_free_context(ctxt->krb5ctxt);
 		return -1;
 	}
 
 	if (ctxt->client_princ) {
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      "calling krb5_parse_name on client principal %s",
 		      ctxt->client_princ);
 
 		ret = krb5_parse_name(ctxt->krb5ctxt, ctxt->client_princ,
 				      &krb5_client_princ);
 		if (ret) {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      "krb5_parse_name failed for "
 			      "specified client principal %s",
 			      ctxt->client_princ);
@@ -419,14 +419,14 @@ sasl_do_kinit(struct lookup_context *ctxt)
 	} else {
 		char *tmp_name = NULL;
 
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      "calling krb5_sname_to_principal using defaults");
 
 		ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL,
 					"autofsclient", KRB5_NT_SRV_HST, 
 					&krb5_client_princ);
 		if (ret) {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      "krb5_sname_to_principal failed for "
 			      "%s with error %d",
 			      ctxt->client_princ ? "" : "autofsclient", ret);
@@ -437,13 +437,13 @@ sasl_do_kinit(struct lookup_context *ctxt)
 		ret = krb5_unparse_name(ctxt->krb5ctxt,
 					krb5_client_princ, &tmp_name);
 		if (ret) {
-			debug(LOGOPT_NONE,
+			debug(logopt,
 			      "krb5_unparse_name failed with error %d",
 			      ret);
 			goto out_cleanup_cc;
 		}
 
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      "principal used for authentication: \"%s\"", tmp_name);
 
 		krb5_free_unparsed_name(ctxt->krb5ctxt, tmp_name);
@@ -458,19 +458,19 @@ sasl_do_kinit(struct lookup_context *ctxt)
 		krb5_princ_realm(ctxt->krb5ctxt, krb5_client_princ)->data,
 		0);
 	if (ret) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      "krb5_build_principal failed with error %d", ret);
 		goto out_cleanup_cc;
 	}
 
 	ret = krb5_unparse_name(ctxt->krb5ctxt, tgs_princ, &tgs_name);
 	if (ret) {
-		error(LOGOPT_ANY, "krb5_unparse_name failed with error %d",
+		error(logopt, "krb5_unparse_name failed with error %d",
 		      ret);
 		goto out_cleanup_cc;
 	}
 
-	debug(LOGOPT_NONE, "Using tgs name %s", tgs_name);
+	debug(logopt, "Using tgs name %s", tgs_name);
 
 	memset(&my_creds, 0, sizeof(my_creds));
 	ret = krb5_get_init_creds_keytab(ctxt->krb5ctxt, &my_creds,
@@ -479,7 +479,7 @@ sasl_do_kinit(struct lookup_context *ctxt)
 					 0 /* relative start time */,
 					 tgs_name, NULL);
 	if (ret) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      "krb5_get_init_creds_keytab failed with error %d",
 		      ret);
 		goto out_cleanup_unparse;
@@ -500,7 +500,7 @@ sasl_do_kinit(struct lookup_context *ctxt)
 		fatal(status);
 
 	if (ret) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      "krb5_cc_initialize failed with error %d", ret);
 		goto out_cleanup_unparse;
 	}
@@ -508,7 +508,7 @@ sasl_do_kinit(struct lookup_context *ctxt)
 	/* and store credentials for that principal */
 	ret = krb5_cc_store_cred(ctxt->krb5ctxt, ctxt->krb5_ccache, &my_creds);
 	if (ret) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      "krb5_cc_store_cred failed with error %d", ret);
 		goto out_cleanup_unparse;
 	}
@@ -516,12 +516,12 @@ sasl_do_kinit(struct lookup_context *ctxt)
 	/* finally, set the environment variable to point to our
 	 * credentials cache */
 	if (setenv(krb5ccenv, krb5ccval, 1) != 0) {
-		error(LOGOPT_ANY, "setenv failed with %d", errno);
+		error(logopt, "setenv failed with %d", errno);
 		goto out_cleanup_unparse;
 	}
 	ctxt->kinit_successful = 1;
 
-	debug(LOGOPT_NONE, "Kerberos authentication was successful!");
+	debug(logopt, "Kerberos authentication was successful!");
 
 	krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name);
 
@@ -540,7 +540,7 @@ out_cleanup_cc:
 	else
 		ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache);
 	if (ret)
-		warn(LOGOPT_ANY,
+		warn(logopt,
 		     "krb5_cc_destroy failed with non-fatal error %d", ret);
 
 	status = pthread_mutex_unlock(&krb5cc_mutex);
@@ -559,7 +559,7 @@ out_cleanup_cc:
  *  Returns a valid sasl_conn_t pointer upon success, NULL on failure.
  */
 sasl_conn_t *
-sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech)
+sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *mech)
 {
 	sasl_conn_t *conn;
 	char *tmp, *host = NULL;
@@ -569,15 +569,15 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech)
 	int result;
 
 	if (!strncmp(mech, "GSSAPI", 6)) {
-		if (sasl_do_kinit(ctxt) != 0)
+		if (sasl_do_kinit(logopt, ctxt) != 0)
 			return NULL;
 	}
 
-	debug(LOGOPT_NONE, "Attempting sasl bind with mechanism %s", mech);
+	debug(logopt, "Attempting sasl bind with mechanism %s", mech);
 
 	result = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
 	if (result != LDAP_SUCCESS || !host) {
-		debug(LOGOPT_NONE, "failed to get hostname for connection");
+		debug(logopt, "failed to get hostname for connection");
 		return NULL;
 	}
 
@@ -587,7 +587,7 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech)
 	/* Create a new authentication context for the service. */
 	result = sasl_client_new("ldap", host, NULL, NULL, NULL, 0, &conn);
 	if (result != SASL_OK) {
-		error(LOGOPT_ANY, "sasl_client_new failed with error %d",
+		error(logopt, "sasl_client_new failed with error %d",
 		      result);
 		ldap_memfree(host);
 		return NULL;
@@ -599,23 +599,23 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech)
 
 	/* OK and CONTINUE are the only non-fatal return codes here. */
 	if ((result != SASL_OK) && (result != SASL_CONTINUE)) {
-		error(LOGOPT_ANY, "sasl_client start failed with error: %s",
+		error(logopt, "sasl_client start failed with error: %s",
 		      sasl_errdetail(conn));
 		ldap_memfree(host);
 		sasl_dispose(&conn);
 		return NULL;
 	}
 
-	result = do_sasl_bind(ldap, conn,
+	result = do_sasl_bind(logopt, ldap, conn,
 			 &clientout, &clientoutlen, chosen_mech, result);
 	if (result == 0) {
 		ldap_memfree(host);
-		debug(LOGOPT_NONE, "sasl bind with mechanism %s succeeded",
+		debug(logopt, "sasl bind with mechanism %s succeeded",
 		      chosen_mech);
 		return conn;
 	}
 
-	info(LOGOPT_ANY, "sasl bind with mechanism %s failed", mech);
+	info(logopt, "sasl bind with mechanism %s failed", mech);
 
 	/* sasl bind failed */
 	ldap_memfree(host);
@@ -629,14 +629,14 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech)
  *  -1 on error or if no mechanism is supported by both client and server.
  */
 sasl_conn_t *
-sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt)
+sasl_choose_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	sasl_conn_t *conn;
 	int authenticated;
 	int i;
 	char **mechanisms;
 
-	mechanisms = get_server_SASL_mechanisms(ldap);
+	mechanisms = get_server_SASL_mechanisms(logopt, ldap);
 	if (!mechanisms)
 		return NULL;
 
@@ -652,12 +652,11 @@ sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt)
 		if (authtype_requires_creds(mechanisms[i]))
 			continue;
 
-		conn = sasl_bind_mech(ldap, ctxt, mechanisms[i]);
+		conn = sasl_bind_mech(logopt, ldap, ctxt, mechanisms[i]);
 		if (conn) {
 			ctxt->sasl_mech = strdup(mechanisms[i]);
 			if (!ctxt->sasl_mech) {
-				crit(LOGOPT_ANY,
-				     "Successfully authenticated with "
+				crit(logopt, "Successfully authenticated with "
 				     "mechanism %s, but failed to allocate "
 				     "memory to hold the mechanism type.",
 				     mechanisms[i]);
@@ -668,11 +667,11 @@ sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt)
 			authenticated = 1;
 			break;
 		}
-		debug(LOGOPT_NONE, "Failed to authenticate with mech %s",
+		debug(logopt, "Failed to authenticate with mech %s",
 		      mechanisms[i]);
 	}
 
-	debug(LOGOPT_NONE, "authenticated: %d, sasl_mech: %s",
+	debug(logopt, "authenticated: %d, sasl_mech: %s",
 	      authenticated, ctxt->sasl_mech);
 
 	ldap_value_free(mechanisms);
@@ -680,14 +679,14 @@ sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt)
 }
 
 int
-autofs_sasl_bind(LDAP *ldap, struct lookup_context *ctxt)
+autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	sasl_conn_t *conn;
 
 	if (!ctxt->sasl_mech)
 		return -1;
 
-	conn = sasl_bind_mech(ldap, ctxt, ctxt->sasl_mech);
+	conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech);
 	if (!conn)
 		return -1;
 
@@ -717,13 +716,13 @@ autofs_sasl_unbind(struct lookup_context *ctxt)
  * -1  -  Failure
  */
 int
-autofs_sasl_init(LDAP *ldap, struct lookup_context *ctxt)
+autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	sasl_conn_t *conn;
 
 	/* Start up Cyrus SASL--only needs to be done once. */
 	if (sasl_client_init(callbacks) != SASL_OK) {
-		error(LOGOPT_ANY, "sasl_client_init failed");
+		error(logopt, "sasl_client_init failed");
 		return -1;
 	}
 
@@ -736,9 +735,9 @@ autofs_sasl_init(LDAP *ldap, struct lookup_context *ctxt)
 	 *  select one.
 	 */
 	if (ctxt->sasl_mech)
-		conn = sasl_bind_mech(ldap, ctxt, ctxt->sasl_mech);
+		conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech);
 	else
-		conn = sasl_choose_mech(ldap, ctxt);
+		conn = sasl_choose_mech(logopt, ldap, ctxt);
 
 	if (conn) {
 		sasl_dispose(&conn);
@@ -772,8 +771,7 @@ autofs_sasl_done(struct lookup_context *ctxt)
 		else 
 			ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache);
 		if (ret)
-			warn(LOGOPT_ANY,
-			     "krb5_cc_destroy failed with non-fatal error %d",
+			logmsg("krb5_cc_destroy failed with non-fatal error %d",
 			     ret);
 
 		status = pthread_mutex_unlock(&krb5cc_mutex);
@@ -782,8 +780,7 @@ autofs_sasl_done(struct lookup_context *ctxt)
 
 		krb5_free_context(ctxt->krb5ctxt);
 		if (unsetenv(krb5ccenv) != 0)
-			warn(LOGOPT_ANY,
-			     "unsetenv failed with error %d", errno);
+			logerr("unsetenv failed with error %d", errno);
 
 		ctxt->krb5ctxt = NULL;
 		ctxt->krb5_ccache = NULL;
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 31ee0fb..921b32b 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -63,13 +63,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return 1;
 	}
 
 	if (argc < 1) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "No map name");
+		logerr(MODPREFIX "No map name");
 		return 1;
 	}
 
@@ -77,21 +77,21 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 
 	if (ctxt->mapname[0] != '/') {
 		free(ctxt);
-		msg(MODPREFIX "file map %s is not an absolute pathname",
-		    argv[0]);
+		logmsg(MODPREFIX
+		     "file map %s is not an absolute pathname", argv[0]);
 		return 1;
 	}
 
 	if (access(ctxt->mapname, R_OK)) {
 		free(ctxt);
-		msg(MODPREFIX "file map %s missing or not readable",
-		    argv[0]);
+		warn(LOGOPT_NONE, MODPREFIX
+		    "file map %s missing or not readable", argv[0]);
 		return 1;
 	}
 
 	if (stat(ctxt->mapname, &st)) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat",
+		logmsg(MODPREFIX "file map %s, could not stat",
 		     argv[0]);
 		return 1;
 	}
@@ -104,7 +104,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parse) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logmsg(MODPREFIX "failed to open parse context");
 		return 1;
 	}
 	*context = ctxt;
@@ -112,7 +112,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	return 0;
 }
 
-static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsigned int *m_len)
+static int read_one(unsigned logopt, FILE *f, char *key, unsigned int *k_len, char *mapent, unsigned int *m_len)
 {
 	char *kptr, *p;
 	int mapent_len, key_len;
@@ -193,7 +193,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig
 				if (gotten == got_plus)
 					goto got_it;
 				else if (escape == esc_all) {
-					warn(LOGOPT_ANY, MODPREFIX
+					warn(logopt, MODPREFIX
 					    "unmatched \" in map key %s", key);
 					goto next;
 				} else if (escape != esc_val)
@@ -208,7 +208,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig
 				if (key_len == KEY_MAX_LEN) {
 					state = st_badent;
 					gotten = got_nothing;
-					warn(LOGOPT_ANY,
+					warn(logopt,
 					      MODPREFIX "map key \"%s...\" "
 					      "is too long.  The maximum key "
 					      "length is %d", key,
@@ -245,7 +245,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig
 				state = st_begin;
 				if (gotten == got_real || gotten == getting)
 					goto got_it;
-				warn(LOGOPT_ANY, MODPREFIX 
+				warn(logopt, MODPREFIX 
 				      "bad map entry \"%s...\" for key "
 				      "\"%s\"", mapent, key);
 				goto next;
@@ -286,7 +286,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig
 			if (ch == '\n') {
 				if (escape == esc_all) {
 					state = st_begin;
-					warn(LOGOPT_ANY, MODPREFIX
+					warn(logopt, MODPREFIX
 					     "unmatched \" in %s for key %s",
 					     mapent, key);
 					goto next;
@@ -310,7 +310,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig
 				   	goto got_it;
 				ungetc(nch, f);
 			} else {
-				warn(LOGOPT_ANY,
+				warn(logopt,
 				      MODPREFIX "map entry \"%s...\" for key "
 				      "\"%s\" is too long.  The maximum entry"
 				      " size is %d", mapent, key,
@@ -388,6 +388,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	unsigned int timeout = master->default_timeout;
 	unsigned int logging = master->default_logging;
+	unsigned int logopt = master->logopt;
 	char *buffer;
 	int blen;
 	char *path;
@@ -402,29 +403,28 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		return NSS_STATUS_UNAVAIL;
 
 	if (master->depth > MAX_INCLUDE_DEPTH) {
-		error(LOGOPT_ANY,
-		      MODPREFIX
+		error(logopt, MODPREFIX
 		      "maximum include depth exceeded %s", master->name);
 		return NSS_STATUS_UNAVAIL;
 	}
 
 	path = alloca(KEY_MAX_LEN + 1);
 	if (!path) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX "could not malloc storage for path");
 		return NSS_STATUS_UNAVAIL;
 	}
 
 	ent = alloca(MAPENT_MAX_LEN + 1);
 	if (!ent) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX "could not malloc storage for mapent");
 		return NSS_STATUS_UNAVAIL;
 	}
 
 	f = fopen(ctxt->mapname, "r");
 	if (!f) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX "could not open master map file %s",
 		      ctxt->mapname);
 		return NSS_STATUS_UNAVAIL;
@@ -438,19 +438,19 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	}
 
 	while(1) {
-		entry = read_one(f, path, &path_len, ent, &ent_len);
+		entry = read_one(logopt, f, path, &path_len, ent, &ent_len);
 		if (!entry) {
 			if (feof(f))
 				break;
 			if (ferror(f)) {
-				warn(LOGOPT_ANY, MODPREFIX
+				warn(logopt, MODPREFIX
 				     "error reading map %s", ctxt->mapname);
 				break;
 			}
 			continue;
 		}
 
-		debug(LOGOPT_NONE, MODPREFIX "read entry %s", path);
+		debug(logopt, MODPREFIX "read entry %s", path);
 
 		/*
 		 * If key starts with '+' it has to be an
@@ -470,7 +470,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			master->depth++;
 			status = lookup_nss_read_master(master, age);
 			if (!status)
-				warn(LOGOPT_ANY,
+				warn(logopt,
 				     MODPREFIX
 				     "failed to read included master map %s",
 				     master->name);
@@ -482,7 +482,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			blen = path_len + 1 + ent_len + 1;
 			buffer = malloc(blen);
 			if (!buffer) {
-				error(LOGOPT_ANY,
+				error(logopt,
 				      MODPREFIX "could not malloc parse buffer");
 				return NSS_STATUS_UNAVAIL;
 			}
@@ -503,7 +503,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	}
 
 	if (fstat(fd, &st)) {
-		crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat",
+		crit(logopt, MODPREFIX "file map %s, could not stat",
 		       ctxt->mapname);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -684,12 +684,12 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 	}
 
 	while(1) {
-		entry = read_one(f, key, &k_len, mapent, &m_len);
+		entry = read_one(ap->logopt, f, key, &k_len, mapent, &m_len);
 		if (!entry) {
 			if (feof(f))
 				break;
 			if (ferror(f)) {
-				warn(LOGOPT_ANY, MODPREFIX
+				warn(ap->logopt, MODPREFIX
 				      "error reading map %s", ctxt->mapname);
 				break;
 			}
@@ -791,7 +791,7 @@ static int lookup_one(struct autofs_point *ap,
 	}
 
 	while(1) {
-		entry = read_one(f, mkey, &k_len, mapent, &m_len);
+		entry = read_one(ap->logopt, f, mkey, &k_len, mapent, &m_len);
 		if (entry) {
 			/*
 			 * If key starts with '+' it has to be an
@@ -860,7 +860,7 @@ static int lookup_one(struct autofs_point *ap,
 			break;
 
 		if (ferror(f)) {
-			warn(LOGOPT_ANY, MODPREFIX
+			warn(ap->logopt, MODPREFIX
 			      "error reading map %s", ctxt->mapname);
 			break;
 		}		
@@ -904,7 +904,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
 	}
 
 	while(1) {
-		entry = read_one(f, mkey, &k_len, mapent, &m_len);
+		entry = read_one(ap->logopt, f, mkey, &k_len, mapent, &m_len);
 		if (entry) {
 			int eq;
 
@@ -925,7 +925,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
 			break;
 
 		if (ferror(f)) {
-			warn(LOGOPT_ANY, MODPREFIX
+			warn(ap->logopt, MODPREFIX
 			      "error reading map %s", ctxt->mapname);
 			break;
 		}		
diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c
index f30e9b2..649e24c 100644
--- a/modules/lookup_hesiod.c
+++ b/modules/lookup_hesiod.c
@@ -48,7 +48,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return 1;
 	}
 
@@ -58,7 +58,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	/* Initialize the hesiod context. */
 	if (hesiod_init(&(ctxt->hesiod_context)) != 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "hesiod_init(): %s", estr);
+		logerr(MODPREFIX "hesiod_init(): %s", estr);
 		free(ctxt);
 		return 1;
 	}
@@ -70,7 +70,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	/* Open the parser, if we can. */
 	ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parser) {
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logerr(MODPREFIX "failed to open parse context");
 		free(ctxt);
 		return 1;
 	}
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index d711611..d746e42 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -57,7 +57,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return 1;
 	}
 
@@ -65,7 +65,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc, argv);
 	if (!ctxt->parse) {
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logerr(MODPREFIX "failed to open parse context");
 		free(ctxt);
 		return 1;
 	}
@@ -94,7 +94,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 
 	status = pthread_mutex_lock(&hostent_mutex);
 	if (status) {
-		error(LOGOPT_ANY, MODPREFIX "failed to lock hostent mutex");
+		error(ap->logopt, MODPREFIX "failed to lock hostent mutex");
 		return NSS_STATUS_UNAVAIL;
 	}
 
@@ -110,7 +110,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 
 	status = pthread_mutex_unlock(&hostent_mutex);
 	if (status)
-		error(LOGOPT_ANY, MODPREFIX "failed to unlock hostent mutex");
+		error(ap->logopt, MODPREFIX "failed to unlock hostent mutex");
 
 	source->age = age;
 
@@ -157,10 +157,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		}
 
 		if (*name == '/')
-			msg(MODPREFIX
+			info(ap->logopt, MODPREFIX
 			      "can't find path in hosts map %s", name);
 		else
-			msg(MODPREFIX
+			info(ap->logopt, MODPREFIX
 			      "can't find path in hosts map %s/%s",
 			      ap->path, name);
 
@@ -216,7 +216,7 @@ done:
 			if (!mapent) {
 				char *estr;
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(ap->logopt, MODPREFIX "malloc: %s", estr);
+				logerr(MODPREFIX "malloc: %s", estr);
 				rpc_exports_free(exp);
 				return NSS_STATUS_UNAVAIL;
 			}
@@ -230,7 +230,7 @@ done:
 			if (!mapent) {
 				char *estr;
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(ap->logopt, MODPREFIX "malloc: %s", estr);
+				logerr(MODPREFIX "malloc: %s", estr);
 				rpc_exports_free(exp);
 				return NSS_STATUS_UNAVAIL;
 			}
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index c0f228b..00215af 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -49,9 +49,9 @@ 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 *);
+static LDAP *auth_init(unsigned logopt, const char *, struct lookup_context *);
 
-int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
+int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	int rv;
 
@@ -62,15 +62,14 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
 
 	if (rv != LDAP_SUCCESS) {
 		if (!ctxt->uri) {
-			crit(LOGOPT_ANY,
-			     MODPREFIX "Unable to bind to the LDAP server: "
+			crit(logopt, 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: "
+			info(logopt, MODPREFIX "Unable to bind to the LDAP server: "
 			     "%s, error %s", uri->uri, ldap_err2string(rv));
 		}
 		return -1;
@@ -79,12 +78,11 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt)
 	return 0;
 }
 
-int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt)
+int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	int rv;
 
 #ifdef WITH_SASL
-	debug(LOGOPT_NONE, "use_tls: %d", ctxt->use_tls);
 	/*
 	 * The OpenSSL library can't handle having its message and error
 	 * string database loaded multiple times and segfaults if the
@@ -102,13 +100,12 @@ int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt)
 
 	rv = ldap_unbind_ext(ldap, NULL, NULL);
 	if (rv != LDAP_SUCCESS)
-		error(LOGOPT_ANY,
-		     "unbind failed: %s", ldap_err2string(rv));
+		error(logopt, "unbind failed: %s", ldap_err2string(rv));
 
 	return rv;
 }
 
-LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
+LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
 {
 	LDAP *ldap = NULL;
 	struct timeval timeout     = { ctxt->timeout, 0 };
@@ -120,9 +117,9 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 	/* Initialize the LDAP context. */
 	rv = ldap_initialize(&ldap, uri);
 	if (rv != LDAP_OPT_SUCCESS) {
-		crit(LOGOPT_ANY,
-		     MODPREFIX "couldn't initialize LDAP connection to %s",
-		     uri ? uri : "default server");
+		info(logopt, MODPREFIX
+		     "couldn't initialize LDAP connection to %s",
+		     uri ? uri : "default");
 		return NULL;
 	}
 
@@ -133,7 +130,7 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 		ldap_unbind_ext(ldap, NULL, NULL);
 		rv = ldap_initialize(&ldap, uri);
 		if (rv != LDAP_OPT_SUCCESS) {
-			crit(LOGOPT_ANY, MODPREFIX "couldn't initialize LDAP");
+			crit(logopt, MODPREFIX "couldn't initialize LDAP");
 			return NULL;
 		}
 		ctxt->version = 2;
@@ -144,7 +141,7 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 		/* Set synchronous call timeout */
 		rv = ldap_set_option(ldap, LDAP_OPT_TIMEOUT, &timeout);
 		if (rv != LDAP_OPT_SUCCESS)
-			info(LOGOPT_ANY, MODPREFIX
+			info(logopt, MODPREFIX
 			     "failed to set synchronous call timeout to %d",
 			     timeout.tv_sec);
 	}
@@ -152,16 +149,14 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 	/* 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",
+		info(logopt, MODPREFIX "failed to set connection timeout to %d",
 		     net_timeout.tv_sec);
 
 #ifdef WITH_SASL
 	if (ctxt->use_tls) {
 		if (ctxt->version == 2) {
 			if (ctxt->tls_required) {
-				error(LOGOPT_ANY,
-				    MODPREFIX
+				error(logopt, MODPREFIX
 				    "TLS required but connection is version 2");
 				ldap_unbind_ext(ldap, NULL, NULL);
 				return NULL;
@@ -171,16 +166,15 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 
 		rv = ldap_start_tls_s(ldap, NULL, NULL);
 		if (rv != LDAP_SUCCESS) {
-			unbind_ldap_connection(ldap, ctxt);
+			unbind_ldap_connection(logopt, ldap, ctxt);
 			if (ctxt->tls_required) {
-				error(LOGOPT_ANY,
-				      MODPREFIX
+				error(logopt, MODPREFIX
 				      "TLS required but START_TLS failed: %s",
 				      ldap_err2string(rv));
 				return NULL;
 			}
 			ctxt->use_tls = LDAP_TLS_DONT_USE;
-			ldap = init_ldap_connection(uri, ctxt);
+			ldap = init_ldap_connection(logopt, uri, ctxt);
 			if (ldap)
 				ctxt->use_tls = LDAP_TLS_INIT;
 			return ldap;
@@ -192,7 +186,7 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt)
 	return ldap;
 }
 
-static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
+static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
 {
 	char buf[PARSE_MAX_BUF];
 	char *query, *dn, *qdn;
@@ -206,7 +200,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
 	attrs[1] = NULL;
 
 	if (!ctxt->mapname && !ctxt->base) {
-		error(LOGOPT_ANY, MODPREFIX "no master map to lookup");
+		error(logopt, MODPREFIX "no master map to lookup");
 		return 0;
 	}
 
@@ -218,7 +212,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
 	query = alloca(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		crit(logopt, MODPREFIX "alloca: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
@@ -229,14 +223,14 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
 	if (ctxt->mapname) {
 		if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class,
 		     key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) {
-			debug(LOGOPT_NONE,
+			debug(logopt,
 			      MODPREFIX "error forming query string");
 			return 0;
 		}
 		scope = LDAP_SCOPE_SUBTREE;
 	} else {
 		if (sprintf(query, "(objectclass=%s)", class) >= l) {
-			debug(LOGOPT_NONE,
+			debug(logopt,
 			      MODPREFIX "error forming query string");
 			return 0;
 		}
@@ -259,15 +253,14 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
 	else {
 		struct ldap_searchdn *this = ctxt->sdns;
 
-		debug(LOGOPT_NONE, MODPREFIX
-			      "check search base list");
+		debug(logopt, 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
+				debug(logopt, MODPREFIX
 				      "found search base under %s",
 				      this->basedn);
 				break;
@@ -283,7 +276,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla
 	}
 
 	if ((rv != LDAP_SUCCESS) || !result) {
-		error(LOGOPT_NONE,
+		error(logopt,
 		      MODPREFIX "query failed for %s: %s",
 		      query, ldap_err2string(rv));
 		return 0;
@@ -292,9 +285,9 @@ 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 "found query dn %s", dn);
+		debug(logopt, MODPREFIX "found query dn %s", dn);
 	} else {
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      MODPREFIX "query succeeded, no matches for %s",
 		      query);
 		ldap_msgfree(result);
@@ -373,7 +366,7 @@ static struct ldap_schema *alloc_common_schema(struct ldap_schema *s)
 	return schema;
 }
 
-static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
+static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	struct ldap_schema *schema;
 	unsigned int i;
@@ -384,11 +377,10 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
 	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)) {
+		if (get_query_dn(logopt, ldap, ctxt, class, key)) {
 			schema = alloc_common_schema(&common_schema[i]);
 			if (!schema) {
-				error(LOGOPT_ANY,
-				      MODPREFIX "failed to allocate schema");
+				error(logopt, MODPREFIX "failed to allocate schema");
 				return 0;
 			}
 			ctxt->schema = schema;
@@ -399,28 +391,26 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt)
 	return 0;
 }
 
-static int do_bind(LDAP *ldap, struct lookup_context *ctxt)
+static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 {
 	char *host = NULL, *nhost;
 	int rv, need_base = 1;
 
 #ifdef WITH_SASL
-	debug(LOGOPT_NONE, "auth_required: %d, sasl_mech %s",
+	debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s",
 	      ctxt->auth_required, ctxt->sasl_mech);
 
 	if (ctxt->sasl_mech ||
 	   (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT))) {
-		rv = autofs_sasl_bind(ldap, ctxt);
-		debug(LOGOPT_NONE, MODPREFIX
-		      "autofs_sasl_bind returned %d", rv);
+		rv = autofs_sasl_bind(logopt, ldap, ctxt);
+		debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
 	} else {
-		rv = bind_ldap_anonymous(ldap, ctxt);
-		debug(LOGOPT_NONE,
-		      MODPREFIX "ldap anonymous bind returned %d", rv);
+		rv = bind_ldap_anonymous(logopt, ldap, ctxt);
+		debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
 	}
 #else
-	rv = bind_ldap_anonymous(ldap, ctxt);
-	debug(LOGOPT_NONE, MODPREFIX "ldap anonymous bind returned %d", rv);
+	rv = bind_ldap_anonymous(logopt, ldap, ctxt);
+	debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
 #endif
 
 	if (rv != 0)
@@ -428,13 +418,13 @@ static int do_bind(LDAP *ldap, struct lookup_context *ctxt)
 
 	rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
         if (rv != LDAP_SUCCESS || !host) {
-		debug(LOGOPT_ANY, "failed to get hostname for connection");
+		debug(logopt, "failed to get hostname for connection");
 		return 0;
 	}
 
 	nhost = strdup(host);
 	if (!nhost) {
-		debug(LOGOPT_ANY, "failed to alloc context for hostname");
+		debug(logopt, "failed to alloc context for hostname");
 		return 0;
 	}
 	ldap_memfree(host);
@@ -463,16 +453,16 @@ static int do_bind(LDAP *ldap, struct lookup_context *ctxt)
 	 * base dn for searches.
 	 */
 	if (!ctxt->schema) {
-		if (!find_query_dn(ldap, ctxt)) {
-			error(LOGOPT_ANY,
-		      	      MODPREFIX "failed to find valid query dn");
+		if (!find_query_dn(logopt, ldap, ctxt)) {
+			warn(logopt,
+			      MODPREFIX "failed to find valid query dn");
 			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)) {
-			error(LOGOPT_ANY, MODPREFIX "failed to get query dn");
+		if (!get_query_dn(logopt, ldap, ctxt, class, key)) {
+			error(logopt, MODPREFIX "failed to get query dn");
 			return 0;
 		}
 	}
@@ -480,23 +470,23 @@ static int do_bind(LDAP *ldap, struct lookup_context *ctxt)
 	return 1;
 }
 
-static LDAP *do_connect(const char *uri, struct lookup_context *ctxt)
+static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context *ctxt)
 {
 	LDAP *ldap;
 
-	ldap = init_ldap_connection(uri, ctxt);
+	ldap = init_ldap_connection(logopt, uri, ctxt);
 	if (!ldap)
 		return NULL;
 
-	if (!do_bind(ldap, ctxt)) {
-		unbind_ldap_connection(ldap, ctxt);
+	if (!do_bind(logopt, ldap, ctxt)) {
+		unbind_ldap_connection(logopt, ldap, ctxt);
 		return NULL;
 	}
 
 	return ldap;
 }
 
-static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt)
+static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_context *ctxt)
 {
 	LDAP *ldap;
 
@@ -506,19 +496,19 @@ static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt)
 	 * authentication.
 	 */
 	if (ctxt->auth_required & LDAP_AUTH_REQUIRED) {
-		ldap = auth_init(uri, ctxt);
+		ldap = auth_init(logopt, uri, ctxt);
 		if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT)
-			warn(LOGOPT_NONE,
+			info(logopt,
 			     "no authentication mechanisms auto detected.");
 		if (!ldap) {
-			error(LOGOPT_ANY, MODPREFIX
+			error(logopt, 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");
+		if (!do_bind(logopt, ldap, ctxt)) {
+			unbind_ldap_connection(logopt, ldap, ctxt);
+			error(logopt, MODPREFIX "cannot bind to server");
 			return NULL;
 		}
 
@@ -526,16 +516,18 @@ static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt)
 	}
 #endif
 
-	ldap = do_connect(uri, ctxt);
+	ldap = do_connect(logopt, uri, ctxt);
 	if (!ldap) {
-		error(LOGOPT_ANY, MODPREFIX "cannot connect to server");
+		warn(logopt,
+		     MODPREFIX "couldn't connect to server %s",
+		     uri ? uri : "default");
 		return NULL;
 	}
 
 	return ldap;
 }
 
-static LDAP *find_server(struct lookup_context *ctxt)
+static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 {
 	LDAP *ldap = NULL;
 	struct ldap_uri *this;
@@ -547,10 +539,9 @@ static LDAP *find_server(struct lookup_context *ctxt)
 	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);
+		ldap = connect_to_server(logopt, this->uri, ctxt);
 		if (ldap) {
-			debug(LOGOPT_ANY, "connexted to uri %s", this->uri);
+			info(logopt, "connected to uri %s", this->uri);
 			break;
 		}
 		list_del_init(&this->list);
@@ -568,17 +559,17 @@ static LDAP *find_server(struct lookup_context *ctxt)
 	return ldap;
 }
 
-static LDAP *do_reconnect(struct lookup_context *ctxt)
+static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 {
 	LDAP *ldap;
 
 	if (ctxt->server || !ctxt->uri) {
-		ldap = do_connect(ctxt->server, ctxt);
+		ldap = do_connect(logopt, 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);
+		ldap = do_connect(logopt, this->uri, ctxt);
 		if (ldap)
 			return ldap;
 		/* Failed to connect, put at end of list */
@@ -589,15 +580,15 @@ static LDAP *do_reconnect(struct lookup_context *ctxt)
 	autofs_sasl_done(ctxt);
 
 	/* Current server failed connect, try the rest */
-	ldap = find_server(ctxt);
+	ldap = find_server(logopt, ctxt);
 	if (!ldap)
-		error(LOGOPT_ANY, MODPREFIX "failed to find available server");
+		error(logopt, MODPREFIX "failed to find available server");
 
 	return ldap;
 }
 
 #ifdef WITH_SASL
-int get_property(xmlNodePtr node, const char *prop, char **value)
+int get_property(unsigned logopt, xmlNodePtr node, const char *prop, char **value)
 {
 	xmlChar *ret;
 	xmlChar *property = (xmlChar *) prop;
@@ -608,8 +599,7 @@ int get_property(xmlNodePtr node, const char *prop, char **value)
 	}
 
 	if (!(*value = strdup((char *) ret))) {
-		error(LOGOPT_ANY,
-		      MODPREFIX "strdup failed with %d", errno);
+		logerr(MODPREFIX "strdup failed with %d", errno);
 		xmlFree(ret);
 		return -1;
 	}
@@ -645,7 +635,7 @@ int authtype_requires_creds(const char *authtype)
  *  then no further action is necessary.  If it is not, the caller is free
  *  to then use another method to determine how to connect to the server.
  */
-int parse_ldap_config(struct lookup_context *ctxt)
+int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
 {
 	int          ret = 0, fallback = 0;
 	unsigned int auth_required = LDAP_AUTH_NOTREQUIRED;
@@ -662,7 +652,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 
 	auth_conf = (char *) defaults_get_auth_conf_file();
 	if (!auth_conf) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX "failed to get auth config file name.");
 		return 0;
 	}
@@ -687,7 +677,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 			ctxt->client_princ = NULL;
 			return 0;
 		}
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX "stat(2) failed with error %s.",
 		      strerror(errno));
 		return 0;
@@ -696,8 +686,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 	if (!S_ISREG(st.st_mode) ||
 	    st.st_uid != 0 || st.st_gid != 0 ||
 	    (st.st_mode & 0x01ff) != 0600) {
-		error(LOGOPT_ANY,
-		      MODPREFIX
+		error(logopt, MODPREFIX
 		      "Configuration file %s exists, but is not usable. "
 		      "Please make sure that it is owned by root, group "
 		      "is root, and the mode is 0600.",
@@ -708,30 +697,29 @@ int parse_ldap_config(struct lookup_context *ctxt)
 	xmlInitParser();
 	doc = xmlParseFile(auth_conf);
 	if (!doc) {
-		warn(LOGOPT_ANY,
-		     MODPREFIX "xmlParseFile failed for %s.", auth_conf);
+		error(logopt, MODPREFIX
+		     "xmlParseFile failed for %s.", auth_conf);
 		goto out;
 	}
 
 	root = xmlDocGetRootElement(doc);
 	if (!root) {
-		debug(LOGOPT_ANY,
-		      MODPREFIX "empty xml document (%s).", auth_conf);
+		debug(logopt, MODPREFIX
+		      "empty xml document (%s).", auth_conf);
 		fallback = 1;
 		goto out;
 	}
 
 	if (xmlStrcmp(root->name, (const xmlChar *)"autofs_ldap_sasl_conf")) {
-		error(LOGOPT_ANY,
-		      MODPREFIX
+		error(logopt, MODPREFIX
 		      "The root node of the XML document %s is not "
 		      "autofs_ldap_sasl_conf.", auth_conf);
 		goto out;
 	}
 
-	ret = get_property(root, "usetls", &usetls);
+	ret = get_property(logopt, root, "usetls", &usetls);
 	if (ret != 0) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX
 		      "Failed read the usetls property from "
 		      "the configuration file %s.", auth_conf);
@@ -746,7 +734,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 		else if (!strcasecmp(usetls, "no"))
 			use_tls = LDAP_TLS_DONT_USE;
 		else {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      MODPREFIX
 			      "The usetls property must have value "
 			      "\"yes\" or \"no\".");
@@ -756,9 +744,9 @@ int parse_ldap_config(struct lookup_context *ctxt)
 		free(usetls);
 	}
 
-	ret = get_property(root, "tlsrequired", &tlsrequired);
+	ret = get_property(logopt, root, "tlsrequired", &tlsrequired);
 	if (ret != 0) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX
 		      "Failed read the tlsrequired property from "
 		      "the configuration file %s.", auth_conf);
@@ -773,7 +761,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 		else if (!strcasecmp(tlsrequired, "no"))
 			tls_required = LDAP_TLS_DONT_USE;
 		else {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      MODPREFIX
 			      "The tlsrequired property must have value "
 			      "\"yes\" or \"no\".");
@@ -783,9 +771,9 @@ int parse_ldap_config(struct lookup_context *ctxt)
 		free(tlsrequired);
 	}
 
-	ret = get_property(root, "authrequired", &authrequired);
+	ret = get_property(logopt, root, "authrequired", &authrequired);
 	if (ret != 0) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX
 		      "Failed read the authrequired property from "
 		      "the configuration file %s.", auth_conf);
@@ -802,7 +790,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 		else if (!strcasecmp(authrequired, "autodetect"))
 			auth_required = LDAP_AUTH_AUTODETECT;
 		else {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      MODPREFIX
 			      "The authrequired property must have value "
 			      "\"yes\", \"no\" or \"autodetect\".");
@@ -812,9 +800,9 @@ int parse_ldap_config(struct lookup_context *ctxt)
 		free(authrequired);
 	}
 
-	ret = get_property(root, "authtype", &authtype);
+	ret = get_property(logopt, root, "authtype", &authtype);
 	if (ret != 0) {
-		error(LOGOPT_ANY,
+		error(logopt,
 		      MODPREFIX
 		      "Failed read the authtype property from the "
 		      "configuration file %s.", auth_conf);
@@ -822,10 +810,10 @@ int parse_ldap_config(struct lookup_context *ctxt)
 	}
 
 	if (authtype && authtype_requires_creds(authtype)) {
-		ret = get_property(root, "user",  &user);
-		ret |= get_property(root, "secret", &secret);
+		ret = get_property(logopt, root, "user",  &user);
+		ret |= get_property(logopt, root, "secret", &secret);
 		if (ret != 0 || (!user || !secret)) {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      MODPREFIX
 			      "%s authentication type requires a username "
 			      "and a secret.  Please fix your configuration "
@@ -845,7 +833,7 @@ int parse_ldap_config(struct lookup_context *ctxt)
 	 * We allow the admin to specify the principal to use for the
 	 * client.  The default is "autofsclient/hostname@REALM".
 	 */
-	(void)get_property(root, "clientprinc", &client_princ);
+	(void)get_property(logopt, root, "clientprinc", &client_princ);
 
 	ctxt->auth_conf = auth_conf;
 	ctxt->use_tls = use_tls;
@@ -856,15 +844,15 @@ int parse_ldap_config(struct lookup_context *ctxt)
 	ctxt->secret = secret;
 	ctxt->client_princ = client_princ;
 
-	debug(LOGOPT_NONE,
+	debug(logopt, MODPREFIX
 	      "ldap authentication configured with the following options:");
-	debug(LOGOPT_NONE,
+	debug(logopt, MODPREFIX
 	      "use_tls: %u, "
 	      "tls_required: %u, "
 	      "auth_required: %u, "
 	      "sasl_mech: %s",
 	      use_tls, tls_required, auth_required, authtype);
-	debug(LOGOPT_NONE,
+	debug(logopt, MODPREFIX
 	      "user: %s, "
 	      "secret: %s, "
 	      "client principal: %s",
@@ -889,7 +877,7 @@ out:
  *  Returns ldap connection on success, with authtype, user and secret
  *  filled in as appropriate.  Returns NULL on failre.
  */
-static LDAP *auth_init(const char *uri, struct lookup_context *ctxt)
+static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context *ctxt)
 {
 	int ret;
 	LDAP *ldap;
@@ -900,11 +888,11 @@ static LDAP *auth_init(const char *uri, struct lookup_context *ctxt)
 	 *  if the permissions on the file were incorrect, or if the
 	 *  specified authentication type is not valid.
 	 */
-	ret = parse_ldap_config(ctxt);
+	ret = parse_ldap_config(logopt, ctxt);
 	if (ret)
 		return NULL;
 
-	ldap = init_ldap_connection(uri, ctxt);
+	ldap = init_ldap_connection(logopt, uri, ctxt);
 	if (!ldap)
 		return NULL;
 
@@ -916,7 +904,7 @@ static LDAP *auth_init(const char *uri, struct lookup_context *ctxt)
 	 *  to use. If kerberos is used, it will also take care to initialize
 	 *  the credential cache and the client and service principals.
 	 */
-	ret = autofs_sasl_init(ldap, ctxt);
+	ret = autofs_sasl_init(logopt, ldap, ctxt);
 	if (ret) {
 		ctxt->sasl_mech = NULL;
 		return NULL;
@@ -930,7 +918,7 @@ static LDAP *auth_init(const char *uri, struct lookup_context *ctxt)
  *  Take an input string as specified in the master map, and break it
  *  down into a server name and basedn.
  */
-static int parse_server_string(const char *url, struct lookup_context *ctxt)
+static int parse_server_string(unsigned logopt, const char *url, struct lookup_context *ctxt)
 {
 	char buf[MAX_ERR_BUF], *tmp = NULL, proto[9];
 	const char *ptr, *name;
@@ -939,8 +927,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 	memset(proto, 0, 9);
 	ptr = url;
 
-	debug(LOGOPT_NONE,
-	      MODPREFIX
+	debug(logopt, MODPREFIX
 	      "Attempting to parse LDAP information from string \"%s\".", ptr);
 
 	ctxt->port = LDAP_PORT;
@@ -974,7 +961,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 			if (!tmp) {
 				char *estr;
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+				logerr(MODPREFIX "malloc: %s", estr);
 				return 0;
 			}
 			ctxt->server = tmp;
@@ -987,7 +974,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 				memcpy(ctxt->server, s, l);
 			ptr = q + 1;
 		} else {
-			crit(LOGOPT_ANY,
+			crit(logopt,
 			     MODPREFIX "invalid LDAP map syntax %s", ptr);
 			return 0;
 /* TODO: why did I put this here, the parser shouldn't let this by
@@ -996,7 +983,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 			if (!tmp) {
 				char *estr;
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+				crit(logopt, MODPREFIX "malloc: %s", estr);
 				return 0;
 			}
 			ctxt->server = tmp;
@@ -1014,7 +1001,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 				q++;
 
 		if (*q != ':') {
-			crit(LOGOPT_ANY,
+			crit(logopt,
 			     MODPREFIX "invalid LDAP map syntax %s", ptr);
 			return 0;
 		}
@@ -1031,7 +1018,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 		if (!tmp) {
 			char *estr;
 			estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+			logerr(MODPREFIX "malloc: %s", estr);
 			return 0;
 		}
 		ctxt->server = tmp;
@@ -1072,7 +1059,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 			else {
 				char *estr;
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+				logerr(MODPREFIX "malloc: %s", estr);
 				if (ctxt->server)
 					free(ctxt->server);
 				return 0;
@@ -1083,7 +1070,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 			if (!base) {
 				char *estr;
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+				logerr(MODPREFIX "malloc: %s", estr);
 				if (ctxt->server)
 					free(ctxt->server);
 				return 0;
@@ -1097,7 +1084,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 		if (!map) {
 			char *estr;
 			estr = strerror_r(errno, buf, MAX_ERR_BUF);
-			crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+			logerr(MODPREFIX "malloc: %s", estr);
 			if (ctxt->server)
 				free(ctxt->server);
 			return 0;
@@ -1109,16 +1096,16 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt)
 
 	if (!ctxt->server && *proto) {
 		if (!strncmp(proto, "ldaps", 5)) {
-			warn(LOGOPT_ANY, MODPREFIX
+			info(logopt, MODPREFIX
 			     "server must be given to force ldaps, connection "
 			     "will use LDAP client configured protocol");
 		}
 	}
 done:
 	if (ctxt->mapname)
-		debug(LOGOPT_NONE, MODPREFIX "mapname %s", ctxt->mapname);
+		debug(logopt, MODPREFIX "mapname %s", ctxt->mapname);
 	else
-		debug(LOGOPT_NONE, MODPREFIX "server \"%s\", base dn \"%s\"",
+		debug(logopt, MODPREFIX "server \"%s\", base dn \"%s\"",
 			ctxt->server ? ctxt->server : "(default)",
 			ctxt->base);
 
@@ -1175,8 +1162,6 @@ static void validate_uris(struct list_head *list)
 
 		/* 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);
@@ -1202,7 +1187,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return 1;
 	}
 	memset(ctxt, 0, sizeof(struct lookup_context));
@@ -1215,7 +1200,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	 * Parse out the server name and base dn, and fill them
 	 * into the proper places in the lookup context structure.
 	 */
-	if (!parse_server_string(argv[0], ctxt)) {
+	if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) {
 		error(LOGOPT_ANY, MODPREFIX "cannot parse server string");
 		free_context(ctxt);
 		return 1;
@@ -1236,13 +1221,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	}
 
 	if (ctxt->server || !ctxt->uri) {
-		ldap = connect_to_server(ctxt->server, ctxt);
+		ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt);
 		if (!ldap) {
 			free_context(ctxt);
 			return 1;
 		}
 	} else {
-		ldap = find_server(ctxt);
+		ldap = find_server(LOGOPT_NONE, ctxt);
 		if (!ldap) {
 			free_context(ctxt);
 			error(LOGOPT_ANY, MODPREFIX
@@ -1250,13 +1235,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 			return 1;
 		}
 	}
-	unbind_ldap_connection(ldap, ctxt);
+	unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt);
 
 	/* Open the parser, if we can. */
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parse) {
 		free_context(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logerr(MODPREFIX "failed to open parse context");
 		return 1;
 	}
 	*context = ctxt;
@@ -1269,6 +1254,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	unsigned int timeout = master->default_timeout;
 	unsigned int logging = master->default_logging;
+	unsigned int logopt = master->logopt;
 	int rv, l, count, blen;
 	char buf[PARSE_MAX_BUF];
 	char *query;
@@ -1293,45 +1279,44 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	query = alloca(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
 	if (sprintf(query, "(objectclass=%s)", class) >= l) {
-		debug(LOGOPT_NONE, MODPREFIX "error forming query string");
+		error(logopt, MODPREFIX "error forming query string");
 		return NSS_STATUS_UNAVAIL;
 	}
 	query[l] = '\0';
 
 	/* Initialize the LDAP context. */
-	ldap = do_reconnect(ctxt);
+	ldap = do_reconnect(logopt, ctxt);
 	if (!ldap)
 		return NSS_STATUS_UNAVAIL;
 
 	/* Look around. */
-	debug(LOGOPT_NONE,
+	debug(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) {
-		error(LOGOPT_NONE,
-		      MODPREFIX "query failed for %s: %s",
+		error(logopt, MODPREFIX "query failed for %s: %s",
 		      query, ldap_err2string(rv));
-		unbind_ldap_connection(ldap, ctxt);
+		unbind_ldap_connection(logging, ldap, ctxt);
 		return NSS_STATUS_NOTFOUND;
 	}
 
 	e = ldap_first_entry(ldap, result);
 	if (!e) {
-		debug(LOGOPT_NONE,
+		debug(logopt,
 		      MODPREFIX "query succeeded, no matches for %s",
 		      query);
 		ldap_msgfree(result);
-		unbind_ldap_connection(ldap, ctxt);
+		unbind_ldap_connection(logging, ldap, ctxt);
 		return NSS_STATUS_NOTFOUND;
 	} else
-		debug(LOGOPT_NONE, MODPREFIX "examining entries");
+		debug(logopt, MODPREFIX "examining entries");
 
 	while (e) {
 		keyValue = ldap_get_values(ldap, e, entry);
@@ -1346,7 +1331,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		 * each map entry
 		 */
 		if (ldap_count_values(keyValue) > 1) {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      MODPREFIX
 			      "key %s has duplicate entries - ignoring",
 			      *keyValue);
@@ -1358,7 +1343,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		 * inclusion is only valid in file maps.
 		 */
 		if (**keyValue == '+') {
-			warn(LOGOPT_ANY,
+			warn(logopt,
 			     MODPREFIX
 			     "ignoreing '+' map entry - not in file map");
 			goto next;
@@ -1366,7 +1351,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 
 		values = ldap_get_values(ldap, e, info);
 		if (!values || !*values) {
-			debug(LOGOPT_NONE,
+			debug(logopt,
 			      MODPREFIX "no %s defined for %s", info, query);
 			goto next;
 		}
@@ -1376,7 +1361,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		 */
 		count = ldap_count_values(values);
 		if (count > 1) {
-			error(LOGOPT_ANY,
+			error(logopt,
 			      MODPREFIX
 			      "one value per key allowed in master map");
 			ldap_value_free(values);
@@ -1385,7 +1370,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 
 		blen = strlen(*keyValue) + 1 + strlen(*values) + 1;
 		if (blen > PARSE_MAX_BUF) {
-			error(LOGOPT_ANY, MODPREFIX "map entry too long");
+			error(logopt, MODPREFIX "map entry too long");
 			ldap_value_free(values);
 			goto next;
 		}
@@ -1403,7 +1388,7 @@ next:
 
 	/* Clean up. */
 	ldap_msgfree(result);
-	unbind_ldap_connection(ldap, ctxt);
+	unbind_ldap_connection(logopt, ldap, ctxt);
 
 	return NSS_STATUS_SUCCESS;
 }
@@ -1445,7 +1430,7 @@ static int read_one_map(struct autofs_point *ap,
 	query = alloca(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
@@ -1456,7 +1441,7 @@ static int read_one_map(struct autofs_point *ap,
 	query[l] = '\0';
 
 	/* Initialize the LDAP context. */
-	ldap = do_reconnect(ctxt);
+	ldap = do_reconnect(ap->logopt, ctxt);
 	if (!ldap)
 		return NSS_STATUS_UNAVAIL;
 
@@ -1470,7 +1455,7 @@ static int read_one_map(struct autofs_point *ap,
 		debug(ap->logopt,
 		      MODPREFIX "query failed for %s: %s",
 		      query, ldap_err2string(rv));
-		unbind_ldap_connection(ldap, ctxt);
+		unbind_ldap_connection(ap->logopt, ldap, ctxt);
 		*result_ldap = rv;
 		return NSS_STATUS_NOTFOUND;
 	}
@@ -1480,7 +1465,7 @@ static int read_one_map(struct autofs_point *ap,
 		debug(ap->logopt,
 		      MODPREFIX "query succeeded, no matches for %s", query);
 		ldap_msgfree(result);
-		unbind_ldap_connection(ldap, ctxt);
+		unbind_ldap_connection(ap->logopt, ldap, ctxt);
 		return NSS_STATUS_NOTFOUND;
 	} else
 		debug(ap->logopt, MODPREFIX "examining entries");
@@ -1612,8 +1597,7 @@ static int read_one_map(struct autofs_point *ap,
 				if (!mapent) {
 					char *estr;
 					estr = strerror_r(errno, buf, MAX_ERR_BUF);
-					error(ap->logopt,
-					      MODPREFIX "malloc: %s", estr);
+					logerr(MODPREFIX "malloc: %s", estr);
 					ldap_value_free_len(bvValues);
 					goto next;
 				}
@@ -1633,8 +1617,7 @@ static int read_one_map(struct autofs_point *ap,
 				} else {
 					char *estr;
 					estr = strerror_r(errno, buf, MAX_ERR_BUF);
-					error(ap->logopt,
-					      MODPREFIX "realloc: %s", estr);
+					logerr(MODPREFIX "realloc: %s", estr);
 				}
 			}
 		}
@@ -1669,7 +1652,7 @@ next:
 
 	/* Clean up. */
 	ldap_msgfree(result);
-	unbind_ldap_connection(ldap, ctxt);
+	unbind_ldap_connection(ap->logopt, ldap, ctxt);
 
 	source->age = age;
 
@@ -1766,7 +1749,7 @@ static int lookup_one(struct autofs_point *ap,
 	query[ql] = '\0';
 
 	/* Initialize the LDAP context. */
-	ldap = do_reconnect(ctxt);
+	ldap = do_reconnect(ap->logopt, ctxt);
 	if (!ldap)
 		return CHE_FAIL;
 
@@ -1777,7 +1760,7 @@ static int lookup_one(struct autofs_point *ap,
 
 	if ((rv != LDAP_SUCCESS) || !result) {
 		crit(ap->logopt, MODPREFIX "query failed for %s", query);
-		unbind_ldap_connection(ldap, ctxt);
+		unbind_ldap_connection(ap->logopt, ldap, ctxt);
 		return CHE_FAIL;
 	}
 
@@ -1789,7 +1772,7 @@ static int lookup_one(struct autofs_point *ap,
 		debug(ap->logopt,
 		     MODPREFIX "got answer, but no entry for %s", query);
 		ldap_msgfree(result);
-		unbind_ldap_connection(ldap, ctxt);
+		unbind_ldap_connection(ap->logopt, ldap, ctxt);
 		return CHE_MISSING;
 	}
 
@@ -1897,8 +1880,7 @@ static int lookup_one(struct autofs_point *ap,
 				if (!mapent) {
 					char *estr;
 					estr = strerror_r(errno, buf, MAX_ERR_BUF);
-					error(ap->logopt,
-					      MODPREFIX "malloc: %s", estr);
+					logerr(MODPREFIX "malloc: %s", estr);
 					ldap_value_free_len(bvValues);
 					goto next;
 				}
@@ -1918,8 +1900,7 @@ static int lookup_one(struct autofs_point *ap,
 				} else {
 					char *estr;
 					estr = strerror_r(errno, buf, MAX_ERR_BUF);
-					error(ap->logopt,
-					      MODPREFIX "realloc: %s", estr);
+					logerr(MODPREFIX "realloc: %s", estr);
 				}
 			}
 		}
@@ -1955,7 +1936,7 @@ next:
 	}
 
 	ldap_msgfree(result);
-	unbind_ldap_connection(ldap, ctxt);
+	unbind_ldap_connection(ap->logopt, ldap, ctxt);
 
 	/* Failed to find wild entry, update cache if needed */
 	pthread_cleanup_push(cache_lock_cleanup, mc);
diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c
index 8fa94ae..601d48e 100644
--- a/modules/lookup_multi.c
+++ b/modules/lookup_multi.c
@@ -73,7 +73,7 @@ static struct lookup_mod *nss_open_lookup(const char *format, int argc, const ch
 	if (nsswitch_parse(&nsslist)) {
 		if (!list_empty(&nsslist))
 			free_sources(&nsslist);
-		error(LOGOPT_ANY, "can't to read name service switch config.");
+		logerr("can't to read name service switch config.");
 		return NULL;
 	}
 
@@ -92,7 +92,7 @@ static struct lookup_mod *nss_open_lookup(const char *format, int argc, const ch
 			path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(argv[0]) + 2);
 			if (!path) {
 				estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				crit(LOGOPT_ANY, MODPREFIX "error: %s", estr);
+				logerr(MODPREFIX "error: %s", estr);
 				free_sources(&nsslist);
 				return NULL;
 			}
@@ -150,7 +150,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 	memset(ctxt, 0, sizeof(struct lookup_context));
 
 	if (argc < 1) {
-		crit(LOGOPT_ANY, MODPREFIX "No map list");
+		logerr(MODPREFIX "No map list");
 		goto error_out;
 	}
 
@@ -176,8 +176,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 		if (!strcmp(ctxt->argl[an], "--")) {
 			ctxt->argl[an] = NULL;
 			if (!args) {
-				crit(LOGOPT_ANY,
-				     MODPREFIX "error assigning map args");
+				logerr(MODPREFIX "error assigning map args");
 				goto error_out;
 			}
 			ctxt->m[i].argv = copy_argv(ctxt->m[i].argc, (const char **) args);
@@ -201,7 +200,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 		ctxt->m[i].mod = nss_open_lookup(my_mapfmt,
 				 ctxt->m[i].argc, ctxt->m[i].argv);
 		if (!ctxt->m[i].mod) {
-			error(LOGOPT_ANY, MODPREFIX "error opening module");
+			logerr(MODPREFIX "error opening module");
 			goto error_out;
 		}
 	}
@@ -211,7 +210,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
 
 nomem:
 	estr = strerror_r(errno, buf, MAX_ERR_BUF);
-	crit(LOGOPT_ANY, MODPREFIX "error: %s", estr);
+	logerr(MODPREFIX "error: %s", estr);
 error_out:
 	if (ctxt) {
 		for (i = 0; i < ctxt->n; i++) {
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index 83e99e0..ff8bd49 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -41,13 +41,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "%s", estr);
+		logerr(MODPREFIX "%s", estr);
 		return 1;
 	}
 
 	if (argc < 1) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "No map name");
+		logmsg(MODPREFIX "No map name");
 		return 1;
 	}
 	ctxt->mapname = argv[0];
@@ -59,7 +59,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt->domainname = nis_local_directory();
 	if (!ctxt->domainname) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "NIS+ domain not set");
+		logmsg(MODPREFIX "NIS+ domain not set");
 		return 1;
 	}
 
@@ -69,7 +69,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parse) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logerr(MODPREFIX "failed to open parse context");
 		return 1;
 	}
 	*context = ctxt;
@@ -81,7 +81,8 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 {
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	unsigned int timeout = master->default_timeout;
-	unsigned int logging =  master->default_logging;
+	unsigned int logging = master->default_logging;
+	unsigned int logopt =  master->logopt;
 	char *tablename;
 	nis_result *result;
 	nis_object *this;
@@ -95,7 +96,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -105,8 +106,8 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	result = nis_lookup(tablename, FOLLOW_PATH | FOLLOW_LINKS);
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
 		nis_freeresult(result);
-		crit(LOGOPT_ANY,
-		     MODPREFIX "couldn't locat nis+ table %s", ctxt->mapname);
+		crit(logopt,
+		     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_NOTFOUND;
 	}
@@ -116,7 +117,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
 		nis_freeresult(result);
-		crit(LOGOPT_ANY,
+		crit(logopt,
 		     MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
@@ -139,8 +140,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 
 		buffer = malloc(ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 1);
 		if (!buffer) {
-			error(LOGOPT_ANY,
-			      MODPREFIX "could not malloc parse buffer");
+			logerr(MODPREFIX "could not malloc parse buffer");
 			continue;
 		}
 
@@ -182,7 +182,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_UNAVAIL;
 	}
@@ -193,7 +193,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 	if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
 		nis_freeresult(result);
 		crit(ap->logopt,
-		     MODPREFIX "couldn't locat nis+ table %s", ctxt->mapname);
+		     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_NOTFOUND;
 	}
@@ -274,7 +274,7 @@ static int lookup_one(struct autofs_point *ap,
 			strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return -1;
 	}
@@ -327,7 +327,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
 	tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
 	if (!tablename) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		pthread_setcancelstate(cur_state, NULL);
 		return -1;
 	}
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
index 2fd521a..e28168e 100644
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -51,28 +51,26 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return 1;
 	}
 
 	if (argc < 1) {
-		crit(LOGOPT_ANY, MODPREFIX "No map name");
+		logmsg(MODPREFIX "No map name");
 		free(ctxt);
 		return 1;
 	}
 	ctxt->mapname = argv[0];
 
 	if (ctxt->mapname[0] != '/') {
-		crit(LOGOPT_ANY,
-		     MODPREFIX "program map %s is not an absolute pathname",
+		logmsg(MODPREFIX "program map %s is not an absolute pathname",
 		     ctxt->mapname);
 		free(ctxt);
 		return 1;
 	}
 
 	if (access(ctxt->mapname, X_OK)) {
-		crit(LOGOPT_ANY,
-		     MODPREFIX "program map %s missing or not executable",
+		logmsg(MODPREFIX "program map %s missing or not executable",
 		     ctxt->mapname);
 		free(ctxt);
 		return 1;
@@ -83,7 +81,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parse) {
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logmsg(MODPREFIX "failed to open parse context");
 		free(ctxt);
 		return 1;
 	}
@@ -163,7 +161,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	mapent = (char *) malloc(MAPENT_MAX_LEN + 1);
 	if (!mapent) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
@@ -176,7 +174,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	 */
 	if (pipe(pipefd)) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "pipe: %s", estr);
+		logerr(MODPREFIX "pipe: %s", estr);
 		goto out_free;
 	}
 	if (pipe(epipefd)) {
@@ -188,7 +186,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	f = fork();
 	if (f < 0) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "fork: %s", estr);
+		logerr(MODPREFIX "fork: %s", estr);
 		close(pipefd[0]);
 		close(pipefd[1]);
 		close(epipefd[0]);
@@ -271,8 +269,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 						       ++alloci));
 					if (!tmp) {
 						alloci--;
-						error(ap->logopt,
-						      MODPREFIX "realloc: %s",
+						logerr(MODPREFIX "realloc: %s",
 						      strerror(errno));
 						break;
 					}
@@ -308,12 +305,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 			} else if (ch == '\n') {
 				*errp = '\0';
 				if (errbuf[0])
-					error(ap->logopt, ">> %s", errbuf);
+					logmsg(">> %s", errbuf);
 				errp = errbuf;
 			} else {
 				if (errp >= &errbuf[1023]) {
 					*errp = '\0';
-					error(ap->logopt, ">> %s", errbuf);
+					logmsg(">> %s", errbuf);
 					errp = errbuf;
 				}
 				*(errp++) = ch;
@@ -325,7 +322,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 		*mapp = '\0';
 	if (errp > errbuf) {
 		*errp = '\0';
-		error(ap->logopt, ">> %s", errbuf);
+		logmsg(">> %s", errbuf);
 	}
 
 	close(pipefd[0]);
@@ -333,12 +330,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	if (waitpid(f, &status, 0) != f) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "waitpid: %s", estr);
+		logerr(MODPREFIX "waitpid: %s", estr);
 		goto out_free;
 	}
 
 	if (mapp == mapent || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-		msg(MODPREFIX "lookup for %s failed", name);
+		info(ap->logopt, MODPREFIX "lookup for %s failed", name);
 		goto out_free;
 	}
 
diff --git a/modules/lookup_userhome.c b/modules/lookup_userhome.c
index efcab0b..680ddaf 100644
--- a/modules/lookup_userhome.c
+++ b/modules/lookup_userhome.c
@@ -73,7 +73,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	/* Create the appropriate symlink */
 	if (chdir(ap->path)) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "chdir failed: %s", estr);
+		logerr(MODPREFIX "chdir failed: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
@@ -88,7 +88,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	if (symlink(pw->pw_dir, name) && errno != EEXIST) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "symlink failed: %s", estr);
+		logerr(MODPREFIX "symlink failed: %s", estr);
 		return NSS_STATUS_UNAVAIL;
 	}
 
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index da280cc..63fc8e3 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -45,12 +45,14 @@ struct lookup_context {
 struct callback_master_data {
 	unsigned timeout;
 	unsigned logging;
+	unsigned logopt;
 	time_t age;
 };
 
 struct callback_data {
 	struct autofs_point *ap;
 	struct map_source *source;
+	unsigned logopt;
 	time_t age;
 };
 
@@ -111,20 +113,18 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt = malloc(sizeof(struct lookup_context));
 	if (!ctxt) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "%s", estr);
+		logerr(MODPREFIX "%s", estr);
 		return 1;
 	}
 	memset(ctxt, 0, sizeof(struct lookup_context));
 
 	if (argc < 1) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "no map name");
+		logerr(MODPREFIX "no map name");
 		return 1;
 	}
 	ctxt->mapname = argv[0];
 
-	debug(LOGOPT_NONE, MODPREFIX "ctxt->mapname=%s", ctxt->mapname);
-
 	/* This should, but doesn't, take a const char ** */
 	err = yp_get_default_domain((char **) &ctxt->domainname);
 	if (err) {
@@ -133,8 +133,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		memcpy(name, ctxt->mapname, len);
 		name[len] = '\0';
 		free(ctxt);
-		debug(LOGOPT_NONE, MODPREFIX "map %s: %s", name,
-		       yperr_string(err));
+		logerr(MODPREFIX "map %s: %s", name, yperr_string(err));
 		return 1;
 	}
 
@@ -146,7 +145,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
 	if (!ctxt->parse) {
 		free(ctxt);
-		crit(LOGOPT_ANY, MODPREFIX "failed to open parse context");
+		logmsg(MODPREFIX "failed to open parse context");
 		return 1;
 	}
 	*context = ctxt;
@@ -161,6 +160,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen,
 			(struct callback_master_data *) ypcb_data;
 	unsigned int timeout = cbdata->timeout;
 	unsigned int logging = cbdata->logging;
+	unsigned int logopt = cbdata->logopt;
 	time_t age = cbdata->age;
 	char *buffer;
 	unsigned int len;
@@ -182,7 +182,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen,
 
 	buffer = alloca(len);
 	if (!buffer) {
-		error(LOGOPT_ANY, MODPREFIX "could not malloc parse buffer");
+		error(logopt, MODPREFIX "could not malloc parse buffer");
 		return 0;
 	}
 	memset(buffer, 0, len);
@@ -201,6 +201,8 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	struct ypall_callback ypcb;
 	struct callback_master_data ypcb_data;
+	unsigned int logging = master->default_logging;
+	unsigned int logopt = master->logopt;
 	char *mapname;
 	int err;
 
@@ -211,7 +213,8 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	strcpy(mapname, ctxt->mapname);
 
 	ypcb_data.timeout = master->default_timeout;
-	ypcb_data.logging = master->default_logging;
+	ypcb_data.logging = logging;
+	ypcb_data.logopt = logopt;
 	ypcb_data.age = age;
 
 	ypcb.foreach = yp_all_master_callback;
@@ -232,7 +235,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		if (err == YPERR_SUCCESS)
 			return NSS_STATUS_SUCCESS;
 
-		warn(LOGOPT_ANY,
+		info(logopt,
 		     MODPREFIX "read of master map %s failed: %s",
 		     mapname, yperr_string(err));
 
@@ -249,6 +252,7 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen,
 	struct autofs_point *ap = cbdata->ap;
 	struct map_source *source = cbdata->source;
 	struct mapent_cache *mc = source->mc;
+	unsigned int logopt = cbdata->logopt;
 	time_t age = cbdata->age;
 	char *key, *mapent;
 	int ret;
@@ -264,8 +268,10 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen,
 		return 0;
 
 	key = sanitize_path(ypkey, ypkeylen, ap->type, ap->logopt);
-	if (!key)
+	if (!key) {
+		error(logopt, MODPREFIX "invalid path %s", ypkey);
 		return 0;
+	}
 
 	mapent = alloca(vallen + 1);
 	strncpy(mapent, val, vallen);
@@ -288,6 +294,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	struct ypall_callback ypcb;
 	struct callback_data ypcb_data;
+	unsigned int logopt = ap->logopt;
 	struct map_source *source;
 	char *mapname;
 	int err;
@@ -298,6 +305,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 
 	ypcb_data.ap = ap;
 	ypcb_data.source = source;
+	ypcb_data.logopt = logopt;
 	ypcb_data.age = age;
 
 	ypcb.foreach = yp_all_callback;
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index c45b91b..356fb14 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -64,7 +64,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
 	fullpath = alloca(strlen(root) + name_len + 2);
 	if (!fullpath) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		return 1;
 	}
 
@@ -156,7 +156,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
 	}
 	nap = entry->ap;
 	nap->parent = ap;
-	set_mnt_logging(nap);
 
 	argc = 1;
 
@@ -208,7 +207,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
 		return 1;
 	}
 
-	source->mc = cache_init(source);
+	source->mc = cache_init(entry->ap, source);
 	if (!source->mc) {
 		error(ap->logopt, MODPREFIX "failed to init source cache");
 		master_free_mapent(entry);
diff --git a/modules/mount_bind.c b/modules/mount_bind.c
index cb17ce4..04284f5 100644
--- a/modules/mount_bind.c
+++ b/modules/mount_bind.c
@@ -52,16 +52,14 @@ int mount_init(void **context)
 	if (lstat(t1_dir, &st1) == -1)
 		goto out;
 
-	err = spawn_mount(log_debug, "-n", "--bind", t1_dir, t2_dir, NULL);
+	err = spawn_mount(LOGOPT_NONE, "-n", "--bind", t1_dir, t2_dir, NULL);
 	if (err == 0 &&
 	    lstat(t2_dir, &st2) == 0 &&
 	    st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
 		bind_works = 1;
 	}
 
-	debug(LOGOPT_NONE, MODPREFIX "bind_works = %d", bind_works);
-
-	spawn_umount(log_debug, "-n", t2_dir, NULL);
+	spawn_umount(LOGOPT_NONE, "-n", t2_dir, NULL);
 
 out:
 	rmdir(t1_dir);
@@ -91,7 +89,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	fullpath = alloca(rlen + name_len + 2);
 	if (!fullpath) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		return 1;
 	}
 
@@ -139,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 		      "calling mount --bind " SLOPPY " -o %s %s %s",
 		      options, what, fullpath);
 
-		err = spawn_bind_mount(log_debug,
+		err = spawn_bind_mount(ap->logopt,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 
 		if (err) {
diff --git a/modules/mount_changer.c b/modules/mount_changer.c
index 6e04c7c..08d9147 100644
--- a/modules/mount_changer.c
+++ b/modules/mount_changer.c
@@ -66,7 +66,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	fullpath = alloca(rlen + name_len + 2);
 	if (!fullpath) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		return 1;
 	}
 
@@ -80,7 +80,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 
 	debug(ap->logopt, MODPREFIX "calling umount %s", what);
 
-	err = spawn_umount(log_debug, what, NULL);
+	err = spawn_umount(ap->logopt, what, NULL);
 	if (err) {
 		error(ap->logopt,
 		      MODPREFIX
@@ -115,18 +115,18 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 		      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
 		      fstype, options, what, fullpath);
 
-		err = spawn_mount(log_debug, "-t", fstype,
+		err = spawn_mount(ap->logopt, "-t", fstype,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 	} else {
 		debug(ap->logopt,
 		      MODPREFIX "calling mount -t %s %s %s",
 		      fstype, what, fullpath);
 
-		err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL);
+		err = spawn_mount(ap->logopt, "-t", fstype, what, fullpath, NULL);
 	}
 
 	if (err) {
-		msg(MODPREFIX "failed to mount %s (type %s) on %s",
+		info(ap->logopt, MODPREFIX "failed to mount %s (type %s) on %s",
 		    what, fstype, fullpath);
 
 		if (ap->type != LKP_INDIRECT)
@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 
 		return 1;
 	} else {
-		msg(MODPREFIX "mounted %s type %s on %s",
+		info(ap->logopt, MODPREFIX "mounted %s type %s on %s",
 		    what, fstype, fullpath);
 		return 0;
 	}
@@ -161,7 +161,7 @@ int swapCD(const char *device, const char *slotName)
 	/* open device */
 	fd = open(device, O_RDONLY | O_NONBLOCK);
 	if (fd < 0) {
-		error(LOGOPT_ANY, MODPREFIX "Opening device %s failed : %s",
+		logerr(MODPREFIX "Opening device %s failed : %s",
 		      device, strerror(errno));
 		return 1;
 	}
@@ -174,7 +174,7 @@ int swapCD(const char *device, const char *slotName)
 	/* Check CD player status */
 	total_slots_available = ioctl(fd, CDROM_CHANGER_NSLOTS);
 	if (total_slots_available <= 1) {
-		error(LOGOPT_ANY, MODPREFIX
+		logerr(MODPREFIX
 		      "Device %s is not an ATAPI compliant CD changer.",
 		      device);
 		return 1;
@@ -183,14 +183,14 @@ int swapCD(const char *device, const char *slotName)
 	/* load */
 	slot = ioctl(fd, CDROM_SELECT_DISC, slot);
 	if (slot < 0) {
-		error(LOGOPT_ANY, MODPREFIX "CDROM_SELECT_DISC failed");
+		logerr(MODPREFIX "CDROM_SELECT_DISC failed");
 		return 1;
 	}
 
 	/* close device */
 	status = close(fd);
 	if (status != 0) {
-		error(LOGOPT_ANY, MODPREFIX "close failed for `%s': %s",
+		logerr(MODPREFIX "close failed for `%s': %s",
 		      device, strerror(errno));
 		return 1;
 	}
diff --git a/modules/mount_ext2.c b/modules/mount_ext2.c
index 45f0615..8cf9937 100644
--- a/modules/mount_ext2.c
+++ b/modules/mount_ext2.c
@@ -58,7 +58,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	fullpath = alloca(rlen + name_len + 2);
 	if (!fullpath) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		return 1;
 	}
 
@@ -108,11 +108,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	if (ro) {
 		debug(ap->logopt,
 		      MODPREFIX "calling %s -n %s", fsck_prog, what);
-		err = spawnl(log_debug, fsck_prog, fsck_prog, "-n", what, NULL);
+		err = spawnl(ap->logopt, fsck_prog, fsck_prog, "-n", what, NULL);
 	} else {
 		debug(ap->logopt,
 		      MODPREFIX "calling %s -p %s", fsck_prog, what);
-		err = spawnl(log_debug, fsck_prog, fsck_prog, "-p", what, NULL);
+		err = spawnl(ap->logopt, fsck_prog, fsck_prog, "-p", what, NULL);
 	}
 
 	/*
@@ -132,17 +132,17 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 		debug(ap->logopt,
 		      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
 		      fstype, options, what, fullpath);
-		err = spawn_mount(log_debug, "-t", fstype,
+		err = spawn_mount(ap->logopt, "-t", fstype,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 	} else {
 		debug(ap->logopt,
 		      MODPREFIX "calling mount -t %s %s %s",
 		      fstype, what, fullpath);
-		err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL);
+		err = spawn_mount(ap->logopt, "-t", fstype, what, fullpath, NULL);
 	}
 
 	if (err) {
-		msg(MODPREFIX "failed to mount %s (type %s) on %s",
+		info(ap->logopt, MODPREFIX "failed to mount %s (type %s) on %s",
 		    what, fstype, fullpath);
 
 		if (ap->type != LKP_INDIRECT)
@@ -153,7 +153,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 
 		return 1;
 	} else {
-		debug(ap->logopt,
+		info(ap->logopt,
 		      MODPREFIX "mounted %s type %s on %s",
 		      what, fstype, fullpath);
 		return 0;
diff --git a/modules/mount_generic.c b/modules/mount_generic.c
index 1f43baa..85b4391 100644
--- a/modules/mount_generic.c
+++ b/modules/mount_generic.c
@@ -57,7 +57,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	fullpath = alloca(rlen + name_len + 2);
 	if (!fullpath) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		return 1;
 	}
 
@@ -93,16 +93,16 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 		      MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s",
 		      fstype, options, what, fullpath);
 
-		err = spawn_mount(log_debug, "-t", fstype,
+		err = spawn_mount(ap->logopt, "-t", fstype,
 			     SLOPPYOPT "-o", options, what, fullpath, NULL);
 	} else {
 		debug(ap->logopt, MODPREFIX "calling mount -t %s %s %s",
 		      fstype, what, fullpath);
-		err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL);
+		err = spawn_mount(ap->logopt, "-t", fstype, what, fullpath, NULL);
 	}
 
 	if (err) {
-		msg(MODPREFIX "failed to mount %s (type %s) on %s",
+		info(ap->logopt, MODPREFIX "failed to mount %s (type %s) on %s",
 		     what, fstype, fullpath);
 
 		if (ap->type != LKP_INDIRECT)
@@ -113,7 +113,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 
 		return 1;
 	} else {
-		msg(MODPREFIX "mounted %s type %s on %s",
+		info(ap->logopt, MODPREFIX "mounted %s type %s on %s",
 		    what, fstype, fullpath);
 		return 0;
 	}
diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index e4480c5..bad21fc 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -133,14 +133,14 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	else
 		vers = NFS_VERS_MASK | NFS_PROTO_MASK;
 
-	if (!parse_location(&hosts, what)) {
-		warn(ap->logopt, MODPREFIX "no hosts available");
+	if (!parse_location(ap->logopt, &hosts, what)) {
+		info(ap->logopt, MODPREFIX "no hosts available");
 		return 1;
 	}
-	prune_host_list(&hosts, vers, nfsoptions, ap->random_selection);
+	prune_host_list(ap->logopt, &hosts, vers, nfsoptions, ap->random_selection);
 
 	if (!hosts) {
-		warn(ap->logopt, MODPREFIX "no hosts available");
+		info(ap->logopt, MODPREFIX "no hosts available");
 		return 1;
 	}
 
@@ -159,7 +159,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 	fullpath = alloca(rlen + name_len + 2);
 	if (!fullpath) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		error(ap->logopt, MODPREFIX "alloca: %s", estr);
+		logerr(MODPREFIX "alloca: %s", estr);
 		free_host_list(&hosts);
 		return 1;
 	}
@@ -252,19 +252,19 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 			      MODPREFIX "calling mount -t %s " SLOPPY 
 			      "-o %s %s %s", fstype, nfsoptions, loc, fullpath);
 
-			err = spawn_mount(log_debug,
+			err = spawn_mount(ap->logopt,
 					  "-t", fstype, SLOPPYOPT "-o",
 					  nfsoptions, loc, fullpath, NULL);
 		} else {
 			debug(ap->logopt,
 			      MODPREFIX "calling mount -t %s %s %s",
 			      fstype, loc, fullpath);
-			err = spawn_mount(log_debug,
+			err = spawn_mount(ap->logopt,
 					  "-t", fstype, loc, fullpath, NULL);
 		}
 
 		if (!err) {
-			msg(MODPREFIX "mounted %s on %s", loc, fullpath);
+			info(ap->logopt, MODPREFIX "mounted %s on %s", loc, fullpath);
 			free(loc);
 			free_host_list(&hosts);
 			ap->ghost = save_ghost;
@@ -280,7 +280,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 
 	/* If we get here we've failed to complete the mount */
 
-	msg(MODPREFIX "nfs: mount failure %s on %s", what, fullpath);
+	info(ap->logopt, MODPREFIX "nfs: mount failure %s on %s", what, fullpath);
 
 	if (ap->type != LKP_INDIRECT)
 		return 1;
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 079bda6..186e567 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -277,7 +277,7 @@ int parse_init(int argc, const char *const *argv, void **context)
 
 	if (!(ctxt = (struct parse_context *) malloc(sizeof(struct parse_context)))) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-		crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr);
+		logerr(MODPREFIX "malloc: %s", estr);
 		*context = NULL;
 		return 1;
 	}
@@ -302,7 +302,7 @@ int parse_init(int argc, const char *const *argv, void **context)
 
 				if (!def) {
 					char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-					error(LOGOPT_ANY, MODPREFIX "strdup: %s", estr);
+					logerr(MODPREFIX "strdup: %s", estr);
 					break;
 				}
 
@@ -387,7 +387,7 @@ int parse_init(int argc, const char *const *argv, void **context)
 			if (!noptstr) {
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 				kill_context(ctxt);
-				crit(LOGOPT_ANY, MODPREFIX "%s", estr);
+				logerr(MODPREFIX "%s", estr);
 				*context = NULL;
 				return 1;
 			}
@@ -408,7 +408,7 @@ int parse_init(int argc, const char *const *argv, void **context)
 			char *tmp = concat_options(gbl_options, ctxt->optstr);
 			if (!tmp) {
 				char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
-				error(LOGOPT_ANY, MODPREFIX "concat_options: %s", estr);
+				logerr(MODPREFIX "concat_options: %s", estr);
 				free(gbl_options);
 			} else
 				ctxt->optstr = tmp;
@@ -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;
diff --git a/CHANGELOG b/CHANGELOG
index a7ac9fb..93c79cf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -36,6 +36,7 @@
 - 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).
 
 18/06/2007 autofs-5.0.2
 -----------------------
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--) {
diff --git a/CHANGELOG b/CHANGELOG
index 93c79cf..ca290f9 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -37,6 +37,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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);
diff --git a/CHANGELOG b/CHANGELOG
index ca290f9..5e3a9ec 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -38,6 +38,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 00cd223..48bc233 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -109,6 +109,7 @@ AT_O		([oO])
 AT_C		([cC])
 DNATTRSTR	{AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}
 DNNAMESTR	([[:alnum:]_.\-]+)
+DNNAMETRM	(,|{WS}{NL}|{WS}#.*|\x00)
 
 INTMAP		(-hosts|-null)
 MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
@@ -281,7 +282,7 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 		return EQUAL;
 	}
 
-	{DNNAMESTR} {
+	{DNNAMESTR}/{DNNAMETRM} {
 		strcpy(master_lval.strtype, master_text);
 		return DNNAME;
 	}
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) {
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 48bc233..5450753 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -108,8 +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:]_.\-]+)
-DNNAMETRM	(,|{WS}{NL}|{WS}#.*|\x00)
+DNNAMESTR	([[:alnum:]_.\- ]+)
+DNNAMETRM	(,|{OPTWS}{NL}|{OPTWS}#.*|{OPTWS}\x00)
 
 INTMAP		(-hosts|-null)
 MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
@@ -379,7 +379,13 @@ void master_set_scan_buffer(const char *buffer)
 {
 	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 --git a/modules/lookup_file.c b/modules/lookup_file.c
index 921b32b..c093415 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -479,7 +479,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 
 			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 --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 00215af..dfb3054 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1368,7 +1368,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			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 --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index ff8bd49..bcdaeeb 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -90,7 +90,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 	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 *master, time_t age, void *context)
 
 		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 --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 63fc8e3..7ba6940 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -178,7 +178,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen,
 	*(ypkey + ypkeylen) = '\0';
 	*(val + vallen) = '\0';
 
-	len = ypkeylen + 1 + vallen + 1;
+	len = ypkeylen + 1 + vallen + 2;
 
 	buffer = alloca(len);
 	if (!buffer) {
diff --git a/CHANGELOG b/CHANGELOG
index 5e3a9ec..795ec30 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -39,6 +39,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/spawn.c b/daemon/spawn.c
index ab3274c..0ed873e 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -268,9 +268,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 +285,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 +307,40 @@ int spawn_mount(unsigned logopt, ...)
 
 	while (retries--) {
 		ret = do_spawn(logopt, options, prog, (const char **) argv);
-		if (ret & MTAB_NOTUPDATED)
+		if (ret & MTAB_NOTUPDATED) {
+			/*
+			 * 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;
+			}
 			continue;
+		}
 		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;
 }
 
@@ -328,9 +360,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 +373,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 +394,40 @@ 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) {
+			/*
+			 * 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;
+			}
 			continue;
+		}
 		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;
 }
 
@@ -373,7 +440,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 +464,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;
diff --git a/lib/master_tok.l b/lib/master_tok.l
index 5450753..36aa785 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -108,8 +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:]_.\- ]+)
-DNNAMETRM	(,|{OPTWS}{NL}|{OPTWS}#.*|{OPTWS}\x00)
+DNNAMESTR1	([[:alnum:]_.\- ]+)
+DNNAMESTR2	([[:alnum:]_.\-]+)
 
 INTMAP		(-hosts|-null)
 MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
@@ -282,7 +282,12 @@ OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
 		return EQUAL;
 	}
 
-	{DNNAMESTR}/{DNNAMETRM} {
+	{DNNAMESTR1}/"," {
+		strcpy(master_lval.strtype, master_text);
+		return DNNAME;
+	}
+
+	{DNNAMESTR2} {
 		strcpy(master_lval.strtype, master_text);
 		return DNNAME;
 	}
diff --git a/CHANGELOG b/CHANGELOG
index 795ec30..1c147c5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -40,6 +40,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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;
diff --git a/CHANGELOG b/CHANGELOG
index 1c147c5..74d39fd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -41,6 +41,7 @@
 - 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.
+- fix schema selection in LDAP schema discovery.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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 {
diff --git a/CHANGELOG b/CHANGELOG
index 74d39fd..2c815e7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -42,6 +42,7 @@
 - handle MTAB_NOTUPDATED status return from mount.
 - when default master map, auto.master, is used also check for auto_master.
 - fix schema selection in LDAP schema discovery.
+- update negative mount timeout handling.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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"
diff --git a/CHANGELOG b/CHANGELOG
index 2c815e7..f8260b1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -43,6 +43,7 @@
 - when default master map, auto.master, is used also check for auto_master.
 - fix schema selection in LDAP schema discovery.
 - update negative mount timeout handling.
+- fix large group handling (Ryan Thomas).
 
 18/06/2007 autofs-5.0.2
 -----------------------
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);
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;
diff --git a/CHANGELOG b/CHANGELOG
index f8260b1..be50aad 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -44,6 +44,7 @@
 - fix schema selection in LDAP schema discovery.
 - update negative mount timeout handling.
 - fix large group handling (Ryan Thomas).
+- fix for dynamic logging breaking non-sasl build (Guillaume Rousse)
 
 18/06/2007 autofs-5.0.2
 -----------------------
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);
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 0ed873e..78d69c6 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -25,6 +25,7 @@
 #include <time.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/mount.h>
 
 #include "automount.h"
 
@@ -308,6 +309,8 @@ int spawn_mount(unsigned logopt, ...)
 	while (retries--) {
 		ret = do_spawn(logopt, options, prog, (const char **) argv);
 		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)
@@ -329,6 +332,9 @@ int spawn_mount(unsigned logopt, ...)
 				argv[argc - 1] = argv[argc - 2];
 				argv[argc - 2] = arg_fake;
 			}
+
+			nanosleep(&tm, NULL);
+
 			continue;
 		}
 		break;
@@ -336,9 +342,16 @@ int spawn_mount(unsigned logopt, ...)
 
 	/* 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;
+		/*
+		 * 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;
@@ -395,6 +408,8 @@ int spawn_bind_mount(unsigned logopt, ...)
 	while (retries--) {
 		ret = do_spawn(logopt, options, prog, (const char **) argv);
 		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)
@@ -416,6 +431,9 @@ int spawn_bind_mount(unsigned logopt, ...)
 				argv[argc - 1] = argv[argc - 2];
 				argv[argc - 2] = arg_fake;
 			}
+
+			nanosleep(&tm, NULL);
+
 			continue;
 		}
 		break;
@@ -423,9 +441,16 @@ int spawn_bind_mount(unsigned logopt, ...)
 
 	/* 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;
+		/*
+		 * 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;
diff --git a/include/automount.h b/include/automount.h
index 4887da6..fa5cd97 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -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 --git a/modules/mount_bind.c b/modules/mount_bind.c
index 04284f5..ef973e1 100644
--- a/modules/mount_bind.c
+++ b/modules/mount_bind.c
@@ -147,7 +147,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 			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 --git a/modules/mount_nfs.c b/modules/mount_nfs.c
index bad21fc..0e7aebe 100644
--- a/modules/mount_nfs.c
+++ b/modules/mount_nfs.c
@@ -233,6 +233,10 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
 				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, const char *root, const char *name, int
 		this = this->next;
 	}
 
+forced_fail:
 	free_host_list(&hosts);
 	ap->ghost = save_ghost;
 
diff --git a/CHANGELOG b/CHANGELOG
index be50aad..3557b16 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -45,6 +45,7 @@
 - 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.
 
 18/06/2007 autofs-5.0.2
 -----------------------
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;
diff --git a/CHANGELOG b/CHANGELOG
index 3557b16..7e58092 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -46,6 +46,7 @@
 - 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.
+- fix incorrect read/write size of startup status token (Matthias Koenig).
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 7becad5..f31ec11 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1125,7 +1125,7 @@ static void become_daemon(unsigned foreground)
 		if (pid > 0) {
 			int r;
 			close(start_pipefd[1]);
-			r = read(start_pipefd[0], pst_stat, sizeof(pst_stat));
+			r = read(start_pipefd[0], pst_stat, sizeof(*pst_stat));
 			if (r < 0)
 				exit(1);
 			exit(*pst_stat);
@@ -2061,12 +2061,12 @@ int main(int argc, char *argv[])
 	if (!master_read_master(master_list, age, 0)) {
 		master_kill(master_list);
 		*pst_stat = 3;
-		res = write(start_pipefd[1], pst_stat, sizeof(pst_stat));
+		res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
 		close(start_pipefd[1]);
 		exit(3);
 	}
 
-	res = write(start_pipefd[1], pst_stat, sizeof(pst_stat));
+	res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
 	close(start_pipefd[1]);
 
 	state_mach_thid = pthread_self();
diff --git a/CHANGELOG b/CHANGELOG
index 9312ad5..6379d18 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -47,6 +47,7 @@
 - fix for dynamic logging breaking non-sasl build (Guillaume Rousse)
 - eliminate NULL proc ping for singleton host or local mounts.
 - fix incorrect read/write size of startup status token (Matthias Koenig).
+- fix off-by-one error for lookup of map keys exactly 255 characters long.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 23ea07d..550bf5c 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -1047,7 +1047,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	debug(ap->logopt, MODPREFIX "looking up %s", name);
 
-	key_len = snprintf(key, KEY_MAX_LEN, "%s", name);
+	key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
 	if (key_len > KEY_MAX_LEN)
 		return NSS_STATUS_NOTFOUND;
 
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 93a1b40..b8484a2 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -2053,7 +2053,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	debug(ap->logopt, MODPREFIX "looking up %s", name);
 
-	key_len = snprintf(key, KEY_MAX_LEN, "%s", name);
+	key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
 	if (key_len > KEY_MAX_LEN)
 		return NSS_STATUS_NOTFOUND;
 
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index bb1ca42..fee8b16 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -476,7 +476,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	debug(ap->logopt, MODPREFIX "looking up %s", name);
 
-	key_len = snprintf(key, KEY_MAX_LEN, "%s", name);
+	key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
 	if (key_len > KEY_MAX_LEN)
 		return NSS_STATUS_NOTFOUND;
 
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index e8ca8e8..5f4f95f 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -567,7 +567,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 
 	debug(ap->logopt, MODPREFIX "looking up %s", name);
 
-	key_len = snprintf(key, KEY_MAX_LEN, "%s", name);
+	key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
 	if (key_len > KEY_MAX_LEN)
 		return NSS_STATUS_NOTFOUND;
 
diff --git a/CHANGELOG b/CHANGELOG
index 6379d18..a9e509d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -48,6 +48,7 @@
 - eliminate NULL proc ping for singleton host or local mounts.
 - fix incorrect read/write size of startup status token (Matthias Koenig).
 - fix off-by-one error for lookup of map keys exactly 255 characters long.
+- improve handling of server not available.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 0be10d3..eb72411 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -298,8 +298,6 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
 
 	status = lookup->lookup_read_map(ap, age, lookup->context);
 
-	map->stale = 0;
-
 	/*
 	 * For maps that don't support enumeration return success
 	 * and do whatever we must to have autofs function with an
@@ -533,6 +531,10 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
 			if (result == NSS_STATUS_UNKNOWN)
 				continue;
 
+			/* Don't try to update the map cache if it's unavailable */
+			if (result == NSS_STATUS_UNAVAIL)
+				map->stale = 0;
+
 			if (result == NSS_STATUS_SUCCESS) {
 				at_least_one = 1;
 				result = NSS_STATUS_TRYAGAIN;
@@ -553,7 +555,7 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
 	}
 	pthread_cleanup_pop(1);
 
-	if (!result ||  at_least_one)
+	if (!result || at_least_one)
 		return 1;
 
 	return 0;
diff --git a/daemon/state.c b/daemon/state.c
index cf07aac..5bccfef 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -432,6 +432,7 @@ static void *do_readmap(void *arg)
 				me = cache_enumerate(mc, me);
 			}
 			pthread_cleanup_pop(1);
+			map->stale = 0;
 			map = map->next;
 		}
 		pthread_cleanup_pop(1);
diff --git a/include/automount.h b/include/automount.h
index fa5cd97..133fd32 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -121,6 +121,7 @@ struct autofs_point;
 #define CHE_MISSING	0x0008
 #define CHE_COMPLETED	0x0010
 #define CHE_DUPLICATE	0x0020
+#define CHE_UNAVAIL	0x0040
 
 #define HASHSIZE		77
 #define NEGATIVE_TIMEOUT	10
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 550bf5c..a77068a 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -469,11 +469,14 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 				master->recurse = 1;;
 			master->depth++;
 			status = lookup_nss_read_master(master, age);
-			if (!status)
+			if (!status) {
 				warn(logopt,
 				     MODPREFIX
 				     "failed to read included master map %s",
 				     master->name);
+				fclose(f);
+				return NSS_STATUS_UNAVAIL;
+			}
 			master->depth--;
 			master->recurse = 0;
 
@@ -484,6 +487,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 			if (!buffer) {
 				error(logopt,
 				      MODPREFIX "could not malloc parse buffer");
+				fclose(f);
 				return NSS_STATUS_UNAVAIL;
 			}
 			memset(buffer, 0, blen);
@@ -721,9 +725,12 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 
 			/* Gim'ee some o' that 16k stack baby !! */
 			status = lookup_nss_read_map(ap, inc_source, age);
-			if (!status)
+			if (!status) {
 				warn(ap->logopt,
 				     "failed to read included map %s", key);
+				fclose(f);
+				return NSS_STATUS_UNAVAIL;
+			}
 		} else {
 			char *s_key; 
 
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index b8484a2..7effbf1 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1755,7 +1755,7 @@ static int lookup_one(struct autofs_point *ap,
 	/* Initialize the LDAP context. */
 	ldap = do_reconnect(ap->logopt, ctxt);
 	if (!ldap)
-		return CHE_FAIL;
+		return CHE_UNAVAIL;
 
 	debug(ap->logopt,
 	      MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
@@ -1999,6 +1999,21 @@ static int check_map_indirect(struct autofs_point *ap,
 	if (ret == CHE_FAIL) {
 		pthread_setcancelstate(cur_state, NULL);
 		return NSS_STATUS_NOTFOUND;
+	} else if (ret == CHE_UNAVAIL) {
+		/*
+		 * If the server is down and the entry exists in the cache
+		 * and belongs to this map return success and use the entry.
+		 */
+		struct mapent *exists = cache_lookup(mc, key);
+		if (exists && exists->source == source) {
+			pthread_setcancelstate(cur_state, NULL);
+			return NSS_STATUS_SUCCESS;
+		}
+
+		warn(ap->logopt,
+		     MODPREFIX "lookup for %s failed: connection failed", key);
+
+		return NSS_STATUS_UNAVAIL;
 	}
 	pthread_setcancelstate(cur_state, NULL);
 
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index fee8b16..628ffcf 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -385,9 +385,18 @@ static int check_map_indirect(struct autofs_point *ap,
 		return NSS_STATUS_NOTFOUND;
 
 	if (ret < 0) {
+		/*
+		 * If the server is down and the entry exists in the cache
+		 * and belongs to this map return success and use the entry.
+		 */
+		exists = cache_lookup(mc, key);
+		if (exists && exists->source == source)
+			return NSS_STATUS_SUCCESS;
+
 		warn(ap->logopt,
 		     MODPREFIX "lookup for %s failed: %s",
 		     key, nis_sperrno(-ret));
+
 		return NSS_STATUS_UNAVAIL;
 	}
 
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 5f4f95f..f5097dc 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -239,6 +239,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
 		     MODPREFIX "read of master map %s failed: %s",
 		     mapname, yperr_string(err));
 
+		if (err == YPERR_PMAP || err == YPERR_YPSERV)
+			return NSS_STATUS_UNAVAIL;
+
 		return NSS_STATUS_NOTFOUND;
 	}
 
@@ -336,6 +339,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
 		     MODPREFIX "read of map %s failed: %s",
 		     ap->path, yperr_string(err));
 
+		if (err == YPERR_PMAP || err == YPERR_YPSERV)
+			return NSS_STATUS_UNAVAIL;
+
 		return NSS_STATUS_NOTFOUND;
 	}
 
@@ -481,9 +487,18 @@ static int check_map_indirect(struct autofs_point *ap,
 		return NSS_STATUS_NOTFOUND;
 
 	if (ret < 0) {
+		/*
+		 * If the server is down and the entry exists in the cache
+		 * and belongs to this map return success and use the entry.
+		 */
+		exists = cache_lookup(mc, key);
+		if (exists && exists->source == source)
+			return NSS_STATUS_SUCCESS;
+
 		warn(ap->logopt,
 		     MODPREFIX "lookup for %s failed: %s",
 		     key, yperr_string(-ret));
+
 		return NSS_STATUS_UNAVAIL;
 	}
 
diff --git a/CHANGELOG b/CHANGELOG
index a9e509d..85af0ad 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,6 +49,7 @@
 - fix incorrect read/write size of startup status token (Matthias Koenig).
 - fix off-by-one error for lookup of map keys exactly 255 characters long.
 - improve handling of server not available.
+- fix LDAP_URI server selection.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
index 18733f3..303b7f2 100644
--- a/modules/cyrus-sasl.c
+++ b/modules/cyrus-sasl.c
@@ -75,6 +75,7 @@ static const char *krb5ccval = "MEMORY:_autofstkt";
 static pthread_mutex_t krb5cc_mutex = PTHREAD_MUTEX_INITIALIZER;
 static unsigned int krb5cc_in_use = 0;
 
+static unsigned int init_callbacks = 1;
 static int sasl_log_func(void *, int, const char *);
 static int getpass_func(sasl_conn_t *, void *, int, sasl_secret_t **);
 static int getuser_func(void *, int, const char **, unsigned *);
@@ -386,7 +387,7 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 
 	debug(logopt,
 	      "initializing kerberos ticket: client principal %s ",
-	      ctxt->client_princ ? "" : "autofsclient");
+	      ctxt->client_princ ? ctxt->client_princ : "autofsclient");
 
 	ret = krb5_init_context(&ctxt->krb5ctxt);
 	if (ret) {
@@ -599,8 +600,8 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c
 
 	/* OK and CONTINUE are the only non-fatal return codes here. */
 	if ((result != SASL_OK) && (result != SASL_CONTINUE)) {
-		error(logopt, "sasl_client start failed with error: %s",
-		      sasl_errdetail(conn));
+		warn(logopt, "sasl_client_start failed for %s", host);
+		debug(logopt, "sasl_client_start: %s", sasl_errdetail(conn));
 		ldap_memfree(host);
 		sasl_dispose(&conn);
 		return NULL;
@@ -721,23 +722,30 @@ autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 	sasl_conn_t *conn;
 
 	/* Start up Cyrus SASL--only needs to be done once. */
-	if (sasl_client_init(callbacks) != SASL_OK) {
+	if (init_callbacks && sasl_client_init(callbacks) != SASL_OK) {
 		error(logopt, "sasl_client_init failed");
 		return -1;
 	}
+	init_callbacks = 0;
 
 	sasl_auth_id = ctxt->user;
 	sasl_auth_secret = ctxt->secret;
 
 	/*
-	 *  If sasl_mech was not filled in, it means that there was no
-	 *  mechanism specified in the configuration file.  Try to auto-
-	 *  select one.
+	 *  If LDAP_AUTH_AUTODETECT is set, it means that there was no
+	 *  mechanism specified in the configuration file or auto
+	 *  selection has been requested, so try to auto-select an
+	 *  auth mechanism.
 	 */
-	if (ctxt->sasl_mech)
+	if (!(ctxt->auth_required & LDAP_AUTH_AUTODETECT))
 		conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech);
-	else
+	else {
+		if (ctxt->sasl_mech) {
+			free(ctxt->sasl_mech);
+			ctxt->sasl_mech = NULL;
+		}
 		conn = sasl_choose_mech(logopt, ldap, ctxt);
+	}
 
 	if (conn) {
 		sasl_dispose(&conn);
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 7effbf1..93f0477 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -402,8 +402,7 @@ static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
 	debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s",
 	      ctxt->auth_required, ctxt->sasl_mech);
 
-	if (ctxt->sasl_mech ||
-	   (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT))) {
+	if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) {
 		rv = autofs_sasl_bind(logopt, ldap, ctxt);
 		debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
 	} else {
@@ -497,7 +496,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c
 	 * Determine which authentication mechanism to use if we require
 	 * authentication.
 	 */
-	if (ctxt->auth_required & LDAP_AUTH_REQUIRED) {
+	if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) {
 		ldap = auth_init(logopt, uri, ctxt);
 		if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT)
 			info(logopt,
@@ -510,6 +509,7 @@ static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_c
 
 		if (!do_bind(logopt, ldap, ctxt)) {
 			unbind_ldap_connection(logopt, ldap, ctxt);
+			autofs_sasl_done(ctxt);
 			error(logopt, MODPREFIX "cannot bind to server");
 			return NULL;
 		}
@@ -541,6 +541,7 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 	while(p != ctxt->uri) {
 		this = list_entry(p, struct ldap_uri, list);
 		p = p->next;
+		debug(logopt, "trying server %s", this->uri);
 		ldap = connect_to_server(logopt, this->uri, ctxt);
 		if (ldap) {
 			info(logopt, "connected to uri %s", this->uri);
@@ -563,22 +564,23 @@ static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
 
 static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
 {
+	struct ldap_uri *this;
 	LDAP *ldap;
 
 	if (ctxt->server || !ctxt->uri) {
 		ldap = do_connect(logopt, ctxt->server, ctxt);
 		return ldap;
-	} else {
-		struct ldap_uri *this;
-		this = list_entry(ctxt->uri->next, struct ldap_uri, list);
-		ldap = do_connect(logopt, 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);
 	}
 
+	this = list_entry(ctxt->uri->next, struct ldap_uri, list);
+	ldap = do_connect(logopt, 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);
+
 #ifdef WITH_SASL
 	autofs_sasl_done(ctxt);
 #endif
@@ -844,6 +846,8 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
 	ctxt->tls_required = tls_required;
 	ctxt->auth_required = auth_required;
 	ctxt->sasl_mech = authtype;
+	if (!authtype && (auth_required & LDAP_AUTH_REQUIRED))
+		ctxt->auth_required |= LDAP_AUTH_AUTODETECT;
 	ctxt->user = user;
 	ctxt->secret = secret;
 	ctxt->client_princ = client_princ;
@@ -886,16 +890,6 @@ static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context *
 	int ret;
 	LDAP *ldap;
 
-	/*
-	 *  First, check to see if a preferred authentication method was
-	 *  specified by the user.  parse_ldap_config will return error
-	 *  if the permissions on the file were incorrect, or if the
-	 *  specified authentication type is not valid.
-	 */
-	ret = parse_ldap_config(logopt, ctxt);
-	if (ret)
-		return NULL;
-
 	ldap = init_ldap_connection(logopt, uri, ctxt);
 	if (!ldap)
 		return NULL;
@@ -909,10 +903,8 @@ static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context *
 	 *  the credential cache and the client and service principals.
 	 */
 	ret = autofs_sasl_init(logopt, ldap, ctxt);
-	if (ret) {
-		ctxt->sasl_mech = NULL;
+	if (ret)
 		return NULL;
-	}
 
 	return ldap;
 }
@@ -1134,6 +1126,8 @@ static void free_context(struct lookup_context *ctxt)
 		free(ctxt->user);
 	if (ctxt->secret)
 		free(ctxt->secret);
+	if (ctxt->client_princ)
+		free(ctxt->client_princ);
 	if (ctxt->mapname)
 		free(ctxt->mapname);
 	if (ctxt->qdn)
@@ -1184,6 +1178,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 	struct lookup_context *ctxt;
 	char buf[MAX_ERR_BUF];
 	LDAP *ldap = NULL;
+	int ret;
 
 	*context = NULL;
 
@@ -1224,6 +1219,20 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
 		}
 	}
 
+#ifdef WITH_SASL
+	/*
+	 *  First, check to see if a preferred authentication method was
+	 *  specified by the user.  parse_ldap_config will return error
+	 *  if the permissions on the file were incorrect, or if the
+	 *  specified authentication type is not valid.
+	 */
+	ret = parse_ldap_config(LOGOPT_NONE, ctxt);
+	if (ret) {
+		free_context(ctxt);
+		return 1;
+	}
+#endif
+
 	if (ctxt->server || !ctxt->uri) {
 		ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt);
 		if (!ldap) {
diff --git a/CHANGELOG b/CHANGELOG
index 85af0ad..fcfbe62 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -50,6 +50,7 @@
 - fix off-by-one error for lookup of map keys exactly 255 characters long.
 - improve handling of server not available.
 - fix LDAP_URI server selection.
+- add authentication option for using an external credential cache.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h
index 5b5c475..d6a754d 100644
--- a/include/lookup_ldap.h
+++ b/include/lookup_ldap.h
@@ -67,10 +67,10 @@ struct lookup_context {
 	char        *user;
 	char        *secret;
 	char        *client_princ;
+	char        *client_cc;
 	int          kinit_done;
 	int          kinit_successful;
 #ifdef WITH_SASL
-	krb5_principal  krb5_client_princ;
 	krb5_context krb5ctxt;
 	krb5_ccache  krb5_ccache;
 	sasl_conn_t  *sasl_conn;
diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c
index 303b7f2..f24f46b 100644
--- a/modules/cyrus-sasl.c
+++ b/modules/cyrus-sasl.c
@@ -72,6 +72,7 @@
  */
 static const char *krb5ccenv = "KRB5CCNAME";
 static const char *krb5ccval = "MEMORY:_autofstkt";
+static const char *default_client = "autofsclient";
 static pthread_mutex_t krb5cc_mutex = PTHREAD_MUTEX_INITIALIZER;
 static unsigned int krb5cc_in_use = 0;
 
@@ -376,7 +377,7 @@ int
 sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 {
 	krb5_error_code ret;
-	krb5_principal tgs_princ, krb5_client_princ = ctxt->krb5_client_princ;
+	krb5_principal tgs_princ, krb5_client_princ;
 	krb5_creds my_creds;
 	char *tgs_name;
 	int status;
@@ -386,8 +387,8 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 	ctxt->kinit_done = 1;
 
 	debug(logopt,
-	      "initializing kerberos ticket: client principal %s ",
-	      ctxt->client_princ ? ctxt->client_princ : "autofsclient");
+	      "initializing kerberos ticket: client principal %s",
+	      ctxt->client_princ ? ctxt->client_princ : default_client);
 
 	ret = krb5_init_context(&ctxt->krb5ctxt);
 	if (ret) {
@@ -424,13 +425,12 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 		      "calling krb5_sname_to_principal using defaults");
 
 		ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL,
-					"autofsclient", KRB5_NT_SRV_HST, 
+					default_client, KRB5_NT_SRV_HST, 
 					&krb5_client_princ);
 		if (ret) {
 			error(logopt,
 			      "krb5_sname_to_principal failed for "
-			      "%s with error %d",
-			      ctxt->client_princ ? "" : "autofsclient", ret);
+			      "%s with error %d", default_client, ret);
 			goto out_cleanup_cc;
 		}
 
@@ -441,11 +441,11 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 			debug(logopt,
 			      "krb5_unparse_name failed with error %d",
 			      ret);
-			goto out_cleanup_cc;
+			goto out_cleanup_client_princ;
 		}
 
 		debug(logopt,
-		      "principal used for authentication: \"%s\"", tmp_name);
+		      "principal used for authentication: %s", tmp_name);
 
 		krb5_free_unparsed_name(ctxt->krb5ctxt, tmp_name);
 	}
@@ -461,14 +461,14 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 	if (ret) {
 		error(logopt,
 		      "krb5_build_principal failed with error %d", ret);
-		goto out_cleanup_cc;
+		goto out_cleanup_client_princ;
 	}
 
 	ret = krb5_unparse_name(ctxt->krb5ctxt, tgs_princ, &tgs_name);
 	if (ret) {
 		error(logopt, "krb5_unparse_name failed with error %d",
 		      ret);
-		goto out_cleanup_cc;
+		goto out_cleanup_client_princ;
 	}
 
 	debug(logopt, "Using tgs name %s", tgs_name);
@@ -486,7 +486,6 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 		goto out_cleanup_unparse;
 	}
 
-
 	status = pthread_mutex_lock(&krb5cc_mutex);
 	if (status)
 		fatal(status);
@@ -503,7 +502,7 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 	if (ret) {
 		error(logopt,
 		      "krb5_cc_initialize failed with error %d", ret);
-		goto out_cleanup_unparse;
+		goto out_cleanup_creds;
 	}
 
 	/* and store credentials for that principal */
@@ -511,26 +510,34 @@ sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt)
 	if (ret) {
 		error(logopt,
 		      "krb5_cc_store_cred failed with error %d", ret);
-		goto out_cleanup_unparse;
+		goto out_cleanup_creds;
 	}
 
 	/* finally, set the environment variable to point to our
 	 * credentials cache */
 	if (setenv(krb5ccenv, krb5ccval, 1) != 0) {
 		error(logopt, "setenv failed with %d", errno);
-		goto out_cleanup_unparse;
+		goto out_cleanup_creds;
 	}
 	ctxt->kinit_successful = 1;
 
 	debug(logopt, "Kerberos authentication was successful!");
 
 	krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name);
+	krb5_free_cred_contents(ctxt->krb5ctxt, &my_creds);
+	krb5_free_principal(ctxt->krb5ctxt, tgs_princ);
+	krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
 
 	return 0;
 
-out_cleanup_unparse:
+out_cleanup_creds:
 	krb5cc_in_use--;
+	krb5_free_cred_contents(ctxt->krb5ctxt, &my_creds);
+out_cleanup_unparse:
+	krb5_free_principal(ctxt->krb5ctxt, tgs_princ);
 	krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name);
+out_cleanup_client_princ:
+	krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
 out_cleanup_cc:
 	status = pthread_mutex_lock(&krb5cc_mutex);
 	if (status)
@@ -554,6 +561,152 @@ out_cleanup_cc:
 }
 
 /*
+ *  Check a client given external credential cache.
+ *
+ *  Returns 0 upon success.  ctxt->kinit_done and ctxt->kinit_successful
+ *  are set for cleanup purposes.  The krb5 context and ccache entries in
+ *  the lookup_context are also filled in.
+ *
+ *  Upon failure, -1 is returned.
+ */
+int
+sasl_do_kinit_ext_cc(unsigned logopt, struct lookup_context *ctxt)
+{
+	krb5_principal def_princ;
+	krb5_principal krb5_client_princ;
+	krb5_error_code ret;
+	char *cc_princ, *client_princ;
+
+	if (ctxt->kinit_done)
+		return 0;
+	ctxt->kinit_done = 1;
+
+	debug(logopt,
+	      "using external credential cache for auth: client principal %s",
+	      ctxt->client_princ ? ctxt->client_princ : default_client);
+
+	ret = krb5_init_context(&ctxt->krb5ctxt);
+	if (ret) {
+		error(logopt, "krb5_init_context failed with %d", ret);
+		return -1;
+	}
+
+	ret = krb5_cc_resolve(ctxt->krb5ctxt, ctxt->client_cc, &ctxt->krb5_ccache);
+	if (ret) {
+		error(logopt, "krb5_cc_resolve failed with error %d",
+		      ret);
+		krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+		krb5_free_context(ctxt->krb5ctxt);
+		return -1;
+	}
+
+	ret = krb5_cc_get_principal(ctxt->krb5ctxt, ctxt->krb5_ccache, &def_princ);
+	if (ret) {
+		error(logopt, "krb5_cc_get_principal failed with error %d", ret);
+		krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+		krb5_free_context(ctxt->krb5ctxt);
+		return -1;
+	}
+
+	ret = krb5_unparse_name(ctxt->krb5ctxt, def_princ, &cc_princ);
+	if (ret) {
+		error(logopt, "krb5_unparse_name failed with error %d", ret);
+		krb5_free_principal(ctxt->krb5ctxt, def_princ);
+		krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+		krb5_free_context(ctxt->krb5ctxt);
+		return -1;
+	}
+
+	debug(logopt, "external credential cache default principal %s", cc_princ);
+
+	/*
+	 * If the principal isn't set in the config construct the default
+	 * so we can check against the default principal of the external
+	 * cred cache.
+	 */
+	if (ctxt->client_princ)
+		client_princ = ctxt->client_princ;
+	else {
+		debug(logopt,
+		      "calling krb5_sname_to_principal using defaults");
+
+		ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL,
+					default_client, KRB5_NT_SRV_HST, 
+					&krb5_client_princ);
+		if (ret) {
+			error(logopt,
+			      "krb5_sname_to_principal failed for "
+			      "%s with error %d", default_client, ret);
+			krb5_free_principal(ctxt->krb5ctxt, def_princ);
+			krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+			krb5_free_context(ctxt->krb5ctxt);
+			return -1;
+		}
+
+
+		ret = krb5_unparse_name(ctxt->krb5ctxt,
+					krb5_client_princ, &client_princ);
+		if (ret) {
+			debug(logopt,
+			      "krb5_unparse_name failed with error %d",
+			      ret);
+			krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
+			krb5_free_principal(ctxt->krb5ctxt, def_princ);
+			krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+			krb5_free_context(ctxt->krb5ctxt);
+			return -1;
+		}
+
+		debug(logopt,
+		      "principal used for authentication: %s", client_princ);
+
+		krb5_free_principal(ctxt->krb5ctxt, krb5_client_princ);
+	}
+
+	/*
+	 * Check if the principal to be used matches the default principal in
+	 * the external cred cache.
+	 */
+	if (strcmp(cc_princ, client_princ)) {
+		error(logopt,
+		      "configured client principal %s ",
+		      ctxt->client_princ);
+		error(logopt,
+		      "external credential cache default principal %s",
+		      cc_princ);
+		error(logopt, 
+		      "cannot use credential cache, external "
+		      "default principal does not match configured "
+		      "principal");
+		if (!ctxt->client_princ)
+			krb5_free_unparsed_name(ctxt->krb5ctxt, client_princ);
+		krb5_free_unparsed_name(ctxt->krb5ctxt, cc_princ);
+		krb5_free_principal(ctxt->krb5ctxt, def_princ);
+		krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+		krb5_free_context(ctxt->krb5ctxt);
+		return -1;
+	}
+
+	if (!ctxt->client_princ)
+		krb5_free_unparsed_name(ctxt->krb5ctxt, client_princ);
+	krb5_free_unparsed_name(ctxt->krb5ctxt, cc_princ);
+	krb5_free_principal(ctxt->krb5ctxt, def_princ);
+
+	/* Set the environment variable to point to the external cred cache */
+	if (setenv(krb5ccenv, ctxt->client_cc, 1) != 0) {
+		error(logopt, "setenv failed with %d", errno);
+		krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
+		krb5_free_context(ctxt->krb5ctxt);
+		return -1;
+	}
+	ctxt->kinit_successful = 1;
+
+	debug(logopt, "Kerberos authentication was successful!");
+
+	return 0;
+}
+
+/*
  *  Attempt to bind to the ldap server using a given authentication
  *  mechanism.  ldap should be a properly initialzed ldap pointer.
  *
@@ -570,7 +723,11 @@ sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const c
 	int result;
 
 	if (!strncmp(mech, "GSSAPI", 6)) {
-		if (sasl_do_kinit(logopt, ctxt) != 0)
+		if (ctxt->client_cc)
+			result = sasl_do_kinit_ext_cc(logopt, ctxt);
+		else
+			result = sasl_do_kinit(logopt, ctxt);
+		if (result != 0)
 			return NULL;
 	}
 
@@ -774,7 +931,7 @@ autofs_sasl_done(struct lookup_context *ctxt)
 		if (status)
 			fatal(status);
 
-		if (--krb5cc_in_use)
+		if (--krb5cc_in_use || ctxt->client_cc)
 			ret = krb5_cc_close(ctxt->krb5ctxt, ctxt->krb5_ccache);
 		else 
 			ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache);
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 93f0477..13fbff7 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -651,7 +651,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
 	xmlNodePtr   root = NULL;
 	char         *authrequired, *auth_conf, *authtype;
 	char         *user = NULL, *secret = NULL;
-	char         *client_princ = NULL;
+	char         *client_princ = NULL, *client_cc = NULL;
 	char	     *usetls, *tlsrequired;
 
 	authtype = user = secret = NULL;
@@ -840,6 +840,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
 	 * client.  The default is "autofsclient/hostname@REALM".
 	 */
 	(void)get_property(logopt, root, "clientprinc", &client_princ);
+	(void)get_property(logopt, root, "credentialcache", &client_cc);
 
 	ctxt->auth_conf = auth_conf;
 	ctxt->use_tls = use_tls;
@@ -851,6 +852,7 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
 	ctxt->user = user;
 	ctxt->secret = secret;
 	ctxt->client_princ = client_princ;
+	ctxt->client_cc = client_cc;
 
 	debug(logopt, MODPREFIX
 	      "ldap authentication configured with the following options:");
@@ -863,9 +865,10 @@ int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
 	debug(logopt, MODPREFIX
 	      "user: %s, "
 	      "secret: %s, "
-	      "client principal: %s",
+	      "client principal: %s "
+	      "credential cache: %s",
 	      user, secret ? "specified" : "unspecified",
-	      client_princ);
+	      client_princ, client_cc);
 
 out:
 	xmlFreeDoc(doc);
@@ -1128,6 +1131,8 @@ static void free_context(struct lookup_context *ctxt)
 		free(ctxt->secret);
 	if (ctxt->client_princ)
 		free(ctxt->client_princ);
+	if (ctxt->client_cc)
+		free(ctxt->client_cc);
 	if (ctxt->mapname)
 		free(ctxt->mapname);
 	if (ctxt->qdn)
diff --git a/samples/autofs_ldap_auth.conf b/samples/autofs_ldap_auth.conf
index e10d1ea..a1f60c0 100644
--- a/samples/autofs_ldap_auth.conf
+++ b/samples/autofs_ldap_auth.conf
@@ -56,6 +56,11 @@ clientprinc  -  When using GSSAPI authentication, this attribute is
 	    consulted to determine the principal name to use when
 	    authenticating to the directory server.  By default, this will
 	    be set to "autofsclient/<fqdn>@<REALM>.
+
+credentialcache - When using GSSAPI authentication, this attribute
+	    can be used to specify an externally configured credential
+	    cache that is used during authentication. By default, autofs
+	    will setup a memory based credential cache.
 -->
 
 <autofs_ldap_sasl_conf
diff --git a/CHANGELOG b/CHANGELOG
index fcfbe62..c29d577 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -51,6 +51,7 @@
 - improve handling of server not available.
 - fix LDAP_URI server selection.
 - add authentication option for using an external credential cache.
+- expand support for the "%" hack.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 13fbff7..65f1fda 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1411,6 +1411,140 @@ next:
 	return NSS_STATUS_SUCCESS;
 }
 
+/*
+ * Deal with encode and decode of % hack.
+ * Return
+ * 0 => % hack not present.
+ * -1 => syntax error or alloc fail.
+ * 1 transofrmed value returned.
+ */
+static int decode_percent_hack(const char *name, char **key)
+{
+	const char *tmp;
+	char *ptr, *new;
+
+	if (!key)
+		return -1;
+
+	*key = NULL;
+
+	tmp = name;
+	while (*tmp && *tmp != '%' && *tmp != '[' && *tmp != ']')
+		tmp++;
+	if (!*tmp)
+		return 0;
+
+	tmp = name;
+	while (*tmp) {
+		if (*tmp == '%') {
+			tmp++;
+			if (!*tmp)
+				return -1;
+			if (*tmp != '[')
+				continue;
+			tmp++;
+			while (*tmp && *tmp != ']') {
+				if (*tmp == '%')
+					tmp++;
+				tmp++;
+			}
+			if (!tmp)
+				return -1;
+		}
+		tmp++;
+	}
+
+	new = malloc(strlen(name) + 1);
+	if (!new)
+		return -1;
+
+	ptr = new;
+	tmp = name;
+	while (*tmp) {
+		if (*tmp == '%' || *tmp == '[' || *tmp == ']') {
+			tmp++;
+			if (*tmp && *tmp != '%')
+				continue;
+		}
+		*ptr++ = *tmp++;
+	}
+	*ptr = '\0';
+
+	*key = new;
+
+	return strlen(new);
+}
+
+static int encode_percent_hack(const char *name, char **key, unsigned int use_class)
+{
+	const char *tmp;
+	unsigned int len = 0;
+	char *ptr, *new;
+
+	if (!key)
+		return -1;
+
+	*key = NULL;
+
+	tmp = name;
+	while (*tmp) {
+		if (*tmp == '%')
+			len++;
+		else if (isupper(*tmp)) {
+			tmp++;
+			len++;
+			if (!use_class)
+				len++;
+			else {
+				if (*tmp && isupper(*tmp))
+					len += 2;
+				else
+					return 0;
+				while (*tmp && isupper(*tmp)) {
+					len++;
+					tmp++;
+				}
+			}
+			continue;
+		}
+		len++;
+		tmp++;
+	}
+	if (len == strlen(name))
+		return 0;
+
+	new = malloc(len + 1);
+	if (!new)
+		return -1;
+
+	ptr = new;
+	tmp = name;
+	while (*tmp) {
+		if (*tmp == '%')
+			*ptr++ = '%';
+		else if (isupper(*tmp)) {
+			char next = *tmp++;
+			*ptr++ = '%';
+			if (*tmp && (!isupper(*tmp) || !use_class))
+				*ptr++ = next;
+			else {
+				*ptr++ = '[';
+				*ptr++ = next;
+				while (*tmp && isupper(*tmp))
+					*ptr++ = *tmp++;
+				*ptr++ = ']';
+			}
+			continue;
+		}
+		*ptr++ = *tmp++;
+	}
+	*ptr = '\0';
+
+	*key = new;
+
+	return strlen(new);
+}
+
 static int read_one_map(struct autofs_point *ap,
 			struct lookup_context *ctxt,
 			time_t age, int *result_ldap)
@@ -1518,7 +1652,7 @@ static int read_one_map(struct autofs_point *ap,
 		 * people using older schemas that allow '*' as a key
 		 * value. Another case where there can be multiple key
 		 * values is when people have used the "%" hack to specify
-		 * case matching ctriteria in a caase insensitive attribute.
+		 * case matching ctriteria in a case insensitive attribute.
 		 */
 		count = ldap_count_values_len(bvKey);
 		if (count > 1) {
@@ -1647,9 +1781,30 @@ static int read_one_map(struct autofs_point *ap,
 			*k_val = '*';
 		}
 
-		s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
-		if (!s_key)
-			goto next;
+		if (strcasecmp(class, "nisObject")) {
+			s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
+			if (!s_key)
+				goto next;
+		} else {
+			char *dec_key;
+			int dec_len = decode_percent_hack(k_val, &dec_key);
+
+			if (dec_len < 0) {
+				crit(ap->logopt,
+				     "could not use percent hack to decode key %s",
+				     k_val);
+				goto next;
+			}
+
+			if (dec_len == 0)
+				s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
+			else {
+				s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt);
+				free(dec_key);
+			}
+			if (!s_key)
+				goto next;
+		}
 
 		cache_writelock(mc);
 		cache_update(mc, source, s_key, mapent, age);
@@ -1712,6 +1867,8 @@ static int lookup_one(struct autofs_point *ap,
 	char *query;
 	LDAPMessage *result, *e;
 	char *class, *info, *entry;
+	char *enc_key1, *enc_key2;
+	int enc_len1 = 0, enc_len2 = 0;
 	struct berval **bvKey;
 	struct berval **bvValues;
 	char *attrs[3];
@@ -1742,14 +1899,38 @@ static int lookup_one(struct autofs_point *ap,
 
 	if (*qKey == '*' && qKey_len == 1)
 		*qKey = '/';
+	else if (!strcasecmp(class, "nisObject")) {
+		enc_len1 = encode_percent_hack(qKey, &enc_key1, 0);
+		if (enc_len1 < 0) {
+			crit(ap->logopt,
+			     "could not use percent hack encode key %s",
+			     qKey);
+			return CHE_FAIL;
+		}
+		if (enc_len1 != 0) {
+			enc_len2 = encode_percent_hack(qKey, &enc_key2, 1);
+			if (enc_len2 < 0) {
+				crit(ap->logopt,
+				     "could not use percent hack encode key %s",
+				     qKey);
+				return CHE_FAIL;
+			}
+		}
+	}
 
 	/* Build a query string. */
 	l = strlen(class) + 3*strlen(entry) + strlen(qKey) + 35;
+	if (enc_len1)
+		l += 2*strlen(entry) + enc_len1 + enc_len2 + 6;
 
 	query = alloca(l);
 	if (query == NULL) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		crit(ap->logopt, MODPREFIX "malloc: %s", estr);
+		if (enc_len1) {
+			free(enc_key1);
+			free(enc_key2);
+		}
 		return CHE_FAIL;
 	}
 
@@ -1757,8 +1938,27 @@ static int lookup_one(struct autofs_point *ap,
 	 * Look for an entry in class under ctxt-base
 	 * whose entry is equal to qKey.
 	 */
-	ql = sprintf(query,
-	      "(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))", class, entry, qKey, entry, entry);
+	if (!enc_len1) {
+		ql = sprintf(query,
+			"(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))",
+			class, entry, qKey, entry, entry);
+	} else {
+		if (enc_len2) {
+			ql = sprintf(query,
+				"(&(objectclass=%s)"
+				"(|(%s=%s)(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))",
+				class, entry, qKey,
+				entry, enc_key1, entry, enc_key2, entry, entry);
+			free(enc_key1);
+			free(enc_key2);
+		} else {
+			ql = sprintf(query,
+				"(&(objectclass=%s)"
+				"(|(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))",
+				class, entry, qKey, entry, enc_key1, entry, entry);
+			free(enc_key1);
+		}
+	}
 	if (ql >= l) {
 		error(ap->logopt,
 		      MODPREFIX "error forming query string");
@@ -1934,9 +2134,30 @@ static int lookup_one(struct autofs_point *ap,
 			goto next;
 		}
 
-		s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
-		if (!s_key)
-			goto next;
+		if (strcasecmp(class, "nisObject")) {
+			s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
+			if (!s_key)
+				goto next;
+		} else {
+			char *dec_key;
+			int dec_len = decode_percent_hack(k_val, &dec_key);
+
+			if (dec_len < 0) {
+				crit(ap->logopt,
+				     "could not use percent hack to decode key %s",
+				     k_val);
+				goto next;
+			}
+
+			if (dec_len == 0)
+				s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
+			else {
+				s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt);
+				free(dec_key);
+			}
+			if (!s_key)
+				goto next;
+		}
 
 		cache_writelock(mc);
 		ret = cache_update(mc, source, s_key, mapent, age);
diff --git a/CHANGELOG b/CHANGELOG
index c29d577..c486a7b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -52,6 +52,7 @@
 - fix LDAP_URI server selection.
 - add authentication option for using an external credential cache.
 - expand support for the "%" hack.
+- fix to quoting for exports gathered by hosts map.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index 1ef420e..70b13a7 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -179,9 +179,14 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	if (*name == '/') {
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		mapent_len = strlen(me->mapent);
-		mapent = alloca(mapent_len + 1);
-		if (mapent)
-			strcpy(mapent, me->mapent);
+		mapent = alloca(mapent_len + 3);
+		if (mapent) {
+			/* Add quotes to keep the parser happy */
+			mapent[0] = '"';
+			strcpy(mapent + 1, me->mapent);
+			mapent[mapent_len + 1] = '"';
+			mapent[mapent_len + 2] = '\0';
+		}
 		pthread_cleanup_pop(0);
 	}
 	cache_unlock(mc);
diff --git a/CHANGELOG b/CHANGELOG
index c486a7b..0fcdfd4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -53,6 +53,7 @@
 - add authentication option for using an external credential cache.
 - expand support for the "%" hack.
 - fix to quoting for exports gathered by hosts map.
+- use mount option "nosuid" for "-hosts" map unless "suid" is explicily specified.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index d488960..56aaa5d 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -195,6 +195,9 @@ For example, with an entry in the master map of
 .hy
 accessing /net/myserver will mount exports from myserver on directories below
 /net/myserver.
+.P
+NOTE: mounts done from a hosts map will be mounted with the "nosuid" option
+unless the "suid" option is explicitly given in the master map entry.
 .SH LDAP MAPS
 If the map type \fBldap\fP is specified the mapname is of the form
 \fB[//servername/]dn\fP, where the optional \fBservername\fP is
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 186e567..9a97329 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -496,6 +496,7 @@ static int sun_mount(struct autofs_point *ap, const char *root,
 	int rv, cur_state;
 	char *mountpoint;
 	char *what;
+	char *type;
 
 	if (*options == '\0')
 		options = NULL;
@@ -585,6 +586,36 @@ static int sun_mount(struct autofs_point *ap, const char *root,
 	mountpoint = alloca(namelen + 1);
 	sprintf(mountpoint, "%.*s", namelen, name);
 
+	type = ap->entry->maps->type;
+	if (type && !strcmp(type, "hosts")) {
+		if (options) {
+			if (!strstr(options, "suid")) {
+				char *tmp = alloca(strlen(options) + 8);
+				if (!tmp) {
+					error(ap->logopt, MODPREFIX
+					      "alloca failed for options");
+					if (nonstrict)
+						return -1;
+					return 1;
+				}
+				strcpy(tmp, options);
+				strcat(tmp, ",nosuid");
+				options = tmp;
+			}
+		} else {
+			char *tmp = alloca(7);
+			if (!tmp) {
+				error(ap->logopt,
+				      MODPREFIX "alloca failed for options");
+				if (nonstrict)
+					return -1;
+				return 1;
+			}
+			strcpy(tmp, "nosuid");
+			options = tmp;
+		}
+	}
+
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 	if (!strcmp(fstype, "nfs")) {
 		what = alloca(loclen + 1);
diff --git a/samples/auto.master b/samples/auto.master
index d4796a3..4995976 100644
--- a/samples/auto.master
+++ b/samples/auto.master
@@ -5,6 +5,11 @@
 # For details of the format look at autofs(5).
 #
 /misc	/etc/auto.misc
+#
+# NOTE: mounts done from a hosts map will be mounted with the
+#	"nosuid" option unless the "suid" option is explicitly
+#	given.
+#
 /net	-hosts
 #
 # Include central master map if it can be found using
diff --git a/CHANGELOG b/CHANGELOG
index 0fcdfd4..4aa384b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -54,6 +54,7 @@
 - expand support for the "%" hack.
 - fix to quoting for exports gathered by hosts map.
 - use mount option "nosuid" for "-hosts" map unless "suid" is explicily specified.
+- second attempt fixing quoting for exports gathered by hosts map.
 
 18/06/2007 autofs-5.0.2
 -----------------------
diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
index 70b13a7..1ef420e 100644
--- a/modules/lookup_hosts.c
+++ b/modules/lookup_hosts.c
@@ -179,14 +179,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
 	if (*name == '/') {
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		mapent_len = strlen(me->mapent);
-		mapent = alloca(mapent_len + 3);
-		if (mapent) {
-			/* Add quotes to keep the parser happy */
-			mapent[0] = '"';
-			strcpy(mapent + 1, me->mapent);
-			mapent[mapent_len + 1] = '"';
-			mapent[mapent_len + 2] = '\0';
-		}
+		mapent = alloca(mapent_len + 1);
+		if (mapent)
+			strcpy(mapent, me->mapent);
 		pthread_cleanup_pop(0);
 	}
 	cache_unlock(mc);
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 9a97329..a97a7aa 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -878,7 +878,7 @@ static int parse_mapent(const char *ent, char *g_options, char **options, char *
 	}
 
 	if (!validate_location(loc)) {
-		warn(logopt, MODPREFIX "invalid location");
+		warn(logopt, MODPREFIX "invalid location %s", loc);
 		free(myoptions);
 		free(loc);
 		return 0;
@@ -913,7 +913,7 @@ static int parse_mapent(const char *ent, char *g_options, char **options, char *
 
 		if (!validate_location(ent_chunk)) {
 			warn(logopt,
-			      MODPREFIX "invalid location %s", ent);
+			      MODPREFIX "invalid location %s", ent_chunk);
 			free(ent_chunk);
 			free(myoptions);
 			free(loc);
@@ -1344,6 +1344,23 @@ int parse_mount(struct autofs_point *ap, const char *name,
 		int loclen;
 		int l;
 
+		/*
+		 * If this is an offset belonging to a multi-mount entry
+		 * it's already been parsed (above) and any option string
+		 * has already been stripped so just use the remainder.
+		 */
+		if (*name == '/' &&
+		   (me = cache_lookup_distinct(mc, name)) && me->multi) {
+			loc = strdup(p);
+			if (!loc) {
+				free(options);
+				warn(ap->logopt, MODPREFIX "out of memory");
+				return 1;
+			}
+			loclen = strlen(p);
+			goto mount_it;
+		}
+
 		l = chunklen(p, check_colon(p));
 		loc = dequote(p, l, ap->logopt);
 		if (!loc) {
@@ -1361,9 +1378,9 @@ int parse_mount(struct autofs_point *ap, const char *name,
 		}
 
 		if (!validate_location(loc)) {
+			warn(ap->logopt, MODPREFIX "invalid location %s", loc);
 			free(loc);
 			free(options);
-			warn(ap->logopt, MODPREFIX "invalid location");
 			return 1;
 		}
 
@@ -1387,10 +1404,11 @@ int parse_mount(struct autofs_point *ap, const char *name,
 			}
 
 			if (!validate_location(ent)) {
+				warn(ap->logopt,
+				     MODPREFIX "invalid location %s", loc);
 				free(ent);
 				free(loc);
 				free(options);
-				warn(ap->logopt, MODPREFIX "invalid location");
 				return 1;
 			}
 
@@ -1424,7 +1442,7 @@ int parse_mount(struct autofs_point *ap, const char *name,
 			      MODPREFIX "entry %s is empty!", name);
 			return 1;
 		}
-
+mount_it:
 		debug(ap->logopt,
 		      MODPREFIX "core of entry: options=%s, loc=%.*s",
 		      options, loclen, loc);
openSUSE Build Service is sponsored by