From eaad949314471e382bc0b4c9d8fde19befc66ecb Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Nov 20 2007 07:54:34 +0000 Subject: - fix schema selection in LDAP schema discovery. - check for "*" when looking up wildcard in LDAP. - fix couple of edge case parse fails of timeout option. - add SEARCH_BASE configuration option. - add random selection as a master map entry option. - re-read config on HUP signal. - add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options. - fix deadlock in submount mount module. - fix lack of ferror() checking when reading files. - fix typo in autofs(5) man page. - fix map entry expansion when undefined macro is present. - remove unused export validation code. - add dynamic logging (adapted from v4 patch from Jeff Moyer). - fix recursive loopback mounts (Matthias Koenig). - add map re-load to verbose logging. - fix handling of LDAP base dns with spaces. - handle MTAB_NOTUPDATED status return from mount. - when default master map, auto.master, is used also check for auto_master. - update negative mount timeout handling. - fix large group handling (Ryan Thomas). - fix for dynamic logging breaking non-sasl build (Guillaume Rousse). - eliminate NULL proc ping for singleton host or local mounts. --- diff --git a/autofs-5.0.2-add-ferror-check.patch b/autofs-5.0.2-add-ferror-check.patch new file mode 100644 index 0000000..f178e73 --- /dev/null +++ b/autofs-5.0.2-add-ferror-check.patch @@ -0,0 +1,122 @@ +diff --git a/daemon/automount.c b/daemon/automount.c +index 930b13f..70a3b9d 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -978,7 +978,7 @@ static void *do_read_master(void *arg) + if (status) + fatal(status); + +- defaults_read_config(); ++ defaults_read_config(1); + + status = master_read_master(master, age, readall); + +@@ -1465,7 +1465,7 @@ int main(int argc, char *argv[]) + + program = argv[0]; + +- defaults_read_config(); ++ defaults_read_config(0); + + kpkt_len = get_kpkt_len(); + timeout = defaults_get_timeout(); +diff --git a/include/defaults.h b/include/defaults.h +index 46393d9..0e0e2a5 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -41,7 +41,7 @@ + struct ldap_schema; + struct ldap_searchdn; + +-unsigned int defaults_read_config(void); ++unsigned int defaults_read_config(unsigned int); + const char *defaults_get_master_map(void); + unsigned int defaults_get_timeout(void); + unsigned int defaults_get_browse_mode(void); +diff --git a/lib/defaults.c b/lib/defaults.c +index bf1ceed..2cccf20 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -280,7 +280,7 @@ struct list_head *defaults_get_uris(void) + * is valid bourne shell script without spaces around "=" + * and that it has valid values. + */ +-unsigned int defaults_read_config(void) ++unsigned int defaults_read_config(unsigned int to_syslog) + { + FILE *f; + char buf[MAX_LINE_LEN]; +@@ -312,9 +312,16 @@ unsigned int defaults_read_config(void) + ; + } + +- if (!feof(f)) { +- fprintf(stderr, "fgets returned error %d while reading %s\n", +- ferror(f), DEFAULTS_CONFIG_FILE); ++ if (!feof(f) || ferror(f)) { ++ if (!to_syslog) { ++ fprintf(stderr, ++ "fgets returned error %d while reading %s\n", ++ ferror(f), DEFAULTS_CONFIG_FILE); ++ } else { ++ error(LOGOPT_ANY, ++ "fgets returned error %d while reading %s", ++ ferror(f), DEFAULTS_CONFIG_FILE); ++ } + fclose(f); + return 0; + } +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index 6346602..31ee0fb 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -442,6 +442,11 @@ int lookup_read_master(struct master *master, time_t age, void *context) + if (!entry) { + if (feof(f)) + break; ++ if (ferror(f)) { ++ warn(LOGOPT_ANY, MODPREFIX ++ "error reading map %s", ctxt->mapname); ++ break; ++ } + continue; + } + +@@ -683,6 +688,11 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + if (!entry) { + if (feof(f)) + break; ++ if (ferror(f)) { ++ warn(LOGOPT_ANY, MODPREFIX ++ "error reading map %s", ctxt->mapname); ++ break; ++ } + continue; + } + +@@ -848,6 +858,12 @@ static int lookup_one(struct autofs_point *ap, + + if (feof(f)) + break; ++ ++ if (ferror(f)) { ++ warn(LOGOPT_ANY, MODPREFIX ++ "error reading map %s", ctxt->mapname); ++ break; ++ } + } + + fclose(f); +@@ -907,6 +923,12 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) + + if (feof(f)) + break; ++ ++ if (ferror(f)) { ++ warn(LOGOPT_ANY, MODPREFIX ++ "error reading map %s", ctxt->mapname); ++ break; ++ } + } + + fclose(f); diff --git a/autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch b/autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch new file mode 100644 index 0000000..f29801a --- /dev/null +++ b/autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch @@ -0,0 +1,27 @@ +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index dfb3054..8719af9 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -193,10 +193,11 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt + LDAPMessage *result = NULL, *e; + struct ldap_searchdn *sdns = NULL; + char *attrs[2]; ++ struct berval **value; + int scope; + int rv, l; + +- attrs[0] = LDAP_NO_ATTRS; ++ attrs[0] = (char *) key; + attrs[1] = NULL; + + if (!ctxt->mapname && !ctxt->base) { +@@ -283,7 +284,8 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt + } + + e = ldap_first_entry(ldap, result); +- if (e) { ++ if (e && (value = ldap_get_values_len(ldap, e, key))) { ++ ldap_value_free_len(value); + dn = ldap_get_dn(ldap, e); + debug(logopt, MODPREFIX "found query dn %s", dn); + } else { diff --git a/autofs-5.0.2-add-multiple-server-selection-option.patch b/autofs-5.0.2-add-multiple-server-selection-option.patch new file mode 100644 index 0000000..e2eea04 --- /dev/null +++ b/autofs-5.0.2-add-multiple-server-selection-option.patch @@ -0,0 +1,852 @@ +diff --git a/include/defaults.h b/include/defaults.h +index 0984b1c..46393d9 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -26,7 +26,8 @@ + #define DEFAULT_BROWSE_MODE 1 + #define DEFAULT_LOGGING 0 + +-#define DEFAULT_LDAP_SERVER NULL ++#define DEFAULT_LDAP_TIMEOUT -1 ++#define DEFAULT_LDAP_NETWORK_TIMEOUT 8 + + #define DEFAULT_MAP_OBJ_CLASS "nisMap" + #define DEFAULT_ENTRY_OBJ_CLASS "nisObject" +@@ -46,6 +47,10 @@ unsigned int defaults_get_timeout(void); + unsigned int defaults_get_browse_mode(void); + unsigned int defaults_get_logging(void); + const char *defaults_get_ldap_server(void); ++unsigned int defaults_get_ldap_timeout(void); ++unsigned int defaults_get_ldap_network_timeout(void); ++struct list_head *defaults_get_uris(void); ++void defaults_free_uris(struct list_head *); + struct ldap_schema *defaults_get_default_schema(void); + struct ldap_schema *defaults_get_schema(void); + struct ldap_searchdn *defaults_get_searchdns(void); +diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h +index 1a924be..ca8d658 100644 +--- a/include/lookup_ldap.h ++++ b/include/lookup_ldap.h +@@ -18,6 +18,11 @@ struct ldap_schema { + char *value_attr; + }; + ++struct ldap_uri { ++ char *uri; ++ struct list_head list; ++}; ++ + struct ldap_searchdn { + char *basedn; + struct ldap_searchdn *next; +@@ -30,6 +35,8 @@ struct lookup_context { + int port; + char *base; + char *qdn; ++ unsigned int timeout; ++ unsigned int network_timeout; + + /* LDAP version 2 or 3 */ + int version; +@@ -37,7 +44,17 @@ struct lookup_context { + /* LDAP lookup configuration */ + struct ldap_schema *schema; + +- /* List of base dns for searching */ ++ /* ++ * List of servers and base dns for searching. ++ * uri is the list of servers to attempt connection to and is ++ * used only if server, above, is NULL. The head of the list ++ * is the server which we are currently connected to. ++ * cur_host tracks chnages to connected server, triggering ++ * a scan of basedns when it changes. ++ * sdns is the list of basdns to check, done in the order ++ * given in configuration. ++ */ ++ struct list_head *uri; + char *cur_host; + struct ldap_searchdn *sdns; + +@@ -77,7 +94,7 @@ struct lookup_context { + #define LDAP_AUTH_AUTODETECT 0x0004 + + /* lookup_ldap.c */ +-LDAP *init_ldap_connection(struct lookup_context *ctxt); ++LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt); + int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt); + int authtype_requires_creds(const char *authtype); + +diff --git a/lib/defaults.c b/lib/defaults.c +index 7da4631..bf1ceed 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -17,6 +17,7 @@ + #include + #include + ++#include "list.h" + #include "defaults.h" + #include "lookup_ldap.h" + #include "log.h" +@@ -30,7 +31,9 @@ + #define ENV_NAME_BROWSE_MODE "BROWSE_MODE" + #define ENV_NAME_LOGGING "LOGGING" + +-#define ENV_LDAP_SERVER "LDAP_SERVER" ++#define LDAP_URI "LDAP_URI" ++#define ENV_LDAP_TIMEOUT "LDAP_TIMEOUT" ++#define ENV_LDAP_NETWORK_TIMEOUT "LDAP_NETWORK_TIMEOUT" + + #define SEARCH_BASE "SEARCH_BASE" + +@@ -44,7 +47,6 @@ + #define ENV_AUTH_CONF_FILE "AUTH_CONF_FILE" + + static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME; +-static const char *default_ldap_server = DEFAULT_LDAP_SERVER; + static const char *default_auth_conf_file = DEFAULT_AUTH_CONF_FILE; + + static char *get_env_string(const char *name) +@@ -178,6 +180,99 @@ static int parse_line(char *line, char **res, char **value) + return 1; + } + ++void defaults_free_uris(struct list_head *list) ++{ ++ struct list_head *next; ++ struct ldap_uri *uri; ++ ++ if (list_empty(list)) { ++ free(list); ++ return; ++ } ++ ++ next = list->next; ++ while (next != list) { ++ uri = list_entry(next, struct ldap_uri, list); ++ next = next->next; ++ list_del(&uri->list); ++ free(uri->uri); ++ free(uri); ++ } ++ free(list); ++ ++ return; ++} ++ ++static unsigned int add_uris(char *value, struct list_head *list) ++{ ++ char *str, *tok, *ptr = NULL; ++ size_t len = strlen(value); ++ ++ str = alloca(len); ++ if (!str) ++ return 0; ++ strcpy(str, value); ++ ++ tok = strtok_r(str, " ", &ptr); ++ while (tok) { ++ struct ldap_uri *new; ++ char *uri; ++ ++ new = malloc(sizeof(struct ldap_uri)); ++ if (!new) ++ continue; ++ ++ uri = strdup(tok); ++ if (!uri) ++ free(new); ++ else { ++ new->uri = uri; ++ list_add_tail(&new->list, list); ++ } ++ ++ tok = strtok_r(NULL, " ", &ptr); ++ } ++ ++ return 1; ++} ++ ++struct list_head *defaults_get_uris(void) ++{ ++ FILE *f; ++ char buf[MAX_LINE_LEN]; ++ char *res; ++ struct list_head *list; ++ ++ f = fopen(DEFAULTS_CONFIG_FILE, "r"); ++ if (!f) ++ return NULL; ++ ++ list = malloc(sizeof(struct list_head)); ++ if (!list) { ++ fclose(f); ++ return NULL; ++ } ++ INIT_LIST_HEAD(list); ++ ++ while ((res = fgets(buf, MAX_LINE_LEN, f))) { ++ char *key, *value; ++ ++ if (!parse_line(res, &key, &value)) ++ continue; ++ ++ if (!strcasecmp(res, LDAP_URI)) ++ add_uris(value, list); ++ } ++ ++ if (list_empty(list)) { ++ free(list); ++ list = NULL; ++ } ++ ++ fclose(f); ++ return list; ++} ++ + /* + * Read config env variables and check they have been set. + * +@@ -205,7 +300,8 @@ unsigned int defaults_read_config(void) + check_set_config_value(key, ENV_NAME_TIMEOUT, value) || + check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) || + check_set_config_value(key, ENV_NAME_LOGGING, value) || +- check_set_config_value(key, ENV_LDAP_SERVER, value) || ++ check_set_config_value(key, ENV_LDAP_TIMEOUT, value) || ++ check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value) || + check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) || + check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) || + check_set_config_value(key, ENV_NAME_MAP_ATTR, value) || +@@ -284,15 +380,26 @@ unsigned int defaults_get_logging(void) + return logging; + } + +-const char *defaults_get_ldap_server(void) ++unsigned int defaults_get_ldap_timeout(void) + { +- char *server; ++ int res; + +- server = get_env_string(ENV_LDAP_SERVER); +- if (!server) +- return default_ldap_server; ++ res = get_env_number(ENV_LDAP_TIMEOUT); ++ if (res < 0) ++ res = DEFAULT_LDAP_TIMEOUT; + +- return (const char *) server; ++ return res; ++} ++ ++unsigned int defaults_get_ldap_network_timeout(void) ++{ ++ int res; ++ ++ res = get_env_number(ENV_LDAP_NETWORK_TIMEOUT); ++ if (res < 0) ++ res = DEFAULT_LDAP_NETWORK_TIMEOUT; ++ ++ return res; + } + + struct ldap_schema *defaults_get_default_schema(void) +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index 0cb2f07..68447e0 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -230,10 +230,27 @@ values must be set, any partial schema specification will be ignored. + .P + The configuration settings available are: + .TP ++.B LDAP_TIMEOUT ++Set the network response timeout (default 8). ++Set timeout value for the synchronous API calls. The default is the LDAP ++library default of an infinite timeout. ++.TP ++.B LDAP_NETWORK_TIMEOUT ++Set the network response timeout (default 8). ++.TP ++.B LDAP_URI ++A space seperated list of server uris of the form ://[/] ++where can be ldap or ldaps. The option can be given multiple times. ++Map entries that include a server name override this option and it is then ++not used. Default is an empty list in which case either the server given ++in a map entry or the LDAP configured default is used. This uri list is read at ++startup and whenever the daemon receives a HUP signal. ++.TP + .B SEARCH_BASE + The base dn to use when searching for amap base dn. This entry may be + given multiple times and each will be checked for a map base dn in +-the order they occur in the configuration. ++the order they occur in the configuration. The search base list is read ++at startup and whenever the daemon recieves a HUP signal. + .TP + .B MAP_OBJECT_CLASS + The map object class. In the \fBnisMap\fP schema this corresponds to the class +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 2baf8b8..4068561 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -49,6 +49,8 @@ static struct ldap_schema common_schema[] = { + }; + static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); + ++static LDAP *auth_init(const char *, struct lookup_context *); ++ + int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt) + { + int rv; +@@ -59,10 +61,18 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt) + rv = ldap_simple_bind_s(ldap, NULL, NULL); + + if (rv != LDAP_SUCCESS) { +- crit(LOGOPT_ANY, +- MODPREFIX "Unable to bind to the LDAP server: " +- "%s, error %s", ctxt->server ? "" : "(default)", +- ldap_err2string(rv)); ++ if (!ctxt->uri) { ++ crit(LOGOPT_ANY, ++ MODPREFIX "Unable to bind to the LDAP server: " ++ "%s, error %s", ctxt->server ? "" : "(default)", ++ ldap_err2string(rv)); ++ } else { ++ struct ldap_uri *uri; ++ uri = list_entry(ctxt->uri->next, struct ldap_uri, list); ++ warn(LOGOPT_ANY, ++ MODPREFIX "Unable to bind to the LDAP server: " ++ "%s, error %s", uri->uri, ldap_err2string(rv)); ++ } + return -1; + } + +@@ -98,20 +108,21 @@ int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt) + return rv; + } + +-LDAP *init_ldap_connection(struct lookup_context *ctxt) ++LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap = NULL; +- int timeout = 8; ++ struct timeval timeout = { ctxt->timeout, 0 }; ++ struct timeval net_timeout = { ctxt->network_timeout, 0 }; + int rv; + + ctxt->version = 3; + + /* Initialize the LDAP context. */ +- rv = ldap_initialize(&ldap, ctxt->server); ++ rv = ldap_initialize(&ldap, uri); + if (rv != LDAP_OPT_SUCCESS) { + crit(LOGOPT_ANY, + MODPREFIX "couldn't initialize LDAP connection to %s", +- ctxt->server ? ctxt->server : "default server"); ++ uri ? uri : "default server"); + return NULL; + } + +@@ -120,7 +131,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) + if (rv != LDAP_OPT_SUCCESS) { + /* fall back to LDAPv2 */ + ldap_unbind_ext(ldap, NULL, NULL); +- rv = ldap_initialize(&ldap, ctxt->server); ++ rv = ldap_initialize(&ldap, uri); + if (rv != LDAP_OPT_SUCCESS) { + crit(LOGOPT_ANY, MODPREFIX "couldn't initialize LDAP"); + return NULL; +@@ -128,12 +139,22 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) + ctxt->version = 2; + } + +- /* Sane network connection timeout */ +- rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); ++ ++ if (ctxt->timeout != -1) { ++ /* Set synchronous call timeout */ ++ rv = ldap_set_option(ldap, LDAP_OPT_TIMEOUT, &timeout); ++ if (rv != LDAP_OPT_SUCCESS) ++ info(LOGOPT_ANY, MODPREFIX ++ "failed to set synchronous call timeout to %d", ++ timeout.tv_sec); ++ } ++ ++ /* Sane network timeout */ ++ rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &net_timeout); + if (rv != LDAP_OPT_SUCCESS) + info(LOGOPT_ANY, + MODPREFIX "failed to set connection timeout to %d", +- timeout); ++ net_timeout.tv_sec); + + #ifdef WITH_SASL + if (ctxt->use_tls) { +@@ -159,7 +180,7 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) + return NULL; + } + ctxt->use_tls = LDAP_TLS_DONT_USE; +- ldap = init_ldap_connection(ctxt); ++ ldap = init_ldap_connection(uri, ctxt); + if (ldap) + ctxt->use_tls = LDAP_TLS_INIT; + return ldap; +@@ -271,7 +292,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + e = ldap_first_entry(ldap, result); + if (e) { + dn = ldap_get_dn(ldap, e); +- debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); ++ debug(LOGOPT_NONE, MODPREFIX "found query dn %s", dn); + } else { + debug(LOGOPT_NONE, + MODPREFIX "query succeeded, no matches for %s", +@@ -378,16 +399,11 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) + return 0; + } + +-static LDAP *do_connect(struct lookup_context *ctxt) ++static int do_bind(LDAP *ldap, struct lookup_context *ctxt) + { +- LDAP *ldap; + char *host = NULL, *nhost; + int rv, need_base = 1; + +- ldap = init_ldap_connection(ctxt); +- if (!ldap) +- return NULL; +- + #ifdef WITH_SASL + debug(LOGOPT_NONE, "auth_required: %d, sasl_mech %s", + ctxt->auth_required, ctxt->sasl_mech); +@@ -407,23 +423,19 @@ static LDAP *do_connect(struct lookup_context *ctxt) + debug(LOGOPT_NONE, MODPREFIX "ldap anonymous bind returned %d", rv); + #endif + +- if (rv != 0) { +- unbind_ldap_connection(ldap, ctxt); +- return NULL; +- } ++ if (rv != 0) ++ return 0; + + rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host); + if (rv != LDAP_SUCCESS || !host) { +- unbind_ldap_connection(ldap, ctxt); + debug(LOGOPT_ANY, "failed to get hostname for connection"); +- return NULL; ++ return 0; + } + + nhost = strdup(host); + if (!nhost) { +- unbind_ldap_connection(ldap, ctxt); + debug(LOGOPT_ANY, "failed to alloc context for hostname"); +- return NULL; ++ return 0; + } + ldap_memfree(host); + +@@ -443,7 +455,7 @@ static LDAP *do_connect(struct lookup_context *ctxt) + } + + if (!need_base) +- return ldap; ++ return 1; + + /* + * If the schema isn't defined in the configuration then check for +@@ -452,20 +464,134 @@ static LDAP *do_connect(struct lookup_context *ctxt) + */ + if (!ctxt->schema) { + if (!find_query_dn(ldap, ctxt)) { +- unbind_ldap_connection(ldap, ctxt); + error(LOGOPT_ANY, + MODPREFIX "failed to find valid query dn"); +- return NULL; ++ return 0; + } + } else { + const char *class = ctxt->schema->map_class; + const char *key = ctxt->schema->map_attr; + if (!get_query_dn(ldap, ctxt, class, key)) { +- unbind_ldap_connection(ldap, ctxt); + error(LOGOPT_ANY, MODPREFIX "failed to get query dn"); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static LDAP *do_connect(const char *uri, struct lookup_context *ctxt) ++{ ++ LDAP *ldap; ++ ++ ldap = init_ldap_connection(uri, ctxt); ++ if (!ldap) ++ return NULL; ++ ++ if (!do_bind(ldap, ctxt)) { ++ unbind_ldap_connection(ldap, ctxt); ++ return NULL; ++ } ++ ++ return ldap; ++} ++ ++static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt) ++{ ++ LDAP *ldap; ++ ++#ifdef WITH_SASL ++ /* ++ * Determine which authentication mechanism to use if we require ++ * authentication. ++ */ ++ if (ctxt->auth_required & LDAP_AUTH_REQUIRED) { ++ ldap = auth_init(uri, ctxt); ++ if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT) ++ warn(LOGOPT_NONE, ++ "no authentication mechanisms auto detected."); ++ if (!ldap) { ++ error(LOGOPT_ANY, MODPREFIX ++ "cannot initialize authentication setup"); + return NULL; + } ++ ++ if (!do_bind(ldap, ctxt)) { ++ unbind_ldap_connection(ldap, ctxt); ++ error(LOGOPT_ANY, MODPREFIX "cannot bind to server"); ++ return NULL; ++ } ++ ++ return ldap; ++ } ++#endif ++ ++ ldap = do_connect(uri, ctxt); ++ if (!ldap) { ++ error(LOGOPT_ANY, MODPREFIX "cannot connect to server"); ++ return NULL; ++ } ++ ++ return ldap; ++} ++ ++static LDAP *find_server(struct lookup_context *ctxt) ++{ ++ LDAP *ldap = NULL; ++ struct ldap_uri *this; ++ struct list_head *p; ++ LIST_HEAD(tmp); ++ ++ /* Try each uri in list, add connect fails to tmp list */ ++ p = ctxt->uri->next; ++ while(p != ctxt->uri) { ++ this = list_entry(p, struct ldap_uri, list); ++ p = p->next; ++ debug(LOGOPT_ANY, "check uri %s", this->uri); ++ ldap = connect_to_server(this->uri, ctxt); ++ if (ldap) { ++ debug(LOGOPT_ANY, "connexted to uri %s", this->uri); ++ break; ++ } ++ list_del_init(&this->list); ++ list_add_tail(&this->list, &tmp); + } ++ /* ++ * Successfuly connected uri (head of list) and untried uris are ++ * in ctxt->uri list. Make list of remainder and failed uris with ++ * failed uris at end and assign back to ctxt-uri. ++ */ ++ list_splice(ctxt->uri, &tmp); ++ INIT_LIST_HEAD(ctxt->uri); ++ list_splice(&tmp, ctxt->uri); ++ ++ return ldap; ++} ++ ++static LDAP *do_reconnect(struct lookup_context *ctxt) ++{ ++ LDAP *ldap; ++ ++ if (ctxt->server || !ctxt->uri) { ++ ldap = do_connect(ctxt->server, ctxt); ++ return ldap; ++ } else { ++ struct ldap_uri *this; ++ this = list_entry(ctxt->uri->next, struct ldap_uri, list); ++ ldap = do_connect(this->uri, ctxt); ++ if (ldap) ++ return ldap; ++ /* Failed to connect, put at end of list */ ++ list_del_init(&this->list); ++ list_add_tail(&this->list, ctxt->uri); ++ } ++ ++ autofs_sasl_done(ctxt); ++ ++ /* Current server failed connect, try the rest */ ++ ldap = find_server(ctxt); ++ if (!ldap) ++ error(LOGOPT_ANY, MODPREFIX "failed to find available server"); + + return ldap; + } +@@ -760,10 +886,10 @@ out: + * information. If there is no configuration file, then we fall back to + * trying all supported authentication mechanisms until one works. + * +- * Returns 0 on success, with authtype, user and secret filled in as +- * appropriate. Returns -1 on failre. ++ * Returns ldap connection on success, with authtype, user and secret ++ * filled in as appropriate. Returns NULL on failre. + */ +-int auth_init(struct lookup_context *ctxt) ++static LDAP *auth_init(const char *uri, struct lookup_context *ctxt) + { + int ret; + LDAP *ldap; +@@ -776,14 +902,11 @@ int auth_init(struct lookup_context *ctxt) + */ + ret = parse_ldap_config(ctxt); + if (ret) +- return -1; +- +- if (ctxt->auth_required & LDAP_AUTH_NOTREQUIRED) +- return 0; ++ return NULL; + +- ldap = init_ldap_connection(ctxt); ++ ldap = init_ldap_connection(uri, ctxt); + if (!ldap) +- return -1; ++ return NULL; + + /* + * Initialize the sasl library. It is okay if user and secret +@@ -794,18 +917,12 @@ int auth_init(struct lookup_context *ctxt) + * the credential cache and the client and service principals. + */ + ret = autofs_sasl_init(ldap, ctxt); +- unbind_ldap_connection(ldap, ctxt); + if (ret) { + ctxt->sasl_mech = NULL; +- if (ctxt->auth_required & LDAP_AUTH_AUTODETECT) { +- warn(LOGOPT_NONE, +- "no authentication mechanisms auto detected."); +- return 0; +- } +- return -1; ++ return NULL; + } + +- return 0; ++ return ldap; + } + #endif + +@@ -1036,6 +1153,8 @@ static void free_context(struct lookup_context *ctxt) + free(ctxt->cur_host); + if (ctxt->base) + free(ctxt->base); ++ if (ctxt->uri) ++ defaults_free_uris(ctxt->uri); + if (ctxt->sdns) + defaults_free_searchdns(ctxt->sdns); + free(ctxt); +@@ -1043,6 +1162,30 @@ static void free_context(struct lookup_context *ctxt) + return; + } + ++static void validate_uris(struct list_head *list) ++{ ++ struct list_head *next; ++ ++ next = list->next; ++ while (next != list) { ++ struct ldap_uri *this; ++ ++ this = list_entry(next, struct ldap_uri, list); ++ next = next->next; ++ ++ /* At least we get some basic validation */ ++ if (!ldap_is_ldap_url(this->uri)) { ++ warn(LOGOPT_ANY, ++ "removed invalid uri from list, %s", this->uri); ++ list_del(&this->list); ++ free(this->uri); ++ free(this); ++ } ++ } ++ ++ return; ++} ++ + /* + * This initializes a context (persistent non-global data) for queries to + * this module. Return zero if we succeed. +@@ -1051,7 +1194,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + { + struct lookup_context *ctxt; + char buf[MAX_ERR_BUF]; +- int ret; + LDAP *ldap = NULL; + + *context = NULL; +@@ -1079,33 +1221,42 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + return 1; + } + +-#ifdef WITH_SASL +- /* +- * Determine which authentication mechanism to use. We sanity- +- * check by binding to the server temporarily. +- */ +- ret = auth_init(ctxt); +- if (ret && (ctxt->auth_required & LDAP_AUTH_REQUIRED)) { +- error(LOGOPT_ANY, MODPREFIX +- "cannot initialize authentication setup"); +- free_context(ctxt); +- return 1; ++ ctxt->timeout = defaults_get_ldap_timeout(); ++ ctxt->network_timeout = defaults_get_ldap_network_timeout(); ++ ++ if (!ctxt->server) { ++ struct list_head *uris = defaults_get_uris(); ++ if (uris) { ++ validate_uris(uris); ++ if (!list_empty(uris)) ++ ctxt->uri = uris; ++ else ++ free(uris); ++ } + } +-#endif + +- ldap = do_connect(ctxt); +- if (!ldap) { +- error(LOGOPT_ANY, MODPREFIX "cannot connect to server"); +- free_context(ctxt); +- return 1; ++ if (ctxt->server || !ctxt->uri) { ++ ldap = connect_to_server(ctxt->server, ctxt); ++ if (!ldap) { ++ free_context(ctxt); ++ return 1; ++ } ++ } else { ++ ldap = find_server(ctxt); ++ if (!ldap) { ++ free_context(ctxt); ++ error(LOGOPT_ANY, MODPREFIX ++ "failed to find available server"); ++ return 1; ++ } + } + unbind_ldap_connection(ldap, ctxt); + + /* Open the parser, if we can. */ + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); + free_context(ctxt); ++ crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); + return 1; + } + *context = ctxt; +@@ -1153,7 +1304,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + query[l] = '\0'; + + /* Initialize the LDAP context. */ +- ldap = do_connect(ctxt); ++ ldap = do_reconnect(ctxt); + if (!ldap) + return NSS_STATUS_UNAVAIL; + +@@ -1305,7 +1456,7 @@ static int read_one_map(struct autofs_point *ap, + query[l] = '\0'; + + /* Initialize the LDAP context. */ +- ldap = do_connect(ctxt); ++ ldap = do_reconnect(ctxt); + if (!ldap) + return NSS_STATUS_UNAVAIL; + +@@ -1536,6 +1687,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + if (ret != NSS_STATUS_SUCCESS) { + switch (rv) { + case LDAP_SIZELIMIT_EXCEEDED: ++ crit(ap->logopt, MODPREFIX ++ "Unable to download entire LDAP map for: %s", ++ ap->path); + case LDAP_UNWILLING_TO_PERFORM: + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_UNAVAIL; +@@ -1612,7 +1766,7 @@ static int lookup_one(struct autofs_point *ap, + query[ql] = '\0'; + + /* Initialize the LDAP context. */ +- ldap = do_connect(ctxt); ++ ldap = do_reconnect(ctxt); + if (!ldap) + return CHE_FAIL; + +diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in +index 2b1e20a..f01ee5f 100644 +--- a/redhat/autofs.sysconfig.in ++++ b/redhat/autofs.sysconfig.in +@@ -23,6 +23,25 @@ BROWSE_MODE="no" + # + # Define base dn for map dn lookup. + # ++# Define server URIs ++# ++# LDAP_URI - space seperated list of server uris of the form ++# ://[/] where can be ldap ++# or ldaps. The option can be given multiple times. ++# Map entries that include a server name override ++# this option. ++# ++#LDAP_URI="" ++# ++# LDAP__TIMEOUT - timeout value for the synchronous API calls ++# (default is LDAP library default). ++# ++#LDAP_TIMEOUT=-1 ++# ++# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8). ++# ++#LDAP_NETWORK_TIMEOUT=8 ++# + # SEARCH_BASE - base dn to use for searching for map search dn. + # Multiple entries can be given and they are checked + # in the order they occur here. +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index 2b1e20a..028341c 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -21,6 +21,25 @@ BROWSE_MODE="no" + # + #LOGGING="none" + # ++# Define server URIs ++# ++# LDAP_URI - space seperated list of server uris of the form ++# ://[/] where can be ldap ++# or ldaps. The option can be given multiple times. ++# Map entries that include a server name override ++# this option. ++# ++#LDAP_URI="" ++# ++# LDAP__TIMEOUT - timeout value for the synchronous API calls ++# (default is LDAP library default). ++# ++#LDAP_TIMEOUT=-1 ++# ++# LDAP_NETWORK_TIMEOUT - set the network response timeout (default 8). ++# ++#LDAP_NETWORK_TIMEOUT=8 ++# + # Define base dn for map dn lookup. + # + # SEARCH_BASE - base dn to use for searching for map search dn. diff --git a/autofs-5.0.2-autofs-5-typo.patch b/autofs-5.0.2-autofs-5-typo.patch new file mode 100644 index 0000000..d10db55 --- /dev/null +++ b/autofs-5.0.2-autofs-5-typo.patch @@ -0,0 +1,13 @@ +diff --git a/man/autofs.5 b/man/autofs.5 +index eb15c2a..5a01791 100644 +--- a/man/autofs.5 ++++ b/man/autofs.5 +@@ -128,7 +128,7 @@ entry looks like this: + .RS +.2i + .ta 1.0i + .nf +-* server:i/export/home/& ++* server:/export/home/& + .fi + .RE + .sp diff --git a/autofs-5.0.2-basedn-with-spaces.patch b/autofs-5.0.2-basedn-with-spaces.patch new file mode 100644 index 0000000..926628c --- /dev/null +++ b/autofs-5.0.2-basedn-with-spaces.patch @@ -0,0 +1,105 @@ +diff -Nurp autofs-5.0.2.orig/lib/master_tok.l autofs-5.0.2/lib/master_tok.l +--- autofs-5.0.2.orig/lib/master_tok.l 2007-11-20 15:37:48.000000000 +0900 ++++ autofs-5.0.2/lib/master_tok.l 2007-11-20 15:38:21.000000000 +0900 +@@ -108,7 +108,8 @@ AT_DC ([dD][[cC]) + AT_O ([oO]) + AT_C ([cC]) + DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} +-DNNAMESTR ([[:alnum:]_.\-]+) ++DNNAMESTR1 ([[:alnum:]_.\- ]+) ++DNNAMESTR2 ([[:alnum:]_.\-]+) + + INTMAP (-hosts|-null) + MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS})) +@@ -281,7 +282,12 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|-- + return EQUAL; + } + +- {DNNAMESTR} { ++ {DNNAMESTR1}/"," { ++ strcpy(master_lval.strtype, master_text); ++ return DNNAME; ++ } ++ ++ {DNNAMESTR2} { + strcpy(master_lval.strtype, master_text); + return DNNAME; + } +@@ -378,7 +384,13 @@ void master_set_scan_buffer(const char * + { + line = buffer; + line_pos = &line[0]; +- line_lim = line + strlen(buffer); ++ /* ++ * Ensure buffer is 1 greater than string and is zeroed before ++ * the parse so we can fit the extra NULL which allows us to ++ * explicitly match an end of line within the buffer (ie. the ++ * need for 2 NULLS when parsing in memeory buffers). ++ */ ++ line_lim = line + strlen(buffer) + 1; + } + + #define min(a,b) (((a) < (b)) ? (a) : (b)) +diff -Nurp autofs-5.0.2.orig/modules/lookup_file.c autofs-5.0.2/modules/lookup_file.c +--- autofs-5.0.2.orig/modules/lookup_file.c 2007-11-20 15:37:48.000000000 +0900 ++++ autofs-5.0.2/modules/lookup_file.c 2007-11-20 15:38:18.000000000 +0900 +@@ -479,7 +479,7 @@ int lookup_read_master(struct master *ma + + master->name = save_name; + } else { +- blen = path_len + 1 + ent_len + 1; ++ blen = path_len + 1 + ent_len + 2; + buffer = malloc(blen); + if (!buffer) { + error(logopt, +diff -Nurp autofs-5.0.2.orig/modules/lookup_ldap.c autofs-5.0.2/modules/lookup_ldap.c +--- autofs-5.0.2.orig/modules/lookup_ldap.c 2007-11-20 15:37:48.000000000 +0900 ++++ autofs-5.0.2/modules/lookup_ldap.c 2007-11-20 15:38:18.000000000 +0900 +@@ -1368,7 +1368,7 @@ int lookup_read_master(struct master *ma + goto next; + } + +- blen = strlen(*keyValue) + 1 + strlen(*values) + 1; ++ blen = strlen(*keyValue) + 1 + strlen(*values) + 2; + if (blen > PARSE_MAX_BUF) { + error(logopt, MODPREFIX "map entry too long"); + ldap_value_free(values); +diff -Nurp autofs-5.0.2.orig/modules/lookup_nisplus.c autofs-5.0.2/modules/lookup_nisplus.c +--- autofs-5.0.2.orig/modules/lookup_nisplus.c 2007-11-20 15:37:48.000000000 +0900 ++++ autofs-5.0.2/modules/lookup_nisplus.c 2007-11-20 15:38:18.000000000 +0900 +@@ -90,7 +90,7 @@ int lookup_read_master(struct master *ma + char *path, *ent; + char *buffer; + char buf[MAX_ERR_BUF]; +- int cur_state; ++ int cur_state, len; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); +@@ -138,11 +138,13 @@ int lookup_read_master(struct master *ma + + ent = ENTRY_VAL(this, 1); + +- buffer = malloc(ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 1); ++ len = ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 2; ++ buffer = malloc(len); + if (!buffer) { + logerr(MODPREFIX "could not malloc parse buffer"); + continue; + } ++ memset(buffer, 0, len); + + strcat(buffer, path); + strcat(buffer, " "); +diff -Nurp autofs-5.0.2.orig/modules/lookup_yp.c autofs-5.0.2/modules/lookup_yp.c +--- autofs-5.0.2.orig/modules/lookup_yp.c 2007-11-20 15:37:48.000000000 +0900 ++++ autofs-5.0.2/modules/lookup_yp.c 2007-11-20 15:38:18.000000000 +0900 +@@ -178,7 +178,7 @@ int yp_all_master_callback(int status, c + *(ypkey + ypkeylen) = '\0'; + *(val + vallen) = '\0'; + +- len = ypkeylen + 1 + vallen + 1; ++ len = ypkeylen + 1 + vallen + 2; + + buffer = alloca(len); + if (!buffer) { diff --git a/autofs-5.0.2-check-auto_master.patch b/autofs-5.0.2-check-auto_master.patch new file mode 100644 index 0000000..8aa65a8 --- /dev/null +++ b/autofs-5.0.2-check-auto_master.patch @@ -0,0 +1,65 @@ +diff --git a/daemon/lookup.c b/daemon/lookup.c +index fd99cf2..0be10d3 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -222,6 +222,28 @@ int lookup_nss_read_master(struct master *master, time_t age) + "reading master %s %s", this->source, master->name); + + result = read_master_map(master, this->source, age); ++ ++ /* ++ * If the name of the master map hasn't been explicitly ++ * configured and we're not reading an included master map ++ * then we're using auto.master as the default. Many setups ++ * also use auto_master as the default master map so we ++ * check for this map when auto.master isn't found. ++ */ ++ if (result != NSS_STATUS_SUCCESS && ++ !master->depth && !defaults_master_set()) { ++ char *tmp = strchr(master->name, '.'); ++ if (tmp) { ++ debug(logopt, ++ "%s not found, replacing '.' with '_'", ++ master->name); ++ *tmp = '_'; ++ result = read_master_map(master, this->source, age); ++ if (result != NSS_STATUS_SUCCESS) ++ *tmp = '.'; ++ } ++ } ++ + if (result == NSS_STATUS_UNKNOWN) { + debug(logopt, "no map - continuing to next source"); + continue; +diff --git a/include/defaults.h b/include/defaults.h +index 0e0e2a5..e296478 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -43,6 +43,7 @@ struct ldap_searchdn; + + unsigned int defaults_read_config(unsigned int); + const char *defaults_get_master_map(void); ++int defaults_master_set(void); + unsigned int defaults_get_timeout(void); + unsigned int defaults_get_browse_mode(void); + unsigned int defaults_get_logging(void); +diff --git a/lib/defaults.c b/lib/defaults.c +index 94885e8..f494103 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -350,6 +350,15 @@ const char *defaults_get_master_map(void) + return (const char *) master; + } + ++int defaults_master_set(void) ++{ ++ char *val = getenv(ENV_NAME_MASTER_MAP); ++ if (!val) ++ return 0; ++ ++ return 1; ++} ++ + unsigned int defaults_get_timeout(void) + { + long timeout; diff --git a/autofs-5.0.2-check-mtab-updated.patch b/autofs-5.0.2-check-mtab-updated.patch new file mode 100644 index 0000000..d59ac39 --- /dev/null +++ b/autofs-5.0.2-check-mtab-updated.patch @@ -0,0 +1,264 @@ +diff -up autofs-5.0.2/include/automount.h.check-mtab-updated autofs-5.0.2/include/automount.h +--- autofs-5.0.2/include/automount.h.check-mtab-updated 2007-11-20 16:10:13.000000000 +0900 ++++ autofs-5.0.2/include/automount.h 2007-11-20 16:10:36.000000000 +0900 +@@ -78,6 +78,7 @@ int load_autofs4_module(void); + #define MOUNTED_LOCK _PATH_MOUNTED "~" /* mounts' lock file */ + #define MTAB_NOTUPDATED 0x1000 /* mtab succeded but not updated */ + #define NOT_MOUNTED 0x0100 /* path notmounted */ ++#define MNT_FORCE_FAIL -1 + #define _PROC_MOUNTS "/proc/mounts" + + /* Constants for lookup modules */ +diff -up autofs-5.0.2/modules/mount_bind.c.check-mtab-updated autofs-5.0.2/modules/mount_bind.c +--- autofs-5.0.2/modules/mount_bind.c.check-mtab-updated 2007-11-20 16:10:58.000000000 +0900 ++++ autofs-5.0.2/modules/mount_bind.c 2007-11-20 16:11:49.000000000 +0900 +@@ -147,7 +147,7 @@ int mount_mount(struct autofs_point *ap, + if ((!ap->ghost && name_len) || !existed) + rmdir_path(ap, fullpath, ap->dev); + +- return 1; ++ return err; + } else { + debug(ap->logopt, + MODPREFIX "mounted %s type %s on %s", +diff -up autofs-5.0.2/modules/mount_nfs.c.check-mtab-updated autofs-5.0.2/modules/mount_nfs.c +--- autofs-5.0.2/modules/mount_nfs.c.check-mtab-updated 2007-11-20 16:11:08.000000000 +0900 ++++ autofs-5.0.2/modules/mount_nfs.c 2007-11-20 16:12:44.000000000 +0900 +@@ -233,6 +233,10 @@ int mount_mount(struct autofs_point *ap, + return 0; + } + ++ /* Failed to update mtab, don't try any more */ ++ if (err == MNT_FORCE_FAIL) ++ goto forced_fail; ++ + /* No hostname, can't be NFS */ + if (!this->name) { + this = this->next; +@@ -275,6 +279,7 @@ int mount_mount(struct autofs_point *ap, + this = this->next; + } + ++forced_fail: + free_host_list(&hosts); + ap->ghost = save_ghost; + +diff -up autofs-5.0.2/daemon/spawn.c.check-mtab-updated autofs-5.0.2/daemon/spawn.c +--- autofs-5.0.2/daemon/spawn.c.check-mtab-updated 2007-11-20 16:06:45.000000000 +0900 ++++ autofs-5.0.2/daemon/spawn.c 2007-11-20 16:06:45.000000000 +0900 +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "automount.h" + +@@ -268,9 +269,11 @@ int spawn_mount(unsigned logopt, ...) + char **argv, **p; + char prog[] = PATH_MOUNT; + char arg0[] = PATH_MOUNT; ++ /* In case we need to use the fake option to mount */ ++ char arg_fake[] = "-f"; + unsigned int options; + unsigned int retries = MTAB_LOCK_RETRIES; +- int ret; ++ int ret, printed = 0; + + /* If we use mount locking we can't validate the location */ + #ifdef ENABLE_MOUNT_LOCKING +@@ -283,7 +286,8 @@ int spawn_mount(unsigned logopt, ...) + for (argc = 1; va_arg(arg, char *); argc++); + va_end(arg); + +- if (!(argv = alloca(sizeof(char *) * argc + 1))) ++ /* Alloc 1 extra slot in case we need to use the "-f" option */ ++ if (!(argv = alloca(sizeof(char *) * argc + 2))) + return -1; + + argv[0] = arg0; +@@ -304,11 +308,52 @@ int spawn_mount(unsigned logopt, ...) + + while (retries--) { + ret = do_spawn(logopt, options, prog, (const char **) argv); +- if (ret & MTAB_NOTUPDATED) ++ if (ret & MTAB_NOTUPDATED) { ++ struct timespec tm = {3, 0}; ++ ++ /* ++ * If the mount succeeded but the mtab was not ++ * updated, then retry the mount with the -f (fake) ++ * option to just update the mtab. ++ */ ++ if (!printed) { ++ debug(logopt, "mount failed with error code 16" ++ ", retrying with the -f option"); ++ printed = 1; ++ } ++ ++ /* ++ * Move the last two args so do_spawn() can find the ++ * mount target. ++ */ ++ if (!argv[argc]) { ++ argv[argc + 1] = NULL; ++ argv[argc] = argv[argc - 1]; ++ argv[argc - 1] = argv[argc - 2]; ++ argv[argc - 2] = arg_fake; ++ } ++ ++ nanosleep(&tm, NULL); ++ + continue; ++ } + break; + } + ++ /* This is not a fatal error */ ++ if (ret == MTAB_NOTUPDATED) { ++ /* ++ * Version 5 requires that /etc/mtab be in sync with ++ * /proc/mounts. If we're unable to update matb after ++ * retrying then we have no choice but umount the mount ++ * and return a fail. ++ */ ++ warn(logopt, ++ "Unable to update the mtab file, forcing mount fail!"); ++ umount(argv[argc]); ++ ret = MNT_FORCE_FAIL; ++ } ++ + return ret; + } + +@@ -328,9 +373,11 @@ int spawn_bind_mount(unsigned logopt, .. + char prog[] = PATH_MOUNT; + char arg0[] = PATH_MOUNT; + char bind[] = "--bind"; ++ /* In case we need to use the fake option to mount */ ++ char arg_fake[] = "-f"; + unsigned int options; + unsigned int retries = MTAB_LOCK_RETRIES; +- int ret; ++ int ret, printed = 0; + + /* If we use mount locking we can't validate the location */ + #ifdef ENABLE_MOUNT_LOCKING +@@ -339,8 +386,12 @@ int spawn_bind_mount(unsigned logopt, .. + options = SPAWN_OPT_ACCESS; + #endif + ++ /* ++ * Alloc 2 extra slots, one for the bind option and one in case ++ * we need to use the "-f" option ++ */ + va_start(arg, logopt); +- for (argc = 1; va_arg(arg, char *); argc++); ++ for (argc = 2; va_arg(arg, char *); argc++); + va_end(arg); + + if (!(argv = alloca(sizeof(char *) * argc + 2))) +@@ -356,11 +407,52 @@ int spawn_bind_mount(unsigned logopt, .. + + while (retries--) { + ret = do_spawn(logopt, options, prog, (const char **) argv); +- if (ret & MTAB_NOTUPDATED) ++ if (ret & MTAB_NOTUPDATED) { ++ struct timespec tm = {3, 0}; ++ ++ /* ++ * If the mount succeeded but the mtab was not ++ * updated, then retry the mount with the -f (fake) ++ * option to just update the mtab. ++ */ ++ if (!printed) { ++ debug(logopt, "mount failed with error code 16" ++ ", retrying with the -f option"); ++ printed = 1; ++ } ++ ++ /* ++ * Move the last two args so do_spawn() can find the ++ * mount target. ++ */ ++ if (!argv[argc]) { ++ argv[argc + 1] = NULL; ++ argv[argc] = argv[argc - 1]; ++ argv[argc - 1] = argv[argc - 2]; ++ argv[argc - 2] = arg_fake; ++ } ++ ++ nanosleep(&tm, NULL); ++ + continue; ++ } + break; + } + ++ /* This is not a fatal error */ ++ if (ret == MTAB_NOTUPDATED) { ++ /* ++ * Version 5 requires that /etc/mtab be in sync with ++ * /proc/mounts. If we're unable to update matb after ++ * retrying then we have no choice but umount the mount ++ * and return a fail. ++ */ ++ warn(logopt, ++ "Unable to update the mtab file, forcing mount fail!"); ++ umount(argv[argc]); ++ ret = MNT_FORCE_FAIL; ++ } ++ + return ret; + } + +@@ -373,7 +465,7 @@ int spawn_umount(unsigned logopt, ...) + char arg0[] = PATH_UMOUNT; + unsigned int options; + unsigned int retries = MTAB_LOCK_RETRIES; +- int ret; ++ int ret, printed = 0; + + #ifdef ENABLE_MOUNT_LOCKING + options = SPAWN_OPT_LOCK; +@@ -397,9 +489,37 @@ int spawn_umount(unsigned logopt, ...) + + while (retries--) { + ret = do_spawn(logopt, options, prog, (const char **) argv); +- if (ret & MTAB_NOTUPDATED) +- continue; +- break; ++ if (ret & MTAB_NOTUPDATED) { ++ /* ++ * If the mount succeeded but the mtab was not ++ * updated, then retry the umount just to update ++ * the mtab. ++ */ ++ if (!printed) { ++ debug(logopt, "mount failed with error code 16" ++ ", retrying with the -f option"); ++ printed = 1; ++ } ++ } else { ++ /* ++ * umount does not support the "fake" option. Thus, ++ * if we got a return value of MTAB_NOTUPDATED the ++ * first time, that means the umount actually ++ * succeeded. Then, a following umount will fail ++ * due to the fact that nothing was mounted on the ++ * mount point. So, report this as success. ++ */ ++ if (retries < MTAB_LOCK_RETRIES - 1) ++ ret = 0; ++ break; ++ } ++ } ++ ++ /* This is not a fatal error */ ++ if (ret == MTAB_NOTUPDATED) { ++ warn(logopt, "Unable to update the mtab file, /proc/mounts " ++ "and /etc/mtab will differ"); ++ ret = 0; + } + + return ret; diff --git a/autofs-5.0.2-dynamic-logging-fixes.patch b/autofs-5.0.2-dynamic-logging-fixes.patch new file mode 100644 index 0000000..d93538b --- /dev/null +++ b/autofs-5.0.2-dynamic-logging-fixes.patch @@ -0,0 +1,385 @@ +diff --git a/Makefile.conf.in b/Makefile.conf.in +index ea5fe1d..09c3129 100644 +--- a/Makefile.conf.in ++++ b/Makefile.conf.in +@@ -71,6 +71,9 @@ autofsconfdir = @confdir@ + # Location for autofs maps + autofsmapdir = @mapdir@ + ++# Location for autofs fifos ++autofsfifodir = @fifodir@ ++ + # Where to install the automount program + sbindir = @sbindir@ + +diff --git a/aclocal.m4 b/aclocal.m4 +index ffeb232..118ef0d 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -120,6 +120,22 @@ AC_DEFUN(AF_MAP_D, + done + fi]) + ++dnl -------------------------------------------------------------------------- ++dnl AF_FIFO_D ++dnl ++dnl Check the location of the autofs fifos directory ++dnl -------------------------------------------------------------------------- ++AC_DEFUN(AF_FIFO_D, ++[if test -z "$fifodir"; then ++ for fifo_d in /var/run /tmp; do ++ if test -z "$fifodir"; then ++ if test -d "$fifo_d"; then ++ fifodir="$fifo_d" ++ fi ++ fi ++ done ++fi]) ++ + dnl ----------------------------------- ## -*- Autoconf -*- + dnl Check if --with-dmalloc was given. ## + dnl From Franc,ois Pinard ## +diff --git a/configure b/configure +index 3508224..0360086 100755 +--- a/configure ++++ b/configure +@@ -654,6 +654,7 @@ target_alias + initdir + confdir + mapdir ++fifodir + DMALLOCLIB + MOUNT + HAVE_MOUNT +@@ -1293,6 +1294,7 @@ Optional Packages: + --with-path=PATH look in PATH for binaries needed by the automounter + --with-confdir=DIR use DIR for autofs configuration files + --with-mapdir=PATH look in PATH for mount maps used by the automounter ++ --with-fifodir=PATH use PATH as the directory for fifos used by the automounter + --with-dmalloc use dmalloc, as in + http://www.dmalloc.com/dmalloc.tar.gz + --with-hesiod=DIR enable Hesiod support (libs and includes in DIR) +@@ -1844,6 +1846,36 @@ echo "${ECHO_T}$mapdir" >&6; } + + + # ++# The user can specify --with-fifodir=PATH to specify where autofs fifos go ++# ++if test -z "$fifodir"; then ++ for fifo_d in /var/run /tmp; do ++ if test -z "$fifodir"; then ++ if test -d "$fifo_d"; then ++ fifodir="$fifo_d" ++ fi ++ fi ++ done ++fi ++ ++# Check whether --with-fifodir was given. ++if test "${with_fifodir+set}" = set; then ++ withval=$with_fifodir; if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no" ++ then ++ : ++ else ++ fifodir="${withval}" ++ fi ++ ++fi ++ ++{ echo "$as_me:$LINENO: checking for autofs fifos directory" >&5 ++echo $ECHO_N "checking for autofs fifos directory... $ECHO_C" >&6; } ++{ echo "$as_me:$LINENO: result: $fifodir" >&5 ++echo "${ECHO_T}$fifodir" >&6; } ++ ++ ++# + # Optional include dmalloc + # + { echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5 +@@ -6074,6 +6106,7 @@ target_alias!$target_alias$ac_delim + initdir!$initdir$ac_delim + confdir!$confdir$ac_delim + mapdir!$mapdir$ac_delim ++fifodir!$fifodir$ac_delim + DMALLOCLIB!$DMALLOCLIB$ac_delim + MOUNT!$MOUNT$ac_delim + HAVE_MOUNT!$HAVE_MOUNT$ac_delim +@@ -6124,7 +6157,7 @@ LIBOBJS!$LIBOBJS$ac_delim + LTLIBOBJS!$LTLIBOBJS$ac_delim + _ACEOF + +- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then ++ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 89; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +diff --git a/configure.in b/configure.in +index 8cddf90..a83b3f1 100644 +--- a/configure.in ++++ b/configure.in +@@ -79,6 +79,23 @@ AC_MSG_RESULT([$mapdir]) + AC_SUBST(mapdir) + + # ++# The user can specify --with-fifodir=PATH to specify where autofs fifos go ++# ++AF_FIFO_D() ++AC_ARG_WITH(fifodir, ++[ --with-fifodir=PATH use PATH as the directory for fifos used by the automounter], ++ if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no" ++ then ++ : ++ else ++ fifodir="${withval}" ++ fi ++) ++AC_MSG_CHECKING([for autofs fifos directory]) ++AC_MSG_RESULT([$fifodir]) ++AC_SUBST(fifodir) ++ ++# + # Optional include dmalloc + # + AM_WITH_DMALLOC() +diff --git a/daemon/Makefile b/daemon/Makefile +index 4ee70eb..528a684 100644 +--- a/daemon/Makefile ++++ b/daemon/Makefile +@@ -16,6 +16,7 @@ CFLAGS += -rdynamic $(DAEMON_CFLAGS) -D_GNU_SOURCE -I../include + CFLAGS += -DAUTOFS_LIB_DIR=\"$(autofslibdir)\" + CFLAGS += -DAUTOFS_MAP_DIR=\"$(autofsmapdir)\" + CFLAGS += -DAUTOFS_CONF_DIR=\"$(autofsconfdir)\" ++CFLAGS += -DAUTOFS_FIFO_DIR=\"$(autofsfifodir)\" + CFLAGS += -DVERSION_STRING=\"$(version)\" + LDFLAGS += -rdynamic + LIBS = -ldl +diff --git a/daemon/automount.c b/daemon/automount.c +index 7e7d1e6..a12b6da 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -50,6 +50,9 @@ const char *libdir = AUTOFS_LIB_DIR; /* Location of library modules */ + const char *mapdir = AUTOFS_MAP_DIR; /* Location of mount maps */ + const char *confdir = AUTOFS_CONF_DIR; /* Location of autofs config file */ + ++/* autofs fifo name prefix */ ++const char *fifodir = AUTOFS_FIFO_DIR "/autofs.fifo"; ++ + const char *global_options; /* Global option, from command line */ + + static char *pid_file = NULL; /* File in which to keep pid */ +@@ -650,14 +653,13 @@ static int fullread(int fd, void *ptr, size_t len) + static char *automount_path_to_fifo(unsigned logopt, const char *path) + { + char *fifo_name, *p; +- int name_len = strlen(path) + strlen(AUTOFS_LOGPRI_FIFO) + 1; ++ int name_len = strlen(path) + strlen(fifodir) + 1; + int ret; + + fifo_name = malloc(name_len); + if (!fifo_name) + return NULL; +- ret = snprintf(fifo_name, name_len, "%s%s", +- AUTOFS_LOGPRI_FIFO, path); ++ ret = snprintf(fifo_name, name_len, "%s%s", fifodir, path); + if (ret >= name_len) { + info(logopt, + "fifo path for \"%s\" truncated to \"%s\". This may " +@@ -670,7 +672,7 @@ static char *automount_path_to_fifo(unsigned logopt, const char *path) + * create the fifo name, we will just replace instances of '/' with + * '-'. + */ +- p = fifo_name + strlen(AUTOFS_LOGPRI_FIFO); ++ p = fifo_name + strlen(fifodir); + while (*p != '\0') { + if (*p == '/') + *p = '-'; +@@ -685,8 +687,9 @@ static char *automount_path_to_fifo(unsigned logopt, const char *path) + static int create_logpri_fifo(struct autofs_point *ap) + { + int ret = -1; +- int fd; ++ int fd, cl_flags; + char *fifo_name; ++ char buf[MAX_ERR_BUF]; + + fifo_name = automount_path_to_fifo(ap->logopt, ap->path); + if (!fifo_name) { +@@ -704,18 +707,27 @@ static int create_logpri_fifo(struct autofs_point *ap) + + ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR); + if (ret != 0) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(ap->logopt, +- "mkfifo for %s returned %d", fifo_name, errno); ++ "mkfifo for %s failed: %s", fifo_name, estr); + goto out_free; + } + + fd = open(fifo_name, O_RDWR|O_NONBLOCK); + if (fd < 0) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(ap->logopt, +- "Failed to open %s, errno %d", fifo_name, errno); ++ "Failed to open %s: %s", fifo_name, estr); ++ unlink(fifo_name); ++ ret = -1; + goto out_free; + } + ++ if ((cl_flags = fcntl(fd, F_GETFD, 0)) != -1) { ++ cl_flags |= FD_CLOEXEC; ++ fcntl(fd, F_SETFD, cl_flags); ++ } ++ + ap->logpri_fifo = fd; + + out_free: +@@ -728,6 +740,10 @@ static int destroy_logpri_fifo(struct autofs_point *ap) + int ret = -1; + int fd = ap->logpri_fifo; + char *fifo_name; ++ char buf[MAX_ERR_BUF]; ++ ++ if (fd == -1) ++ return 0; + + fifo_name = automount_path_to_fifo(ap->logopt, ap->path); + if (!fifo_name) { +@@ -739,8 +755,9 @@ static int destroy_logpri_fifo(struct autofs_point *ap) + + ret = close(fd); + if (ret != 0) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + warn(ap->logopt, +- "close for fifo %s returned %d", fifo_name, errno); ++ "close for fifo %s: %s", fifo_name, estr); + } + + ret = unlink(fifo_name); +@@ -760,11 +777,13 @@ static void handle_fifo_message(struct autofs_point *ap, int fd) + char buffer[PIPE_BUF]; + char *end; + long pri; ++ char buf[MAX_ERR_BUF]; + + memset(buffer, 0, sizeof(buffer)); + ret = read(fd, &buffer, sizeof(buffer)); + if (ret < 0) { +- warn(ap->logopt, "read on fifo returned error %d", errno); ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ warn(ap->logopt, "read on fifo returned error: %s", estr); + return; + } + +@@ -846,16 +865,18 @@ static int set_log_priority(const char *path, int priority) + */ + fd = open(fifo_name, O_WRONLY|O_NONBLOCK); + if (fd < 0) { +- fprintf(stderr, "%s: open of %s failed with %d\n", +- __FUNCTION__, fifo_name, errno); ++ fprintf(stderr, "%s: open of %s failed with %s\n", ++ __FUNCTION__, fifo_name, strerror(errno)); ++ fprintf(stderr, "%s: perhaps the fifo wasn't setup," ++ " please check your log for more information\n", __FUNCTION__); + free(fifo_name); + return -1; + } + + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { + fprintf(stderr, "Failed to change logging priority. "); +- fprintf(stderr, "write to fifo failed with errno %d.\n", +- errno); ++ fprintf(stderr, "write to fifo failed: %s.\n", ++ strerror(errno)); + close(fd); + free(fifo_name); + return -1; +@@ -870,6 +891,7 @@ static int set_log_priority(const char *path, int priority) + static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt) + { + struct pollfd fds[3]; ++ int pollfds = 3; + char buf[MAX_ERR_BUF]; + + fds[0].fd = ap->pipefd; +@@ -878,9 +900,11 @@ static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt) + fds[1].events = POLLIN; + fds[2].fd = ap->logpri_fifo; + fds[2].events = POLLIN; ++ if (fds[2].fd == -1) ++ pollfds--; + + for (;;) { +- if (poll(fds, 3, -1) == -1) { ++ if (poll(fds, pollfds, -1) == -1) { + char *estr; + if (errno == EINTR) + continue; +@@ -930,7 +954,7 @@ static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt) + if (fds[0].revents & POLLIN) + return fullread(ap->pipefd, pkt, kpkt_len); + +- if (fds[2].revents & POLLIN) { ++ if (fds[2].fd != -1 && fds[2].revents & POLLIN) { + debug(ap->logopt, "message pending on control fifo."); + handle_fifo_message(ap, fds[2].fd); + } +@@ -983,7 +1007,6 @@ static int autofs_init_ap(struct autofs_point *ap) + crit(ap->logopt, + "failed to create commumication pipe for autofs path %s", + ap->path); +- free(ap->path); + return -1; + } + +@@ -1006,7 +1029,6 @@ static int autofs_init_ap(struct autofs_point *ap) + "failed create state pipe for autofs path %s", ap->path); + close(ap->pipefd); + close(ap->kpipefd); /* Close kernel pipe end */ +- free(ap->path); + return -1; + } + +@@ -1021,15 +1043,8 @@ static int autofs_init_ap(struct autofs_point *ap) + } + + if (create_logpri_fifo(ap) < 0) { +- crit(ap->logopt, +- "failed to create FIFO for path %s\n", ap->path); +- destroy_logpri_fifo(ap); +- close(ap->pipefd); +- close(ap->kpipefd); +- free(ap->path); +- close(ap->state_pipe[0]); +- close(ap->state_pipe[1]); +- return -1; ++ logmsg("could not create FIFO for path %s\n", ap->path); ++ logmsg("dynamic log level changes not available for %s", ap->path); + } + + return 0; +diff --git a/include/automount.h b/include/automount.h +index 37a3c0a..b0d1a9c 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -223,8 +223,6 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev); + #define MAPENT_MAX_LEN 4095 + #define PARSE_MAX_BUF KEY_MAX_LEN + MAPENT_MAX_LEN + 2 + +-#define AUTOFS_LOGPRI_FIFO "/tmp/autofs.fifo" +- + int lookup_nss_read_master(struct master *master, time_t age); + int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age); + int lookup_enumerate(struct autofs_point *ap, +diff --git a/lib/master.c b/lib/master.c +index 2e24ad0..2188bca 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -56,6 +56,7 @@ int master_add_autofs_point(struct master_mapent *entry, + + ap->state_pipe[0] = -1; + ap->state_pipe[1] = -1; ++ ap->logpri_fifo = -1; + + ap->path = strdup(entry->path); + if (!ap->path) { diff --git a/autofs-5.0.2-dynamic-logging-non-sasl.patch b/autofs-5.0.2-dynamic-logging-non-sasl.patch new file mode 100644 index 0000000..fc10162 --- /dev/null +++ b/autofs-5.0.2-dynamic-logging-non-sasl.patch @@ -0,0 +1,14 @@ +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index bad48bb..93a1b40 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -579,7 +579,9 @@ static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + list_add_tail(&this->list, ctxt->uri); + } + ++#ifdef WITH_SASL + autofs_sasl_done(ctxt); ++#endif + + /* Current server failed connect, try the rest */ + ldap = find_server(logopt, ctxt); diff --git a/autofs-5.0.2-dynamic-logging.patch b/autofs-5.0.2-dynamic-logging.patch new file mode 100644 index 0000000..7c1f878 --- /dev/null +++ b/autofs-5.0.2-dynamic-logging.patch @@ -0,0 +1,6212 @@ +diff --git a/daemon/automount.c b/daemon/automount.c +index 70a3b9d..9ec6923 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -173,7 +173,7 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev) + */ + memset(&st, 0, sizeof(st)); + if (lstat(buf, &st) != 0) { +- crit(ap->logopt, "lstat of %s failed.", buf); ++ crit(ap->logopt, "lstat of %s failed", buf); + return -1; + } + +@@ -234,14 +234,15 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev) + /* Like ftw, except fn gets called twice: before a directory is + entered, and after. If the before call returns 0, the directory + isn't entered. */ +-static int walk_tree(const char *base, int (*fn) (const char *file, ++static int walk_tree(const char *base, int (*fn) (unsigned logopt, ++ const char *file, + const struct stat * st, +- int, void *), int incl, void *arg) ++ int, void *), int incl, unsigned logopt, void *arg) + { + char buf[PATH_MAX + 1]; + struct stat st; + +- if (lstat(base, &st) != -1 && (fn) (base, &st, 0, arg)) { ++ if (lstat(base, &st) != -1 && (fn) (logopt, base, &st, 0, arg)) { + if (S_ISDIR(st.st_mode)) { + struct dirent **de; + int n; +@@ -269,18 +270,18 @@ static int walk_tree(const char *base, int (*fn) (const char *file, + return -1; + } + +- walk_tree(buf, fn, 1, arg); ++ walk_tree(buf, fn, 1, logopt, arg); + free(de[n]); + } + free(de); + } + if (incl) +- (fn) (base, &st, 1, arg); ++ (fn) (logopt, base, &st, 1, arg); + } + return 0; + } + +-static int rm_unwanted_fn(const char *file, const struct stat *st, int when, void *arg) ++static int rm_unwanted_fn(unsigned logopt, const char *file, const struct stat *st, int when, void *arg) + { + dev_t dev = *(dev_t *) arg; + char buf[MAX_ERR_BUF]; +@@ -293,41 +294,38 @@ static int rm_unwanted_fn(const char *file, const struct stat *st, int when, voi + } + + if (lstat(file, &newst)) { +- crit(LOGOPT_ANY, +- "unable to stat file, possible race condition"); ++ crit(logopt, "unable to stat file, possible race condition"); + return 0; + } + + if (newst.st_dev != dev) { +- crit(LOGOPT_ANY, +- "file %s has the wrong device, possible race condition", ++ crit(logopt, "file %s has the wrong device, possible race condition", + file); + return 0; + } + + if (S_ISDIR(newst.st_mode)) { +- debug(LOGOPT_ANY, "removing directory %s", file); ++ debug(logopt, "removing directory %s", file); + if (rmdir(file)) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(LOGOPT_ANY, ++ warn(logopt, + "unable to remove directory %s: %s", file, estr); + return 0; + } + } else if (S_ISREG(newst.st_mode)) { +- crit(LOGOPT_ANY, +- "attempting to remove files from a mounted " ++ crit(logopt, "attempting to remove files from a mounted " + "directory. file %s", file); + return 0; + } else if (S_ISLNK(newst.st_mode)) { +- debug(LOGOPT_ANY, "removing symlink %s", file); ++ debug(logopt, "removing symlink %s", file); + unlink(file); + } + return 1; + } + +-void rm_unwanted(const char *path, int incl, dev_t dev) ++void rm_unwanted(unsigned logopt, const char *path, int incl, dev_t dev) + { +- walk_tree(path, rm_unwanted_fn, incl, &dev); ++ walk_tree(path, rm_unwanted_fn, incl, logopt, &dev); + } + + struct counter_args { +@@ -335,7 +333,7 @@ struct counter_args { + dev_t dev; + }; + +-static int counter_fn(const char *file, const struct stat *st, int when, void *arg) ++static int counter_fn(unsigned logopt, const char *file, const struct stat *st, int when, void *arg) + { + struct counter_args *counter = (struct counter_args *) arg; + +@@ -349,14 +347,14 @@ static int counter_fn(const char *file, const struct stat *st, int when, void *a + } + + /* Count mounted filesystems and symlinks */ +-int count_mounts(const char *path, dev_t dev) ++int count_mounts(unsigned logopt, const char *path, dev_t dev) + { + struct counter_args counter; + + counter.count = 0; + counter.dev = dev; + +- if (walk_tree(path, counter_fn, 0, &counter) == -1) ++ if (walk_tree(path, counter_fn, 0, logopt, &counter) == -1) + return -1; + + return counter.count; +@@ -368,9 +366,9 @@ static void check_rm_dirs(struct autofs_point *ap, const char *path, int incl) + (ap->state == ST_SHUTDOWN_PENDING || + ap->state == ST_SHUTDOWN_FORCE || + ap->state == ST_SHUTDOWN)) +- rm_unwanted(path, incl, ap->dev); ++ rm_unwanted(ap->logopt, path, incl, ap->dev); + else if (ap->ghost && (ap->type == LKP_INDIRECT)) +- rm_unwanted(path, 0, ap->dev); ++ rm_unwanted(ap->logopt, path, 0, ap->dev); + } + + /* Try to purge cache entries kept around due to existing mounts */ +@@ -466,7 +464,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + cache_multi_lock(me->parent); + if (umount_multi_triggers(ap, root, me, base)) { + warn(ap->logopt, +- "could not umount some offsets under %s", path); ++ "some offset mounts still present under %s", path); + left++; + } + cache_multi_unlock(me->parent); +@@ -483,7 +481,7 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi + * it already to ensure it's ok to remove any offset triggers. + */ + if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) { +- msg("unmounting dir = %s", path); ++ info(ap->logopt, "unmounting dir = %s", path); + if (umount_ent(ap, path)) { + warn(ap->logopt, "could not umount dir %s", path); + left++; +@@ -576,35 +574,35 @@ int umount_autofs(struct autofs_point *ap, int force) + return ret; + } + +-int send_ready(int ioctlfd, unsigned int wait_queue_token) ++int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token) + { + char buf[MAX_ERR_BUF]; + + if (wait_queue_token == 0) + return 0; + +- debug(LOGOPT_NONE, "token = %d", wait_queue_token); ++ debug(logopt, "token = %d", wait_queue_token); + + if (ioctl(ioctlfd, AUTOFS_IOC_READY, wait_queue_token) < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "AUTOFS_IOC_READY: error %s", estr); ++ logerr("AUTOFS_IOC_READY: error %s", estr); + return 1; + } + return 0; + } + +-int send_fail(int ioctlfd, unsigned int wait_queue_token) ++int send_fail(unsigned logopt, int ioctlfd, unsigned int wait_queue_token) + { + char buf[MAX_ERR_BUF]; + + if (wait_queue_token == 0) + return 0; + +- debug(LOGOPT_NONE, "token = %d", wait_queue_token); ++ debug(logopt, "token = %d", wait_queue_token); + + if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, wait_queue_token) < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "AUTOFS_IOC_FAIL: error %s", estr); ++ logerr("AUTOFS_IOC_FAIL: error %s", estr); + return 1; + } + return 0; +@@ -649,23 +647,245 @@ static int fullread(int fd, void *ptr, size_t len) + return len; + } + ++static char *automount_path_to_fifo(unsigned logopt, const char *path) ++{ ++ char *fifo_name, *p; ++ int name_len = strlen(path) + strlen(AUTOFS_LOGPRI_FIFO) + 1; ++ int ret; ++ ++ fifo_name = malloc(name_len); ++ if (!fifo_name) ++ return NULL; ++ ret = snprintf(fifo_name, name_len, "%s%s", ++ AUTOFS_LOGPRI_FIFO, path); ++ if (ret >= name_len) { ++ info(logopt, ++ "fifo path for \"%s\" truncated to \"%s\". This may " ++ "lead to --set-log-priority commands being sent to the " ++ "wrong automount daemon.", path, fifo_name); ++ } ++ ++ /* ++ * An automount path can be made up of subdirectories. So, to ++ * create the fifo name, we will just replace instances of '/' with ++ * '-'. ++ */ ++ p = fifo_name + strlen(AUTOFS_LOGPRI_FIFO); ++ while (*p != '\0') { ++ if (*p == '/') ++ *p = '-'; ++ p++; ++ } ++ ++ debug(logopt, "fifo name %s",fifo_name); ++ ++ return fifo_name; ++} ++ ++static int create_logpri_fifo(struct autofs_point *ap) ++{ ++ int ret = -1; ++ int fd; ++ char *fifo_name; ++ ++ fifo_name = automount_path_to_fifo(ap->logopt, ap->path); ++ if (!fifo_name) { ++ crit(ap->logopt, "Failed to allocate memory!"); ++ goto out_free; /* free(NULL) is okay */ ++ } ++ ++ ret = unlink(fifo_name); ++ if (ret != 0 && errno != ENOENT) { ++ crit(ap->logopt, ++ "Failed to unlink FIFO. Is the automount daemon " ++ "already running?"); ++ goto out_free; ++ } ++ ++ ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR); ++ if (ret != 0) { ++ crit(ap->logopt, ++ "mkfifo for %s returned %d", fifo_name, errno); ++ goto out_free; ++ } ++ ++ fd = open(fifo_name, O_RDWR|O_NONBLOCK); ++ if (fd < 0) { ++ crit(ap->logopt, ++ "Failed to open %s, errno %d", fifo_name, errno); ++ goto out_free; ++ } ++ ++ ap->logpri_fifo = fd; ++ ++out_free: ++ free(fifo_name); ++ return ret; ++} ++ ++static int destroy_logpri_fifo(struct autofs_point *ap) ++{ ++ int ret = -1; ++ int fd = ap->logpri_fifo; ++ char *fifo_name; ++ ++ fifo_name = automount_path_to_fifo(ap->logopt, ap->path); ++ if (!fifo_name) { ++ crit(ap->logopt, "Failed to allocate memory!"); ++ goto out_free; /* free(NULL) is okay */ ++ } ++ ++ ap->logpri_fifo = -1; ++ ++ ret = close(fd); ++ if (ret != 0) { ++ warn(ap->logopt, ++ "close for fifo %s returned %d", fifo_name, errno); ++ } ++ ++ ret = unlink(fifo_name); ++ if (ret != 0) { ++ warn(ap->logopt, ++ "Failed to unlink FIFO. Was the fifo created OK?"); ++ } ++ ++out_free: ++ free(fifo_name); ++ return ret; ++} ++ ++static void handle_fifo_message(struct autofs_point *ap, int fd) ++{ ++ int ret; ++ char buffer[PIPE_BUF]; ++ char *end; ++ long pri; ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ret = read(fd, &buffer, sizeof(buffer)); ++ if (ret < 0) { ++ warn(ap->logopt, "read on fifo returned error %d", errno); ++ return; ++ } ++ ++ if (ret != 2) { ++ debug(ap->logopt, "expected 2 bytes, received %d.", ret); ++ return; ++ } ++ ++ errno = 0; ++ pri = strtol(buffer, &end, 10); ++ if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) { ++ debug(ap->logopt, "strtol reported an %s. Failed to set " ++ "log priority.", pri == LONG_MIN ? "underflow" : "overflow"); ++ return; ++ } ++ if ((pri == 0 && errno == EINVAL) || end == buffer) { ++ debug(ap->logopt, "priority is expected to be an integer " ++ "in the range 0-7 inclusive."); ++ return; ++ } ++ ++ if (pri > LOG_DEBUG || pri < LOG_EMERG) { ++ debug(ap->logopt, "invalid log priority (%ld) received " ++ "on fifo", pri); ++ return; ++ } ++ ++ /* ++ * OK, the message passed all of the sanity checks. The ++ * automounter actually only supports three log priorities. ++ * Everything is logged at log level debug, deamon messages ++ * and everything except debug messages are logged with the ++ * verbose setting and only error and critical messages are ++ * logged when debugging isn't enabled. ++ */ ++ if (pri >= LOG_WARNING) { ++ if (pri == LOG_DEBUG) { ++ set_log_debug_ap(ap); ++ info(ap->logopt, "Debug logging set for %s", ap->path); ++ } else { ++ set_log_verbose_ap(ap); ++ info(ap->logopt, "Verbose logging set for %s", ap->path); ++ } ++ } else { ++ if (ap->logopt & LOGOPT_ANY) ++ info(ap->logopt, "Basic logging set for %s", ap->path); ++ set_log_norm_ap(ap); ++ } ++} ++ ++static int set_log_priority(const char *path, int priority) ++{ ++ int fd; ++ char *fifo_name; ++ char buf[2]; ++ ++ if (priority > LOG_DEBUG || priority < LOG_EMERG) { ++ fprintf(stderr, "Log priority %d is invalid.\n", priority); ++ fprintf(stderr, "Please spcify a number in the range 0-7.\n"); ++ return -1; ++ } ++ ++ /* ++ * This is an ascii based protocol, so we want the string ++ * representation of the integer log priority. ++ */ ++ snprintf(buf, sizeof(buf), "%d", priority); ++ ++ fifo_name = automount_path_to_fifo(LOGOPT_NONE, path); ++ if (!fifo_name) { ++ fprintf(stderr, "%s: Failed to allocate memory!\n", ++ __FUNCTION__); ++ return -1; ++ } ++ ++ /* ++ * Specify O_NONBLOCK so that the open will fail if there is no ++ * daemon reading from the other side of the FIFO. ++ */ ++ fd = open(fifo_name, O_WRONLY|O_NONBLOCK); ++ if (fd < 0) { ++ fprintf(stderr, "%s: open of %s failed with %d\n", ++ __FUNCTION__, fifo_name, errno); ++ free(fifo_name); ++ return -1; ++ } ++ ++ if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { ++ fprintf(stderr, "Failed to change logging priority. "); ++ fprintf(stderr, "write to fifo failed with errno %d.\n", ++ errno); ++ close(fd); ++ free(fifo_name); ++ return -1; ++ } ++ close(fd); ++ free(fifo_name); ++ fprintf(stdout, "Successfully set log priority for %s.\n", path); ++ ++ return 0; ++} ++ + static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt) + { +- struct pollfd fds[2]; ++ struct pollfd fds[3]; + char buf[MAX_ERR_BUF]; + + fds[0].fd = ap->pipefd; + fds[0].events = POLLIN; + fds[1].fd = ap->state_pipe[0]; + fds[1].events = POLLIN; ++ fds[2].fd = ap->logpri_fifo; ++ fds[2].events = POLLIN; + + for (;;) { +- if (poll(fds, 2, -1) == -1) { ++ if (poll(fds, 3, -1) == -1) { + char *estr; + if (errno == EINTR) + continue; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, "poll failed: %s", estr); ++ logerr("poll failed: %s", estr); + return -1; + } + +@@ -709,6 +929,11 @@ static int get_pkt(struct autofs_point *ap, union autofs_packet_union *pkt) + + if (fds[0].revents & POLLIN) + return fullread(ap->pipefd, pkt, kpkt_len); ++ ++ if (fds[2].revents & POLLIN) { ++ debug(ap->logopt, "message pending on control fifo."); ++ handle_fifo_message(ap, fds[2].fd); ++ } + } + } + +@@ -730,21 +955,93 @@ int do_expire(struct autofs_point *ap, const char *name, int namelen) + return 1; + } + +- msg("expiring path %s", buf); ++ info(ap->logopt, "expiring path %s", buf); + + ret = umount_multi(ap, buf, 1); + if (ret == 0) +- msg("expired %s", buf); ++ info(ap->logopt, "expired %s", buf); + else + warn(ap->logopt, "couldn't complete expire of %s", buf); + + return ret; + } + ++static int autofs_init_ap(struct autofs_point *ap) ++{ ++ int pipefd[2], cl_flags; ++ ++ if ((ap->state != ST_INIT)) { ++ /* This can happen if an autofs process is already running*/ ++ error(ap->logopt, "bad state %d", ap->state); ++ return -1; ++ } ++ ++ ap->pipefd = ap->kpipefd = ap->ioctlfd = -1; ++ ++ /* Pipe for kernel communications */ ++ if (pipe(pipefd) < 0) { ++ crit(ap->logopt, ++ "failed to create commumication pipe for autofs path %s", ++ ap->path); ++ free(ap->path); ++ return -1; ++ } ++ ++ ap->pipefd = pipefd[0]; ++ ap->kpipefd = pipefd[1]; ++ ++ if ((cl_flags = fcntl(ap->pipefd, F_GETFD, 0)) != -1) { ++ cl_flags |= FD_CLOEXEC; ++ fcntl(ap->pipefd, F_SETFD, cl_flags); ++ } ++ ++ if ((cl_flags = fcntl(ap->kpipefd, F_GETFD, 0)) != -1) { ++ cl_flags |= FD_CLOEXEC; ++ fcntl(ap->kpipefd, F_SETFD, cl_flags); ++ } ++ ++ /* Pipe state changes from signal handler to main loop */ ++ if (pipe(ap->state_pipe) < 0) { ++ crit(ap->logopt, ++ "failed create state pipe for autofs path %s", ap->path); ++ close(ap->pipefd); ++ close(ap->kpipefd); /* Close kernel pipe end */ ++ free(ap->path); ++ return -1; ++ } ++ ++ if ((cl_flags = fcntl(ap->state_pipe[0], F_GETFD, 0)) != -1) { ++ cl_flags |= FD_CLOEXEC; ++ fcntl(ap->state_pipe[0], F_SETFD, cl_flags); ++ } ++ ++ if ((cl_flags = fcntl(ap->state_pipe[1], F_GETFD, 0)) != -1) { ++ cl_flags |= FD_CLOEXEC; ++ fcntl(ap->state_pipe[1], F_SETFD, cl_flags); ++ } ++ ++ if (create_logpri_fifo(ap) < 0) { ++ crit(ap->logopt, ++ "failed to create FIFO for path %s\n", ap->path); ++ destroy_logpri_fifo(ap); ++ close(ap->pipefd); ++ close(ap->kpipefd); ++ free(ap->path); ++ close(ap->state_pipe[0]); ++ close(ap->state_pipe[1]); ++ return -1; ++ } ++ ++ return 0; ++} ++ + static int mount_autofs(struct autofs_point *ap) + { + int status = 0; + ++ if (autofs_init_ap(ap) != 0) ++ return -1; ++ + if (ap->type == LKP_DIRECT) + status = mount_autofs_direct(ap); + else +@@ -841,9 +1138,8 @@ static void become_daemon(unsigned foreground) + fclose(pidfp); + } else { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(LOGOPT_ANY, +- "failed to write pid file %s: %s", +- pid_file, estr); ++ logerr("failed to write pid file %s: %s", ++ pid_file, estr); + pid_file = NULL; + } + } +@@ -889,12 +1185,12 @@ static void *do_notify_state(void *arg) + + master = mrc.master; + +- debug(master->default_logging, "signal %d", sig); ++ debug(master->logopt, "signal %d", sig); + + mrc.signaled = 1; + status = pthread_cond_signal(&mrc.cond); + if (status) { +- error(master->default_logging, ++ error(master->logopt, + "failed to signal state notify condition"); + status = pthread_mutex_unlock(&mrc.mutex); + if (status) +@@ -923,7 +1219,7 @@ static pthread_t do_signals(struct master *master, int sig) + + status = pthread_create(&thid, &thread_attr, do_notify_state, &r_sig); + if (status) { +- error(master->default_logging, ++ error(master->logopt, + "mount state notify thread create failed"); + status = pthread_mutex_unlock(&mrc.mutex); + if (status) +@@ -951,6 +1247,7 @@ static pthread_t do_signals(struct master *master, int sig) + static void *do_read_master(void *arg) + { + struct master *master; ++ unsigned int logopt; + time_t age; + int readall = 1; + int status; +@@ -961,11 +1258,12 @@ static void *do_read_master(void *arg) + + master = mrc.master; + age = mrc.age; ++ logopt = master->logopt; + + mrc.signaled = 1; + status = pthread_cond_signal(&mrc.cond); + if (status) { +- error(master->default_logging, ++ error(logopt, + "failed to signal master read map condition"); + master->reading = 0; + status = pthread_mutex_unlock(&mrc.mutex); +@@ -989,6 +1287,7 @@ static void *do_read_master(void *arg) + + static int do_hup_signal(struct master *master, time_t age) + { ++ unsigned int logopt = master->logopt; + pthread_t thid; + int status; + +@@ -1007,7 +1306,7 @@ static int do_hup_signal(struct master *master, time_t age) + + status = pthread_create(&thid, &thread_attr, do_read_master, NULL); + if (status) { +- error(master->default_logging, ++ error(logopt, + "master read map thread create failed"); + master->reading = 0; + status = pthread_mutex_unlock(&mrc.mutex); +@@ -1062,8 +1361,7 @@ static void *statemachine(void *arg) + break; + + default: +- error(master_list->default_logging, +- "got unexpected signal %d!", sig); ++ logerr("got unexpected signal %d!", sig); + continue; + } + } +@@ -1134,10 +1432,11 @@ static void handle_mounts_cleanup(void *arg) + struct autofs_point *ap; + char path[PATH_MAX + 1]; + char buf[MAX_ERR_BUF]; +- unsigned int clean = 0, submount; ++ unsigned int clean = 0, submount, logopt; + + ap = (struct autofs_point *) arg; + ++ logopt = ap->logopt; + submount = ap->submount; + + strcpy(path, ap->path); +@@ -1152,6 +1451,7 @@ static void handle_mounts_cleanup(void *arg) + + umount_autofs(ap, 1); + ++ destroy_logpri_fifo(ap); + master_signal_submount(ap, MASTER_SUBMNT_JOIN); + master_remove_mapent(ap->entry); + master_free_mapent_sources(ap->entry, 1); +@@ -1162,12 +1462,12 @@ static void handle_mounts_cleanup(void *arg) + if (clean) { + if (rmdir(path) == -1) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(LOGOPT_NONE, "failed to remove dir %s: %s", ++ warn(logopt, "failed to remove dir %s: %s", + path, estr); + } + } + +- msg("shut down path %s", path); ++ info(logopt, "shut down path %s", path); + + /* If we are the last tell the state machine to shutdown */ + if (!submount && master_list_empty(master_list)) +@@ -1190,7 +1490,7 @@ void *handle_mounts(void *arg) + + status = pthread_mutex_lock(&suc.mutex); + if (status) { +- crit(ap->logopt, "failed to lock startup condition mutex!"); ++ logerr("failed to lock startup condition mutex!"); + fatal(status); + } + +@@ -1204,7 +1504,7 @@ void *handle_mounts(void *arg) + } + + if (ap->ghost && ap->type != LKP_DIRECT) +- msg("ghosting enabled"); ++ info(ap->logopt, "ghosting enabled"); + + suc.status = 0; + pthread_cleanup_pop(1); +@@ -1356,6 +1656,8 @@ static void usage(void) + " use ramdom replicated server selection\n" + " -O --global-options\n" + " specify global mount options\n" ++ " -l --set-log-priority priority path [path,...]\n" ++ " set daemon log verbosity\n" + " -V --version print version, build config and exit\n" + , program); + } +@@ -1437,9 +1739,45 @@ static void show_build_info(void) + return; + } + ++typedef struct _code { ++ char *c_name; ++ int c_val; ++} CODE; ++ ++CODE prioritynames[] = { ++ { "alert", LOG_ALERT }, ++ { "crit", LOG_CRIT }, ++ { "debug", LOG_DEBUG }, ++ { "emerg", LOG_EMERG }, ++ { "err", LOG_ERR }, ++ { "error", LOG_ERR }, /* DEPRECATED */ ++ { "info", LOG_INFO }, ++ { "notice", LOG_NOTICE }, ++ { "panic", LOG_EMERG }, /* DEPRECATED */ ++ { "warn", LOG_WARNING }, /* DEPRECATED */ ++ { "warning", LOG_WARNING }, ++ { NULL, -1 }, ++}; ++ ++static int convert_log_priority(char *priority_name) ++{ ++ CODE *priority_mapping; ++ ++ for (priority_mapping = prioritynames; ++ priority_mapping->c_name != NULL; ++ priority_mapping++) { ++ ++ if (!strcasecmp(priority_name, priority_mapping->c_name)) ++ return priority_mapping->c_val; ++ } ++ ++ return -1; ++} ++ + int main(int argc, char *argv[]) + { + int res, opt, status; ++ int logpri = -1; + unsigned ghost, logging; + unsigned foreground, have_global_options; + time_t timeout; +@@ -1457,6 +1795,7 @@ int main(int argc, char *argv[]) + {"random-multimount-selection", 0, 0, 'r'}, + {"global-options", 1, 0, 'O'}, + {"version", 0, 0, 'V'}, ++ {"set-log-priority", 1, 0, 'l'}, + {0, 0, 0, 0} + }; + +@@ -1477,7 +1816,7 @@ int main(int argc, char *argv[]) + foreground = 0; + + opterr = 0; +- while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:", long_options, NULL)) != EOF) { ++ while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:", long_options, NULL)) != EOF) { + switch (opt) { + case 'h': + usage(); +@@ -1525,6 +1864,23 @@ int main(int argc, char *argv[]) + program); + break; + ++ case 'l': ++ if (isalpha(*optarg)) { ++ logpri = convert_log_priority(optarg); ++ if (logpri < 0) { ++ fprintf(stderr, "Invalid log priority:" ++ " %s\n", optarg); ++ exit(1); ++ } ++ } else if (isdigit(*optarg)) { ++ logpri = getnumopt(optarg, opt); ++ } else { ++ fprintf(stderr, "non-alphanumeric character " ++ "found in log priority. Aborting.\n"); ++ exit(1); ++ } ++ break; ++ + case '?': + case ':': + printf("%s: Ambiguous or unknown options\n", program); +@@ -1548,6 +1904,26 @@ int main(int argc, char *argv[]) + argv += optind; + argc -= optind; + ++ if (logpri >= 0) { ++ int exit_code = 0; ++ int i; ++ ++ /* ++ * The remaining argv elements are the paths for which ++ * log priorities must be changed. ++ */ ++ for (i = 0; i < argc; i++) { ++ if (set_log_priority(argv[i], logpri) < 0) ++ exit_code = 1; ++ } ++ if (argc < 1) { ++ fprintf(stderr, ++ "--set-log-priority requires a path.\n"); ++ exit_code = 1; ++ } ++ exit(exit_code); ++ } ++ + if (is_automount_running() > 0) { + fprintf(stderr, "%s: program is already running.\n", + program); +@@ -1572,7 +1948,7 @@ int main(int argc, char *argv[]) + rlim.rlim_max = MAX_OPEN_FILES; + res = setrlimit(RLIMIT_NOFILE, &rlim); + if (res) +- warn(LOGOPT_NONE, ++ warn(logging, + "can't increase open file limit - continuing"); + + #if ENABLE_CORES +@@ -1580,7 +1956,7 @@ int main(int argc, char *argv[]) + rlim.rlim_max = RLIM_INFINITY; + res = setrlimit(RLIMIT_CORE, &rlim); + if (res) +- warn(LOGOPT_NONE, ++ warn(logging, + "can't increase core file limit - continuing"); + #endif + +@@ -1592,15 +1968,14 @@ int main(int argc, char *argv[]) + master_list = master_new(argv[0], timeout, ghost); + + if (!master_list) { +- crit(LOGOPT_ANY, "%s: can't create master map %s", ++ logerr("%s: can't create master map %s", + program, argv[0]); + close(start_pipefd[1]); + exit(1); + } + + if (pthread_attr_init(&thread_attr)) { +- crit(LOGOPT_ANY, +- "%s: failed to init thread attribute struct!", ++ logerr("%s: failed to init thread attribute struct!", + program); + close(start_pipefd[1]); + exit(1); +@@ -1608,8 +1983,7 @@ int main(int argc, char *argv[]) + + if (pthread_attr_setdetachstate( + &thread_attr, PTHREAD_CREATE_DETACHED)) { +- crit(LOGOPT_ANY, +- "%s: failed to set detached thread attribute!", ++ logerr("%s: failed to set detached thread attribute!", + program); + close(start_pipefd[1]); + exit(1); +@@ -1618,38 +1992,37 @@ int main(int argc, char *argv[]) + #ifdef _POSIX_THREAD_ATTR_STACKSIZE + if (pthread_attr_setstacksize( + &thread_attr, PTHREAD_STACK_MIN*64)) { +- crit(LOGOPT_ANY, +- "%s: failed to set stack size thread attribute!", +- program); ++ logerr("%s: failed to set stack size thread attribute!", ++ program); + close(start_pipefd[1]); + exit(1); + } + #endif + +- msg("Starting automounter version %s, master map %s", ++ info(logging, "Starting automounter version %s, master map %s", + version, master_list->name); +- msg("using kernel protocol version %d.%02d", ++ info(logging, "using kernel protocol version %d.%02d", + get_kver_major(), get_kver_minor()); + + status = pthread_key_create(&key_thread_stdenv_vars, + key_thread_stdenv_vars_destroy); + if (status) { +- crit(LOGOPT_ANY, +- "failed to create thread data key for std env vars!"); ++ logerr("%s: failed to create thread data key for std env vars!", ++ program); + master_kill(master_list); + close(start_pipefd[1]); + exit(1); + } + + if (!alarm_start_handler()) { +- crit(LOGOPT_ANY, "failed to create alarm handler thread!"); ++ logerr("%s: failed to create alarm handler thread!", program); + master_kill(master_list); + close(start_pipefd[1]); + exit(1); + } + + if (!st_start_handler()) { +- crit(LOGOPT_ANY, "failed to create FSM handler thread!"); ++ logerr("%s: failed to create FSM handler thread!", program); + master_kill(master_list); + close(start_pipefd[1]); + exit(1); +@@ -1685,5 +2058,7 @@ int main(int argc, char *argv[]) + if (dh) + dlclose(dh); + #endif ++ info(logging, "autofs stopped"); ++ + exit(0); + } +diff --git a/daemon/direct.c b/daemon/direct.c +index 9a39a6f..4ab4204 100644 +--- a/daemon/direct.c ++++ b/daemon/direct.c +@@ -86,61 +86,6 @@ static void mnts_cleanup(void *arg) + return; + } + +-static int autofs_init_direct(struct autofs_point *ap) +-{ +- int pipefd[2], cl_flags; +- +- if ((ap->state != ST_INIT)) { +- /* This can happen if an autofs process is already running*/ +- error(ap->logopt, "bad state %d", ap->state); +- return -1; +- } +- +- ap->pipefd = ap->kpipefd = ap->ioctlfd = -1; +- +- /* Pipe for kernel communications */ +- if (pipe(pipefd) < 0) { +- crit(ap->logopt, +- "failed to create commumication pipe for autofs path %s", +- ap->path); +- return -1; +- } +- +- ap->pipefd = pipefd[0]; +- ap->kpipefd = pipefd[1]; +- +- if ((cl_flags = fcntl(ap->pipefd, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->pipefd, F_SETFD, cl_flags); +- } +- +- if ((cl_flags = fcntl(ap->kpipefd, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->kpipefd, F_SETFD, cl_flags); +- } +- +- /* Pipe state changes from signal handler to main loop */ +- if (pipe(ap->state_pipe) < 0) { +- crit(ap->logopt, "failed create state pipe for autofs path %s", +- ap->path); +- close(ap->pipefd); +- close(ap->kpipefd); +- return -1; +- } +- +- if ((cl_flags = fcntl(ap->state_pipe[0], F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->state_pipe[0], F_SETFD, cl_flags); +- } +- +- if ((cl_flags = fcntl(ap->state_pipe[1], F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->state_pipe[1], F_SETFD, cl_flags); +- } +- +- return 0; +-} +- + int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me) + { + char buf[MAX_ERR_BUF]; +@@ -241,10 +186,10 @@ int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, stru + + force_umount: + if (rv != 0) { +- msg("forcing umount of direct mount %s", me->key); ++ info(ap->logopt, "forcing umount of direct mount %s", me->key); + rv = umount2(me->key, MNT_DETACH); + } else +- msg("umounted direct mount %s", me->key); ++ info(ap->logopt, "umounted direct mount %s", me->key); + + if (!rv && me->dir_created) { + if (rmdir(me->key) == -1) { +@@ -326,7 +271,7 @@ static int unlink_mount_tree(struct autofs_point *ap, struct list_head *list) + continue; + + if (strcmp(mnt->fs_type, "autofs")) +- rv = spawn_umount(log_debug, "-l", mnt->path, NULL); ++ rv = spawn_umount(ap->logopt, "-l", mnt->path, NULL); + else + rv = umount2(mnt->path, MNT_DETACH); + if (rv == -1) { +@@ -475,13 +420,15 @@ int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struc + ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout); + + if (ap->exp_timeout) +- msg("mounted direct mount on %s " ++ info(ap->logopt, ++ "mounted direct mount on %s " + "with timeout %u, freq %u seconds", me->key, + (unsigned int) ap->exp_timeout, + (unsigned int) ap->exp_runfreq); + else +- msg("mounted direct mount on %s with timeouts disabled", +- me->key); ++ info(ap->logopt, ++ "mounted direct mount on %s with timeouts disabled", ++ me->key); + + ret = fstat(ioctlfd, &st); + if (ret == -1) { +@@ -522,9 +469,6 @@ int mount_autofs_direct(struct autofs_point *ap) + return -1; + } + +- if (autofs_init_direct(ap)) +- return -1; +- + /* TODO: check map type */ + if (lookup_nss_read_map(ap, NULL, now)) + lookup_prune_cache(ap, now); +@@ -607,7 +551,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me) + /* offset isn't mounted, return success and try to recover */ + if (!is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) { + debug(ap->logopt, +- "offset %s unexpectedly not mounted", ++ "offset %s not mounted", + me->key); + return 0; + } +@@ -627,7 +571,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me) + rv = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status); + if (rv) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, "ioctl failed: %s", estr); ++ logerr("ioctl failed: %s", estr); + return 1; + } else if (!status) { + if (ap->state != ST_SHUTDOWN_FORCE) { +@@ -692,10 +636,10 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me) + + force_umount: + if (rv != 0) { +- msg("forcing umount of offset mount %s", me->key); ++ info(ap->logopt, "forcing umount of offset mount %s", me->key); + rv = umount2(me->key, MNT_DETACH); + } else +- msg("umounted offset mount %s", me->key); ++ info(ap->logopt, "umounted offset mount %s", me->key); + + if (!rv && me->dir_created) { + if (rmdir(me->key) == -1) { +@@ -868,7 +812,7 @@ static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsig + return 0; + } + +- retries = (count_mounts(path, st.st_dev) + 1) * EXPIRE_RETRIES; ++ retries = (count_mounts(logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES; + + while (retries--) { + struct timespec tm = {0, 100000000}; +@@ -1018,7 +962,7 @@ void *expire_proc_direct(void *arg) + + if (me->ioctlfd != -1 && + fstat(ioctlfd, &st) != -1 && +- !count_mounts(next->path, st.st_dev)) { ++ !count_mounts(ap->logopt, next->path, st.st_dev)) { + close(ioctlfd); + me->ioctlfd = -1; + } +@@ -1049,6 +993,9 @@ void *expire_proc_direct(void *arg) + } + pthread_cleanup_pop(1); + ++ if (left) ++ info(ap->logopt, "%d remaining in %s", left, ap->path); ++ + ec.status = left; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); +@@ -1072,7 +1019,7 @@ static void pending_cond_destroy(void *arg) + static void expire_send_fail(void *arg) + { + struct pending_args *mt = arg; +- send_fail(mt->ioctlfd, mt->wait_queue_token); ++ send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token); + } + + static void free_pending_args(void *arg) +@@ -1124,14 +1071,14 @@ static void *do_expire_direct(void *arg) + status = do_expire(ap, mt->name, len); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); + if (status) +- send_fail(mt->ioctlfd, mt->wait_queue_token); ++ send_fail(ap->logopt, mt->ioctlfd, mt->wait_queue_token); + else { + struct mapent *me; + cache_readlock(mt->mc); + me = cache_lookup_distinct(mt->mc, mt->name); + me->ioctlfd = -1; + cache_unlock(mt->mc); +- send_ready(mt->ioctlfd, mt->wait_queue_token); ++ send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token); + close(mt->ioctlfd); + } + pthread_setcancelstate(state, NULL); +@@ -1194,7 +1141,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di + if (!mt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, "malloc: %s", estr); +- send_fail(me->ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, me->ioctlfd, pkt->wait_queue_token); + cache_unlock(mc); + pthread_setcancelstate(state, NULL); + return 1; +@@ -1223,7 +1170,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di + status = pthread_create(&thid, &thread_attr, do_expire_direct, mt); + if (status) { + error(ap->logopt, "expire thread create failed"); +- send_fail(mt->ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, mt->ioctlfd, pkt->wait_queue_token); + cache_unlock(mc); + expire_mutex_unlock(NULL); + pending_cond_destroy(mt); +@@ -1252,7 +1199,7 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di + static void mount_send_fail(void *arg) + { + struct pending_args *mt = arg; +- send_fail(mt->ioctlfd, mt->wait_queue_token); ++ send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token); + close(mt->ioctlfd); + } + +@@ -1319,7 +1266,7 @@ static void *do_mount_direct(void *arg) + + pthread_setcancelstate(state, NULL); + +- msg("attempting to mount entry %s", mt->name); ++ info(ap->logopt, "attempting to mount entry %s", mt->name); + + /* + * Setup thread specific data values for macro +@@ -1445,16 +1392,16 @@ cont: + cache_unlock(mt->mc); + if (set_fd) { + me->ioctlfd = mt->ioctlfd; +- send_ready(mt->ioctlfd, mt->wait_queue_token); ++ send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token); + } else { +- send_ready(mt->ioctlfd, mt->wait_queue_token); ++ send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token); + close(mt->ioctlfd); + } +- msg("mounted %s", mt->name); ++ info(ap->logopt, "mounted %s", mt->name); + } else { +- send_fail(mt->ioctlfd, mt->wait_queue_token); ++ send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token); + close(mt->ioctlfd); +- msg("failed to mount %s", mt->name); ++ info(ap->logopt, "failed to mount %s", mt->name); + } + pthread_setcancelstate(state, NULL); + +@@ -1505,7 +1452,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ + * Shouldn't happen as the kernel is telling us + * someone has walked on our mount point. + */ +- crit(ap->logopt, "can't find map entry for (%lu,%lu)", ++ logerr("can't find map entry for (%lu,%lu)", + (unsigned long) pkt->dev, (unsigned long) pkt->ino); + pthread_setcancelstate(state, NULL); + return 1; +@@ -1538,7 +1485,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ + if (ap->state == ST_SHUTDOWN_PENDING || + ap->state == ST_SHUTDOWN_FORCE || + ap->state == ST_SHUTDOWN) { +- send_fail(ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token); + close(ioctlfd); + cache_unlock(mc); + pthread_setcancelstate(state, NULL); +@@ -1549,7 +1496,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ + if (!mt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, "malloc: %s", estr); +- send_fail(ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token); + close(ioctlfd); + cache_unlock(mc); + pthread_setcancelstate(state, NULL); +@@ -1578,7 +1525,7 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ + status = pthread_create(&thid, &thread_attr, do_mount_direct, mt); + if (status) { + error(ap->logopt, "missing mount thread create failed"); +- send_fail(ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token); + close(ioctlfd); + cache_unlock(mc); + mount_mutex_unlock(NULL); +diff --git a/daemon/indirect.c b/daemon/indirect.c +index 02e7045..5c422c8 100644 +--- a/daemon/indirect.c ++++ b/daemon/indirect.c +@@ -43,63 +43,6 @@ extern pthread_attr_t thread_attr; + static pthread_mutex_t ma_mutex = PTHREAD_MUTEX_INITIALIZER; + static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER; + +-static int autofs_init_indirect(struct autofs_point *ap) +-{ +- int pipefd[2], cl_flags; +- +- if ((ap->state != ST_INIT)) { +- /* This can happen if an autofs process is already running*/ +- error(ap->logopt, "bad state %d", ap->state); +- return -1; +- } +- +- ap->pipefd = ap->kpipefd = ap->ioctlfd = -1; +- +- /* Pipe for kernel communications */ +- if (pipe(pipefd) < 0) { +- crit(ap->logopt, +- "failed to create commumication pipe for autofs path %s", +- ap->path); +- free(ap->path); +- return -1; +- } +- +- ap->pipefd = pipefd[0]; +- ap->kpipefd = pipefd[1]; +- +- if ((cl_flags = fcntl(ap->pipefd, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->pipefd, F_SETFD, cl_flags); +- } +- +- if ((cl_flags = fcntl(ap->kpipefd, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->kpipefd, F_SETFD, cl_flags); +- } +- +- /* Pipe state changes from signal handler to main loop */ +- if (pipe(ap->state_pipe) < 0) { +- crit(ap->logopt, +- "failed create state pipe for autofs path %s", ap->path); +- close(ap->pipefd); +- close(ap->kpipefd); /* Close kernel pipe end */ +- free(ap->path); +- return -1; +- } +- +- if ((cl_flags = fcntl(ap->state_pipe[0], F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->state_pipe[0], F_SETFD, cl_flags); +- } +- +- if ((cl_flags = fcntl(ap->state_pipe[1], F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(ap->state_pipe[1], F_SETFD, cl_flags); +- } +- +- return 0; +-} +- + static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts) + { + struct mnt_list *this; +@@ -118,7 +61,7 @@ static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts) + } + + if (strcmp(this->fs_type, "autofs")) +- rv = spawn_umount(log_debug, "-l", this->path, NULL); ++ rv = spawn_umount(ap->logopt, "-l", this->path, NULL); + else + rv = umount2(this->path, MNT_DETACH); + if (rv == -1) { +@@ -222,12 +165,14 @@ static int do_mount_autofs_indirect(struct autofs_point *ap) + ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout); + + if (ap->exp_timeout) +- msg("mounted indirect mount on %s " ++ info(ap->logopt, ++ "mounted indirect mount on %s " + "with timeout %u, freq %u seconds", ap->path, +- (unsigned int) ap->exp_timeout, +- (unsigned int) ap->exp_runfreq); ++ (unsigned int) ap->exp_timeout, ++ (unsigned int) ap->exp_runfreq); + else +- msg("mounted indirect mount on %s with timeouts disabled", ++ info(ap->logopt, ++ "mounted indirect mount on %s with timeouts disabled", + ap->path); + + fstat(ap->ioctlfd, &st); +@@ -257,9 +202,6 @@ int mount_autofs_indirect(struct autofs_point *ap) + int status; + int map; + +- if (autofs_init_indirect(ap)) +- return -1; +- + /* TODO: read map, determine map type is OK */ + if (lookup_nss_read_map(ap, NULL, now)) + lookup_prune_cache(ap, now); +@@ -309,7 +251,7 @@ int umount_autofs_indirect(struct autofs_point *ap) + rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret); + if (rv == -1) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, "ioctl failed: %s", estr); ++ logerr("ioctl failed: %s", estr); + return 1; + } else if (!ret) { + error(ap->logopt, "ask umount returned busy %s", ap->path); +@@ -370,9 +312,9 @@ force_umount: + "forcing umount of indirect mount %s", ap->path); + rv = umount2(ap->path, MNT_DETACH); + } else { +- msg("umounted indirect mount %s", ap->path); ++ info(ap->logopt, "umounted indirect mount %s", ap->path); + if (ap->submount) +- rm_unwanted(ap->path, 1, ap->dev); ++ rm_unwanted(ap->logopt, ap->path, 1, ap->dev); + } + + return rv; +@@ -390,7 +332,7 @@ static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *pat + return 0; + } + +- retries = (count_mounts(path, st.st_dev) + 1) * EXPIRE_RETRIES; ++ retries = (count_mounts(ap->logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES; + + while (retries--) { + struct timespec tm = {0, 100000000}; +@@ -559,13 +501,7 @@ void *expire_proc_indirect(void *arg) + * words) the umounts are done by the time we reach here + */ + if (count) +- debug(ap->logopt, "%d remaining in %s", count, ap->path); +- +- /* If we are trying to shutdown make sure we can umount */ +- if (!ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) { +- if (!ret) +- msg("mount still busy %s", ap->path); +- } ++ info(ap->logopt, "%d remaining in %s", count, ap->path); + + ec.status = left; + +@@ -590,7 +526,7 @@ static void pending_cond_destroy(void *arg) + static void expire_send_fail(void *arg) + { + struct pending_args *mt = arg; +- send_fail(mt->ap->ioctlfd, mt->wait_queue_token); ++ send_fail(mt->ap->logopt, mt->ap->ioctlfd, mt->wait_queue_token); + } + + static void free_pending_args(void *arg) +@@ -634,9 +570,9 @@ static void *do_expire_indirect(void *arg) + status = do_expire(mt->ap, mt->name, mt->len); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); + if (status) +- send_fail(ap->ioctlfd, mt->wait_queue_token); ++ send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token); + else +- send_ready(ap->ioctlfd, mt->wait_queue_token); ++ send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token); + pthread_setcancelstate(state, NULL); + + pthread_cleanup_pop(0); +@@ -661,8 +597,8 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_ + mt = malloc(sizeof(struct pending_args)); + if (!mt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, "malloc: %s", estr); +- send_fail(ap->ioctlfd, pkt->wait_queue_token); ++ logerr("malloc: %s", estr); ++ send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token); + pthread_setcancelstate(state, NULL); + return 1; + } +@@ -684,7 +620,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_ + status = pthread_create(&thid, &thread_attr, do_expire_indirect, mt); + if (status) { + error(ap->logopt, "expire thread create failed"); +- send_fail(ap->ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token); + expire_mutex_unlock(NULL); + pending_cond_destroy(mt); + free_pending_args(mt); +@@ -710,7 +646,7 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_ + static void mount_send_fail(void *arg) + { + struct pending_args *mt = arg; +- send_fail(mt->ap->ioctlfd, mt->wait_queue_token); ++ send_fail(mt->ap->logopt, mt->ap->ioctlfd, mt->wait_queue_token); + } + + static void mount_mutex_unlock(void *arg) +@@ -775,7 +711,7 @@ static void *do_mount_indirect(void *arg) + + pthread_setcancelstate(state, NULL); + +- msg("attempting to mount entry %s", buf); ++ info(ap->logopt, "attempting to mount entry %s", buf); + + /* + * Setup thread specific data values for macro +@@ -887,11 +823,11 @@ cont: + status = lookup_nss_mount(ap, NULL, mt->name, mt->len); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); + if (status) { +- send_ready(ap->ioctlfd, mt->wait_queue_token); +- msg("mounted %s", buf); ++ send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token); ++ info(ap->logopt, "mounted %s", buf); + } else { +- send_fail(ap->ioctlfd, mt->wait_queue_token); +- msg("failed to mount %s", buf); ++ send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token); ++ info(ap->logopt, "failed to mount %s", buf); + } + pthread_setcancelstate(state, NULL); + +@@ -918,7 +854,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin + if (ap->state == ST_SHUTDOWN_PENDING || + ap->state == ST_SHUTDOWN_FORCE || + ap->state == ST_SHUTDOWN) { +- send_fail(ap->ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token); + pthread_setcancelstate(state, NULL); + return 0; + } +@@ -926,8 +862,8 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin + mt = malloc(sizeof(struct pending_args)); + if (!mt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, "malloc: %s", estr); +- send_fail(ap->ioctlfd, pkt->wait_queue_token); ++ logerr("malloc: %s", estr); ++ send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token); + pthread_setcancelstate(state, NULL); + return 1; + } +@@ -953,7 +889,7 @@ int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missin + status = pthread_create(&thid, &thread_attr, do_mount_indirect, mt); + if (status) { + error(ap->logopt, "expire thread create failed"); +- send_fail(ap->ioctlfd, pkt->wait_queue_token); ++ send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token); + mount_mutex_unlock(NULL); + pending_cond_destroy(mt); + free_pending_args(mt); +diff --git a/daemon/lookup.c b/daemon/lookup.c +index 4f2b318..fd99cf2 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -103,6 +103,7 @@ static int do_read_master(struct master *master, char *type, time_t age) + + static int read_master_map(struct master *master, char *type, time_t age) + { ++ unsigned int logopt = master->logopt; + char *path, *save_name; + int result; + +@@ -117,7 +118,7 @@ static int read_master_map(struct master *master, char *type, time_t age) + */ + + if (strchr(master->name, '/')) { +- error(LOGOPT_ANY, "relative path invalid in files map name"); ++ error(logopt, "relative path invalid in files map name"); + return NSS_STATUS_NOTFOUND; + } + +@@ -142,6 +143,7 @@ static int read_master_map(struct master *master, char *type, time_t age) + + int lookup_nss_read_master(struct master *master, time_t age) + { ++ unsigned int logopt = master->logopt; + struct list_head nsslist; + struct list_head *head, *p; + int result = NSS_STATUS_UNKNOWN; +@@ -149,12 +151,10 @@ int lookup_nss_read_master(struct master *master, time_t age) + /* If it starts with a '/' it has to be a file or LDAP map */ + if (*master->name == '/') { + if (*(master->name + 1) == '/') { +- debug(LOGOPT_NONE, +- "reading master ldap %s", master->name); ++ debug(logopt, "reading master ldap %s", master->name); + result = do_read_master(master, "ldap", age); + } else { +- debug(LOGOPT_NONE, +- "reading master file %s", master->name); ++ debug(logopt, "reading master file %s", master->name); + result = do_read_master(master, "file", age); + } + +@@ -184,13 +184,11 @@ int lookup_nss_read_master(struct master *master, time_t age) + */ + if (strncmp(name, "ldap", 4)) { + master->name = tmp + 1; +- debug(LOGOPT_NONE, +- "reading master %s %s", ++ debug(logopt, "reading master %s %s", + source, master->name); + } else { + master->name = name; +- debug(LOGOPT_NONE, +- "reading master %s %s", ++ debug(logopt, "reading master %s %s", + source, tmp + 1); + } + +@@ -208,7 +206,7 @@ int lookup_nss_read_master(struct master *master, time_t age) + if (result) { + if (!list_empty(&nsslist)) + free_sources(&nsslist); +- error(LOGOPT_ANY, "can't to read name service switch config."); ++ error(logopt, "can't to read name service switch config."); + return 0; + } + +@@ -220,13 +218,12 @@ int lookup_nss_read_master(struct master *master, time_t age) + + this = list_entry(p, struct nss_source, list); + +- debug(LOGOPT_NONE, ++ debug(logopt, + "reading master %s %s", this->source, master->name); + + result = read_master_map(master, this->source, age); + if (result == NSS_STATUS_UNKNOWN) { +- debug(LOGOPT_NONE, +- "no map - continuing to next source"); ++ debug(logopt, "no map - continuing to next source"); + continue; + } + +@@ -1008,9 +1005,10 @@ int lookup_prune_cache(struct autofs_point *ap, time_t age) + if (this->ioctlfd == -1) + status = cache_delete(mc, key); + if (status != CHE_FAIL) { +- if (ap->type == LKP_INDIRECT) +- rmdir_path(ap, path, ap->dev); +- else ++ if (ap->type == LKP_INDIRECT) { ++ if (ap->ghost) ++ rmdir_path(ap, path, ap->dev); ++ } else + rmdir_path(ap, path, this->dev); + } + } +diff --git a/daemon/module.c b/daemon/module.c +index e83c929..36eca00 100644 +--- a/daemon/module.c ++++ b/daemon/module.c +@@ -33,7 +33,7 @@ int load_autofs4_module(void) + */ + fp = fopen("/proc/filesystems", "r"); + if (!fp) { +- error(LOGOPT_ANY, "cannot open /proc/filesystems\n"); ++ logerr("cannot open /proc/filesystems\n"); + return 0; + } + +@@ -45,7 +45,7 @@ int load_autofs4_module(void) + } + fclose(fp); + +- ret = spawnl(log_debug, PATH_MODPROBE, PATH_MODPROBE, ++ ret = spawnl(LOGOPT_NONE, PATH_MODPROBE, PATH_MODPROBE, + "-q", FS_MODULE_NAME, NULL); + if (ret) + return 0; +@@ -72,7 +72,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix, + if (!mod) { + if (err_prefix) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, "%s%s", err_prefix, estr); ++ logerr("%s%s", err_prefix, estr); + } + return NULL; + } +@@ -83,7 +83,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix, + free(mod); + if (err_prefix) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, "%s%s", err_prefix, estr); ++ logerr("%s%s", err_prefix, estr); + } + return NULL; + } +@@ -91,7 +91,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix, + + if (!(dh = dlopen(fnbuf, RTLD_NOW))) { + if (err_prefix) +- crit(LOGOPT_ANY, "%scannot open lookup module %s (%s)", ++ logerr("%scannot open lookup module %s (%s)", + err_prefix, name, dlerror()); + free(mod); + return NULL; +@@ -100,8 +100,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix, + if (!(ver = (int *) dlsym(dh, "lookup_version")) + || *ver != AUTOFS_LOOKUP_VERSION) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%slookup module %s version mismatch", ++ logerr("%slookup module %s version mismatch", + err_prefix, name); + dlclose(dh); + free(mod); +@@ -114,7 +113,7 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix, + !(mod->lookup_mount = (lookup_mount_t) dlsym(dh, "lookup_mount")) || + !(mod->lookup_done = (lookup_done_t) dlsym(dh, "lookup_done"))) { + if (err_prefix) +- crit(LOGOPT_ANY, "%slookup module %s corrupt", err_prefix, name); ++ logerr("%slookup module %s corrupt", err_prefix, name); + dlclose(dh); + free(mod); + return NULL; +@@ -156,7 +155,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix, + if (!mod) { + if (err_prefix) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, "%s%s", err_prefix, estr); ++ logerr("%s%s", err_prefix, estr); + } + return NULL; + } +@@ -167,7 +166,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix, + free(mod); + if (err_prefix) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, "%s%s", err_prefix, estr); ++ logerr("%s%s", err_prefix, estr); + } + return NULL; + } +@@ -175,8 +174,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix, + + if (!(dh = dlopen(fnbuf, RTLD_NOW))) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%scannot open parse module %s (%s)", ++ logerr("%scannot open parse module %s (%s)", + err_prefix, name, dlerror()); + free(mod); + return NULL; +@@ -185,8 +183,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix, + if (!(ver = (int *) dlsym(dh, "parse_version")) + || *ver != AUTOFS_PARSE_VERSION) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%sparse module %s version mismatch", ++ logerr("%sparse module %s version mismatch", + err_prefix, name); + dlclose(dh); + free(mod); +@@ -197,8 +194,7 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix, + !(mod->parse_mount = (parse_mount_t) dlsym(dh, "parse_mount")) || + !(mod->parse_done = (parse_done_t) dlsym(dh, "parse_done"))) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%sparse module %s corrupt", ++ logerr("%sparse module %s corrupt", + err_prefix, name); + dlclose(dh); + free(mod); +@@ -240,7 +236,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix) + if (!mod) { + if (err_prefix) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, "%s%s", err_prefix, estr); ++ logerr("%s%s", err_prefix, estr); + } + return NULL; + } +@@ -251,7 +247,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix) + free(mod); + if (err_prefix) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, "%s%s", err_prefix, estr); ++ logerr("%s%s", err_prefix, estr); + } + return NULL; + } +@@ -259,8 +255,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix) + + if (!(dh = dlopen(fnbuf, RTLD_NOW))) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%scannot open mount module %s (%s)", ++ logerr("%scannot open mount module %s (%s)", + err_prefix, name, dlerror()); + free(mod); + return NULL; +@@ -269,8 +264,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix) + if (!(ver = (int *) dlsym(dh, "mount_version")) + || *ver != AUTOFS_MOUNT_VERSION) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%smount module %s version mismatch", ++ logerr("%smount module %s version mismatch", + err_prefix, name); + dlclose(dh); + free(mod); +@@ -281,8 +275,7 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix) + !(mod->mount_mount = (mount_mount_t) dlsym(dh, "mount_mount")) || + !(mod->mount_done = (mount_done_t) dlsym(dh, "mount_done"))) { + if (err_prefix) +- crit(LOGOPT_ANY, +- "%smount module %s corrupt", ++ logerr("%smount module %s corrupt", + err_prefix, name); + dlclose(dh); + free(mod); +diff --git a/daemon/spawn.c b/daemon/spawn.c +index 271d37e..3d5ea56 100644 +--- a/daemon/spawn.c ++++ b/daemon/spawn.c +@@ -88,7 +88,7 @@ void reset_signals(void) + + #define ERRBUFSIZ 2047 /* Max length of error string excl \0 */ + +-static int do_spawn(logger *log, unsigned int options, const char *prog, const char *const *argv) ++static int do_spawn(unsigned logopt, unsigned int options, const char *prog, const char *const *argv) + { + pid_t f; + int ret, status, pipefd[2]; +@@ -195,7 +195,7 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c + while (errp && (p = memchr(sp, '\n', errp))) { + *p++ = '\0'; + if (sp[0]) /* Don't output empty lines */ +- log(LOGOPT_ANY, ">> %s", sp); ++ warn(logopt, ">> %s", sp); + errp -= (p - sp); + sp = p; + } +@@ -206,7 +206,7 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c + if (errp >= ERRBUFSIZ) { + /* Line too long, split */ + errbuf[errp] = '\0'; +- log(LOGOPT_ANY, ">> %s", errbuf); ++ warn(logopt, ">> %s", errbuf); + errp = 0; + } + } +@@ -217,7 +217,7 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c + if (errp > 0) { + /* End of file without \n */ + errbuf[errp] = '\0'; +- log(LOGOPT_ANY, ">> %s", errbuf); ++ warn(logopt, ">> %s", errbuf); + } + + if (waitpid(f, &ret, 0) != f) +@@ -235,12 +235,12 @@ static int do_spawn(logger *log, unsigned int options, const char *prog, const c + } + } + +-int spawnv(logger *log, const char *prog, const char *const *argv) ++int spawnv(unsigned logopt, const char *prog, const char *const *argv) + { +- return do_spawn(log, SPAWN_OPT_NONE, prog, argv); ++ return do_spawn(logopt, SPAWN_OPT_NONE, prog, argv); + } + +-int spawnl(logger *log, const char *prog, ...) ++int spawnl(unsigned logopt, const char *prog, ...) + { + va_list arg; + int argc; +@@ -258,10 +258,10 @@ int spawnl(logger *log, const char *prog, ...) + while ((*p++ = va_arg(arg, char *))); + va_end(arg); + +- return do_spawn(log, SPAWN_OPT_NONE, prog, (const char **) argv); ++ return do_spawn(logopt, SPAWN_OPT_NONE, prog, (const char **) argv); + } + +-int spawn_mount(logger *log, ...) ++int spawn_mount(unsigned logopt, ...) + { + va_list arg; + int argc; +@@ -279,7 +279,7 @@ int spawn_mount(logger *log, ...) + options = SPAWN_OPT_NONE; + #endif + +- va_start(arg, log); ++ va_start(arg, logopt); + for (argc = 1; va_arg(arg, char *); argc++); + va_end(arg); + +@@ -288,13 +288,13 @@ int spawn_mount(logger *log, ...) + + argv[0] = arg0; + +- va_start(arg, log); ++ va_start(arg, logopt); + p = argv + 1; + while ((*p++ = va_arg(arg, char *))); + va_end(arg); + + while (retries--) { +- ret = do_spawn(log, options, prog, (const char **) argv); ++ ret = do_spawn(logopt, options, prog, (const char **) argv); + if (ret & MTAB_NOTUPDATED) + continue; + break; +@@ -311,7 +311,7 @@ int spawn_mount(logger *log, ...) + * NOTE: If mount locking is enabled this type of recursive mount cannot + * work. + */ +-int spawn_bind_mount(logger *log, ...) ++int spawn_bind_mount(unsigned logopt, ...) + { + va_list arg; + int argc; +@@ -330,7 +330,7 @@ int spawn_bind_mount(logger *log, ...) + options = SPAWN_OPT_ACCESS; + #endif + +- va_start(arg, log); ++ va_start(arg, logopt); + for (argc = 1; va_arg(arg, char *); argc++); + va_end(arg); + +@@ -340,13 +340,13 @@ int spawn_bind_mount(logger *log, ...) + argv[0] = arg0; + argv[1] = bind; + +- va_start(arg, log); ++ va_start(arg, logopt); + p = argv + 2; + while ((*p++ = va_arg(arg, char *))); + va_end(arg); + + while (retries--) { +- ret = do_spawn(log, options, prog, (const char **) argv); ++ ret = do_spawn(logopt, options, prog, (const char **) argv); + if (ret & MTAB_NOTUPDATED) + continue; + break; +@@ -355,7 +355,7 @@ int spawn_bind_mount(logger *log, ...) + return ret; + } + +-int spawn_umount(logger *log, ...) ++int spawn_umount(unsigned logopt, ...) + { + va_list arg; + int argc; +@@ -372,7 +372,7 @@ int spawn_umount(logger *log, ...) + options = SPAWN_OPT_NONE; + #endif + +- va_start(arg, log); ++ va_start(arg, logopt); + for (argc = 1; va_arg(arg, char *); argc++); + va_end(arg); + +@@ -381,13 +381,13 @@ int spawn_umount(logger *log, ...) + + argv[0] = arg0; + +- va_start(arg, log); ++ va_start(arg, logopt); + p = argv + 1; + while ((*p++ = va_arg(arg, char *))); + va_end(arg); + + while (retries--) { +- ret = do_spawn(log, options, prog, (const char **) argv); ++ ret = do_spawn(logopt, options, prog, (const char **) argv); + if (ret & MTAB_NOTUPDATED) + continue; + break; +diff --git a/daemon/state.c b/daemon/state.c +index 39f4497..a2da762 100644 +--- a/daemon/state.c ++++ b/daemon/state.c +@@ -58,22 +58,20 @@ void dump_state_queue(void) + struct list_head *head = &state_queue; + struct list_head *p, *q; + +- debug(LOGOPT_ANY, "dumping queue"); ++ logmsg("dumping queue"); + + list_for_each(p, head) { + struct state_queue *entry; + + entry = list_entry(p, struct state_queue, list); +- debug(LOGOPT_ANY, +- "queue list head path %s state %d busy %d", ++ logmsg("queue list head path %s state %d busy %d", + entry->ap->path, entry->state, entry->busy); + + list_for_each(q, &entry->pending) { + struct state_queue *this; + + this = list_entry(q, struct state_queue, pending); +- debug(LOGOPT_ANY, +- "queue list entry path %s state %d busy %d", ++ logmsg("queue list entry path %s state %d busy %d", + this->ap->path, this->state, this->busy); + } + } +@@ -85,7 +83,7 @@ void nextstate(int statefd, enum states next) + + if (write(statefd, &next, sizeof(next)) != sizeof(next)) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "write failed %s", estr); ++ logerr("write failed %s", estr); + } + } + +diff --git a/include/automount.h b/include/automount.h +index d55ba5c..37a3c0a 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -131,6 +131,7 @@ struct mapent_cache { + unsigned int size; + pthread_mutex_t ino_index_mutex; + struct list_head *ino_index; ++ struct autofs_point *ap; + struct map_source *map; + struct mapent **hash; + }; +@@ -164,7 +165,7 @@ void cache_readlock(struct mapent_cache *mc); + void cache_writelock(struct mapent_cache *mc); + int cache_try_writelock(struct mapent_cache *mc); + void cache_unlock(struct mapent_cache *mc); +-struct mapent_cache *cache_init(struct map_source *map); ++struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map); + struct mapent_cache *cache_init_null_cache(struct master *master); + int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino); + /* void cache_set_ino(struct mapent *me, dev_t dev, ino_t ino); */ +@@ -200,11 +201,11 @@ int free_argv(int argc, const char **argv); + inline void dump_core(void); + int aquire_lock(void); + void release_lock(void); +-int spawnl(logger *log, const char *prog, ...); +-int spawnv(logger *log, const char *prog, const char *const *argv); +-int spawn_mount(logger *log, ...); +-int spawn_bind_mount(logger *log, ...); +-int spawn_umount(logger *log, ...); ++int spawnl(unsigned logopt, const char *prog, ...); ++int spawnv(unsigned logopt, const char *prog, const char *const *argv); ++int spawn_mount(unsigned logopt, ...); ++int spawn_bind_mount(unsigned logopt, ...); ++int spawn_umount(unsigned logopt, ...); + void reset_signals(void); + int do_mount(struct autofs_point *ap, const char *root, const char *name, + int name_len, const char *what, const char *fstype, +@@ -222,6 +223,8 @@ int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev); + #define MAPENT_MAX_LEN 4095 + #define PARSE_MAX_BUF KEY_MAX_LEN + MAPENT_MAX_LEN + 2 + ++#define AUTOFS_LOGPRI_FIFO "/tmp/autofs.fifo" ++ + int lookup_nss_read_master(struct master *master, time_t age); + int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time_t age); + int lookup_enumerate(struct autofs_point *ap, +@@ -435,6 +438,7 @@ struct autofs_point { + int pipefd; /* File descriptor for pipe */ + int kpipefd; /* Kernel end descriptor for pipe */ + int ioctlfd; /* File descriptor for ioctls */ ++ int logpri_fifo; /* FIFO used for changing log levels */ + dev_t dev; /* "Device" number assigned by kernel */ + struct master_mapent *entry; /* Master map entry for this mount */ + unsigned int type; /* Type of map direct or indirect */ +@@ -464,8 +468,8 @@ struct autofs_point { + + void *handle_mounts(void *arg); + int umount_multi(struct autofs_point *ap, const char *path, int incl); +-int send_ready(int ioctlfd, unsigned int wait_queue_token); +-int send_fail(int ioctlfd, unsigned int wait_queue_token); ++int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token); ++int send_fail(unsigned logopt, int ioctlfd, unsigned int wait_queue_token); + int do_expire(struct autofs_point *ap, const char *name, int namelen); + void *expire_proc_indirect(void *); + void *expire_proc_direct(void *); +@@ -483,8 +487,8 @@ int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_ + int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_direct_t *pkt); + int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missing_indirect_t *pkt); + int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_direct_t *pkt); +-void rm_unwanted(const char *path, int incl, dev_t dev); +-int count_mounts(const char *path, dev_t dev); ++void rm_unwanted(unsigned logopt, const char *path, int incl, dev_t dev); ++int count_mounts(unsigned logopt, const char *path, dev_t dev); + + #define state_mutex_lock(ap) \ + do { \ +diff --git a/include/log.h b/include/log.h +index 3276cca..6a4a942 100644 +--- a/include/log.h ++++ b/include/log.h +@@ -20,6 +20,7 @@ + /* Define logging functions */ + + #define LOGOPT_NONE 0x0000 ++#define LOGOPT_ERROR 0x0000 + #define LOGOPT_DEBUG 0x0001 + #define LOGOPT_VERBOSE 0x0002 + #define LOGOPT_ANY (LOGOPT_DEBUG | LOGOPT_VERBOSE) +@@ -29,34 +30,33 @@ struct autofs_point; + extern void set_log_norm(void); + extern void set_log_verbose(void); + extern void set_log_debug(void); +-extern void set_mnt_logging(struct autofs_point *); ++extern void set_log_norm_ap(struct autofs_point *ap); ++extern void set_log_verbose_ap(struct autofs_point *ap); ++extern void set_log_debug_ap(struct autofs_point *ap); ++extern void set_mnt_logging(unsigned global_logopt); + + extern void log_to_syslog(void); + extern void log_to_stderr(void); + +-typedef void logger(unsigned int logopt, const char* msg, ...); +- +-extern void (*log_info)(unsigned int, const char* msg, ...); +-extern void (*log_notice)(unsigned int, const char* msg, ...); +-extern void (*log_warn)(unsigned int, const char* msg, ...); +-extern void (*log_error)(unsigned int, const char* msg, ...); +-extern void (*log_crit)(unsigned int, const char* msg, ...); +-extern void (*log_debug)(unsigned int, const char* msg, ...); +- +-#define msg(msg, args...) \ +- do { log_info(LOGOPT_NONE, msg, ##args); } while (0) ++extern void log_info(unsigned int, const char* msg, ...); ++extern void log_notice(unsigned int, const char* msg, ...); ++extern void log_warn(unsigned int, const char* msg, ...); ++extern void log_error(unsigned, const char* msg, ...); ++extern void log_crit(unsigned, const char* msg, ...); ++extern void log_debug(unsigned int, const char* msg, ...); ++extern void logmsg(const char* msg, ...); + + #define debug(opt, msg, args...) \ + do { log_debug(opt, "%s: " msg, __FUNCTION__, ##args); } while (0) + +-#define info(opt, msg, args...) \ +- do { log_info(opt, "%s: " msg, __FUNCTION__, ##args); } while (0) ++#define info(opt, msg, args...) \ ++ do { log_info(opt, msg, ##args); } while (0) + + #define notice(opt, msg, args...) \ +- do { log_notice(opt, "%s: " msg, __FUNCTION__, ##args); } while (0) ++ do { log_notice(opt, msg, ##args); } while (0) + +-#define warn(opt, msg, args...) \ +- do { log_warn(opt, "%s: " msg, __FUNCTION__, ##args); } while (0) ++#define warn(opt, msg, args...) \ ++ do { log_warn(opt, msg, ##args); } while (0) + + #define error(opt, msg, args...) \ + do { log_error(opt, "%s: " msg, __FUNCTION__, ##args); } while (0) +@@ -64,17 +64,18 @@ extern void (*log_debug)(unsigned int, const char* msg, ...); + #define crit(opt, msg, args...) \ + do { log_crit(opt, "%s: " msg, __FUNCTION__, ##args); } while (0) + ++#define logerr(msg, args...) \ ++ do { logmsg("%s:%d: " msg, __FUNCTION__, __LINE__, ##args); } while (0) ++ + #define fatal(status) \ + do { \ + if (status == EDEADLK) { \ +- log_crit(LOGOPT_ANY, \ +- "%s: deadlock detected " \ ++ logmsg("deadlock detected " \ + "at line %d in %s, dumping core.", \ +- __FUNCTION__, __LINE__, __FILE__); \ ++ __LINE__, __FILE__); \ + dump_core(); \ + } \ +- log_crit(LOGOPT_ANY, \ +- "unexpected pthreads error: %d at %d " \ ++ logmsg("unexpected pthreads error: %d at %d " \ + "in %s", status, __LINE__, __FILE__); \ + abort(); \ + } while(0) +@@ -83,7 +84,7 @@ extern void (*log_debug)(unsigned int, const char* msg, ...); + #define assert(x) \ + do { \ + if (!(x)) { \ +- log_crit(LOGOPT_ANY, __FILE__ \ ++ logmsg(__FILE__ \ + ":%d: assertion failed: " #x, __LINE__); \ + } \ + } while(0) +diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h +index ca8d658..5b5c475 100644 +--- a/include/lookup_ldap.h ++++ b/include/lookup_ldap.h +@@ -94,13 +94,13 @@ struct lookup_context { + #define LDAP_AUTH_AUTODETECT 0x0004 + + /* lookup_ldap.c */ +-LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt); +-int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt); ++LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt); ++int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt); + int authtype_requires_creds(const char *authtype); + + /* cyrus-sasl.c */ +-int autofs_sasl_init(LDAP *ldap, struct lookup_context *ctxt); +-int autofs_sasl_bind(LDAP *ldap, struct lookup_context *ctxt); ++int autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt); ++int autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt); + void autofs_sasl_unbind(struct lookup_context *ctxt); + void autofs_sasl_done(struct lookup_context *ctxt); + #endif +diff --git a/include/master.h b/include/master.h +index 8470bb1..5f10d1f 100644 +--- a/include/master.h ++++ b/include/master.h +@@ -62,6 +62,7 @@ struct master { + unsigned int default_ghost; + unsigned int default_logging; + unsigned int default_timeout; ++ unsigned int logopt; + struct mapent_cache *nc; + struct list_head mounts; + }; +@@ -106,6 +107,7 @@ int master_notify_submount(struct autofs_point *, const char *path, enum states) + void master_signal_submount(struct autofs_point *, unsigned int); + void master_notify_state_change(struct master *, int); + int master_mount_mounts(struct master *, time_t, int); ++extern inline unsigned int master_get_logopt(void); + int master_list_empty(struct master *); + int master_kill(struct master *); + +diff --git a/include/replicated.h b/include/replicated.h +index 3afe9f7..672f853 100644 +--- a/include/replicated.h ++++ b/include/replicated.h +@@ -62,8 +62,8 @@ struct host { + + void seed_random(void); + void free_host_list(struct host **); +-int parse_location(struct host **, const char *); +-int prune_host_list(struct host **, unsigned int, const char *, unsigned int); ++int parse_location(unsigned, struct host **, const char *); ++int prune_host_list(unsigned, struct host **, unsigned int, const char *, unsigned int); + void dump_host_list(struct host *); + + #endif +diff --git a/lib/alarm.c b/lib/alarm.c +index 90bf7aa..6a70ed1 100755 +--- a/lib/alarm.c ++++ b/lib/alarm.c +@@ -51,7 +51,7 @@ void dump_alarms(void) + struct alarm *this; + + this = list_entry(p, struct alarm, list); +- msg("alarm time = %d", this->time); ++ logmsg("alarm time = %d", this->time); + } + pthread_mutex_unlock(&mutex); + } +diff --git a/lib/args.c b/lib/args.c +index fbfb004..9616598 100644 +--- a/lib/args.c ++++ b/lib/args.c +@@ -37,7 +37,7 @@ char **add_argv(int argc, char **argv, char *str) + if (argv[i]) { + vector[i] = strdup(argv[i]); + if (!vector[i]) { +- error(LOGOPT_ANY, "failed to strdup arg"); ++ logerr("failed to strdup arg"); + break; + } + } else +@@ -81,7 +81,7 @@ char **append_argv(int argc1, char **argv1, int argc2, char **argv2) + if (argv2[j]) { + vector[i] = strdup(argv2[j]); + if (!vector[i]) { +- error(LOGOPT_ANY, "failed to strdup arg"); ++ logerr("failed to strdup arg"); + break; + } + } else +@@ -116,7 +116,7 @@ const char **copy_argv(int argc, const char **argv) + if (argv[i]) { + vector[i] = strdup(argv[i]); + if (!vector[i]) { +- error(LOGOPT_ANY, "failed to strdup arg"); ++ logerr("failed to strdup arg"); + break; + } + } else +diff --git a/lib/cache.c b/lib/cache.c +index 06bb461..55586a3 100644 +--- a/lib/cache.c ++++ b/lib/cache.c +@@ -34,7 +34,7 @@ void cache_dump_multi(struct list_head *list) + + list_for_each(p, list) { + me = list_entry(p, struct mapent, multi_list); +- msg("key=%s", me->key); ++ logmsg("key=%s", me->key); + } + } + +@@ -48,7 +48,7 @@ void cache_dump_cache(struct mapent_cache *mc) + if (me == NULL) + continue; + while (me) { +- msg("me->key=%s me->multi=%p dev=%ld ino=%ld", ++ logmsg("me->key=%s me->multi=%p dev=%ld ino=%ld", + me->key, me->multi, me->dev, me->ino); + me = me->next; + } +@@ -61,7 +61,7 @@ void cache_readlock(struct mapent_cache *mc) + + status = pthread_rwlock_rdlock(&mc->rwlock); + if (status) { +- error(LOGOPT_ANY, "mapent cache rwlock lock failed"); ++ logmsg("mapent cache rwlock lock failed"); + fatal(status); + } + return; +@@ -73,7 +73,7 @@ void cache_writelock(struct mapent_cache *mc) + + status = pthread_rwlock_wrlock(&mc->rwlock); + if (status) { +- error(LOGOPT_ANY, "mapent cache rwlock lock failed"); ++ logmsg("mapent cache rwlock lock failed"); + fatal(status); + } + return; +@@ -85,7 +85,7 @@ int cache_try_writelock(struct mapent_cache *mc) + + status = pthread_rwlock_trywrlock(&mc->rwlock); + if (status) { +- debug(LOGOPT_ANY, "mapent cache rwlock busy"); ++ logmsg("mapent cache rwlock busy"); + return 0; + } + return 1; +@@ -97,7 +97,7 @@ void cache_unlock(struct mapent_cache *mc) + + status = pthread_rwlock_unlock(&mc->rwlock); + if (status) { +- error(LOGOPT_ANY, "mapent cache rwlock unlock failed"); ++ logmsg("mapent cache rwlock unlock failed"); + fatal(status); + } + return; +@@ -120,7 +120,7 @@ void cache_multi_lock(struct mapent *me) + + status = pthread_mutex_lock(&me->multi_mutex); + if (status) { +- error(LOGOPT_ANY, "mapent cache multi mutex lock failed"); ++ logmsg("mapent cache multi mutex lock failed"); + fatal(status); + } + return; +@@ -135,7 +135,7 @@ void cache_multi_unlock(struct mapent *me) + + status = pthread_mutex_unlock(&me->multi_mutex); + if (status) { +- error(LOGOPT_ANY, "mapent cache multi mutex unlock failed"); ++ logmsg("mapent cache multi mutex unlock failed"); + fatal(status); + } + return; +@@ -164,7 +164,7 @@ static inline void ino_index_unlock(struct mapent_cache *mc) + return; + } + +-struct mapent_cache *cache_init(struct map_source *map) ++struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map) + { + struct mapent_cache *mc; + unsigned int i; +@@ -207,6 +207,7 @@ struct mapent_cache *cache_init(struct map_source *map) + INIT_LIST_HEAD(&mc->ino_index[i]); + } + ++ mc->ap = ap; + mc->map = map; + + cache_unlock(mc); +@@ -257,6 +258,9 @@ struct mapent_cache *cache_init_null_cache(struct master *master) + INIT_LIST_HEAD(&mc->ino_index[i]); + } + ++ mc->ap = NULL; ++ mc->map = NULL; ++ + cache_unlock(mc); + + return mc; +@@ -608,6 +612,7 @@ static void cache_add_ordered_offset(struct mapent *me, struct list_head *head) + /* cache must be write locked by caller */ + int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age) + { ++ unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt(); + struct mapent *me, *owner; + int ret = CHE_OK; + +@@ -621,7 +626,7 @@ int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, + + ret = cache_add(mc, owner->source, key, mapent, age); + if (ret == CHE_FAIL) { +- warn(LOGOPT_ANY, "failed to add key %s to cache", key); ++ warn(logopt, "failed to add key %s to cache", key); + return CHE_FAIL; + } + +@@ -689,6 +694,7 @@ int cache_set_parents(struct mapent *mm) + /* cache must be write locked by caller */ + int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age) + { ++ unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt(); + struct mapent *me = NULL; + char *pent; + int ret = CHE_OK; +@@ -697,7 +703,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key + if (!me || (*me->key == '*' && *key != '*')) { + ret = cache_add(mc, ms, key, mapent, age); + if (!ret) { +- debug(LOGOPT_NONE, "failed for %s", key); ++ debug(logopt, "failed for %s", key); + return CHE_FAIL; + } + ret = CHE_UPDATED; +@@ -796,6 +802,7 @@ done: + /* cache must be write locked by caller */ + int cache_delete_offset_list(struct mapent_cache *mc, const char *key) + { ++ unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt(); + struct mapent *me; + struct mapent *this; + struct list_head *head, *next; +@@ -816,7 +823,7 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key) + this = list_entry(next, struct mapent, multi_list); + next = next->next; + if (this->ioctlfd != -1) { +- error(LOGOPT_ANY, ++ error(logopt, + "active offset mount key %s", this->key); + return CHE_FAIL; + } +@@ -829,10 +836,10 @@ int cache_delete_offset_list(struct mapent_cache *mc, const char *key) + next = next->next; + list_del_init(&this->multi_list); + this->multi = NULL; +- debug(LOGOPT_NONE, "deleting offset key %s", this->key); ++ debug(logopt, "deleting offset key %s", this->key); + status = cache_delete(mc, this->key); + if (status == CHE_FAIL) { +- warn(LOGOPT_ANY, ++ warn(logopt, + "failed to delete offset %s", this->key); + this->multi = me; + /* TODO: add list back in */ +diff --git a/lib/defaults.c b/lib/defaults.c +index 2cccf20..94885e8 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -105,17 +105,22 @@ static int get_env_yesno(const char *name) + * We've changed the key names so we need to check for the + * config key and it's old name for backward conpatibility. + */ +-static int check_set_config_value(const char *res, const char *name, const char *value) ++static int check_set_config_value(const char *res, const char *name, const char *value, unsigned to_syslog) + { + char *old_name; + int ret; + + if (!strcasecmp(res, name)) { + ret = setenv(name, value, 0); +- if (ret) +- fprintf(stderr, +- "can't set config value for %s, " +- "error %d", name, ret); ++ if (ret) { ++ if (!to_syslog) ++ fprintf(stderr, ++ "can't set config value for %s, " ++ "error %d\n", name, ret); ++ else ++ logmsg("can't set config value for %s, " ++ "error %d", name, ret); ++ } + return 1; + } + +@@ -125,10 +130,15 @@ static int check_set_config_value(const char *res, const char *name, const char + + if (!strcasecmp(res, old_name)) { + ret = setenv(name, value, 0); +- if (ret) +- fprintf(stderr, +- "can't set config value for %s, " +- "error %d", name, ret); ++ if (ret) { ++ if (!to_syslog) ++ fprintf(stderr, ++ "can't set config value for %s, " ++ "error %d\n", name, ret); ++ else ++ logmsg("can't set config value for %s, " ++ "error %d\n", name, ret); ++ } + return 1; + } + return 0; +@@ -296,19 +306,19 @@ unsigned int defaults_read_config(unsigned int to_syslog) + if (!parse_line(res, &key, &value)) + continue; + +- if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value) || +- check_set_config_value(key, ENV_NAME_TIMEOUT, value) || +- check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) || +- check_set_config_value(key, ENV_NAME_LOGGING, value) || +- check_set_config_value(key, ENV_LDAP_TIMEOUT, value) || +- check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value) || +- check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) || +- check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) || +- check_set_config_value(key, ENV_NAME_MAP_ATTR, value) || +- check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value) || +- check_set_config_value(key, ENV_NAME_VALUE_ATTR, value) || +- check_set_config_value(key, ENV_APPEND_OPTIONS, value) || +- check_set_config_value(key, ENV_AUTH_CONF_FILE, value)) ++ if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_TIMEOUT, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_BROWSE_MODE, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_LOGGING, value, to_syslog) || ++ check_set_config_value(key, ENV_LDAP_TIMEOUT, value, to_syslog) || ++ check_set_config_value(key, ENV_LDAP_NETWORK_TIMEOUT, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_MAP_ATTR, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_VALUE_ATTR, value, to_syslog) || ++ check_set_config_value(key, ENV_APPEND_OPTIONS, value, to_syslog) || ++ check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog)) + ; + } + +@@ -318,8 +328,7 @@ unsigned int defaults_read_config(unsigned int to_syslog) + "fgets returned error %d while reading %s\n", + ferror(f), DEFAULTS_CONFIG_FILE); + } else { +- error(LOGOPT_ANY, +- "fgets returned error %d while reading %s", ++ logmsg("fgets returned error %d while reading %s", + ferror(f), DEFAULTS_CONFIG_FILE); + } + fclose(f); +diff --git a/lib/log.c b/lib/log.c +index b747e12..65e8ad2 100644 +--- a/lib/log.c ++++ b/lib/log.c +@@ -27,11 +27,6 @@ + + #include "automount.h" + +-/* +-struct syslog_data syslog_context = AUTOFS_SYSLOG_CONTEXT; +-struct syslog_data *slc = &syslog_context; +-*/ +- + static unsigned int syslog_open = 0; + static unsigned int logging_to_syslog = 0; + +@@ -39,32 +34,44 @@ static unsigned int logging_to_syslog = 0; + static unsigned int do_verbose = 0; /* Verbose feedback option */ + static unsigned int do_debug = 0; /* Full debug output */ + +-static void null(unsigned int logopt, const char *msg, ...) { } +- +-void (*log_info)(unsigned int logopt, const char* msg, ...) = null; +-void (*log_notice)(unsigned int logopt, const char* msg, ...) = null; +-void (*log_warn)(unsigned int logopt, const char* msg, ...) = null; +-void (*log_error)(unsigned int logopt, const char* msg, ...) = null; +-void (*log_crit)(unsigned int logopt, const char* msg, ...) = null; +-void (*log_debug)(unsigned int logopt, const char* msg, ...) = null; +- + void set_log_norm(void) + { + do_verbose = 0; + do_debug = 0; ++ return; + } + + void set_log_verbose(void) + { + do_verbose = 1; ++ return; + } + + void set_log_debug(void) + { + do_debug = 1; ++ return; ++} ++ ++void set_log_norm_ap(struct autofs_point *ap) ++{ ++ ap->logopt = LOGOPT_ERROR; ++ return; ++} ++ ++void set_log_verbose_ap(struct autofs_point *ap) ++{ ++ ap->logopt = LOGOPT_VERBOSE; ++ return; ++} ++ ++void set_log_debug_ap(struct autofs_point *ap) ++{ ++ ap->logopt = LOGOPT_DEBUG; ++ return; + } + +-static void syslog_info(unsigned int logopt, const char *msg, ...) ++void log_info(unsigned int logopt, const char *msg, ...) + { + unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE); + va_list ap; +@@ -73,11 +80,18 @@ static void syslog_info(unsigned int logopt, const char *msg, ...) + return; + + va_start(ap, msg); +- vsyslog(LOG_INFO, msg, ap); ++ if (logging_to_syslog) ++ vsyslog(LOG_INFO, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } + va_end(ap); ++ ++ return; + } + +-static void syslog_notice(unsigned int logopt, const char *msg, ...) ++void log_notice(unsigned int logopt, const char *msg, ...) + { + unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE); + va_list ap; +@@ -86,11 +100,18 @@ static void syslog_notice(unsigned int logopt, const char *msg, ...) + return; + + va_start(ap, msg); +- vsyslog(LOG_NOTICE, msg, ap); ++ if (logging_to_syslog) ++ vsyslog(LOG_NOTICE, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } + va_end(ap); ++ ++ return; + } + +-static void syslog_warn(unsigned int logopt, const char *msg, ...) ++void log_warn(unsigned int logopt, const char *msg, ...) + { + unsigned int opt_log = logopt & (LOGOPT_DEBUG | LOGOPT_VERBOSE); + va_list ap; +@@ -99,70 +120,79 @@ static void syslog_warn(unsigned int logopt, const char *msg, ...) + return; + + va_start(ap, msg); +- vsyslog(LOG_WARNING, msg, ap); ++ if (logging_to_syslog) ++ vsyslog(LOG_WARNING, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } + va_end(ap); ++ ++ return; + } + +-static void syslog_err(unsigned int logopt, const char *msg, ...) ++void log_error(unsigned logopt, const char *msg, ...) + { + va_list ap; ++ + va_start(ap, msg); +- vsyslog(LOG_ERR, msg, ap); ++ if (logging_to_syslog) ++ vsyslog(LOG_ERR, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } + va_end(ap); ++ return; + } + +-static void syslog_crit(unsigned int logopt, const char *msg, ...) ++void log_crit(unsigned logopt, const char *msg, ...) + { + va_list ap; ++ + va_start(ap, msg); +- vsyslog(LOG_CRIT, msg, ap); ++ if (logging_to_syslog) ++ vsyslog(LOG_CRIT, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } + va_end(ap); ++ return; + } + +-static void syslog_debug(unsigned int logopt, const char *msg, ...) ++void log_debug(unsigned int logopt, const char *msg, ...) + { ++ unsigned int opt_log = logopt & LOGOPT_DEBUG; + va_list ap; + +- if (!do_debug && !(logopt & LOGOPT_DEBUG)) ++ if (!do_debug && !opt_log) + return; + + va_start(ap, msg); +- vsyslog(LOG_DEBUG, msg, ap); ++ if (logging_to_syslog) ++ vsyslog(LOG_WARNING, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); ++ } + va_end(ap); ++ ++ return; + } + +-static void to_stderr(unsigned int logopt, const char *msg, ...) ++void logmsg(const char *msg, ...) + { + va_list ap; + va_start(ap, msg); +- vfprintf(stderr, msg, ap); +- fputc('\n',stderr); +- va_end(ap); +-} +- +-void set_mnt_logging(struct autofs_point *ap) +-{ +- unsigned int opt_verbose = ap->logopt & LOGOPT_VERBOSE; +- unsigned int opt_debug = ap->logopt & LOGOPT_DEBUG; +- +- if (opt_debug) { +- if (logging_to_syslog) +- log_debug = syslog_debug; +- else +- log_debug = to_stderr; +- } +- +- if (opt_verbose || opt_debug) { +- if (logging_to_syslog) { +- log_info = syslog_info; +- log_notice = syslog_notice; +- log_warn = syslog_warn; +- } else { +- log_info = to_stderr; +- log_notice = to_stderr; +- log_warn = to_stderr; +- } ++ if (logging_to_syslog) ++ vsyslog(LOG_CRIT, msg, ap); ++ else { ++ vfprintf(stderr, msg, ap); ++ fputc('\n', stderr); + } ++ va_end(ap); ++ return; + } + + void log_to_syslog(void) +@@ -175,31 +205,13 @@ void log_to_syslog(void) + openlog("automount", LOG_PID, LOG_DAEMON); + } + +- if (do_debug) +- log_debug = syslog_debug; +- else +- log_debug = null; +- +- if (do_verbose || do_debug) { +- log_info = syslog_info; +- log_notice = syslog_notice; +- log_warn = syslog_warn; +- } else { +- log_info = null; +- log_notice = null; +- log_warn = null; +- } +- +- log_error = syslog_err; +- log_crit = syslog_crit; +- + logging_to_syslog = 1; + + /* Redirect all our file descriptors to /dev/null */ + nullfd = open("/dev/null", O_RDWR); + if (nullfd < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- syslog_crit(LOGOPT_ANY, "cannot open /dev/null: %s", estr); ++ fprintf(stderr, "cannot open /dev/null: %s", estr); + exit(1); + } + +@@ -207,13 +219,15 @@ void log_to_syslog(void) + dup2(nullfd, STDOUT_FILENO) < 0 || + dup2(nullfd, STDERR_FILENO) < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- syslog_crit(LOGOPT_ANY, +- "redirecting file descriptors failed: %s", estr); ++ fprintf(stderr, ++ "redirecting file descriptors failed: %s", estr); + exit(1); + } + + if (nullfd > 2) + close(nullfd); ++ ++ return; + } + + void log_to_stderr(void) +@@ -223,23 +237,7 @@ void log_to_stderr(void) + closelog(); + } + +- if (do_debug) +- log_debug = to_stderr; +- else +- log_debug = null; +- +- if (do_verbose || do_debug) { +- log_info = to_stderr; +- log_notice = to_stderr; +- log_warn = to_stderr; +- } else { +- log_info = null; +- log_notice = null; +- log_warn = null; +- } +- +- log_error = to_stderr; +- log_crit = to_stderr; +- + logging_to_syslog = 0; ++ ++ return; + } +diff --git a/lib/macros.c b/lib/macros.c +index 936ae06..fa6db8e 100644 +--- a/lib/macros.c ++++ b/lib/macros.c +@@ -50,8 +50,7 @@ void dump_table(struct substvar *table) + fatal(status); + + while (lv) { +- debug(LOGOPT_NONE, +- "lv->def %s lv->val %s lv->next %p", ++ logmsg("lv->def %s lv->val %s lv->next %p", + lv->def, lv->val, lv->next); + lv = lv->next; + } +diff --git a/lib/master.c b/lib/master.c +index abc3bc2..2e24ad0 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -524,8 +524,7 @@ void master_source_writelock(struct master_mapent *entry) + + status = pthread_rwlock_wrlock(&entry->source_lock); + if (status) { +- error(LOGOPT_ANY, +- "master_mapent source write lock failed"); ++ logmsg("master_mapent source write lock failed"); + fatal(status); + } + return; +@@ -537,8 +536,7 @@ void master_source_readlock(struct master_mapent *entry) + + status = pthread_rwlock_rdlock(&entry->source_lock); + if (status) { +- error(LOGOPT_ANY, +- "master_mapent source read lock failed"); ++ logmsg("master_mapent source read lock failed"); + fatal(status); + } + return; +@@ -550,8 +548,7 @@ void master_source_unlock(struct master_mapent *entry) + + status = pthread_rwlock_unlock(&entry->source_lock); + if (status) { +- error(LOGOPT_ANY, +- "master_mapent source unlock failed"); ++ logmsg("master_mapent source unlock failed"); + fatal(status); + } + return; +@@ -572,7 +569,7 @@ void master_source_current_wait(struct master_mapent *entry) + + status = pthread_mutex_lock(&entry->current_mutex); + if (status) { +- error(LOGOPT_ANY, "entry current source lock failed"); ++ logmsg("entry current source lock failed"); + fatal(status); + } + +@@ -580,8 +577,7 @@ void master_source_current_wait(struct master_mapent *entry) + status = pthread_cond_wait( + &entry->current_cond, &entry->current_mutex); + if (status) { +- error(LOGOPT_ANY, +- "entry current source condition wait failed"); ++ logmsg("entry current source condition wait failed"); + fatal(status); + } + } +@@ -595,14 +591,13 @@ void master_source_current_signal(struct master_mapent *entry) + + status = pthread_cond_signal(&entry->current_cond); + if (status) { +- error(LOGOPT_ANY, +- "entry current source condition signal failed"); ++ logmsg("entry current source condition signal failed"); + fatal(status); + } + + status = pthread_mutex_unlock(&entry->current_mutex); + if (status) { +- error(LOGOPT_ANY, "entry current source unlock failed"); ++ logmsg("entry current source unlock failed"); + fatal(status); + } + +@@ -770,6 +765,7 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g + master->default_ghost = ghost; + master->default_timeout = timeout; + master->default_logging = defaults_get_logging(); ++ master->logopt = master->default_logging; + + INIT_LIST_HEAD(&master->mounts); + +@@ -778,11 +774,12 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int g + + int master_read_master(struct master *master, time_t age, int readall) + { ++ unsigned int logopt = master->logopt; + struct mapent_cache *nc; + + nc = cache_init_null_cache(master); + if (!nc) { +- error(LOGOPT_ANY, ++ error(logopt, + "failed to init null map cache for %s", master->name); + return 0; + } +@@ -791,7 +788,7 @@ int master_read_master(struct master *master, time_t age, int readall) + master_init_scan(); + + if (!lookup_nss_read_master(master, age)) { +- error(LOGOPT_ANY, ++ error(logopt, + "can't read master map %s", master->name); + return 0; + } +@@ -802,7 +799,7 @@ int master_read_master(struct master *master, time_t age, int readall) + + if (list_empty(&master->mounts)) { + master_mutex_unlock(); +- warn(LOGOPT_ANY, "no mounts in table"); ++ warn(logopt, "no mounts in table"); + return 1; + } + +@@ -934,6 +931,7 @@ void master_notify_state_change(struct master *master, int sig) + struct autofs_point *ap; + struct list_head *p; + int state_pipe, cur_state; ++ unsigned int logopt; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + master_mutex_lock(); +@@ -944,6 +942,7 @@ void master_notify_state_change(struct master *master, int sig) + entry = list_entry(p, struct master_mapent, list); + + ap = entry->ap; ++ logopt = ap->logopt; + + state_mutex_lock(ap); + +@@ -978,7 +977,7 @@ void master_notify_state_change(struct master *master, int sig) + } + next: + if (next != ST_INVAL) +- debug(ap->logopt, ++ debug(logopt, + "sig %d switching %s from %d to %d", + sig, ap->path, ap->state, next); + +@@ -1230,6 +1229,11 @@ int master_list_empty(struct master *master) + return res; + } + ++inline unsigned int master_get_logopt(void) ++{ ++ return master_list ? master_list->logopt : LOGOPT_NONE; ++} ++ + int master_kill(struct master *master) + { + if (!list_empty(&master->mounts)) +@@ -1251,6 +1255,6 @@ void dump_master(struct master *master) + head = &master->mounts; + list_for_each(p, head) { + struct master_mapent *this = list_entry(p, struct master_mapent, list); +- debug(LOGOPT_ANY, "path %s", this->path); ++ logmsg("path %s", this->path); + } + } +diff --git a/lib/master_parse.y b/lib/master_parse.y +index 70b48be..a767f9e 100644 +--- a/lib/master_parse.y ++++ b/lib/master_parse.y +@@ -585,13 +585,13 @@ static char *master_strdup(char *str) + + static int master_error(const char *s) + { +- error(LOGOPT_ANY, "%s while parsing map.", s); ++ logmsg("%s while parsing map.", s); + return 0; + } + + static int master_notify(const char *s) + { +- warn(LOGOPT_ANY, "syntax error in map near [ %s ]", s); ++ logmsg("syntax error in map near [ %s ]", s); + return(0); + } + +@@ -704,6 +704,7 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + struct master_mapent *entry, *new; + struct map_source *source; + unsigned int logopt = logging; ++ unsigned int m_logopt = master->logopt; + int ret; + + local_init_vars(); +@@ -758,8 +759,8 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + } else { + if (entry->age && entry->age == age) { + if (strcmp(path, "/-")) { +- warn(LOGOPT_VERBOSE, +- "ignoring duplicate indirect mount %s", ++ info(m_logopt, ++ "ignoring duplicate indirect mount %s", + path); + local_free_vars(); + return 0; +@@ -770,13 +771,12 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + if (!entry->ap) { + ret = master_add_autofs_point(entry, timeout, logopt, ghost, 0); + if (!ret) { +- error(LOGOPT_ANY, "failed to add autofs_point"); ++ error(m_logopt, "failed to add autofs_point"); + if (new) + master_free_mapent(new); + local_free_vars(); + return 0; + } +- set_mnt_logging(entry->ap); + } else { + struct autofs_point *ap = entry->ap; + time_t tout = timeout; +@@ -786,14 +786,11 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + * use the ghost, log and timeout of the first + */ + if (entry->age < age) { +- ap->ghost = ghost; +- ap->logopt = logopt; + ap->exp_timeout = timeout; + ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO; + if (ap->ioctlfd != -1 && ap->type == LKP_INDIRECT) + ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout); + } +- set_mnt_logging(ap); + } + entry->ap->random_selection = random_selection; + +@@ -809,7 +806,7 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + source = master_add_map_source(entry, type, format, age, + local_argc, (const char **) local_argv); + if (!source) { +- error(LOGOPT_ANY, "failed to add source"); ++ error(m_logopt, "failed to add source"); + if (new) + master_free_mapent(new); + local_free_vars(); +@@ -817,9 +814,9 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + } + + if (!source->mc) { +- source->mc = cache_init(source); ++ source->mc = cache_init(entry->ap, source); + if (!source->mc) { +- error(LOGOPT_ANY, "failed to init source cache"); ++ error(m_logopt, "failed to init source cache"); + if (new) + master_free_mapent(new); + local_free_vars(); +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 2735223..00cd223 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -368,7 +368,7 @@ int master_wrap(void) + + static void master_echo(void) + { +- debug(LOGOPT_NONE, "%s", master_text); ++ logmsg("%s", master_text); + return; + } + +diff --git a/lib/mounts.c b/lib/mounts.c +index 0e428e8..425a65a 100644 +--- a/lib/mounts.c ++++ b/lib/mounts.c +@@ -126,7 +126,7 @@ char *make_options_string(char *path, int pipefd, char *extra) + + options = malloc(MAX_OPTIONS_LEN + 1); + if (!options) { +- crit(LOGOPT_ANY, "can't malloc options string"); ++ logerr("can't malloc options string"); + return NULL; + } + +@@ -141,13 +141,12 @@ char *make_options_string(char *path, int pipefd, char *extra) + AUTOFS_MAX_PROTO_VERSION); + + if (len >= MAX_OPTIONS_LEN) { +- crit(LOGOPT_ANY, "buffer to small for options - truncated"); ++ logerr("buffer to small for options - truncated"); + len = MAX_OPTIONS_LEN - 1; + } + + if (len < 0) { +- crit(LOGOPT_ANY, +- "failed to malloc autofs mount options for %s", path); ++ logerr("failed to malloc autofs mount options for %s", path); + free(options); + return NULL; + } +@@ -163,7 +162,7 @@ char *make_mnt_name_string(char *path) + + mnt_name = malloc(MAX_MNT_NAME_LEN + 1); + if (!mnt_name) { +- crit(LOGOPT_ANY, "can't malloc mnt_name string"); ++ logerr("can't malloc mnt_name string"); + return NULL; + } + +@@ -171,13 +170,12 @@ char *make_mnt_name_string(char *path) + mnt_name_template, (unsigned) getpid()); + + if (len >= MAX_MNT_NAME_LEN) { +- crit(LOGOPT_ANY, "buffer to small for mnt_name - truncated"); ++ logerr("buffer to small for mnt_name - truncated"); + len = MAX_MNT_NAME_LEN - 1; + } + + if (len < 0) { +- crit(LOGOPT_ANY, +- "failed setting up mnt_name for autofs path %s", path); ++ logerr("failed setting up mnt_name for autofs path %s", path); + free(mnt_name); + return NULL; + } +@@ -207,7 +205,7 @@ struct mnt_list *get_mnt_list(const char *table, const char *path, int include) + tab = setmntent(table, "r"); + if (!tab) { + char *estr = strerror_r(errno, buf, PATH_MAX - 1); +- error(LOGOPT_ANY, "setmntent: %s", estr); ++ logerr("setmntent: %s", estr); + return NULL; + } + +@@ -398,7 +396,7 @@ int is_mounted(const char *table, const char *path, unsigned int type) + tab = setmntent(table, "r"); + if (!tab) { + char *estr = strerror_r(errno, buf, PATH_MAX - 1); +- error(LOGOPT_ANY, "setmntent: %s", estr); ++ logerr("setmntent: %s", estr); + return 0; + } + +@@ -443,7 +441,7 @@ int has_fstab_option(const char *opt) + tab = setmntent(_PATH_MNTTAB, "r"); + if (!tab) { + char *estr = strerror_r(errno, buf, PATH_MAX - 1); +- error(LOGOPT_ANY, "setmntent: %s", estr); ++ logerr("setmntent: %s", estr); + return 0; + } + +@@ -471,7 +469,7 @@ char *find_mnt_ino(const char *table, dev_t dev, ino_t ino) + tab = setmntent(table, "r"); + if (!tab) { + char *estr = strerror_r(errno, buf, (size_t) PATH_MAX - 1); +- error(LOGOPT_ANY, "setmntent: %s", estr); ++ logerr("setmntent: %s", estr); + return 0; + } + +@@ -667,7 +665,7 @@ struct mnt_list *tree_make_mnt_tree(const char *table, const char *path) + tab = setmntent(table, "r"); + if (!tab) { + char *estr = strerror_r(errno, buf, PATH_MAX - 1); +- error(LOGOPT_ANY, "setmntent: %s", estr); ++ logerr("setmntent: %s", estr); + return NULL; + } + +diff --git a/lib/nss_parse.y b/lib/nss_parse.y +index e559696..90b7d25 100644 +--- a/lib/nss_parse.y ++++ b/lib/nss_parse.y +@@ -127,13 +127,13 @@ status_exp: STATUS EQUAL ACTION + + static int nss_ignore(const char *s) + { +- msg("ignored invalid nsswitch config near [ %s ]", s); ++ logmsg("ignored invalid nsswitch config near [ %s ]", s); + return(0); + } + + static int nss_error(const char *s) + { +- msg("syntax error in nsswitch config near [ %s ]\n", s); ++ logmsg("syntax error in nsswitch config near [ %s ]\n", s); + return(0); + } + +@@ -167,7 +167,7 @@ int nsswitch_parse(struct list_head *list) + + nsswitch = fopen(NSSWITCH_FILE, "r"); + if (!nsswitch) { +- error(LOGOPT_ANY, "couldn't open %s\n", NSSWITCH_FILE); ++ logerr("couldn't open %s\n", NSSWITCH_FILE); + return 1; + } + +diff --git a/lib/nss_tok.l b/lib/nss_tok.l +index f96b47f..c435b63 100644 +--- a/lib/nss_tok.l ++++ b/lib/nss_tok.l +@@ -135,6 +135,6 @@ int nss_wrap(void) + + static void nss_echo(void) + { +- msg("%s", nss_text); ++ logmsg("%s", nss_text); + return; + } +diff --git a/lib/parse_subs.c b/lib/parse_subs.c +index 3627f44..5422fef 100644 +--- a/lib/parse_subs.c ++++ b/lib/parse_subs.c +@@ -337,9 +337,9 @@ int umount_ent(struct autofs_point *ap, const char *path) + * and EBADSLT relates to CD changer not responding. + */ + if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) { +- rv = spawn_umount(log_debug, path, NULL); ++ rv = spawn_umount(ap->logopt, path, NULL); + } else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) { +- rv = spawn_umount(log_debug, path, NULL); ++ rv = spawn_umount(ap->logopt, path, NULL); + } + + /* We are doing a forced shutcwdown down so unlink busy mounts */ +@@ -356,8 +356,8 @@ int umount_ent(struct autofs_point *ap, const char *path) + } + + if (ap->state == ST_SHUTDOWN_FORCE) { +- msg("forcing umount of %s", path); +- rv = spawn_umount(log_debug, "-l", path, NULL); ++ info(ap->logopt, "forcing umount of %s", path); ++ rv = spawn_umount(ap->logopt, "-l", path, NULL); + } + + /* +@@ -503,7 +503,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me + * the offset triggers back. + */ + if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) { +- msg("unmounting dir = %s", root); ++ info(ap->logopt, "unmounting dir = %s", root); + if (umount_ent(ap, root)) { + if (!mount_multi_triggers(ap, root, me, "/")) + warn(ap->logopt, +diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c +index d79a94f..5797639 100644 +--- a/lib/rpc_subs.c ++++ b/lib/rpc_subs.c +@@ -96,7 +96,7 @@ static CLIENT *create_udp_client(struct conn_info *info) + if (ret || !result) { + int err = ghn_errno == -1 ? errno : ghn_errno; + char *estr = strerror_r(err, buf, HOST_ENT_BUF_SIZE); +- error(LOGOPT_ANY, "hostname lookup failed: %s", estr); ++ logerr("hostname lookup failed: %s", estr); + goto out_close; + } + memcpy(&raddr.sin_addr.s_addr, php->h_addr, php->h_length); +@@ -305,7 +305,7 @@ static CLIENT *create_tcp_client(struct conn_info *info) + if (ret || !result) { + int err = ghn_errno == -1 ? errno : ghn_errno; + char *estr = strerror_r(err, buf, HOST_ENT_BUF_SIZE); +- error(LOGOPT_ANY, "hostname lookup failed: %s", estr); ++ logerr("hostname lookup failed: %s", estr); + goto out_close; + } + memcpy(&addr.sin_addr.s_addr, php->h_addr, php->h_length); +diff --git a/man/automount.8 b/man/automount.8 +index e203a3e..5cd63c7 100644 +--- a/man/automount.8 ++++ b/man/automount.8 +@@ -62,6 +62,22 @@ setting. + .TP + .I "\-V, \-\-version" + Display the version number, then exit. ++.TP ++.I "\-l, \-\-set-log-priority priority path [path,...]" ++Set the daemon log priority to the specified value. Valid values include ++the numbers 0-7, or the strings emerg, alert, crit, err, warning, notice, ++info, or debug. Log level debug will log everything, log levels info, warn ++(or warning), or notice with enable the daemon verbose logging. Any other ++level will set basic logging. Note that enabling debug or verbose ++logging in the autofs global configuration will override dynamic log level ++changes. For example, if verbose logging is set in the configuration then ++attempting to set logging to basic logging, by using alert, crit, err ++or emerg won't stop the verbose logging. However, setting logging to debug ++will lead to everything (debug logging) being logged witch can then also ++be disabled, returning the daemon to verbose logging. ++.P ++The \fIpath\fP argument corresponds to the automounted ++path name as specified in the master map. + .SH ARGUMENTS + \fBautomount\fP takes one optional argument, the name of the master map to + use. +diff --git a/modules/cyrus-sasl.c b/modules/cyrus-sasl.c +index 68e5dd7..18733f3 100644 +--- a/modules/cyrus-sasl.c ++++ b/modules/cyrus-sasl.c +@@ -96,18 +96,18 @@ sasl_log_func(void *context, int level, const char *message) + switch (level) { + case SASL_LOG_ERR: + case SASL_LOG_FAIL: +- error(LOGOPT_ANY, "%s", message); ++ logerr("%s", message); + break; + case SASL_LOG_WARN: +- warn(LOGOPT_ANY, "%s", message); ++ logmsg("%s", message); + break; + case SASL_LOG_NOTE: +- info(LOGOPT_ANY, "%s", message); ++ logmsg("%s", message); + break; + case SASL_LOG_DEBUG: + case SASL_LOG_TRACE: + case SASL_LOG_PASS: +- debug(LOGOPT_NONE, "%s", message); ++ debug(LOGOPT_DEBUG, "%s", message); + break; + default: + break; +@@ -129,7 +129,7 @@ getuser_func(void *context, int id, const char **result, unsigned *len) + *len = strlen(sasl_auth_id); + break; + default: +- error(LOGOPT_ANY, "unknown id in request: %d", id); ++ error(LOGOPT_VERBOSE, "unknown id in request: %d", id); + return SASL_FAIL; + } + +@@ -166,7 +166,7 @@ getpass_func(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret) + * the returned data. + */ + char ** +-get_server_SASL_mechanisms(LDAP *ld) ++get_server_SASL_mechanisms(unsigned logopt, LDAP *ld) + { + int ret; + const char *saslattrlist[] = {"supportedSASLmechanisms", NULL}; +@@ -178,7 +178,7 @@ get_server_SASL_mechanisms(LDAP *ld) + NULL, NULL, + NULL, LDAP_NO_LIMIT, &results); + if (ret != LDAP_SUCCESS) { +- error(LOGOPT_ANY, "%s", ldap_err2string(ret)); ++ error(logopt, "%s", ldap_err2string(ret)); + return NULL; + } + +@@ -186,7 +186,7 @@ get_server_SASL_mechanisms(LDAP *ld) + if (entry == NULL) { + /* No root DSE. (!) */ + ldap_msgfree(results); +- debug(LOGOPT_NONE, ++ debug(logopt, + "a lookup of \"supportedSASLmechanisms\" returned " + "no results."); + return NULL; +@@ -196,7 +196,7 @@ get_server_SASL_mechanisms(LDAP *ld) + ldap_msgfree(results); + if (mechanisms == NULL) { + /* Well, that was a waste of time. */ +- msg("No SASL authentication mechanisms are supported" ++ info(logopt, "No SASL authentication mechanisms are supported" + " by the LDAP server."); + return NULL; + } +@@ -208,7 +208,7 @@ get_server_SASL_mechanisms(LDAP *ld) + * Returns 0 upon successful connect, -1 on failure. + */ + int +-do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, ++do_sasl_bind(unsigned logopt, LDAP *ld, sasl_conn_t *conn, const char **clientout, + unsigned int *clientoutlen, const char *auth_mech, int sasl_result) + { + int ret, msgid, bind_result; +@@ -226,7 +226,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + &client_cred : NULL, + NULL, NULL, &msgid); + if (ret != LDAP_SUCCESS) { +- crit(LOGOPT_ANY, ++ crit(logopt, + "Error sending sasl_bind request to " + "the server: %s", ldap_err2string(ret)); + return -1; +@@ -236,7 +236,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + results = NULL; + ret = ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, &results); + if (ret != LDAP_RES_BIND) { +- crit(LOGOPT_ANY, ++ crit(logopt, + "Error while waiting for response to " + "sasl_bind request: %s", ldap_err2string(ret)); + return -1; +@@ -264,7 +264,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + ret = ldap_get_option(ld, LDAP_OPT_RESULT_CODE, + &bind_result); + if (ret != LDAP_SUCCESS) { +- crit(LOGOPT_ANY, ++ crit(logopt, + "Error retrieving response to sasl_bind " + "request: %s", ldap_err2string(ret)); + ret = -1; +@@ -277,7 +277,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + bind_result = ret; + break; + default: +- warn(LOGOPT_ANY, ++ warn(logopt, + "Error parsing response to sasl_bind " + "request: %s.", ldap_err2string(ret)); + break; +@@ -299,7 +299,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + expected_data = sasl_result == SASL_CONTINUE; + + if (have_data && !expected_data) { +- warn(LOGOPT_ANY, ++ warn(logopt, + "The LDAP server sent data in response to our " + "bind request, but indicated that the bind was " + "complete. LDAP SASL bind with mechansim %s " +@@ -308,7 +308,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + break; + } + if (expected_data && !have_data) { +- warn(LOGOPT_ANY, ++ warn(logopt, + "The LDAP server indicated that the LDAP SASL " + "bind was incomplete, but did not provide the " + "required data to proceed. LDAP SASL bind with " +@@ -340,7 +340,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + */ + if ((*clientoutlen > 0) && + (bind_result != LDAP_SASL_BIND_IN_PROGRESS)) { +- warn(LOGOPT_ANY, ++ warn(logopt, + "We have data for the server, " + "but it thinks we are done!"); + /* XXX should print out debug data here */ +@@ -372,7 +372,7 @@ do_sasl_bind(LDAP *ld, sasl_conn_t *conn, const char **clientout, + * Upon failure, -1 is returned. + */ + int +-sasl_do_kinit(struct lookup_context *ctxt) ++sasl_do_kinit(unsigned logopt, struct lookup_context *ctxt) + { + krb5_error_code ret; + krb5_principal tgs_princ, krb5_client_princ = ctxt->krb5_client_princ; +@@ -384,33 +384,33 @@ sasl_do_kinit(struct lookup_context *ctxt) + return 0; + ctxt->kinit_done = 1; + +- debug(LOGOPT_NONE, ++ debug(logopt, + "initializing kerberos ticket: client principal %s ", + ctxt->client_princ ? "" : "autofsclient"); + + ret = krb5_init_context(&ctxt->krb5ctxt); + if (ret) { +- error(LOGOPT_ANY, "krb5_init_context failed with %d", ret); ++ error(logopt, "krb5_init_context failed with %d", ret); + return -1; + } + + ret = krb5_cc_resolve(ctxt->krb5ctxt, krb5ccval, &ctxt->krb5_ccache); + if (ret) { +- error(LOGOPT_ANY, "krb5_cc_resolve failed with error %d", ++ error(logopt, "krb5_cc_resolve failed with error %d", + ret); + krb5_free_context(ctxt->krb5ctxt); + return -1; + } + + if (ctxt->client_princ) { +- debug(LOGOPT_NONE, ++ debug(logopt, + "calling krb5_parse_name on client principal %s", + ctxt->client_princ); + + ret = krb5_parse_name(ctxt->krb5ctxt, ctxt->client_princ, + &krb5_client_princ); + if (ret) { +- error(LOGOPT_ANY, ++ error(logopt, + "krb5_parse_name failed for " + "specified client principal %s", + ctxt->client_princ); +@@ -419,14 +419,14 @@ sasl_do_kinit(struct lookup_context *ctxt) + } else { + char *tmp_name = NULL; + +- debug(LOGOPT_NONE, ++ debug(logopt, + "calling krb5_sname_to_principal using defaults"); + + ret = krb5_sname_to_principal(ctxt->krb5ctxt, NULL, + "autofsclient", KRB5_NT_SRV_HST, + &krb5_client_princ); + if (ret) { +- error(LOGOPT_ANY, ++ error(logopt, + "krb5_sname_to_principal failed for " + "%s with error %d", + ctxt->client_princ ? "" : "autofsclient", ret); +@@ -437,13 +437,13 @@ sasl_do_kinit(struct lookup_context *ctxt) + ret = krb5_unparse_name(ctxt->krb5ctxt, + krb5_client_princ, &tmp_name); + if (ret) { +- debug(LOGOPT_NONE, ++ debug(logopt, + "krb5_unparse_name failed with error %d", + ret); + goto out_cleanup_cc; + } + +- debug(LOGOPT_NONE, ++ debug(logopt, + "principal used for authentication: \"%s\"", tmp_name); + + krb5_free_unparsed_name(ctxt->krb5ctxt, tmp_name); +@@ -458,19 +458,19 @@ sasl_do_kinit(struct lookup_context *ctxt) + krb5_princ_realm(ctxt->krb5ctxt, krb5_client_princ)->data, + 0); + if (ret) { +- error(LOGOPT_ANY, ++ error(logopt, + "krb5_build_principal failed with error %d", ret); + goto out_cleanup_cc; + } + + ret = krb5_unparse_name(ctxt->krb5ctxt, tgs_princ, &tgs_name); + if (ret) { +- error(LOGOPT_ANY, "krb5_unparse_name failed with error %d", ++ error(logopt, "krb5_unparse_name failed with error %d", + ret); + goto out_cleanup_cc; + } + +- debug(LOGOPT_NONE, "Using tgs name %s", tgs_name); ++ debug(logopt, "Using tgs name %s", tgs_name); + + memset(&my_creds, 0, sizeof(my_creds)); + ret = krb5_get_init_creds_keytab(ctxt->krb5ctxt, &my_creds, +@@ -479,7 +479,7 @@ sasl_do_kinit(struct lookup_context *ctxt) + 0 /* relative start time */, + tgs_name, NULL); + if (ret) { +- error(LOGOPT_ANY, ++ error(logopt, + "krb5_get_init_creds_keytab failed with error %d", + ret); + goto out_cleanup_unparse; +@@ -500,7 +500,7 @@ sasl_do_kinit(struct lookup_context *ctxt) + fatal(status); + + if (ret) { +- error(LOGOPT_ANY, ++ error(logopt, + "krb5_cc_initialize failed with error %d", ret); + goto out_cleanup_unparse; + } +@@ -508,7 +508,7 @@ sasl_do_kinit(struct lookup_context *ctxt) + /* and store credentials for that principal */ + ret = krb5_cc_store_cred(ctxt->krb5ctxt, ctxt->krb5_ccache, &my_creds); + if (ret) { +- error(LOGOPT_ANY, ++ error(logopt, + "krb5_cc_store_cred failed with error %d", ret); + goto out_cleanup_unparse; + } +@@ -516,12 +516,12 @@ sasl_do_kinit(struct lookup_context *ctxt) + /* finally, set the environment variable to point to our + * credentials cache */ + if (setenv(krb5ccenv, krb5ccval, 1) != 0) { +- error(LOGOPT_ANY, "setenv failed with %d", errno); ++ error(logopt, "setenv failed with %d", errno); + goto out_cleanup_unparse; + } + ctxt->kinit_successful = 1; + +- debug(LOGOPT_NONE, "Kerberos authentication was successful!"); ++ debug(logopt, "Kerberos authentication was successful!"); + + krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name); + +@@ -540,7 +540,7 @@ out_cleanup_cc: + else + ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache); + if (ret) +- warn(LOGOPT_ANY, ++ warn(logopt, + "krb5_cc_destroy failed with non-fatal error %d", ret); + + status = pthread_mutex_unlock(&krb5cc_mutex); +@@ -559,7 +559,7 @@ out_cleanup_cc: + * Returns a valid sasl_conn_t pointer upon success, NULL on failure. + */ + sasl_conn_t * +-sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech) ++sasl_bind_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *mech) + { + sasl_conn_t *conn; + char *tmp, *host = NULL; +@@ -569,15 +569,15 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech) + int result; + + if (!strncmp(mech, "GSSAPI", 6)) { +- if (sasl_do_kinit(ctxt) != 0) ++ if (sasl_do_kinit(logopt, ctxt) != 0) + return NULL; + } + +- debug(LOGOPT_NONE, "Attempting sasl bind with mechanism %s", mech); ++ debug(logopt, "Attempting sasl bind with mechanism %s", mech); + + result = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host); + if (result != LDAP_SUCCESS || !host) { +- debug(LOGOPT_NONE, "failed to get hostname for connection"); ++ debug(logopt, "failed to get hostname for connection"); + return NULL; + } + +@@ -587,7 +587,7 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech) + /* Create a new authentication context for the service. */ + result = sasl_client_new("ldap", host, NULL, NULL, NULL, 0, &conn); + if (result != SASL_OK) { +- error(LOGOPT_ANY, "sasl_client_new failed with error %d", ++ error(logopt, "sasl_client_new failed with error %d", + result); + ldap_memfree(host); + return NULL; +@@ -599,23 +599,23 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech) + + /* OK and CONTINUE are the only non-fatal return codes here. */ + if ((result != SASL_OK) && (result != SASL_CONTINUE)) { +- error(LOGOPT_ANY, "sasl_client start failed with error: %s", ++ error(logopt, "sasl_client start failed with error: %s", + sasl_errdetail(conn)); + ldap_memfree(host); + sasl_dispose(&conn); + return NULL; + } + +- result = do_sasl_bind(ldap, conn, ++ result = do_sasl_bind(logopt, ldap, conn, + &clientout, &clientoutlen, chosen_mech, result); + if (result == 0) { + ldap_memfree(host); +- debug(LOGOPT_NONE, "sasl bind with mechanism %s succeeded", ++ debug(logopt, "sasl bind with mechanism %s succeeded", + chosen_mech); + return conn; + } + +- info(LOGOPT_ANY, "sasl bind with mechanism %s failed", mech); ++ info(logopt, "sasl bind with mechanism %s failed", mech); + + /* sasl bind failed */ + ldap_memfree(host); +@@ -629,14 +629,14 @@ sasl_bind_mech(LDAP *ldap, struct lookup_context *ctxt, const char *mech) + * -1 on error or if no mechanism is supported by both client and server. + */ + sasl_conn_t * +-sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt) ++sasl_choose_mech(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + sasl_conn_t *conn; + int authenticated; + int i; + char **mechanisms; + +- mechanisms = get_server_SASL_mechanisms(ldap); ++ mechanisms = get_server_SASL_mechanisms(logopt, ldap); + if (!mechanisms) + return NULL; + +@@ -652,12 +652,11 @@ sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt) + if (authtype_requires_creds(mechanisms[i])) + continue; + +- conn = sasl_bind_mech(ldap, ctxt, mechanisms[i]); ++ conn = sasl_bind_mech(logopt, ldap, ctxt, mechanisms[i]); + if (conn) { + ctxt->sasl_mech = strdup(mechanisms[i]); + if (!ctxt->sasl_mech) { +- crit(LOGOPT_ANY, +- "Successfully authenticated with " ++ crit(logopt, "Successfully authenticated with " + "mechanism %s, but failed to allocate " + "memory to hold the mechanism type.", + mechanisms[i]); +@@ -668,11 +667,11 @@ sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt) + authenticated = 1; + break; + } +- debug(LOGOPT_NONE, "Failed to authenticate with mech %s", ++ debug(logopt, "Failed to authenticate with mech %s", + mechanisms[i]); + } + +- debug(LOGOPT_NONE, "authenticated: %d, sasl_mech: %s", ++ debug(logopt, "authenticated: %d, sasl_mech: %s", + authenticated, ctxt->sasl_mech); + + ldap_value_free(mechanisms); +@@ -680,14 +679,14 @@ sasl_choose_mech(LDAP *ldap, struct lookup_context *ctxt) + } + + int +-autofs_sasl_bind(LDAP *ldap, struct lookup_context *ctxt) ++autofs_sasl_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + sasl_conn_t *conn; + + if (!ctxt->sasl_mech) + return -1; + +- conn = sasl_bind_mech(ldap, ctxt, ctxt->sasl_mech); ++ conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech); + if (!conn) + return -1; + +@@ -717,13 +716,13 @@ autofs_sasl_unbind(struct lookup_context *ctxt) + * -1 - Failure + */ + int +-autofs_sasl_init(LDAP *ldap, struct lookup_context *ctxt) ++autofs_sasl_init(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + sasl_conn_t *conn; + + /* Start up Cyrus SASL--only needs to be done once. */ + if (sasl_client_init(callbacks) != SASL_OK) { +- error(LOGOPT_ANY, "sasl_client_init failed"); ++ error(logopt, "sasl_client_init failed"); + return -1; + } + +@@ -736,9 +735,9 @@ autofs_sasl_init(LDAP *ldap, struct lookup_context *ctxt) + * select one. + */ + if (ctxt->sasl_mech) +- conn = sasl_bind_mech(ldap, ctxt, ctxt->sasl_mech); ++ conn = sasl_bind_mech(logopt, ldap, ctxt, ctxt->sasl_mech); + else +- conn = sasl_choose_mech(ldap, ctxt); ++ conn = sasl_choose_mech(logopt, ldap, ctxt); + + if (conn) { + sasl_dispose(&conn); +@@ -772,8 +771,7 @@ autofs_sasl_done(struct lookup_context *ctxt) + else + ret = krb5_cc_destroy(ctxt->krb5ctxt, ctxt->krb5_ccache); + if (ret) +- warn(LOGOPT_ANY, +- "krb5_cc_destroy failed with non-fatal error %d", ++ logmsg("krb5_cc_destroy failed with non-fatal error %d", + ret); + + status = pthread_mutex_unlock(&krb5cc_mutex); +@@ -782,8 +780,7 @@ autofs_sasl_done(struct lookup_context *ctxt) + + krb5_free_context(ctxt->krb5ctxt); + if (unsetenv(krb5ccenv) != 0) +- warn(LOGOPT_ANY, +- "unsetenv failed with error %d", errno); ++ logerr("unsetenv failed with error %d", errno); + + ctxt->krb5ctxt = NULL; + ctxt->krb5_ccache = NULL; +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index 31ee0fb..921b32b 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -63,13 +63,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + + if (argc < 1) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "No map name"); ++ logerr(MODPREFIX "No map name"); + return 1; + } + +@@ -77,21 +77,21 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + + if (ctxt->mapname[0] != '/') { + free(ctxt); +- msg(MODPREFIX "file map %s is not an absolute pathname", +- argv[0]); ++ logmsg(MODPREFIX ++ "file map %s is not an absolute pathname", argv[0]); + return 1; + } + + if (access(ctxt->mapname, R_OK)) { + free(ctxt); +- msg(MODPREFIX "file map %s missing or not readable", +- argv[0]); ++ warn(LOGOPT_NONE, MODPREFIX ++ "file map %s missing or not readable", argv[0]); + return 1; + } + + if (stat(ctxt->mapname, &st)) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat", ++ logmsg(MODPREFIX "file map %s, could not stat", + argv[0]); + return 1; + } +@@ -104,7 +104,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logmsg(MODPREFIX "failed to open parse context"); + return 1; + } + *context = ctxt; +@@ -112,7 +112,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + return 0; + } + +-static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsigned int *m_len) ++static int read_one(unsigned logopt, FILE *f, char *key, unsigned int *k_len, char *mapent, unsigned int *m_len) + { + char *kptr, *p; + int mapent_len, key_len; +@@ -193,7 +193,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig + if (gotten == got_plus) + goto got_it; + else if (escape == esc_all) { +- warn(LOGOPT_ANY, MODPREFIX ++ warn(logopt, MODPREFIX + "unmatched \" in map key %s", key); + goto next; + } else if (escape != esc_val) +@@ -208,7 +208,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig + if (key_len == KEY_MAX_LEN) { + state = st_badent; + gotten = got_nothing; +- warn(LOGOPT_ANY, ++ warn(logopt, + MODPREFIX "map key \"%s...\" " + "is too long. The maximum key " + "length is %d", key, +@@ -245,7 +245,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig + state = st_begin; + if (gotten == got_real || gotten == getting) + goto got_it; +- warn(LOGOPT_ANY, MODPREFIX ++ warn(logopt, MODPREFIX + "bad map entry \"%s...\" for key " + "\"%s\"", mapent, key); + goto next; +@@ -286,7 +286,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig + if (ch == '\n') { + if (escape == esc_all) { + state = st_begin; +- warn(LOGOPT_ANY, MODPREFIX ++ warn(logopt, MODPREFIX + "unmatched \" in %s for key %s", + mapent, key); + goto next; +@@ -310,7 +310,7 @@ static int read_one(FILE *f, char *key, unsigned int *k_len, char *mapent, unsig + goto got_it; + ungetc(nch, f); + } else { +- warn(LOGOPT_ANY, ++ warn(logopt, + MODPREFIX "map entry \"%s...\" for key " + "\"%s\" is too long. The maximum entry" + " size is %d", mapent, key, +@@ -388,6 +388,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + struct lookup_context *ctxt = (struct lookup_context *) context; + unsigned int timeout = master->default_timeout; + unsigned int logging = master->default_logging; ++ unsigned int logopt = master->logopt; + char *buffer; + int blen; + char *path; +@@ -402,29 +403,28 @@ int lookup_read_master(struct master *master, time_t age, void *context) + return NSS_STATUS_UNAVAIL; + + if (master->depth > MAX_INCLUDE_DEPTH) { +- error(LOGOPT_ANY, +- MODPREFIX ++ error(logopt, MODPREFIX + "maximum include depth exceeded %s", master->name); + return NSS_STATUS_UNAVAIL; + } + + path = alloca(KEY_MAX_LEN + 1); + if (!path) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX "could not malloc storage for path"); + return NSS_STATUS_UNAVAIL; + } + + ent = alloca(MAPENT_MAX_LEN + 1); + if (!ent) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX "could not malloc storage for mapent"); + return NSS_STATUS_UNAVAIL; + } + + f = fopen(ctxt->mapname, "r"); + if (!f) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX "could not open master map file %s", + ctxt->mapname); + return NSS_STATUS_UNAVAIL; +@@ -438,19 +438,19 @@ int lookup_read_master(struct master *master, time_t age, void *context) + } + + while(1) { +- entry = read_one(f, path, &path_len, ent, &ent_len); ++ entry = read_one(logopt, f, path, &path_len, ent, &ent_len); + if (!entry) { + if (feof(f)) + break; + if (ferror(f)) { +- warn(LOGOPT_ANY, MODPREFIX ++ warn(logopt, MODPREFIX + "error reading map %s", ctxt->mapname); + break; + } + continue; + } + +- debug(LOGOPT_NONE, MODPREFIX "read entry %s", path); ++ debug(logopt, MODPREFIX "read entry %s", path); + + /* + * If key starts with '+' it has to be an +@@ -470,7 +470,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + master->depth++; + status = lookup_nss_read_master(master, age); + if (!status) +- warn(LOGOPT_ANY, ++ warn(logopt, + MODPREFIX + "failed to read included master map %s", + master->name); +@@ -482,7 +482,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + blen = path_len + 1 + ent_len + 1; + buffer = malloc(blen); + if (!buffer) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX "could not malloc parse buffer"); + return NSS_STATUS_UNAVAIL; + } +@@ -503,7 +503,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + } + + if (fstat(fd, &st)) { +- crit(LOGOPT_ANY, MODPREFIX "file map %s, could not stat", ++ crit(logopt, MODPREFIX "file map %s, could not stat", + ctxt->mapname); + return NSS_STATUS_UNAVAIL; + } +@@ -684,12 +684,12 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + } + + while(1) { +- entry = read_one(f, key, &k_len, mapent, &m_len); ++ entry = read_one(ap->logopt, f, key, &k_len, mapent, &m_len); + if (!entry) { + if (feof(f)) + break; + if (ferror(f)) { +- warn(LOGOPT_ANY, MODPREFIX ++ warn(ap->logopt, MODPREFIX + "error reading map %s", ctxt->mapname); + break; + } +@@ -791,7 +791,7 @@ static int lookup_one(struct autofs_point *ap, + } + + while(1) { +- entry = read_one(f, mkey, &k_len, mapent, &m_len); ++ entry = read_one(ap->logopt, f, mkey, &k_len, mapent, &m_len); + if (entry) { + /* + * If key starts with '+' it has to be an +@@ -860,7 +860,7 @@ static int lookup_one(struct autofs_point *ap, + break; + + if (ferror(f)) { +- warn(LOGOPT_ANY, MODPREFIX ++ warn(ap->logopt, MODPREFIX + "error reading map %s", ctxt->mapname); + break; + } +@@ -904,7 +904,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) + } + + while(1) { +- entry = read_one(f, mkey, &k_len, mapent, &m_len); ++ entry = read_one(ap->logopt, f, mkey, &k_len, mapent, &m_len); + if (entry) { + int eq; + +@@ -925,7 +925,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) + break; + + if (ferror(f)) { +- warn(LOGOPT_ANY, MODPREFIX ++ warn(ap->logopt, MODPREFIX + "error reading map %s", ctxt->mapname); + break; + } +diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c +index f30e9b2..649e24c 100644 +--- a/modules/lookup_hesiod.c ++++ b/modules/lookup_hesiod.c +@@ -48,7 +48,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + +@@ -58,7 +58,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + /* Initialize the hesiod context. */ + if (hesiod_init(&(ctxt->hesiod_context)) != 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "hesiod_init(): %s", estr); ++ logerr(MODPREFIX "hesiod_init(): %s", estr); + free(ctxt); + return 1; + } +@@ -70,7 +70,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + /* Open the parser, if we can. */ + ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parser) { +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logerr(MODPREFIX "failed to open parse context"); + free(ctxt); + return 1; + } +diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c +index d711611..d746e42 100644 +--- a/modules/lookup_hosts.c ++++ b/modules/lookup_hosts.c +@@ -57,7 +57,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + +@@ -65,7 +65,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc, argv); + if (!ctxt->parse) { +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logerr(MODPREFIX "failed to open parse context"); + free(ctxt); + return 1; + } +@@ -94,7 +94,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + + status = pthread_mutex_lock(&hostent_mutex); + if (status) { +- error(LOGOPT_ANY, MODPREFIX "failed to lock hostent mutex"); ++ error(ap->logopt, MODPREFIX "failed to lock hostent mutex"); + return NSS_STATUS_UNAVAIL; + } + +@@ -110,7 +110,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + + status = pthread_mutex_unlock(&hostent_mutex); + if (status) +- error(LOGOPT_ANY, MODPREFIX "failed to unlock hostent mutex"); ++ error(ap->logopt, MODPREFIX "failed to unlock hostent mutex"); + + source->age = age; + +@@ -157,10 +157,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + + if (*name == '/') +- msg(MODPREFIX ++ info(ap->logopt, MODPREFIX + "can't find path in hosts map %s", name); + else +- msg(MODPREFIX ++ info(ap->logopt, MODPREFIX + "can't find path in hosts map %s/%s", + ap->path, name); + +@@ -216,7 +216,7 @@ done: + if (!mapent) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(ap->logopt, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + rpc_exports_free(exp); + return NSS_STATUS_UNAVAIL; + } +@@ -230,7 +230,7 @@ done: + if (!mapent) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(ap->logopt, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + rpc_exports_free(exp); + return NSS_STATUS_UNAVAIL; + } +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index c0f228b..00215af 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -49,9 +49,9 @@ static struct ldap_schema common_schema[] = { + }; + static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema); + +-static LDAP *auth_init(const char *, struct lookup_context *); ++static LDAP *auth_init(unsigned logopt, const char *, struct lookup_context *); + +-int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt) ++int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + int rv; + +@@ -62,15 +62,14 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt) + + if (rv != LDAP_SUCCESS) { + if (!ctxt->uri) { +- crit(LOGOPT_ANY, +- MODPREFIX "Unable to bind to the LDAP server: " ++ crit(logopt, MODPREFIX ++ "Unable to bind to the LDAP server: " + "%s, error %s", ctxt->server ? "" : "(default)", + ldap_err2string(rv)); + } else { + struct ldap_uri *uri; + uri = list_entry(ctxt->uri->next, struct ldap_uri, list); +- warn(LOGOPT_ANY, +- MODPREFIX "Unable to bind to the LDAP server: " ++ info(logopt, MODPREFIX "Unable to bind to the LDAP server: " + "%s, error %s", uri->uri, ldap_err2string(rv)); + } + return -1; +@@ -79,12 +78,11 @@ int bind_ldap_anonymous(LDAP *ldap, struct lookup_context *ctxt) + return 0; + } + +-int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt) ++int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + int rv; + + #ifdef WITH_SASL +- debug(LOGOPT_NONE, "use_tls: %d", ctxt->use_tls); + /* + * The OpenSSL library can't handle having its message and error + * string database loaded multiple times and segfaults if the +@@ -102,13 +100,12 @@ int unbind_ldap_connection(LDAP *ldap, struct lookup_context *ctxt) + + rv = ldap_unbind_ext(ldap, NULL, NULL); + if (rv != LDAP_SUCCESS) +- error(LOGOPT_ANY, +- "unbind failed: %s", ldap_err2string(rv)); ++ error(logopt, "unbind failed: %s", ldap_err2string(rv)); + + return rv; + } + +-LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) ++LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap = NULL; + struct timeval timeout = { ctxt->timeout, 0 }; +@@ -120,9 +117,9 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + /* Initialize the LDAP context. */ + rv = ldap_initialize(&ldap, uri); + if (rv != LDAP_OPT_SUCCESS) { +- crit(LOGOPT_ANY, +- MODPREFIX "couldn't initialize LDAP connection to %s", +- uri ? uri : "default server"); ++ info(logopt, MODPREFIX ++ "couldn't initialize LDAP connection to %s", ++ uri ? uri : "default"); + return NULL; + } + +@@ -133,7 +130,7 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + ldap_unbind_ext(ldap, NULL, NULL); + rv = ldap_initialize(&ldap, uri); + if (rv != LDAP_OPT_SUCCESS) { +- crit(LOGOPT_ANY, MODPREFIX "couldn't initialize LDAP"); ++ crit(logopt, MODPREFIX "couldn't initialize LDAP"); + return NULL; + } + ctxt->version = 2; +@@ -144,7 +141,7 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + /* Set synchronous call timeout */ + rv = ldap_set_option(ldap, LDAP_OPT_TIMEOUT, &timeout); + if (rv != LDAP_OPT_SUCCESS) +- info(LOGOPT_ANY, MODPREFIX ++ info(logopt, MODPREFIX + "failed to set synchronous call timeout to %d", + timeout.tv_sec); + } +@@ -152,16 +149,14 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + /* Sane network timeout */ + rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &net_timeout); + if (rv != LDAP_OPT_SUCCESS) +- info(LOGOPT_ANY, +- MODPREFIX "failed to set connection timeout to %d", ++ info(logopt, MODPREFIX "failed to set connection timeout to %d", + net_timeout.tv_sec); + + #ifdef WITH_SASL + if (ctxt->use_tls) { + if (ctxt->version == 2) { + if (ctxt->tls_required) { +- error(LOGOPT_ANY, +- MODPREFIX ++ error(logopt, MODPREFIX + "TLS required but connection is version 2"); + ldap_unbind_ext(ldap, NULL, NULL); + return NULL; +@@ -171,16 +166,15 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + + rv = ldap_start_tls_s(ldap, NULL, NULL); + if (rv != LDAP_SUCCESS) { +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(logopt, ldap, ctxt); + if (ctxt->tls_required) { +- error(LOGOPT_ANY, +- MODPREFIX ++ error(logopt, MODPREFIX + "TLS required but START_TLS failed: %s", + ldap_err2string(rv)); + return NULL; + } + ctxt->use_tls = LDAP_TLS_DONT_USE; +- ldap = init_ldap_connection(uri, ctxt); ++ ldap = init_ldap_connection(logopt, uri, ctxt); + if (ldap) + ctxt->use_tls = LDAP_TLS_INIT; + return ldap; +@@ -192,7 +186,7 @@ LDAP *init_ldap_connection(const char *uri, struct lookup_context *ctxt) + return ldap; + } + +-static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) ++static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) + { + char buf[PARSE_MAX_BUF]; + char *query, *dn, *qdn; +@@ -206,7 +200,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + attrs[1] = NULL; + + if (!ctxt->mapname && !ctxt->base) { +- error(LOGOPT_ANY, MODPREFIX "no master map to lookup"); ++ error(logopt, MODPREFIX "no master map to lookup"); + return 0; + } + +@@ -218,7 +212,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + query = alloca(l); + if (query == NULL) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ crit(logopt, MODPREFIX "alloca: %s", estr); + return NSS_STATUS_UNAVAIL; + } + +@@ -229,14 +223,14 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + if (ctxt->mapname) { + if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class, + key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) { +- debug(LOGOPT_NONE, ++ debug(logopt, + MODPREFIX "error forming query string"); + return 0; + } + scope = LDAP_SCOPE_SUBTREE; + } else { + if (sprintf(query, "(objectclass=%s)", class) >= l) { +- debug(LOGOPT_NONE, ++ debug(logopt, + MODPREFIX "error forming query string"); + return 0; + } +@@ -259,15 +253,14 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + else { + struct ldap_searchdn *this = ctxt->sdns; + +- debug(LOGOPT_NONE, MODPREFIX +- "check search base list"); ++ debug(logopt, MODPREFIX "check search base list"); + + while (this) { + rv = ldap_search_s(ldap, this->basedn, + scope, query, attrs, 0, &result); + + if ((rv == LDAP_SUCCESS) && result) { +- debug(LOGOPT_NONE, MODPREFIX ++ debug(logopt, MODPREFIX + "found search base under %s", + this->basedn); + break; +@@ -283,7 +276,7 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + } + + if ((rv != LDAP_SUCCESS) || !result) { +- error(LOGOPT_NONE, ++ error(logopt, + MODPREFIX "query failed for %s: %s", + query, ldap_err2string(rv)); + return 0; +@@ -292,9 +285,9 @@ static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *cla + e = ldap_first_entry(ldap, result); + if (e) { + dn = ldap_get_dn(ldap, e); +- debug(LOGOPT_NONE, MODPREFIX "found query dn %s", dn); ++ debug(logopt, MODPREFIX "found query dn %s", dn); + } else { +- debug(LOGOPT_NONE, ++ debug(logopt, + MODPREFIX "query succeeded, no matches for %s", + query); + ldap_msgfree(result); +@@ -373,7 +366,7 @@ static struct ldap_schema *alloc_common_schema(struct ldap_schema *s) + return schema; + } + +-static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) ++static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + struct ldap_schema *schema; + unsigned int i; +@@ -384,11 +377,10 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) + for (i = 0; i < common_schema_count; i++) { + const char *class = common_schema[i].map_class; + const char *key = common_schema[i].map_attr; +- if (get_query_dn(ldap, ctxt, class, key)) { ++ if (get_query_dn(logopt, ldap, ctxt, class, key)) { + schema = alloc_common_schema(&common_schema[i]); + if (!schema) { +- error(LOGOPT_ANY, +- MODPREFIX "failed to allocate schema"); ++ error(logopt, MODPREFIX "failed to allocate schema"); + return 0; + } + ctxt->schema = schema; +@@ -399,28 +391,26 @@ static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) + return 0; + } + +-static int do_bind(LDAP *ldap, struct lookup_context *ctxt) ++static int do_bind(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt) + { + char *host = NULL, *nhost; + int rv, need_base = 1; + + #ifdef WITH_SASL +- debug(LOGOPT_NONE, "auth_required: %d, sasl_mech %s", ++ debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s", + ctxt->auth_required, ctxt->sasl_mech); + + if (ctxt->sasl_mech || + (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT))) { +- rv = autofs_sasl_bind(ldap, ctxt); +- debug(LOGOPT_NONE, MODPREFIX +- "autofs_sasl_bind returned %d", rv); ++ rv = autofs_sasl_bind(logopt, ldap, ctxt); ++ debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv); + } else { +- rv = bind_ldap_anonymous(ldap, ctxt); +- debug(LOGOPT_NONE, +- MODPREFIX "ldap anonymous bind returned %d", rv); ++ rv = bind_ldap_anonymous(logopt, ldap, ctxt); ++ debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv); + } + #else +- rv = bind_ldap_anonymous(ldap, ctxt); +- debug(LOGOPT_NONE, MODPREFIX "ldap anonymous bind returned %d", rv); ++ rv = bind_ldap_anonymous(logopt, ldap, ctxt); ++ debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv); + #endif + + if (rv != 0) +@@ -428,13 +418,13 @@ static int do_bind(LDAP *ldap, struct lookup_context *ctxt) + + rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host); + if (rv != LDAP_SUCCESS || !host) { +- debug(LOGOPT_ANY, "failed to get hostname for connection"); ++ debug(logopt, "failed to get hostname for connection"); + return 0; + } + + nhost = strdup(host); + if (!nhost) { +- debug(LOGOPT_ANY, "failed to alloc context for hostname"); ++ debug(logopt, "failed to alloc context for hostname"); + return 0; + } + ldap_memfree(host); +@@ -463,16 +453,16 @@ static int do_bind(LDAP *ldap, struct lookup_context *ctxt) + * base dn for searches. + */ + if (!ctxt->schema) { +- if (!find_query_dn(ldap, ctxt)) { +- error(LOGOPT_ANY, +- MODPREFIX "failed to find valid query dn"); ++ if (!find_query_dn(logopt, ldap, ctxt)) { ++ warn(logopt, ++ MODPREFIX "failed to find valid query dn"); + return 0; + } + } else { + const char *class = ctxt->schema->map_class; + const char *key = ctxt->schema->map_attr; +- if (!get_query_dn(ldap, ctxt, class, key)) { +- error(LOGOPT_ANY, MODPREFIX "failed to get query dn"); ++ if (!get_query_dn(logopt, ldap, ctxt, class, key)) { ++ error(logopt, MODPREFIX "failed to get query dn"); + return 0; + } + } +@@ -480,23 +470,23 @@ static int do_bind(LDAP *ldap, struct lookup_context *ctxt) + return 1; + } + +-static LDAP *do_connect(const char *uri, struct lookup_context *ctxt) ++static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap; + +- ldap = init_ldap_connection(uri, ctxt); ++ ldap = init_ldap_connection(logopt, uri, ctxt); + if (!ldap) + return NULL; + +- if (!do_bind(ldap, ctxt)) { +- unbind_ldap_connection(ldap, ctxt); ++ if (!do_bind(logopt, ldap, ctxt)) { ++ unbind_ldap_connection(logopt, ldap, ctxt); + return NULL; + } + + return ldap; + } + +-static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt) ++static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + LDAP *ldap; + +@@ -506,19 +496,19 @@ static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt) + * authentication. + */ + if (ctxt->auth_required & LDAP_AUTH_REQUIRED) { +- ldap = auth_init(uri, ctxt); ++ ldap = auth_init(logopt, uri, ctxt); + if (!ldap && ctxt->auth_required & LDAP_AUTH_AUTODETECT) +- warn(LOGOPT_NONE, ++ info(logopt, + "no authentication mechanisms auto detected."); + if (!ldap) { +- error(LOGOPT_ANY, MODPREFIX ++ error(logopt, MODPREFIX + "cannot initialize authentication setup"); + return NULL; + } + +- if (!do_bind(ldap, ctxt)) { +- unbind_ldap_connection(ldap, ctxt); +- error(LOGOPT_ANY, MODPREFIX "cannot bind to server"); ++ if (!do_bind(logopt, ldap, ctxt)) { ++ unbind_ldap_connection(logopt, ldap, ctxt); ++ error(logopt, MODPREFIX "cannot bind to server"); + return NULL; + } + +@@ -526,16 +516,18 @@ static LDAP *connect_to_server(const char *uri, struct lookup_context *ctxt) + } + #endif + +- ldap = do_connect(uri, ctxt); ++ ldap = do_connect(logopt, uri, ctxt); + if (!ldap) { +- error(LOGOPT_ANY, MODPREFIX "cannot connect to server"); ++ warn(logopt, ++ MODPREFIX "couldn't connect to server %s", ++ uri ? uri : "default"); + return NULL; + } + + return ldap; + } + +-static LDAP *find_server(struct lookup_context *ctxt) ++static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt) + { + LDAP *ldap = NULL; + struct ldap_uri *this; +@@ -547,10 +539,9 @@ static LDAP *find_server(struct lookup_context *ctxt) + while(p != ctxt->uri) { + this = list_entry(p, struct ldap_uri, list); + p = p->next; +- debug(LOGOPT_ANY, "check uri %s", this->uri); +- ldap = connect_to_server(this->uri, ctxt); ++ ldap = connect_to_server(logopt, this->uri, ctxt); + if (ldap) { +- debug(LOGOPT_ANY, "connexted to uri %s", this->uri); ++ info(logopt, "connected to uri %s", this->uri); + break; + } + list_del_init(&this->list); +@@ -568,17 +559,17 @@ static LDAP *find_server(struct lookup_context *ctxt) + return ldap; + } + +-static LDAP *do_reconnect(struct lookup_context *ctxt) ++static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt) + { + LDAP *ldap; + + if (ctxt->server || !ctxt->uri) { +- ldap = do_connect(ctxt->server, ctxt); ++ ldap = do_connect(logopt, ctxt->server, ctxt); + return ldap; + } else { + struct ldap_uri *this; + this = list_entry(ctxt->uri->next, struct ldap_uri, list); +- ldap = do_connect(this->uri, ctxt); ++ ldap = do_connect(logopt, this->uri, ctxt); + if (ldap) + return ldap; + /* Failed to connect, put at end of list */ +@@ -589,15 +580,15 @@ static LDAP *do_reconnect(struct lookup_context *ctxt) + autofs_sasl_done(ctxt); + + /* Current server failed connect, try the rest */ +- ldap = find_server(ctxt); ++ ldap = find_server(logopt, ctxt); + if (!ldap) +- error(LOGOPT_ANY, MODPREFIX "failed to find available server"); ++ error(logopt, MODPREFIX "failed to find available server"); + + return ldap; + } + + #ifdef WITH_SASL +-int get_property(xmlNodePtr node, const char *prop, char **value) ++int get_property(unsigned logopt, xmlNodePtr node, const char *prop, char **value) + { + xmlChar *ret; + xmlChar *property = (xmlChar *) prop; +@@ -608,8 +599,7 @@ int get_property(xmlNodePtr node, const char *prop, char **value) + } + + if (!(*value = strdup((char *) ret))) { +- error(LOGOPT_ANY, +- MODPREFIX "strdup failed with %d", errno); ++ logerr(MODPREFIX "strdup failed with %d", errno); + xmlFree(ret); + return -1; + } +@@ -645,7 +635,7 @@ int authtype_requires_creds(const char *authtype) + * then no further action is necessary. If it is not, the caller is free + * to then use another method to determine how to connect to the server. + */ +-int parse_ldap_config(struct lookup_context *ctxt) ++int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt) + { + int ret = 0, fallback = 0; + unsigned int auth_required = LDAP_AUTH_NOTREQUIRED; +@@ -662,7 +652,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + + auth_conf = (char *) defaults_get_auth_conf_file(); + if (!auth_conf) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX "failed to get auth config file name."); + return 0; + } +@@ -687,7 +677,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + ctxt->client_princ = NULL; + return 0; + } +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX "stat(2) failed with error %s.", + strerror(errno)); + return 0; +@@ -696,8 +686,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + if (!S_ISREG(st.st_mode) || + st.st_uid != 0 || st.st_gid != 0 || + (st.st_mode & 0x01ff) != 0600) { +- error(LOGOPT_ANY, +- MODPREFIX ++ error(logopt, MODPREFIX + "Configuration file %s exists, but is not usable. " + "Please make sure that it is owned by root, group " + "is root, and the mode is 0600.", +@@ -708,30 +697,29 @@ int parse_ldap_config(struct lookup_context *ctxt) + xmlInitParser(); + doc = xmlParseFile(auth_conf); + if (!doc) { +- warn(LOGOPT_ANY, +- MODPREFIX "xmlParseFile failed for %s.", auth_conf); ++ error(logopt, MODPREFIX ++ "xmlParseFile failed for %s.", auth_conf); + goto out; + } + + root = xmlDocGetRootElement(doc); + if (!root) { +- debug(LOGOPT_ANY, +- MODPREFIX "empty xml document (%s).", auth_conf); ++ debug(logopt, MODPREFIX ++ "empty xml document (%s).", auth_conf); + fallback = 1; + goto out; + } + + if (xmlStrcmp(root->name, (const xmlChar *)"autofs_ldap_sasl_conf")) { +- error(LOGOPT_ANY, +- MODPREFIX ++ error(logopt, MODPREFIX + "The root node of the XML document %s is not " + "autofs_ldap_sasl_conf.", auth_conf); + goto out; + } + +- ret = get_property(root, "usetls", &usetls); ++ ret = get_property(logopt, root, "usetls", &usetls); + if (ret != 0) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "Failed read the usetls property from " + "the configuration file %s.", auth_conf); +@@ -746,7 +734,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + else if (!strcasecmp(usetls, "no")) + use_tls = LDAP_TLS_DONT_USE; + else { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "The usetls property must have value " + "\"yes\" or \"no\"."); +@@ -756,9 +744,9 @@ int parse_ldap_config(struct lookup_context *ctxt) + free(usetls); + } + +- ret = get_property(root, "tlsrequired", &tlsrequired); ++ ret = get_property(logopt, root, "tlsrequired", &tlsrequired); + if (ret != 0) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "Failed read the tlsrequired property from " + "the configuration file %s.", auth_conf); +@@ -773,7 +761,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + else if (!strcasecmp(tlsrequired, "no")) + tls_required = LDAP_TLS_DONT_USE; + else { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "The tlsrequired property must have value " + "\"yes\" or \"no\"."); +@@ -783,9 +771,9 @@ int parse_ldap_config(struct lookup_context *ctxt) + free(tlsrequired); + } + +- ret = get_property(root, "authrequired", &authrequired); ++ ret = get_property(logopt, root, "authrequired", &authrequired); + if (ret != 0) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "Failed read the authrequired property from " + "the configuration file %s.", auth_conf); +@@ -802,7 +790,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + else if (!strcasecmp(authrequired, "autodetect")) + auth_required = LDAP_AUTH_AUTODETECT; + else { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "The authrequired property must have value " + "\"yes\", \"no\" or \"autodetect\"."); +@@ -812,9 +800,9 @@ int parse_ldap_config(struct lookup_context *ctxt) + free(authrequired); + } + +- ret = get_property(root, "authtype", &authtype); ++ ret = get_property(logopt, root, "authtype", &authtype); + if (ret != 0) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "Failed read the authtype property from the " + "configuration file %s.", auth_conf); +@@ -822,10 +810,10 @@ int parse_ldap_config(struct lookup_context *ctxt) + } + + if (authtype && authtype_requires_creds(authtype)) { +- ret = get_property(root, "user", &user); +- ret |= get_property(root, "secret", &secret); ++ ret = get_property(logopt, root, "user", &user); ++ ret |= get_property(logopt, root, "secret", &secret); + if (ret != 0 || (!user || !secret)) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "%s authentication type requires a username " + "and a secret. Please fix your configuration " +@@ -845,7 +833,7 @@ int parse_ldap_config(struct lookup_context *ctxt) + * We allow the admin to specify the principal to use for the + * client. The default is "autofsclient/hostname@REALM". + */ +- (void)get_property(root, "clientprinc", &client_princ); ++ (void)get_property(logopt, root, "clientprinc", &client_princ); + + ctxt->auth_conf = auth_conf; + ctxt->use_tls = use_tls; +@@ -856,15 +844,15 @@ int parse_ldap_config(struct lookup_context *ctxt) + ctxt->secret = secret; + ctxt->client_princ = client_princ; + +- debug(LOGOPT_NONE, ++ debug(logopt, MODPREFIX + "ldap authentication configured with the following options:"); +- debug(LOGOPT_NONE, ++ debug(logopt, MODPREFIX + "use_tls: %u, " + "tls_required: %u, " + "auth_required: %u, " + "sasl_mech: %s", + use_tls, tls_required, auth_required, authtype); +- debug(LOGOPT_NONE, ++ debug(logopt, MODPREFIX + "user: %s, " + "secret: %s, " + "client principal: %s", +@@ -889,7 +877,7 @@ out: + * Returns ldap connection on success, with authtype, user and secret + * filled in as appropriate. Returns NULL on failre. + */ +-static LDAP *auth_init(const char *uri, struct lookup_context *ctxt) ++static LDAP *auth_init(unsigned logopt, const char *uri, struct lookup_context *ctxt) + { + int ret; + LDAP *ldap; +@@ -900,11 +888,11 @@ static LDAP *auth_init(const char *uri, struct lookup_context *ctxt) + * if the permissions on the file were incorrect, or if the + * specified authentication type is not valid. + */ +- ret = parse_ldap_config(ctxt); ++ ret = parse_ldap_config(logopt, ctxt); + if (ret) + return NULL; + +- ldap = init_ldap_connection(uri, ctxt); ++ ldap = init_ldap_connection(logopt, uri, ctxt); + if (!ldap) + return NULL; + +@@ -916,7 +904,7 @@ static LDAP *auth_init(const char *uri, struct lookup_context *ctxt) + * to use. If kerberos is used, it will also take care to initialize + * the credential cache and the client and service principals. + */ +- ret = autofs_sasl_init(ldap, ctxt); ++ ret = autofs_sasl_init(logopt, ldap, ctxt); + if (ret) { + ctxt->sasl_mech = NULL; + return NULL; +@@ -930,7 +918,7 @@ static LDAP *auth_init(const char *uri, struct lookup_context *ctxt) + * Take an input string as specified in the master map, and break it + * down into a server name and basedn. + */ +-static int parse_server_string(const char *url, struct lookup_context *ctxt) ++static int parse_server_string(unsigned logopt, const char *url, struct lookup_context *ctxt) + { + char buf[MAX_ERR_BUF], *tmp = NULL, proto[9]; + const char *ptr, *name; +@@ -939,8 +927,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + memset(proto, 0, 9); + ptr = url; + +- debug(LOGOPT_NONE, +- MODPREFIX ++ debug(logopt, MODPREFIX + "Attempting to parse LDAP information from string \"%s\".", ptr); + + ctxt->port = LDAP_PORT; +@@ -974,7 +961,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + if (!tmp) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 0; + } + ctxt->server = tmp; +@@ -987,7 +974,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + memcpy(ctxt->server, s, l); + ptr = q + 1; + } else { +- crit(LOGOPT_ANY, ++ crit(logopt, + MODPREFIX "invalid LDAP map syntax %s", ptr); + return 0; + /* TODO: why did I put this here, the parser shouldn't let this by +@@ -996,7 +983,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + if (!tmp) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ crit(logopt, MODPREFIX "malloc: %s", estr); + return 0; + } + ctxt->server = tmp; +@@ -1014,7 +1001,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + q++; + + if (*q != ':') { +- crit(LOGOPT_ANY, ++ crit(logopt, + MODPREFIX "invalid LDAP map syntax %s", ptr); + return 0; + } +@@ -1031,7 +1018,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + if (!tmp) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 0; + } + ctxt->server = tmp; +@@ -1072,7 +1059,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + else { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + if (ctxt->server) + free(ctxt->server); + return 0; +@@ -1083,7 +1070,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + if (!base) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + if (ctxt->server) + free(ctxt->server); + return 0; +@@ -1097,7 +1084,7 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + if (!map) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + if (ctxt->server) + free(ctxt->server); + return 0; +@@ -1109,16 +1096,16 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) + + if (!ctxt->server && *proto) { + if (!strncmp(proto, "ldaps", 5)) { +- warn(LOGOPT_ANY, MODPREFIX ++ info(logopt, MODPREFIX + "server must be given to force ldaps, connection " + "will use LDAP client configured protocol"); + } + } + done: + if (ctxt->mapname) +- debug(LOGOPT_NONE, MODPREFIX "mapname %s", ctxt->mapname); ++ debug(logopt, MODPREFIX "mapname %s", ctxt->mapname); + else +- debug(LOGOPT_NONE, MODPREFIX "server \"%s\", base dn \"%s\"", ++ debug(logopt, MODPREFIX "server \"%s\", base dn \"%s\"", + ctxt->server ? ctxt->server : "(default)", + ctxt->base); + +@@ -1175,8 +1162,6 @@ static void validate_uris(struct list_head *list) + + /* At least we get some basic validation */ + if (!ldap_is_ldap_url(this->uri)) { +- warn(LOGOPT_ANY, +- "removed invalid uri from list, %s", this->uri); + list_del(&this->list); + free(this->uri); + free(this); +@@ -1202,7 +1187,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + memset(ctxt, 0, sizeof(struct lookup_context)); +@@ -1215,7 +1200,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + * Parse out the server name and base dn, and fill them + * into the proper places in the lookup context structure. + */ +- if (!parse_server_string(argv[0], ctxt)) { ++ if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) { + error(LOGOPT_ANY, MODPREFIX "cannot parse server string"); + free_context(ctxt); + return 1; +@@ -1236,13 +1221,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + } + + if (ctxt->server || !ctxt->uri) { +- ldap = connect_to_server(ctxt->server, ctxt); ++ ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt); + if (!ldap) { + free_context(ctxt); + return 1; + } + } else { +- ldap = find_server(ctxt); ++ ldap = find_server(LOGOPT_NONE, ctxt); + if (!ldap) { + free_context(ctxt); + error(LOGOPT_ANY, MODPREFIX +@@ -1250,13 +1235,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + return 1; + } + } +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt); + + /* Open the parser, if we can. */ + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { + free_context(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logerr(MODPREFIX "failed to open parse context"); + return 1; + } + *context = ctxt; +@@ -1269,6 +1254,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + struct lookup_context *ctxt = (struct lookup_context *) context; + unsigned int timeout = master->default_timeout; + unsigned int logging = master->default_logging; ++ unsigned int logopt = master->logopt; + int rv, l, count, blen; + char buf[PARSE_MAX_BUF]; + char *query; +@@ -1293,45 +1279,44 @@ int lookup_read_master(struct master *master, time_t age, void *context) + query = alloca(l); + if (query == NULL) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return NSS_STATUS_UNAVAIL; + } + + if (sprintf(query, "(objectclass=%s)", class) >= l) { +- debug(LOGOPT_NONE, MODPREFIX "error forming query string"); ++ error(logopt, MODPREFIX "error forming query string"); + return NSS_STATUS_UNAVAIL; + } + query[l] = '\0'; + + /* Initialize the LDAP context. */ +- ldap = do_reconnect(ctxt); ++ ldap = do_reconnect(logopt, ctxt); + if (!ldap) + return NSS_STATUS_UNAVAIL; + + /* Look around. */ +- debug(LOGOPT_NONE, ++ debug(logopt, + MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn); + + rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result); + + if ((rv != LDAP_SUCCESS) || !result) { +- error(LOGOPT_NONE, +- MODPREFIX "query failed for %s: %s", ++ error(logopt, MODPREFIX "query failed for %s: %s", + query, ldap_err2string(rv)); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(logging, ldap, ctxt); + return NSS_STATUS_NOTFOUND; + } + + e = ldap_first_entry(ldap, result); + if (!e) { +- debug(LOGOPT_NONE, ++ debug(logopt, + MODPREFIX "query succeeded, no matches for %s", + query); + ldap_msgfree(result); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(logging, ldap, ctxt); + return NSS_STATUS_NOTFOUND; + } else +- debug(LOGOPT_NONE, MODPREFIX "examining entries"); ++ debug(logopt, MODPREFIX "examining entries"); + + while (e) { + keyValue = ldap_get_values(ldap, e, entry); +@@ -1346,7 +1331,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + * each map entry + */ + if (ldap_count_values(keyValue) > 1) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "key %s has duplicate entries - ignoring", + *keyValue); +@@ -1358,7 +1343,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + * inclusion is only valid in file maps. + */ + if (**keyValue == '+') { +- warn(LOGOPT_ANY, ++ warn(logopt, + MODPREFIX + "ignoreing '+' map entry - not in file map"); + goto next; +@@ -1366,7 +1351,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + + values = ldap_get_values(ldap, e, info); + if (!values || !*values) { +- debug(LOGOPT_NONE, ++ debug(logopt, + MODPREFIX "no %s defined for %s", info, query); + goto next; + } +@@ -1376,7 +1361,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + */ + count = ldap_count_values(values); + if (count > 1) { +- error(LOGOPT_ANY, ++ error(logopt, + MODPREFIX + "one value per key allowed in master map"); + ldap_value_free(values); +@@ -1385,7 +1370,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + + blen = strlen(*keyValue) + 1 + strlen(*values) + 1; + if (blen > PARSE_MAX_BUF) { +- error(LOGOPT_ANY, MODPREFIX "map entry too long"); ++ error(logopt, MODPREFIX "map entry too long"); + ldap_value_free(values); + goto next; + } +@@ -1403,7 +1388,7 @@ next: + + /* Clean up. */ + ldap_msgfree(result); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(logopt, ldap, ctxt); + + return NSS_STATUS_SUCCESS; + } +@@ -1445,7 +1430,7 @@ static int read_one_map(struct autofs_point *ap, + query = alloca(l); + if (query == NULL) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return NSS_STATUS_UNAVAIL; + } + +@@ -1456,7 +1441,7 @@ static int read_one_map(struct autofs_point *ap, + query[l] = '\0'; + + /* Initialize the LDAP context. */ +- ldap = do_reconnect(ctxt); ++ ldap = do_reconnect(ap->logopt, ctxt); + if (!ldap) + return NSS_STATUS_UNAVAIL; + +@@ -1470,7 +1455,7 @@ static int read_one_map(struct autofs_point *ap, + debug(ap->logopt, + MODPREFIX "query failed for %s: %s", + query, ldap_err2string(rv)); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); + *result_ldap = rv; + return NSS_STATUS_NOTFOUND; + } +@@ -1480,7 +1465,7 @@ static int read_one_map(struct autofs_point *ap, + debug(ap->logopt, + MODPREFIX "query succeeded, no matches for %s", query); + ldap_msgfree(result); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); + return NSS_STATUS_NOTFOUND; + } else + debug(ap->logopt, MODPREFIX "examining entries"); +@@ -1612,8 +1597,7 @@ static int read_one_map(struct autofs_point *ap, + if (!mapent) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + ldap_value_free_len(bvValues); + goto next; + } +@@ -1633,8 +1617,7 @@ static int read_one_map(struct autofs_point *ap, + } else { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "realloc: %s", estr); ++ logerr(MODPREFIX "realloc: %s", estr); + } + } + } +@@ -1669,7 +1652,7 @@ next: + + /* Clean up. */ + ldap_msgfree(result); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); + + source->age = age; + +@@ -1766,7 +1749,7 @@ static int lookup_one(struct autofs_point *ap, + query[ql] = '\0'; + + /* Initialize the LDAP context. */ +- ldap = do_reconnect(ctxt); ++ ldap = do_reconnect(ap->logopt, ctxt); + if (!ldap) + return CHE_FAIL; + +@@ -1777,7 +1760,7 @@ static int lookup_one(struct autofs_point *ap, + + if ((rv != LDAP_SUCCESS) || !result) { + crit(ap->logopt, MODPREFIX "query failed for %s", query); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); + return CHE_FAIL; + } + +@@ -1789,7 +1772,7 @@ static int lookup_one(struct autofs_point *ap, + debug(ap->logopt, + MODPREFIX "got answer, but no entry for %s", query); + ldap_msgfree(result); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); + return CHE_MISSING; + } + +@@ -1897,8 +1880,7 @@ static int lookup_one(struct autofs_point *ap, + if (!mapent) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + ldap_value_free_len(bvValues); + goto next; + } +@@ -1918,8 +1900,7 @@ static int lookup_one(struct autofs_point *ap, + } else { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "realloc: %s", estr); ++ logerr(MODPREFIX "realloc: %s", estr); + } + } + } +@@ -1955,7 +1936,7 @@ next: + } + + ldap_msgfree(result); +- unbind_ldap_connection(ldap, ctxt); ++ unbind_ldap_connection(ap->logopt, ldap, ctxt); + + /* Failed to find wild entry, update cache if needed */ + pthread_cleanup_push(cache_lock_cleanup, mc); +diff --git a/modules/lookup_multi.c b/modules/lookup_multi.c +index 8fa94ae..601d48e 100644 +--- a/modules/lookup_multi.c ++++ b/modules/lookup_multi.c +@@ -73,7 +73,7 @@ static struct lookup_mod *nss_open_lookup(const char *format, int argc, const ch + if (nsswitch_parse(&nsslist)) { + if (!list_empty(&nsslist)) + free_sources(&nsslist); +- error(LOGOPT_ANY, "can't to read name service switch config."); ++ logerr("can't to read name service switch config."); + return NULL; + } + +@@ -92,7 +92,7 @@ static struct lookup_mod *nss_open_lookup(const char *format, int argc, const ch + 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); ++ logerr(MODPREFIX "error: %s", estr); + free_sources(&nsslist); + return NULL; + } +@@ -150,7 +150,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void * + memset(ctxt, 0, sizeof(struct lookup_context)); + + if (argc < 1) { +- crit(LOGOPT_ANY, MODPREFIX "No map list"); ++ logerr(MODPREFIX "No map list"); + goto error_out; + } + +@@ -176,8 +176,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void * + if (!strcmp(ctxt->argl[an], "--")) { + ctxt->argl[an] = NULL; + if (!args) { +- crit(LOGOPT_ANY, +- MODPREFIX "error assigning map args"); ++ logerr(MODPREFIX "error assigning map args"); + goto error_out; + } + ctxt->m[i].argv = copy_argv(ctxt->m[i].argc, (const char **) args); +@@ -201,7 +200,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void * + 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"); ++ logerr(MODPREFIX "error opening module"); + goto error_out; + } + } +@@ -211,7 +210,7 @@ int lookup_init(const char *my_mapfmt, int argc, const char *const *argv, void * + + nomem: + estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "error: %s", estr); ++ logerr(MODPREFIX "error: %s", estr); + error_out: + if (ctxt) { + for (i = 0; i < ctxt->n; i++) { +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index 83e99e0..ff8bd49 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -41,13 +41,13 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "%s", estr); ++ logerr(MODPREFIX "%s", estr); + return 1; + } + + if (argc < 1) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "No map name"); ++ logmsg(MODPREFIX "No map name"); + return 1; + } + ctxt->mapname = argv[0]; +@@ -59,7 +59,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt->domainname = nis_local_directory(); + if (!ctxt->domainname) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "NIS+ domain not set"); ++ logmsg(MODPREFIX "NIS+ domain not set"); + return 1; + } + +@@ -69,7 +69,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logerr(MODPREFIX "failed to open parse context"); + return 1; + } + *context = ctxt; +@@ -81,7 +81,8 @@ int lookup_read_master(struct master *master, time_t age, void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; + unsigned int timeout = master->default_timeout; +- unsigned int logging = master->default_logging; ++ unsigned int logging = master->default_logging; ++ unsigned int logopt = master->logopt; + char *tablename; + nis_result *result; + nis_object *this; +@@ -95,7 +96,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); + if (!tablename) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_UNAVAIL; + } +@@ -105,8 +106,8 @@ int lookup_read_master(struct master *master, time_t age, void *context) + result = nis_lookup(tablename, FOLLOW_PATH | FOLLOW_LINKS); + if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) { + nis_freeresult(result); +- crit(LOGOPT_ANY, +- MODPREFIX "couldn't locat nis+ table %s", ctxt->mapname); ++ crit(logopt, ++ MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_NOTFOUND; + } +@@ -116,7 +117,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); + if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) { + nis_freeresult(result); +- crit(LOGOPT_ANY, ++ crit(logopt, + MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_UNAVAIL; +@@ -139,8 +140,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + + buffer = malloc(ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 1); + if (!buffer) { +- error(LOGOPT_ANY, +- MODPREFIX "could not malloc parse buffer"); ++ logerr(MODPREFIX "could not malloc parse buffer"); + continue; + } + +@@ -182,7 +182,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); + if (!tablename) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_UNAVAIL; + } +@@ -193,7 +193,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) { + nis_freeresult(result); + crit(ap->logopt, +- MODPREFIX "couldn't locat nis+ table %s", ctxt->mapname); ++ MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname); + pthread_setcancelstate(cur_state, NULL); + return NSS_STATUS_NOTFOUND; + } +@@ -274,7 +274,7 @@ static int lookup_one(struct autofs_point *ap, + strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); + if (!tablename) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); + return -1; + } +@@ -327,7 +327,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt) + tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20); + if (!tablename) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + pthread_setcancelstate(cur_state, NULL); + return -1; + } +diff --git a/modules/lookup_program.c b/modules/lookup_program.c +index 2fd521a..e28168e 100644 +--- a/modules/lookup_program.c ++++ b/modules/lookup_program.c +@@ -51,28 +51,26 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return 1; + } + + if (argc < 1) { +- crit(LOGOPT_ANY, MODPREFIX "No map name"); ++ logmsg(MODPREFIX "No map name"); + free(ctxt); + return 1; + } + ctxt->mapname = argv[0]; + + if (ctxt->mapname[0] != '/') { +- crit(LOGOPT_ANY, +- MODPREFIX "program map %s is not an absolute pathname", ++ logmsg(MODPREFIX "program map %s is not an absolute pathname", + ctxt->mapname); + free(ctxt); + return 1; + } + + if (access(ctxt->mapname, X_OK)) { +- crit(LOGOPT_ANY, +- MODPREFIX "program map %s missing or not executable", ++ logmsg(MODPREFIX "program map %s missing or not executable", + ctxt->mapname); + free(ctxt); + return 1; +@@ -83,7 +81,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logmsg(MODPREFIX "failed to open parse context"); + free(ctxt); + return 1; + } +@@ -163,7 +161,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + mapent = (char *) malloc(MAPENT_MAX_LEN + 1); + if (!mapent) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return NSS_STATUS_UNAVAIL; + } + +@@ -176,7 +174,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + */ + if (pipe(pipefd)) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "pipe: %s", estr); ++ logerr(MODPREFIX "pipe: %s", estr); + goto out_free; + } + if (pipe(epipefd)) { +@@ -188,7 +186,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + f = fork(); + if (f < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "fork: %s", estr); ++ logerr(MODPREFIX "fork: %s", estr); + close(pipefd[0]); + close(pipefd[1]); + close(epipefd[0]); +@@ -271,8 +269,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + ++alloci)); + if (!tmp) { + alloci--; +- error(ap->logopt, +- MODPREFIX "realloc: %s", ++ logerr(MODPREFIX "realloc: %s", + strerror(errno)); + break; + } +@@ -308,12 +305,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } else if (ch == '\n') { + *errp = '\0'; + if (errbuf[0]) +- error(ap->logopt, ">> %s", errbuf); ++ logmsg(">> %s", errbuf); + errp = errbuf; + } else { + if (errp >= &errbuf[1023]) { + *errp = '\0'; +- error(ap->logopt, ">> %s", errbuf); ++ logmsg(">> %s", errbuf); + errp = errbuf; + } + *(errp++) = ch; +@@ -325,7 +322,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + *mapp = '\0'; + if (errp > errbuf) { + *errp = '\0'; +- error(ap->logopt, ">> %s", errbuf); ++ logmsg(">> %s", errbuf); + } + + close(pipefd[0]); +@@ -333,12 +330,12 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + if (waitpid(f, &status, 0) != f) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "waitpid: %s", estr); ++ logerr(MODPREFIX "waitpid: %s", estr); + goto out_free; + } + + if (mapp == mapent || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { +- msg(MODPREFIX "lookup for %s failed", name); ++ info(ap->logopt, MODPREFIX "lookup for %s failed", name); + goto out_free; + } + +diff --git a/modules/lookup_userhome.c b/modules/lookup_userhome.c +index efcab0b..680ddaf 100644 +--- a/modules/lookup_userhome.c ++++ b/modules/lookup_userhome.c +@@ -73,7 +73,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + /* Create the appropriate symlink */ + if (chdir(ap->path)) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "chdir failed: %s", estr); ++ logerr(MODPREFIX "chdir failed: %s", estr); + return NSS_STATUS_UNAVAIL; + } + +@@ -88,7 +88,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + if (symlink(pw->pw_dir, name) && errno != EEXIST) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "symlink failed: %s", estr); ++ logerr(MODPREFIX "symlink failed: %s", estr); + return NSS_STATUS_UNAVAIL; + } + +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index da280cc..63fc8e3 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -45,12 +45,14 @@ struct lookup_context { + struct callback_master_data { + unsigned timeout; + unsigned logging; ++ unsigned logopt; + time_t age; + }; + + struct callback_data { + struct autofs_point *ap; + struct map_source *source; ++ unsigned logopt; + time_t age; + }; + +@@ -111,20 +113,18 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt = malloc(sizeof(struct lookup_context)); + if (!ctxt) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "%s", estr); ++ logerr(MODPREFIX "%s", estr); + return 1; + } + memset(ctxt, 0, sizeof(struct lookup_context)); + + if (argc < 1) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "no map name"); ++ logerr(MODPREFIX "no map name"); + return 1; + } + ctxt->mapname = argv[0]; + +- debug(LOGOPT_NONE, MODPREFIX "ctxt->mapname=%s", ctxt->mapname); +- + /* This should, but doesn't, take a const char ** */ + err = yp_get_default_domain((char **) &ctxt->domainname); + if (err) { +@@ -133,8 +133,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + memcpy(name, ctxt->mapname, len); + name[len] = '\0'; + free(ctxt); +- debug(LOGOPT_NONE, MODPREFIX "map %s: %s", name, +- yperr_string(err)); ++ logerr(MODPREFIX "map %s: %s", name, yperr_string(err)); + return 1; + } + +@@ -146,7 +145,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co + ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); + if (!ctxt->parse) { + free(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "failed to open parse context"); ++ logmsg(MODPREFIX "failed to open parse context"); + return 1; + } + *context = ctxt; +@@ -161,6 +160,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen, + (struct callback_master_data *) ypcb_data; + unsigned int timeout = cbdata->timeout; + unsigned int logging = cbdata->logging; ++ unsigned int logopt = cbdata->logopt; + time_t age = cbdata->age; + char *buffer; + unsigned int len; +@@ -182,7 +182,7 @@ int yp_all_master_callback(int status, char *ypkey, int ypkeylen, + + buffer = alloca(len); + if (!buffer) { +- error(LOGOPT_ANY, MODPREFIX "could not malloc parse buffer"); ++ error(logopt, MODPREFIX "could not malloc parse buffer"); + return 0; + } + memset(buffer, 0, len); +@@ -201,6 +201,8 @@ int lookup_read_master(struct master *master, time_t age, void *context) + struct lookup_context *ctxt = (struct lookup_context *) context; + struct ypall_callback ypcb; + struct callback_master_data ypcb_data; ++ unsigned int logging = master->default_logging; ++ unsigned int logopt = master->logopt; + char *mapname; + int err; + +@@ -211,7 +213,8 @@ int lookup_read_master(struct master *master, time_t age, void *context) + strcpy(mapname, ctxt->mapname); + + ypcb_data.timeout = master->default_timeout; +- ypcb_data.logging = master->default_logging; ++ ypcb_data.logging = logging; ++ ypcb_data.logopt = logopt; + ypcb_data.age = age; + + ypcb.foreach = yp_all_master_callback; +@@ -232,7 +235,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + if (err == YPERR_SUCCESS) + return NSS_STATUS_SUCCESS; + +- warn(LOGOPT_ANY, ++ info(logopt, + MODPREFIX "read of master map %s failed: %s", + mapname, yperr_string(err)); + +@@ -249,6 +252,7 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen, + struct autofs_point *ap = cbdata->ap; + struct map_source *source = cbdata->source; + struct mapent_cache *mc = source->mc; ++ unsigned int logopt = cbdata->logopt; + time_t age = cbdata->age; + char *key, *mapent; + int ret; +@@ -264,8 +268,10 @@ int yp_all_callback(int status, char *ypkey, int ypkeylen, + return 0; + + key = sanitize_path(ypkey, ypkeylen, ap->type, ap->logopt); +- if (!key) ++ if (!key) { ++ error(logopt, MODPREFIX "invalid path %s", ypkey); + return 0; ++ } + + mapent = alloca(vallen + 1); + strncpy(mapent, val, vallen); +@@ -288,6 +294,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + struct lookup_context *ctxt = (struct lookup_context *) context; + struct ypall_callback ypcb; + struct callback_data ypcb_data; ++ unsigned int logopt = ap->logopt; + struct map_source *source; + char *mapname; + int err; +@@ -298,6 +305,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + + ypcb_data.ap = ap; + ypcb_data.source = source; ++ ypcb_data.logopt = logopt; + ypcb_data.age = age; + + ypcb.foreach = yp_all_callback; +diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c +index c45b91b..356fb14 100644 +--- a/modules/mount_autofs.c ++++ b/modules/mount_autofs.c +@@ -64,7 +64,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + fullpath = alloca(strlen(root) + name_len + 2); + if (!fullpath) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + +@@ -156,7 +156,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + } + nap = entry->ap; + nap->parent = ap; +- set_mnt_logging(nap); + + argc = 1; + +@@ -208,7 +207,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + return 1; + } + +- source->mc = cache_init(source); ++ source->mc = cache_init(entry->ap, source); + if (!source->mc) { + error(ap->logopt, MODPREFIX "failed to init source cache"); + master_free_mapent(entry); +diff --git a/modules/mount_bind.c b/modules/mount_bind.c +index cb17ce4..04284f5 100644 +--- a/modules/mount_bind.c ++++ b/modules/mount_bind.c +@@ -52,16 +52,14 @@ int mount_init(void **context) + if (lstat(t1_dir, &st1) == -1) + goto out; + +- err = spawn_mount(log_debug, "-n", "--bind", t1_dir, t2_dir, NULL); ++ err = spawn_mount(LOGOPT_NONE, "-n", "--bind", t1_dir, t2_dir, NULL); + if (err == 0 && + lstat(t2_dir, &st2) == 0 && + st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) { + bind_works = 1; + } + +- debug(LOGOPT_NONE, MODPREFIX "bind_works = %d", bind_works); +- +- spawn_umount(log_debug, "-n", t2_dir, NULL); ++ spawn_umount(LOGOPT_NONE, "-n", t2_dir, NULL); + + out: + rmdir(t1_dir); +@@ -91,7 +89,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + fullpath = alloca(rlen + name_len + 2); + if (!fullpath) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + +@@ -139,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + "calling mount --bind " SLOPPY " -o %s %s %s", + options, what, fullpath); + +- err = spawn_bind_mount(log_debug, ++ err = spawn_bind_mount(ap->logopt, + SLOPPYOPT "-o", options, what, fullpath, NULL); + + if (err) { +diff --git a/modules/mount_changer.c b/modules/mount_changer.c +index 6e04c7c..08d9147 100644 +--- a/modules/mount_changer.c ++++ b/modules/mount_changer.c +@@ -66,7 +66,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + fullpath = alloca(rlen + name_len + 2); + if (!fullpath) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + +@@ -80,7 +80,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + + debug(ap->logopt, MODPREFIX "calling umount %s", what); + +- err = spawn_umount(log_debug, what, NULL); ++ err = spawn_umount(ap->logopt, what, NULL); + if (err) { + error(ap->logopt, + MODPREFIX +@@ -115,18 +115,18 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s", + fstype, options, what, fullpath); + +- err = spawn_mount(log_debug, "-t", fstype, ++ err = spawn_mount(ap->logopt, "-t", fstype, + SLOPPYOPT "-o", options, what, fullpath, NULL); + } else { + debug(ap->logopt, + MODPREFIX "calling mount -t %s %s %s", + fstype, what, fullpath); + +- err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL); ++ err = spawn_mount(ap->logopt, "-t", fstype, what, fullpath, NULL); + } + + if (err) { +- msg(MODPREFIX "failed to mount %s (type %s) on %s", ++ info(ap->logopt, MODPREFIX "failed to mount %s (type %s) on %s", + what, fstype, fullpath); + + if (ap->type != LKP_INDIRECT) +@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + + return 1; + } else { +- msg(MODPREFIX "mounted %s type %s on %s", ++ info(ap->logopt, MODPREFIX "mounted %s type %s on %s", + what, fstype, fullpath); + return 0; + } +@@ -161,7 +161,7 @@ int swapCD(const char *device, const char *slotName) + /* open device */ + fd = open(device, O_RDONLY | O_NONBLOCK); + if (fd < 0) { +- error(LOGOPT_ANY, MODPREFIX "Opening device %s failed : %s", ++ logerr(MODPREFIX "Opening device %s failed : %s", + device, strerror(errno)); + return 1; + } +@@ -174,7 +174,7 @@ int swapCD(const char *device, const char *slotName) + /* Check CD player status */ + total_slots_available = ioctl(fd, CDROM_CHANGER_NSLOTS); + if (total_slots_available <= 1) { +- error(LOGOPT_ANY, MODPREFIX ++ logerr(MODPREFIX + "Device %s is not an ATAPI compliant CD changer.", + device); + return 1; +@@ -183,14 +183,14 @@ int swapCD(const char *device, const char *slotName) + /* load */ + slot = ioctl(fd, CDROM_SELECT_DISC, slot); + if (slot < 0) { +- error(LOGOPT_ANY, MODPREFIX "CDROM_SELECT_DISC failed"); ++ logerr(MODPREFIX "CDROM_SELECT_DISC failed"); + return 1; + } + + /* close device */ + status = close(fd); + if (status != 0) { +- error(LOGOPT_ANY, MODPREFIX "close failed for `%s': %s", ++ logerr(MODPREFIX "close failed for `%s': %s", + device, strerror(errno)); + return 1; + } +diff --git a/modules/mount_ext2.c b/modules/mount_ext2.c +index 45f0615..8cf9937 100644 +--- a/modules/mount_ext2.c ++++ b/modules/mount_ext2.c +@@ -58,7 +58,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + fullpath = alloca(rlen + name_len + 2); + if (!fullpath) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + +@@ -108,11 +108,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + if (ro) { + debug(ap->logopt, + MODPREFIX "calling %s -n %s", fsck_prog, what); +- err = spawnl(log_debug, fsck_prog, fsck_prog, "-n", what, NULL); ++ err = spawnl(ap->logopt, fsck_prog, fsck_prog, "-n", what, NULL); + } else { + debug(ap->logopt, + MODPREFIX "calling %s -p %s", fsck_prog, what); +- err = spawnl(log_debug, fsck_prog, fsck_prog, "-p", what, NULL); ++ err = spawnl(ap->logopt, fsck_prog, fsck_prog, "-p", what, NULL); + } + + /* +@@ -132,17 +132,17 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + debug(ap->logopt, + MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s", + fstype, options, what, fullpath); +- err = spawn_mount(log_debug, "-t", fstype, ++ err = spawn_mount(ap->logopt, "-t", fstype, + SLOPPYOPT "-o", options, what, fullpath, NULL); + } else { + debug(ap->logopt, + MODPREFIX "calling mount -t %s %s %s", + fstype, what, fullpath); +- err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL); ++ err = spawn_mount(ap->logopt, "-t", fstype, what, fullpath, NULL); + } + + if (err) { +- msg(MODPREFIX "failed to mount %s (type %s) on %s", ++ info(ap->logopt, MODPREFIX "failed to mount %s (type %s) on %s", + what, fstype, fullpath); + + if (ap->type != LKP_INDIRECT) +@@ -153,7 +153,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + + return 1; + } else { +- debug(ap->logopt, ++ info(ap->logopt, + MODPREFIX "mounted %s type %s on %s", + what, fstype, fullpath); + return 0; +diff --git a/modules/mount_generic.c b/modules/mount_generic.c +index 1f43baa..85b4391 100644 +--- a/modules/mount_generic.c ++++ b/modules/mount_generic.c +@@ -57,7 +57,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + fullpath = alloca(rlen + name_len + 2); + if (!fullpath) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + +@@ -93,16 +93,16 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + MODPREFIX "calling mount -t %s " SLOPPY "-o %s %s %s", + fstype, options, what, fullpath); + +- err = spawn_mount(log_debug, "-t", fstype, ++ err = spawn_mount(ap->logopt, "-t", fstype, + SLOPPYOPT "-o", options, what, fullpath, NULL); + } else { + debug(ap->logopt, MODPREFIX "calling mount -t %s %s %s", + fstype, what, fullpath); +- err = spawn_mount(log_debug, "-t", fstype, what, fullpath, NULL); ++ err = spawn_mount(ap->logopt, "-t", fstype, what, fullpath, NULL); + } + + if (err) { +- msg(MODPREFIX "failed to mount %s (type %s) on %s", ++ info(ap->logopt, MODPREFIX "failed to mount %s (type %s) on %s", + what, fstype, fullpath); + + if (ap->type != LKP_INDIRECT) +@@ -113,7 +113,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + + return 1; + } else { +- msg(MODPREFIX "mounted %s type %s on %s", ++ info(ap->logopt, MODPREFIX "mounted %s type %s on %s", + what, fstype, fullpath); + return 0; + } +diff --git a/modules/mount_nfs.c b/modules/mount_nfs.c +index e4480c5..bad21fc 100644 +--- a/modules/mount_nfs.c ++++ b/modules/mount_nfs.c +@@ -133,14 +133,14 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + else + vers = NFS_VERS_MASK | NFS_PROTO_MASK; + +- if (!parse_location(&hosts, what)) { +- warn(ap->logopt, MODPREFIX "no hosts available"); ++ if (!parse_location(ap->logopt, &hosts, what)) { ++ info(ap->logopt, MODPREFIX "no hosts available"); + return 1; + } +- prune_host_list(&hosts, vers, nfsoptions, ap->random_selection); ++ prune_host_list(ap->logopt, &hosts, vers, nfsoptions, ap->random_selection); + + if (!hosts) { +- warn(ap->logopt, MODPREFIX "no hosts available"); ++ info(ap->logopt, MODPREFIX "no hosts available"); + return 1; + } + +@@ -159,7 +159,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + fullpath = alloca(rlen + name_len + 2); + if (!fullpath) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + free_host_list(&hosts); + return 1; + } +@@ -252,19 +252,19 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + MODPREFIX "calling mount -t %s " SLOPPY + "-o %s %s %s", fstype, nfsoptions, loc, fullpath); + +- err = spawn_mount(log_debug, ++ err = spawn_mount(ap->logopt, + "-t", fstype, SLOPPYOPT "-o", + nfsoptions, loc, fullpath, NULL); + } else { + debug(ap->logopt, + MODPREFIX "calling mount -t %s %s %s", + fstype, loc, fullpath); +- err = spawn_mount(log_debug, ++ err = spawn_mount(ap->logopt, + "-t", fstype, loc, fullpath, NULL); + } + + if (!err) { +- msg(MODPREFIX "mounted %s on %s", loc, fullpath); ++ info(ap->logopt, MODPREFIX "mounted %s on %s", loc, fullpath); + free(loc); + free_host_list(&hosts); + ap->ghost = save_ghost; +@@ -280,7 +280,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int + + /* If we get here we've failed to complete the mount */ + +- msg(MODPREFIX "nfs: mount failure %s on %s", what, fullpath); ++ info(ap->logopt, MODPREFIX "nfs: mount failure %s on %s", what, fullpath); + + if (ap->type != LKP_INDIRECT) + return 1; +diff --git a/modules/parse_sun.c b/modules/parse_sun.c +index 079bda6..186e567 100644 +--- a/modules/parse_sun.c ++++ b/modules/parse_sun.c +@@ -277,7 +277,7 @@ int parse_init(int argc, const char *const *argv, void **context) + + if (!(ctxt = (struct parse_context *) malloc(sizeof(struct parse_context)))) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + *context = NULL; + return 1; + } +@@ -302,7 +302,7 @@ int parse_init(int argc, const char *const *argv, void **context) + + if (!def) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, MODPREFIX "strdup: %s", estr); ++ logerr(MODPREFIX "strdup: %s", estr); + break; + } + +@@ -387,7 +387,7 @@ int parse_init(int argc, const char *const *argv, void **context) + if (!noptstr) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + kill_context(ctxt); +- crit(LOGOPT_ANY, MODPREFIX "%s", estr); ++ logerr(MODPREFIX "%s", estr); + *context = NULL; + return 1; + } +@@ -408,7 +408,7 @@ int parse_init(int argc, const char *const *argv, void **context) + char *tmp = concat_options(gbl_options, ctxt->optstr); + if (!tmp) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, MODPREFIX "concat_options: %s", estr); ++ logerr(MODPREFIX "concat_options: %s", estr); + free(gbl_options); + } else + ctxt->optstr = tmp; +@@ -472,7 +472,7 @@ static char *concat_options(char *left, char *right) + + if (ret == NULL) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); ++ logerr(MODPREFIX "malloc: %s", estr); + return NULL; + } + +@@ -637,8 +637,7 @@ static int check_is_multi(const char *mapent) + int not_first_chunk = 0; + + if (!p) { +- crit(LOGOPT_ANY, +- MODPREFIX "unexpected NULL map entry pointer"); ++ logerr(MODPREFIX "unexpected NULL map entry pointer"); + return 0; + } + +@@ -1021,7 +1020,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + pmapent = alloca(mapent_len + 1); + if (!pmapent) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + ctxt->subst = removestdenv(ctxt->subst); + macro_unlock(); + pthread_setcancelstate(cur_state, NULL); +@@ -1041,7 +1040,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + options = strdup(ctxt->optstr ? ctxt->optstr : ""); + if (!options) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, MODPREFIX "strdup: %s", estr); ++ logerr(MODPREFIX "strdup: %s", estr); + return 1; + } + optlen = strlen(options); +@@ -1119,7 +1118,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + if (!m_root) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + free(options); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + strcpy(m_root, name); +@@ -1129,7 +1128,7 @@ int parse_mount(struct autofs_point *ap, const char *name, + if (!m_root) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + free(options); +- error(ap->logopt, MODPREFIX "alloca: %s", estr); ++ logerr(MODPREFIX "alloca: %s", estr); + return 1; + } + strcpy(m_root, ap->path); +diff --git a/modules/replicated.c b/modules/replicated.c +index e15587c..14b20a9 100644 +--- a/modules/replicated.c ++++ b/modules/replicated.c +@@ -113,7 +113,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len) + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "socket creation failed: %s", estr); ++ logerr("socket creation failed: %s", estr); + return PROXIMITY_ERROR; + } + +@@ -127,7 +127,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len) + ret = ioctl(sock, SIOCGIFCONF, &ifc); + if (ret == -1) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "ioctl: %s", estr); ++ logerr("ioctl: %s", estr); + close(sock); + return PROXIMITY_ERROR; + } +@@ -176,7 +176,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len) + ret = ioctl(sock, SIOCGIFNETMASK, &nmptr); + if (ret == -1) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "ioctl: %s", estr); ++ logerr("ioctl: %s", estr); + close(sock); + return PROXIMITY_ERROR; + } +@@ -387,7 +387,7 @@ static unsigned short get_port_option(const char *options) + return (unsigned short) port; + } + +-static unsigned int get_nfs_info(struct host *host, ++static unsigned int get_nfs_info(unsigned logopt, struct host *host, + struct conn_info *pm_info, struct conn_info *rpc_info, + const char *proto, unsigned int version, + const char *options, unsigned int random_selection) +@@ -533,7 +533,7 @@ done_ver: + return supported; + } + +-static int get_vers_and_cost(struct host *host, ++static int get_vers_and_cost(unsigned logopt, struct host *host, + unsigned int version, const char *options, + unsigned int random_selection) + { +@@ -559,7 +559,7 @@ static int get_vers_and_cost(struct host *host, + vers &= version; + + if (version & UDP_REQUESTED) { +- supported = get_nfs_info(host, ++ supported = get_nfs_info(logopt, host, + &pm_info, &rpc_info, "udp", vers, + options, random_selection); + if (supported) { +@@ -569,7 +569,7 @@ static int get_vers_and_cost(struct host *host, + } + + if (version & TCP_REQUESTED) { +- supported = get_nfs_info(host, ++ supported = get_nfs_info(logopt, host, + &pm_info, &rpc_info, "tcp", vers, + options, random_selection); + if (supported) { +@@ -581,7 +581,7 @@ static int get_vers_and_cost(struct host *host, + return ret; + } + +-static int get_supported_ver_and_cost(struct host *host, ++static int get_supported_ver_and_cost(unsigned logopt, struct host *host, + unsigned int version, const char *options, + unsigned int random_selection) + { +@@ -636,7 +636,7 @@ static int get_supported_ver_and_cost(struct host *host, + vers = NFS4_VERSION; + break; + default: +- crit(LOGOPT_ANY, "called with invalid version: 0x%x\n", version); ++ crit(logopt, "called with invalid version: 0x%x\n", version); + return 0; + } + +@@ -701,7 +701,7 @@ done: + return 0; + } + +-int prune_host_list(struct host **list, ++int prune_host_list(unsigned logopt, struct host **list, + unsigned int vers, const char *options, + unsigned int random_selection) + { +@@ -742,7 +742,7 @@ int prune_host_list(struct host **list, + break; + + if (this->name) { +- status = get_vers_and_cost(this, vers, ++ status = get_vers_and_cost(logopt, this, vers, + options, random_selection); + if (!status) { + if (this == first) { +@@ -833,7 +833,7 @@ int prune_host_list(struct host **list, + remove_host(list, this); + add_host(&new, this); + } else { +- status = get_supported_ver_and_cost(this, ++ status = get_supported_ver_and_cost(logopt, this, + selected_version, options, + random_selection); + if (status) { +@@ -886,11 +886,9 @@ static int add_host_addrs(struct host **list, const char *host, unsigned int wei + buf, MAX_IFC_BUF, &result, &ghn_errno); + if (ret || !result) { + if (ghn_errno == -1) +- error(LOGOPT_ANY, +- "host %s: lookup failure %d", host, errno); ++ logmsg("host %s: lookup failure %d", host, errno); + else +- error(LOGOPT_ANY, +- "host %s: lookup failure %d", host, ghn_errno); ++ logmsg("host %s: lookup failure %d", host, ghn_errno); + return 0; + } + +@@ -965,7 +963,7 @@ static int add_local_path(struct host **hosts, const char *path) + return 1; + } + +-int parse_location(struct host **hosts, const char *list) ++int parse_location(unsigned logopt, struct host **hosts, const char *list) + { + char *str, *p, *delim; + unsigned int empty = 1; +@@ -1072,8 +1070,7 @@ void dump_host_list(struct host *hosts) + + this = hosts; + while (this) { +- debug(LOGOPT_ANY, +- "name %s path %s version %x proximity %u weight %u cost %u", ++ logmsg("name %s path %s version %x proximity %u weight %u cost %u", + this->name, this->path, this->version, + this->proximity, this->weight, this->cost); + this = this->next; diff --git a/autofs-5.0.2-fix-recursive-loopback-mounts.patch b/autofs-5.0.2-fix-recursive-loopback-mounts.patch new file mode 100644 index 0000000..4aa2b91 --- /dev/null +++ b/autofs-5.0.2-fix-recursive-loopback-mounts.patch @@ -0,0 +1,22 @@ +diff --git a/daemon/spawn.c b/daemon/spawn.c +index 3d5ea56..ab3274c 100644 +--- a/daemon/spawn.c ++++ b/daemon/spawn.c +@@ -290,7 +290,16 @@ int spawn_mount(unsigned logopt, ...) + + va_start(arg, logopt); + p = argv + 1; +- while ((*p++ = va_arg(arg, char *))); ++ while ((*p = va_arg(arg, char *))) { ++ if (options == SPAWN_OPT_NONE && !strcmp(*p, "-o")) { ++ *(++p) = va_arg(arg, char *); ++ if (!*p) ++ break; ++ if (strstr(*p, "loop")) ++ options = SPAWN_OPT_ACCESS; ++ } ++ p++; ++ } + va_end(arg); + + while (retries--) { diff --git a/autofs-5.0.2-large-groups.patch b/autofs-5.0.2-large-groups.patch new file mode 100644 index 0000000..84abe3a --- /dev/null +++ b/autofs-5.0.2-large-groups.patch @@ -0,0 +1,130 @@ +diff --git a/daemon/direct.c b/daemon/direct.c +index 4ab4204..88e59ab 100644 +--- a/daemon/direct.c ++++ b/daemon/direct.c +@@ -1218,11 +1218,11 @@ static void *do_mount_direct(void *arg) + struct passwd *ppw = &pw; + struct passwd **pppw = &ppw; + struct group gr; +- struct group *pgr = &gr; +- struct group **ppgr = &pgr; ++ struct group *pgr; ++ struct group **ppgr; + char *pw_tmp, *gr_tmp; + struct thread_stdenv_vars *tsv; +- int tmplen; ++ int tmplen, grplen; + struct stat st; + int status, state; + +@@ -1326,7 +1326,7 @@ static void *do_mount_direct(void *arg) + + /* Try to get group info */ + +- tmplen = sysconf(_SC_GETGR_R_SIZE_MAX); ++ grplen = sysconf(_SC_GETGR_R_SIZE_MAX); + if (tmplen < 0) { + error(ap->logopt, "failed to get buffer size for getgrgid_r"); + free(tsv->user); +@@ -1335,16 +1335,28 @@ static void *do_mount_direct(void *arg) + goto cont; + } + +- gr_tmp = malloc(tmplen + 1); +- if (!gr_tmp) { +- error(ap->logopt, "failed to malloc buffer for getgrgid_r"); +- free(tsv->user); +- free(tsv->home); +- free(tsv); +- goto cont; ++ gr_tmp = NULL; ++ tmplen = grplen; ++ while (1) { ++ char *tmp = realloc(gr_tmp, tmplen + 1); ++ if (!tmp) { ++ error(ap->logopt, "failed to malloc buffer for getgrgid_r"); ++ if (gr_tmp) ++ free(gr_tmp); ++ free(tsv->user); ++ free(tsv->home); ++ free(tsv); ++ goto cont; ++ } ++ gr_tmp = tmp; ++ pgr = &gr; ++ ppgr = &pgr; ++ status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr); ++ if (status != ERANGE) ++ break; ++ tmplen += grplen; + } + +- status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr); + if (status || !pgr) { + error(ap->logopt, "failed to get group info from getgrgid_r"); + free(tsv->user); +diff --git a/daemon/indirect.c b/daemon/indirect.c +index 5c422c8..f6b93d0 100644 +--- a/daemon/indirect.c ++++ b/daemon/indirect.c +@@ -666,11 +666,11 @@ static void *do_mount_indirect(void *arg) + struct passwd *ppw = &pw; + struct passwd **pppw = &ppw; + struct group gr; +- struct group *pgr = &gr; +- struct group **ppgr = &pgr; ++ struct group *pgr; ++ struct group **ppgr; + char *pw_tmp, *gr_tmp; + struct thread_stdenv_vars *tsv; +- int len, tmplen, status, state; ++ int len, tmplen, grplen, status, state; + + mt = (struct pending_args *) arg; + +@@ -771,7 +771,7 @@ static void *do_mount_indirect(void *arg) + + /* Try to get group info */ + +- tmplen = sysconf(_SC_GETGR_R_SIZE_MAX); ++ grplen = sysconf(_SC_GETGR_R_SIZE_MAX); + if (tmplen < 0) { + error(ap->logopt, "failed to get buffer size for getgrgid_r"); + free(tsv->user); +@@ -780,16 +780,28 @@ static void *do_mount_indirect(void *arg) + goto cont; + } + +- gr_tmp = malloc(tmplen + 1); +- if (!gr_tmp) { +- error(ap->logopt, "failed to malloc buffer for getgrgid_r"); +- free(tsv->user); +- free(tsv->home); +- free(tsv); +- goto cont; ++ gr_tmp = NULL; ++ tmplen = grplen; ++ while (1) { ++ char *tmp = realloc(gr_tmp, tmplen + 1); ++ if (!tmp) { ++ error(ap->logopt, "failed to malloc buffer for getgrgid_r"); ++ if (gr_tmp) ++ free(gr_tmp); ++ free(tsv->user); ++ free(tsv->home); ++ free(tsv); ++ goto cont; ++ } ++ gr_tmp = tmp; ++ pgr = &gr; ++ ppgr = &pgr; ++ status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr); ++ if (status != ERANGE) ++ break; ++ tmplen += grplen; + } + +- status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr); + if (status || !pgr) { + error(ap->logopt, "failed to get group info from getgrgid_r"); + free(tsv->user); diff --git a/autofs-5.0.2-ldap-check-star.patch b/autofs-5.0.2-ldap-check-star.patch new file mode 100644 index 0000000..4761ed6 --- /dev/null +++ b/autofs-5.0.2-ldap-check-star.patch @@ -0,0 +1,22 @@ +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index d5e666b..a7b315e 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -1500,7 +1500,7 @@ static int lookup_one(struct autofs_point *ap, + *qKey = '/'; + + /* Build a query string. */ +- l = strlen(class) + 2*strlen(entry) + strlen(qKey) + 29; ++ l = strlen(class) + 3*strlen(entry) + strlen(qKey) + 35; + + query = alloca(l); + if (query == NULL) { +@@ -1514,7 +1514,7 @@ static int lookup_one(struct autofs_point *ap, + * whose entry is equal to qKey. + */ + ql = sprintf(query, +- "(&(objectclass=%s)(|(%s=%s)(%s=/)))", class, entry, qKey, entry); ++ "(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))", class, entry, qKey, entry, entry); + if (ql >= l) { + error(ap->logopt, + MODPREFIX "error forming query string"); diff --git a/autofs-5.0.2-ldap-search-basedn-list.patch b/autofs-5.0.2-ldap-search-basedn-list.patch new file mode 100644 index 0000000..7bddb26 --- /dev/null +++ b/autofs-5.0.2-ldap-search-basedn-list.patch @@ -0,0 +1,816 @@ +diff -up autofs-5.0.2/redhat/autofs.sysconfig.in.ldap-search-basedn-list autofs-5.0.2/redhat/autofs.sysconfig.in +--- autofs-5.0.2/redhat/autofs.sysconfig.in.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/redhat/autofs.sysconfig.in 2007-11-20 14:08:26.000000000 +0900 +@@ -21,6 +21,14 @@ BROWSE_MODE="no" + # + #LOGGING="none" + # ++# Define base dn for map dn lookup. ++# ++# SEARCH_BASE - base dn to use for searching for map search dn. ++# Multiple entries can be given and they are checked ++# in the order they occur here. ++# ++#SEARCH_BASE="" ++# + # Define the LDAP schema to used for lookups + # + # If no schema is set autofs will check each of the schemas +diff -up autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list autofs-5.0.2/include/lookup_ldap.h +--- autofs-5.0.2/include/lookup_ldap.h.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/include/lookup_ldap.h 2007-11-20 14:08:26.000000000 +0900 +@@ -18,6 +18,11 @@ struct ldap_schema { + char *value_attr; + }; + ++struct ldap_searchdn { ++ char *basedn; ++ struct ldap_searchdn *next; ++}; ++ + struct lookup_context { + char *mapname; + +@@ -32,6 +37,10 @@ struct lookup_context { + /* LDAP lookup configuration */ + struct ldap_schema *schema; + ++ /* List of base dns for searching */ ++ char *cur_host; ++ struct ldap_searchdn *sdns; ++ + /* TLS and SASL authentication information */ + char *auth_conf; + unsigned use_tls; +diff -up autofs-5.0.2/include/defaults.h.ldap-search-basedn-list autofs-5.0.2/include/defaults.h +--- autofs-5.0.2/include/defaults.h.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/include/defaults.h 2007-11-20 14:08:26.000000000 +0900 +@@ -37,6 +37,9 @@ + #define DEFAULT_APPEND_OPTIONS 1 + #define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf" + ++struct ldap_schema; ++struct ldap_searchdn; ++ + unsigned int defaults_read_config(void); + const char *defaults_get_master_map(void); + unsigned int defaults_get_timeout(void); +@@ -45,6 +48,8 @@ unsigned int defaults_get_logging(void); + const char *defaults_get_ldap_server(void); + struct ldap_schema *defaults_get_default_schema(void); + struct ldap_schema *defaults_get_schema(void); ++struct ldap_searchdn *defaults_get_searchdns(void); ++void defaults_free_searchdns(struct ldap_searchdn *); + unsigned int defaults_get_append_options(void); + const char *defaults_get_auth_conf_file(void); + +diff -up autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list autofs-5.0.2/modules/lookup_ldap.c +--- autofs-5.0.2/modules/lookup_ldap.c.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/modules/lookup_ldap.c 2007-11-20 14:09:58.000000000 +0900 +@@ -171,10 +171,207 @@ LDAP *init_ldap_connection(struct lookup + return ldap; + } + ++static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) ++{ ++ char buf[PARSE_MAX_BUF]; ++ char *query, *dn; ++ LDAPMessage *result = NULL, *e; ++ struct ldap_searchdn *sdns = NULL; ++ char *attrs[2]; ++ int scope; ++ int rv, l; ++ ++ attrs[0] = LDAP_NO_ATTRS; ++ attrs[1] = NULL; ++ ++ if (!ctxt->mapname && !ctxt->base) { ++ error(LOGOPT_ANY, MODPREFIX "no master map to lookup"); ++ return 0; ++ } ++ ++ /* Build a query string. */ ++ l = strlen("(objectclass=)") + strlen(class) + 1; ++ if (ctxt->mapname) ++ l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))"); ++ ++ query = alloca(l); ++ if (query == NULL) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); ++ return NSS_STATUS_UNAVAIL; ++ } ++ ++ /* ++ * If we have a master mapname construct a query using it ++ * otherwise assume the base dn will catch it. ++ */ ++ if (ctxt->mapname) { ++ if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class, ++ key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) { ++ debug(LOGOPT_NONE, ++ MODPREFIX "error forming query string"); ++ return 0; ++ } ++ scope = LDAP_SCOPE_SUBTREE; ++ } else { ++ if (sprintf(query, "(objectclass=%s)", class) >= l) { ++ debug(LOGOPT_NONE, ++ MODPREFIX "error forming query string"); ++ return 0; ++ } ++ scope = LDAP_SCOPE_SUBTREE; ++ } ++ query[l] = '\0'; ++ ++ if (!ctxt->base) { ++ sdns = defaults_get_searchdns(); ++ if (sdns) ++ ctxt->sdns = sdns; ++ } ++ ++ if (!sdns) ++ rv = ldap_search_s(ldap, ctxt->base, ++ scope, query, attrs, 0, &result); ++ else { ++ struct ldap_searchdn *this = sdns; ++ ++ debug(LOGOPT_NONE, MODPREFIX ++ "check search base list"); ++ ++ while (this) { ++ rv = ldap_search_s(ldap, this->basedn, ++ scope, query, attrs, 0, &result); ++ ++ if ((rv == LDAP_SUCCESS) && result) { ++ debug(LOGOPT_NONE, MODPREFIX ++ "found search base under %s", ++ this->basedn); ++ break; ++ } ++ ++ this = this->next; ++ ++ if (result) { ++ ldap_msgfree(result); ++ result = NULL; ++ } ++ } ++ } ++ ++ if ((rv != LDAP_SUCCESS) || !result) { ++ error(LOGOPT_NONE, ++ MODPREFIX "query failed for %s: %s", ++ query, ldap_err2string(rv)); ++ return 0; ++ } ++ ++ e = ldap_first_entry(ldap, result); ++ if (e) { ++ dn = ldap_get_dn(ldap, e); ++ debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); ++ ldap_msgfree(result); ++ } else { ++ debug(LOGOPT_NONE, ++ MODPREFIX "query succeeded, no matches for %s", ++ query); ++ ldap_msgfree(result); ++ return 0; ++ } ++ ++ ctxt->qdn = dn; ++ ++ return 1; ++} ++ ++static struct ldap_schema *alloc_common_schema(struct ldap_schema *s) ++{ ++ struct ldap_schema *schema; ++ char *mc, *ma, *ec, *ea, *va; ++ ++ mc = strdup(s->map_class); ++ if (!mc) ++ return NULL; ++ ++ ma = strdup(s->map_attr); ++ if (!ma) { ++ free(mc); ++ return NULL; ++ } ++ ++ ec = strdup(s->entry_class); ++ if (!ec) { ++ free(mc); ++ free(ma); ++ return NULL; ++ } ++ ++ ea = strdup(s->entry_attr); ++ if (!ea) { ++ free(mc); ++ free(ma); ++ free(ec); ++ return NULL; ++ } ++ ++ va = strdup(s->value_attr); ++ if (!va) { ++ free(mc); ++ free(ma); ++ free(ec); ++ free(ea); ++ return NULL; ++ } ++ ++ schema = malloc(sizeof(struct ldap_schema)); ++ if (!schema) { ++ free(mc); ++ free(ma); ++ free(ec); ++ free(ea); ++ free(va); ++ return NULL; ++ } ++ ++ schema->map_class = mc; ++ schema->map_attr = ma; ++ schema->entry_class = ec; ++ schema->entry_attr = ea; ++ schema->value_attr = va; ++ ++ return schema; ++} ++ ++static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) ++{ ++ struct ldap_schema *schema; ++ unsigned int i; ++ ++ if (ctxt->schema) ++ return 0; ++ ++ for (i = 0; i < common_schema_count; i++) { ++ const char *class = common_schema[i].map_class; ++ const char *key = common_schema[i].map_attr; ++ if (get_query_dn(ldap, ctxt, class, key)) { ++ schema = alloc_common_schema(&common_schema[i]); ++ if (!schema) { ++ error(LOGOPT_ANY, ++ MODPREFIX "failed to allocate schema"); ++ return 0; ++ } ++ ctxt->schema = schema; ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ + static LDAP *do_connect(struct lookup_context *ctxt) + { + LDAP *ldap; +- int rv; ++ char *host = NULL, *nhost; ++ int rv, need_base = 1; + + ldap = init_ldap_connection(ctxt); + if (!ldap) +@@ -204,6 +401,61 @@ static LDAP *do_connect(struct lookup_co + return NULL; + } + ++ rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host); ++ if (rv != LDAP_SUCCESS || !host) { ++ unbind_ldap_connection(ldap, ctxt); ++ debug(LOGOPT_ANY, "failed to get hostname for connection"); ++ return NULL; ++ } ++ ++ nhost = strdup(host); ++ if (!nhost) { ++ unbind_ldap_connection(ldap, ctxt); ++ debug(LOGOPT_ANY, "failed to alloc context for hostname"); ++ return NULL; ++ } ++ ldap_memfree(host); ++ ++ if (!ctxt->cur_host) { ++ ctxt->cur_host = nhost; ++ /* Check if schema defined in conf first time only */ ++ ctxt->schema = defaults_get_schema(); ++ } else { ++ /* If connection host has changed update */ ++ if (strcmp(ctxt->cur_host, nhost)) { ++ free(ctxt->cur_host); ++ ctxt->cur_host = nhost; ++ } else { ++ free(nhost); ++ need_base = 0; ++ } ++ } ++ ++ if (!need_base) ++ return ldap; ++ ++ /* ++ * If the schema isn't defined in the configuration then check for ++ * presence of a map dn with a the common schema. Then calculate the ++ * base dn for searches. ++ */ ++ if (!ctxt->schema) { ++ if (!find_query_dn(ldap, ctxt)) { ++ unbind_ldap_connection(ldap, ctxt); ++ error(LOGOPT_ANY, ++ MODPREFIX "failed to find valid query dn"); ++ return NULL; ++ } ++ } else { ++ const char *class = ctxt->schema->map_class; ++ const char *key = ctxt->schema->map_attr; ++ if (!get_query_dn(ldap, ctxt, class, key)) { ++ unbind_ldap_connection(ldap, ctxt); ++ error(LOGOPT_ANY, MODPREFIX "failed to get query dn"); ++ return NULL; ++ } ++ } ++ + return ldap; + } + +@@ -769,177 +1021,17 @@ static void free_context(struct lookup_c + ldap_memfree(ctxt->qdn); + if (ctxt->server) + free(ctxt->server); ++ if (ctxt->cur_host) ++ free(ctxt->cur_host); + if (ctxt->base) + free(ctxt->base); ++ if (ctxt->sdns) ++ defaults_free_searchdns(ctxt->sdns); + free(ctxt); + + return; + } + +-static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) +-{ +- char buf[PARSE_MAX_BUF]; +- char *query, *dn; +- LDAPMessage *result, *e; +- char *attrs[2]; +- struct berval **value; +- int scope; +- int rv, l; +- +- attrs[0] = (char *) key; +- attrs[1] = NULL; +- +- if (!ctxt->mapname && !ctxt->base) { +- error(LOGOPT_ANY, MODPREFIX "no master map to lookup"); +- return 0; +- } +- +- /* Build a query string. */ +- l = strlen("(objectclass=)") + strlen(class) + 1; +- if (ctxt->mapname) +- l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))"); +- +- query = alloca(l); +- if (query == NULL) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- crit(LOGOPT_ANY, MODPREFIX "alloca: %s", estr); +- return NSS_STATUS_UNAVAIL; +- } +- +- /* +- * If we have a master mapname construct a query using it +- * otherwise assume the base dn will catch it. +- */ +- if (ctxt->mapname) { +- if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class, +- key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) { +- debug(LOGOPT_NONE, +- MODPREFIX "error forming query string"); +- return 0; +- } +- scope = LDAP_SCOPE_SUBTREE; +- } else { +- if (sprintf(query, "(objectclass=%s)", class) >= l) { +- debug(LOGOPT_NONE, +- MODPREFIX "error forming query string"); +- return 0; +- } +- scope = LDAP_SCOPE_SUBTREE; +- } +- query[l] = '\0'; +- +- rv = ldap_search_s(ldap, ctxt->base, scope, query, attrs, 0, &result); +- +- if ((rv != LDAP_SUCCESS) || !result) { +- error(LOGOPT_NONE, +- MODPREFIX "query failed for %s: %s", +- query, ldap_err2string(rv)); +- return 0; +- } +- +- e = ldap_first_entry(ldap, result); +- if (e && (value = ldap_get_values_len(ldap, e, key))) { +- ldap_value_free_len(value); +- dn = ldap_get_dn(ldap, e); +- debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); +- ldap_msgfree(result); +- } else { +- debug(LOGOPT_NONE, +- MODPREFIX "query succeeded, no matches for %s", +- query); +- ldap_msgfree(result); +- return 0; +- } +- +- ctxt->qdn = dn; +- +- return 1; +-} +- +-static struct ldap_schema *alloc_common_schema(struct ldap_schema *s) +-{ +- struct ldap_schema *schema; +- char *mc, *ma, *ec, *ea, *va; +- +- mc = strdup(s->map_class); +- if (!mc) +- return NULL; +- +- ma = strdup(s->map_attr); +- if (!ma) { +- free(mc); +- return NULL; +- } +- +- ec = strdup(s->entry_class); +- if (!ec) { +- free(mc); +- free(ma); +- return NULL; +- } +- +- ea = strdup(s->entry_attr); +- if (!ea) { +- free(mc); +- free(ma); +- free(ec); +- return NULL; +- } +- +- va = strdup(s->value_attr); +- if (!va) { +- free(mc); +- free(ma); +- free(ec); +- free(ea); +- return NULL; +- } +- +- schema = malloc(sizeof(struct ldap_schema)); +- if (!schema) { +- free(mc); +- free(ma); +- free(ec); +- free(ea); +- free(va); +- return NULL; +- } +- +- schema->map_class = mc; +- schema->map_attr = ma; +- schema->entry_class = ec; +- schema->entry_attr = ea; +- schema->value_attr = va; +- +- return schema; +-} +- +-static int find_query_dn(LDAP *ldap, struct lookup_context *ctxt) +-{ +- struct ldap_schema *schema; +- unsigned int i; +- +- if (ctxt->schema) +- return 0; +- +- for (i = 0; i < common_schema_count; i++) { +- const char *class = common_schema[i].map_class; +- const char *key = common_schema[i].map_attr; +- if (get_query_dn(ldap, ctxt, class, key)) { +- schema = alloc_common_schema(&common_schema[i]); +- if (!schema) { +- error(LOGOPT_ANY, +- MODPREFIX "failed to allocate schema"); +- return 0; +- } +- ctxt->schema = schema; +- return 1; +- } +- } +- +- return 0; +-} +- + /* + * This initializes a context (persistent non-global data) for queries to + * this module. Return zero if we succeed. +@@ -996,31 +1088,6 @@ int lookup_init(const char *mapfmt, int + free_context(ctxt); + return 1; + } +- +- /* +- * Get default schema for queries. +- * If the schema isn't defined in the configuration then check for +- * presence of a map dn in the common schemas. +- */ +- ctxt->schema = defaults_get_schema(); +- if (!ctxt->schema) { +- if (!find_query_dn(ldap, ctxt)) { +- unbind_ldap_connection(ldap, ctxt); +- error(LOGOPT_ANY, +- MODPREFIX "failed to find valid query dn"); +- free_context(ctxt); +- return 1; +- } +- } else { +- const char *class = ctxt->schema->map_class; +- const char *key = ctxt->schema->map_attr; +- if (!get_query_dn(ldap, ctxt, class, key)) { +- unbind_ldap_connection(ldap, ctxt); +- error(LOGOPT_ANY, MODPREFIX "failed to get query dn"); +- free_context(ctxt); +- return 1; +- } +- } + unbind_ldap_connection(ldap, ctxt); + + /* Open the parser, if we can. */ +diff -up autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list autofs-5.0.2/samples/autofs.conf.default.in +--- autofs-5.0.2/samples/autofs.conf.default.in.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/samples/autofs.conf.default.in 2007-11-20 14:08:26.000000000 +0900 +@@ -21,6 +21,14 @@ BROWSE_MODE="no" + # + #LOGGING="none" + # ++# Define base dn for map dn lookup. ++# ++# SEARCH_BASE - base dn to use for searching for map search dn. ++# Multiple entries can be given and they are checked ++# in the order they occur here. ++# ++#SEARCH_BASE="" ++# + # Define the LDAP schema to used for lookups + # + # If no schema is set autofs will check each of the schemas +diff -up autofs-5.0.2/lib/defaults.c.ldap-search-basedn-list autofs-5.0.2/lib/defaults.c +--- autofs-5.0.2/lib/defaults.c.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/lib/defaults.c 2007-11-20 14:08:26.000000000 +0900 +@@ -32,6 +32,8 @@ + + #define ENV_LDAP_SERVER "LDAP_SERVER" + ++#define SEARCH_BASE "SEARCH_BASE" ++ + #define ENV_NAME_MAP_OBJ_CLASS "MAP_OBJECT_CLASS" + #define ENV_NAME_ENTRY_OBJ_CLASS "ENTRY_OBJECT_CLASS" + #define ENV_NAME_MAP_ATTR "MAP_ATTRIBUTE" +@@ -130,6 +132,52 @@ static int check_set_config_value(const + return 0; + } + ++static int parse_line(char *line, char **res, char **value) ++{ ++ char *key, *val, *trailer; ++ int len; ++ ++ key = line; ++ ++ if (*key == '#' || !isalpha(*key)) ++ return 0; ++ ++ while (*key && *key == ' ') ++ key++; ++ ++ if (!key) ++ return 0; ++ ++ if (!(val = strchr(key, '='))) ++ return 0; ++ ++ *val++ = '\0'; ++ ++ while (*val && (*val == '"' || isblank(*val))) ++ val++; ++ ++ len = strlen(val); ++ ++ if (val[len - 1] == '\n') { ++ val[len - 1] = '\0'; ++ len--; ++ } ++ ++ trailer = strchr(val, '#'); ++ if (!trailer) ++ trailer = val + len - 1; ++ else ++ trailer--; ++ ++ while (*trailer && (*trailer == '"' || isblank(*trailer))) ++ *(trailer--) = '\0';; ++ ++ *res = key; ++ *value = val; ++ ++ return 1; ++} ++ + /* + * Read config env variables and check they have been set. + * +@@ -141,61 +189,30 @@ unsigned int defaults_read_config(void) + { + FILE *f; + char buf[MAX_LINE_LEN]; +- char *res, *value; ++ char *res; + + f = fopen(DEFAULTS_CONFIG_FILE, "r"); + if (!f) + return 0; + + while ((res = fgets(buf, MAX_LINE_LEN, f))) { +- char *trailer; +- int len; +- +- if (*res == '#' || !isalpha(*res)) +- continue; +- +- while (*res && *res == ' ') +- res++; +- +- if (!res) +- continue; ++ char *key, *value; + +- if (!(value = strchr(res, '='))) ++ if (!parse_line(res, &key, &value)) + continue; + +- *value++ = '\0'; +- +- while (*value && (*value == '"' || isblank(*value))) +- value++; +- +- len = strlen(value); +- +- if (value[len - 1] == '\n') { +- value[len - 1] = '\0'; +- len--; +- } +- +- trailer = strchr(value, '#'); +- if (!trailer) +- trailer = value + len - 1; +- else +- trailer--; +- +- while (*trailer && (*trailer == '"' || isblank(*trailer))) +- *(trailer--) = '\0';; +- +- if (check_set_config_value(res, ENV_NAME_MASTER_MAP, value) || +- check_set_config_value(res, ENV_NAME_TIMEOUT, value) || +- check_set_config_value(res, ENV_NAME_BROWSE_MODE, value) || +- check_set_config_value(res, ENV_NAME_LOGGING, value) || +- check_set_config_value(res, ENV_LDAP_SERVER, value) || +- check_set_config_value(res, ENV_NAME_MAP_OBJ_CLASS, value) || +- check_set_config_value(res, ENV_NAME_ENTRY_OBJ_CLASS, value) || +- check_set_config_value(res, ENV_NAME_MAP_ATTR, value) || +- check_set_config_value(res, ENV_NAME_ENTRY_ATTR, value) || +- check_set_config_value(res, ENV_NAME_VALUE_ATTR, value) || +- check_set_config_value(res, ENV_APPEND_OPTIONS, value) || +- check_set_config_value(res, ENV_AUTH_CONF_FILE, value)) ++ if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value) || ++ check_set_config_value(key, ENV_NAME_TIMEOUT, value) || ++ check_set_config_value(key, ENV_NAME_BROWSE_MODE, value) || ++ check_set_config_value(key, ENV_NAME_LOGGING, value) || ++ check_set_config_value(key, ENV_LDAP_SERVER, value) || ++ check_set_config_value(key, ENV_NAME_MAP_OBJ_CLASS, value) || ++ check_set_config_value(key, ENV_NAME_ENTRY_OBJ_CLASS, value) || ++ check_set_config_value(key, ENV_NAME_MAP_ATTR, value) || ++ check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value) || ++ check_set_config_value(key, ENV_NAME_VALUE_ATTR, value) || ++ check_set_config_value(key, ENV_APPEND_OPTIONS, value) || ++ check_set_config_value(key, ENV_AUTH_CONF_FILE, value)) + ; + } + +@@ -336,6 +353,86 @@ struct ldap_schema *defaults_get_default + return schema; + } + ++static struct ldap_searchdn *alloc_searchdn(const char *value) ++{ ++ struct ldap_searchdn *sdn; ++ char *val; ++ ++ sdn = malloc(sizeof(struct ldap_searchdn)); ++ if (!sdn) ++ return NULL; ++ ++ val = strdup(value); ++ if (!val) { ++ free(sdn); ++ return NULL; ++ } ++ ++ sdn->basedn = val; ++ sdn->next = NULL; ++ ++ return sdn; ++} ++ ++void defaults_free_searchdns(struct ldap_searchdn *sdn) ++{ ++ struct ldap_searchdn *this = sdn; ++ struct ldap_searchdn *next; ++ ++ next = this; ++ while (this) { ++ next = this->next; ++ free(this->basedn); ++ free(this); ++ this = next; ++ } ++ ++ return; ++} ++ ++struct ldap_searchdn *defaults_get_searchdns(void) ++{ ++ FILE *f; ++ char buf[MAX_LINE_LEN]; ++ char *res; ++ struct ldap_searchdn *sdn, *last; ++ ++ f = fopen(DEFAULTS_CONFIG_FILE, "r"); ++ if (!f) ++ return NULL; ++ ++ sdn = last = NULL; ++ ++ while ((res = fgets(buf, MAX_LINE_LEN, f))) { ++ char *key, *value; ++ ++ if (!parse_line(res, &key, &value)) ++ continue; ++ ++ if (!strcasecmp(key, SEARCH_BASE)) { ++ struct ldap_searchdn *new = alloc_searchdn(value); ++ ++ if (!new) { ++ defaults_free_searchdns(sdn); ++ return NULL; ++ } ++ ++ if (!last) ++ last = new; ++ else { ++ last->next = new; ++ last = new; ++ } ++ ++ if (!sdn) ++ sdn = new; ++ } ++ } ++ ++ fclose(f); ++ return sdn; ++} ++ + struct ldap_schema *defaults_get_schema(void) + { + struct ldap_schema *schema; +diff -up autofs-5.0.2/man/auto.master.5.in.ldap-search-basedn-list autofs-5.0.2/man/auto.master.5.in +--- autofs-5.0.2/man/auto.master.5.in.ldap-search-basedn-list 2007-11-20 14:07:52.000000000 +0900 ++++ autofs-5.0.2/man/auto.master.5.in 2007-11-20 14:08:26.000000000 +0900 +@@ -224,6 +224,11 @@ values must be set, any partial schema s + .P + The configuration settings available are: + .TP ++.B SEARCH_BASE ++The base dn to use when searching for amap base dn. This entry may be ++given multiple times and each will be checked for a map base dn in ++the order they occur in the configuration. ++.TP + .B MAP_OBJECT_CLASS + The map object class. In the \fBnisMap\fP schema this corresponds to the class + \fBnisMap\fP and in the \fBautomountMap\fP schema it corresponds to the class diff --git a/autofs-5.0.2-log-map-reload.patch b/autofs-5.0.2-log-map-reload.patch new file mode 100644 index 0000000..20f296e --- /dev/null +++ b/autofs-5.0.2-log-map-reload.patch @@ -0,0 +1,26 @@ +diff --git a/daemon/automount.c b/daemon/automount.c +index 9ec6923..7e7d1e6 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -1278,6 +1278,8 @@ static void *do_read_master(void *arg) + + defaults_read_config(1); + ++ info(logopt, "re-reading master map %s", master->name); ++ + status = master_read_master(master, age, readall); + + master->reading = 0; +diff --git a/daemon/state.c b/daemon/state.c +index a2da762..cf07aac 100644 +--- a/daemon/state.c ++++ b/daemon/state.c +@@ -376,6 +376,8 @@ static void *do_readmap(void *arg) + + pthread_cleanup_push(do_readmap_cleanup, ra); + ++ info(ap->logopt, "re-reading map for %s", ap->path); ++ + status = lookup_nss_read_map(ap, NULL, now); + if (!status) + pthread_exit(NULL); diff --git a/autofs-5.0.2-negative-timeout-update.patch b/autofs-5.0.2-negative-timeout-update.patch new file mode 100644 index 0000000..77e7c8a --- /dev/null +++ b/autofs-5.0.2-negative-timeout-update.patch @@ -0,0 +1,493 @@ +diff --git a/daemon/automount.c b/daemon/automount.c +index a12b6da..7becad5 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -58,6 +58,8 @@ const char *global_options; /* Global option, from command line */ + static char *pid_file = NULL; /* File in which to keep pid */ + unsigned int global_random_selection; /* use random policy when selecting + * which multi-mount host to mount */ ++long global_negative_timeout = -1; ++ + static int start_pipefd[2]; + static int st_stat = 0; + static int *pst_stat = &st_stat; +@@ -1671,6 +1673,8 @@ static void usage(void) + " -f --foreground do not fork into background\n" + " -r --random-multimount-selection\n" + " use ramdom replicated server selection\n" ++ " -n --negative-timeout n\n" ++ " set the timeout for failed key lookups.\n" + " -O --global-options\n" + " specify global mount options\n" + " -l --set-log-priority priority path [path,...]\n" +@@ -1810,6 +1814,7 @@ int main(int argc, char *argv[]) + {"define", 1, 0, 'D'}, + {"foreground", 0, 0, 'f'}, + {"random-multimount-selection", 0, 0, 'r'}, ++ {"negative-timeout", 1, 0, 'n'}, + {"global-options", 1, 0, 'O'}, + {"version", 0, 0, 'V'}, + {"set-log-priority", 1, 0, 'l'}, +@@ -1833,7 +1838,7 @@ int main(int argc, char *argv[]) + foreground = 0; + + opterr = 0; +- while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:", long_options, NULL)) != EOF) { ++ while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:n:", long_options, NULL)) != EOF) { + switch (opt) { + case 'h': + usage(); +@@ -1871,6 +1876,10 @@ int main(int argc, char *argv[]) + global_random_selection = 1; + break; + ++ case 'n': ++ global_negative_timeout = getnumopt(optarg, opt); ++ break; ++ + case 'O': + if (!have_global_options) { + global_options = strdup(optarg); +diff --git a/include/automount.h b/include/automount.h +index b0d1a9c..4887da6 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -442,6 +442,7 @@ struct autofs_point { + unsigned int type; /* Type of map direct or indirect */ + time_t exp_timeout; /* Timeout for expiring mounts */ + time_t exp_runfreq; /* Frequency for polling for timeouts */ ++ time_t negative_timeout; /* timeout in secs for failed mounts */ + unsigned ghost; /* Enable/disable gohsted directories */ + unsigned logopt; /* Per map logging */ + pthread_t exp_thread; /* Thread that is expiring */ +diff --git a/include/defaults.h b/include/defaults.h +index e296478..6e4f52a 100644 +--- a/include/defaults.h ++++ b/include/defaults.h +@@ -22,9 +22,10 @@ + + #define DEFAULT_MASTER_MAP_NAME "auto.master" + +-#define DEFAULT_TIMEOUT 600 +-#define DEFAULT_BROWSE_MODE 1 +-#define DEFAULT_LOGGING 0 ++#define DEFAULT_TIMEOUT 600 ++#define DEFAULT_NEGATIVE_TIMEOUT 60 ++#define DEFAULT_BROWSE_MODE 1 ++#define DEFAULT_LOGGING 0 + + #define DEFAULT_LDAP_TIMEOUT -1 + #define DEFAULT_LDAP_NETWORK_TIMEOUT 8 +@@ -45,6 +46,7 @@ unsigned int defaults_read_config(unsigned int); + const char *defaults_get_master_map(void); + int defaults_master_set(void); + unsigned int defaults_get_timeout(void); ++unsigned int defaults_get_negative_timeout(void); + unsigned int defaults_get_browse_mode(void); + unsigned int defaults_get_logging(void); + const char *defaults_get_ldap_server(void); +diff --git a/lib/defaults.c b/lib/defaults.c +index f494103..8149549 100644 +--- a/lib/defaults.c ++++ b/lib/defaults.c +@@ -28,6 +28,7 @@ + #define ENV_NAME_MASTER_MAP "MASTER_MAP_NAME" + + #define ENV_NAME_TIMEOUT "TIMEOUT" ++#define ENV_NAME_NEGATIVE_TIMEOUT "NEGATIVE_TIMEOUT" + #define ENV_NAME_BROWSE_MODE "BROWSE_MODE" + #define ENV_NAME_LOGGING "LOGGING" + +@@ -308,6 +309,7 @@ unsigned int defaults_read_config(unsigned int to_syslog) + + if (check_set_config_value(key, ENV_NAME_MASTER_MAP, value, to_syslog) || + check_set_config_value(key, ENV_NAME_TIMEOUT, value, to_syslog) || ++ check_set_config_value(key, ENV_NAME_NEGATIVE_TIMEOUT, value, to_syslog) || + check_set_config_value(key, ENV_NAME_BROWSE_MODE, value, to_syslog) || + check_set_config_value(key, ENV_NAME_LOGGING, value, to_syslog) || + check_set_config_value(key, ENV_LDAP_TIMEOUT, value, to_syslog) || +@@ -370,6 +372,17 @@ unsigned int defaults_get_timeout(void) + return (unsigned int) timeout; + } + ++unsigned int defaults_get_negative_timeout(void) ++{ ++ long n_timeout; ++ ++ n_timeout = get_env_number(ENV_NAME_NEGATIVE_TIMEOUT); ++ if (n_timeout <= 0) ++ n_timeout = DEFAULT_NEGATIVE_TIMEOUT; ++ ++ return (unsigned int) n_timeout; ++} ++ + unsigned int defaults_get_browse_mode(void) + { + int res; +diff --git a/lib/master.c b/lib/master.c +index 2188bca..c001d20 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -30,6 +30,8 @@ + /* The root of the map entry tree */ + struct master *master_list = NULL; + ++extern long global_negative_timeout; ++ + /* Attribute to create detached thread */ + extern pthread_attr_t thread_attr; + +@@ -68,6 +70,14 @@ int master_add_autofs_point(struct master_mapent *entry, + ap->exp_thread = 0; + ap->readmap_thread = 0; + ap->exp_timeout = timeout; ++ /* ++ * Program command line option overrides config. ++ * We can't use 0 negative timeout so use default. ++ */ ++ if (global_negative_timeout <= 0) ++ ap->negative_timeout = defaults_get_negative_timeout(); ++ else ++ ap->negative_timeout = global_negative_timeout; + ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; + ap->ghost = ghost; + +diff --git a/lib/master_parse.y b/lib/master_parse.y +index a767f9e..b450122 100644 +--- a/lib/master_parse.y ++++ b/lib/master_parse.y +@@ -55,6 +55,7 @@ static char *path; + static char *type; + static char *format; + static long timeout; ++static long negative_timeout; + static unsigned ghost; + extern unsigned global_random_selection; + static unsigned random_selection; +@@ -95,7 +96,8 @@ static int master_fprintf(FILE *, char *, ...); + + %token COMMENT + %token MAP +-%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM ++%token OPT_TIMEOUT OPT_NTIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE ++%token OPT_DEBUG OPT_RANDOM + %token COLON COMMA NL DDASH + %type map + %type options +@@ -542,6 +544,7 @@ option: daemon_option + ; + + daemon_option: OPT_TIMEOUT NUMBER { timeout = $2; } ++ | OPT_NTIMEOUT NUMBER { negative_timeout = $2; } + | OPT_NOGHOST { ghost = 0; } + | OPT_GHOST { ghost = 1; } + | OPT_VERBOSE { verbose = 1; } +@@ -603,6 +606,7 @@ static void local_init_vars(void) + verbose = 0; + debug = 0; + timeout = -1; ++ negative_timeout = 0; + ghost = defaults_get_browse_mode(); + random_selection = global_random_selection; + tmp_argv = NULL; +@@ -793,6 +797,8 @@ int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigne + } + } + entry->ap->random_selection = random_selection; ++ if (negative_timeout) ++ entry->ap->negative_timeout = negative_timeout; + + /* + source = master_find_map_source(entry, type, format, +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 36aa785..d908047 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -118,6 +118,7 @@ MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?( + + + OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) ++OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS}) + + %% + +@@ -321,6 +322,8 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) + + {OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); } + ++ {OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); } ++ + {NUMBER} { + master_lval.longtype = atol(master_text); + return(NUMBER); +diff --git a/man/auto.master.5.in b/man/auto.master.5.in +index 68447e0..d488960 100644 +--- a/man/auto.master.5.in ++++ b/man/auto.master.5.in +@@ -152,6 +152,11 @@ Enables the use of ramdom selection when choosing a host from a + list of replicated servers. This option is applied to this mount + only, overriding the global setting that may be specified on the + command line. ++.TP ++.I "\-n, \-\-negative\-timeout " ++Set the timeout for caching failed key lookups. This option can be ++used to override the global default given either on the command line ++or in the configuration. + .SH GENERAL SYSTEM DEFAULTS CONFIGURATION + .P + The default value of several general settings may be changed in the +@@ -164,6 +169,11 @@ They are: + .B TIMEOUT + sets the default mount timeout (program default 600). + .TP ++.B NEGATIVE_TIMEOUT ++Set the default timeout for caching failed key lookups (program default ++60). If the equivalent command line option is given it will override this ++setting. ++.TP + .B BROWSE_MODE + Maps are browsable by default (program default "yes"). + .TP +diff --git a/man/automount.8 b/man/automount.8 +index 5cd63c7..59ad50e 100644 +--- a/man/automount.8 ++++ b/man/automount.8 +@@ -34,6 +34,9 @@ Set the global minimum timeout, in seconds, until directories + are unmounted. The default is 10 minutes. Setting the timeout + to zero disables umounts completely. + .TP ++.I "\-n , \-\-negative\-timeout " ++Set the default timeout for caching failed key lookups. The default is 60 seconds. ++.TP + .I "\-v, \-\-verbose" + Enables logging of general status and progress messages for all + autofs managed mounts. +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index c093415..1007de4 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -1126,7 +1126,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + rv = cache_update(mc, source, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); +- me->status = now + NEGATIVE_TIMEOUT; ++ me->status = now + ap->negative_timeout; + } + cache_unlock(mc); + } +diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c +index d746e42..1ef420e 100644 +--- a/modules/lookup_hosts.c ++++ b/modules/lookup_hosts.c +@@ -138,7 +138,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + cache_readlock(mc); + me = cache_lookup_distinct(mc, name); +- if (!me) { ++ if (me && me->status >= time(NULL)) { ++ cache_unlock(mc); ++ return NSS_STATUS_NOTFOUND; ++ } else if (!me) { + cache_unlock(mc); + /* + * We haven't read the list of hosts into the +@@ -192,10 +195,22 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + ret = ctxt->parse->parse_mount(ap, name, name_len, + mapent, ctxt->parse->context); + +- if (!ret) +- return NSS_STATUS_SUCCESS; +- +- return NSS_STATUS_TRYAGAIN; ++ if (ret) { ++ time_t now = time(NULL); ++ int rv = CHE_OK; ++ ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (!me) ++ rv = cache_update(mc, source, name, NULL, now); ++ if (rv != CHE_FAIL) { ++ me = cache_lookup_distinct(mc, name); ++ me->status = now + ap->negative_timeout; ++ } ++ cache_unlock(mc); ++ return NSS_STATUS_TRYAGAIN; ++ } ++ return NSS_STATUS_SUCCESS; + } + done: + /* +@@ -267,8 +282,21 @@ done: + mapent, ctxt->parse->context); + free(mapent); + +- if (ret) ++ if (ret) { ++ time_t now = time(NULL); ++ int rv = CHE_OK; ++ ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (!me) ++ rv = cache_update(mc, source, name, NULL, now); ++ if (rv != CHE_FAIL) { ++ me = cache_lookup_distinct(mc, name); ++ me->status = now + ap->negative_timeout; ++ } ++ cache_unlock(mc); + return NSS_STATUS_TRYAGAIN; ++ } + + return NSS_STATUS_SUCCESS; + } +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 8719af9..4dea3b2 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -2125,7 +2125,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + rv = cache_update(mc, source, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); +- me->status = now + NEGATIVE_TIMEOUT; ++ me->status = now + ap->negative_timeout; + } + cache_unlock(mc); + } +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index bcdaeeb..e948c14 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -547,7 +547,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + rv = cache_update(mc, source, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); +- me->status = time(NULL) + NEGATIVE_TIMEOUT; ++ me->status = time(NULL) + ap->negative_timeout; + } + cache_unlock(mc); + } +diff --git a/modules/lookup_program.c b/modules/lookup_program.c +index e28168e..7c266d6 100644 +--- a/modules/lookup_program.c ++++ b/modules/lookup_program.c +@@ -134,7 +134,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + /* Catch installed direct offset triggers */ + cache_readlock(mc); + me = cache_lookup_distinct(mc, name); +- if (!me) { ++ if (me && me->status >= time(NULL)) { ++ cache_unlock(mc); ++ return NSS_STATUS_NOTFOUND; ++ } else if (!me) { + cache_unlock(mc); + /* + * If there's a '/' in the name and the offset is not in +@@ -147,15 +150,33 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + } else { + cache_unlock(mc); ++ + /* Otherwise we found a valid offset so try mount it */ + debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent); + +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- ret = ctxt->parse->parse_mount(ap, name, name_len, +- me->mapent, ctxt->parse->context); +- goto out_free; ++ /* ++ * If this is a request for an offset mount (whose entry ++ * must be present in the cache to be valid) or the entry ++ * is newer than the negative timeout value then just ++ * try and mount it. Otherwise try and remove it and ++ * proceed with the program map lookup. ++ */ ++ if (strchr(name, '/') || ++ me->age + ap->negative_timeout > time(NULL)) { ++ master_source_current_wait(ap->entry); ++ ap->entry->current = source; ++ ret = ctxt->parse->parse_mount(ap, name, ++ name_len, me->mapent, ctxt->parse->context); ++ goto out_free; ++ } else { ++ if (me->multi) { ++ warn(ap->logopt, MODPREFIX ++ "unexpected lookup for active multi-mount" ++ " key %s, returning fail", name); ++ return NSS_STATUS_UNAVAIL; ++ } ++ cache_delete(mc, name); ++ } + } + + mapent = (char *) malloc(MAPENT_MAX_LEN + 1); +@@ -356,8 +377,21 @@ out_free: + if (mapent) + free(mapent); + +- if (ret) ++ if (ret) { ++ time_t now = time(NULL); ++ int rv = CHE_OK; ++ ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (!me) ++ rv = cache_update(mc, source, name, NULL, now); ++ if (rv != CHE_FAIL) { ++ me = cache_lookup_distinct(mc, name); ++ me->status = now + ap->negative_timeout; ++ } ++ cache_unlock(mc); + return NSS_STATUS_UNAVAIL; ++ } + + return NSS_STATUS_SUCCESS; + } +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index 7ba6940..6c20145 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -639,7 +639,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + rv = cache_update(mc, source, key, NULL, now); + if (rv != CHE_FAIL) { + me = cache_lookup_distinct(mc, key); +- me->status = now + NEGATIVE_TIMEOUT; ++ me->status = now + ap->negative_timeout; + } + cache_unlock(mc); + } +diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in +index f01ee5f..636763a 100644 +--- a/redhat/autofs.sysconfig.in ++++ b/redhat/autofs.sysconfig.in +@@ -9,6 +9,11 @@ + # + TIMEOUT=300 + # ++# NEGATIVE_TIMEOUT - set the default negative timeout for ++# failed mount attempts (default 60). ++# ++#NEGATIVE_TIMEOUT=60 ++# + # BROWSE_MODE - maps are browsable by default. + # + BROWSE_MODE="no" +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index 028341c..086ba4f 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -9,6 +9,11 @@ + # + TIMEOUT=300 + # ++# NEGATIVE_TIMEOUT - set the default negative timeout for ++# failed mount attempts (default 60). ++# ++#NEGATIVE_TIMEOUT=60 ++# + # BROWSE_MODE - maps are browsable by default. + # + BROWSE_MODE="no" diff --git a/autofs-5.0.2-random-selection-fix.patch b/autofs-5.0.2-random-selection-fix.patch new file mode 100644 index 0000000..2b40d06 --- /dev/null +++ b/autofs-5.0.2-random-selection-fix.patch @@ -0,0 +1,247 @@ +diff -up autofs-5.0.2/include/replicated.h.random-selection-fix autofs-5.0.2/include/replicated.h +--- autofs-5.0.2/include/replicated.h.random-selection-fix 2007-06-18 15:18:08.000000000 +0800 ++++ autofs-5.0.2/include/replicated.h 2007-11-20 14:55:28.000000000 +0900 +@@ -63,7 +63,7 @@ struct host { + void seed_random(void); + void free_host_list(struct host **); + int parse_location(struct host **, const char *); +-int prune_host_list(struct host **, unsigned int, const char *); ++int prune_host_list(struct host **, unsigned int, const char *, unsigned int); + void dump_host_list(struct host *); + + #endif +diff -up autofs-5.0.2/include/automount.h.random-selection-fix autofs-5.0.2/include/automount.h +--- autofs-5.0.2/include/automount.h.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/include/automount.h 2007-11-20 14:55:28.000000000 +0900 +@@ -448,6 +448,8 @@ struct autofs_point { + enum states state; /* Current state */ + int state_pipe[2]; /* State change router pipe */ + unsigned dir_created; /* Directory created for this mount? */ ++ unsigned random_selection; /* Use random policy when selecting a ++ * host from which to mount */ + struct autofs_point *parent; /* Owner of mounts list for submount */ + pthread_mutex_t mounts_mutex; /* Protect mount lists */ + pthread_cond_t mounts_cond; /* Submounts condition variable */ +diff -up autofs-5.0.2/modules/mount_nfs.c.random-selection-fix autofs-5.0.2/modules/mount_nfs.c +--- autofs-5.0.2/modules/mount_nfs.c.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/modules/mount_nfs.c 2007-11-20 14:55:28.000000000 +0900 +@@ -137,7 +137,7 @@ int mount_mount(struct autofs_point *ap, + warn(ap->logopt, MODPREFIX "no hosts available"); + return 1; + } +- prune_host_list(&hosts, vers, nfsoptions); ++ prune_host_list(&hosts, vers, nfsoptions, ap->random_selection); + + if (!hosts) { + warn(ap->logopt, MODPREFIX "no hosts available"); +diff -up autofs-5.0.2/modules/replicated.c.random-selection-fix autofs-5.0.2/modules/replicated.c +--- autofs-5.0.2/modules/replicated.c.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/modules/replicated.c 2007-11-20 14:55:28.000000000 +0900 +@@ -74,8 +74,6 @@ + #define max(x, y) (x >= y ? x : y) + #define mmax(x, y, z) (max(x, y) == x ? max(x, z) : max(y, z)) + +-extern unsigned int random_selection; +- + void seed_random(void) + { + int fd; +@@ -392,7 +390,7 @@ static unsigned short get_port_option(co + static unsigned int get_nfs_info(struct host *host, + struct conn_info *pm_info, struct conn_info *rpc_info, + const char *proto, unsigned int version, +- const char *options) ++ const char *options, unsigned int random_selection) + { + char *have_port_opt = options ? strstr(options, "port=") : NULL; + struct pmap parms; +@@ -535,7 +533,9 @@ done_ver: + return supported; + } + +-static int get_vers_and_cost(struct host *host, unsigned int version, const char *options) ++static int get_vers_and_cost(struct host *host, ++ unsigned int version, const char *options, ++ unsigned int random_selection) + { + struct conn_info pm_info, rpc_info; + time_t timeout = RPC_TIMEOUT; +@@ -559,7 +559,9 @@ static int get_vers_and_cost(struct host + vers &= version; + + if (version & UDP_REQUESTED) { +- supported = get_nfs_info(host, &pm_info, &rpc_info, "udp", vers, options); ++ supported = get_nfs_info(host, ++ &pm_info, &rpc_info, "udp", vers, ++ options, random_selection); + if (supported) { + ret = 1; + host->version |= (supported << 8); +@@ -567,7 +569,9 @@ static int get_vers_and_cost(struct host + } + + if (version & TCP_REQUESTED) { +- supported = get_nfs_info(host, &pm_info, &rpc_info, "tcp", vers, options); ++ supported = get_nfs_info(host, ++ &pm_info, &rpc_info, "tcp", vers, ++ options, random_selection); + if (supported) { + ret = 1; + host->version |= supported; +@@ -577,7 +581,9 @@ static int get_vers_and_cost(struct host + return ret; + } + +-static int get_supported_ver_and_cost(struct host *host, unsigned int version, const char *options) ++static int get_supported_ver_and_cost(struct host *host, ++ unsigned int version, const char *options, ++ unsigned int random_selection) + { + char *have_port_opt = options ? strstr(options, "port=") : NULL; + struct conn_info pm_info, rpc_info; +@@ -695,7 +701,9 @@ done: + return 0; + } + +-int prune_host_list(struct host **list, unsigned int vers, const char *options) ++int prune_host_list(struct host **list, ++ unsigned int vers, const char *options, ++ unsigned int random_selection) + { + struct host *this, *last, *first; + struct host *new = NULL; +@@ -734,7 +742,8 @@ int prune_host_list(struct host **list, + break; + + if (this->name) { +- status = get_vers_and_cost(this, vers, options); ++ status = get_vers_and_cost(this, vers, ++ options, random_selection); + if (!status) { + if (this == first) { + first = next; +@@ -824,7 +833,9 @@ int prune_host_list(struct host **list, + remove_host(list, this); + add_host(&new, this); + } else { +- status = get_supported_ver_and_cost(this, selected_version, options); ++ status = get_supported_ver_and_cost(this, ++ selected_version, options, ++ random_selection); + if (status) { + this->version = selected_version; + remove_host(list, this); +diff -up autofs-5.0.2/daemon/automount.c.random-selection-fix autofs-5.0.2/daemon/automount.c +--- autofs-5.0.2/daemon/automount.c.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/daemon/automount.c 2007-11-20 14:55:28.000000000 +0900 +@@ -52,9 +52,9 @@ const char *confdir = AUTOFS_CONF_DIR; / + + const char *global_options; /* Global option, from command line */ + +-static char *pid_file = NULL; /* File in which to keep pid */ +-unsigned int random_selection; /* use random policy when selecting +- * which multi-mount host to mount */ ++static char *pid_file = NULL; /* File in which to keep pid */ ++unsigned int global_random_selection; /* use random policy when selecting ++ * which multi-mount host to mount */ + static int start_pipefd[2]; + static int st_stat = 0; + static int *pst_stat = &st_stat; +@@ -1469,7 +1469,7 @@ int main(int argc, char *argv[]) + timeout = defaults_get_timeout(); + ghost = defaults_get_browse_mode(); + logging = defaults_get_logging(); +- random_selection = 0; ++ global_random_selection = 0; + global_options = NULL; + have_global_options = 0; + foreground = 0; +@@ -1510,7 +1510,7 @@ int main(int argc, char *argv[]) + exit(0); + + case 'r': +- random_selection = 1; ++ global_random_selection = 1; + break; + + case 'O': +diff -up autofs-5.0.2/lib/master_tok.l.random-selection-fix autofs-5.0.2/lib/master_tok.l +--- autofs-5.0.2/lib/master_tok.l.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/lib/master_tok.l 2007-11-20 14:55:28.000000000 +0900 +@@ -324,6 +324,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|-- + -g|--ghost|-?browse { return(OPT_GHOST); } + -v|--verbose { return(OPT_VERBOSE); } + -d|--debug { return(OPT_DEBUG); } ++ -r|--random-multimount-selection { return(OPT_RANDOM); } + + {OPTWS}","{OPTWS} { return(COMMA); } + +diff -up autofs-5.0.2/lib/master_parse.y.random-selection-fix autofs-5.0.2/lib/master_parse.y +--- autofs-5.0.2/lib/master_parse.y.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/lib/master_parse.y 2007-11-20 14:55:28.000000000 +0900 +@@ -56,6 +56,8 @@ static char *type; + static char *format; + static long timeout; + static unsigned ghost; ++extern unsigned global_random_selection; ++static unsigned random_selection; + static char **tmp_argv; + static int tmp_argc; + static char **local_argv; +@@ -93,7 +95,7 @@ static int master_fprintf(FILE *, char * + + %token COMMENT + %token MAP +-%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG ++%token OPT_TIMEOUT OPT_NOGHOST OPT_GHOST OPT_VERBOSE OPT_DEBUG OPT_RANDOM + %token COLON COMMA NL DDASH + %type map + %type options +@@ -174,6 +176,7 @@ line: + | PATH COLON { master_notify($1); YYABORT; } + | PATH OPTION { master_notify($2); YYABORT; } + | PATH NILL { master_notify($2); YYABORT; } ++ | PATH OPT_RANDOM { master_notify($1); YYABORT; } + | PATH OPT_DEBUG { master_notify($1); YYABORT; } + | PATH OPT_TIMEOUT { master_notify($1); YYABORT; } + | PATH OPT_GHOST { master_notify($1); YYABORT; } +@@ -543,6 +546,7 @@ daemon_option: OPT_TIMEOUT NUMBER { time + | OPT_GHOST { ghost = 1; } + | OPT_VERBOSE { verbose = 1; } + | OPT_DEBUG { debug = 1; } ++ | OPT_RANDOM { random_selection = 1; } + ; + + mount_option: OPTION +@@ -600,6 +604,7 @@ static void local_init_vars(void) + debug = 0; + timeout = -1; + ghost = defaults_get_browse_mode(); ++ random_selection = global_random_selection; + tmp_argv = NULL; + tmp_argc = 0; + local_argv = NULL; +@@ -790,6 +795,7 @@ int master_parse_entry(const char *buffe + } + set_mnt_logging(ap); + } ++ entry->ap->random_selection = random_selection; + + /* + source = master_find_map_source(entry, type, format, +diff -up autofs-5.0.2/man/auto.master.5.in.random-selection-fix autofs-5.0.2/man/auto.master.5.in +--- autofs-5.0.2/man/auto.master.5.in.random-selection-fix 2007-11-20 14:55:28.000000000 +0900 ++++ autofs-5.0.2/man/auto.master.5.in 2007-11-20 14:55:28.000000000 +0900 +@@ -146,6 +146,12 @@ to prevent symlinking of local NFS mount + prevent bind mounting of local NFS filesystems as well. If you need to + prevent bind mounting for only specific entrys in a map then this + can be done by adding the "port=" mount option to the given entries. ++.TP ++.I "\-r, \-\-random-multimount-selection" ++Enables the use of ramdom selection when choosing a host from a ++list of replicated servers. This option is applied to this mount ++only, overriding the global setting that may be specified on the ++command line. + .SH GENERAL SYSTEM DEFAULTS CONFIGURATION + .P + The default value of several general settings may be changed in the diff --git a/autofs-5.0.2-remove-unused-export-validation-code.patch b/autofs-5.0.2-remove-unused-export-validation-code.patch new file mode 100644 index 0000000..8b89e6b --- /dev/null +++ b/autofs-5.0.2-remove-unused-export-validation-code.patch @@ -0,0 +1,611 @@ +diff --git a/lib/rpc_subs.c b/lib/rpc_subs.c +index 831d456..d79a94f 100644 +--- a/lib/rpc_subs.c ++++ b/lib/rpc_subs.c +@@ -52,10 +52,7 @@ + /* Get numeric value of the n bits starting at position p */ + #define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n)) + +-static char *domain = NULL; +- + inline void dump_core(void); +-static pthread_mutex_t networks_mutex = PTHREAD_MUTEX_INITIALIZER; + + /* + * Create a UDP RPC client +@@ -764,573 +761,6 @@ void rpc_exports_free(exports list) + return; + } + +-static int masked_match(const char *addr, const char *mask) +-{ +- char buf[MAX_IFC_BUF], *ptr; +- struct sockaddr_in saddr; +- struct sockaddr_in6 saddr6; +- struct ifconf ifc; +- struct ifreq *ifr; +- int sock, cl_flags, ret, i, is_ipv4, is_ipv6; +- unsigned int msize; +- +- sock = socket(AF_INET, SOCK_DGRAM, 0); +- if (sock < 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "socket creation failed: %s", estr); +- return 0; +- } +- +- if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(sock, F_SETFD, cl_flags); +- } +- +- ifc.ifc_len = sizeof(buf); +- ifc.ifc_req = (struct ifreq *) buf; +- ret = ioctl(sock, SIOCGIFCONF, &ifc); +- if (ret == -1) { +- close(sock); +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "ioctl: %s", estr); +- return 0; +- } +- +- is_ipv4 = is_ipv6 = 0; +- is_ipv4 = inet_pton(AF_INET, addr, &saddr.sin_addr); +- if (!is_ipv4) +- is_ipv6 = inet_pton(AF_INET6, addr, &saddr6.sin6_addr); +- +- if (strchr(mask, '.')) { +- struct sockaddr_in maddr; +- uint32_t ma; +- int i = 0; +- +- ret = inet_aton(mask, &maddr.sin_addr); +- if (!ret) { +- close(sock); +- return 0; +- } +- +- ma = ntohl((uint32_t) maddr.sin_addr.s_addr); +- while (!(ma & 1)) { +- i++; +- ma = ma >> 1; +- } +- +- msize = i; +- } else +- msize = atoi(mask); +- +- i = 0; +- ptr = (char *) &ifc.ifc_buf[0]; +- +- while (ptr < buf + ifc.ifc_len) { +- ifr = (struct ifreq *) ptr; +- +- switch (ifr->ifr_addr.sa_family) { +- case AF_INET: +- { +- struct sockaddr_in *if_addr; +- uint32_t m, ia, ha; +- +- if (!is_ipv4 || msize > 32) +- break; +- +- m = -1; +- m = m << (32 - msize); +- ha = ntohl((uint32_t) saddr.sin_addr.s_addr); +- +- if_addr = (struct sockaddr_in *) &ifr->ifr_addr; +- ia = ntohl((uint32_t) if_addr->sin_addr.s_addr); +- +- if ((ia & m) == (ha & m)) { +- close(sock); +- return 1; +- } +- break; +- } +- +- /* glibc rpc only understands IPv4 atm */ +- case AF_INET6: +- break; +- +- default: +- break; +- } +- +- i++; +- ptr = (char *) &ifc.ifc_req[i]; +- } +- +- close(sock); +- return 0; +-} +- +-/* +- * This function has been adapted from the match_patern function +- * found in OpenSSH and is used in accordance with the copyright +- * notice found their. +- * +- * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland. +- */ +-/* +- * Returns true if the given string matches the pattern (which +- * may contain ? and * as wildcards), and zero if it does not +- * match. +- */ +-static int pattern_match(const char *s, const char *pattern) +-{ +- for (;;) { +- /* If at end of pattern, accept if also at end of string. */ +- if (!*pattern) +- return !*s; +- +- if (*pattern == '*') { +- /* Skip the asterisk. */ +- pattern++; +- +- /* If at end of pattern, accept immediately. */ +- if (!*pattern) +- return 1; +- +- /* If next character in pattern is known, optimize. */ +- if (*pattern != '?' && *pattern != '*') { +- /* +- * Look instances of the next character in +- * pattern, and try to match starting from +- * those. +- */ +- for (; *s; s++) +- if (*s == *pattern && +- pattern_match(s + 1, pattern + 1)) +- return 1; +- +- /* Failed. */ +- return 0; +- } +- /* +- * Move ahead one character at a time and try to +- * match at each position. +- */ +- for (; *s; s++) +- if (pattern_match(s, pattern)) +- return 1; +- /* Failed. */ +- return 0; +- } +- /* +- * There must be at least one more character in the string. +- * If we are at the end, fail. +- */ +- if (!*s) +- return 0; +- +- /* Check if the next character of the string is acceptable. */ +- if (*pattern != '?' && *pattern != *s) +- return 0; +- +- /* Move to the next character, both in string and in pattern. */ +- s++; +- pattern++; +- } +- /* NOTREACHED */ +-} +- +-static int name_match(const char *name, const char *pattern) +-{ +- int ret; +- +- if (strchr(pattern, '*') || strchr(pattern, '?')) +- ret = pattern_match(name, pattern); +- else { +- ret = !memcmp(name, pattern, strlen(pattern)); +- /* Name could still be a netgroup (Solaris) */ +- if (!ret) +- ret = innetgr(pattern, name, NULL, domain); +- } +- +- return ret; +-} +- +-static int fqdn_match(const char *pattern) +-{ +- char buf[MAX_IFC_BUF], *ptr; +- struct ifconf ifc; +- struct ifreq *ifr; +- int sock, cl_flags, ret, i; +- char fqdn[NI_MAXHOST + 1]; +- +- sock = socket(AF_INET, SOCK_DGRAM, 0); +- if (sock < 0) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "socket creation failed: %s", estr); +- return 0; +- } +- +- if ((cl_flags = fcntl(sock, F_GETFD, 0)) != -1) { +- cl_flags |= FD_CLOEXEC; +- fcntl(sock, F_SETFD, cl_flags); +- } +- +- ifc.ifc_len = sizeof(buf); +- ifc.ifc_req = (struct ifreq *) buf; +- ret = ioctl(sock, SIOCGIFCONF, &ifc); +- if (ret == -1) { +- close(sock); +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(LOGOPT_ANY, "ioctl: %s", estr); +- return 0; +- } +- +- i = 0; +- ptr = (char *) &ifc.ifc_buf[0]; +- +- while (ptr < buf + ifc.ifc_len) { +- ifr = (struct ifreq *) ptr; +- +- switch (ifr->ifr_addr.sa_family) { +- case AF_INET: +- { +- socklen_t slen = sizeof(struct sockaddr); +- +- ret = getnameinfo(&ifr->ifr_addr, slen, fqdn, +- NI_MAXHOST, NULL, 0, NI_NAMEREQD); +- if (!ret) { +- ret = name_match(fqdn, pattern); +- if (ret) { +- close(sock); +- return 1; +- } +- } +- break; +- } +- +- /* glibc rpc only understands IPv4 atm */ +- case AF_INET6: +- break; +- +- default: +- break; +- } +- +- i++; +- ptr = (char *) &ifc.ifc_req[i]; +- } +- +- close(sock); +- return 0; +-} +- +-static int string_match(const char *myname, const char *pattern) +-{ +- struct addrinfo hints, *ni; +- int ret; +- +- /* Try simple name match first */ +- ret = name_match(myname, pattern); +- if (ret) +- goto done; +- +- memset(&hints, 0, sizeof(hints)); +- hints.ai_flags = AI_CANONNAME; +- hints.ai_family = 0; +- hints.ai_socktype = 0; +- +- /* See if our canonical name matches */ +- if (getaddrinfo(myname, NULL, &hints, &ni) == 0) { +- ret = name_match(ni->ai_canonname, pattern); +- freeaddrinfo(ni); +- } else +- warn(LOGOPT_ANY, "name lookup failed: %s", gai_strerror(ret)); +- if (ret) +- goto done; +- +- /* Lastly see if the name of an interfaces matches */ +- ret = fqdn_match(pattern); +-done: +- return ret; +-} +- +-static unsigned int inet_get_net_len(uint32_t net) +-{ +- int i; +- +- for (i = 0; i < 32; i += 8) { +- if (getbits(net, i + 7, 8)) +- break; +- } +- +- return (unsigned int) 32 - i; +-} +- +-static char *inet_fill_net(const char *net_num, char *net) +-{ +- char *np; +- unsigned int dots = 3; +- +- if (strlen(net_num) > INET_ADDRSTRLEN) +- return NULL; +- +- if (!isdigit(*net_num)) +- return NULL; +- +- *net = '\0'; +- strcpy(net, net_num); +- +- np = net; +- while (*np++) { +- if (*np == '.') { +- np++; +- dots--; +- if (!*np && dots) +- strcat(net, "0"); +- continue; +- } +- +- if ((*np && !isdigit(*np)) || dots < 0) { +- *net = '\0'; +- return NULL; +- } +- } +- +- while (dots--) +- strcat(net, ".0"); +- +- return net; +-} +- +-static int match_network(const char *network) +-{ +- struct netent *pnent, nent; +- const char *pcnet; +- char *net, cnet[MAX_NETWORK_LEN], mask[4], *pmask; +- unsigned int size; +- size_t l_network = strlen(network) + 1; +- int status; +- +- if (l_network > MAX_NETWORK_LEN) { +- error(LOGOPT_ANY, +- "match string \"%s\" too long", network); +- return 0; +- } +- +- net = alloca(l_network); +- if (!net) +- return 0; +- memset(net, 0, l_network); +- strcpy(net, network); +- +- if ((pmask = strchr(net, '/'))) +- *pmask++ = '\0'; +- +- status = pthread_mutex_lock(&networks_mutex); +- if (status) +- fatal(status); +- +- pnent = getnetbyname(net); +- if (pnent) +- memcpy(&nent, pnent, sizeof(struct netent)); +- +- status = pthread_mutex_unlock(&networks_mutex); +- if (status) +- fatal(status); +- +- if (pnent) { +- uint32_t n_net; +- +- switch (nent.n_addrtype) { +- case AF_INET: +- n_net = ntohl(nent.n_net); +- pcnet = inet_ntop(AF_INET, &n_net, cnet, INET_ADDRSTRLEN); +- if (!pcnet) +- return 0; +- +- if (!pmask) { +- size = inet_get_net_len(nent.n_net); +- if (!size) +- return 0; +- } +- break; +- +- case AF_INET6: +- return 0; +- +- default: +- return 0; +- } +- } else { +- int ret; +- +- if (strchr(net, ':')) { +- return 0; +- } else { +- struct in_addr addr; +- +- pcnet = inet_fill_net(net, cnet); +- if (!pcnet) +- return 0; +- +- ret = inet_pton(AF_INET, pcnet, &addr); +- if (ret <= 0) +- return 0; +- +- if (!pmask) { +- uint32_t nl_addr = htonl(addr.s_addr); +- size = inet_get_net_len(nl_addr); +- if (!size) +- return 0; +- } +- } +- } +- +- if (!pmask) { +- if (sprintf(mask, "%u", size) <= 0) +- return 0; +- pmask = mask; +- } +- +- debug(LOGOPT_ANY, "pcnet %s pmask %s", pcnet, pmask); +- +- return masked_match(pcnet, pmask); +-} +- +-/* +- * Two export formats need to be understood to cater for different +- * NFS server exports. +- * +- * (host|wildcard|network[/mask]|@netgroup) +- * +- * A host name which can be cannonical. +- * A wildcard host name containing "*" and "?" with the usual meaning. +- * A network in numbers and dots form with optional mask given as +- * either a length or as numbers and dots. +- * A netgroup identified by the prefix "@". +- * +- * [-](host|domain suffix|netgroup|@network[/mask]) +- * +- * A host name which can be cannonical. +- * A domain suffix identified by a leading "." which will match all +- * hosts in the given domain. +- * A netgroup. +- * A network identified by the prefix "@" given in numbers and dots +- * form or as a network name with optional mask given as either a +- * length or as numbers and dots. +- * A "-" prefix can be appended to indicate access is denied. +- */ +-static int host_match(char *pattern) +-{ +- unsigned int negate = (*pattern == '-'); +- const char *m_pattern = (negate ? pattern + 1 : pattern); +- char myname[MAXHOSTNAMELEN + 1] = "\0"; +- int ret = 0; +- +- if (gethostname(myname, MAXHOSTNAMELEN)) +- return 0; +- +- if (yp_get_default_domain(&domain)) +- domain = NULL; +- +- if (*m_pattern == '@') { +- /* +- * The pattern begins with an "@" so it's a network +- * spec or it's a netgroup. +- */ +- ret = match_network(m_pattern + 1); +- if (!ret) +- ret = innetgr(m_pattern + 1, myname, NULL, domain); +- } else if (*m_pattern == '.') { +- size_t m_len = strlen(m_pattern); +- char *has_dot = strchr(myname, '.'); +- /* +- * The pattern starts with a "." so it's a domain spec +- * of some sort. +- * +- * If the host name contains a dot then it must be either +- * a cannonical name or a simple NIS name.domain. So +- * perform a string match. Otherwise, append the domain +- * pattern to our simple name and try a wildcard pattern +- * match against the interfaces. +- */ +- if (has_dot) { +- if (strlen(has_dot) == m_len) +- ret = !memcmp(has_dot, m_pattern, m_len); +- } else { +- char *w_pattern = alloca(m_len + 2); +- if (w_pattern) { +- strcpy(w_pattern, "*"); +- strcat(w_pattern, m_pattern); +- ret = fqdn_match(w_pattern); +- } +- } +- } else if (!strcmp(m_pattern, "gss/krb5")) { +- /* Leave this to the GSS layer */ +- return 1; +- } else { +- /* +- * Otherwise it's a network name or host name +- */ +- ret = match_network(m_pattern); +- if (!ret) +- /* if not then try to match host name */ +- ret = string_match(myname, m_pattern); +- } +- +- if (negate && ret) +- ret = -1; +- +- return ret; +-} +- +-static int rpc_export_allowed(groups grouplist) +-{ +- groups grp = grouplist; +- +- /* NULL group list => everyone */ +- if (!grp) +- return 1; +- +- while (grp) { +- int allowed = host_match(grp->gr_name); +- /* Explicitly denied access */ +- if (allowed == -1) +- return 0; +- else if (allowed) +- return 1; +- grp = grp->gr_next; +- } +- return 0; +-} +- +-exports rpc_exports_prune(exports list) +-{ +- exports head = list; +- exports exp; +- exports last; +- int res; +- +- exp = list; +- last = NULL; +- while (exp) { +- res = rpc_export_allowed(exp->ex_groups); +- if (!res) { +- if (last == NULL) { +- head = exp->ex_next; +- rpc_export_free(exp); +- exp = head; +- } else { +- last->ex_next = exp->ex_next; +- rpc_export_free(exp); +- exp = last->ex_next; +- } +- continue; +- } +- last = exp; +- exp = exp->ex_next; +- } +- return head; +-} +- + exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option) + { + struct conn_info info; +diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c +index 1f8fa15..d711611 100644 +--- a/modules/lookup_hosts.c ++++ b/modules/lookup_hosts.c +@@ -45,7 +45,6 @@ struct lookup_context { + int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ + + exports rpc_get_exports(const char *host, long seconds, long micros, unsigned int option); +-exports rpc_exports_prune(exports list); + void rpc_exports_free(exports list); + + int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context) +@@ -207,9 +206,6 @@ done: + + exp = rpc_get_exports(name, 10, 0, RPC_CLOSE_NOLINGER); + +- /* Check exports for obvious ones we don't have access to */ +- /*exp = rpc_exports_prune(exp);*/ +- + mapent = NULL; + while (exp) { + if (mapent) { diff --git a/autofs-5.0.2-report-failed-lookups.patch b/autofs-5.0.2-report-failed-lookups.patch new file mode 100644 index 0000000..3502384 --- /dev/null +++ b/autofs-5.0.2-report-failed-lookups.patch @@ -0,0 +1,123 @@ +diff --git a/modules/lookup_file.c b/modules/lookup_file.c +index 1007de4..23ea07d 100644 +--- a/modules/lookup_file.c ++++ b/modules/lookup_file.c +@@ -1088,8 +1088,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + if (status == NSS_STATUS_COMPLETED) + return NSS_STATUS_SUCCESS; + +- debug(ap->logopt, +- MODPREFIX "check indirect map lookup failed"); ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", ++ name); + + return NSS_STATUS_NOTFOUND; + } +@@ -1130,7 +1131,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + cache_unlock(mc); + } +- } ++ } else ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map.", name); + + if (ret) + return NSS_STATUS_TRYAGAIN; +diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c +index 649e24c..737a47e 100644 +--- a/modules/lookup_hesiod.c ++++ b/modules/lookup_hesiod.c +@@ -129,8 +129,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + if (!hes_result || !hes_result[0]) { + /* Note: it is not clear to me how to distinguish between + * the "no search results" case and other failures. --JM */ +- warn(ap->logopt, +- MODPREFIX "entry \"%s\" not found in map", name); ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", name); + status = pthread_mutex_unlock(&hesiod_mutex); + if (status) + fatal(status); +diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c +index 4dea3b2..bad48bb 100644 +--- a/modules/lookup_ldap.c ++++ b/modules/lookup_ldap.c +@@ -2089,8 +2089,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); + free(lkp_key); + if (status) { +- debug(ap->logopt, +- MODPREFIX "check indirect map failure"); ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", ++ name); + return status; + } + } +@@ -2129,7 +2130,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + cache_unlock(mc); + } +- } ++ } else ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", name); + + if (ret) + return NSS_STATUS_TRYAGAIN; +diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c +index e948c14..bb1ca42 100644 +--- a/modules/lookup_nisplus.c ++++ b/modules/lookup_nisplus.c +@@ -512,8 +512,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); + if (status) { +- debug(ap->logopt, +- MODPREFIX "check indirect map failure"); ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", ++ name); + return status; + } + } +@@ -551,7 +552,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + cache_unlock(mc); + } +- } ++ } else ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", name); + + if (ret) + return NSS_STATUS_NOTFOUND; +diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c +index 6c20145..e8ca8e8 100644 +--- a/modules/lookup_yp.c ++++ b/modules/lookup_yp.c +@@ -604,8 +604,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt); + free(lkp_key); + if (status) { +- debug(ap->logopt, +- MODPREFIX "check indirect map lookup failed"); ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", ++ name); + return status; + } + } +@@ -643,7 +644,9 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void * + } + cache_unlock(mc); + } +- } ++ } else ++ error(ap->logopt, ++ MODPREFIX "key \"%s\" not found in map", name); + + if (ret) + return NSS_STATUS_TRYAGAIN; diff --git a/autofs-5.0.2-reread-config-on-hup.patch b/autofs-5.0.2-reread-config-on-hup.patch new file mode 100644 index 0000000..85afb5b --- /dev/null +++ b/autofs-5.0.2-reread-config-on-hup.patch @@ -0,0 +1,124 @@ +diff -up autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup autofs-5.0.2/modules/cyrus-sasl.c +--- autofs-5.0.2/modules/cyrus-sasl.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 ++++ autofs-5.0.2/modules/cyrus-sasl.c 2007-11-20 15:00:13.000000000 +0900 +@@ -528,6 +528,7 @@ sasl_do_kinit(struct lookup_context *ctx + return 0; + + out_cleanup_unparse: ++ krb5cc_in_use--; + krb5_free_unparsed_name(ctxt->krb5ctxt, tgs_name); + out_cleanup_cc: + status = pthread_mutex_lock(&krb5cc_mutex); +diff -up autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup autofs-5.0.2/modules/lookup_ldap.c +--- autofs-5.0.2/modules/lookup_ldap.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 ++++ autofs-5.0.2/modules/lookup_ldap.c 2007-11-20 15:00:13.000000000 +0900 +@@ -174,7 +174,7 @@ LDAP *init_ldap_connection(struct lookup + static int get_query_dn(LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key) + { + char buf[PARSE_MAX_BUF]; +- char *query, *dn; ++ char *query, *dn, *qdn; + LDAPMessage *result = NULL, *e; + struct ldap_searchdn *sdns = NULL; + char *attrs[2]; +@@ -225,15 +225,18 @@ static int get_query_dn(LDAP *ldap, stru + + if (!ctxt->base) { + sdns = defaults_get_searchdns(); +- if (sdns) ++ if (sdns) { ++ if (ctxt->sdns) ++ defaults_free_searchdns(ctxt->sdns); + ctxt->sdns = sdns; ++ } + } + +- if (!sdns) ++ if (!ctxt->sdns) + rv = ldap_search_s(ldap, ctxt->base, + scope, query, attrs, 0, &result); + else { +- struct ldap_searchdn *this = sdns; ++ struct ldap_searchdn *this = ctxt->sdns; + + debug(LOGOPT_NONE, MODPREFIX + "check search base list"); +@@ -269,7 +272,6 @@ static int get_query_dn(LDAP *ldap, stru + if (e) { + dn = ldap_get_dn(ldap, e); + debug(LOGOPT_NONE, MODPREFIX "query dn %s", dn); +- ldap_msgfree(result); + } else { + debug(LOGOPT_NONE, + MODPREFIX "query succeeded, no matches for %s", +@@ -278,7 +280,16 @@ static int get_query_dn(LDAP *ldap, stru + return 0; + } + +- ctxt->qdn = dn; ++ qdn = strdup(dn); ++ ldap_memfree(dn); ++ ldap_msgfree(result); ++ if (!qdn) ++ return 0; ++ ++ if (ctxt->qdn) ++ free(ctxt->qdn); ++ ++ ctxt->qdn = qdn; + + return 1; + } +@@ -1018,7 +1029,7 @@ static void free_context(struct lookup_c + if (ctxt->mapname) + free(ctxt->mapname); + if (ctxt->qdn) +- ldap_memfree(ctxt->qdn); ++ free(ctxt->qdn); + if (ctxt->server) + free(ctxt->server); + if (ctxt->cur_host) +@@ -1600,14 +1611,14 @@ static int lookup_one(struct autofs_poin + } + query[ql] = '\0'; + +- debug(ap->logopt, +- MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn); +- + /* Initialize the LDAP context. */ + ldap = do_connect(ctxt); + if (!ldap) + return CHE_FAIL; + ++ debug(ap->logopt, ++ MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn); ++ + rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result); + + if ((rv != LDAP_SUCCESS) || !result) { +diff -up autofs-5.0.2/daemon/automount.c.reread-config-on-hup autofs-5.0.2/daemon/automount.c +--- autofs-5.0.2/daemon/automount.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 ++++ autofs-5.0.2/daemon/automount.c 2007-11-20 15:00:13.000000000 +0900 +@@ -978,6 +978,8 @@ static void *do_read_master(void *arg) + if (status) + fatal(status); + ++ defaults_read_config(); ++ + status = master_read_master(master, age, readall); + + master->reading = 0; +diff -up autofs-5.0.2/lib/master.c.reread-config-on-hup autofs-5.0.2/lib/master.c +--- autofs-5.0.2/lib/master.c.reread-config-on-hup 2007-11-20 15:00:13.000000000 +0900 ++++ autofs-5.0.2/lib/master.c 2007-11-20 15:00:13.000000000 +0900 +@@ -1170,6 +1170,10 @@ int master_mount_mounts(struct master *m + continue; + } + ++ master_source_writelock(this); ++ lookup_close_lookup(ap); ++ master_source_unlock(this); ++ + cache_readlock(nc); + ne = cache_lookup_distinct(nc, this->path); + if (ne && this->age > ne->age) { diff --git a/autofs-5.0.2-singleton-host-list.patch b/autofs-5.0.2-singleton-host-list.patch new file mode 100644 index 0000000..9228bc0 --- /dev/null +++ b/autofs-5.0.2-singleton-host-list.patch @@ -0,0 +1,45 @@ +diff --git a/modules/replicated.c b/modules/replicated.c +index 14b20a9..90b2925 100644 +--- a/modules/replicated.c ++++ b/modules/replicated.c +@@ -725,19 +725,21 @@ int prune_host_list(unsigned logopt, struct host **list, + while (this && this->proximity == PROXIMITY_LOCAL) + this = this->next; + +- proximity = PROXIMITY_LOCAL; +- if (this) +- proximity = this->proximity; ++ /* ++ * Check for either a list containing only proximity local hosts ++ * or a single host entry whose proximity isn't local. If so ++ * return immediately as we don't want to add probe latency for ++ * the common case of a single filesystem mount request. ++ */ ++ if (!this || !this->next) ++ return 1; + ++ proximity = this->proximity; ++ first = this; + this = first; + while (this) { + struct host *next = this->next; + +- if (this->proximity == PROXIMITY_LOCAL) { +- this = next; +- continue; +- } +- + if (this->proximity != proximity) + break; + +@@ -758,10 +760,6 @@ int prune_host_list(unsigned logopt, struct host **list, + + last = this; + +- /* If there are only local entries on the list, just return it. */ +- if (!first) +- return 0; +- + /* Select NFS version of highest number of closest servers */ + + v4_tcp_count = v3_tcp_count = v2_tcp_count = 0; diff --git a/autofs-5.0.2-submount-deadlock.patch b/autofs-5.0.2-submount-deadlock.patch new file mode 100644 index 0000000..4fbc7bd --- /dev/null +++ b/autofs-5.0.2-submount-deadlock.patch @@ -0,0 +1,22 @@ +diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c +index f8d8ed2..c45b91b 100644 +--- a/modules/mount_autofs.c ++++ b/modules/mount_autofs.c +@@ -215,6 +215,8 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + return 1; + } + ++ mounts_mutex_lock(ap); ++ + status = pthread_mutex_lock(&suc.mutex); + if (status) { + crit(ap->logopt, +@@ -227,8 +229,6 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, + suc.done = 0; + suc.status = 0; + +- mounts_mutex_lock(ap); +- + if (pthread_create(&thid, NULL, handle_mounts, nap)) { + crit(ap->logopt, + MODPREFIX diff --git a/autofs-5.0.2-swallow-null-macro.patch b/autofs-5.0.2-swallow-null-macro.patch new file mode 100644 index 0000000..5bca30c --- /dev/null +++ b/autofs-5.0.2-swallow-null-macro.patch @@ -0,0 +1,24 @@ +diff --git a/modules/parse_sun.c b/modules/parse_sun.c +index 5e14c75..079bda6 100644 +--- a/modules/parse_sun.c ++++ b/modules/parse_sun.c +@@ -186,8 +186,7 @@ int expandsunent(const char *src, char *dst, const char *key, + dst += l; + } + len += l; +- } else +- return 0; ++ } + src = p + 1; + } else { + p = src; +@@ -201,8 +200,7 @@ int expandsunent(const char *src, char *dst, const char *key, + dst += l; + } + len += l; +- } else +- return 0; ++ } + src = p; + } + break; diff --git a/autofs-5.0.2-timeout-option-parse-fix.patch b/autofs-5.0.2-timeout-option-parse-fix.patch new file mode 100644 index 0000000..fdb5065 --- /dev/null +++ b/autofs-5.0.2-timeout-option-parse-fix.patch @@ -0,0 +1,13 @@ +diff --git a/lib/master_tok.l b/lib/master_tok.l +index 013a15a..2735223 100644 +--- a/lib/master_tok.l ++++ b/lib/master_tok.l +@@ -313,7 +313,7 @@ OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) + return(DDASH); + } + +- {OPTTOUT} { return(OPT_TIMEOUT); } ++ {OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); } + + {NUMBER} { + master_lval.longtype = atol(master_text); diff --git a/autofs.spec b/autofs.spec index dba8275..9c29cd3 100644 --- a/autofs.spec +++ b/autofs.spec @@ -4,7 +4,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.0.2 -Release: 16 +Release: 17 Epoch: 1 License: GPL Group: System Environment/Daemons @@ -31,6 +31,30 @@ Patch17: autofs-5.0.2-add-ldap-schema-discovery.patch Patch18: autofs-5.0.2-ldap-schema-discovery-config-update.patch Patch19: autofs-5.0.2-libxml2-workaround.patch Patch20: autofs-5.0.2-foreground-logging.patch +Patch21: autofs-5.0.2-add-ldap-schema-discovery-fix-2.patch +Patch22: autofs-5.0.2-ldap-check-star.patch +Patch23: autofs-5.0.2-timeout-option-parse-fix.patch +Patch24: autofs-5.0.2-ldap-search-basedn-list.patch +Patch25: autofs-5.0.2-random-selection-fix.patch +Patch26: autofs-5.0.2-reread-config-on-hup.patch +Patch27: autofs-5.0.2-add-multiple-server-selection-option.patch +Patch28: autofs-5.0.2-submount-deadlock.patch +Patch29: autofs-5.0.2-add-ferror-check.patch +Patch30: autofs-5.0.2-autofs-5-typo.patch +Patch31: autofs-5.0.2-swallow-null-macro.patch +Patch32: autofs-5.0.2-remove-unused-export-validation-code.patch +Patch33: autofs-5.0.2-dynamic-logging.patch +Patch34: autofs-5.0.2-fix-recursive-loopback-mounts.patch +Patch35: autofs-5.0.2-log-map-reload.patch +Patch36: autofs-5.0.2-dynamic-logging-fixes.patch +Patch37: autofs-5.0.2-basedn-with-spaces.patch +Patch38: autofs-5.0.2-check-mtab-updated.patch +Patch39: autofs-5.0.2-check-auto_master.patch +Patch40: autofs-5.0.2-negative-timeout-update.patch +Patch41: autofs-5.0.2-large-groups.patch +Patch42: autofs-5.0.2-report-failed-lookups.patch +Patch43: autofs-5.0.2-dynamic-logging-non-sasl.patch +Patch44: autofs-5.0.2-singleton-host-list.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs Conflicts: kernel < 2.6.17 @@ -93,6 +117,30 @@ echo %{version}-%{release} > .version %patch18 -p1 %patch19 -p1 %patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 +%patch43 -p1 +%patch44 -p1 %build #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir} @@ -145,6 +193,30 @@ fi %{_libdir}/autofs/ %changelog +* Tue Nov 20 2007 Ian Kent - 5.0.2-17 +- fix schema selection in LDAP schema discovery. +- check for "*" when looking up wildcard in LDAP. +- fix couple of edge case parse fails of timeout option. +- add SEARCH_BASE configuration option. +- add random selection as a master map entry option. +- re-read config on HUP signal. +- add LDAP_URI, LDAP_TIMEOUT and LDAP_NETWORK_TIMEOUT configuration options. +- fix deadlock in submount mount module. +- fix lack of ferror() checking when reading files. +- fix typo in autofs(5) man page. +- fix map entry expansion when undefined macro is present. +- remove unused export validation code. +- add dynamic logging (adapted from v4 patch from Jeff Moyer). +- fix recursive loopback mounts (Matthias Koenig). +- add map re-load to verbose logging. +- fix handling of LDAP base dns with spaces. +- handle MTAB_NOTUPDATED status return from mount. +- when default master map, auto.master, is used also check for auto_master. +- update negative mount timeout handling. +- fix large group handling (Ryan Thomas). +- fix for dynamic logging breaking non-sasl build (Guillaume Rousse). +- eliminate NULL proc ping for singleton host or local mounts. + * Mon Sep 24 2007 Ian Kent - 5.0.2-16 - add descriptive comments to config about LDAP schema discovery. - work around segfault at exit caused by libxml2.