Blame SOURCES/autofs-5.0.9-amd-lookup-add-parse_amd-c.patch

4d476f
autofs-5.0.9 - amd lookup add parse_amd.c
4d476f
4d476f
From: Ian Kent <raven@themaw.net>
4d476f
4d476f
Add a yacc parser and an autofs parser module for amd format
4d476f
maps.
4d476f
---
4d476f
 include/automount.h |    1 
4d476f
 include/mounts.h    |    6 
4d476f
 include/parse_amd.h |   54 ++
4d476f
 lib/mounts.c        |   81 +++
4d476f
 modules/Makefile    |   21 -
4d476f
 modules/amd_parse.y |  511 ++++++++++++++++++++++++
4d476f
 modules/amd_tok.l   |  316 +++++++++++++++
4d476f
 modules/parse_amd.c | 1081 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4d476f
 8 files changed, 2069 insertions(+), 2 deletions(-)
4d476f
 create mode 100644 include/parse_amd.h
4d476f
 create mode 100644 modules/amd_parse.y
4d476f
 create mode 100644 modules/amd_tok.l
4d476f
 create mode 100644 modules/parse_amd.c
4d476f
4d476f
--- autofs-5.0.7.orig/include/automount.h
4d476f
+++ autofs-5.0.7/include/automount.h
4d476f
@@ -34,6 +34,7 @@
4d476f
 #include "parse_subs.h"
4d476f
 #include "mounts.h"
4d476f
 #include "dev-ioctl-lib.h"
4d476f
+#include "parse_amd.h"
4d476f
 
4d476f
 #ifdef WITH_DMALLOC
4d476f
 #include <dmalloc.h>
4d476f
--- autofs-5.0.7.orig/include/mounts.h
4d476f
+++ autofs-5.0.7/include/mounts.h
4d476f
@@ -85,10 +85,16 @@ unsigned int linux_version_code(void);
4d476f
 int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *);
4d476f
 extern unsigned int nfs_mount_uses_string_options;
4d476f
 
4d476f
+struct amd_entry;
4d476f
+
4d476f
 struct substvar *addstdenv(struct substvar *sv);
4d476f
 struct substvar *removestdenv(struct substvar *sv);
4d476f
 void add_std_amd_vars(struct substvar *sv);
4d476f
 void remove_std_amd_vars(void);
4d476f
+struct amd_entry *new_amd_entry(const struct substvar *sv);
4d476f
+void clear_amd_entry(struct amd_entry *entry);
4d476f
+void free_amd_entry(struct amd_entry *entry);
4d476f
+void free_amd_entry_list(struct list_head *entries);
4d476f
 
4d476f
 unsigned int query_kproto_ver(void);
4d476f
 unsigned int get_kver_major(void);
4d476f
--- /dev/null
4d476f
+++ autofs-5.0.7/include/parse_amd.h
4d476f
@@ -0,0 +1,54 @@
4d476f
+/* ----------------------------------------------------------------------- *
4d476f
+ *
4d476f
+ *  Copyright 2004-2006 Ian Kent <raven@themaw.net>
4d476f
+ *  Copyright 2013 Red Hat, Inc.
4d476f
+ *  All rights reserved.
4d476f
+ *
4d476f
+ *  This program is free software; you can redistribute it and/or modify
4d476f
+ *  it under the terms of the GNU General Public License as published by
4d476f
+ *  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
4d476f
+ *  USA; either version 2 of the License, or (at your option) any later
4d476f
+ *  version; incorporated herein by reference.
4d476f
+ *
4d476f
+ * ----------------------------------------------------------------------- */
4d476f
+
4d476f
+#ifndef PARSE_AMD_H
4d476f
+#define PARSE_AMD_H
4d476f
+
4d476f
+#define AMD_MOUNT_TYPE_NONE	0x00000000
4d476f
+#define AMD_MOUNT_TYPE_AUTO	0x00000001
4d476f
+#define AMD_MOUNT_TYPE_NFS	0x00000002
4d476f
+#define AMD_MOUNT_TYPE_LINK	0x00000004
4d476f
+#define AMD_MOUNT_TYPE_HOST	0x00000008
4d476f
+#define AMD_MOUNT_TYPE_MASK	0x0000ffff
4d476f
+
4d476f
+#define AMD_ENTRY_CUT		0x00010000
4d476f
+#define AMD_ENTRY_MASK		0x00ff0000
4d476f
+
4d476f
+#define AMD_DEFAULTS_MERGE	0x01000000
4d476f
+#define AMD_DEFAULTS_RESET	0x02000000
4d476f
+#define AMD_DEFAULTS_MASK	0xff000000
4d476f
+
4d476f
+struct amd_entry {
4d476f
+	char *path;
4d476f
+	unsigned long flags;
4d476f
+	char *type;
4d476f
+	char *map_type;
4d476f
+	char *pref;
4d476f
+	char *fs;
4d476f
+	char *rhost;
4d476f
+	char *rfs;
4d476f
+	char *opts;
4d476f
+	char *addopts;
4d476f
+	char *remopts;
4d476f
+	char *sublink;
4d476f
+	struct selector *selector;
4d476f
+	struct list_head list;
4d476f
+	struct list_head entries;
4d476f
+	struct list_head ext_mount;
4d476f
+};
4d476f
+
4d476f
+int amd_parse_list(struct autofs_point *,
4d476f
+		   const char *, struct list_head *, struct substvar **);
4d476f
+
4d476f
+#endif
4d476f
--- autofs-5.0.7.orig/lib/mounts.c
4d476f
+++ autofs-5.0.7/lib/mounts.c
4d476f
@@ -442,6 +442,87 @@ void remove_std_amd_vars(void)
4d476f
 	return;
4d476f
  }
4d476f
 
