Blob Blame History Raw
autofs-5.1.6 - move lib/master.c to daemon/master.c

From: Ian Kent <raven@themaw.net>

The lib subdirectory isn't really the right place for master.c, move
it to the deamon subdirectory.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG             |    1 
 daemon/Makefile       |   19 
 daemon/master.c       | 1885 ++++++++++++++++++++++++++++++++++++++++++++++++++
 daemon/master_parse.y |  983 ++++++++++++++++++++++++++
 daemon/master_tok.l   |  504 +++++++++++++
 lib/Makefile          |   23 
 lib/master.c          | 1885 --------------------------------------------------
 lib/master_parse.y    |  983 --------------------------
 lib/master_tok.l      |  504 -------------
 9 files changed, 3394 insertions(+), 3393 deletions(-)
 create mode 100644 daemon/master.c
 create mode 100644 daemon/master_parse.y
 create mode 100644 daemon/master_tok.l
 delete mode 100644 lib/master.c
 delete mode 100644 lib/master_parse.y
 delete mode 100644 lib/master_tok.l

--- autofs-5.1.4.orig/CHANGELOG
+++ autofs-5.1.4/CHANGELOG
@@ -133,6 +133,7 @@ xx/xx/2018 autofs-5.1.5
 - remove unused function tree_get_mnt_list().
 - only add expre alarm for active mounts.
 - move submount check into conditional_alarm_add().
+- move lib/master.c to daemon/master.c.
 
 19/12/2017 autofs-5.1.4
 - fix spec file url.
--- autofs-5.1.4.orig/daemon/Makefile
+++ autofs-5.1.4/daemon/Makefile
@@ -6,9 +6,12 @@
 include ../Makefile.rules
 
 SRCS = automount.c indirect.c direct.c spawn.c module.c mount.c \
-	lookup.c state.c flag.c
+	master.c master_tok.l master_parse.y lookup.c state.c flag.c
 OBJS = automount.o indirect.o direct.o spawn.o module.o mount.o \
-	lookup.o state.o flag.o
+	master.o master_tok.o master_parse.tab.o lookup.o state.o \
+	flag.o
+
+YACCSRC = master_tok.c master_parse.tab.c master_parse.tab.h
 
 version := $(shell cat ../.version)
 
@@ -38,8 +41,18 @@ automount: $(OBJS) $(AUTOFS_LIB)
 	$(CC) $(DAEMON_LDFLAGS) -o automount $(OBJS) $(LDFLAGS) $(AUTOFS_LIB) $(LIBS)
 	$(STRIP) automount
 
+master_tok.c: master_tok.l
+	$(LEX) -o$@ -Pmaster_ $?
+
+master_parse.tab.c master_parse.tab.h: master_parse.y
+	$(YACC) -v -d -p master_ -b master_parse $?
+
+master_tok.o: master_tok.c master_parse.tab.h
+
+master_parse.tab.o: master_parse.tab.c master_parse.tab.h
+
 clean:
-	rm -f *.o *.s *~ automount
+	rm -f *.o *.s *~ $(YACCSRC) *.output *~ automount
 
 install: all
 	install -d -m 755 $(INSTALLROOT)$(sbindir)
