diff --git a/lib/master_parse.y b/lib/master_parse.y index f9cba05..ab2895d 100644 --- a/lib/master_parse.y +++ b/lib/master_parse.y @@ -45,6 +45,7 @@ extern void master_set_scan_buffer(const char *); static char *master_strdup(char *); static void local_init_vars(void); static void local_free_vars(void); +static void trim_maptype(char *); static int add_multi_mapstr(void); static int master_error(const char *s); @@ -141,21 +142,9 @@ line: } | PATH MULTITYPE maplist { - char *tmp; - - tmp = strchr($2, ':'); - if (tmp) - *tmp = '\0'; - else { - int len = strlen($2); - while (len-- && isblank($2[len])) - $2[len] = '\0'; - if (len < 4) { - master_notify($2); - local_free_vars(); - YYABORT; - } - } + char *tmp = NULL; + + trim_maptype($2); path = master_strdup($1); if (!path) { @@ -312,81 +301,93 @@ map: PATH YYABORT; } } - | MAPTYPE COLON PATH + | MAPTYPE PATH { char *tmp = NULL; + trim_maptype($1); + if ((tmp = strchr($1, ','))) *tmp++ = '\0'; type = master_strdup($1); if (!type) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } if (tmp) { format = master_strdup(tmp); if (!format) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } } tmp_argc++; - tmp_argv = add_argv(tmp_argc, tmp_argv, $3); + tmp_argv = add_argv(tmp_argc, tmp_argv, $2); if (!tmp_argv) { master_error("memory allocation error"); local_free_vars(); YYABORT; } } - | MAPTYPE COLON MAPNAME + | MAPTYPE MAPNAME { char *tmp = NULL; + trim_maptype($1); + if ((tmp = strchr($1, ','))) *tmp++ = '\0'; type = master_strdup($1); if (!type) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } if (tmp) { format = master_strdup(tmp); if (!format) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } } tmp_argc++; - tmp_argv = add_argv(tmp_argc, tmp_argv, $3); + tmp_argv = add_argv(tmp_argc, tmp_argv, $2); if (!tmp_argv) { master_error("memory allocation error"); local_free_vars(); YYABORT; } } - | MAPTYPE COLON dn + | MAPTYPE dn { char *tmp = NULL; + trim_maptype($1); + if ((tmp = strchr($1, ','))) *tmp++ = '\0'; type = master_strdup($1); if (!type) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } if (tmp) { format = master_strdup(tmp); if (!format) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } } tmp_argc++; - tmp_argv = add_argv(tmp_argc, tmp_argv, $3); + tmp_argv = add_argv(tmp_argc, tmp_argv, $2); if (!tmp_argv) { master_error("memory allocation error"); local_free_vars(); @@ -396,6 +397,7 @@ map: PATH if (*tmp_argv[0]) { tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2); if (!tmp) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } @@ -628,33 +630,47 @@ static void local_free_vars(void) } } -static int add_multi_mapstr(void) +static void trim_maptype(char *type) { - /* We need the individual map types for a multi map */ - if (!type) { - if (tmp_argc > 0 && *tmp_argv[0] == '/') - type = strdup("file"); - else - return 0; + char *tmp; + + tmp = strchr(type, ':'); + if (tmp) + *tmp = '\0'; + else { + int len = strlen(type); + while (len-- && isblank(type[len])) + type[len] = '\0'; } + return; +} + +static int add_multi_mapstr(void) +{ + if (type) { + /* If type given and format is non-null add it back */ + if (format) { + int len = strlen(type) + strlen(format) + 2; + char *tmp = realloc(type, len); + if (!tmp) + return 0; + type = tmp; + strcat(type, ","); + strcat(type, format); + free(format); + format = NULL; + } - if (format) { - char *tmp = realloc(type, strlen(type) + strlen(format) + 2); - if (!tmp) + local_argc++; + local_argv = add_argv(local_argc, local_argv, type); + if (!local_argv) { + free(type); + type = NULL; return 0; - type = tmp; - strcat(type, ","); - strcat(type, format); - free(format); - format = NULL; - } + } - local_argc++; - local_argv = add_argv(local_argc, local_argv, type); - if (!local_argv) { free(type); type = NULL; - return 0; } local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv); @@ -667,8 +683,6 @@ static int add_multi_mapstr(void) tmp_argc = 0; tmp_argv = NULL; - free(type); - type = NULL; return 1; } diff --git a/lib/master_tok.l b/lib/master_tok.l index 0548de1..9bfeefa 100644 --- a/lib/master_tok.l +++ b/lib/master_tok.l @@ -111,9 +111,9 @@ DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} DNNAMESTR ([[:alnum:]_.\-]+) INTMAP (-hosts|-null) -MULTI ((multi)(,(sun|hesiod))?[\:]?{OPTWS}) +MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) MULTISEP ([\-]{2}[[:blank:]]+) -MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?) +MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?(:{OPTWS}|{WS})) OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) @@ -192,7 +192,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) return(MULTITYPE); } - {MTYPE}/":" { + {MTYPE} { strcpy(master_lval.strtype, master_text); return(MAPTYPE); } diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c index 38ca36c..8fa94ae 100644 --- a/modules/lookup_multi.c +++ b/modules/lookup_multi.c @@ -19,6 +19,7 @@ #include #include #include +#include #define MODULE_LOOKUP #include "automount.h" @@ -28,7 +29,7 @@ struct module_info { int argc; - const char *const *argv; + const char **argv; struct lookup_mod *mod; }; @@ -40,11 +41,105 @@ struct lookup_context { int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ +static struct lookup_mod *nss_open_lookup(const char *format, int argc, const char **argv) +{ + struct list_head nsslist; + struct list_head *head, *p; + struct lookup_mod *mod; + char buf[MAX_ERR_BUF], *estr; + + if (!argv || !argv[0]) + return NULL; + + if (*argv[0] == '/') + return open_lookup("file", MODPREFIX, format, argc, argv); + + if (!strncmp(argv[0], "file", 4) || + !strncmp(argv[0], "yp", 2) || + !strncmp(argv[0], "nisplus", 7) || + !strncmp(argv[0], "nis", 3) || + !strncmp(argv[0], "ldaps", 5) || + !strncmp(argv[0], "ldap", 4)) { + const char *fmt = strchr(argv[0], ','); + if (fmt) + fmt++; + else + fmt = format; + return open_lookup(argv[0], MODPREFIX, fmt, argc -1, argv + 1); + } + + INIT_LIST_HEAD(&nsslist); + + if (nsswitch_parse(&nsslist)) { + if (!list_empty(&nsslist)) + free_sources(&nsslist); + error(LOGOPT_ANY, "can't to read name service switch config."); + return NULL; + } + + head = &nsslist; + list_for_each(p, head) { + struct nss_source *this; + + this = list_entry(p, struct nss_source, list); + + if (!strcmp(this->source, "files")) { + char src_file[] = "file"; + char src_prog[] = "program"; + struct stat st; + char *type, *path, *save_argv0; + + path = malloc(strlen(AUTOFS_MAP_DIR) + strlen(argv[0]) + 2); + if (!path) { + estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(LOGOPT_ANY, MODPREFIX "error: %s", estr); + free_sources(&nsslist); + return NULL; + } + strcpy(path, AUTOFS_MAP_DIR); + strcat(path, "/"); + strcat(path, argv[0]); + + if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { + free(path); + continue; + } + + if (st.st_mode & __S_IEXEC) + type = src_prog; + else + type = src_file; + + save_argv0 = (char *) argv[0]; + argv[0] = path; + + mod = open_lookup(type, MODPREFIX, format, argc, argv); + if (mod) { + free_sources(&nsslist); + free(save_argv0); + return mod; + } + + argv[0] = save_argv0; + free(path); + } + + mod = open_lookup(this->source, MODPREFIX, format, argc, argv); + if (mod) { + free_sources(&nsslist); + return mod; + } + } + free_sources(&nsslist); + + return NULL; +} + int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void **context) { struct lookup_context *ctxt; char buf[MAX_ERR_BUF]; - char *map, *mapfmt; + char **args; int i, an; char *estr; @@ -73,39 +168,42 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void * memcpy(ctxt->argl, argv, (argc + 1) * sizeof(const char *)); + args = NULL; for (i = an = 0; ctxt->argl[an]; an++) { if (ctxt->m[i].argc == 0) { - ctxt->m[i].argv = &ctxt->argl[an]; + args = (char **) &ctxt->argl[an]; } if (!strcmp(ctxt->argl[an], "--")) { ctxt->argl[an] = NULL; + if (!args) { + crit(LOGOPT_ANY, + MODPREFIX "error assigning map args"); + goto error_out; + } + ctxt->m[i].argv = copy_argv(ctxt->m[i].argc, (const char **) args); + if (!ctxt->m[i].argv) + goto nomem; + args = NULL; i++; } else { ctxt->m[i].argc++; } } - for (i = 0; i < ctxt->n; i++) { - if (!ctxt->m[i].argv[0]) { - crit(LOGOPT_ANY, MODPREFIX "missing module name"); - goto error_out; - } - map = strdup(ctxt->m[i].argv[0]); - if (!map) + /* catch the last one */ + if (args) { + ctxt->m[i].argv = copy_argv(ctxt->m[i].argc, (const char **) args); + if (!ctxt->m[i].argv) goto nomem; + } - if ((mapfmt = strchr(map, ','))) - *(mapfmt++) = '\0'; - - if (!(ctxt->m[i].mod = open_lookup(map, MODPREFIX, - mapfmt ? mapfmt : my_mapfmt, - ctxt->m[i].argc - 1, - ctxt->m[i].argv + 1))) { + for (i = 0; i < ctxt->n; i++) { + ctxt->m[i].mod = nss_open_lookup(my_mapfmt, + ctxt->m[i].argc, ctxt->m[i].argv); + if (!ctxt->m[i].mod) { error(LOGOPT_ANY, MODPREFIX "error opening module"); - free(map); goto error_out; } - free(map); } *context = ctxt; @@ -116,9 +214,12 @@ nomem: crit(LOGOPT_ANY, MODPREFIX "error: %s", estr); error_out: if (ctxt) { - for (i = 0; i < ctxt->n; i++) + for (i = 0; i < ctxt->n; i++) { if (ctxt->m[i].mod) close_lookup(ctxt->m[i].mod); + if (ctxt->m[i].argv) + free_argv(ctxt->m[i].argc, ctxt->m[i].argv); + } if (ctxt->m) free(ctxt->m); if (ctxt->argl) @@ -188,6 +289,8 @@ int lookup_done(void *context) for (i = 0; i < ctxt->n; i++) { if (ctxt->m[i].mod) rv = rv || close_lookup(ctxt->m[i].mod); + if (ctxt->m[i].argv) + free_argv(ctxt->m[i].argc, ctxt->m[i].argv); } free(ctxt->argl); free(ctxt->m);