4d476f
+struct amd_entry *new_amd_entry(const struct substvar *sv)
4d476f
+{
4d476f
+	struct amd_entry *new;
4d476f
+	const struct substvar *v;
4d476f
+	char *path;
4d476f
+
4d476f
+	v = macro_findvar(sv, "path", 4);
4d476f
+	if (!v)
4d476f
+		return NULL;
4d476f
+
4d476f
+	path = strdup(v->val);
4d476f
+	if (!path)
4d476f
+		return NULL;
4d476f
+
4d476f
+	new = malloc(sizeof(struct amd_entry));
4d476f
+	if (!new) {
4d476f
+		free(path);
4d476f
+		return NULL;
4d476f
+	}
4d476f
+
4d476f
+	memset(new, 0, sizeof(*new));
4d476f
+	new->path = path;
4d476f
+	INIT_LIST_HEAD(&new->list);
4d476f
+	INIT_LIST_HEAD(&new->entries);
4d476f
+	INIT_LIST_HEAD(&new->ext_mount);
4d476f
+
4d476f
+	return new;
4d476f
+}
4d476f
+
4d476f
+void clear_amd_entry(struct amd_entry *entry)
4d476f
+{
4d476f
+	if (!entry)
4d476f
+		return;
4d476f
+	if (entry->path)
4d476f
+		free(entry->path);
4d476f
+	if (entry->map_type)
4d476f
+		free(entry->map_type);
4d476f
+	if (entry->pref)
4d476f
+		free(entry->pref);
4d476f
+	if (entry->fs)
4d476f
+		free(entry->fs);
4d476f
+	if (entry->rhost)
4d476f
+		free(entry->rhost);
4d476f
+	if (entry->rfs)
4d476f
+		free(entry->rfs);
4d476f
+	if (entry->opts)
4d476f
+		free(entry->opts);
4d476f
+	if (entry->addopts)
4d476f
+		free(entry->addopts);
4d476f
+	if (entry->remopts)
4d476f
+		free(entry->remopts);
4d476f
+	if (entry->sublink)
4d476f
+		free(entry->sublink);
4d476f
+	if (entry->selector)
4d476f
+		free_selector(entry->selector);
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+void free_amd_entry(struct amd_entry *entry)
4d476f
+{
4d476f
+	clear_amd_entry(entry);
4d476f
+	free(entry);
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+void free_amd_entry_list(struct list_head *entries)
4d476f
+{
4d476f
+	if (!list_empty(entries)) {
4d476f
+		struct list_head *head = entries;
4d476f
+		struct amd_entry *this;
4d476f
+		struct list_head *p;
4d476f
+
4d476f
+		p = head->next;
4d476f
+		while (p != head) {
4d476f
+			this = list_entry(p, struct amd_entry, list);
4d476f
+			p = p->next;
4d476f
+			free_amd_entry(this);
4d476f
+		}
4d476f
+	}
4d476f
+}
4d476f
+
4d476f
 /*
4d476f
  * Make common autofs mount options string
4d476f
  */
4d476f
--- autofs-5.0.7.orig/modules/Makefile
4d476f
+++ autofs-5.0.7/modules/Makefile
4d476f
@@ -7,16 +7,18 @@ include ../Makefile.rules
4d476f
 
4d476f
 SRCS :=	lookup_file.c lookup_program.c  lookup_userhome.c \
4d476f
 	lookup_multi.c lookup_hosts.c lookup_dir.c \
4d476f
-	parse_sun.c    \
4d476f
+	parse_sun.c parse_amd.c \
4d476f
 	mount_generic.c  mount_nfs.c  mount_afs.c  mount_autofs.c \
4d476f
 	mount_changer.c  mount_bind.c
4d476f
 
4d476f
 MODS :=	lookup_file.so lookup_program.so lookup_userhome.so \
4d476f
 	lookup_multi.so lookup_hosts.so lookup_dir.so \
4d476f
-	parse_sun.so \
4d476f
+	parse_sun.so parse_amd.so \
4d476f
 	mount_generic.so mount_nfs.so mount_afs.so mount_autofs.so \
4d476f
 	mount_changer.so mount_bind.so
4d476f
 
4d476f
+YACCSRC = amd_tok.c amd_parse.tab.c amd_parse.tab.h \
4d476f
+
4d476f
 ifeq ($(EXT2FS), 1)
4d476f
   SRCS += mount_ext2.c
4d476f
   MODS += mount_ext2.so
4d476f
@@ -94,6 +96,21 @@ else ifeq ($(EXT4FS), 1)
4d476f
 	mv $(INSTALLROOT)$(autofslibdir)/mount_ext2.so $(INSTALLROOT)$(autofslibdir)/mount_ext4.so
4d476f
 endif
4d476f
 
4d476f
+amd_tok.c: amd_tok.l
4d476f
+	$(LEX) -o$@ -Pamd_ $?
4d476f
+
4d476f
+amd_tok.o: amd_tok.c amd_parse.tab.h
4d476f
+
4d476f
+amd_parse.tab.c amd_parse.tab.h: amd_parse.y
4d476f
+	$(YACC) -v -d -p amd_ -b amd_parse $?
4d476f
+
4d476f
+amd_parse.tab.o: amd_parse.tab.c amd_parse.tab.h
4d476f
+
4d476f
+parse_amd.so: parse_amd.c amd_parse.tab.o amd_tok.o
4d476f
+	$(CC) $(LDFLAGS) $(SOLDFLAGS) $(CFLAGS) -o parse_amd.so \
4d476f
+		parse_amd.c amd_parse.tab.o amd_tok.o $(AUTOFS_LIB) $(LIBS)
4d476f
+	$(STRIP) parse_amd.so
4d476f
+
4d476f
 #
4d476f
 # Ad hoc compilation rules for modules which need auxilliary libraries
4d476f
 #
4d476f
--- /dev/null
4d476f
+++ autofs-5.0.7/modules/amd_parse.y
4d476f
@@ -0,0 +1,511 @@
4d476f
+%{
4d476f
+/* ----------------------------------------------------------------------- *
4d476f
+ *
4d476f
+ *  Copyright 2013 Ian Kent <raven@themaw.net>
4d476f
+ *  Copyright 2013 Red Hat, Inc.
4d476f
+ *  All rights reserved.
4d476f
+ *
4d476f
+ *  This program is free software; you can redistribute it and/or modify
4d476f
+ *  it under the terms of the GNU General Public License as published by
4d476f
+ *  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
4d476f
+ *  USA; either version 2 of the License, or (at your option) any later
4d476f
+ *  version.
4d476f
+ *
4d476f
+ *  This program is distributed in the hope that it will be useful,
4d476f
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
4d476f
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4d476f
+ *  GNU General Public License for more details.
4d476f
+ *
4d476f
+ * ----------------------------------------------------------------------- */
4d476f
+
4d476f
+#include <stdio.h>
4d476f
+#include <string.h>
4d476f
+#include <stdlib.h>
4d476f
+#include <stdarg.h>
4d476f
+#include <ctype.h>
4d476f
+#include <sys/ioctl.h>
4d476f
+#include <syslog.h>
4d476f
+
4d476f
+#include "automount.h"
4d476f
+#include "parse_amd.h"
4d476f
+
4d476f
+#define MAX_OPTS_LEN	1024
4d476f
+#define MAX_ERR_LEN	512
4d476f
+
4d476f
+static pthread_mutex_t parse_mutex = PTHREAD_MUTEX_INITIALIZER;
4d476f
+
4d476f
+extern FILE *amd_in;
4d476f
+extern char *amd_text;
4d476f
+extern int amd_lex(void);
4d476f
+extern void amd_set_scan_buffer(const char *);
4d476f
+
4d476f
+static char *amd_strdup(char *);
4d476f
+static void local_init_vars(void);
4d476f
+static void local_free_vars(void);
4d476f
+
4d476f
+static int amd_error(const char *s);
4d476f
+static int amd_notify(const char *s);
4d476f
+static int amd_msg(const char *s);
4d476f
+
4d476f
+static int add_location(void);
4d476f
+static int make_selector(char *name,
4d476f
+			 char *value1, char *value2,
4d476f
+			 unsigned int compare);
4d476f
+static void add_selector(struct selector *selector);
4d476f
+
4d476f
+static struct amd_entry entry;
4d476f
+static struct list_head *entries;
4d476f
+static struct autofs_point *pap;
4d476f
+struct substvar *psv;
4d476f
+static char opts[MAX_OPTS_LEN];
4d476f
+static void prepend_opt(char *, char *);
4d476f
+
4d476f
+#define YYDEBUG 0
4d476f
+
4d476f
+#ifndef YYENABLE_NLS
4d476f
+#define YYENABLE_NLS 0
4d476f
+#endif
4d476f
+#ifndef YYLTYPE_IS_TRIVIAL
4d476f
+#define YYLTYPE_IS_TRIVIAL 0
4d476f
+#endif
4d476f
+
4d476f
+#if YYDEBUG
4d476f
+static int amd_fprintf(FILE *, char *, ...);
4d476f
+#undef YYFPRINTF
4d476f
+#define YYFPRINTF amd_fprintf
4d476f
+#endif
4d476f
+
4d476f
+%}
4d476f
+
4d476f
+%union {
4d476f
+	char strtype[2048];
4d476f
+	int inttype;
4d476f
+	long longtype;
4d476f
+}
4d476f
+
4d476f
+%token COMMENT
4d476f
+%token SEPERATOR
4d476f
+%token SPACE
4d476f
+%token HYPHEN
4d476f
+%token IS_EQUAL
4d476f
+%token CUT
4d476f
+%token NOT_EQUAL
4d476f
+%token COMMA
4d476f
+%token OPTION_ASSIGN
4d476f
+%token NILL
4d476f
+
4d476f
+%token <strtype> MAP_OPTION
4d476f
+%token <strtype> MAP_TYPE
4d476f
+%token <strtype> FS_TYPE
4d476f
+%token <strtype> FS_OPTION
4d476f
+%token <strtype> FS_OPT_VALUE
4d476f
+%token <strtype> MNT_OPTION
4d476f
+%token <strtype> SELECTOR
4d476f
+%token <strtype> SELECTOR_VALUE
4d476f
+%token <strtype> OPTION
4d476f
+%token <strtype> MACRO
4d476f
+%token <strtype> OTHER
4d476f
+
4d476f
+%type <strtype> options
4d476f
+
4d476f
+%start file
4d476f
+
4d476f
+%%
4d476f
+
4d476f
+file: {
4d476f
+#if YYDEBUG != 0
4d476f
+		amd_debug = YYDEBUG;
4d476f
+#endif
4d476f
+		memset(opts, 0, sizeof(opts));
4d476f
+	} line
4d476f
+	;
4d476f
+
4d476f
+line:
4d476f
+	| location_selection_list
4d476f
+	;
4d476f
+
4d476f
+location_selection_list: location
4d476f
+	{
4d476f
+		if (!add_location()) {
4d476f
+			amd_msg("failed to allocate new location");
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| location_selection_list SPACE location
4d476f
+	{
4d476f
+		if (!add_location()) {
4d476f
+			amd_msg("failed to allocate new location");
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| location_selection_list SPACE CUT SPACE location
4d476f
+	{
4d476f
+		entry.flags |= AMD_ENTRY_CUT;
4d476f
+		if (!add_location()) {
4d476f
+			amd_msg("failed to allocate new location");
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+location: location_entry
4d476f
+	{
4d476f
+	}
4d476f
+	| HYPHEN location_entry
4d476f
+	{
4d476f
+		entry.flags |= AMD_DEFAULTS_MERGE;
4d476f
+	}
4d476f
+	| HYPHEN
4d476f
+	{
4d476f
+		entry.flags |= AMD_DEFAULTS_RESET;
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+location_entry: selector_or_option
4d476f
+	{
4d476f
+	}
4d476f
+	| location_entry SEPERATOR selector_or_option
4d476f
+	{
4d476f
+	}
4d476f
+	| location_entry SEPERATOR
4d476f
+	{
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+selector_or_option: selection
4d476f
+	{
4d476f
+	}
4d476f
+	| option_assignment
4d476f
+	{
4d476f
+	}
4d476f
+	| OTHER
4d476f
+	{
4d476f
+		amd_notify($1);
4d476f
+		YYABORT;
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+selection: SELECTOR IS_EQUAL SELECTOR_VALUE
4d476f
+	{
4d476f
+		if (!make_selector($1, $3, NULL, SEL_TYPE_EQUAL)) {
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| SELECTOR NOT_EQUAL SELECTOR_VALUE
4d476f
+	{
4d476f
+		if (!make_selector($1, $3, NULL, SEL_TYPE_NOTEQUAL)) {
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE
4d476f
+	{
4d476f
+		if (!strcmp($3, "auto")) {
4d476f
+			entry.flags |= AMD_MOUNT_TYPE_AUTO;
4d476f
+			entry.type = amd_strdup($3);
4d476f
+		} else if (!strcmp($3, "nfs") ||
4d476f
+			   !strcmp($3, "nfs4")) {
4d476f
+			entry.flags |= AMD_MOUNT_TYPE_NFS;
4d476f
+			entry.type = amd_strdup($3);
4d476f
+		} else if (!strcmp($3, "link")) {
4d476f
+			entry.flags |= AMD_MOUNT_TYPE_LINK;
4d476f
+			entry.type = amd_strdup($3);
4d476f
+		} else if (!strcmp($3, "host")) {
4d476f
+			entry.flags |= AMD_MOUNT_TYPE_HOST;
4d476f
+			entry.type = amd_strdup($3);
4d476f
+		} else {
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| MAP_OPTION OPTION_ASSIGN MAP_TYPE
4d476f
+	{
4d476f
+		if (!strcmp($3, "file") ||
4d476f
+		    !strcmp($3, "nis") ||
4d476f
+		    !strcmp($3, "nisplus") ||
4d476f
+		    !strcmp($3, "ldap") ||
4d476f
+		    !strcmp($3, "hesiod"))
4d476f
+			entry.map_type = amd_strdup($3);
4d476f
+		else if (!strcmp($3, "exec"))
4d476f
+			/* autofs uses "program" for "exec" map type */
4d476f
+			entry.map_type = amd_strdup("program");
4d476f
+		else {
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| MAP_OPTION OPTION_ASSIGN FS_OPT_VALUE
4d476f
+	{
4d476f
+		if (!strcmp($1, "fs"))
4d476f
+			entry.fs = amd_strdup($3);
4d476f
+		else if (!strcmp($1, "sublink"))
4d476f
+			entry.sublink = amd_strdup($3);
4d476f
+		else if (!strcmp($1, "pref")) {
4d476f
+			if (!strcmp($3, "null"))
4d476f
+				entry.pref = amd_strdup("");
4d476f
+			else
4d476f
+				entry.pref = amd_strdup($3);
4d476f
+		} else {
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| FS_OPTION OPTION_ASSIGN FS_OPT_VALUE
4d476f
+	{
4d476f
+		if (!strcmp($1, "rhost"))
4d476f
+			entry.rhost = amd_strdup($3);
4d476f
+		else if (!strcmp($1, "rfs"))
4d476f
+			entry.rfs = amd_strdup($3);
4d476f
+		else {
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	| MNT_OPTION OPTION_ASSIGN options
4d476f
+	{
4d476f
+		if (!strcmp($1, "opts")) {
4d476f
+			entry.opts = amd_strdup(opts);
4d476f
+			memset(opts, 0, sizeof(opts));
4d476f
+		} else if (!strcmp($1, "addopts")) {
4d476f
+			entry.addopts = amd_strdup(opts);
4d476f
+			memset(opts, 0, sizeof(opts));
4d476f
+		} else if (!strcmp($1, "remopts")) {
4d476f
+			entry.remopts = amd_strdup(opts);
4d476f
+			memset(opts, 0, sizeof(opts));
4d476f
+		} else {
4d476f
+			memset(opts, 0, sizeof(opts));
4d476f
+			amd_notify($1);
4d476f
+			YYABORT;
4d476f
+		}
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+options: OPTION
4d476f
+	{
4d476f
+		prepend_opt(opts, $1);
4d476f
+	}
4d476f
+	| OPTION COMMA options
4d476f
+	{
4d476f
+		prepend_opt(opts, $1);
4d476f
+	}
4d476f
+	;
4d476f
+
4d476f
+%%
4d476f
+
4d476f
+static void prepend_opt(char *dest, char *opt)
4d476f
+{
4d476f
+	char new[MAX_OPTS_LEN];
4d476f
+	strcpy(new, opt);
4d476f
+	if (*dest != '\0') {
4d476f
+		strcat(new, ",");
4d476f
+		strcat(new, dest);
4d476f
+	}
4d476f
+	memmove(dest, new, strlen(new));
4d476f
+}
4d476f
+
4d476f
+#if YYDEBUG
4d476f
+static int amd_fprintf(FILE *f, char *msg, ...)
4d476f
+{
4d476f
+	va_list ap;
4d476f
+	va_start(ap, msg);
4d476f
+	vsyslog(LOG_DEBUG, msg, ap);
4d476f
+	va_end(ap);
4d476f
+	return 1;
4d476f
+}
4d476f
+#endif
4d476f
+
4d476f
+static char *amd_strdup(char *str)
4d476f
+{
4d476f
+	char *tmp;
4d476f
+
4d476f
+	tmp = strdup(str);
4d476f
+	if (!tmp)
4d476f
+		amd_error("memory allocation error");
4d476f
+	return tmp;
4d476f
+}
4d476f
+
4d476f
+static int amd_error(const char *s)
4d476f
+{
4d476f
+	if (strcmp(s, "syntax"))
4d476f
+		logmsg("syntax error in location near [ %s ]\n", amd_text);
4d476f
+	else
4d476f
+		logmsg("%s while parsing location.\n", s);
4d476f
+	return 0;
4d476f
+}
4d476f
+
4d476f
+static int amd_notify(const char *s)
4d476f
+{
4d476f
+	logmsg("syntax error in location near [ %s ]\n", s);
4d476f
+	return(0);
4d476f
+}
4d476f
+
4d476f
+static int amd_msg(const char *s)
4d476f
+{
4d476f
+	logmsg("%s\n", s);
4d476f
+	return 0;
4d476f
+}
4d476f
+
4d476f
+static void local_init_vars(void)
4d476f
+{
4d476f
+	memset(&entry, 0, sizeof(entry));
4d476f
+	memset(opts, 0, sizeof(opts));
4d476f
+}
4d476f
+
4d476f
+static void local_free_vars(void)
4d476f
+{
4d476f
+	clear_amd_entry(&entry);
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static void add_selector(struct selector *selector)
4d476f
+{
4d476f
+	struct selector *s = entry.selector;
4d476f
+
4d476f
+	if (!s) {
4d476f
+		entry.selector = selector;
4d476f
+		return;
4d476f
+	}
4d476f
+
4d476f
+	while (s->next)
4d476f
+		s = s->next;
4d476f
+
4d476f
+	selector->next = s;
4d476f
+	entry.selector = selector;
4d476f
+
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static int make_selector(char *name,
4d476f
+			 char *value1, char *value2,
4d476f
+			 unsigned int compare)
4d476f
+{
4d476f
+	struct selector *s;
4d476f
+	char *tmp;
4d476f
+
4d476f
+	if (!sel_lookup(name))
4d476f
+		return 0;
4d476f
+
4d476f
+	if (!value1)
4d476f
+		return 0;
4d476f
+
4d476f
+	s = get_selector(name);
4d476f
+	if (!s)
4d476f
+		return 0;
4d476f
+
4d476f
+	if (s->sel->flags & SEL_FLAG_MACRO) {
4d476f
+		tmp = amd_strdup(value1);
4d476f
+		if (!tmp)
4d476f
+			goto error;
4d476f
+		s->comp.value = tmp;
4d476f
+	} else if (s->sel->flags & SEL_FLAG_FUNC1) {
4d476f
+		char *tmp = amd_strdup(value1);
4d476f
+		if (!tmp)
4d476f
+			goto error;
4d476f
+		s->func.arg1 = tmp;
4d476f
+	} else if (s->sel->flags & SEL_FLAG_FUNC2) {
4d476f
+		char *tmp = amd_strdup(value1);
4d476f
+		if (!tmp)
4d476f
+			goto error;
4d476f
+		s->func.arg1 = tmp;
4d476f
+		if (value2) {
4d476f
+			tmp = amd_strdup(value2);
4d476f
+			if (tmp)
4d476f
+				s->func.arg2 = tmp;
4d476f
+		}
4d476f
+	}
4d476f
+	s->compare = compare;
4d476f
+
4d476f
+	add_selector(s);
4d476f
+
4d476f
+	return 1;
4d476f
+error:
4d476f
+	free_selector(s);
4d476f
+	return 0;
4d476f
+}
4d476f
+
4d476f
+void amd_init_scan(void)
4d476f
+{
4d476f
+}
4d476f
+
4d476f
+static void parse_mutex_lock(void)
4d476f
+{
4d476f
+	int status = pthread_mutex_lock(&parse_mutex);
4d476f
+	if (status)
4d476f
+		fatal(status);
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static void parse_mutex_unlock(void *arg)
4d476f
+{
4d476f
+	int status = pthread_mutex_unlock(&parse_mutex);
4d476f
+	if (status)
4d476f
+		fatal(status);
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static int add_location(void)
4d476f
+{
4d476f
+	struct amd_entry *new;
4d476f
+
4d476f
+	new = new_amd_entry(psv);
4d476f
+	if (!new)
4d476f
+		return 0;
4d476f
+
4d476f
+	if (entry.path) {
4d476f
+		free(new->path);
4d476f
+		new->path = entry.path;
4d476f
+	}
4d476f
+	new->flags = entry.flags;
4d476f
+	new->type = entry.type;
4d476f
+	new->map_type = entry.map_type;
4d476f
+	new->pref = entry.pref;
4d476f
+	new->fs = entry.fs;
4d476f
+	new->rhost = entry.rhost;
4d476f
+	new->rfs = entry.rfs;
4d476f
+	new->dev = entry.dev;
4d476f
+	new->opts = entry.opts;
4d476f
+	new->addopts = entry.addopts;
4d476f
+	new->remopts = entry.remopts;
4d476f
+	new->sublink = entry.sublink;
4d476f
+	new->selector = entry.selector;
4d476f
+	list_add_tail(&new->list, entries);
4d476f
+	memset(&entry, 0, sizeof(struct amd_entry));
4d476f
+
4d476f
+	return 1;
4d476f
+}
4d476f
+
4d476f
+int amd_parse_list(struct autofs_point *ap,
4d476f
+		   const char *buffer, struct list_head *list,
4d476f
+		   struct substvar **sv)
4d476f
+{
4d476f
+	char *buf;
4d476f
+	size_t len;
4d476f
+	int ret;
4d476f
+
4d476f
+	len = strlen(buffer) + 2;
4d476f
+	buf = malloc(len);
4d476f
+	if (!buf)
4d476f
+		return 0;
4d476f
+	strcpy(buf, buffer);
4d476f
+
4d476f
+	parse_mutex_lock();
4d476f
+	pthread_cleanup_push(parse_mutex_unlock, NULL);
4d476f
+
4d476f
+	pap = ap;
4d476f
+	psv = *sv;
4d476f
+	entries = list;
4d476f
+	amd_set_scan_buffer(buf);
4d476f
+
4d476f
+	local_init_vars();
4d476f
+	ret = amd_parse();
4d476f
+	local_free_vars();
4d476f
+	*sv = psv;
4d476f
+
4d476f
+	pthread_cleanup_pop(1);
4d476f
+	free(buf);
4d476f
+
4d476f
+	return ret;
4d476f
+}
4d476f
--- /dev/null
4d476f
+++ autofs-5.0.7/modules/amd_tok.l
4d476f
@@ -0,0 +1,316 @@
4d476f
+%{
4d476f
+/* ----------------------------------------------------------------------- *
4d476f
+ *
4d476f
+ *  Copyright 2013 Ian Kent <raven@themaw.net>
4d476f
+ *  Copyright 2013 Red Hat, Inc.
4d476f
+ *  All rights reserved.
4d476f
+ *
4d476f
+ *  This program is free software; you can redistribute it and/or modify
4d476f
+ *  it under the terms of the GNU General Public License as published by
4d476f
+ *  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
4d476f
+ *  USA; either version 2 of the License, or (at your option) any later
4d476f
+ *  version.
4d476f
+ *
4d476f
+ *  This program is distributed in the hope that it will be useful,
4d476f
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
4d476f
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4d476f
+ *  GNU General Public License for more details.
4d476f
+ *
4d476f
+ * ----------------------------------------------------------------------- */
4d476f
+
4d476f
+#ifdef ECHO
4d476f
+# undef ECHO
4d476f
+#endif
4d476f
+static void amd_echo(void);	/* forward definition */
4d476f
+#define ECHO amd_echo()
4d476f
+int amd_wrap(void);
4d476f
+
4d476f
+#include <stdio.h>
4d476f
+#include <stdlib.h>
4d476f
+#include <string.h>
4d476f
+#include <ctype.h>
4d476f
+#include "amd_parse.tab.h"
4d476f
+
4d476f
+int amd_lex(void);
4d476f
+int mad_wrap(void);
4d476f
+
4d476f
+#define YY_SKIP_YYWRAP
4d476f
+
4d476f
+#ifndef YY_STACK_USED
4d476f
+#define YY_STACK_USED 0
4d476f
+#endif
4d476f
+#ifndef YY_ALWAYS_INTERACTIVE
4d476f
+#define YY_ALWAYS_INTERACTIVE 0
4d476f
+#endif
4d476f
+#ifndef YY_NEVER_INTERACTIVE
4d476f
+#define YY_NEVER_INTERACTIVE 0
4d476f
+#endif
4d476f
+#ifndef YY_MAIN
4d476f
+#define YY_MAIN 0
4d476f
+#endif
4d476f
+
4d476f
+void amd_set_scan_buffer(const char *);
4d476f
+static const char *line = NULL;
4d476f
+
4d476f
+#ifdef FLEX_SCANNER
4d476f
+static const char *line_pos = NULL;
4d476f
+static const char *line_lim = NULL;
4d476f
+int amd_yyinput(char *, int);
4d476f
+
4d476f
+#undef YY_INPUT
4d476f
+#define YY_INPUT(b, r, ms) (r = amd_yyinput(b, ms))
4d476f
+#else
4d476f
+#undef input
4d476f
+#undef unput
4d476f
+#define input()  (*(char *) line++)
4d476f
+#define unput(c) (*(char *) --line = c)
4d476f
+#endif
4d476f
+
4d476f
+%}
4d476f
+
4d476f
+%option nounput
4d476f
+
4d476f
+%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL
4d476f
+
4d476f
+NL		\r?\n
4d476f
+OPTWS		[[:blank:]]*
4d476f
+OTHR		[^!;:=/|\- \t\r\n#]*
4d476f
+
4d476f
+MACRO		(\$\{([[:alpha:]_/]([[:alnum:]_\-])([[:alnum:]_\-/])*)\})
4d476f
+QSTR		(\"([^"\\]|\\.)*\")
4d476f
+OSTR		([[:alpha:]]([[:alnum:]_\-])+)
4d476f
+FSTR		([[:alnum:]_/\.]([[:alnum:]_\-/\.]|(\\.))*)
4d476f
+VSTR		(([[:alnum:]_\-\:/\.])+)
4d476f
+SSTR		([[:alpha:]]([[:alnum:]\-\.])+)
4d476f
+
4d476f
+FOPT		(({QSTR}|{FSTR}|{MACRO})+)
4d476f
+OPTS		({OSTR}(=({VSTR}|{QSTR}|{MACRO})+)?)
4d476f
+SOPT		(({SSTR}|{QSTR}|{MACRO})+)
4d476f
+
4d476f
+MAPOPT		(fs|type|maptype|pref|sublink|delay)
4d476f
+MNTOPT		(opts|addopts|remopts)
4d476f
+FSOPTS		(rhost|rfs|dev|cachedir)
4d476f
+MAPTYPE		(file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union)
4d476f
+FSTYPE		(auto|nfs|link|host|nfsx|ufs|xfs|efs)
4d476f
+
4d476f
+OSSEL		(arch|karch|os|osver|full_os|vendor)
4d476f
+HSTSEL		(host|hostd|xhost|domain|byte|cluster)
4d476f
+NETSEL		(netnumber|network|wire|netgrp|netgrpd|in_network)
4d476f
+USRSEL		(uid|gid)
4d476f
+MAPSEL		(key|map|path)
4d476f
+OTRSEL		(exists|autodir|dollar)
4d476f
+BOLSEL		(true|false)
4d476f
+SELOPT		({OSSEL}|{HSTSEL}|{NETSEL}|{BOLSEL}|{USRSEL}|{MAPSEL}|{OTRSEL})
4d476f
+
4d476f
+CUTSEP		(\|\||\/)
4d476f
+
4d476f
+%%
4d476f
+
4d476f
+<INITIAL>{
4d476f
+	{NL} |
4d476f
+	\x00 { }
4d476f
+
4d476f
+	{MAPOPT} {
4d476f
+		BEGIN(MAPOPTVAL);
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return MAP_OPTION;
4d476f
+
4d476f
+	}
4d476f
+
4d476f
+	{FSOPTS} {
4d476f
+		BEGIN(FSOPTVAL);
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return FS_OPTION;
4d476f
+	}
4d476f
+
4d476f
+	{MNTOPT} {
4d476f
+		BEGIN(MNTOPTVAL);
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return MNT_OPTION;
4d476f
+	}
4d476f
+
4d476f
+	{SELOPT} {
4d476f
+		BEGIN(SELOPTVAL);
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return SELECTOR;
4d476f
+	}
4d476f
+
4d476f
+	{CUTSEP} { return CUT; }
4d476f
+
4d476f
+	"-" { return HYPHEN; }
4d476f
+
4d476f
+	{OPTWS} { return SPACE; }
4d476f
+
4d476f
+	#.*  { return COMMENT; }
4d476f
+
4d476f
+	{OTHR} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return OTHER;
4d476f
+	}
4d476f
+}
4d476f
+
4d476f
+<MAPOPTVAL>{
4d476f
+	{NL} |
4d476f
+	\x00 {
4d476f
+		BEGIN(INITIAL);
4d476f
+		yyless(1);
4d476f
+	}
4d476f
+
4d476f
+	";" {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SEPERATOR;
4d476f
+	}
4d476f
+
4d476f
+	{OPTWS} {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SPACE;
4d476f
+	}
4d476f
+
4d476f
+	":=" { return OPTION_ASSIGN; }
4d476f
+
4d476f
+	{FSTYPE} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return FS_TYPE;
4d476f
+	}
4d476f
+
4d476f
+	{MAPTYPE} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return MAP_TYPE;
4d476f
+	}
4d476f
+
4d476f
+	{FOPT} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return FS_OPT_VALUE;
4d476f
+	}
4d476f
+}
4d476f
+
4d476f
+<FSOPTVAL>{
4d476f
+	{NL} |
4d476f
+	\x00 {
4d476f
+		BEGIN(INITIAL);
4d476f
+		yyless(1);
4d476f
+	}
4d476f
+
4d476f
+	";" {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SEPERATOR;
4d476f
+	}
4d476f
+
4d476f
+	{OPTWS} {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SPACE;
4d476f
+	}
4d476f
+
4d476f
+	":=" { return OPTION_ASSIGN; }
4d476f
+
4d476f
+	{FOPT} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return FS_OPT_VALUE;
4d476f
+	}
4d476f
+}
4d476f
+
4d476f
+<MNTOPTVAL>{
4d476f
+	{NL} |
4d476f
+	\x00 {
4d476f
+		BEGIN(INITIAL);
4d476f
+		yyless(1);
4d476f
+	}
4d476f
+
4d476f
+	";" {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SEPERATOR;
4d476f
+	}
4d476f
+
4d476f
+	{OPTWS} {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SPACE;
4d476f
+	}
4d476f
+
4d476f
+	":=" { return OPTION_ASSIGN; }
4d476f
+
4d476f
+	"," { return COMMA; }
4d476f
+
4d476f
+	{OPTS} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return OPTION;
4d476f
+	}
4d476f
+}
4d476f
+
4d476f
+<SELOPTVAL>{
4d476f
+	{NL} |
4d476f
+	\x00 {
4d476f
+		BEGIN(INITIAL);
4d476f
+		yyless(1);
4d476f
+	}
4d476f
+
4d476f
+	";" {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SEPERATOR;
4d476f
+	}
4d476f
+
4d476f
+	{OPTWS} {
4d476f
+		BEGIN(INITIAL);
4d476f
+		return SPACE;
4d476f
+	}
4d476f
+
4d476f
+	"==" { return IS_EQUAL; }
4d476f
+
4d476f
+	"!=" { return NOT_EQUAL; }
4d476f
+
4d476f
+	{SOPT} {
4d476f
+		strcpy(amd_lval.strtype, amd_text);
4d476f
+		return SELECTOR_VALUE;
4d476f
+	}
4d476f
+}
4d476f
+
4d476f
+%%
4d476f
+
4d476f
+#include "automount.h"
4d476f
+
4d476f
+int amd_wrap(void)
4d476f
+{
4d476f
+	return 1;
4d476f
+}
4d476f
+
4d476f
+static void amd_echo(void)
4d476f
+{
4d476f
+	logmsg("%s\n", amd_text);
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+#ifdef FLEX_SCANNER
4d476f
+
4d476f
+void amd_set_scan_buffer(const char *buffer)
4d476f
+{
4d476f
+	line = buffer;
4d476f
+	line_pos = &line[0];
4d476f
+	/*
4d476f
+	 * Ensure buffer is 1 greater than string and is zeroed before
4d476f
+	 * the parse so we can fit the extra NULL which allows us to
4d476f
+	 * explicitly match an end of line within the buffer (ie. the
4d476f
+	 * need for 2 NULLS when parsing in memeory buffers).
4d476f
+	 */
4d476f
+	line_lim = line + strlen(buffer) + 1;
4d476f
+}
4d476f
+
4d476f
+#define amd_min(a,b) (((a) < (b)) ? (a) : (b))
4d476f
+
4d476f
+int amd_yyinput(char *buffer, int max_size)
4d476f
+{
4d476f
+	int n = amd_min(max_size, line_lim - line_pos);
4d476f
+
4d476f
+	if (n > 0) {
4d476f
+		memcpy(buffer, line_pos, n);
4d476f
+		line_pos += n;
4d476f
+	}
4d476f
+	return n;
4d476f
+}
4d476f
+
4d476f
+#else
4d476f
+
4d476f
+void amd_set_scan_buffer(const char *buffer)
4d476f
+{
4d476f
+	line = buffer;
4d476f
+}
4d476f
+
4d476f
+#endif
4d476f
--- /dev/null
4d476f
+++ autofs-5.0.7/modules/parse_amd.c
4d476f
@@ -0,0 +1,1081 @@
4d476f
+/* ----------------------------------------------------------------------- *
4d476f
+ *
4d476f
+ *  Copyright 2013 Ian Kent <raven@themaw.net>
4d476f
+ *  Copyright 2013 Red Hat, Inc.
4d476f
+ *  All rights reserved.
4d476f
+ *
4d476f
+ *  This program is free software; you can redistribute it and/or modify
4d476f
+ *  it under the terms of the GNU General Public License as published by
4d476f
+ *  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
4d476f
+ *  USA; either version 2 of the License, or (at your option) any later
4d476f
+ *  version; incorporated herein by reference.
4d476f
+ *
4d476f
+ * ----------------------------------------------------------------------- */
4d476f
+
4d476f
+#include <stdio.h>
4d476f
+#include <malloc.h>
4d476f
+#include <netdb.h>
4d476f
+#include <stdlib.h>
4d476f
+#include <string.h>
4d476f
+#include <ctype.h>
4d476f
+#include <limits.h>
4d476f
+#include <sys/param.h>
4d476f
+#include <sys/socket.h>
4d476f
+#include <sys/types.h>
4d476f
+#include <sys/stat.h>
4d476f
+#include <sys/vfs.h>
4d476f
+#include <sys/utsname.h>
4d476f
+#include <netinet/in.h>
4d476f
+#include <sys/mount.h>
4d476f
+#include <linux/fs.h>
4d476f
+
4d476f
+#define MODULE_PARSE
4d476f
+#include "automount.h"
4d476f
+
4d476f
+#define MODPREFIX "parse(amd): "
4d476f
+
4d476f
+int parse_version = AUTOFS_PARSE_VERSION;	/* Required by protocol */
4d476f
+
4d476f
+static struct mount_mod *mount_nfs = NULL;
4d476f
+static int init_ctr = 0;
4d476f
+static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
4d476f
+
4d476f
+static void instance_mutex_lock(void)
4d476f
+{
4d476f
+	int status = pthread_mutex_lock(&instance_mutex);
4d476f
+	if (status)
4d476f
+		fatal(status);
4d476f
+}
4d476f
+
4d476f
+static void instance_mutex_unlock(void)
4d476f
+{
4d476f
+	int status = pthread_mutex_unlock(&instance_mutex);
4d476f
+	if (status)
4d476f
+		fatal(status);
4d476f
+}
4d476f
+
4d476f
+extern const char *global_options;
4d476f
+
4d476f
+struct parse_context {
4d476f
+	char *optstr;		/* Mount options */
4d476f
+	char *macros;		/* Map wide macro defines */
4d476f
+	struct substvar *subst;	/* $-substitutions */
4d476f
+};
4d476f
+
4d476f
+struct multi_mnt {
4d476f
+	char *path;
4d476f
+	char *options;
4d476f
+	char *location;
4d476f
+	struct multi_mnt *next;
4d476f
+};
4d476f
+
4d476f
+/* Default context */
4d476f
+
4d476f
+static struct parse_context default_context = {
4d476f
+	NULL,			/* No mount options */
4d476f
+	NULL,			/* No map wide macros */
4d476f
+	NULL			/* The substvar local vars table */
4d476f
+};
4d476f
+
4d476f
+/* Free all storage associated with this context */
4d476f
+static void kill_context(struct parse_context *ctxt)
4d476f
+{
4d476f
+	macro_lock();
4d476f
+	macro_free_table(ctxt->subst);
4d476f
+	macro_unlock();
4d476f
+	if (ctxt->optstr)
4d476f
+		free(ctxt->optstr);
4d476f
+	if (ctxt->macros)
4d476f
+		free(ctxt->macros);
4d476f
+	free(ctxt);
4d476f
+}
4d476f
+
4d476f
+int parse_init(int argc, const char *const *argv, void **context)
4d476f
+{
4d476f
+	struct parse_context *ctxt;
4d476f
+	char buf[MAX_ERR_BUF];
4d476f
+
4d476f
+	sel_hash_init();
4d476f
+
4d476f
+	/* Set up context and escape chain */
4d476f
+
4d476f
+	if (!(ctxt = (struct parse_context *) malloc(sizeof(struct parse_context)))) {
4d476f
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
4d476f
+		logerr(MODPREFIX "malloc: %s", estr);
4d476f
+		*context = NULL;
4d476f
+		return 1;
4d476f
+	}
4d476f
+	*context = (void *) ctxt;
4d476f
+
4d476f
+	*ctxt = default_context;
4d476f
+
4d476f
+	/* We only need this once.  NFS mounts are so common that we cache
4d476f
+	   this module. */
4d476f
+	instance_mutex_lock();
4d476f
+	if (mount_nfs)
4d476f
+		init_ctr++;
4d476f
+	else {
4d476f
+		if ((mount_nfs = open_mount("nfs", MODPREFIX))) {
4d476f
+			init_ctr++;
4d476f
+		} else {
4d476f
+			kill_context(ctxt);
4d476f
+			*context = NULL;
4d476f
+			instance_mutex_unlock();
4d476f
+			return 1;
4d476f
+		}
4d476f
+	}
4d476f
+	instance_mutex_unlock();
4d476f
+
4d476f
+	return 0;
4d476f
+}
4d476f
+
4d476f
+static void update_with_defaults(struct amd_entry *defaults,
4d476f
+				 struct amd_entry *entry,
4d476f
+				 struct substvar *sv)
4d476f
+{
4d476f
+	const struct substvar *v;
4d476f
+	unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK;
4d476f
+	char *tmp;
4d476f
+
4d476f
+	if (fstype == AMD_MOUNT_TYPE_NONE) {
4d476f
+		unsigned long deftype = defaults->flags & AMD_MOUNT_TYPE_MASK;
4d476f
+		if (deftype != AMD_MOUNT_TYPE_NONE)
4d476f
+			entry->flags |= (defaults->flags & AMD_MOUNT_TYPE_MASK);
4d476f
+		else {
4d476f
+			entry->flags = AMD_MOUNT_TYPE_NFS;
4d476f
+			tmp = strdup("nfs");
4d476f
+			if (tmp)
4d476f
+				entry->type = tmp;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->type && defaults->type) {
4d476f
+		tmp = strdup(defaults->type);
4d476f
+		if (tmp)
4d476f
+			entry->type = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->map_type && defaults->map_type) {
4d476f
+		tmp = strdup(defaults->map_type);
4d476f
+		if (tmp)
4d476f
+			entry->map_type = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->pref && defaults->pref) {
4d476f
+		tmp = strdup(defaults->pref);
4d476f
+		if (tmp)
4d476f
+			entry->pref = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->fs && defaults->fs) {
4d476f
+		tmp = strdup(defaults->fs);
4d476f
+		if (tmp)
4d476f
+			entry->fs = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->rfs && defaults->rfs) {
4d476f
+		tmp = strdup(defaults->rfs);
4d476f
+		if (tmp)
4d476f
+			entry->rfs = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->rhost && defaults->rhost) {
4d476f
+		tmp = strdup(defaults->rhost);
4d476f
+		if (tmp)
4d476f
+			entry->rhost = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->opts && defaults->opts) {
4d476f
+		tmp = merge_options(defaults->opts, entry->opts);
4d476f
+		if (tmp)
4d476f
+			entry->opts = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->addopts && defaults->addopts) {
4d476f
+		tmp = merge_options(defaults->addopts, entry->addopts);
4d476f
+		if (tmp)
4d476f
+			entry->addopts = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (!entry->remopts && defaults->remopts) {
4d476f
+		tmp = merge_options(defaults->remopts, entry->remopts);
4d476f
+		if (tmp)
4d476f
+			entry->remopts = tmp;
4d476f
+	}
4d476f
+
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static char *normalize_hostname(unsigned int logopt, const char *host,
4d476f
+				unsigned int flags, struct substvar *sv)
4d476f
+{
4d476f
+	struct addrinfo hints, *ni;
4d476f
+	char *name;
4d476f
+	int ret;
4d476f
+
4d476f
+	if (!(flags & CONF_NORMALIZE_HOSTNAMES))
4d476f
+		name = strdup(host);
4d476f
+	else {
4d476f
+		memset(&hints, 0, sizeof(hints));
4d476f
+		hints.ai_flags = AI_CANONNAME;
4d476f
+		hints.ai_family = AF_UNSPEC;
4d476f
+		hints.ai_socktype = SOCK_DGRAM;
4d476f
+
4d476f
+		ret = getaddrinfo(host, NULL, &hints, &ni);
4d476f
+		if (ret) {
4d476f
+			error(logopt, "hostname lookup failed: %s", gai_strerror(ret));
4d476f
+			return NULL;
4d476f
+		}
4d476f
+		name = strdup(ni->ai_canonname);
4d476f
+		freeaddrinfo(ni);
4d476f
+	}
4d476f
+
4d476f
+	if (!name)
4d476f
+		return NULL;
4d476f
+
4d476f
+	if (flags & CONF_DOMAIN_STRIP) {
4d476f
+		const struct substvar *v = macro_findvar(sv, "hostd", 5);
4d476f
+		if (v) {
4d476f
+			char *d1 = strchr(name, '.');
4d476f
+			if (d1) {
4d476f
+				char *d2 = strchr(v->val, '.');
4d476f
+				if (d2 && !strcmp(d1, d2))
4d476f
+					*d1 = '\0';
4d476f
+			}
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	return name;
4d476f
+}
4d476f
+
4d476f
+static struct substvar *expand_entry(struct autofs_point *ap,
4d476f
+				     struct amd_entry *entry,
4d476f
+				     unsigned int flags,
4d476f
+				     struct substvar *sv)
4d476f
+{
4d476f
+	unsigned int logopt = ap->logopt;
4d476f
+	char *expand;
4d476f
+
4d476f
+	if (entry->rhost) {
4d476f
+		char *host = strdup(entry->rhost);
4d476f
+		char *nn;
4d476f
+		if (!host) {
4d476f
+			error(ap->logopt, MODPREFIX
4d476f
+			      "failed to allocate storage for rhost");
4d476f
+			goto next;
4d476f
+		}
4d476f
+		if (expand_selectors(ap, host, &expand, sv)) {
4d476f
+			free(host);
4d476f
+			host = expand;
4d476f
+		}
4d476f
+		nn = normalize_hostname(ap->logopt, host, flags, sv);
4d476f
+		if (!nn)
4d476f
+			sv = macro_addvar(sv, "rhost", 5, host);
4d476f
+		else {
4d476f
+			sv = macro_addvar(sv, "rhost", 5, nn);
4d476f
+			free(host);
4d476f
+			host = nn;
4d476f
+		}
4d476f
+		debug(logopt, MODPREFIX
4d476f
+		      "rhost expand(\"%s\") -> %s", entry->rhost, host);
4d476f
+		free(entry->rhost);
4d476f
+		entry->rhost = host;
4d476f
+	}
4d476f
+next:
4d476f
+	if (entry->sublink) {
4d476f
+		if (expand_selectors(ap, entry->sublink, &expand, sv)) {
4d476f
+			debug(logopt, MODPREFIX
4d476f
+			      "sublink expand(\"%s\") -> %s",
4d476f
+			      entry->sublink, expand);
4d476f
+			free(entry->sublink);
4d476f
+			entry->sublink = expand;
4d476f
+		}
4d476f
+		sv = macro_addvar(sv, "sublink", 7, entry->sublink);
4d476f
+	}
4d476f
+
4d476f
+	if (entry->rfs) {
4d476f
+		if (expand_selectors(ap, entry->rfs, &expand, sv)) {
4d476f
+			debug(logopt, MODPREFIX
4d476f
+			      "rfs expand(\"%s\") -> %s", entry->rfs, expand);
4d476f
+			free(entry->rfs);
4d476f
+			entry->rfs = expand;
4d476f
+		}
4d476f
+		sv = macro_addvar(sv, "rfs", 3, entry->rfs);
4d476f
+	}
4d476f
+
4d476f
+	if (entry->fs) {
4d476f
+		if (expand_selectors(ap, entry->fs, &expand, sv)) {
4d476f
+			debug(logopt, MODPREFIX
4d476f
+			      "fs expand(\"%s\") -> %s", entry->fs, expand);
4d476f
+			free(entry->fs);
4d476f
+			entry->fs = expand;
4d476f
+		}
4d476f
+		sv = macro_addvar(sv, "fs", 2, entry->fs);
4d476f
+	}
4d476f
+
4d476f
+	if (entry->opts) {
4d476f
+		if (expand_selectors(ap, entry->opts, &expand, sv)) {
4d476f
+			debug(logopt, MODPREFIX
4d476f
+			      "ops expand(\"%s\") -> %s", entry->opts, expand);
4d476f
+			free(entry->opts);
4d476f
+			entry->opts = expand;
4d476f
+		}
4d476f
+		sv = macro_addvar(sv, "opts", 4, entry->opts);
4d476f
+	}
4d476f
+
4d476f
+	if (entry->addopts) {
4d476f
+		if (expand_selectors(ap, entry->addopts, &expand, sv)) {
4d476f
+			debug(logopt, MODPREFIX
4d476f
+			      "addopts expand(\"%s\") -> %s",
4d476f
+			      entry->addopts, expand);
4d476f
+			free(entry->addopts);
4d476f
+			entry->addopts = expand;
4d476f
+		}
4d476f
+		sv = macro_addvar(sv, "addopts", 7, entry->addopts);
4d476f
+	}
4d476f
+
4d476f
+	if (entry->remopts) {
4d476f
+		if (expand_selectors(ap, entry->remopts, &expand, sv)) {
4d476f
+			debug(logopt, MODPREFIX
4d476f
+			      "remopts expand(\"%s\") -> %s",
4d476f
+			      entry->remopts, expand);
4d476f
+			free(entry->remopts);
4d476f
+			entry->remopts = expand;
4d476f
+		}
4d476f
+		sv = macro_addvar(sv, "remopts", 7, entry->remopts);
4d476f
+	}
4d476f
+
4d476f
+	return sv;
4d476f
+}
4d476f
+
4d476f
+static void expand_merge_options(struct autofs_point *ap,
4d476f
+				 struct amd_entry *entry,
4d476f
+				 struct substvar *sv)
4d476f
+{
4d476f
+	char *tmp;
4d476f
+
4d476f
+	if (entry->opts) {
4d476f
+		if (!expand_selectors(ap, entry->opts, &tmp, sv))
4d476f
+			error(ap->logopt, MODPREFIX "failed to expand opts");
4d476f
+		else {
4d476f
+			free(entry->opts);
4d476f
+			entry->opts = tmp;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->addopts) {
4d476f
+		if (!expand_selectors(ap, entry->addopts, &tmp, sv))
4d476f
+			error(ap->logopt, MODPREFIX "failed to expand addopts");
4d476f
+		else {
4d476f
+			free(entry->addopts);
4d476f
+			entry->addopts = tmp;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->remopts) {
4d476f
+		if (!expand_selectors(ap, entry->remopts, &tmp, sv))
4d476f
+			error(ap->logopt, MODPREFIX "failed to expand remopts");
4d476f
+		else {
4d476f
+			free(entry->remopts);
4d476f
+			entry->remopts = tmp;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static struct substvar *merge_entry_options(struct autofs_point *ap,
4d476f
+					    struct amd_entry *entry,
4d476f
+				            struct substvar *sv)
4d476f
+{
4d476f
+	char *tmp;
4d476f
+
4d476f
+	if (!entry->addopts)
4d476f
+		return sv;
4d476f
+
4d476f
+	if (entry->opts && entry->remopts &&
4d476f
+	    !strcmp(entry->opts, entry->remopts)) {
4d476f
+		expand_merge_options(ap, entry, sv);
4d476f
+		tmp = merge_options(entry->opts, entry->addopts);
4d476f
+		if (tmp) {
4d476f
+			info(ap->logopt, MODPREFIX
4d476f
+			     "merge remopts \"%s\" addopts \"%s\" => \"%s\"",
4d476f
+			      entry->opts, entry->addopts, tmp);
4d476f
+			free(entry->opts);
4d476f
+			entry->opts = tmp;
4d476f
+			sv = macro_addvar(sv, "opts", 4, entry->opts);
4d476f
+		}
4d476f
+		tmp = strdup(entry->opts);
4d476f
+		if (tmp) {
4d476f
+			free(entry->remopts);
4d476f
+			entry->remopts = tmp;
4d476f
+			sv = macro_addvar(sv, "remopts", 7, entry->remopts);
4d476f
+		}
4d476f
+		return sv;
4d476f
+	}
4d476f
+
4d476f
+	expand_merge_options(ap, entry, sv);
4d476f
+
4d476f
+	if (entry->opts && entry->addopts) {
4d476f
+		tmp = merge_options(entry->opts, entry->addopts);
4d476f
+		if (tmp) {
4d476f
+			info(ap->logopt, MODPREFIX
4d476f
+			     "merge opts \"%s\" addopts \"%s\" => \"%s\"",
4d476f
+			      entry->opts, entry->addopts, tmp);
4d476f
+			free(entry->opts);
4d476f
+			entry->opts = tmp;
4d476f
+			sv = macro_addvar(sv, "opts", 4, entry->opts);
4d476f
+		}
4d476f
+	} else if (entry->addopts) {
4d476f
+		tmp = strdup(entry->addopts);
4d476f
+		if (tmp) {
4d476f
+			info(ap->logopt, MODPREFIX
4d476f
+			     "opts add addopts \"%s\" => \"%s\"", entry->addopts, tmp);
4d476f
+			entry->opts = tmp;
4d476f
+			sv = macro_addvar(sv, "opts", 4, entry->opts);
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	expand_merge_options(ap, entry, sv);
4d476f
+
4d476f
+	if (entry->remopts && entry->addopts) {
4d476f
+		tmp = merge_options(entry->remopts, entry->addopts);
4d476f
+		if (tmp) {
4d476f
+			info(ap->logopt, MODPREFIX
4d476f
+			     "merge remopts \"%s\" addopts \"%s\" => \"%s\"",
4d476f
+			      entry->remopts, entry->addopts, tmp);
4d476f
+			free(entry->remopts);
4d476f
+			entry->remopts = tmp;
4d476f
+			sv = macro_addvar(sv, "remopts", 7, entry->remopts);
4d476f
+		}
4d476f
+	} else if (entry->addopts) {
4d476f
+		tmp = strdup(entry->addopts);
4d476f
+		if (tmp) {
4d476f
+			info(ap->logopt, MODPREFIX
4d476f
+			     "remopts add addopts \"%s\" => \"%s\"",
4d476f
+			     entry->addopts, tmp);
4d476f
+			entry->remopts = tmp;
4d476f
+			sv = macro_addvar(sv, "remopts", 7, entry->remopts);
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	return sv;
4d476f
+}
4d476f
+
4d476f
+static int do_auto_mount(struct autofs_point *ap, const char *name,
4d476f
+			 struct amd_entry *entry, unsigned int flags)
4d476f
+{
4d476f
+	char target[PATH_MAX + 1];
4d476f
+	int ret;
4d476f
+
4d476f
+	if (!entry->map_type)
4d476f
+		strcpy(target, entry->fs);
4d476f
+	else {
4d476f
+		strcpy(target, entry->map_type);
4d476f
+		strcat(target, ",amd:");
4d476f
+		strcat(target, entry->fs);
4d476f
+	}
4d476f
+
4d476f
+	ret = do_mount(ap, ap->path,
4d476f
+		       name, strlen(name), target, "autofs", NULL);
4d476f
+	if (!ret) {
4d476f
+		struct autofs_point *sm;
4d476f
+		sm = master_find_submount(ap, entry->path);
4d476f
+		if (sm) {
4d476f
+			sm->pref = entry->pref;
4d476f
+			entry->pref = NULL;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
+static int do_link_mount(struct autofs_point *ap, const char *name,
4d476f
+			 struct amd_entry *entry, unsigned int flags)
4d476f
+{
4d476f
+	char target[PATH_MAX + 1];
4d476f
+	int ret;
4d476f
+
4d476f
+	if (entry->sublink)
4d476f
+		strcpy(target, entry->sublink);
4d476f
+	else
4d476f
+		strcpy(target, entry->fs);
4d476f
+
4d476f
+	if (!(flags & CONF_AUTOFS_USE_LOFS))
4d476f
+		goto symlink;
4d476f
+
4d476f
+	/* For a sublink this might cause an external mount */
4d476f
+	ret = do_mount(ap, ap->path,
4d476f
+		       name, strlen(name), target, "bind", entry->opts);
4d476f
+	if (!ret)
4d476f
+		goto out;
4d476f
+
4d476f
+	debug(ap->logopt, MODPREFIX "bind mount failed, symlinking");
4d476f
+
4d476f
+symlink:
4d476f
+	ret = do_mount(ap, ap->path,
4d476f
+		       name, strlen(name), target, "bind", "symlink");
4d476f
+	if (!ret)
4d476f
+		goto out;
4d476f
+
4d476f
+	error(ap->logopt, MODPREFIX
4d476f
+	      "failed to symlink %s to %s", entry->path, target);
4d476f
+
4d476f
+	if (entry->sublink) {
4d476f
+		/* failed to complete sublink mount */
4d476f
+		if (ext_mount_remove(&entry->ext_mount, entry->fs))
4d476f
+			umount_ent(ap, entry->fs);
4d476f
+	}
4d476f
+out:
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
+static int do_nfs_mount(struct autofs_point *ap, const char *name,
4d476f
+			struct amd_entry *entry, unsigned int flags)
4d476f
+{
4d476f
+	char target[PATH_MAX + 1];
4d476f
+	int ret = 0;
4d476f
+
4d476f
+	strcpy(target, entry->rhost);
4d476f
+	strcat(target, ":");
4d476f
+	strcat(target, entry->rfs);
4d476f
+
4d476f
+	if (!entry->sublink) {
4d476f
+		ret = mount_nfs->mount_mount(ap, ap->path, name, strlen(name),
4d476f
+					     target, entry->type, entry->opts,
4d476f
+					     mount_nfs->context);
4d476f
+	} else {
4d476f
+		if (!is_mounted(_PATH_MOUNTED, entry->fs, MNTS_REAL)) {
4d476f
+			ret = mount_nfs->mount_mount(ap, entry->fs, "/", 1,
4d476f
+						target, entry->type, entry->opts,
4d476f
+						mount_nfs->context);
4d476f
+			if (ret)
4d476f
+				goto out;
4d476f
+		}
4d476f
+		/* We might be using an external mount */
4d476f
+		ext_mount_add(&entry->ext_mount, entry->fs);
4d476f
+		ret = do_link_mount(ap, name, entry, flags);
4d476f
+	}
4d476f
+out:
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
+static int do_host_mount(struct autofs_point *ap, const char *name,
4d476f
+			 struct amd_entry *entry, struct map_source *source,
4d476f
+			 unsigned int flags)
4d476f
+{
4d476f
+	struct lookup_mod *lookup;
4d476f
+	struct mapent *me;
4d476f
+	const char *argv[2];
4d476f
+	int ret = 1;
4d476f
+
4d476f
+	argv[0] = entry->opts;
4d476f
+	argv[1] = NULL;
4d476f
+
4d476f
+	lookup = open_lookup("hosts", MODPREFIX, NULL, 1, argv);
4d476f
+	if (!lookup) {
4d476f
+		debug(ap->logopt, "open lookup module hosts failed");
4d476f
+		goto out;
4d476f
+	}
4d476f
+
4d476f
+	me = cache_lookup_distinct(source->mc, name);
4d476f
+	if (me)
4d476f
+		cache_push_mapent(me, NULL);
4d476f
+
4d476f
+	master_source_current_wait(ap->entry);
4d476f
+	ap->entry->current = source;
4d476f
+
4d476f
+	ret = lookup->lookup_mount(ap, name, strlen(name), lookup->context);
4d476f
+
4d476f
+	close_lookup(lookup);
4d476f
+out:
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
+static int amd_mount(struct autofs_point *ap, const char *name,
4d476f
+		     struct amd_entry *entry, struct map_source *source,
4d476f
+		     struct substvar *sv, unsigned int flags,
4d476f
+		     struct parse_context *ctxt)
4d476f
+{
4d476f
+	unsigned long fstype = entry->flags & AMD_MOUNT_TYPE_MASK;
4d476f
+	int ret = 1;
4d476f
+
4d476f
+	switch (fstype) {
4d476f
+	case AMD_MOUNT_TYPE_AUTO:
4d476f
+		ret = do_auto_mount(ap, name, entry, flags);
4d476f
+		break;
4d476f
+
4d476f
+	case AMD_MOUNT_TYPE_NFS:
4d476f
+		ret = do_nfs_mount(ap, name, entry, flags);
4d476f
+		break;
4d476f
+
4d476f
+	case AMD_MOUNT_TYPE_LINK:
4d476f
+		ret = do_link_mount(ap, name, entry, flags);
4d476f
+		break;
4d476f
+
4d476f
+	case AMD_MOUNT_TYPE_HOST:
4d476f
+		ret = do_host_mount(ap, name, entry, source, flags);
4d476f
+		break;
4d476f
+
4d476f
+	default:
4d476f
+		info(ap->logopt,
4d476f
+		     MODPREFIX "unkown file system type %x", fstype);
4d476f
+		break;
4d476f
+	}
4d476f
+
4d476f
+	return ret;
4d476f
+}
4d476f
+
4d476f
+void dequote_entry(struct autofs_point *ap, struct amd_entry *entry)
4d476f
+{
4d476f
+	char *res;
4d476f
+
4d476f
+	if (entry->pref) {
4d476f
+		res = dequote(entry->pref, strlen(entry->pref), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "pref dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->pref), entry->pref, res);
4d476f
+			free(entry->pref);
4d476f
+			entry->pref = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->sublink) {
4d476f
+		res = dequote(entry->sublink, strlen(entry->sublink), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "sublink dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->sublink), entry->sublink, res);
4d476f
+			free(entry->sublink);
4d476f
+			entry->sublink = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->fs) {
4d476f
+		res = dequote(entry->fs, strlen(entry->fs), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "fs dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->fs), entry->fs, res);
4d476f
+			free(entry->fs);
4d476f
+			entry->fs = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->rfs) {
4d476f
+		res = dequote(entry->rfs, strlen(entry->rfs), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "rfs dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->rfs), entry->rfs, res);
4d476f
+			free(entry->rfs);
4d476f
+			entry->rfs = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->opts) {
4d476f
+		res = dequote(entry->opts, strlen(entry->opts), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "ops dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->opts), entry->opts, res);
4d476f
+			free(entry->opts);
4d476f
+			entry->opts = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->remopts) {
4d476f
+		res = dequote(entry->remopts, strlen(entry->remopts), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "remopts dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->remopts), entry->remopts, res);
4d476f
+			free(entry->remopts);
4d476f
+			entry->remopts = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	if (entry->addopts) {
4d476f
+		res = dequote(entry->addopts, strlen(entry->addopts), ap->logopt);
4d476f
+		if (res) {
4d476f
+			debug(ap->logopt,
4d476f
+			      MODPREFIX "addopts dequote(\"%.*s\") -> %s",
4d476f
+			      strlen(entry->addopts), entry->addopts, res);
4d476f
+			free(entry->addopts);
4d476f
+			entry->addopts = res;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static void normalize_sublink(unsigned int logopt,
4d476f
+			      struct amd_entry *entry, struct substvar *sv)
4d476f
+{
4d476f
+	char *new;
4d476f
+	size_t len;
4d476f
+
4d476f
+	if (entry->sublink && *entry->sublink != '/') {
4d476f
+		len = strlen(entry->fs) + strlen(entry->sublink) + 2;
4d476f
+		new = malloc(len);
4d476f
+		if (!new) {
4d476f
+			error(logopt, MODPREFIX
4d476f
+			      "error: couldn't allocate storage for sublink");
4d476f
+			return;
4d476f
+		}
4d476f
+		strcpy(new, entry->fs);
4d476f
+		strcat(new, "/");
4d476f
+		strcat(new, entry->sublink);
4d476f
+		debug(logopt, MODPREFIX
4d476f
+		      "rfs dequote(\"%.*s\") -> %s",
4d476f
+		      strlen(entry->sublink), entry->sublink, new);
4d476f
+		free(entry->sublink);
4d476f
+		entry->sublink = new;
4d476f
+	}
4d476f
+	return;
4d476f
+}
4d476f
+
4d476f
+static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults)
4d476f
+{
4d476f
+	struct amd_entry *entry;
4d476f
+	char *tmp;
4d476f
+
4d476f
+	entry = malloc(sizeof(struct amd_entry));
4d476f
+	if (!entry)
4d476f
+		return NULL;
4d476f
+	memset(entry, 0, sizeof(struct amd_entry));
4d476f
+
4d476f
+	entry->flags = defaults->flags;
4d476f
+
4d476f
+	if (defaults->type) {
4d476f
+		tmp = strdup(defaults->type);
4d476f
+		if (tmp)
4d476f
+			entry->type = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->map_type) {
4d476f
+		tmp = strdup(defaults->map_type);
4d476f
+		if (tmp)
4d476f
+			entry->map_type = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->pref) {
4d476f
+		tmp = strdup(defaults->pref);
4d476f
+		if (tmp)
4d476f
+			entry->pref = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->fs) {
4d476f
+		tmp = strdup(defaults->fs);
4d476f
+		if (tmp)
4d476f
+			entry->fs = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->rfs) {
4d476f
+		tmp = strdup(defaults->rfs);
4d476f
+		if (tmp)
4d476f
+			entry->rfs = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->rhost) {
4d476f
+		tmp = strdup(defaults->rhost);
4d476f
+		if (tmp)
4d476f
+			entry->rhost = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->opts) {
4d476f
+		tmp = strdup(defaults->opts);
4d476f
+		if (tmp)
4d476f
+			entry->opts = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->addopts) {
4d476f
+		tmp = strdup(defaults->addopts);
4d476f
+		if (tmp)
4d476f
+			entry->addopts = tmp;
4d476f
+	}
4d476f
+
4d476f
+	if (defaults->remopts) {
4d476f
+		tmp = strdup(defaults->remopts);
4d476f
+		if (tmp)
4d476f
+			entry->remopts = tmp;
4d476f
+	}
4d476f
+
4d476f
+	INIT_LIST_HEAD(&entry->list);
4d476f
+
4d476f
+	return entry;
4d476f
+}
4d476f
+
4d476f
+struct amd_entry *make_default_entry(struct autofs_point *ap,
4d476f
+				     struct substvar *sv)
4d476f
+{
4d476f
+	char *defaults = "opts:=rw,defaults";
4d476f
+	struct amd_entry *defaults_entry;
4d476f
+	struct list_head dflts;
4d476f
+
4d476f
+	INIT_LIST_HEAD(&dflts);
4d476f
+	if (amd_parse_list(ap, defaults, &dflts, &sv))
4d476f
+		return NULL;
4d476f
+	defaults_entry = list_entry(dflts.next, struct amd_entry, list);
4d476f
+	list_del_init(&defaults_entry->list);
4d476f
+	/* The list should now be empty .... */
4d476f
+	free_amd_entry_list(&dflts);
4d476f
+	return defaults_entry;
4d476f
+}
4d476f
+
4d476f
+static struct amd_entry *select_default_entry(struct autofs_point *ap,
4d476f
+					      struct list_head *entries,
4d476f
+					      struct substvar *sv)
4d476f
+{
4d476f
+	unsigned long flags = conf_amd_get_flags(ap->path);
4d476f
+	struct amd_entry *defaults_entry = NULL;
4d476f
+	struct amd_entry *entry_default = NULL;
4d476f
+	struct list_head *p, *head;
4d476f
+
4d476f
+	if (!(flags & CONF_SELECTORS_IN_DEFAULTS))
4d476f
+		goto no_sel;
4d476f
+
4d476f
+	head = entries;
4d476f
+	p = head->next;
4d476f
+	while (p != head) {
4d476f
+		struct amd_entry *this = list_entry(p, struct amd_entry, list);
4d476f
+
4d476f
+		p = p->next;
4d476f
+
4d476f
+		if (this->flags & AMD_DEFAULTS_MERGE) {
4d476f
+			if (entry_default)
4d476f
+				free_amd_entry(entry_default);
4d476f
+			list_del_init(&this->list);
4d476f
+			entry_default = this;
4d476f
+			continue;
4d476f
+		} else if (this->flags & AMD_DEFAULTS_RESET) {
4d476f
+			struct amd_entry *new;
4d476f
+			new = dup_defaults_entry(defaults_entry);
4d476f
+			if (new) {
4d476f
+				free_amd_entry(entry_default);
4d476f
+				entry_default = new;
4d476f
+			}
4d476f
+			list_del_init(&this->list);
4d476f
+			free_amd_entry(this);
4d476f
+			continue;
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	/* Not strickly amd semantics but ... */
4d476f
+	if (!defaults_entry && entry_default) {
4d476f
+		defaults_entry = entry_default;
4d476f
+		goto done;
4d476f
+	}
4d476f
+
4d476f
+	if (!defaults_entry) {
4d476f
+		debug(ap->logopt, MODPREFIX
4d476f
+		      "no matching selector(s) found in defaults, "
4d476f
+		      "using internal defaults");
4d476f
+		goto ret_default;
4d476f
+	}
4d476f
+
4d476f
+	goto done;
4d476f
+
4d476f
+no_sel:
4d476f
+	if (list_empty(entries))
4d476f
+		goto ret_default;
4d476f
+
4d476f
+	defaults_entry = list_entry(entries->next, struct amd_entry, list);
4d476f
+	list_del_init(&defaults_entry->list);
4d476f
+	if (!list_empty(entries)) {
4d476f
+		free_amd_entry(defaults_entry);
4d476f
+		goto ret_default;
4d476f
+	}
4d476f
+done:
4d476f
+	/*merge_entry_options(ap, defaults_entry, sv);*/
4d476f
+	/*normalize_sublink(ap->logopt, defaults_entry, sv);*/
4d476f
+	return defaults_entry;
4d476f
+
4d476f
+ret_default:
4d476f
+	return make_default_entry(ap, sv);
4d476f
+}
4d476f
+
4d476f
+static struct amd_entry *get_defaults_entry(struct autofs_point *ap,
4d476f
+					    const char *defaults,
4d476f
+					    struct substvar *sv)
4d476f
+{
4d476f
+	struct amd_entry *entry;
4d476f
+	struct list_head dflts;
4d476f
+
4d476f
+	INIT_LIST_HEAD(&dflts);
4d476f
+
4d476f
+	entry = NULL;
4d476f
+	if (!defaults)
4d476f
+		goto out;
4d476f
+	else {
4d476f
+		char *expand;
4d476f
+		if (!expand_selectors(ap, defaults, &expand, sv))
4d476f
+			goto out;
4d476f
+		if (amd_parse_list(ap, expand, &dflts, &sv))
4d476f
+			goto out;
4d476f
+		entry = select_default_entry(ap, &dflts, sv);
4d476f
+		free(expand);
4d476f
+	}
4d476f
+
4d476f
+	return entry;
4d476f
+out:
4d476f
+	return make_default_entry(ap, sv);
4d476f
+}
4d476f
+
4d476f
+int parse_mount(struct autofs_point *ap, const char *name,
4d476f
+		int name_len, const char *mapent, void *context)
4d476f
+{
4d476f
+	struct parse_context *ctxt = (struct parse_context *) context;
4d476f
+	unsigned int flags = conf_amd_get_flags(ap->path);
4d476f
+	struct substvar *sv = NULL;
4d476f
+	struct map_source *source;
4d476f
+	struct mapent_cache *mc;
4d476f
+	struct mapent *me;
4d476f
+	struct list_head entries, *p, *head;
4d476f
+	struct amd_entry *defaults_entry;
4d476f
+	struct amd_entry *cur_defaults;
4d476f
+	char *defaults;
4d476f
+	char *pmapent;
4d476f
+	int len, rv = 1;
4d476f
+	int cur_state;
4d476f
+	int ret;
4d476f
+
4d476f
+	source = ap->entry->current;
4d476f
+	ap->entry->current = NULL;
4d476f
+	master_source_current_signal(ap->entry);
4d476f
+
4d476f
+	mc = source->mc;
4d476f
+
4d476f
+	if (!mapent) {
4d476f
+		warn(ap->logopt, MODPREFIX "error: empty map entry");
4d476f
+		return 1;
4d476f
+	}
4d476f
+
4d476f
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
4d476f
+
4d476f
+	len = expand_selectors(ap, mapent, &pmapent, sv);
4d476f
+	if (!len) {
4d476f
+		macro_free_table(sv);
4d476f
+		pthread_setcancelstate(cur_state, NULL);
4d476f
+		return 1;
4d476f
+	}
4d476f
+
4d476f
+	pthread_setcancelstate(cur_state, NULL);
4d476f
+
4d476f
+	debug(ap->logopt, MODPREFIX "expanded mapent: %s", pmapent);
4d476f
+
4d476f
+	defaults = conf_amd_get_map_defaults(ap->path);
4d476f
+	if (defaults) {
4d476f
+		debug(ap->logopt, MODPREFIX
4d476f
+		      "using map_defaults %s for %s", defaults, ap->path);
4d476f
+	} else if ((me = cache_lookup_distinct(mc, "/defaults"))) {
4d476f
+		defaults = strdup(me->mapent);
4d476f
+		if (defaults)
4d476f
+			debug(ap->logopt, MODPREFIX
4d476f
+			      "using /defaults %s from map", defaults);
4d476f
+		else {
4d476f
+			char buf[MAX_ERR_BUF];
4d476f
+			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
4d476f
+			error(ap->logopt, MODPREFIX "malloc: %s", estr);
4d476f
+		}
4d476f
+	}
4d476f
+
4d476f
+	defaults_entry = get_defaults_entry(ap, defaults, sv);
4d476f
+	if (!defaults_entry) {
4d476f
+		error(ap->logopt, MODPREFIX "failed to get a defaults entry");
4d476f
+		if (defaults)
4d476f
+			free(defaults);
4d476f
+		free(pmapent);
4d476f
+		macro_free_table(sv);
4d476f
+		return 1;
4d476f
+	}
4d476f
+	if (defaults)
4d476f
+		free(defaults);
4d476f
+
4d476f
+	INIT_LIST_HEAD(&entries);
4d476f
+
4d476f
+	ret = amd_parse_list(ap, pmapent, &entries, &sv;;
4d476f
+	if (ret) {
4d476f
+		error(ap->logopt,
4d476f
+		      MODPREFIX "failed to parse entry: %s", pmapent);
4d476f
+		free(pmapent);
4d476f
+		goto done;
4d476f
+	}
4d476f
+
4d476f
+	free(pmapent);
4d476f
+
4d476f
+	if (list_empty(&entries)) {
4d476f
+		error(ap->logopt, MODPREFIX "no location found after parse");
4d476f
+		goto done;
4d476f
+	}
4d476f
+
4d476f
+	cur_defaults = dup_defaults_entry(defaults_entry);
4d476f
+	if (!cur_defaults) {
4d476f
+		error(ap->logopt, MODPREFIX
4d476f
+		      "failed to duplicate defaults entry");
4d476f
+		goto done;
4d476f
+	}
4d476f
+
4d476f
+	head = &entries;
4d476f
+	p = head->next;
4d476f
+	while (p != head) {
4d476f
+		struct amd_entry *this = list_entry(p, struct amd_entry, list);
4d476f
+		p = p->next;
4d476f
+
4d476f
+		if (this->flags & AMD_DEFAULTS_MERGE) {
4d476f
+			free_amd_entry(cur_defaults);
4d476f
+			list_del_init(&this->list);
4d476f
+			cur_defaults = this;
4d476f
+			continue;
4d476f
+		} else if (this->flags & AMD_DEFAULTS_RESET) {
4d476f
+			struct amd_entry *new;
4d476f
+			new = dup_defaults_entry(defaults_entry);
4d476f
+			if (new) {
4d476f
+				free_amd_entry(cur_defaults);
4d476f
+				cur_defaults = new;
4d476f
+			}
4d476f
+			list_del_init(&this->list);
4d476f
+			free_amd_entry(this);
4d476f
+			continue;
4d476f
+		}
4d476f
+
4d476f
+		update_with_defaults(cur_defaults, this, sv);
4d476f
+		sv = expand_entry(ap, this, flags, sv);
4d476f
+		sv = merge_entry_options(ap, this, sv);
4d476f
+		normalize_sublink(ap->logopt, this, sv);
4d476f
+
4d476f
+		dequote_entry(ap, this);
4d476f
+
4d476f
+		rv = amd_mount(ap, name, this, source, sv, flags, ctxt);
4d476f
+		if (!rv)
4d476f
+			break;
4d476f
+	}
4d476f
+	free_amd_entry(cur_defaults);
4d476f
+
4d476f
+	if (rv)
4d476f
+		debug(ap->logopt, "no more locations to try, returning fail");
4d476f
+done:
4d476f
+	free_amd_entry_list(&entries);
4d476f
+	free_amd_entry(defaults_entry);
4d476f
+	macro_free_table(sv);
4d476f
+
4d476f
+	return rv;
4d476f
+}
4d476f
+
4d476f
+int parse_done(void *context)
4d476f
+{
4d476f
+	int rv = 0;
4d476f
+	struct parse_context *ctxt = (struct parse_context *) context;
4d476f
+
4d476f
+	instance_mutex_lock();
4d476f
+	if (--init_ctr == 0) {
4d476f
+		rv = close_mount(mount_nfs);
4d476f
+		mount_nfs = NULL;
4d476f
+	}
4d476f
+	instance_mutex_unlock();
4d476f
+	if (ctxt)
4d476f
+		kill_context(ctxt);
4d476f
+
4d476f
+	return rv;
4d476f
+}