--- /dev/null
+++ autofs-5.1.4/daemon/master.c
@@ -0,0 +1,1885 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *  master.c - master map utility routines.
+ *
+ *   Copyright 2006 Ian Kent <raven@themaw.net>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *   
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <limits.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include "automount.h"
+
+/* The root of the map entry tree */
+struct master *master_list = NULL;
+
+extern const char *global_options;
+extern long global_negative_timeout;
+
+/* Attribute to create a joinable thread */
+extern pthread_attr_t th_attr;
+
+extern struct startup_cond suc;
+
+static struct map_source *
+__master_find_map_source(struct master_mapent *,
+			 const char *, const char *, int, const char **);
+
+static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void master_mutex_lock(void)
+{
+	int status = pthread_mutex_lock(&master_mutex);
+	if (status)
+		fatal(status);
+}
+
+void master_mutex_unlock(void)
+{
+	int status = pthread_mutex_unlock(&master_mutex);
+	if (status)
+		fatal(status);
+}
+
+void master_mutex_lock_cleanup(void *arg)
+{
+	master_mutex_unlock();
+	return;
+}
+
+int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
+			    unsigned nobind, unsigned ghost, int submount)
+{
+	struct autofs_point *ap;
+	int status;
+
+	ap = malloc(sizeof(struct autofs_point));
+	if (!ap)
+		return 0;
+
+	ap->state = ST_INIT;
+
+	ap->state_pipe[0] = -1;
+	ap->state_pipe[1] = -1;
+	ap->logpri_fifo = -1;
+
+	ap->path = strdup(entry->path);
+	if (!ap->path) {
+		free(ap);
+		return 0;
+	}
+	ap->pref = NULL;
+
+	ap->entry = entry;
+	ap->exp_thread = 0;
+	ap->readmap_thread = 0;
+	/*
+	 * 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_timeout = defaults_get_timeout();
+	ap->exp_runfreq = 0;
+	ap->flags = 0;
+
+	if (defaults_get_use_ignore_mount_option())
+		ap->flags = MOUNT_FLAG_IGNORE;
+	if (ghost)
+		ap->flags |= MOUNT_FLAG_GHOST;
+
+	if (nobind)
+		ap->flags |= MOUNT_FLAG_NOBIND;
+
+	if (ap->path[1] == '-')
+		ap->type = LKP_DIRECT;
+	else
+		ap->type = LKP_INDIRECT;
+
+	ap->logopt = logopt;
+
+	ap->parent = NULL;
+	ap->thid = 0;
+	ap->submnt_count = 0;
+	ap->submount = submount;
+	INIT_LIST_HEAD(&ap->mounts);
+	INIT_LIST_HEAD(&ap->submounts);
+	INIT_LIST_HEAD(&ap->amdmounts);
+	ap->shutdown = 0;
+
+	status = pthread_mutex_init(&ap->mounts_mutex, NULL);
+	if (status) {
+		free(ap->path);
+		free(ap);
+		return 0;
+	}
+	ap->mode = 0;
+
+	entry->ap = ap;
+
+	return 1;
+}
+
+void master_free_autofs_point(struct autofs_point *ap)
+{
+	struct list_head *p, *head;
+	int status;
+
+	if (!ap)
+		return;
+
+	mounts_mutex_lock(ap);
+	head = &ap->amdmounts;
+	p = head->next;
+	while (p != head) {
+		struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
+		p = p->next;
+		ext_mount_remove(mnt->ext_mp);
+		mnts_remove_amdmount(mnt->mp);
+	}
+	mounts_mutex_unlock(ap);
+
+	status = pthread_mutex_destroy(&ap->mounts_mutex);
+	if (status)
+		fatal(status);
+
+	if (ap->pref)
+		free(ap->pref);
+	free(ap->path);
+	free(ap);
+}
+
+struct map_source *
+master_add_map_source(struct master_mapent *entry,
+		      char *type, char *format, time_t age,
+		      int argc, const char **argv)
+{
+	struct map_source *source;
+	char *ntype, *nformat;
+	const char **tmpargv;
+
+	source = malloc(sizeof(struct map_source));
+	if (!source)
+		return NULL;
+	memset(source, 0, sizeof(struct map_source));
+	source->ref = 1;
+
+	if (type) {
+		ntype = strdup(type);
+		if (!ntype) {
+			master_free_map_source(source, 0);
+			return NULL;
+		}
+		source->type = ntype;
+	}
+
+	if (format) {
+		nformat = strdup(format);
+		if (!nformat) {
+			master_free_map_source(source, 0);
+			return NULL;
+		}
+		source->format = nformat;
+		if (!strcmp(nformat, "amd"))
+			source->flags |= MAP_FLAG_FORMAT_AMD;
+	}
+
+	source->age = age;
+	source->stale = 1;
+
+	tmpargv = copy_argv(argc, argv);
+	if (!tmpargv) {
+		master_free_map_source(source, 0);
+		return NULL;
+	}
+	source->argc = argc;
+	source->argv = tmpargv;
+	if (source->argv[0])
+		source->name = strdup(source->argv[0]);
+
+	master_source_writelock(entry);
+
+	if (!entry->maps) {
+		source->mc = cache_init(entry->ap, source);
+		if (!source->mc) {
+			master_free_map_source(source, 0);
+			master_source_unlock(entry);
+			return NULL;
+		}
+		entry->maps = source;
+	} else {
+		struct map_source *this, *last, *next;
+
+		/* Typically there only a few map sources */
+
+		this = __master_find_map_source(entry, type, format, argc, tmpargv);
+		if (this) {
+			debug(entry->ap->logopt,
+			      "map source used without taking reference");
+			this->age = age;
+			master_free_map_source(source, 0);
+			master_source_unlock(entry);
+			return this;
+		}
+
+		source->mc = cache_init(entry->ap, source);
+		if (!source->mc) {
+			master_free_map_source(source, 0);
+			master_source_unlock(entry);
+			return NULL;
+		}
+
+		last = NULL;
+		next = entry->maps;
+		while (next) {
+			last = next;
+			next = next->next;
+		}
+		if (last)
+			last->next = source;
+		else
+			entry->maps = source;
+	}
+
+	master_source_unlock(entry);
+
+	return source;
+}
+
+static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
+{
+	int res = 0;
+
+	if (type) {
+		if (!map->type)
+			goto done;
+
+		if (strcmp(map->type, type))
+			goto done;
+	} else if (map->type)
+		goto done;
+
+	if (format) {
+		if (!map->format)
+			goto done;
+
+		if (strcmp(map->format, format))
+			goto done;
+	} else if (map->format)
+		goto done;
+
+	res = 1;
+done:
+	return res;
+}
+
+static struct map_source *
+__master_find_map_source(struct master_mapent *entry,
+			 const char *type, const char *format,
+			 int argc, const char **argv)
+{
+	struct map_source *map;
+	struct map_source *source = NULL;
+	int res;
+
+	map = entry->maps;
+	while (map) {
+		res = compare_source_type_and_format(map, type, format);
+		if (!res)
+			goto next;
+
+		res = compare_argv(map->argc, map->argv, argc, argv);
+		if (!res)
+			goto next;
+
+		source = map;
+		break;
+next:
+		map = map->next;
+	}
+
+	return source;
+}
+
+struct map_source *master_find_map_source(struct master_mapent *entry,
+				const char *type, const char *format,
+				int argc, const char **argv)
+{
+	struct map_source *source = NULL;
+
+	master_source_readlock(entry);
+	source = __master_find_map_source(entry, type, format, argc, argv);
+	master_source_unlock(entry);
+
+	return source;
+}
+
+struct map_source *
+master_get_map_source(struct master_mapent *entry,
+		      const char *type, const char *format,
+		      int argc, const char **argv)
+{
+	struct map_source *source = NULL;
+
+	master_source_readlock(entry);
+	source = __master_find_map_source(entry, type, format, argc, argv);
+	if (source)
+		source->ref++;
+	master_source_unlock(entry);
+
+	return source;
+}
+
+static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
+{
+	/* instance map sources are not ref counted */
+	if (source->ref && --source->ref)
+		return;
+	if (source->type)
+		free(source->type);
+	if (source->format)
+		free(source->format);
+	if (source->name)
+		free(source->name);
+	if (free_cache && source->mc)
+		cache_release(source);
+	if (source->lookup) {
+		struct map_source *instance;
+
+		instance = source->instance;
+		while (instance) {
+			if (instance->lookup)
+				close_lookup(instance->lookup);
+			instance = instance->next;
+		}
+		close_lookup(source->lookup);
+	}
+	if (source->argv)
+		free_argv(source->argc, source->argv);
+	if (source->instance) {
+		struct map_source *instance, *next;
+
+		instance = source->instance;
+		while (instance) {
+			next = instance->next;
+			__master_free_map_source(instance, 0);
+			instance = next;
+		}
+	}
+
+	free(source);
+
+	return;
+}
+
+void master_free_map_source(struct map_source *source, unsigned int free_cache)
+{
+	int status;
+
+	status = pthread_mutex_lock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	__master_free_map_source(source, free_cache);
+
+	status = pthread_mutex_unlock(&instance_mutex);
+	if (status)
+		fatal(status);
+}
+
+struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
+{
+	struct map_source *map;
+	struct map_source *instance = NULL;
+	int status, res;
+
+	status = pthread_mutex_lock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	map = source->instance;
+	while (map) {
+		res = compare_source_type_and_format(map, type, format);
+		if (!res)
+			goto next;
+
+		if (!argv) {
+			instance = map;
+			break;
+		}
+
+		res = compare_argv(map->argc, map->argv, argc, argv);
+		if (!res)
+			goto next;
+
+		instance = map;
+		break;
+next:
+		map = map->next;
+	}
+
+	status = pthread_mutex_unlock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	return instance;
+}
+
+struct map_source *
+master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
+{
+	struct map_source *instance;
+	struct map_source *new;
+	char *ntype, *nformat;
+	const char **tmpargv;
+	int status;
+
+	instance = master_find_source_instance(source, type, format, argc, argv);
+	if (instance)
+		return instance;
+
+	new = malloc(sizeof(struct map_source));
+	if (!new)
+		return NULL;
+	memset(new, 0, sizeof(struct map_source));
+
+	if (type) {
+		ntype = strdup(type);
+		if (!ntype) {
+			master_free_map_source(new, 0);
+			return NULL;
+		}
+		new->type = ntype;
+	}
+
+	if (format) {
+		nformat = strdup(format);
+		if (!nformat) {
+			master_free_map_source(new, 0);
+			return NULL;
+		}
+		new->format = nformat;
+		if (!strcmp(nformat, "amd"))
+			new->flags |= MAP_FLAG_FORMAT_AMD;
+	}
+
+	new->age = age;
+	new->master_line = 0;
+	new->mc = source->mc;
+	new->exp_timeout = source->exp_timeout;
+	new->stale = 1;
+
+	tmpargv = copy_argv(argc, argv);
+	if (!tmpargv) {
+		master_free_map_source(new, 0);
+		return NULL;
+	}
+	new->argc = argc;
+	new->argv = tmpargv;
+	if (source->name)
+		new->name = strdup(source->name);
+
+	status = pthread_mutex_lock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	if (!source->instance)
+		source->instance = new;
+	else {
+		/*
+		 * We know there's no other instance of this
+		 * type so just add to head of list
+		 */
+		new->next = source->instance;
+		source->instance = new;
+	}
+
+	status = pthread_mutex_unlock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	return new;
+}
+
+int check_stale_instances(struct map_source *source)
+{
+	struct map_source *map;
+
+	if (!source)
+		return 0;
+
+	map = source->instance;
+	while (map) {
+		if (map->stale)
+			return 1;
+		if (check_stale_instances(map))
+			return 1;
+		map = map->next;
+	}
+
+	return 0;
+}
+
+void clear_stale_instances(struct map_source *source)
+{
+	struct map_source *map;
+
+	if (!source)
+		return;
+
+	map = source->instance;
+	while (map) {
+		clear_stale_instances(map);
+		if (map->stale)
+			map->stale = 0;
+		map = map->next;
+	}
+
+	return;
+}
+
+void send_map_update_request(struct autofs_point *ap)
+{
+	struct map_source *map;
+	int status, need_update = 0;
+
+	status = pthread_mutex_lock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	map = ap->entry->maps;
+	while (map) {
+		if (check_stale_instances(map))
+			map->stale = 1;
+		if (map->stale) {
+			need_update = 1;
+			break;
+		}
+		map = map->next;
+	}
+
+	status = pthread_mutex_unlock(&instance_mutex);
+	if (status)
+		fatal(status);
+
+	if (!need_update)
+		return;
+
+	st_add_task(ap, ST_READMAP);
+
+	return;
+}
+
+void master_source_writelock(struct master_mapent *entry)
+{
+	int status;
+
+	status = pthread_rwlock_wrlock(&entry->source_lock);
+	if (status) {
+		logmsg("master_mapent source write lock failed");
+		fatal(status);
+	}
+	return;
+}
+
+void master_source_readlock(struct master_mapent *entry)
+{
+	int retries = 25;
+	int status;
+
+	while (retries--) {
+		status = pthread_rwlock_rdlock(&entry->source_lock);
+		if (status != EAGAIN && status != EBUSY)
+			break;
+		else {
+                	struct timespec t = { 0, 200000000 };
+	                struct timespec r;
+
+			if (status == EAGAIN)
+				logmsg("master_mapent source too many readers");
+			else
+				logmsg("master_mapent source write lock held");
+
+                	while (nanosleep(&t, &r) == -1 && errno == EINTR)
+                        	memcpy(&t, &r, sizeof(struct timespec));
+		}
+	}
+
+	if (status) {
+		logmsg("master_mapent source read lock failed");
+		fatal(status);
+	}
+
+	return;
+}
+
+void master_source_unlock(struct master_mapent *entry)
+{
+	int status;
+
+	status = pthread_rwlock_unlock(&entry->source_lock);
+	if (status) {
+		logmsg("master_mapent source unlock failed");
+		fatal(status);
+	}
+	return;
+}
+
+void master_source_lock_cleanup(void *arg)
+{
+	struct master_mapent *entry = (struct master_mapent *) arg;
+
+	master_source_unlock(entry);
+
+	return;
+}
+
+void master_source_current_wait(struct master_mapent *entry)
+{
+	int status;
+
+	status = pthread_mutex_lock(&entry->current_mutex);
+	if (status) {
+		logmsg("entry current source lock failed");
+		fatal(status);
+	}
+
+	while (entry->current != NULL) {
+		status = pthread_cond_wait(
+				&entry->current_cond, &entry->current_mutex);
+		if (status) {
+			logmsg("entry current source condition wait failed");
+			fatal(status);
+		}
+	}
+
+	return;
+}
+
+void master_source_current_signal(struct master_mapent *entry)
+{
+	int status;
+
+	status = pthread_cond_signal(&entry->current_cond);
+	if (status) {
+		logmsg("entry current source condition signal failed");
+		fatal(status);
+	}
+
+	status = pthread_mutex_unlock(&entry->current_mutex);
+	if (status) {
+		logmsg("entry current source unlock failed");
+		fatal(status);
+	}
+
+	return;
+}
+
+struct master_mapent *master_find_mapent(struct master *master, const char *path)
+{
+	struct list_head *head, *p;
+
+	head = &master->mounts;
+	list_for_each(p, head) {
+		struct master_mapent *entry;
+
+		entry = list_entry(p, struct master_mapent, list);
+
+		if (!strcmp(entry->path, path))
+			return entry;
+	}
+
+	return NULL;
+}
+
+unsigned int master_partial_match_mapent(struct master *master, const char *path)
+{
+	struct list_head *head, *p;
+	size_t path_len = strlen(path);
+	int ret = 0;
+
+	head = &master->mounts;
+	list_for_each(p, head) {
+		struct master_mapent *entry;
+		size_t entry_len;
+		size_t cmp_len;
+
+		entry = list_entry(p, struct master_mapent, list);
+
+		entry_len = strlen(entry->path);
+		cmp_len = min(entry_len, path_len);
+
+		if (!strncmp(entry->path, path, cmp_len)) {
+			/* paths are equal, matching master map entry ? */
+			if (entry_len == path_len) {
+				if (entry->maps &&
+				    entry->maps->flags & MAP_FLAG_FORMAT_AMD)
+					ret = 1;
+				else
+					ret = -1;
+				break;
+			}
+
+			/* amd mount conflicts with entry mount */
+			if (entry_len > path_len &&
+			    *(entry->path + path_len) == '/') {
+				ret = -1;
+				break;
+			}
+
+			/* entry mount conflicts with amd mount */
+			if (entry_len < path_len &&
+			    *(path + entry_len) == '/') {
+				ret = -1;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
+{
+	struct master_mapent *entry;
+	int status;
+	char *tmp;
+
+	entry = malloc(sizeof(struct master_mapent));
+	if (!entry)
+		return NULL;
+
+	memset(entry, 0, sizeof(struct master_mapent));
+
+	tmp = strdup(path);
+	if (!tmp) {
+		free(entry);
+		return NULL;
+	}
+	entry->path = tmp;
+
+	entry->thid = 0;
+	entry->age = age;
+	entry->master = master;
+	entry->current = NULL;
+	entry->maps = NULL;
+	entry->ap = NULL;
+
+	status = pthread_rwlock_init(&entry->source_lock, NULL);
+	if (status)
+		fatal(status);
+
+	status = pthread_mutex_init(&entry->current_mutex, NULL);
+	if (status)
+		fatal(status);
+
+	status = pthread_cond_init(&entry->current_cond, NULL);
+	if (status)
+		fatal(status);
+
+	INIT_LIST_HEAD(&entry->list);
+
+	return entry;
+}
+
+void master_add_mapent(struct master *master, struct master_mapent *entry)
+{
+	list_add_tail(&entry->list, &master->mounts);
+	return;
+}
+
+void master_remove_mapent(struct master_mapent *entry)
+{
+	struct master *master = entry->master;
+
+	if (entry->ap->submount)
+		return;
+
+	if (!list_empty(&entry->list)) {
+		list_del_init(&entry->list);
+		list_add(&entry->join, &master->completed);
+	}
+
+	return;
+}
+
+void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
+{
+	if (entry->maps) {
+		struct map_source *m, *n;
+
+		m = entry->maps;
+		while (m) {
+			n = m->next;
+			master_free_map_source(m, free_cache);
+			m = n;
+		}
+		entry->maps = NULL;
+	}
+
+	return;
+}
+
+void master_free_mapent(struct master_mapent *entry)
+{
+	int status;
+
+	if (entry->path)
+		free(entry->path);
+
+	master_free_autofs_point(entry->ap);
+
+	status = pthread_rwlock_destroy(&entry->source_lock);
+	if (status)
+		fatal(status);
+
+	status = pthread_mutex_destroy(&entry->current_mutex);
+	if (status)
+		fatal(status);
+
+	status = pthread_cond_destroy(&entry->current_cond);
+	if (status)
+		fatal(status);
+
+	free(entry);
+
+	return;
+}
+
+struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
+{
+	struct master *master;
+	char *tmp;
+
+	master = malloc(sizeof(struct master));
+	if (!master)
+		return NULL;
+
+	if (!name)
+		tmp = (char *) defaults_get_master_map();
+	else
+		tmp = strdup(name);
+
+	if (!tmp) {
+		free(master);
+		return NULL;
+	}
+
+	master->name = tmp;
+	master->nc = NULL;
+
+	master->recurse = 0;
+	master->depth = 0;
+	master->reading = 0;
+	master->read_fail = 0;
+	master->readall = 0;
+	master->default_ghost = flags & DAEMON_FLAGS_GHOST;
+	master->default_timeout = timeout;
+	master->default_logging = defaults_get_logging();
+	master->logopt = master->default_logging;
+
+	INIT_LIST_HEAD(&master->mounts);
+	INIT_LIST_HEAD(&master->completed);
+
+	return master;
+}
+
+static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
+{
+	unsigned int m_logopt = master->logopt;
+	struct master_mapent *entry;
+	struct map_source *source;
+	unsigned int loglevel;
+	unsigned int logopt;
+	unsigned int flags;
+	char *argv[2];
+	char **paths;
+	int ret;
+	int i;
+
+	loglevel = conf_amd_get_log_options();
+
+	paths = conf_amd_get_mount_paths();
+	if (!paths)
+		return;
+
+	i = 0;
+	while (paths[i]) {
+		const char *path = paths[i];
+		unsigned int ghost = 0;
+		time_t timeout;
+		char *type = NULL;
+		char *map = NULL;
+		char *opts;
+
+		ret = master_partial_match_mapent(master, path);
+		if (ret) {
+			/* If this amd entry is already present in the
+			 * master map it's not a duplicate, don't issue
+			 * an error message.
+			 */
+			if (ret == 1)
+				goto next;
+			info(m_logopt,
+			     "amd section mount path conflict, %s ignored",
+			     path);
+			goto next;
+		}
+
+		map = conf_amd_get_map_name(path);
+		if (!map) {
+			error(m_logopt,
+			      "failed to get map name for amd section mount %s",
+			      path);
+			goto next;
+		}
+
+		entry = master_new_mapent(master, path, age);
+		if (!entry) {
+			error(m_logopt,
+			      "failed to allocate new amd section mount %s",
+			      path);
+			goto next;
+		}
+
+		logopt = m_logopt;
+		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
+			logopt = LOGOPT_DEBUG;
+		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
+			logopt = LOGOPT_VERBOSE;
+
+		/* It isn't possible to provide the fullybrowsable amd
+		 * browsing functionality within the autofs framework.
+		 * This flag will not be set if browsable_dirs = full
+		 * in the configuration or fullybrowsable is present as
+		 * an option.
+		 */
+		flags = conf_amd_get_flags(path);
+		if (flags & CONF_BROWSABLE_DIRS)
+			ghost = 1;
+
+		ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
+		if (!ret) {
+			error(m_logopt, "failed to add autofs_point");
+			master_free_mapent(entry);
+			goto next;
+		}
+
+		opts = conf_amd_get_map_options(path);
+		if (opts) {
+			/* autofs uses the equivalent of cache:=inc,sync
+			 * (except for file maps which use cache:=all,sync)
+			 * but if the map is large then it may be necessary
+			 * to read the whole map at startup even if browsing
+			 * is is not enabled, so look for cache:=all in the
+			 * map_options configuration entry.
+			 */
+			if (strstr(opts, "cache:=all"))
+				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
+			free(opts);
+		}
+
+		type = conf_amd_get_map_type(path);
+		argv[0] = map;
+		argv[1] = NULL;
+
+		source = master_add_map_source(entry, type, "amd",
+					       age, 1, (const char **) argv);
+		if (!source) {
+			error(m_logopt,
+			      "failed to add source for amd section mount %s",
+			      path);
+			master_free_mapent(entry);
+			goto next;
+		}
+
+		timeout = conf_amd_get_dismount_interval(path);
+		set_exp_timeout(entry->ap, source, timeout);
+		source->master_line = 0;
+
+		entry->age = age;
+		entry->current = NULL;
+
+		master_add_mapent(master, entry);
+next:
+		if (type)
+			free(type);
+		if (map)
+			free(map);
+		i++;
+	}
+
+	i = 0;
+	while (paths[i])
+		free(paths[i++]);
+	free(paths);
+}
+
+static void wait_for_lookups_and_lock(struct master *master)
+{
+	struct list_head *p, *head;
+	int status;
+
+again:
+	master_mutex_lock();
+
+	head = &master->mounts;
+	p = head->next;
+	while (p != head) {
+		struct master_mapent *this;
+
+		this = list_entry(p, struct master_mapent, list);
+
+		status = pthread_rwlock_trywrlock(&this->source_lock);
+		if (status) {
+			struct timespec t = { 0, 200000000 };
+			struct timespec r;
+
+			master_mutex_unlock();
+
+			while (nanosleep(&t, &r) == -1 && errno == EINTR)
+				memcpy(&t, &r, sizeof(struct timespec));
+
+			goto again;
+		}
+		master_source_unlock(this);
+
+		p = p->next;
+	}
+}
+
+int master_read_master(struct master *master, time_t age)
+{
+	unsigned int logopt = master->logopt;
+	struct mapent_cache *nc;
+
+	/*
+	 * We need to clear and re-populate the null map entry cache
+	 * before alowing anyone else to use it.
+	 */
+	wait_for_lookups_and_lock(master);
+	if (master->nc) {
+		cache_writelock(master->nc);
+		nc = master->nc;
+		cache_clean_null_cache(nc);
+	} else {
+		nc = cache_init_null_cache(master);
+		if (!nc) {
+			error(logopt,
+			      "failed to init null map cache for %s",
+			      master->name);
+			return 0;
+		}
+		cache_writelock(nc);
+		master->nc = nc;
+	}
+	master_init_scan();
+	lookup_nss_read_master(master, age);
+	cache_unlock(nc);
+	master_add_amd_mount_section_mounts(master, age);
+
+	if (!master->read_fail)
+		master_mount_mounts(master, age);
+	else {
+		master->read_fail = 0;
+		/* HUP signal sets master->readall == 1 only */
+		if (!master->readall) {
+			master_mutex_unlock();
+			return 0;
+		} else
+			master_mount_mounts(master, age);
+	}
+
+	if (list_empty(&master->mounts))
+		warn(logopt, "no mounts in table");
+
+	master_mutex_unlock();
+
+	return 1;
+}
+
+int master_submount_list_empty(struct autofs_point *ap)
+{
+	int res = 0;
+
+	mounts_mutex_lock(ap);
+	if (list_empty(&ap->submounts))
+		res = 1;
+	mounts_mutex_unlock(ap);
+
+	return res;
+}
+
+int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
+{
+	struct mnt_list *this, *sbmnt;
+	int ret = 1;
+
+	this = mnts_find_submount(path);
+	if (this) {
+		/* We have found a submount to expire */
+		st_mutex_lock();
+
+		if (this->ap->state == ST_SHUTDOWN) {
+			this = NULL;
+			st_mutex_unlock();
+			goto done;
+		}
+
+		this->ap->shutdown = ap->shutdown;
+
+		__st_add_task(this->ap, state);
+
+		st_mutex_unlock();
+
+		st_wait_task(this->ap, state, 0);
+
+		/*
+		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
+		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
+		 * to ST_READY.
+		 */
+		st_mutex_lock();
+		while ((sbmnt = mnts_find_submount(path))) {
+			struct timespec t = { 0, 300000000 };
+			struct timespec r;
+
+			if (sbmnt->ap->state != ST_SHUTDOWN &&
+			    sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
+			    sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
+				ret = 0;
+				mnts_put_mount(sbmnt);
+				break;
+			}
+			mnts_put_mount(sbmnt);
+
+			st_mutex_unlock();
+			while (nanosleep(&t, &r) == -1 && errno == EINTR)
+				memcpy(&t, &r, sizeof(struct timespec));
+			st_mutex_lock();
+		}
+		st_mutex_unlock();
+done:
+		mnts_put_mount(this);
+	}
+
+	return ret;
+}
+
+void master_notify_state_change(struct master *master, int sig)
+{
+	struct master_mapent *entry;
+	struct autofs_point *ap;
+	struct list_head *p;
+	int cur_state;
+	unsigned int logopt;
+
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+	master_mutex_lock();
+
+	list_for_each(p, &master->mounts) {
+		enum states next = ST_INVAL;
+
+		entry = list_entry(p, struct master_mapent, list);
+
+		ap = entry->ap;
+		logopt = ap->logopt;
+
+		st_mutex_lock();
+
+		if (ap->state == ST_SHUTDOWN)
+			goto next;
+
+		switch (sig) {
+		case SIGTERM:
+		case SIGINT:
+			if (ap->state != ST_SHUTDOWN_PENDING &&
+			    ap->state != ST_SHUTDOWN_FORCE) {
+				next = ST_SHUTDOWN_PENDING;
+				ap->shutdown = 1;
+				__st_add_task(ap, next);
+			}
+			break;
+#ifdef ENABLE_FORCED_SHUTDOWN
+		case SIGUSR2:
+			if (ap->state != ST_SHUTDOWN_FORCE &&
+			    ap->state != ST_SHUTDOWN_PENDING) {
+				next = ST_SHUTDOWN_FORCE;
+				ap->shutdown = 1;
+				__st_add_task(ap, next);
+			}
+			break;
+#endif
+		case SIGUSR1:
+			assert(ap->state == ST_READY);
+			next = ST_PRUNE;
+			__st_add_task(ap, next);
+			break;
+		}
+next:
+		if (next != ST_INVAL)
+			debug(logopt,
+			      "sig %d switching %s from %d to %d",
+			      sig, ap->path, ap->state, next);
+
+		st_mutex_unlock();
+	}
+
+	master_mutex_unlock();
+	pthread_setcancelstate(cur_state, NULL);
+
+	return;
+}
+
+static int master_do_mount(struct master_mapent *entry)
+{
+	struct startup_cond suc;
+	struct autofs_point *ap;
+	pthread_t thid;
+	int status;
+
+	ap = entry->ap;
+
+	if (handle_mounts_startup_cond_init(&suc)) {
+		crit(ap->logopt,
+		     "failed to init startup cond for mount %s", entry->path);
+		return 0;
+	}
+
+	suc.ap = ap;
+	suc.root = ap->path;
+	suc.done = 0;
+	suc.status = 0;
+
+	if (!(do_force_unlink & UNLINK_AND_EXIT))
+		debug(ap->logopt, "mounting %s", entry->path);
+
+	status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
+	if (status) {
+		crit(ap->logopt,
+		     "failed to create mount handler thread for %s",
+		     entry->path);
+		handle_mounts_startup_cond_destroy(&suc);
+		return 0;
+	}
+
+	while (!suc.done) {
+		status = pthread_cond_wait(&suc.cond, &suc.mutex);
+		if (status)
+			fatal(status);
+	}
+
+	if (suc.status) {
+		if (!(do_force_unlink & UNLINK_AND_EXIT))
+			error(ap->logopt, "failed to startup mount");
+		handle_mounts_startup_cond_destroy(&suc);
+		return 0;
+	}
+	entry->thid = thid;
+
+	handle_mounts_startup_cond_destroy(&suc);
+
+	return 1;
+}
+
+static void check_update_map_sources(struct master_mapent *entry, int readall)
+{
+	struct map_source *source, *last;
+	struct autofs_point *ap;
+	int map_stale = 0;
+
+	if (readall)
+		map_stale = 1;
+
+	ap = entry->ap;
+
+	master_source_writelock(entry);
+
+	last = NULL;
+	source = entry->maps;
+	while (source) {
+		if (readall)
+			source->stale = 1;
+
+		/*
+		 * If a map source is no longer valid and all it's
+		 * entries have expired away we can get rid of it.
+		 */
+		if (entry->age > source->age) {
+			struct mapent *me;
+			cache_readlock(source->mc);
+			me = cache_lookup_first(source->mc);
+			if (!me) {
+				struct map_source *next = source->next;
+
+				cache_unlock(source->mc);
+
+				if (!last)
+					entry->maps = next;
+				else
+					last->next = next;
+
+				if (entry->maps == source)
+					entry->maps = next;
+
+				master_free_map_source(source, 1);
+
+				source = next;
+				continue;
+			} else {
+				source->stale = 1;
+				map_stale = 1;
+			}
+			cache_unlock(source->mc);
+		}
+		last = source;
+		source = source->next;
+	}
+
+	master_source_unlock(entry);
+
+	/* The map sources have changed */
+	if (map_stale)
+		st_add_task(ap, ST_READMAP);
+
+	return;
+}
+
+int master_mount_mounts(struct master *master, time_t age)
+{
+	struct mapent_cache *nc = master->nc;
+	struct list_head *p, *head;
+	int cur_state;
+
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
+
+	head = &master->mounts;
+	p = head->next;
+	while (p != head) {
+		struct master_mapent *this;
+		struct autofs_point *ap;
+		struct mapent *ne, *nested;
+		struct stat st;
+		int state_pipe, save_errno;
+		int ret;
+
+		this = list_entry(p, struct master_mapent, list);
+		p = p->next;
+
+		ap = this->ap;
+
+		/* A master map entry has gone away */
+		if (this->age < age) {
+			st_add_task(ap, ST_SHUTDOWN_PENDING);
+			continue;
+		}
+
+		cache_readlock(nc);
+		ne = cache_lookup_distinct(nc, this->path);
+		/*
+		 * If this path matched a nulled entry the master map entry
+		 * must be an indirect mount so the master map entry line
+		 * number may be obtained from this->maps.
+		 */
+		if (ne) {
+			int lineno = ne->age;
+			cache_unlock(nc);
+
+			/* null entry appears after map entry */
+			if (this->maps->master_line < lineno) {
+				warn(ap->logopt,
+				     "ignoring null entry that appears after "
+				     "existing entry for %s", this->path);
+				goto cont;
+			}
+			if (ap->state != ST_INIT) {
+				st_add_task(ap, ST_SHUTDOWN_PENDING);
+				continue;
+			}
+			/*
+			 * The map entry hasn't been started yet and we've
+			 * seen a preceeding null map entry for it so just
+			 * delete it from the master map entry list so it
+			 * doesn't get in the road.
+			 */
+			list_del_init(&this->list);
+			master_free_mapent_sources(ap->entry, 1);
+			master_free_mapent(ap->entry);
+			continue;
+		}
+		nested = cache_partial_match(nc, this->path);
+		if (nested) {
+			error(ap->logopt,
+			     "removing invalid nested null entry %s",
+			     nested->key);
+			nested = cache_partial_match(nc, this->path);
+			if (nested)
+				cache_delete(nc, nested->key);
+		}
+		cache_unlock(nc);
+cont:
+		st_mutex_lock();
+
+		state_pipe = this->ap->state_pipe[1];
+
+		/* No pipe so mount is needed */
+		ret = fstat(state_pipe, &st);
+		save_errno = errno;
+
+		st_mutex_unlock();
+
+		if (!ret)
+			check_update_map_sources(this, master->readall);
+		else if (ret == -1 && save_errno == EBADF) {
+			if (!master_do_mount(this)) {
+				list_del_init(&this->list);
+				master_free_mapent_sources(ap->entry, 1);
+				master_free_mapent(ap->entry);
+			}
+		}
+	}
+
+	pthread_setcancelstate(cur_state, NULL);
+
+	return 1;
+}
+
+/* The nss source instances end up in reverse order. */
+static void list_source_instances(struct map_source *source, struct map_source *instance)
+{
+	if (!source || !instance) {
+		printf("none");
+		return;
+	}
+
+	if (instance->next)
+		list_source_instances(source, instance->next);
+
+	/*
+	 * For convienience we map nss instance type "files" to "file".
+	 * Check for that and report corrected instance type.
+	 */
+	if (strcmp(instance->type, "file"))
+		printf("%s ", instance->type);
+	else {
+		if (source->argv && *(source->argv[0]) != '/')
+			printf("files ");
+		else
+			printf("%s ", instance->type);
+	}
+
+	return;
+}
+
+static void print_map_info(struct map_source *source)
+{
+	int argc = source->argc;
+	int i, multi, map_num;
+
+	multi = (source->type && !strcmp(source->type, "multi"));
+	map_num = 1;
+	for (i = 0; i < argc; i++) {
+		if (source->argv[i] && *source->argv[i] != '-') {
+			if (!multi)
+				printf("  map: %s\n", source->argv[i]);
+			else
+				printf("  map[%i]: %s\n", map_num, source->argv[i]);
+			i++;
+		}
+
+		if (i >= argc)
+			return;
+
+		if (!strcmp(source->argv[i], "--"))
+			continue;
+
+		if (source->argv[i]) {
+			int need_newline = 0;
+			int j;
+
+			if (!multi)
+				printf("  arguments:");
+			else
+				printf("  arguments[%i]:", map_num);
+
+			for (j = i; j < source->argc; j++) {
+				if (!strcmp(source->argv[j], "--"))
+					break;
+				printf(" %s", source->argv[j]);
+				i++;
+				need_newline = 1;
+			}
+			if (need_newline)
+				printf("\n");
+		}
+		if (multi)
+			map_num++;
+	}
+
+	return;
+}
+
+static int match_type(const char *source, const char *type)
+{
+	if (!strcmp(source, type))
+		return 1;
+	/* Sources file and files are synonymous */
+	if (!strncmp(source, type, 4) && (strlen(source) <= 5))
+		return 1;
+	return 0;
+}
+
+static char *get_map_name(const char *string)
+{
+	char *name, *tmp;
+	char *start, *end, *base;
+
+	tmp = strdup(string);
+	if (!tmp) {
+		printf("error: allocation failure: %s\n", strerror(errno));
+		return NULL;
+	}
+
+	base = basename(tmp);
+	end = strchr(base, ',');
+	if (end)
+		*end = '\0';
+	start = strchr(tmp, '=');
+	if (start)
+		start++;
+	else {
+		char *colon = strrchr(base, ':');
+		if (colon)
+			start = ++colon;
+		else
+			start = base;
+	}
+
+	name = strdup(start);
+	if (!name)
+		printf("error: allocation failure: %s\n", strerror(errno));
+	free(tmp);
+
+	return name;
+}
+
+static int match_name(struct map_source *source, const char *name)
+{
+	int argc = source->argc;
+	int ret = 0;
+	int i;
+
+	/*
+	 * This can't work for old style "multi" type sources since
+	 * there's no way to know from which map the cache entry came
+	 * from and duplicate entries are ignored at map read time.
+	 * All we can really do is list all the entries for the given
+	 * multi map if one of its map names matches.
+	 */
+	for (i = 0; i < argc; i++) {
+		if (i == 0 || !strcmp(source->argv[i], "--")) {
+			if (i != 0) {
+				i++;
+				if (i >= argc)
+					break;
+			}
+
+			if (source->argv[i] && *source->argv[i] != '-') {
+				char *map = get_map_name(source->argv[i]);
+				if (!map)
+					break;
+				if (!strcmp(map, name)) {
+					ret = 1;
+					free(map);
+					break;
+				}
+				free(map);
+			}
+		}
+	}
+
+	return ret;
+}
+
+int dump_map(struct master *master, const char *type, const char *name)
+{
+	struct list_head *p, *head;
+
+	if (list_empty(&master->mounts)) {
+		printf("no master map entries found\n");
+		return 1;
+	}
+
+	head = &master->mounts;
+	p = head->next;
+	while (p != head) {
+		struct map_source *source;
+		struct master_mapent *this;
+		struct autofs_point *ap;
+		time_t now = monotonic_time(NULL);
+
+		this = list_entry(p, struct master_mapent, list);
+		p = p->next;
+
+		ap = this->ap;
+
+		/*
+		 * Ensure we actually read indirect map entries so we can
+		 * list them. The map reads won't read any indirect map
+		 * entries (other than those in a file map) unless the
+		 * browse option is set.
+		 */
+		if (ap->type == LKP_INDIRECT)
+			ap->flags |= MOUNT_FLAG_GHOST;
+
+		/* Read the map content into the cache */
+		if (lookup_nss_read_map(ap, NULL, now))
+			lookup_prune_cache(ap, now);
+		else {
+			printf("failed to read map\n");
+			lookup_close_lookup(ap);
+			continue;
+		}
+
+		if (!this->maps) {
+			printf("no map sources found for %s\n", ap->path);
+			lookup_close_lookup(ap);
+			continue;
+		}
+
+		source = this->maps;
+		while (source) {
+			struct map_source *instance;
+			struct mapent *me;
+
+			instance = NULL;
+			if (source->type) {
+				if (!match_type(source->type, type)) {
+					source = source->next;
+					continue;
+				}
+				if (!match_name(source, name)) {
+					source = source->next;
+					continue;
+				}
+				instance = source;
+			} else {
+				struct map_source *map;
+
+				map = source->instance;
+				while (map) {
+					if (!match_type(map->type, type)) {
+						map = map->next;
+						continue;
+					}
+					if (!match_name(map, name)) {
+						map = map->next;
+						continue;
+					}
+					instance = map;
+					break;
+				}
+			}
+
+			if (!instance) {
+				source = source->next;
+				lookup_close_lookup(ap);
+				continue;
+			}
+
+			me = cache_lookup_first(source->mc);
+			if (!me)
+				printf("no keys found in map\n");
+			else {
+				do {
+					if (me->source == instance)
+						printf("%s\t%s\n", me->key, me->mapent);
+				} while ((me = cache_lookup_next(source->mc, me)));
+			}
+
+			lookup_close_lookup(ap);
+			return 1;
+		}
+		lookup_close_lookup(ap);
+	}
+
+	return 0;
+}
+
+int master_show_mounts(struct master *master)
+{
+	struct list_head *p, *head;
+
+	printf("\nautofs dump map information\n"
+		 "===========================\n\n");
+
+	printf("global options: ");
+	if (!global_options)
+		printf("none configured\n");
+	else {
+		printf("%s\n", global_options);
+		unsigned int append_options = defaults_get_append_options();
+		const char *append = append_options ? "will" : "will not";
+		printf("global options %s be appended to map entries\n", append);
+	}
+
+	if (list_empty(&master->mounts)) {
+		printf("no master map entries found\n\n");
+		return 1;
+	}
+
+	head = &master->mounts;
+	p = head->next;
+	while (p != head) {
+		struct map_source *source;
+		struct master_mapent *this;
+		struct autofs_point *ap;
+		time_t now = monotonic_time(NULL);
+		unsigned int count = 0;
+
+		this = list_entry(p, struct master_mapent, list);
+		p = p->next;
+
+		ap = this->ap;
+
+		printf("\nMount point: %s\n", ap->path);
+
+		printf("\nsource(s):\n");
+
+		/*
+		 * Ensure we actually read indirect map entries so we can
+		 * list them. The map reads won't read any indirect map
+		 * entries (other than those in a file map) unless the
+		 * browse option is set.
+		 */
+		if (ap->type == LKP_INDIRECT)
+			ap->flags |= MOUNT_FLAG_GHOST;
+
+		/* Read the map content into the cache */
+		if (lookup_nss_read_map(ap, NULL, now))
+			lookup_prune_cache(ap, now);
+		else {
+			printf("  failed to read map\n\n");
+			continue;
+		}
+
+		if (!this->maps) {
+			printf("  no map sources found\n\n");
+			continue;
+		}
+
+		source = this->maps;
+		while (source) {
+			struct mapent *me;
+
+			if (source->type)
+				printf("\n  type: %s\n", source->type);
+			else {
+				printf("\n  instance type(s): ");
+				list_source_instances(source, source->instance);
+				printf("\n");
+			}
+
+			if (source->argc >= 1) {
+				print_map_info(source);
+				if (count && ap->type == LKP_INDIRECT)
+					printf("  duplicate indirect map entry"
+					       " will be ignored at run time\n");
+			}
+
+			printf("\n");
+
+			me = cache_lookup_first(source->mc);
+			if (!me)
+				printf("  no keys found in map\n");
+			else {
+				do {
+					printf("  %s | %s\n", me->key, me->mapent);
+				} while ((me = cache_lookup_next(source->mc, me)));
+			}
+
+			count++;
+
+			source = source->next;
+		}
+
+		lookup_close_lookup(ap);
+
+		printf("\n");
+	}
+
+	return 1;
+}
+
+int master_list_empty(struct master *master)
+{
+	int res = 0;
+
+	master_mutex_lock();
+	if (list_empty(&master->mounts))
+		res = 1;
+	master_mutex_unlock();
+
+	return res;
+}
+
+int master_done(struct master *master)
+{
+	struct list_head *head, *p;
+	struct master_mapent *entry;
+	int res = 0;
+
+	head = &master->completed;
+	p = head->next;
+	while (p != head) {
+		entry = list_entry(p, struct master_mapent, join);
+		p = p->next;
+		list_del(&entry->join);
+		pthread_join(entry->thid, NULL);
+		master_free_mapent_sources(entry, 1);
+		master_free_mapent(entry);
+	}
+	if (list_empty(&master->mounts))
+		res = 1;
+
+	return res;
+}
+
+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))
+		return 0;
+
+	if (master->name)
+		free(master->name);
+
+	cache_release_null_cache(master);
+	free(master);
+
+	return 1;
+}
--- /dev/null
+++ autofs-5.1.4/daemon/master_parse.y
@@ -0,0 +1,983 @@
+%{
+/* ----------------------------------------------------------------------- *
+ *   
+ *  master_parser.y - master map buffer parser.
+ *
+ *   Copyright 2006 Ian Kent <raven@themaw.net>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *   
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sys/ioctl.h>
+
+#include "automount.h"
+#include "master.h"
+
+#define MAX_ERR_LEN	512
+
+extern struct master *master_list;
+
+char **add_argv(int, char **, char *);
+const char **copy_argv(int, const char **);
+int free_argv(int, const char **);
+
+extern FILE *master_in;
+extern char *master_text;
+extern int master_lex(void);
+extern int master_lineno;
+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);
+static int master_notify(const char *s);
+static int master_msg(const char *s);
+ 
+static char *path;
+static char *type;
+static char *format;
+static long timeout;
+static long negative_timeout;
+static unsigned symlnk;
+static unsigned strictexpire;
+static unsigned nobind;
+static unsigned ghost;
+extern unsigned global_selection_options;
+static unsigned random_selection;
+static unsigned use_weight;
+static unsigned long mode;
+static char **tmp_argv;
+static int tmp_argc;
+static char **local_argv;
+static int local_argc;
+
+#define PROPAGATION_SHARED	MOUNT_FLAG_SHARED
+#define PROPAGATION_SLAVE	MOUNT_FLAG_SLAVE
+#define PROPAGATION_PRIVATE	MOUNT_FLAG_PRIVATE
+#define PROPAGATION_MASK	(MOUNT_FLAG_SHARED | \
+				 MOUNT_FLAG_SLAVE  | \
+				 MOUNT_FLAG_PRIVATE)
+static unsigned int propagation;
+
+static char errstr[MAX_ERR_LEN];
+
+static unsigned int verbose;
+static unsigned int debug;
+
+static int lineno;
+
+#define YYDEBUG 0
+
+#ifndef YYENABLE_NLS
+#define YYENABLE_NLS 0
+#endif
+#ifndef YYLTYPE_IS_TRIVIAL
+#define YYLTYPE_IS_TRIVIAL 0
+#endif
+
+#if YYDEBUG
+static int master_fprintf(FILE *, char *, ...);
+#undef YYFPRINTF
+#define YYFPRINTF master_fprintf
+#endif
+
+%}
+
+%union {
+	char strtype[2048];
+	int inttype;
+	long longtype;
+}
+
+%token COMMENT
+%token MAP
+%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
+%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
+%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
+%token COLON COMMA NL DDASH
+%type <strtype> map
+%type <strtype> options
+%type <strtype> dn
+%type <strtype> dnattrs
+%type <strtype> dnattr
+%type <strtype> option
+%type <strtype> daemon_option
+%type <strtype> mount_option
+%token <strtype> PATH
+%token <strtype> QUOTE
+%token <strtype> NILL
+%token <strtype> SPACE
+%token <strtype> EQUAL
+%token <strtype> MULTITYPE
+%token <strtype> MAPTYPE
+%token <strtype> DNSERVER
+%token <strtype> DNATTR
+%token <strtype> DNNAME
+%token <strtype> MAPHOSTS
+%token <strtype> MAPNULL
+%token <strtype> MAPXFN
+%token <strtype> MAPNAME
+%token <longtype> NUMBER
+%token <longtype> OCTALNUMBER
+%token <strtype> OPTION
+
+%start file
+
+%%
+
+file: {
+		master_lineno = 0;
+#if YYDEBUG != 0
+		master_debug = YYDEBUG;
+#endif
+	} line
+	;
+
+line:
+	| PATH mapspec
+	{
+		path = master_strdup($1);
+		if (!path) {
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| PATH MULTITYPE maplist
+	{
+		char *tmp = NULL;
+
+		trim_maptype($2);
+
+		if (path)
+			free(path);
+		path = master_strdup($1);
+		if (!path) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+
+		if ((tmp = strchr($2, ',')))
+			*tmp++ = '\0';
+#ifndef WITH_HESIOD
+		/* Map type or map type parser is hesiod */
+		if (!strcmp($2, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
+			master_error("hesiod support not built in");
+			local_free_vars();
+			YYABORT;
+		}
+#endif
+		if (type)
+			free(type);
+		type = master_strdup($2);
+		if (!type) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+		if (tmp) {
+			if (format)
+				free(format);
+			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; }
+	| PATH OPT_RANDOM { master_notify($1); YYABORT; }
+	| PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
+	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
+	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
+	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
+	| PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
+	| PATH OPT_SHARED { master_notify($1); YYABORT; }
+	| PATH OPT_SLAVE { master_notify($1); YYABORT; }
+	| PATH OPT_PRIVATE { master_notify($1); YYABORT; }
+	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
+	| PATH OPT_GHOST { master_notify($1); YYABORT; }
+	| PATH OPT_NOGHOST { master_notify($1); YYABORT; }
+	| PATH OPT_VERBOSE { master_notify($1); YYABORT; }
+	| PATH OPT_MODE { master_notify($1); YYABORT; }
+	| PATH { master_notify($1); YYABORT; }
+	| QUOTE { master_notify($1); YYABORT; }
+	| OPTION { master_notify($1); YYABORT; }
+	| NILL { master_notify($1); YYABORT; }
+	| COMMENT { YYABORT; }
+	;
+
+mapspec: map
+	{
+		if (local_argv)
+			free_argv(local_argc, (const char **) local_argv);
+		local_argc = tmp_argc;
+		local_argv = tmp_argv;
+		tmp_argc = 0;
+		tmp_argv = NULL;
+	}
+	| map options
+	{
+		if (local_argv)
+			free_argv(local_argc, (const char **) local_argv);
+		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, "--");
+		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;
+		}
+	}
+	| maplist DDASH map options
+	{
+		local_argc++;
+		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
+	{
+		if (type)
+			free(type);
+		type = master_strdup($1 + 1);
+		if (!type) {
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| MAPXFN
+	{
+		master_notify($1);
+		master_msg("X/Open Federated Naming service not supported");
+		YYABORT;
+	}
+	| MAPNULL
+	{
+		if (type)
+			free(type);
+		type = master_strdup($1 + 1);
+		if (!type) {
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| dnattrs
+	{
+		if (type)
+			free(type);
+		type = master_strdup("ldap");
+		if (!type) {
+			local_free_vars();
+			YYABORT;
+		}
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| MAPTYPE PATH
+	{
+		char *tmp = NULL;
+
+		trim_maptype($1);
+
+		if ((tmp = strchr($1, ',')))
+			*tmp++ = '\0';
+#ifndef WITH_HESIOD
+		/* Map type or map type parser is hesiod */
+		if (!strcmp($1, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
+			master_error("hesiod support not built in");
+			local_free_vars();
+			YYABORT;
+		}
+#endif
+		if (type)
+			free(type);
+		if (strcmp($1, "exec"))
+			type = master_strdup($1);
+		else
+			type = master_strdup("program");
+		if (!type) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+		if (tmp) {
+			if (format)
+				free(format);
+			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, $2);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| MAPTYPE MAPNAME
+	{
+		char *tmp = NULL;
+
+		trim_maptype($1);
+
+		if ((tmp = strchr($1, ',')))
+			*tmp++ = '\0';
+
+		if (type)
+			free(type);
+		if (strcmp($1, "exec"))
+			type = master_strdup($1);
+		else
+			type = master_strdup("program");
+		if (!type) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+		if (tmp) {
+			if (format)
+				free(format);
+			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, $2);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	| MAPTYPE dn
+	{
+		char *tmp = NULL;
+
+		trim_maptype($1);
+
+		if ((tmp = strchr($1, ',')))
+			*tmp++ = '\0';
+
+		if (type)
+			free(type);
+		if (strcmp($1, "exec"))
+			type = master_strdup($1);
+		else
+			type = master_strdup("program");
+		if (!type) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+		if (tmp) {
+			if (format)
+				free(format);
+			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, $2);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+		/* Add back the type for lookup_ldap.c to handle ldaps */
+		if (*tmp_argv[0]) {
+			tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
+			if (!tmp) {
+				master_error("memory allocation error");
+				local_free_vars();
+				YYABORT;
+			}
+			strcpy(tmp, type);
+			strcat(tmp, ":");
+			strcat(tmp, tmp_argv[0]);
+			free(tmp_argv[0]);
+			tmp_argv[0] = tmp;
+		}
+	}
+	;
+
+dn:	DNSERVER dnattrs
+	{
+		strcpy($$, $1);
+		strcat($$, $2);
+	}
+	| dnattrs
+	{
+		strcpy($$, $1);
+	}
+	|
+	{
+		master_notify("syntax error in dn");
+		YYABORT;
+	}
+	;
+
+dnattrs: DNATTR EQUAL DNNAME
+	{
+		if (strcasecmp($1, "cn") &&
+		    strcasecmp($1, "ou") &&
+		    strcasecmp($1, "automountMapName") &&
+		    strcasecmp($1, "nisMapName")) {
+			strcpy(errstr, $1);
+			strcat(errstr, "=");
+			strcat(errstr, $3);
+			master_notify(errstr);
+			YYABORT;
+		}
+		strcpy($$, $1);
+		strcat($$, "=");
+		strcat($$, $3);
+	}
+	| DNATTR EQUAL DNNAME COMMA dnattr
+	{
+		if (strcasecmp($1, "cn") &&
+		    strcasecmp($1, "ou") &&
+		    strcasecmp($1, "automountMapName") &&
+		    strcasecmp($1, "nisMapName")) {
+			strcpy(errstr, $1);
+			strcat(errstr, "=");
+			strcat(errstr, $3);
+			master_notify(errstr);
+			YYABORT;
+		}
+		strcpy($$, $1);
+		strcat($$, "=");
+		strcat($$, $3);
+		strcat($$, ",");
+		strcat($$, $5);
+	}
+	| DNNAME
+	{
+		/* Matches map in old style syntax ldap:server:map */
+		strcpy($$, $1);
+	}
+	| DNATTR
+	{
+		master_notify($1);
+		YYABORT;
+	}
+	;
+
+dnattr: DNATTR EQUAL DNNAME
+	{
+		if (!strcasecmp($1, "automountMapName") ||
+		    !strcasecmp($1, "nisMapName")) {
+			strcpy(errstr, $1);
+			strcat(errstr, "=");
+			strcat(errstr, $3);
+			master_notify(errstr);
+			YYABORT;
+		}
+		strcpy($$, $1);
+		strcat($$, "=");
+		strcat($$, $3);
+	}
+	| DNATTR EQUAL DNNAME COMMA dnattr
+	{
+		if (!strcasecmp($1, "automountMapName") ||
+		    !strcasecmp($1, "nisMapName")) {
+			strcpy(errstr, $1);
+			strcat(errstr, "=");
+			strcat(errstr, $3);
+			master_notify(errstr);
+			YYABORT;
+		}
+		strcpy($$, $1);
+		strcat($$, "=");
+		strcat($$, $3);
+		strcat($$, ",");
+		strcat($$, $5);
+	}
+	| DNATTR
+	{
+		master_notify($1);
+		YYABORT;
+	}
+	| DNNAME
+	{
+		master_notify($1);
+		YYABORT;
+	}
+	;
+
+options: option {}
+	| options COMMA option {}
+	| options option {}
+	| options COMMA COMMA option
+	{
+		master_notify($1);
+		YYABORT;
+	}
+	| options EQUAL
+	{
+		master_notify($1);
+		YYABORT;
+	}
+	;
+
+option: daemon_option
+	| mount_option {}
+	| error
+	{
+		master_notify("bogus option");
+		YYABORT;
+	}
+	;
+
+daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
+	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
+	| OPT_SYMLINK	{ symlnk = 1; }
+	| OPT_STRICTEXPIRE { strictexpire = 1; }
+	| OPT_SHARED	{ propagation = PROPAGATION_SHARED; }
+	| OPT_SLAVE	{ propagation = PROPAGATION_SLAVE; }
+	| OPT_PRIVATE	{ propagation = PROPAGATION_PRIVATE; }
+	| OPT_NOBIND	{ nobind = 1; }
+	| OPT_NOGHOST	{ ghost = 0; }
+	| OPT_GHOST	{ ghost = 1; }
+	| OPT_VERBOSE	{ verbose = 1; }
+	| OPT_DEBUG	{ debug = 1; }
+	| OPT_RANDOM	{ random_selection = 1; }
+	| OPT_USE_WEIGHT { use_weight = 1; }
+	| OPT_MODE OCTALNUMBER { mode = $2; }
+	;
+
+mount_option: OPTION
+	{
+		tmp_argc++;
+		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+		if (!tmp_argv) {
+			master_error("memory allocation error");
+			local_free_vars();
+			YYABORT;
+		}
+	}
+	;
+%%
+
+#if YYDEBUG
+static int master_fprintf(FILE *f, char *msg, ...)
+{
+	va_list ap;
+	va_start(ap, msg);
+	vsyslog(LOG_DEBUG, msg, ap);
+	va_end(ap);
+	return 1;
+}
+#endif
+
+static char *master_strdup(char *str)
+{
+	char *tmp;
+
+	tmp = strdup(str);
+	if (!tmp)
+		master_error("memory allocation error");
+	return tmp;
+}
+
+static int master_error(const char *s)
+{
+	logmsg("%s while parsing map.", s);
+	return 0;
+}
+
+static int master_notify(const char *s)
+{
+	logmsg("syntax error in map near [ %s ]", s);
+	return(0);
+}
+
+static int master_msg(const char *s)
+{
+	logmsg("%s", s);
+	return 0;
+}
+
+static void local_init_vars(void)
+{
+	path = NULL;
+	type = NULL;
+	format = NULL;
+	verbose = 0;
+	debug = 0;
+	timeout = -1;
+	negative_timeout = 0;
+	symlnk = 0;
+	strictexpire = 0;
+	propagation = PROPAGATION_SLAVE;
+	nobind = 0;
+	ghost = defaults_get_browse_mode();
+	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
+	use_weight = 0;
+	mode = 0;
+	tmp_argv = NULL;
+	tmp_argc = 0;
+	local_argv = NULL;
+	local_argc = 0;
+}
+
+static void local_free_vars(void)
+{
+	if (path)
+		free(path);
+
+	if (type)
+		free(type);
+
+	if (format)
+		free(format);
+
+	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 void trim_maptype(char *type)
+{
+	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;
+		}
+
+		local_argc++;
+		local_argv = add_argv(local_argc, local_argv, type);
+		if (!local_argv) {
+			free(type);
+			type = NULL;
+			return 0;
+		}
+
+		free(type);
+		type = NULL;
+	}
+
+	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;
+
+	return 1;
+}
+
+void master_init_scan(void)
+{
+	lineno = 0;
+}
+
+int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
+{
+	struct master *master = master_list;
+	struct mapent_cache *nc;
+	struct master_mapent *entry, *new;
+	struct map_source *source;
+	unsigned int logopt = logging;
+	unsigned int m_logopt = master->logopt;
+	size_t mp_len;
+	int ret;
+
+	local_init_vars();
+
+	lineno++;
+
+	master_set_scan_buffer(buffer);
+
+	ret = master_parse();
+	if (ret != 0) {
+		local_free_vars();
+		return 0;
+	}
+
+	mp_len = strlen(path);
+	while (mp_len && path[--mp_len] == '/')
+		path[mp_len] = 0;
+
+	nc = master->nc;
+
+	/* Add null map entries to the null map cache */
+	if (type && !strcmp(type, "null")) {
+		cache_update(nc, NULL, path, NULL, lineno);
+		local_free_vars();
+		return 1;
+	}
+
+	/* Ignore all subsequent matching nulled entries */
+	if (cache_lookup_distinct(nc, path)) {
+		local_free_vars();
+		return 1;
+	}
+
+	if (debug || verbose) {
+		logopt = (debug ? LOGOPT_DEBUG : 0);
+		logopt |= (verbose ? LOGOPT_VERBOSE : 0);
+	}
+
+	new = NULL;
+	entry = master_find_mapent(master, path);
+	if (!entry) {
+		new = master_new_mapent(master, path, age);
+		if (!new) {
+			local_free_vars();
+			return 0;
+		}
+		entry = new;
+	} else {
+		if (entry->age && entry->age == age) {
+			if (strcmp(path, "/-")) {
+				info(m_logopt,
+				    "ignoring duplicate indirect mount %s",
+				     path);
+				local_free_vars();
+				return 0;
+			}
+		}
+	}
+
+	if (!format) {
+		if (conf_amd_mount_section_exists(path))
+			format = strdup("amd");
+	}
+
+	if (format && !strcmp(format, "amd")) {
+		unsigned int loglevel = conf_amd_get_log_options();
+		unsigned int flags = conf_amd_get_flags(path);
+
+		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
+			logopt = LOGOPT_DEBUG;
+		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
+			logopt = LOGOPT_VERBOSE;
+
+		/* It isn't possible to provide the fullybrowsable amd
+		 * browsing functionality within the autofs framework.
+		 * This flag will not be set if browsable_dirs = full
+		 * in the configuration or fullybrowsable is present as
+		 * an option.
+		 */
+		if (flags & CONF_BROWSABLE_DIRS)
+			ghost = 1;
+	}
+
+	if (!entry->ap) {
+		ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
+		if (!ret) {
+			error(m_logopt, "failed to add autofs_point");
+			if (new)
+				master_free_mapent(new);
+			local_free_vars();
+			return 0;
+		}
+	}
+	entry->ap->flags &= ~(PROPAGATION_MASK);
+	entry->ap->flags |= propagation;
+
+	if (random_selection)
+		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
+	if (use_weight)
+		entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
+	if (symlnk)
+		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
+	if (strictexpire)
+		entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
+	if (negative_timeout)
+		entry->ap->negative_timeout = negative_timeout;
+	if (mode && mode < LONG_MAX)
+		entry->ap->mode = mode;
+
+	if (timeout < 0) {
+		/*
+		 * If no timeout is given get the timout from the
+		 * autofs point, or the first map, or the config
+		 * for amd maps.
+		 */
+		if (format && !strcmp(format, "amd"))
+			timeout = conf_amd_get_dismount_interval(path);
+		else
+			timeout = get_exp_timeout(entry->ap, entry->maps);
+	}
+
+	if (format && !strcmp(format, "amd")) {
+		char *opts = conf_amd_get_map_options(path);
+		if (opts) {
+			/* autofs uses the equivalent of cache:=inc,sync
+			 * (except for file maps which use cache:=all,sync)
+			 * but if the map is large then it may be necessary
+			 * to read the whole map at startup even if browsing
+			 * is is not enabled, so look for cache:=all in the
+			 * map_options configuration entry.
+			 */
+			if (strstr(opts, "cache:=all"))
+				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
+			free(opts);
+		}
+	}
+
+/*
+	source = master_find_map_source(entry, type, format,
+					local_argc, (const char **) local_argv); 
+	if (!source)
+		source = master_add_map_source(entry, type, format, age, 
+					local_argc, (const char **) local_argv);
+	else
+		source->age = age;
+*/
+	source = master_add_map_source(entry, type, format, age, 
+					local_argc, (const char **) local_argv);
+	if (!source) {
+		error(m_logopt, "failed to add source");
+		if (new)
+			master_free_mapent(new);
+		local_free_vars();
+		return 0;
+	}
+	set_exp_timeout(entry->ap, source, timeout);
+	source->master_line = lineno;
+
+	entry->age = age;
+	entry->current = NULL;
+
+	if (new)
+		master_add_mapent(master, entry);
+
+	local_free_vars();
+
+	return 1;
+}
+
--- /dev/null
+++ autofs-5.1.4/daemon/master_tok.l
@@ -0,0 +1,504 @@
+%{
+/* ----------------------------------------------------------------------- *
+ *   
+ *  master_tok.l - master map tokenizer.
+ *
+ *   Copyright 2006 Ian Kent <raven@themaw.net>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *   
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifdef ECHO
+# undef ECHO
+#endif /* ECHO */
+static void master_echo(void);	/* forward definition */
+#define ECHO master_echo()
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "master_parse.tab.h"
+
+/*
+ * There are some things that need to be defined only if useing GNU flex.
+ * These must not be defined if using standard lex
+ */
+#ifdef FLEX_SCANNER
+int master_lineno;
+#endif
+
+int master_lex(void);
+int master_wrap(void);
+
+/* no need for yywrap() */
+#define YY_SKIP_YYWRAP
+
+#ifndef YY_STACK_USED
+#define YY_STACK_USED 0
+#endif
+#ifndef YY_ALWAYS_INTERACTIVE
+#define YY_ALWAYS_INTERACTIVE 0
+#endif
+#ifndef YY_NEVER_INTERACTIVE
+#define YY_NEVER_INTERACTIVE 0
+#endif
+#ifndef YY_MAIN
+#define YY_MAIN 0
+#endif
+
+void master_set_scan_buffer(const char *);
+const char *line = NULL;
+
+#ifdef FLEX_SCANNER
+const char *line_pos = NULL;
+const char *line_lim = NULL;
+int my_yyinput(char *, int);
+
+#undef YY_INPUT
+#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
+#else
+#undef input
+#undef unput
+#define input()  (*(char *) line++)
+#define unput(c) (*(char *) --line = c)
+#endif
+
+#define BUFF_LEN	1024
+char buff[BUFF_LEN];
+char *bptr;
+char *optr = buff;
+unsigned int tlen;
+
+%}
+
+%option nounput
+
+%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
+
+WS		[[:blank:]]+
+OPTWS		[[:blank:]]*
+NL		\r?\n
+CONT		\\\n{OPTWS}
+
+OPTIONSTR	([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
+MACROSTR	(-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
+SLASHIFYSTR	(--(no-)?slashify-colons)
+NUMBER		[0-9]+
+OCTALNUMBER	[0-7]+
+
+DNSERVSTR1	([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
+DNSERVSTR2	(\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
+DNSERVSTR3	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
+DNSERVSTR4	(\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
+DNSERVSTR5	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
+DNSERVSTR6	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
+DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
+
+AT_CN		([cC][[nN])
+AT_NMN		([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
+AT_AMN		([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
+AT_OU		([oO][[uU])
+AT_DC		([dD][[cC])
+AT_O		([oO])
+AT_C		([cC])
+AT_L		([lL])
+DNATTRSTR	({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
+DNNAMESTR1	([[:alnum:]_.\- ]+)
+DNNAMESTR2	([[:alnum:]_.\-]+)
+
+INTMAP		(-hosts|-null)
+MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
+MULTISEP	([\-]{2}[[:blank:]]+)
+MTYPE		((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
+
+
+OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
+OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
+
+MODE		(--mode{OPTWS}|--mode{OPTWS}={OPTWS})
+
+%%
+
+<INITIAL>{
+	{NL} | 
+	\x00 {
+		if (optr != buff) {
+			*optr = '\0';
+			strcpy(master_lval.strtype, buff);
+			return NILL;
+		}
+	}
+
+	#.*  { return COMMENT; }
+
+	"/" {
+		if (optr != buff) {
+			*optr = '\0';
+			strcpy(master_lval.strtype, buff);
+			return NILL;
+		}
+		BEGIN(PATHSTR);
+		bptr = buff;
+		yyless(0);
+	}
+
+	.    { *optr++ = *master_text; }
+}
+
+<PATHSTR>{
+	\x00 {
+		BEGIN(INITIAL);
+		*bptr++ = *master_text;
+		strcpy(master_lval.strtype, buff);
+		return NILL;
+	}
+
+	\\.  { *bptr++ = *(master_text + 1); }
+	\"   {
+		BEGIN(INITIAL);
+		*bptr++ = *master_text;
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		return QUOTE;
+	}
+
+	{WS} {
+		BEGIN(MAPSTR);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		bptr = buff;
+		memset(buff, 0, BUFF_LEN);
+		return(PATH);
+	}
+
+	<<EOF>> {
+		BEGIN(INITIAL);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		return(PATH);
+	}
+
+	{NL} {
+		BEGIN(INITIAL);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		return PATH;
+	}
+
+	.    { *bptr++ = *master_text; }
+}
+
+<MAPSTR>{
+	{OPTWS}\\\n{OPTWS} {}
+
+	{MULTI} {
+		tlen = master_leng - 1;
+		if (bptr != buff && isblank(master_text[tlen])) {
+			/*
+			 * We can't handle unescaped white space in map names
+			 * so just eat the white space. We always have the
+			 * "multi" at the beginning of the string so the while
+			 * will not fall off the end.
+			 */
+			while (isblank(master_text[tlen - 1]))
+				tlen--;
+			strncat(buff, master_text, tlen);
+			bptr += tlen;
+			yyless(tlen);
+		} else {
+			strcpy(master_lval.strtype, master_text);
+			return(MULTITYPE);
+		}
+	}
+
+	{MTYPE} |
+	{MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
+	{MTYPE}/{DNATTRSTR}= {
+		tlen = master_leng - 1;
+		if (bptr != buff && isblank(master_text[tlen])) {
+			/*
+			 * We can't handle unescaped white space in map names
+			 * so just eat the white space. We always have the
+			 * maptype keyword at the beginning of the string so
+			 * the while will not fall off the end.
+			 */
+			while (isblank(master_text[tlen - 1]))
+				tlen--;
+			strncat(buff, master_text, tlen);
+			bptr += tlen;
+			yyless(tlen);
+		} else {
+			strcpy(master_lval.strtype, master_text);
+			return(MAPTYPE);
+		}
+	}
+
+	{MULTISEP} { return(DDASH); }
+
+	":"	{ return(COLON); }
+
+	"-hosts" {
+		BEGIN(OPTSTR);
+		strcpy(master_lval.strtype, master_text);
+		return MAPHOSTS;
+	}
+
+	"-null" {
+		BEGIN(OPTSTR);
+		strcpy(master_lval.strtype, master_text);
+		return MAPNULL;
+	}
+
+	"-xfn" {
+		/*
+		 * The X/Open Federated Naming service isn't supported
+		 * and the parser will call YYABORT() when it sees the
+		 * MAPXFN token so we must set the start state to the
+		 * INITIAL state here for the next yylex() call.
+		 */
+		BEGIN(INITIAL);
+		strcpy(master_lval.strtype, master_text);
+		return MAPXFN;
+	}
+
+	"//" {
+		BEGIN(DNSTR);
+		yyless(0);
+	}
+
+	{DNSERVERSTR}{DNATTRSTR}= {
+		BEGIN(DNSTR);
+		yyless(0);
+	}
+
+	{DNATTRSTR}= {
+		BEGIN(DNSTR);
+		yyless(0);
+	}
+
+	{OPTWS}/{NL} {
+		BEGIN(INITIAL);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		bptr = buff;
+		return(MAPNAME);
+	}
+
+	\\. { *bptr++ = *(master_text + 1); }
+
+	{WS} {
+		BEGIN(OPTSTR);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		bptr = buff;
+		return(MAPNAME);
+	}
+
+	{NL} |
+	\x00 {
+		BEGIN(INITIAL);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		return(MAPNAME);
+	}
+
+	<<EOF>> {
+		BEGIN(INITIAL);
+		*bptr = '\0';
+		strcpy(master_lval.strtype, buff);
+		return(MAPNAME);
+	}
+
+	.	{ *bptr++ = *master_text; }
+}
+
+<DNSTR>{
+	{OPTWS}\\\n{OPTWS} {}
+
+	{DNSERVERSTR} {
+		strcpy(master_lval.strtype, master_text);
+		return DNSERVER;
+	}
+
+	{DNATTRSTR}/"=" {
+		strcpy(master_lval.strtype, master_text);
+		return DNATTR;
+	}
+
+	"=" {
+		return EQUAL;
+	}
+
+	{DNNAMESTR1}/","{DNATTRSTR}"=" {
+		strcpy(master_lval.strtype, master_text);
+		return DNNAME;
+	}
+
+	{DNNAMESTR2} {
+		strcpy(master_lval.strtype, master_text);
+		return DNNAME;
+	}
+
+	{OPTWS}","{OPTWS} {
+		return COMMA;
+	}
+
+	{WS}"=" |
+	"="{WS} {
+		BEGIN(INITIAL);
+		strcpy(master_lval.strtype, master_text);
+		return SPACE;
+	}
+
+	{WS}    { BEGIN(OPTSTR); }
+
+	{NL} |
+	\x00	{ BEGIN(INITIAL); }
+
+	<<EOF>> { BEGIN(INITIAL); }
+}
+
+<OPTSTR>{
+	{OPTWS}\\\n{OPTWS} {}
+
+	{MULTISEP} {
+		BEGIN(MAPSTR);
+		return(DDASH);
+	}
+
+	{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
+
+	{OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
+
+	{NUMBER} {
+		master_lval.longtype = atol(master_text);
+		return(NUMBER);
+	}
+
+	-?symlink		{ return(OPT_SYMLINK); }
+	-?nobind		{ return(OPT_NOBIND); }
+	-?nobrowse		{ return(OPT_NOGHOST); }
+	-?shared		{ return(OPT_SHARED); }
+	-?slave			{ return(OPT_SLAVE); }
+	-?private		{ return(OPT_PRIVATE); }
+	-?strictexpire		{ return(OPT_STRICTEXPIRE); }
+	-g|--ghost|-?browse	{ return(OPT_GHOST); }
+	-v|--verbose		{ return(OPT_VERBOSE); }
+	-d|--debug		{ return(OPT_DEBUG); }
+	-w|--use-weight-only	{ return(OPT_USE_WEIGHT); }
+	-r|--random-multimount-selection { return(OPT_RANDOM); }
+
+	{MODE}/{OCTALNUMBER} {
+		BEGIN(OCTAL);
+		return(OPT_MODE);
+	}
+
+	{OPTWS}","{OPTWS}	{ return(COMMA); }
+
+	{OPTWS} {}
+
+	{SLASHIFYSTR} {
+		strcpy(master_lval.strtype, master_text);
+		return(OPTION);
+	}
+
+	{MACROSTR} {
+		strcpy(master_lval.strtype, master_text);
+		return(OPTION);
+	}
+
+	{OPTIONSTR} {
+		strcpy(master_lval.strtype, master_text);
+		return(OPTION);
+	}
+
+	"="	{
+		strcpy(master_lval.strtype, master_text);
+		return(EQUAL);
+	}
+
+	{WS}	{}
+	{NL} |
+	\x00 { BEGIN(INITIAL); }
+
+	<<EOF>> { BEGIN(INITIAL); }
+}
+
+<OCTAL>{
+	{OCTALNUMBER} {
+		master_lval.longtype = strtoul(master_text, NULL, 8);
+		return(OCTALNUMBER);
+	}
+
+	. { BEGIN(OPTSTR); yyless(0); }
+}
+
+%%
+
+#include "automount.h"
+
+int master_wrap(void)
+{
+	return 1;
+}
+
+static void master_echo(void)
+{
+	logmsg("%s", master_text);
+	return;
+}
+
+#ifdef FLEX_SCANNER
+
+void master_set_scan_buffer(const char *buffer)
+{
+	memset(buff, 0, sizeof(buff));
+	optr = buff;
+
+	YY_FLUSH_BUFFER;
+
+	line = buffer;
+	line_pos = &line[0];
+	/*
+	 * 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;
+}
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+int my_yyinput(char *buffer, int max_size)
+{
+	int n = min(max_size, line_lim - line_pos);
+
+	if (n > 0) {
+		memcpy(buffer, line_pos, n);
+		line_pos += n;
+	}
+	return n;
+}
+
+#else
+
+void master_set_scan_buffer(const char *buffer)
+{
+	line = buffer;
+}
+
+#endif
--- autofs-5.1.4.orig/lib/Makefile
+++ autofs-5.1.4/lib/Makefile
@@ -6,17 +6,14 @@
 include ../Makefile.rules
 
 SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \
-	master_tok.l master_parse.y nss_tok.c nss_parse.tab.c \
-	args.c alarm.c macros.c master.c defaults.c parse_subs.c \
-	dev-ioctl-lib.c
+	nss_tok.c nss_parse.tab.c args.c alarm.c macros.c defaults.c \
+	parse_subs.c dev-ioctl-lib.c
 RPCS = mount.h mount_clnt.c mount_xdr.c
 OBJS = cache.o mount_clnt.o mount_xdr.o cat_path.o rpc_subs.o \
-	mounts.o log.o nsswitch.o master_tok.o master_parse.tab.o \
-	nss_tok.o nss_parse.tab.o args.o alarm.o macros.o master.o \
-	defaults.o parse_subs.o dev-ioctl-lib.o
+	mounts.o log.o nsswitch.o nss_tok.o nss_parse.tab.o args.o \
+	alarm.o macros.o defaults.o parse_subs.o dev-ioctl-lib.o
 
-YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h \
-	  master_tok.c master_parse.tab.c master_parse.tab.h
+YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h
 
 LIB = autofs.a
 
@@ -54,16 +51,6 @@ mount_xdr.o: mount_xdr.c
 	$(CC) $(CFLAGS) -Wno-unused-variable -o mount_xdr.o -c mount_xdr.c
 	$(STRIP) mount_xdr.o
 
-master_tok.c: master_tok.l
-	$(LEX) -o$@ -Pmaster_ $?
-
-master_parse.tab.c master_parse.tab.h: master_parse.y
-	$(YACC) -v -d -p master_ -b master_parse $?
-
-master_tok.o: master_tok.c master_parse.tab.h
-
-master_parse.tab.o: master_parse.tab.c master_parse.tab.h
-
 nss_tok.c: nss_tok.l
 	$(LEX) -o$@ -Pnss_ $?
 
--- autofs-5.1.4.orig/lib/master.c
+++ /dev/null
@@ -1,1885 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *   
- *  master.c - master map utility routines.
- *
- *   Copyright 2006 Ian Kent <raven@themaw.net>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- *   USA; either version 2 of the License, or (at your option) any later
- *   version.
- *   
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- * ----------------------------------------------------------------------- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <memory.h>
-#include <limits.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include "automount.h"
-
-/* The root of the map entry tree */
-struct master *master_list = NULL;
-
-extern const char *global_options;
-extern long global_negative_timeout;
-
-/* Attribute to create a joinable thread */
-extern pthread_attr_t th_attr;
-
-extern struct startup_cond suc;
-
-static struct map_source *
-__master_find_map_source(struct master_mapent *,
-			 const char *, const char *, int, const char **);
-
-static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-void master_mutex_lock(void)
-{
-	int status = pthread_mutex_lock(&master_mutex);
-	if (status)
-		fatal(status);
-}
-
-void master_mutex_unlock(void)
-{
-	int status = pthread_mutex_unlock(&master_mutex);
-	if (status)
-		fatal(status);
-}
-
-void master_mutex_lock_cleanup(void *arg)
-{
-	master_mutex_unlock();
-	return;
-}
-
-int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
-			    unsigned nobind, unsigned ghost, int submount)
-{
-	struct autofs_point *ap;
-	int status;
-
-	ap = malloc(sizeof(struct autofs_point));
-	if (!ap)
-		return 0;
-
-	ap->state = ST_INIT;
-
-	ap->state_pipe[0] = -1;
-	ap->state_pipe[1] = -1;
-	ap->logpri_fifo = -1;
-
-	ap->path = strdup(entry->path);
-	if (!ap->path) {
-		free(ap);
-		return 0;
-	}
-	ap->pref = NULL;
-
-	ap->entry = entry;
-	ap->exp_thread = 0;
-	ap->readmap_thread = 0;
-	/*
-	 * 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_timeout = defaults_get_timeout();
-	ap->exp_runfreq = 0;
-	ap->flags = 0;
-
-	if (defaults_get_use_ignore_mount_option())
-		ap->flags = MOUNT_FLAG_IGNORE;
-	if (ghost)
-		ap->flags |= MOUNT_FLAG_GHOST;
-
-	if (nobind)
-		ap->flags |= MOUNT_FLAG_NOBIND;
-
-	if (ap->path[1] == '-')
-		ap->type = LKP_DIRECT;
-	else
-		ap->type = LKP_INDIRECT;
-
-	ap->logopt = logopt;
-
-	ap->parent = NULL;
-	ap->thid = 0;
-	ap->submnt_count = 0;
-	ap->submount = submount;
-	INIT_LIST_HEAD(&ap->mounts);
-	INIT_LIST_HEAD(&ap->submounts);
-	INIT_LIST_HEAD(&ap->amdmounts);
-	ap->shutdown = 0;
-
-	status = pthread_mutex_init(&ap->mounts_mutex, NULL);
-	if (status) {
-		free(ap->path);
-		free(ap);
-		return 0;
-	}
-	ap->mode = 0;
-
-	entry->ap = ap;
-
-	return 1;
-}
-
-void master_free_autofs_point(struct autofs_point *ap)
-{
-	struct list_head *p, *head;
-	int status;
-
-	if (!ap)
-		return;
-
-	mounts_mutex_lock(ap);
-	head = &ap->amdmounts;
-	p = head->next;
-	while (p != head) {
-		struct mnt_list *mnt = list_entry(p, struct mnt_list, amdmount);
-		p = p->next;
-		ext_mount_remove(mnt->ext_mp);
-		mnts_remove_amdmount(mnt->mp);
-	}
-	mounts_mutex_unlock(ap);
-
-	status = pthread_mutex_destroy(&ap->mounts_mutex);
-	if (status)
-		fatal(status);
-
-	if (ap->pref)
-		free(ap->pref);
-	free(ap->path);
-	free(ap);
-}
-
-struct map_source *
-master_add_map_source(struct master_mapent *entry,
-		      char *type, char *format, time_t age,
-		      int argc, const char **argv)
-{
-	struct map_source *source;
-	char *ntype, *nformat;
-	const char **tmpargv;
-
-	source = malloc(sizeof(struct map_source));
-	if (!source)
-		return NULL;
-	memset(source, 0, sizeof(struct map_source));
-	source->ref = 1;
-
-	if (type) {
-		ntype = strdup(type);
-		if (!ntype) {
-			master_free_map_source(source, 0);
-			return NULL;
-		}
-		source->type = ntype;
-	}
-
-	if (format) {
-		nformat = strdup(format);
-		if (!nformat) {
-			master_free_map_source(source, 0);
-			return NULL;
-		}
-		source->format = nformat;
-		if (!strcmp(nformat, "amd"))
-			source->flags |= MAP_FLAG_FORMAT_AMD;
-	}
-
-	source->age = age;
-	source->stale = 1;
-
-	tmpargv = copy_argv(argc, argv);
-	if (!tmpargv) {
-		master_free_map_source(source, 0);
-		return NULL;
-	}
-	source->argc = argc;
-	source->argv = tmpargv;
-	if (source->argv[0])
-		source->name = strdup(source->argv[0]);
-
-	master_source_writelock(entry);
-
-	if (!entry->maps) {
-		source->mc = cache_init(entry->ap, source);
-		if (!source->mc) {
-			master_free_map_source(source, 0);
-			master_source_unlock(entry);
-			return NULL;
-		}
-		entry->maps = source;
-	} else {
-		struct map_source *this, *last, *next;
-
-		/* Typically there only a few map sources */
-
-		this = __master_find_map_source(entry, type, format, argc, tmpargv);
-		if (this) {
-			debug(entry->ap->logopt,
-			      "map source used without taking reference");
-			this->age = age;
-			master_free_map_source(source, 0);
-			master_source_unlock(entry);
-			return this;
-		}
-
-		source->mc = cache_init(entry->ap, source);
-		if (!source->mc) {
-			master_free_map_source(source, 0);
-			master_source_unlock(entry);
-			return NULL;
-		}
-
-		last = NULL;
-		next = entry->maps;
-		while (next) {
-			last = next;
-			next = next->next;
-		}
-		if (last)
-			last->next = source;
-		else
-			entry->maps = source;
-	}
-
-	master_source_unlock(entry);
-
-	return source;
-}
-
-static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
-{
-	int res = 0;
-
-	if (type) {
-		if (!map->type)
-			goto done;
-
-		if (strcmp(map->type, type))
-			goto done;
-	} else if (map->type)
-		goto done;
-
-	if (format) {
-		if (!map->format)
-			goto done;
-
-		if (strcmp(map->format, format))
-			goto done;
-	} else if (map->format)
-		goto done;
-
-	res = 1;
-done:
-	return res;
-}
-
-static struct map_source *
-__master_find_map_source(struct master_mapent *entry,
-			 const char *type, const char *format,
-			 int argc, const char **argv)
-{
-	struct map_source *map;
-	struct map_source *source = NULL;
-	int res;
-
-	map = entry->maps;
-	while (map) {
-		res = compare_source_type_and_format(map, type, format);
-		if (!res)
-			goto next;
-
-		res = compare_argv(map->argc, map->argv, argc, argv);
-		if (!res)
-			goto next;
-
-		source = map;
-		break;
-next:
-		map = map->next;
-	}
-
-	return source;
-}
-
-struct map_source *master_find_map_source(struct master_mapent *entry,
-				const char *type, const char *format,
-				int argc, const char **argv)
-{
-	struct map_source *source = NULL;
-
-	master_source_readlock(entry);
-	source = __master_find_map_source(entry, type, format, argc, argv);
-	master_source_unlock(entry);
-
-	return source;
-}
-
-struct map_source *
-master_get_map_source(struct master_mapent *entry,
-		      const char *type, const char *format,
-		      int argc, const char **argv)
-{
-	struct map_source *source = NULL;
-
-	master_source_readlock(entry);
-	source = __master_find_map_source(entry, type, format, argc, argv);
-	if (source)
-		source->ref++;
-	master_source_unlock(entry);
-
-	return source;
-}
-
-static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
-{
-	/* instance map sources are not ref counted */
-	if (source->ref && --source->ref)
-		return;
-	if (source->type)
-		free(source->type);
-	if (source->format)
-		free(source->format);
-	if (source->name)
-		free(source->name);
-	if (free_cache && source->mc)
-		cache_release(source);
-	if (source->lookup) {
-		struct map_source *instance;
-
-		instance = source->instance;
-		while (instance) {
-			if (instance->lookup)
-				close_lookup(instance->lookup);
-			instance = instance->next;
-		}
-		close_lookup(source->lookup);
-	}
-	if (source->argv)
-		free_argv(source->argc, source->argv);
-	if (source->instance) {
-		struct map_source *instance, *next;
-
-		instance = source->instance;
-		while (instance) {
-			next = instance->next;
-			__master_free_map_source(instance, 0);
-			instance = next;
-		}
-	}
-
-	free(source);
-
-	return;
-}
-
-void master_free_map_source(struct map_source *source, unsigned int free_cache)
-{
-	int status;
-
-	status = pthread_mutex_lock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	__master_free_map_source(source, free_cache);
-
-	status = pthread_mutex_unlock(&instance_mutex);
-	if (status)
-		fatal(status);
-}
-
-struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
-{
-	struct map_source *map;
-	struct map_source *instance = NULL;
-	int status, res;
-
-	status = pthread_mutex_lock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	map = source->instance;
-	while (map) {
-		res = compare_source_type_and_format(map, type, format);
-		if (!res)
-			goto next;
-
-		if (!argv) {
-			instance = map;
-			break;
-		}
-
-		res = compare_argv(map->argc, map->argv, argc, argv);
-		if (!res)
-			goto next;
-
-		instance = map;
-		break;
-next:
-		map = map->next;
-	}
-
-	status = pthread_mutex_unlock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	return instance;
-}
-
-struct map_source *
-master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
-{
-	struct map_source *instance;
-	struct map_source *new;
-	char *ntype, *nformat;
-	const char **tmpargv;
-	int status;
-
-	instance = master_find_source_instance(source, type, format, argc, argv);
-	if (instance)
-		return instance;
-
-	new = malloc(sizeof(struct map_source));
-	if (!new)
-		return NULL;
-	memset(new, 0, sizeof(struct map_source));
-
-	if (type) {
-		ntype = strdup(type);
-		if (!ntype) {
-			master_free_map_source(new, 0);
-			return NULL;
-		}
-		new->type = ntype;
-	}
-
-	if (format) {
-		nformat = strdup(format);
-		if (!nformat) {
-			master_free_map_source(new, 0);
-			return NULL;
-		}
-		new->format = nformat;
-		if (!strcmp(nformat, "amd"))
-			new->flags |= MAP_FLAG_FORMAT_AMD;
-	}
-
-	new->age = age;
-	new->master_line = 0;
-	new->mc = source->mc;
-	new->exp_timeout = source->exp_timeout;
-	new->stale = 1;
-
-	tmpargv = copy_argv(argc, argv);
-	if (!tmpargv) {
-		master_free_map_source(new, 0);
-		return NULL;
-	}
-	new->argc = argc;
-	new->argv = tmpargv;
-	if (source->name)
-		new->name = strdup(source->name);
-
-	status = pthread_mutex_lock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	if (!source->instance)
-		source->instance = new;
-	else {
-		/*
-		 * We know there's no other instance of this
-		 * type so just add to head of list
-		 */
-		new->next = source->instance;
-		source->instance = new;
-	}
-
-	status = pthread_mutex_unlock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	return new;
-}
-
-int check_stale_instances(struct map_source *source)
-{
-	struct map_source *map;
-
-	if (!source)
-		return 0;
-
-	map = source->instance;
-	while (map) {
-		if (map->stale)
-			return 1;
-		if (check_stale_instances(map))
-			return 1;
-		map = map->next;
-	}
-
-	return 0;
-}
-
-void clear_stale_instances(struct map_source *source)
-{
-	struct map_source *map;
-
-	if (!source)
-		return;
-
-	map = source->instance;
-	while (map) {
-		clear_stale_instances(map);
-		if (map->stale)
-			map->stale = 0;
-		map = map->next;
-	}
-
-	return;
-}
-
-void send_map_update_request(struct autofs_point *ap)
-{
-	struct map_source *map;
-	int status, need_update = 0;
-
-	status = pthread_mutex_lock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	map = ap->entry->maps;
-	while (map) {
-		if (check_stale_instances(map))
-			map->stale = 1;
-		if (map->stale) {
-			need_update = 1;
-			break;
-		}
-		map = map->next;
-	}
-
-	status = pthread_mutex_unlock(&instance_mutex);
-	if (status)
-		fatal(status);
-
-	if (!need_update)
-		return;
-
-	st_add_task(ap, ST_READMAP);
-
-	return;
-}
-
-void master_source_writelock(struct master_mapent *entry)
-{
-	int status;
-
-	status = pthread_rwlock_wrlock(&entry->source_lock);
-	if (status) {
-		logmsg("master_mapent source write lock failed");
-		fatal(status);
-	}
-	return;
-}
-
-void master_source_readlock(struct master_mapent *entry)
-{
-	int retries = 25;
-	int status;
-
-	while (retries--) {
-		status = pthread_rwlock_rdlock(&entry->source_lock);
-		if (status != EAGAIN && status != EBUSY)
-			break;
-		else {
-                	struct timespec t = { 0, 200000000 };
-	                struct timespec r;
-
-			if (status == EAGAIN)
-				logmsg("master_mapent source too many readers");
-			else
-				logmsg("master_mapent source write lock held");
-
-                	while (nanosleep(&t, &r) == -1 && errno == EINTR)
-                        	memcpy(&t, &r, sizeof(struct timespec));
-		}
-	}
-
-	if (status) {
-		logmsg("master_mapent source read lock failed");
-		fatal(status);
-	}
-
-	return;
-}
-
-void master_source_unlock(struct master_mapent *entry)
-{
-	int status;
-
-	status = pthread_rwlock_unlock(&entry->source_lock);
-	if (status) {
-		logmsg("master_mapent source unlock failed");
-		fatal(status);
-	}
-	return;
-}
-
-void master_source_lock_cleanup(void *arg)
-{
-	struct master_mapent *entry = (struct master_mapent *) arg;
-
-	master_source_unlock(entry);
-
-	return;
-}
-
-void master_source_current_wait(struct master_mapent *entry)
-{
-	int status;
-
-	status = pthread_mutex_lock(&entry->current_mutex);
-	if (status) {
-		logmsg("entry current source lock failed");
-		fatal(status);
-	}
-
-	while (entry->current != NULL) {
-		status = pthread_cond_wait(
-				&entry->current_cond, &entry->current_mutex);
-		if (status) {
-			logmsg("entry current source condition wait failed");
-			fatal(status);
-		}
-	}
-
-	return;
-}
-
-void master_source_current_signal(struct master_mapent *entry)
-{
-	int status;
-
-	status = pthread_cond_signal(&entry->current_cond);
-	if (status) {
-		logmsg("entry current source condition signal failed");
-		fatal(status);
-	}
-
-	status = pthread_mutex_unlock(&entry->current_mutex);
-	if (status) {
-		logmsg("entry current source unlock failed");
-		fatal(status);
-	}
-
-	return;
-}
-
-struct master_mapent *master_find_mapent(struct master *master, const char *path)
-{
-	struct list_head *head, *p;
-
-	head = &master->mounts;
-	list_for_each(p, head) {
-		struct master_mapent *entry;
-
-		entry = list_entry(p, struct master_mapent, list);
-
-		if (!strcmp(entry->path, path))
-			return entry;
-	}
-
-	return NULL;
-}
-
-unsigned int master_partial_match_mapent(struct master *master, const char *path)
-{
-	struct list_head *head, *p;
-	size_t path_len = strlen(path);
-	int ret = 0;
-
-	head = &master->mounts;
-	list_for_each(p, head) {
-		struct master_mapent *entry;
-		size_t entry_len;
-		size_t cmp_len;
-
-		entry = list_entry(p, struct master_mapent, list);
-
-		entry_len = strlen(entry->path);
-		cmp_len = min(entry_len, path_len);
-
-		if (!strncmp(entry->path, path, cmp_len)) {
-			/* paths are equal, matching master map entry ? */
-			if (entry_len == path_len) {
-				if (entry->maps &&
-				    entry->maps->flags & MAP_FLAG_FORMAT_AMD)
-					ret = 1;
-				else
-					ret = -1;
-				break;
-			}
-
-			/* amd mount conflicts with entry mount */
-			if (entry_len > path_len &&
-			    *(entry->path + path_len) == '/') {
-				ret = -1;
-				break;
-			}
-
-			/* entry mount conflicts with amd mount */
-			if (entry_len < path_len &&
-			    *(path + entry_len) == '/') {
-				ret = -1;
-				break;
-			}
-		}
-	}
-
-	return ret;
-}
-
-struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
-{
-	struct master_mapent *entry;
-	int status;
-	char *tmp;
-
-	entry = malloc(sizeof(struct master_mapent));
-	if (!entry)
-		return NULL;
-
-	memset(entry, 0, sizeof(struct master_mapent));
-
-	tmp = strdup(path);
-	if (!tmp) {
-		free(entry);
-		return NULL;
-	}
-	entry->path = tmp;
-
-	entry->thid = 0;
-	entry->age = age;
-	entry->master = master;
-	entry->current = NULL;
-	entry->maps = NULL;
-	entry->ap = NULL;
-
-	status = pthread_rwlock_init(&entry->source_lock, NULL);
-	if (status)
-		fatal(status);
-
-	status = pthread_mutex_init(&entry->current_mutex, NULL);
-	if (status)
-		fatal(status);
-
-	status = pthread_cond_init(&entry->current_cond, NULL);
-	if (status)
-		fatal(status);
-
-	INIT_LIST_HEAD(&entry->list);
-
-	return entry;
-}
-
-void master_add_mapent(struct master *master, struct master_mapent *entry)
-{
-	list_add_tail(&entry->list, &master->mounts);
-	return;
-}
-
-void master_remove_mapent(struct master_mapent *entry)
-{
-	struct master *master = entry->master;
-
-	if (entry->ap->submount)
-		return;
-
-	if (!list_empty(&entry->list)) {
-		list_del_init(&entry->list);
-		list_add(&entry->join, &master->completed);
-	}
-
-	return;
-}
-
-void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
-{
-	if (entry->maps) {
-		struct map_source *m, *n;
-
-		m = entry->maps;
-		while (m) {
-			n = m->next;
-			master_free_map_source(m, free_cache);
-			m = n;
-		}
-		entry->maps = NULL;
-	}
-
-	return;
-}
-
-void master_free_mapent(struct master_mapent *entry)
-{
-	int status;
-
-	if (entry->path)
-		free(entry->path);
-
-	master_free_autofs_point(entry->ap);
-
-	status = pthread_rwlock_destroy(&entry->source_lock);
-	if (status)
-		fatal(status);
-
-	status = pthread_mutex_destroy(&entry->current_mutex);
-	if (status)
-		fatal(status);
-
-	status = pthread_cond_destroy(&entry->current_cond);
-	if (status)
-		fatal(status);
-
-	free(entry);
-
-	return;
-}
-
-struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
-{
-	struct master *master;
-	char *tmp;
-
-	master = malloc(sizeof(struct master));
-	if (!master)
-		return NULL;
-
-	if (!name)
-		tmp = (char *) defaults_get_master_map();
-	else
-		tmp = strdup(name);
-
-	if (!tmp) {
-		free(master);
-		return NULL;
-	}
-
-	master->name = tmp;
-	master->nc = NULL;
-
-	master->recurse = 0;
-	master->depth = 0;
-	master->reading = 0;
-	master->read_fail = 0;
-	master->readall = 0;
-	master->default_ghost = flags & DAEMON_FLAGS_GHOST;
-	master->default_timeout = timeout;
-	master->default_logging = defaults_get_logging();
-	master->logopt = master->default_logging;
-
-	INIT_LIST_HEAD(&master->mounts);
-	INIT_LIST_HEAD(&master->completed);
-
-	return master;
-}
-
-static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
-{
-	unsigned int m_logopt = master->logopt;
-	struct master_mapent *entry;
-	struct map_source *source;
-	unsigned int loglevel;
-	unsigned int logopt;
-	unsigned int flags;
-	char *argv[2];
-	char **paths;
-	int ret;
-	int i;
-
-	loglevel = conf_amd_get_log_options();
-
-	paths = conf_amd_get_mount_paths();
-	if (!paths)
-		return;
-
-	i = 0;
-	while (paths[i]) {
-		const char *path = paths[i];
-		unsigned int ghost = 0;
-		time_t timeout;
-		char *type = NULL;
-		char *map = NULL;
-		char *opts;
-
-		ret = master_partial_match_mapent(master, path);
-		if (ret) {
-			/* If this amd entry is already present in the
-			 * master map it's not a duplicate, don't issue
-			 * an error message.
-			 */
-			if (ret == 1)
-				goto next;
-			info(m_logopt,
-			     "amd section mount path conflict, %s ignored",
-			     path);
-			goto next;
-		}
-
-		map = conf_amd_get_map_name(path);
-		if (!map) {
-			error(m_logopt,
-			      "failed to get map name for amd section mount %s",
-			      path);
-			goto next;
-		}
-
-		entry = master_new_mapent(master, path, age);
-		if (!entry) {
-			error(m_logopt,
-			      "failed to allocate new amd section mount %s",
-			      path);
-			goto next;
-		}
-
-		logopt = m_logopt;
-		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
-			logopt = LOGOPT_DEBUG;
-		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
-			logopt = LOGOPT_VERBOSE;
-
-		/* It isn't possible to provide the fullybrowsable amd
-		 * browsing functionality within the autofs framework.
-		 * This flag will not be set if browsable_dirs = full
-		 * in the configuration or fullybrowsable is present as
-		 * an option.
-		 */
-		flags = conf_amd_get_flags(path);
-		if (flags & CONF_BROWSABLE_DIRS)
-			ghost = 1;
-
-		ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
-		if (!ret) {
-			error(m_logopt, "failed to add autofs_point");
-			master_free_mapent(entry);
-			goto next;
-		}
-
-		opts = conf_amd_get_map_options(path);
-		if (opts) {
-			/* autofs uses the equivalent of cache:=inc,sync
-			 * (except for file maps which use cache:=all,sync)
-			 * but if the map is large then it may be necessary
-			 * to read the whole map at startup even if browsing
-			 * is is not enabled, so look for cache:=all in the
-			 * map_options configuration entry.
-			 */
-			if (strstr(opts, "cache:=all"))
-				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
-			free(opts);
-		}
-
-		type = conf_amd_get_map_type(path);
-		argv[0] = map;
-		argv[1] = NULL;
-
-		source = master_add_map_source(entry, type, "amd",
-					       age, 1, (const char **) argv);
-		if (!source) {
-			error(m_logopt,
-			      "failed to add source for amd section mount %s",
-			      path);
-			master_free_mapent(entry);
-			goto next;
-		}
-
-		timeout = conf_amd_get_dismount_interval(path);
-		set_exp_timeout(entry->ap, source, timeout);
-		source->master_line = 0;
-
-		entry->age = age;
-		entry->current = NULL;
-
-		master_add_mapent(master, entry);
-next:
-		if (type)
-			free(type);
-		if (map)
-			free(map);
-		i++;
-	}
-
-	i = 0;
-	while (paths[i])
-		free(paths[i++]);
-	free(paths);
-}
-
-static void wait_for_lookups_and_lock(struct master *master)
-{
-	struct list_head *p, *head;
-	int status;
-
-again:
-	master_mutex_lock();
-
-	head = &master->mounts;
-	p = head->next;
-	while (p != head) {
-		struct master_mapent *this;
-
-		this = list_entry(p, struct master_mapent, list);
-
-		status = pthread_rwlock_trywrlock(&this->source_lock);
-		if (status) {
-			struct timespec t = { 0, 200000000 };
-			struct timespec r;
-
-			master_mutex_unlock();
-
-			while (nanosleep(&t, &r) == -1 && errno == EINTR)
-				memcpy(&t, &r, sizeof(struct timespec));
-
-			goto again;
-		}
-		master_source_unlock(this);
-
-		p = p->next;
-	}
-}
-
-int master_read_master(struct master *master, time_t age)
-{
-	unsigned int logopt = master->logopt;
-	struct mapent_cache *nc;
-
-	/*
-	 * We need to clear and re-populate the null map entry cache
-	 * before alowing anyone else to use it.
-	 */
-	wait_for_lookups_and_lock(master);
-	if (master->nc) {
-		cache_writelock(master->nc);
-		nc = master->nc;
-		cache_clean_null_cache(nc);
-	} else {
-		nc = cache_init_null_cache(master);
-		if (!nc) {
-			error(logopt,
-			      "failed to init null map cache for %s",
-			      master->name);
-			return 0;
-		}
-		cache_writelock(nc);
-		master->nc = nc;
-	}
-	master_init_scan();
-	lookup_nss_read_master(master, age);
-	cache_unlock(nc);
-	master_add_amd_mount_section_mounts(master, age);
-
-	if (!master->read_fail)
-		master_mount_mounts(master, age);
-	else {
-		master->read_fail = 0;
-		/* HUP signal sets master->readall == 1 only */
-		if (!master->readall) {
-			master_mutex_unlock();
-			return 0;
-		} else
-			master_mount_mounts(master, age);
-	}
-
-	if (list_empty(&master->mounts))
-		warn(logopt, "no mounts in table");
-
-	master_mutex_unlock();
-
-	return 1;
-}
-
-int master_submount_list_empty(struct autofs_point *ap)
-{
-	int res = 0;
-
-	mounts_mutex_lock(ap);
-	if (list_empty(&ap->submounts))
-		res = 1;
-	mounts_mutex_unlock(ap);
-
-	return res;
-}
-
-int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
-{
-	struct mnt_list *this, *sbmnt;
-	int ret = 1;
-
-	this = mnts_find_submount(path);
-	if (this) {
-		/* We have found a submount to expire */
-		st_mutex_lock();
-
-		if (this->ap->state == ST_SHUTDOWN) {
-			this = NULL;
-			st_mutex_unlock();
-			goto done;
-		}
-
-		this->ap->shutdown = ap->shutdown;
-
-		__st_add_task(this->ap, state);
-
-		st_mutex_unlock();
-
-		st_wait_task(this->ap, state, 0);
-
-		/*
-		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
-		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
-		 * to ST_READY.
-		 */
-		st_mutex_lock();
-		while ((sbmnt = mnts_find_submount(path))) {
-			struct timespec t = { 0, 300000000 };
-			struct timespec r;
-
-			if (sbmnt->ap->state != ST_SHUTDOWN &&
-			    sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
-			    sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
-				ret = 0;
-				mnts_put_mount(sbmnt);
-				break;
-			}
-			mnts_put_mount(sbmnt);
-
-			st_mutex_unlock();
-			while (nanosleep(&t, &r) == -1 && errno == EINTR)
-				memcpy(&t, &r, sizeof(struct timespec));
-			st_mutex_lock();
-		}
-		st_mutex_unlock();
-done:
-		mnts_put_mount(this);
-	}
-
-	return ret;
-}
-
-void master_notify_state_change(struct master *master, int sig)
-{
-	struct master_mapent *entry;
-	struct autofs_point *ap;
-	struct list_head *p;
-	int cur_state;
-	unsigned int logopt;
-
-	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-	master_mutex_lock();
-
-	list_for_each(p, &master->mounts) {
-		enum states next = ST_INVAL;
-
-		entry = list_entry(p, struct master_mapent, list);
-
-		ap = entry->ap;
-		logopt = ap->logopt;
-
-		st_mutex_lock();
-
-		if (ap->state == ST_SHUTDOWN)
-			goto next;
-
-		switch (sig) {
-		case SIGTERM:
-		case SIGINT:
-			if (ap->state != ST_SHUTDOWN_PENDING &&
-			    ap->state != ST_SHUTDOWN_FORCE) {
-				next = ST_SHUTDOWN_PENDING;
-				ap->shutdown = 1;
-				__st_add_task(ap, next);
-			}
-			break;
-#ifdef ENABLE_FORCED_SHUTDOWN
-		case SIGUSR2:
-			if (ap->state != ST_SHUTDOWN_FORCE &&
-			    ap->state != ST_SHUTDOWN_PENDING) {
-				next = ST_SHUTDOWN_FORCE;
-				ap->shutdown = 1;
-				__st_add_task(ap, next);
-			}
-			break;
-#endif
-		case SIGUSR1:
-			assert(ap->state == ST_READY);
-			next = ST_PRUNE;
-			__st_add_task(ap, next);
-			break;
-		}
-next:
-		if (next != ST_INVAL)
-			debug(logopt,
-			      "sig %d switching %s from %d to %d",
-			      sig, ap->path, ap->state, next);
-
-		st_mutex_unlock();
-	}
-
-	master_mutex_unlock();
-	pthread_setcancelstate(cur_state, NULL);
-
-	return;
-}
-
-static int master_do_mount(struct master_mapent *entry)
-{
-	struct startup_cond suc;
-	struct autofs_point *ap;
-	pthread_t thid;
-	int status;
-
-	ap = entry->ap;
-
-	if (handle_mounts_startup_cond_init(&suc)) {
-		crit(ap->logopt,
-		     "failed to init startup cond for mount %s", entry->path);
-		return 0;
-	}
-
-	suc.ap = ap;
-	suc.root = ap->path;
-	suc.done = 0;
-	suc.status = 0;
-
-	if (!(do_force_unlink & UNLINK_AND_EXIT))
-		debug(ap->logopt, "mounting %s", entry->path);
-
-	status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
-	if (status) {
-		crit(ap->logopt,
-		     "failed to create mount handler thread for %s",
-		     entry->path);
-		handle_mounts_startup_cond_destroy(&suc);
-		return 0;
-	}
-
-	while (!suc.done) {
-		status = pthread_cond_wait(&suc.cond, &suc.mutex);
-		if (status)
-			fatal(status);
-	}
-
-	if (suc.status) {
-		if (!(do_force_unlink & UNLINK_AND_EXIT))
-			error(ap->logopt, "failed to startup mount");
-		handle_mounts_startup_cond_destroy(&suc);
-		return 0;
-	}
-	entry->thid = thid;
-
-	handle_mounts_startup_cond_destroy(&suc);
-
-	return 1;
-}
-
-static void check_update_map_sources(struct master_mapent *entry, int readall)
-{
-	struct map_source *source, *last;
-	struct autofs_point *ap;
-	int map_stale = 0;
-
-	if (readall)
-		map_stale = 1;
-
-	ap = entry->ap;
-
-	master_source_writelock(entry);
-
-	last = NULL;
-	source = entry->maps;
-	while (source) {
-		if (readall)
-			source->stale = 1;
-
-		/*
-		 * If a map source is no longer valid and all it's
-		 * entries have expired away we can get rid of it.
-		 */
-		if (entry->age > source->age) {
-			struct mapent *me;
-			cache_readlock(source->mc);
-			me = cache_lookup_first(source->mc);
-			if (!me) {
-				struct map_source *next = source->next;
-
-				cache_unlock(source->mc);
-
-				if (!last)
-					entry->maps = next;
-				else
-					last->next = next;
-
-				if (entry->maps == source)
-					entry->maps = next;
-
-				master_free_map_source(source, 1);
-
-				source = next;
-				continue;
-			} else {
-				source->stale = 1;
-				map_stale = 1;
-			}
-			cache_unlock(source->mc);
-		}
-		last = source;
-		source = source->next;
-	}
-
-	master_source_unlock(entry);
-
-	/* The map sources have changed */
-	if (map_stale)
-		st_add_task(ap, ST_READMAP);
-
-	return;
-}
-
-int master_mount_mounts(struct master *master, time_t age)
-{
-	struct mapent_cache *nc = master->nc;
-	struct list_head *p, *head;
-	int cur_state;
-
-	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
-
-	head = &master->mounts;
-	p = head->next;
-	while (p != head) {
-		struct master_mapent *this;
-		struct autofs_point *ap;
-		struct mapent *ne, *nested;
-		struct stat st;
-		int state_pipe, save_errno;
-		int ret;
-
-		this = list_entry(p, struct master_mapent, list);
-		p = p->next;
-
-		ap = this->ap;
-
-		/* A master map entry has gone away */
-		if (this->age < age) {
-			st_add_task(ap, ST_SHUTDOWN_PENDING);
-			continue;
-		}
-
-		cache_readlock(nc);
-		ne = cache_lookup_distinct(nc, this->path);
-		/*
-		 * If this path matched a nulled entry the master map entry
-		 * must be an indirect mount so the master map entry line
-		 * number may be obtained from this->maps.
-		 */
-		if (ne) {
-			int lineno = ne->age;
-			cache_unlock(nc);
-
-			/* null entry appears after map entry */
-			if (this->maps->master_line < lineno) {
-				warn(ap->logopt,
-				     "ignoring null entry that appears after "
-				     "existing entry for %s", this->path);
-				goto cont;
-			}
-			if (ap->state != ST_INIT) {
-				st_add_task(ap, ST_SHUTDOWN_PENDING);
-				continue;
-			}
-			/*
-			 * The map entry hasn't been started yet and we've
-			 * seen a preceeding null map entry for it so just
-			 * delete it from the master map entry list so it
-			 * doesn't get in the road.
-			 */
-			list_del_init(&this->list);
-			master_free_mapent_sources(ap->entry, 1);
-			master_free_mapent(ap->entry);
-			continue;
-		}
-		nested = cache_partial_match(nc, this->path);
-		if (nested) {
-			error(ap->logopt,
-			     "removing invalid nested null entry %s",
-			     nested->key);
-			nested = cache_partial_match(nc, this->path);
-			if (nested)
-				cache_delete(nc, nested->key);
-		}
-		cache_unlock(nc);
-cont:
-		st_mutex_lock();
-
-		state_pipe = this->ap->state_pipe[1];
-
-		/* No pipe so mount is needed */
-		ret = fstat(state_pipe, &st);
-		save_errno = errno;
-
-		st_mutex_unlock();
-
-		if (!ret)
-			check_update_map_sources(this, master->readall);
-		else if (ret == -1 && save_errno == EBADF) {
-			if (!master_do_mount(this)) {
-				list_del_init(&this->list);
-				master_free_mapent_sources(ap->entry, 1);
-				master_free_mapent(ap->entry);
-			}
-		}
-	}
-
-	pthread_setcancelstate(cur_state, NULL);
-
-	return 1;
-}
-
-/* The nss source instances end up in reverse order. */
-static void list_source_instances(struct map_source *source, struct map_source *instance)
-{
-	if (!source || !instance) {
-		printf("none");
-		return;
-	}
-
-	if (instance->next)
-		list_source_instances(source, instance->next);
-
-	/*
-	 * For convienience we map nss instance type "files" to "file".
-	 * Check for that and report corrected instance type.
-	 */
-	if (strcmp(instance->type, "file"))
-		printf("%s ", instance->type);
-	else {
-		if (source->argv && *(source->argv[0]) != '/')
-			printf("files ");
-		else
-			printf("%s ", instance->type);
-	}
-
-	return;
-}
-
-static void print_map_info(struct map_source *source)
-{
-	int argc = source->argc;
-	int i, multi, map_num;
-
-	multi = (source->type && !strcmp(source->type, "multi"));
-	map_num = 1;
-	for (i = 0; i < argc; i++) {
-		if (source->argv[i] && *source->argv[i] != '-') {
-			if (!multi)
-				printf("  map: %s\n", source->argv[i]);
-			else
-				printf("  map[%i]: %s\n", map_num, source->argv[i]);
-			i++;
-		}
-
-		if (i >= argc)
-			return;
-
-		if (!strcmp(source->argv[i], "--"))
-			continue;
-
-		if (source->argv[i]) {
-			int need_newline = 0;
-			int j;
-
-			if (!multi)
-				printf("  arguments:");
-			else
-				printf("  arguments[%i]:", map_num);
-
-			for (j = i; j < source->argc; j++) {
-				if (!strcmp(source->argv[j], "--"))
-					break;
-				printf(" %s", source->argv[j]);
-				i++;
-				need_newline = 1;
-			}
-			if (need_newline)
-				printf("\n");
-		}
-		if (multi)
-			map_num++;
-	}
-
-	return;
-}
-
-static int match_type(const char *source, const char *type)
-{
-	if (!strcmp(source, type))
-		return 1;
-	/* Sources file and files are synonymous */
-	if (!strncmp(source, type, 4) && (strlen(source) <= 5))
-		return 1;
-	return 0;
-}
-
-static char *get_map_name(const char *string)
-{
-	char *name, *tmp;
-	char *start, *end, *base;
-
-	tmp = strdup(string);
-	if (!tmp) {
-		printf("error: allocation failure: %s\n", strerror(errno));
-		return NULL;
-	}
-
-	base = basename(tmp);
-	end = strchr(base, ',');
-	if (end)
-		*end = '\0';
-	start = strchr(tmp, '=');
-	if (start)
-		start++;
-	else {
-		char *colon = strrchr(base, ':');
-		if (colon)
-			start = ++colon;
-		else
-			start = base;
-	}
-
-	name = strdup(start);
-	if (!name)
-		printf("error: allocation failure: %s\n", strerror(errno));
-	free(tmp);
-
-	return name;
-}
-
-static int match_name(struct map_source *source, const char *name)
-{
-	int argc = source->argc;
-	int ret = 0;
-	int i;
-
-	/*
-	 * This can't work for old style "multi" type sources since
-	 * there's no way to know from which map the cache entry came
-	 * from and duplicate entries are ignored at map read time.
-	 * All we can really do is list all the entries for the given
-	 * multi map if one of its map names matches.
-	 */
-	for (i = 0; i < argc; i++) {
-		if (i == 0 || !strcmp(source->argv[i], "--")) {
-			if (i != 0) {
-				i++;
-				if (i >= argc)
-					break;
-			}
-
-			if (source->argv[i] && *source->argv[i] != '-') {
-				char *map = get_map_name(source->argv[i]);
-				if (!map)
-					break;
-				if (!strcmp(map, name)) {
-					ret = 1;
-					free(map);
-					break;
-				}
-				free(map);
-			}
-		}
-	}
-
-	return ret;
-}
-
-int dump_map(struct master *master, const char *type, const char *name)
-{
-	struct list_head *p, *head;
-
-	if (list_empty(&master->mounts)) {
-		printf("no master map entries found\n");
-		return 1;
-	}
-
-	head = &master->mounts;
-	p = head->next;
-	while (p != head) {
-		struct map_source *source;
-		struct master_mapent *this;
-		struct autofs_point *ap;
-		time_t now = monotonic_time(NULL);
-
-		this = list_entry(p, struct master_mapent, list);
-		p = p->next;
-
-		ap = this->ap;
-
-		/*
-		 * Ensure we actually read indirect map entries so we can
-		 * list them. The map reads won't read any indirect map
-		 * entries (other than those in a file map) unless the
-		 * browse option is set.
-		 */
-		if (ap->type == LKP_INDIRECT)
-			ap->flags |= MOUNT_FLAG_GHOST;
-
-		/* Read the map content into the cache */
-		if (lookup_nss_read_map(ap, NULL, now))
-			lookup_prune_cache(ap, now);
-		else {
-			printf("failed to read map\n");
-			lookup_close_lookup(ap);
-			continue;
-		}
-
-		if (!this->maps) {
-			printf("no map sources found for %s\n", ap->path);
-			lookup_close_lookup(ap);
-			continue;
-		}
-
-		source = this->maps;
-		while (source) {
-			struct map_source *instance;
-			struct mapent *me;
-
-			instance = NULL;
-			if (source->type) {
-				if (!match_type(source->type, type)) {
-					source = source->next;
-					continue;
-				}
-				if (!match_name(source, name)) {
-					source = source->next;
-					continue;
-				}
-				instance = source;
-			} else {
-				struct map_source *map;
-
-				map = source->instance;
-				while (map) {
-					if (!match_type(map->type, type)) {
-						map = map->next;
-						continue;
-					}
-					if (!match_name(map, name)) {
-						map = map->next;
-						continue;
-					}
-					instance = map;
-					break;
-				}
-			}
-
-			if (!instance) {
-				source = source->next;
-				lookup_close_lookup(ap);
-				continue;
-			}
-
-			me = cache_lookup_first(source->mc);
-			if (!me)
-				printf("no keys found in map\n");
-			else {
-				do {
-					if (me->source == instance)
-						printf("%s\t%s\n", me->key, me->mapent);
-				} while ((me = cache_lookup_next(source->mc, me)));
-			}
-
-			lookup_close_lookup(ap);
-			return 1;
-		}
-		lookup_close_lookup(ap);
-	}
-
-	return 0;
-}
-
-int master_show_mounts(struct master *master)
-{
-	struct list_head *p, *head;
-
-	printf("\nautofs dump map information\n"
-		 "===========================\n\n");
-
-	printf("global options: ");
-	if (!global_options)
-		printf("none configured\n");
-	else {
-		printf("%s\n", global_options);
-		unsigned int append_options = defaults_get_append_options();
-		const char *append = append_options ? "will" : "will not";
-		printf("global options %s be appended to map entries\n", append);
-	}
-
-	if (list_empty(&master->mounts)) {
-		printf("no master map entries found\n\n");
-		return 1;
-	}
-
-	head = &master->mounts;
-	p = head->next;
-	while (p != head) {
-		struct map_source *source;
-		struct master_mapent *this;
-		struct autofs_point *ap;
-		time_t now = monotonic_time(NULL);
-		unsigned int count = 0;
-
-		this = list_entry(p, struct master_mapent, list);
-		p = p->next;
-
-		ap = this->ap;
-
-		printf("\nMount point: %s\n", ap->path);
-
-		printf("\nsource(s):\n");
-
-		/*
-		 * Ensure we actually read indirect map entries so we can
-		 * list them. The map reads won't read any indirect map
-		 * entries (other than those in a file map) unless the
-		 * browse option is set.
-		 */
-		if (ap->type == LKP_INDIRECT)
-			ap->flags |= MOUNT_FLAG_GHOST;
-
-		/* Read the map content into the cache */
-		if (lookup_nss_read_map(ap, NULL, now))
-			lookup_prune_cache(ap, now);
-		else {
-			printf("  failed to read map\n\n");
-			continue;
-		}
-
-		if (!this->maps) {
-			printf("  no map sources found\n\n");
-			continue;
-		}
-
-		source = this->maps;
-		while (source) {
-			struct mapent *me;
-
-			if (source->type)
-				printf("\n  type: %s\n", source->type);
-			else {
-				printf("\n  instance type(s): ");
-				list_source_instances(source, source->instance);
-				printf("\n");
-			}
-
-			if (source->argc >= 1) {
-				print_map_info(source);
-				if (count && ap->type == LKP_INDIRECT)
-					printf("  duplicate indirect map entry"
-					       " will be ignored at run time\n");
-			}
-
-			printf("\n");
-
-			me = cache_lookup_first(source->mc);
-			if (!me)
-				printf("  no keys found in map\n");
-			else {
-				do {
-					printf("  %s | %s\n", me->key, me->mapent);
-				} while ((me = cache_lookup_next(source->mc, me)));
-			}
-
-			count++;
-
-			source = source->next;
-		}
-
-		lookup_close_lookup(ap);
-
-		printf("\n");
-	}
-
-	return 1;
-}
-
-int master_list_empty(struct master *master)
-{
-	int res = 0;
-
-	master_mutex_lock();
-	if (list_empty(&master->mounts))
-		res = 1;
-	master_mutex_unlock();
-
-	return res;
-}
-
-int master_done(struct master *master)
-{
-	struct list_head *head, *p;
-	struct master_mapent *entry;
-	int res = 0;
-
-	head = &master->completed;
-	p = head->next;
-	while (p != head) {
-		entry = list_entry(p, struct master_mapent, join);
-		p = p->next;
-		list_del(&entry->join);
-		pthread_join(entry->thid, NULL);
-		master_free_mapent_sources(entry, 1);
-		master_free_mapent(entry);
-	}
-	if (list_empty(&master->mounts))
-		res = 1;
-
-	return res;
-}
-
-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))
-		return 0;
-
-	if (master->name)
-		free(master->name);
-
-	cache_release_null_cache(master);
-	free(master);
-
-	return 1;
-}
--- autofs-5.1.4.orig/lib/master_parse.y
+++ /dev/null
@@ -1,983 +0,0 @@
-%{
-/* ----------------------------------------------------------------------- *
- *   
- *  master_parser.y - master map buffer parser.
- *
- *   Copyright 2006 Ian Kent <raven@themaw.net>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- *   USA; either version 2 of the License, or (at your option) any later
- *   version.
- *   
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- * ----------------------------------------------------------------------- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-
-#include "automount.h"
-#include "master.h"
-
-#define MAX_ERR_LEN	512
-
-extern struct master *master_list;
-
-char **add_argv(int, char **, char *);
-const char **copy_argv(int, const char **);
-int free_argv(int, const char **);
-
-extern FILE *master_in;
-extern char *master_text;
-extern int master_lex(void);
-extern int master_lineno;
-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);
-static int master_notify(const char *s);
-static int master_msg(const char *s);
- 
-static char *path;
-static char *type;
-static char *format;
-static long timeout;
-static long negative_timeout;
-static unsigned symlnk;
-static unsigned strictexpire;
-static unsigned nobind;
-static unsigned ghost;
-extern unsigned global_selection_options;
-static unsigned random_selection;
-static unsigned use_weight;
-static unsigned long mode;
-static char **tmp_argv;
-static int tmp_argc;
-static char **local_argv;
-static int local_argc;
-
-#define PROPAGATION_SHARED	MOUNT_FLAG_SHARED
-#define PROPAGATION_SLAVE	MOUNT_FLAG_SLAVE
-#define PROPAGATION_PRIVATE	MOUNT_FLAG_PRIVATE
-#define PROPAGATION_MASK	(MOUNT_FLAG_SHARED | \
-				 MOUNT_FLAG_SLAVE  | \
-				 MOUNT_FLAG_PRIVATE)
-static unsigned int propagation;
-
-static char errstr[MAX_ERR_LEN];
-
-static unsigned int verbose;
-static unsigned int debug;
-
-static int lineno;
-
-#define YYDEBUG 0
-
-#ifndef YYENABLE_NLS
-#define YYENABLE_NLS 0
-#endif
-#ifndef YYLTYPE_IS_TRIVIAL
-#define YYLTYPE_IS_TRIVIAL 0
-#endif
-
-#if YYDEBUG
-static int master_fprintf(FILE *, char *, ...);
-#undef YYFPRINTF
-#define YYFPRINTF master_fprintf
-#endif
-
-%}
-
-%union {
-	char strtype[2048];
-	int inttype;
-	long longtype;
-}
-
-%token COMMENT
-%token MAP
-%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOBIND OPT_NOGHOST OPT_GHOST OPT_VERBOSE
-%token OPT_DEBUG OPT_RANDOM OPT_USE_WEIGHT OPT_SYMLINK OPT_MODE
-%token OPT_STRICTEXPIRE OPT_SHARED OPT_SLAVE OPT_PRIVATE
-%token COLON COMMA NL DDASH
-%type <strtype> map
-%type <strtype> options
-%type <strtype> dn
-%type <strtype> dnattrs
-%type <strtype> dnattr
-%type <strtype> option
-%type <strtype> daemon_option
-%type <strtype> mount_option
-%token <strtype> PATH
-%token <strtype> QUOTE
-%token <strtype> NILL
-%token <strtype> SPACE
-%token <strtype> EQUAL
-%token <strtype> MULTITYPE
-%token <strtype> MAPTYPE
-%token <strtype> DNSERVER
-%token <strtype> DNATTR
-%token <strtype> DNNAME
-%token <strtype> MAPHOSTS
-%token <strtype> MAPNULL
-%token <strtype> MAPXFN
-%token <strtype> MAPNAME
-%token <longtype> NUMBER
-%token <longtype> OCTALNUMBER
-%token <strtype> OPTION
-
-%start file
-
-%%
-
-file: {
-		master_lineno = 0;
-#if YYDEBUG != 0
-		master_debug = YYDEBUG;
-#endif
-	} line
-	;
-
-line:
-	| PATH mapspec
-	{
-		path = master_strdup($1);
-		if (!path) {
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	| PATH MULTITYPE maplist
-	{
-		char *tmp = NULL;
-
-		trim_maptype($2);
-
-		if (path)
-			free(path);
-		path = master_strdup($1);
-		if (!path) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-
-		if ((tmp = strchr($2, ',')))
-			*tmp++ = '\0';
-#ifndef WITH_HESIOD
-		/* Map type or map type parser is hesiod */
-		if (!strcmp($2, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
-			master_error("hesiod support not built in");
-			local_free_vars();
-			YYABORT;
-		}
-#endif
-		if (type)
-			free(type);
-		type = master_strdup($2);
-		if (!type) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-		if (tmp) {
-			if (format)
-				free(format);
-			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; }
-	| PATH OPT_RANDOM { master_notify($1); YYABORT; }
-	| PATH OPT_USE_WEIGHT { master_notify($1); YYABORT; }
-	| PATH OPT_DEBUG { master_notify($1); YYABORT; }
-	| PATH OPT_TIMEOUT { master_notify($1); YYABORT; }
-	| PATH OPT_SYMLINK { master_notify($1); YYABORT; }
-	| PATH OPT_STRICTEXPIRE { master_notify($1); YYABORT; }
-	| PATH OPT_SHARED { master_notify($1); YYABORT; }
-	| PATH OPT_SLAVE { master_notify($1); YYABORT; }
-	| PATH OPT_PRIVATE { master_notify($1); YYABORT; }
-	| PATH OPT_NOBIND { master_notify($1); YYABORT; }
-	| PATH OPT_GHOST { master_notify($1); YYABORT; }
-	| PATH OPT_NOGHOST { master_notify($1); YYABORT; }
-	| PATH OPT_VERBOSE { master_notify($1); YYABORT; }
-	| PATH OPT_MODE { master_notify($1); YYABORT; }
-	| PATH { master_notify($1); YYABORT; }
-	| QUOTE { master_notify($1); YYABORT; }
-	| OPTION { master_notify($1); YYABORT; }
-	| NILL { master_notify($1); YYABORT; }
-	| COMMENT { YYABORT; }
-	;
-
-mapspec: map
-	{
-		if (local_argv)
-			free_argv(local_argc, (const char **) local_argv);
-		local_argc = tmp_argc;
-		local_argv = tmp_argv;
-		tmp_argc = 0;
-		tmp_argv = NULL;
-	}
-	| map options
-	{
-		if (local_argv)
-			free_argv(local_argc, (const char **) local_argv);
-		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, "--");
-		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;
-		}
-	}
-	| maplist DDASH map options
-	{
-		local_argc++;
-		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
-	{
-		if (type)
-			free(type);
-		type = master_strdup($1 + 1);
-		if (!type) {
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	| MAPXFN
-	{
-		master_notify($1);
-		master_msg("X/Open Federated Naming service not supported");
-		YYABORT;
-	}
-	| MAPNULL
-	{
-		if (type)
-			free(type);
-		type = master_strdup($1 + 1);
-		if (!type) {
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	| dnattrs
-	{
-		if (type)
-			free(type);
-		type = master_strdup("ldap");
-		if (!type) {
-			local_free_vars();
-			YYABORT;
-		}
-		tmp_argc++;
-		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
-		if (!tmp_argv) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	| MAPTYPE PATH
-	{
-		char *tmp = NULL;
-
-		trim_maptype($1);
-
-		if ((tmp = strchr($1, ',')))
-			*tmp++ = '\0';
-#ifndef WITH_HESIOD
-		/* Map type or map type parser is hesiod */
-		if (!strcmp($1, "hesiod") || (tmp && !strcmp(tmp, "hesiod"))) {
-			master_error("hesiod support not built in");
-			local_free_vars();
-			YYABORT;
-		}
-#endif
-		if (type)
-			free(type);
-		if (strcmp($1, "exec"))
-			type = master_strdup($1);
-		else
-			type = master_strdup("program");
-		if (!type) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-		if (tmp) {
-			if (format)
-				free(format);
-			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, $2);
-		if (!tmp_argv) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	| MAPTYPE MAPNAME
-	{
-		char *tmp = NULL;
-
-		trim_maptype($1);
-
-		if ((tmp = strchr($1, ',')))
-			*tmp++ = '\0';
-
-		if (type)
-			free(type);
-		if (strcmp($1, "exec"))
-			type = master_strdup($1);
-		else
-			type = master_strdup("program");
-		if (!type) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-		if (tmp) {
-			if (format)
-				free(format);
-			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, $2);
-		if (!tmp_argv) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	| MAPTYPE dn
-	{
-		char *tmp = NULL;
-
-		trim_maptype($1);
-
-		if ((tmp = strchr($1, ',')))
-			*tmp++ = '\0';
-
-		if (type)
-			free(type);
-		if (strcmp($1, "exec"))
-			type = master_strdup($1);
-		else
-			type = master_strdup("program");
-		if (!type) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-		if (tmp) {
-			if (format)
-				free(format);
-			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, $2);
-		if (!tmp_argv) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-		/* Add back the type for lookup_ldap.c to handle ldaps */
-		if (*tmp_argv[0]) {
-			tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
-			if (!tmp) {
-				master_error("memory allocation error");
-				local_free_vars();
-				YYABORT;
-			}
-			strcpy(tmp, type);
-			strcat(tmp, ":");
-			strcat(tmp, tmp_argv[0]);
-			free(tmp_argv[0]);
-			tmp_argv[0] = tmp;
-		}
-	}
-	;
-
-dn:	DNSERVER dnattrs
-	{
-		strcpy($$, $1);
-		strcat($$, $2);
-	}
-	| dnattrs
-	{
-		strcpy($$, $1);
-	}
-	|
-	{
-		master_notify("syntax error in dn");
-		YYABORT;
-	}
-	;
-
-dnattrs: DNATTR EQUAL DNNAME
-	{
-		if (strcasecmp($1, "cn") &&
-		    strcasecmp($1, "ou") &&
-		    strcasecmp($1, "automountMapName") &&
-		    strcasecmp($1, "nisMapName")) {
-			strcpy(errstr, $1);
-			strcat(errstr, "=");
-			strcat(errstr, $3);
-			master_notify(errstr);
-			YYABORT;
-		}
-		strcpy($$, $1);
-		strcat($$, "=");
-		strcat($$, $3);
-	}
-	| DNATTR EQUAL DNNAME COMMA dnattr
-	{
-		if (strcasecmp($1, "cn") &&
-		    strcasecmp($1, "ou") &&
-		    strcasecmp($1, "automountMapName") &&
-		    strcasecmp($1, "nisMapName")) {
-			strcpy(errstr, $1);
-			strcat(errstr, "=");
-			strcat(errstr, $3);
-			master_notify(errstr);
-			YYABORT;
-		}
-		strcpy($$, $1);
-		strcat($$, "=");
-		strcat($$, $3);
-		strcat($$, ",");
-		strcat($$, $5);
-	}
-	| DNNAME
-	{
-		/* Matches map in old style syntax ldap:server:map */
-		strcpy($$, $1);
-	}
-	| DNATTR
-	{
-		master_notify($1);
-		YYABORT;
-	}
-	;
-
-dnattr: DNATTR EQUAL DNNAME
-	{
-		if (!strcasecmp($1, "automountMapName") ||
-		    !strcasecmp($1, "nisMapName")) {
-			strcpy(errstr, $1);
-			strcat(errstr, "=");
-			strcat(errstr, $3);
-			master_notify(errstr);
-			YYABORT;
-		}
-		strcpy($$, $1);
-		strcat($$, "=");
-		strcat($$, $3);
-	}
-	| DNATTR EQUAL DNNAME COMMA dnattr
-	{
-		if (!strcasecmp($1, "automountMapName") ||
-		    !strcasecmp($1, "nisMapName")) {
-			strcpy(errstr, $1);
-			strcat(errstr, "=");
-			strcat(errstr, $3);
-			master_notify(errstr);
-			YYABORT;
-		}
-		strcpy($$, $1);
-		strcat($$, "=");
-		strcat($$, $3);
-		strcat($$, ",");
-		strcat($$, $5);
-	}
-	| DNATTR
-	{
-		master_notify($1);
-		YYABORT;
-	}
-	| DNNAME
-	{
-		master_notify($1);
-		YYABORT;
-	}
-	;
-
-options: option {}
-	| options COMMA option {}
-	| options option {}
-	| options COMMA COMMA option
-	{
-		master_notify($1);
-		YYABORT;
-	}
-	| options EQUAL
-	{
-		master_notify($1);
-		YYABORT;
-	}
-	;
-
-option: daemon_option
-	| mount_option {}
-	| error
-	{
-		master_notify("bogus option");
-		YYABORT;
-	}
-	;
-
-daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
-	| OPT_NTIMEOUT NUMBER { negative_timeout = $2; }
-	| OPT_SYMLINK	{ symlnk = 1; }
-	| OPT_STRICTEXPIRE { strictexpire = 1; }
-	| OPT_SHARED	{ propagation = PROPAGATION_SHARED; }
-	| OPT_SLAVE	{ propagation = PROPAGATION_SLAVE; }
-	| OPT_PRIVATE	{ propagation = PROPAGATION_PRIVATE; }
-	| OPT_NOBIND	{ nobind = 1; }
-	| OPT_NOGHOST	{ ghost = 0; }
-	| OPT_GHOST	{ ghost = 1; }
-	| OPT_VERBOSE	{ verbose = 1; }
-	| OPT_DEBUG	{ debug = 1; }
-	| OPT_RANDOM	{ random_selection = 1; }
-	| OPT_USE_WEIGHT { use_weight = 1; }
-	| OPT_MODE OCTALNUMBER { mode = $2; }
-	;
-
-mount_option: OPTION
-	{
-		tmp_argc++;
-		tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
-		if (!tmp_argv) {
-			master_error("memory allocation error");
-			local_free_vars();
-			YYABORT;
-		}
-	}
-	;
-%%
-
-#if YYDEBUG
-static int master_fprintf(FILE *f, char *msg, ...)
-{
-	va_list ap;
-	va_start(ap, msg);
-	vsyslog(LOG_DEBUG, msg, ap);
-	va_end(ap);
-	return 1;
-}
-#endif
-
-static char *master_strdup(char *str)
-{
-	char *tmp;
-
-	tmp = strdup(str);
-	if (!tmp)
-		master_error("memory allocation error");
-	return tmp;
-}
-
-static int master_error(const char *s)
-{
-	logmsg("%s while parsing map.", s);
-	return 0;
-}
-
-static int master_notify(const char *s)
-{
-	logmsg("syntax error in map near [ %s ]", s);
-	return(0);
-}
-
-static int master_msg(const char *s)
-{
-	logmsg("%s", s);
-	return 0;
-}
-
-static void local_init_vars(void)
-{
-	path = NULL;
-	type = NULL;
-	format = NULL;
-	verbose = 0;
-	debug = 0;
-	timeout = -1;
-	negative_timeout = 0;
-	symlnk = 0;
-	strictexpire = 0;
-	propagation = PROPAGATION_SLAVE;
-	nobind = 0;
-	ghost = defaults_get_browse_mode();
-	random_selection = global_selection_options & MOUNT_FLAG_RANDOM_SELECT;
-	use_weight = 0;
-	mode = 0;
-	tmp_argv = NULL;
-	tmp_argc = 0;
-	local_argv = NULL;
-	local_argc = 0;
-}
-
-static void local_free_vars(void)
-{
-	if (path)
-		free(path);
-
-	if (type)
-		free(type);
-
-	if (format)
-		free(format);
-
-	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 void trim_maptype(char *type)
-{
-	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;
-		}
-
-		local_argc++;
-		local_argv = add_argv(local_argc, local_argv, type);
-		if (!local_argv) {
-			free(type);
-			type = NULL;
-			return 0;
-		}
-
-		free(type);
-		type = NULL;
-	}
-
-	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;
-
-	return 1;
-}
-
-void master_init_scan(void)
-{
-	lineno = 0;
-}
-
-int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
-{
-	struct master *master = master_list;
-	struct mapent_cache *nc;
-	struct master_mapent *entry, *new;
-	struct map_source *source;
-	unsigned int logopt = logging;
-	unsigned int m_logopt = master->logopt;
-	size_t mp_len;
-	int ret;
-
-	local_init_vars();
-
-	lineno++;
-
-	master_set_scan_buffer(buffer);
-
-	ret = master_parse();
-	if (ret != 0) {
-		local_free_vars();
-		return 0;
-	}
-
-	mp_len = strlen(path);
-	while (mp_len && path[--mp_len] == '/')
-		path[mp_len] = 0;
-
-	nc = master->nc;
-
-	/* Add null map entries to the null map cache */
-	if (type && !strcmp(type, "null")) {
-		cache_update(nc, NULL, path, NULL, lineno);
-		local_free_vars();
-		return 1;
-	}
-
-	/* Ignore all subsequent matching nulled entries */
-	if (cache_lookup_distinct(nc, path)) {
-		local_free_vars();
-		return 1;
-	}
-
-	if (debug || verbose) {
-		logopt = (debug ? LOGOPT_DEBUG : 0);
-		logopt |= (verbose ? LOGOPT_VERBOSE : 0);
-	}
-
-	new = NULL;
-	entry = master_find_mapent(master, path);
-	if (!entry) {
-		new = master_new_mapent(master, path, age);
-		if (!new) {
-			local_free_vars();
-			return 0;
-		}
-		entry = new;
-	} else {
-		if (entry->age && entry->age == age) {
-			if (strcmp(path, "/-")) {
-				info(m_logopt,
-				    "ignoring duplicate indirect mount %s",
-				     path);
-				local_free_vars();
-				return 0;
-			}
-		}
-	}
-
-	if (!format) {
-		if (conf_amd_mount_section_exists(path))
-			format = strdup("amd");
-	}
-
-	if (format && !strcmp(format, "amd")) {
-		unsigned int loglevel = conf_amd_get_log_options();
-		unsigned int flags = conf_amd_get_flags(path);
-
-		if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
-			logopt = LOGOPT_DEBUG;
-		else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
-			logopt = LOGOPT_VERBOSE;
-
-		/* It isn't possible to provide the fullybrowsable amd
-		 * browsing functionality within the autofs framework.
-		 * This flag will not be set if browsable_dirs = full
-		 * in the configuration or fullybrowsable is present as
-		 * an option.
-		 */
-		if (flags & CONF_BROWSABLE_DIRS)
-			ghost = 1;
-	}
-
-	if (!entry->ap) {
-		ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0);
-		if (!ret) {
-			error(m_logopt, "failed to add autofs_point");
-			if (new)
-				master_free_mapent(new);
-			local_free_vars();
-			return 0;
-		}
-	}
-	entry->ap->flags &= ~(PROPAGATION_MASK);
-	entry->ap->flags |= propagation;
-
-	if (random_selection)
-		entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT;
-	if (use_weight)
-		entry->ap->flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
-	if (symlnk)
-		entry->ap->flags |= MOUNT_FLAG_SYMLINK;
-	if (strictexpire)
-		entry->ap->flags |= MOUNT_FLAG_STRICTEXPIRE;
-	if (negative_timeout)
-		entry->ap->negative_timeout = negative_timeout;
-	if (mode && mode < LONG_MAX)
-		entry->ap->mode = mode;
-
-	if (timeout < 0) {
-		/*
-		 * If no timeout is given get the timout from the
-		 * autofs point, or the first map, or the config
-		 * for amd maps.
-		 */
-		if (format && !strcmp(format, "amd"))
-			timeout = conf_amd_get_dismount_interval(path);
-		else
-			timeout = get_exp_timeout(entry->ap, entry->maps);
-	}
-
-	if (format && !strcmp(format, "amd")) {
-		char *opts = conf_amd_get_map_options(path);
-		if (opts) {
-			/* autofs uses the equivalent of cache:=inc,sync
-			 * (except for file maps which use cache:=all,sync)
-			 * but if the map is large then it may be necessary
-			 * to read the whole map at startup even if browsing
-			 * is is not enabled, so look for cache:=all in the
-			 * map_options configuration entry.
-			 */
-			if (strstr(opts, "cache:=all"))
-				entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
-			free(opts);
-		}
-	}
-
-/*
-	source = master_find_map_source(entry, type, format,
-					local_argc, (const char **) local_argv); 
-	if (!source)
-		source = master_add_map_source(entry, type, format, age, 
-					local_argc, (const char **) local_argv);
-	else
-		source->age = age;
-*/
-	source = master_add_map_source(entry, type, format, age, 
-					local_argc, (const char **) local_argv);
-	if (!source) {
-		error(m_logopt, "failed to add source");
-		if (new)
-			master_free_mapent(new);
-		local_free_vars();
-		return 0;
-	}
-	set_exp_timeout(entry->ap, source, timeout);
-	source->master_line = lineno;
-
-	entry->age = age;
-	entry->current = NULL;
-
-	if (new)
-		master_add_mapent(master, entry);
-
-	local_free_vars();
-
-	return 1;
-}
-
--- autofs-5.1.4.orig/lib/master_tok.l
+++ /dev/null
@@ -1,504 +0,0 @@
-%{
-/* ----------------------------------------------------------------------- *
- *   
- *  master_tok.l - master map tokenizer.
- *
- *   Copyright 2006 Ian Kent <raven@themaw.net>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- *   USA; either version 2 of the License, or (at your option) any later
- *   version.
- *   
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- * ----------------------------------------------------------------------- */
-
-#ifdef ECHO
-# undef ECHO
-#endif /* ECHO */
-static void master_echo(void);	/* forward definition */
-#define ECHO master_echo()
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "master_parse.tab.h"
-
-/*
- * There are some things that need to be defined only if useing GNU flex.
- * These must not be defined if using standard lex
- */
-#ifdef FLEX_SCANNER
-int master_lineno;
-#endif
-
-int master_lex(void);
-int master_wrap(void);
-
-/* no need for yywrap() */
-#define YY_SKIP_YYWRAP
-
-#ifndef YY_STACK_USED
-#define YY_STACK_USED 0
-#endif
-#ifndef YY_ALWAYS_INTERACTIVE
-#define YY_ALWAYS_INTERACTIVE 0
-#endif
-#ifndef YY_NEVER_INTERACTIVE
-#define YY_NEVER_INTERACTIVE 0
-#endif
-#ifndef YY_MAIN
-#define YY_MAIN 0
-#endif
-
-void master_set_scan_buffer(const char *);
-const char *line = NULL;
-
-#ifdef FLEX_SCANNER
-const char *line_pos = NULL;
-const char *line_lim = NULL;
-int my_yyinput(char *, int);
-
-#undef YY_INPUT
-#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
-#else
-#undef input
-#undef unput
-#define input()  (*(char *) line++)
-#define unput(c) (*(char *) --line = c)
-#endif
-
-#define BUFF_LEN	1024
-char buff[BUFF_LEN];
-char *bptr;
-char *optr = buff;
-unsigned int tlen;
-
-%}
-
-%option nounput
-
-%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
-
-WS		[[:blank:]]+
-OPTWS		[[:blank:]]*
-NL		\r?\n
-CONT		\\\n{OPTWS}
-
-OPTIONSTR	([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
-MACROSTR	(-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
-SLASHIFYSTR	(--(no-)?slashify-colons)
-NUMBER		[0-9]+
-OCTALNUMBER	[0-7]+
-
-DNSERVSTR1	([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
-DNSERVSTR2	(\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
-DNSERVSTR3	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
-DNSERVSTR4	(\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
-DNSERVSTR5	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
-DNSERVSTR6	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
-DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
-
-AT_CN		([cC][[nN])
-AT_NMN		([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
-AT_AMN		([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
-AT_OU		([oO][[uU])
-AT_DC		([dD][[cC])
-AT_O		([oO])
-AT_C		([cC])
-AT_L		([lL])
-DNATTRSTR	({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
-DNNAMESTR1	([[:alnum:]_.\- ]+)
-DNNAMESTR2	([[:alnum:]_.\-]+)
-
-INTMAP		(-hosts|-null)
-MULTI		((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
-MULTISEP	([\-]{2}[[:blank:]]+)
-MTYPE		((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
-
-
-OPTTOUT		(-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
-OPTNTOUT	(-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
-
-MODE		(--mode{OPTWS}|--mode{OPTWS}={OPTWS})
-
-%%
-
-<INITIAL>{
-	{NL} | 
-	\x00 {
-		if (optr != buff) {
-			*optr = '\0';
-			strcpy(master_lval.strtype, buff);
-			return NILL;
-		}
-	}
-
-	#.*  { return COMMENT; }
-
-	"/" {
-		if (optr != buff) {
-			*optr = '\0';
-			strcpy(master_lval.strtype, buff);
-			return NILL;
-		}
-		BEGIN(PATHSTR);
-		bptr = buff;
-		yyless(0);
-	}
-
-	.    { *optr++ = *master_text; }
-}
-
-<PATHSTR>{
-	\x00 {
-		BEGIN(INITIAL);
-		*bptr++ = *master_text;
-		strcpy(master_lval.strtype, buff);
-		return NILL;
-	}
-
-	\\.  { *bptr++ = *(master_text + 1); }
-	\"   {
-		BEGIN(INITIAL);
-		*bptr++ = *master_text;
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		return QUOTE;
-	}
-
-	{WS} {
-		BEGIN(MAPSTR);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		bptr = buff;
-		memset(buff, 0, BUFF_LEN);
-		return(PATH);
-	}
-
-	<<EOF>> {
-		BEGIN(INITIAL);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		return(PATH);
-	}
-
-	{NL} {
-		BEGIN(INITIAL);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		return PATH;
-	}
-
-	.    { *bptr++ = *master_text; }
-}
-
-<MAPSTR>{
-	{OPTWS}\\\n{OPTWS} {}
-
-	{MULTI} {
-		tlen = master_leng - 1;
-		if (bptr != buff && isblank(master_text[tlen])) {
-			/*
-			 * We can't handle unescaped white space in map names
-			 * so just eat the white space. We always have the
-			 * "multi" at the beginning of the string so the while
-			 * will not fall off the end.
-			 */
-			while (isblank(master_text[tlen - 1]))
-				tlen--;
-			strncat(buff, master_text, tlen);
-			bptr += tlen;
-			yyless(tlen);
-		} else {
-			strcpy(master_lval.strtype, master_text);
-			return(MULTITYPE);
-		}
-	}
-
-	{MTYPE} |
-	{MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
-	{MTYPE}/{DNATTRSTR}= {
-		tlen = master_leng - 1;
-		if (bptr != buff && isblank(master_text[tlen])) {
-			/*
-			 * We can't handle unescaped white space in map names
-			 * so just eat the white space. We always have the
-			 * maptype keyword at the beginning of the string so
-			 * the while will not fall off the end.
-			 */
-			while (isblank(master_text[tlen - 1]))
-				tlen--;
-			strncat(buff, master_text, tlen);
-			bptr += tlen;
-			yyless(tlen);
-		} else {
-			strcpy(master_lval.strtype, master_text);
-			return(MAPTYPE);
-		}
-	}
-
-	{MULTISEP} { return(DDASH); }
-
-	":"	{ return(COLON); }
-
-	"-hosts" {
-		BEGIN(OPTSTR);
-		strcpy(master_lval.strtype, master_text);
-		return MAPHOSTS;
-	}
-
-	"-null" {
-		BEGIN(OPTSTR);
-		strcpy(master_lval.strtype, master_text);
-		return MAPNULL;
-	}
-
-	"-xfn" {
-		/*
-		 * The X/Open Federated Naming service isn't supported
-		 * and the parser will call YYABORT() when it sees the
-		 * MAPXFN token so we must set the start state to the
-		 * INITIAL state here for the next yylex() call.
-		 */
-		BEGIN(INITIAL);
-		strcpy(master_lval.strtype, master_text);
-		return MAPXFN;
-	}
-
-	"//" {
-		BEGIN(DNSTR);
-		yyless(0);
-	}
-
-	{DNSERVERSTR}{DNATTRSTR}= {
-		BEGIN(DNSTR);
-		yyless(0);
-	}
-
-	{DNATTRSTR}= {
-		BEGIN(DNSTR);
-		yyless(0);
-	}
-
-	{OPTWS}/{NL} {
-		BEGIN(INITIAL);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		bptr = buff;
-		return(MAPNAME);
-	}
-
-	\\. { *bptr++ = *(master_text + 1); }
-
-	{WS} {
-		BEGIN(OPTSTR);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		bptr = buff;
-		return(MAPNAME);
-	}
-
-	{NL} |
-	\x00 {
-		BEGIN(INITIAL);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		return(MAPNAME);
-	}
-
-	<<EOF>> {
-		BEGIN(INITIAL);
-		*bptr = '\0';
-		strcpy(master_lval.strtype, buff);
-		return(MAPNAME);
-	}
-
-	.	{ *bptr++ = *master_text; }
-}
-
-<DNSTR>{
-	{OPTWS}\\\n{OPTWS} {}
-
-	{DNSERVERSTR} {
-		strcpy(master_lval.strtype, master_text);
-		return DNSERVER;
-	}
-
-	{DNATTRSTR}/"=" {
-		strcpy(master_lval.strtype, master_text);
-		return DNATTR;
-	}
-
-	"=" {
-		return EQUAL;
-	}
-
-	{DNNAMESTR1}/","{DNATTRSTR}"=" {
-		strcpy(master_lval.strtype, master_text);
-		return DNNAME;
-	}
-
-	{DNNAMESTR2} {
-		strcpy(master_lval.strtype, master_text);
-		return DNNAME;
-	}
-
-	{OPTWS}","{OPTWS} {
-		return COMMA;
-	}
-
-	{WS}"=" |
-	"="{WS} {
-		BEGIN(INITIAL);
-		strcpy(master_lval.strtype, master_text);
-		return SPACE;
-	}
-
-	{WS}    { BEGIN(OPTSTR); }
-
-	{NL} |
-	\x00	{ BEGIN(INITIAL); }
-
-	<<EOF>> { BEGIN(INITIAL); }
-}
-
-<OPTSTR>{
-	{OPTWS}\\\n{OPTWS} {}
-
-	{MULTISEP} {
-		BEGIN(MAPSTR);
-		return(DDASH);
-	}
-
-	{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
-
-	{OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
-
-	{NUMBER} {
-		master_lval.longtype = atol(master_text);
-		return(NUMBER);
-	}
-
-	-?symlink		{ return(OPT_SYMLINK); }
-	-?nobind		{ return(OPT_NOBIND); }
-	-?nobrowse		{ return(OPT_NOGHOST); }
-	-?shared		{ return(OPT_SHARED); }
-	-?slave			{ return(OPT_SLAVE); }
-	-?private		{ return(OPT_PRIVATE); }
-	-?strictexpire		{ return(OPT_STRICTEXPIRE); }
-	-g|--ghost|-?browse	{ return(OPT_GHOST); }
-	-v|--verbose		{ return(OPT_VERBOSE); }
-	-d|--debug		{ return(OPT_DEBUG); }
-	-w|--use-weight-only	{ return(OPT_USE_WEIGHT); }
-	-r|--random-multimount-selection { return(OPT_RANDOM); }
-
-	{MODE}/{OCTALNUMBER} {
-		BEGIN(OCTAL);
-		return(OPT_MODE);
-	}
-
-	{OPTWS}","{OPTWS}	{ return(COMMA); }
-
-	{OPTWS} {}
-
-	{SLASHIFYSTR} {
-		strcpy(master_lval.strtype, master_text);
-		return(OPTION);
-	}
-
-	{MACROSTR} {
-		strcpy(master_lval.strtype, master_text);
-		return(OPTION);
-	}
-
-	{OPTIONSTR} {
-		strcpy(master_lval.strtype, master_text);
-		return(OPTION);
-	}
-
-	"="	{
-		strcpy(master_lval.strtype, master_text);
-		return(EQUAL);
-	}
-
-	{WS}	{}
-	{NL} |
-	\x00 { BEGIN(INITIAL); }
-
-	<<EOF>> { BEGIN(INITIAL); }
-}
-
-<OCTAL>{
-	{OCTALNUMBER} {
-		master_lval.longtype = strtoul(master_text, NULL, 8);
-		return(OCTALNUMBER);
-	}
-
-	. { BEGIN(OPTSTR); yyless(0); }
-}
-
-%%
-
-#include "automount.h"
-
-int master_wrap(void)
-{
-	return 1;
-}
-
-static void master_echo(void)
-{
-	logmsg("%s", master_text);
-	return;
-}
-
-#ifdef FLEX_SCANNER
-
-void master_set_scan_buffer(const char *buffer)
-{
-	memset(buff, 0, sizeof(buff));
-	optr = buff;
-
-	YY_FLUSH_BUFFER;
-
-	line = buffer;
-	line_pos = &line[0];
-	/*
-	 * 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;
-}
-
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-int my_yyinput(char *buffer, int max_size)
-{
-	int n = min(max_size, line_lim - line_pos);
-
-	if (n > 0) {
-		memcpy(buffer, line_pos, n);
-		line_pos += n;
-	}
-	return n;
-}
-
-#else
-
-void master_set_scan_buffer(const char *buffer)
-{
-	line = buffer;
-}
-
-#endif