diff --git a/CHANGELOG b/CHANGELOG index 6b16b0f..d66b8fc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ - include krb5.h in lookup_ldap.h (some openssl doesn't implicitly include it). - correct initialization of local var in parse_server_string. - add missing "multi" map support. +- add multi nsswitch lookup. 18/06/2007 autofs-5.0.2 ----------------------- diff --git a/lib/master_parse.y b/lib/master_parse.y index f9cba05..ab2895d 100644 --- a/lib/master_parse.y +++ b/lib/master_parse.y @@ -45,6 +45,7 @@ extern void master_set_scan_buffer(const char *); static char *master_strdup(char *); static void local_init_vars(void); static void local_free_vars(void); +static void trim_maptype(char *); static int add_multi_mapstr(void); static int master_error(const char *s); @@ -141,21 +142,9 @@ line: } | PATH MULTITYPE maplist { - char *tmp; - - tmp = strchr($2, ':'); - if (tmp) - *tmp = '\0'; - else { - int len = strlen($2); - while (len-- && isblank($2[len])) - $2[len] = '\0'; - if (len < 4) { - master_notify($2); - local_free_vars(); - YYABORT; - } - } + char *tmp = NULL; + + trim_maptype($2); path = master_strdup($1); if (!path) { @@ -312,81 +301,93 @@ map: PATH YYABORT; } } - | MAPTYPE COLON PATH + | MAPTYPE PATH { char *tmp = NULL; + trim_maptype($1); + if ((tmp = strchr($1, ','))) *tmp++ = '\0'; type = master_strdup($1); if (!type) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } if (tmp) { format = master_strdup(tmp); if (!format) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } } tmp_argc++; - tmp_argv = add_argv(tmp_argc, tmp_argv, $3); + tmp_argv = add_argv(tmp_argc, tmp_argv, $2); if (!tmp_argv) { master_error("memory allocation error"); local_free_vars(); YYABORT; } } - | MAPTYPE COLON MAPNAME + | MAPTYPE MAPNAME { char *tmp = NULL; + trim_maptype($1); + if ((tmp = strchr($1, ','))) *tmp++ = '\0'; type = master_strdup($1); if (!type) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } if (tmp) { format = master_strdup(tmp); if (!format) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } } tmp_argc++; - tmp_argv = add_argv(tmp_argc, tmp_argv, $3); + tmp_argv = add_argv(tmp_argc, tmp_argv, $2); if (!tmp_argv) { master_error("memory allocation error"); local_free_vars(); YYABORT; } } - | MAPTYPE COLON dn + | MAPTYPE dn { char *tmp = NULL; + trim_maptype($1); + if ((tmp = strchr($1, ','))) *tmp++ = '\0'; type = master_strdup($1); if (!type) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } if (tmp) { format = master_strdup(tmp); if (!format) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } } tmp_argc++; - tmp_argv = add_argv(tmp_argc, tmp_argv, $3); + tmp_argv = add_argv(tmp_argc, tmp_argv, $2); if (!tmp_argv) { master_error("memory allocation error"); local_free_vars(); @@ -396,6 +397,7 @@ map: PATH if (*tmp_argv[0]) { tmp = malloc(strlen(type) + strlen(tmp_argv[0]) + 2); if (!tmp) { + master_error("memory allocation error"); local_free_vars(); YYABORT; } @@ -628,33 +630,47 @@ static void local_free_vars(void) } } -static int add_multi_mapstr(void) +static void trim_maptype(char *type) { - /* We need the individual map types for a multi map */ - if (!type) { - if (tmp_argc > 0 && *tmp_argv[0] == '/') - type = strdup("file"); - else - return 0; + char *tmp; + + tmp = strchr(type, ':'); + if (tmp) + *tmp = '\0'; + else { + int len = strlen(type); + while (len-- && isblank(type[len])) + type[len] = '\0'; } + return; +} + +static int add_multi_mapstr(void) +{ + if (type) { + /* If type given and format is non-null add it back */ + if (format) { + int len = strlen(type) + strlen(format) + 2; + char *tmp = realloc(type, len); + if (!tmp) + return 0; + type = tmp; + strcat(type, ","); + strcat(type, format); + free(format); + format = NULL; + } - if (format) { - char *tmp = realloc(type, strlen(type) + strlen(format) + 2); - if (!tmp) + local_argc++; + local_argv = add_argv(local_argc, local_argv, type); + if (!local_argv) { + free(type); + type = NULL; return 0; - type = tmp; - strcat(type, ","); - strcat(type, format); - free(format); - format = NULL; - } + } - local_argc++; - local_argv = add_argv(local_argc, local_argv, type); - if (!local_argv) { free(type); type = NULL; - return 0; } local_argv = append_argv(local_argc, local_argv, tmp_argc, tmp_argv); @@ -667,8 +683,6 @@ static int add_multi_mapstr(void) tmp_argc = 0; tmp_argv = NULL; - free(type); - type = NULL; return 1; } diff --git a/lib/master_tok.l b/lib/master_tok.l index 0548de1..9bfeefa 100644 --- a/lib/master_tok.l +++ b/lib/master_tok.l @@ -111,9 +111,9 @@ DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} DNNAMESTR ([[:alnum:]_.\-]+) INTMAP (-hosts|-null) -MULTI ((multi)(,(sun|hesiod))?[\:]?{OPTWS}) +MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) MULTISEP ([\-]{2}[[:blank:]]+) -MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?) +MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?(:{OPTWS}|{WS})) OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) @@ -192,7 +192,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) return(MULTITYPE); } - {MTYPE}/":" { + {MTYPE} { strcpy(master_lval.strtype, master_text); return(MAPTYPE); } diff --git a/man/auto.master.5.in b/man/auto.master.5.in index 0e36a6f..98afaa9 100644 --- a/man/auto.master.5.in +++ b/man/auto.master.5.in @@ -103,6 +103,10 @@ entries are used for maps. .B ldap \fPor\fB ldaps The map is stored in an LDAP directory. If \fBldaps\fP is used the appropriate certificate must be configured in the LDAP client. +.TP +.B multi +This map type allows the specification of multiple maps separated +by "--". These maps are searched in order to resolve key lookups. .RE .TP \fBformat\fP diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c index 38ca36c..8fa94ae 100644 --- a/modules/lookup_multi.c +++ b/modules/lookup_multi.c @@ -19,6 +19,7 @@ #include #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);