diff --git a/daemon/lookup.c b/daemon/lookup.c
index 06fcecc..70b9e02 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -456,8 +456,12 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
}
if (map->type) {
- debug(ap->logopt,
- "reading map %s %s", map->type, map->argv[0]);
+ if (!strncmp(map->type, "multi", 5))
+ debug(ap->logopt, "reading multi map");
+ else
+ debug(ap->logopt,
+ "reading map %s %s",
+ map->type, map->argv[0]);
result = do_read_map(ap, map, age);
map = map->next;
continue;
diff --git a/include/automount.h b/include/automount.h
index 85e6e9c..106ed0a 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -192,6 +192,7 @@ char *cache_get_offset(const char *prefix, char *offset, int start, struct list_
/* Utility functions */
char **add_argv(int argc, char **argv, char *str);
+char **append_argv(int argc1, char **argv1, int argc2, char **argv2);
const char **copy_argv(int argc, const char **argv);
int compare_argv(int argc1, const char **argv1, int argc2, const char **argv2);
int free_argv(int argc, const char **argv);
diff --git a/lib/args.c b/lib/args.c
index 9e35388..fbfb004 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -62,6 +62,45 @@ char **add_argv(int argc, char **argv, char *str)
return vector;
}
+char **append_argv(int argc1, char **argv1, int argc2, char **argv2)
+{
+ char **vector;
+ size_t vector_size;
+ int len, i, j;
+
+ len = argc1 + argc2;
+ vector_size = (len + 1) * sizeof(char *);
+ vector = (char **) realloc(argv1, vector_size);
+ if (!vector) {
+ free_argv(argc1, (const char **) argv1);
+ free_argv(argc2, (const char **) argv2);
+ return NULL;
+ }
+
+ for (i = argc1, j = 0; i <= len; i++, j++) {
+ if (argv2[j]) {
+ vector[i] = strdup(argv2[j]);
+ if (!vector[i]) {
+ error(LOGOPT_ANY, "failed to strdup arg");
+ break;
+ }
+ } else
+ vector[i] = NULL;
+ }
+
+ if (i < len) {
+ free_argv(len, (const char **) vector);
+ free_argv(argc2, (const char **) argv2);
+ return NULL;
+ }
+
+ vector[len] = NULL;
+
+ free_argv(argc2, (const char **) argv2);
+
+ return vector;
+}
+
const char **copy_argv(int argc, const char **argv)
{
char **vector;
diff --git a/lib/master_parse.y b/lib/master_parse.y
index 8d2be02..f9cba05 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -22,6 +22,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <ctype.h>
#include <sys/ioctl.h>
#include "automount.h"
@@ -44,6 +45,7 @@ extern void master_set_scan_buffer(const char *);
static char *master_strdup(char *);
static void local_init_vars(void);
static void local_free_vars(void);
+static int add_multi_mapstr(void);
static int master_error(const char *s);
static int master_notify(const char *s);
@@ -53,6 +55,8 @@ static char *type;
static char *format;
static long timeout;
static unsigned ghost;
+static char **tmp_argv;
+static int tmp_argc;
static char **local_argv;
static int local_argc;
@@ -89,7 +93,7 @@ static int master_fprintf(FILE *, char *, ...);
%token COMMENT
%token MAP
%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG
-%token COLON COMMA NL
+%token COLON COMMA NL DDASH
%type <strtype> map
%type <strtype> options
%type <strtype> dn
@@ -103,6 +107,7 @@ static int master_fprintf(FILE *, char *, ...);
%token <strtype> NILL
%token <strtype> SPACE
%token <strtype> EQUAL
+%token <strtype> MULTITYPE
%token <strtype> MAPTYPE
%token <strtype> DNSERVER
%token <strtype> DNATTR
@@ -126,7 +131,7 @@ file: {
;
line:
- | PATH map
+ | PATH mapspec
{
path = master_strdup($1);
if (!path) {
@@ -134,14 +139,49 @@ line:
YYABORT;
}
}
- | PATH map options
+ | PATH MULTITYPE maplist
{
+ char *tmp;
+
+ tmp = strchr($2, ':');
+ if (tmp)
+ *tmp = '\0';
+ else {
+ int len = strlen($2);
+ while (len-- && isblank($2[len]))
+ $2[len] = '\0';
+ if (len < 4) {
+ master_notify($2);
+ local_free_vars();
+ YYABORT;
+ }
+ }
+
path = master_strdup($1);
if (!path) {
+ master_error("memory allocation error");
local_free_vars();
YYABORT;
}
- }
+
+ if ((tmp = strchr($2, ',')))
+ *tmp++ = '\0';
+
+ type = master_strdup($2);
+ if (!type) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ if (tmp) {
+ format = master_strdup(tmp);
+ if (!format) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ }
| PATH COLON { master_notify($1); YYABORT; }
| PATH OPTION { master_notify($2); YYABORT; }
| PATH NILL { master_notify($2); YYABORT; }
@@ -157,25 +197,89 @@ line:
| COMMENT { YYABORT; }
;
-map: PATH
+mapspec: map
+ {
+ local_argc = tmp_argc;
+ local_argv = tmp_argv;
+ tmp_argc = 0;
+ tmp_argv = NULL;
+ }
+ | map options
+ {
+ local_argc = tmp_argc;
+ local_argv = tmp_argv;
+ tmp_argc = 0;
+ tmp_argv = NULL;
+ }
+ ;
+
+maplist: map
+ {
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | map options
+ {
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | maplist DDASH map
{
local_argc++;
- local_argv = add_argv(local_argc, local_argv, $1);
+ local_argv = add_argv(local_argc, local_argv, "--");
if (!local_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
}
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
}
- | MAPNAME
+ | maplist DDASH map options
{
local_argc++;
- local_argv = add_argv(local_argc, local_argv, $1);
+ local_argv = add_argv(local_argc, local_argv, "--");
if (!local_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
}
+ if (!add_multi_mapstr()) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ ;
+
+map: PATH
+ {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
+ }
+ | MAPNAME
+ {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
+ master_error("memory allocation error");
+ local_free_vars();
+ YYABORT;
+ }
}
| MAPHOSTS
{
@@ -200,9 +304,9 @@ map: PATH
local_free_vars();
YYABORT;
}
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, $1);
- if (!local_argv) {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
@@ -227,9 +331,9 @@ map: PATH
YYABORT;
}
}
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, $3);
- if (!local_argv) {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+ if (!tmp_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
@@ -254,9 +358,9 @@ map: PATH
YYABORT;
}
}
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, $3);
- if (!local_argv) {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+ if (!tmp_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
@@ -281,25 +385,25 @@ map: PATH
YYABORT;
}
}
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, $3);
- if (!local_argv) {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $3);
+ if (!tmp_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
}
/* Add back the type for lookup_ldap.c to handle ldaps */
- if (*local_argv[0]) {
- tmp = malloc(strlen(type) + strlen(local_argv[0]) + 2);
+ if (*tmp_argv[0]) {
+ tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2);
if (!tmp) {
local_free_vars();
YYABORT;
}
strcpy(tmp, type);
strcat(tmp, ":");
- strcat(tmp, local_argv[0]);
- free(local_argv[0]);
- local_argv[0] = tmp;
+ strcat(tmp, tmp_argv[0]);
+ free(tmp_argv[0]);
+ tmp_argv[0] = tmp;
}
}
;
@@ -441,9 +545,9 @@ daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; }
mount_option: OPTION
{
- local_argc++;
- local_argv = add_argv(local_argc, local_argv, $1);
- if (!local_argv) {
+ tmp_argc++;
+ tmp_argv = add_argv(tmp_argc, tmp_argv, $1);
+ if (!tmp_argv) {
master_error("memory allocation error");
local_free_vars();
YYABORT;
@@ -494,6 +598,8 @@ static void local_init_vars(void)
debug = 0;
timeout = -1;
ghost = defaults_get_browse_mode();
+ tmp_argv = NULL;
+ tmp_argc = 0;
local_argv = NULL;
local_argc = 0;
}
@@ -509,8 +615,62 @@ static void local_free_vars(void)
if (format)
free(format);
- if (local_argv)
+ if (local_argv) {
free_argv(local_argc, (const char **) local_argv);
+ local_argv = NULL;
+ local_argc = 0;
+ }
+
+ if (tmp_argv) {
+ free_argv(tmp_argc, (const char **) tmp_argv);
+ tmp_argv = NULL;
+ tmp_argc = 0;
+ }
+}
+
+static int add_multi_mapstr(void)
+{
+ /* We need the individual map types for a multi map */
+ if (!type) {
+ if (tmp_argc > 0 && *tmp_argv[0] == '/')
+ type = strdup("file");
+ else
+ return 0;
+ }
+
+ if (format) {
+ char *tmp = realloc(type, strlen(type) + strlen(format) + 2);
+ if (!tmp)
+ return 0;
+ type = tmp;
+ strcat(type, ",");
+ strcat(type, format);
+ free(format);
+ format = NULL;
+ }
+
+ local_argc++;
+ local_argv = add_argv(local_argc, local_argv, type);
+ if (!local_argv) {
+ free(type);
+ type = NULL;
+ return 0;
+ }
+
+ local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv);
+ if (!local_argv) {
+ free(type);
+ type = NULL;
+ return 0;
+ }
+ local_argc += tmp_argc;
+
+ tmp_argc = 0;
+ tmp_argv = NULL;
+ free(type);
+ type = NULL;
+
+ return 1;
}
void master_init_scan(void)
diff --git a/lib/master_tok.l b/lib/master_tok.l
index ee2a4eb..0548de1 100644
--- a/lib/master_tok.l
+++ b/lib/master_tok.l
@@ -27,6 +27,7 @@ static void master_echo(void); /* forward definition */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include "master_parse.tab.h"
/*
@@ -110,7 +111,9 @@ DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}
DNNAMESTR ([[:alnum:]_.\-]+)
INTMAP (-hosts|-null)
-MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?)
+MULTI ((multi)(,(sun|hesiod))?[\:]?{OPTWS})
+MULTISEP ([\-]{2}[[:blank:]]+)
+MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?)
OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
@@ -184,11 +187,18 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
<MAPSTR>{
{OPTWS}\\\n{OPTWS} {}
+ {MULTI} {
+ strcpy(master_lval.strtype, master_text);
+ return(MULTITYPE);
+ }
+
{MTYPE}/":" {
strcpy(master_lval.strtype, master_text);
return(MAPTYPE);
}
+ {MULTISEP} { return(DDASH); }
+
":" { return(COLON); }
"-hosts" {
@@ -298,6 +308,11 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
<OPTSTR>{
{OPTWS}\\\n{OPTWS} {}
+ {MULTISEP} {
+ BEGIN(MAPSTR);
+ return(DDASH);
+ }
+
{OPTTOUT} { return(OPT_TIMEOUT); }
{NUMBER} {
diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c
index 00ab28e..38ca36c 100644
--- a/modules/lookup_multi.c
+++ b/modules/lookup_multi.c
@@ -45,7 +45,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
struct lookup_context *ctxt;
char buf[MAX_ERR_BUF];
char *map, *mapfmt;
- int i, j, an;
+ int i, an;
char *estr;
ctxt = malloc(sizeof(struct lookup_context));
@@ -73,7 +73,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
memcpy(ctxt->argl, argv, (argc + 1) * sizeof(const char *));
- for (i = j = an = 0; ctxt->argl[an]; an++) {
+ for (i = an = 0; ctxt->argl[an]; an++) {
if (ctxt->m[i].argc == 0) {
ctxt->m[i].argv = &ctxt->argl[an];
}
@@ -100,9 +100,12 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void *
if (!(ctxt->m[i].mod = open_lookup(map, MODPREFIX,
mapfmt ? mapfmt : my_mapfmt,
ctxt->m[i].argc - 1,
- ctxt->m[i].argv + 1)))
+ ctxt->m[i].argv + 1))) {
error(LOGOPT_ANY, MODPREFIX "error opening module");
+ free(map);
goto error_out;
+ }
+ free(map);
}
*context = ctxt;