--- autofs-4.1.3/modules/lookup_nssldap.c	1970-01-01 01:00:00.000000000 +0100
+++ autofs-4.1.3/modules/lookup_nssldap.c	2005-06-28 15:13:49.000000000 +0200
@@ -0,0 +1,326 @@
+#ident "$Id: autofs-4.1.3-lookup-nssldap.patch,v 1.1 2005/08/08 23:28:37 lukeh Exp $"
+/* ----------------------------------------------------------------------- *
+ *
+ *  lookup_nss.c - module for Linux automountd to access a NSS
+ *		 automount map
+ *
+ *   Copyright 1997 Transmeta Corporation - All Rights Reserved
+ *   Copyright 2001-2003 Ian Kent <raven@themaw.net>
+ *   Copyright 2005 PADL Software Pty Ltd - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <dlfcn.h>
+#include <nss.h>
+
+#define MODULE_LOOKUP
+#include "automount.h"
+
+#define MAPFMT_DEFAULT "sun"
+
+#define NAMESERVICE "ldap"
+
+#define MODPREFIX "lookup(nss" NAMESERVICE "): "
+
+struct lookup_context {
+	char *nsname;
+	char *mapname;
+	struct parse_mod *parse;
+	void *dlhandle;
+	enum nss_status (*setautomntent)(const char *, void **);
+	enum nss_status (*getautomntent_r)(void *, const char **, const char **,
+					   char *, size_t, int *);
+	enum nss_status (*endautomntent)(void **);
+	enum nss_status (*getautomntbyname_r)(void *, const char *,
+					      const char **, const char **,
+					      char *, size_t, int *);
+};
+
+int lookup_version = AUTOFS_LOOKUP_VERSION;
+
+int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context_p)
+{
+	struct lookup_context *context;
+	char buf[1024];
+
+	context = (struct lookup_context *)malloc(sizeof(*context));
+	if (context == NULL) {
+		crit(MODPREFIX "malloc: %m");
+		return 1;
+	}
+	memset(context, 0, sizeof(*context));
+
+	context->nsname = NULL;
+	context->parse = NULL;
+	context->dlhandle = NULL;
+	context->setautomntent = NULL;
+	context->getautomntent_r = NULL;
+	context->endautomntent = NULL;
+
+	if (mapfmt == NULL) {
+		mapfmt = MAPFMT_DEFAULT;
+	}
+
+	if (argc < 1) {
+		crit(MODPREFIX "invalid number of arguments");
+		return 1;
+	}
+
+	asprintf(&context->nsname, "nss%s", NAMESERVICE);
+	if (context->nsname == NULL) {
+		crit(MODPREFIX "strdup: %m");
+		return 1;
+	}
+
+	snprintf(buf, sizeof(buf), "/lib/libnss_%s.so.2", NAMESERVICE);
+
+	context->dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
+	if (context->dlhandle == NULL) {
+		crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
+		return 1;
+	}
+
+	snprintf(buf, sizeof(buf), "_nss_%s_setautomntent", NAMESERVICE);
+	context->setautomntent = dlsym(context->dlhandle, buf);
+	if (context->setautomntent == NULL) {
+		crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
+		return 1;
+	}
+
+	snprintf(buf, sizeof(buf), "_nss_%s_getautomntent_r", NAMESERVICE);
+	context->getautomntent_r = dlsym(context->dlhandle, buf);
+	if (context->getautomntent_r == NULL) {
+		crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
+		return 1;
+	}
+
+	snprintf(buf, sizeof(buf), "_nss_%s_endautomntent", NAMESERVICE);
+	context->endautomntent = dlsym(context->dlhandle, buf);
+	if (context->endautomntent == NULL) {
+		crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
+		return 1;
+	}
+
+	snprintf(buf, sizeof(buf), "_nss_%s_getautomntbyname_r", NAMESERVICE);
+	context->getautomntbyname_r = dlsym(context->dlhandle, buf);
+	if (context->getautomntbyname_r == NULL) {
+		crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
+		return 1;
+	}
+
+	context->mapname = strdup(argv[0]);
+	if (context->mapname == NULL) {
+		crit(MODPREFIX "strdup: %m");
+		return 1;
+	}
+
+	context->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
+	if (context->parse == NULL) {
+		free(context);
+		return 1;
+	}
+
+	*context_p = context;
+	return 0;
+}
+
+static const char *nsserr_string(enum nss_status status)
+{
+	switch (status) {
+	case NSS_STATUS_TRYAGAIN:
+		return "Insufficient buffer space";
+		break;
+	case NSS_STATUS_UNAVAIL:
+		return "Name service unavailable";
+		break;
+	case NSS_STATUS_NOTFOUND:
+		return "Not found";
+		break;
+	case NSS_STATUS_SUCCESS:
+		return "Success";
+		break;
+	default:
+		break;
+	}
+
+	return "Unknown error";
+}
+
+static int read_map(const char *root, struct lookup_context *context)
+{
+	enum nss_status status;
+	void *private = NULL;
+	time_t age = time(NULL);
+	const char *key, *mapent;
+	int nss_errno;
+	char buffer[KEY_MAX_LEN + 1 + MAPENT_MAX_LEN + 1];
+
+	status = (*context->setautomntent)(context->mapname, &private);
+	if (status != NSS_STATUS_SUCCESS) {
+		warn(MODPREFIX "failed to read map %s: %s",
+			context->mapname, nsserr_string(status));
+		return 0;
+	}
+
+	for (;;) {
+		status = (*context->getautomntent_r)(private, &key, &mapent,
+						     buffer, sizeof(buffer),
+						     &nss_errno);
+		if (status != NSS_STATUS_SUCCESS)
+			break;
+
+		cache_update(key, mapent, age);
+	}
+
+	(*context->endautomntent)(&private);
+	
+	cache_clean(root, age);
+	return 1;
+}
+
+int lookup_ghost(const char *root, int ghost, void *context)
+{
+	struct lookup_context *ctxt = (struct lookup_context *)context;
+	struct mapent_cache *me;
+	int status = 1;
+
+	if (!read_map(root, ctxt))
+		return LKP_FAIL;
+
+	status = cache_ghost(root, ghost, ctxt->mapname, ctxt->nsname, ctxt->parse);
+
+	me = cache_lookup_first();
+	if (me == NULL)
+		return LKP_FAIL;
+
+	if (*me->key == '/' && *(root + 1) != '-') {
+		me = cache_partial_match(root);
+		/* me NULL => no entries for this direct mount root or indirect map */
+		if (me == NULL)
+			return LKP_FAIL | LKP_INDIRECT;
+	}
+
+	return status;
+}
+
+int lookup_mount(const char *root, const char *name, int name_len, void *context)
+{
+	struct lookup_context *ctxt = (struct lookup_context *)context;
+	char key[KEY_MAX_LEN + 1];
+	char buffer[KEY_MAX_LEN + 1 + MAPENT_MAX_LEN + 1];
+	const char *canon_key, *mapent;
+	struct mapent_cache *me = NULL;
+	time_t age = time(NULL);
+	enum nss_status status;
+
+	debug(MODPREFIX "looking up %s", name);
+
+	snprintf(key, sizeof(key), "%s/%s", root, name);
+
+	me = cache_lookup(name);
+	if (me == NULL) {
+		me = cache_lookup(key);
+	}
+
+	if (me == NULL) {
+		/* path component, do submount */
+		me = cache_partial_match(key);
+
+		if (me) {
+			snprintf(buffer, sizeof(buffer), "-fstype=autofs %s:%s",
+				 ctxt->nsname, ctxt->mapname);
+			mapent = buffer;
+		}
+	} else {
+		snprintf(buffer, sizeof(buffer), "%s", me->mapent);
+		mapent = buffer;
+	}
+
+	if (me == NULL) {
+		const char *keys[3];
+		int i;
+		int nss_errno;
+		void *private = NULL;
+
+		status = (*ctxt->setautomntent)(ctxt->mapname, &private);
+		if (status != NSS_STATUS_SUCCESS) {
+			warn(MODPREFIX "failed to read map %s: %s", ctxt->mapname, nsserr_string(status));
+			goto out_err;
+		}
+
+		keys[0] = name,
+		keys[1] = key;
+		keys[2] = "*";
+
+		for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
+			status = (*ctxt->getautomntbyname_r)(private, name,
+							     &canon_key, &mapent,
+							     buffer, sizeof(buffer),
+							     &nss_errno);
+			if (status != NSS_STATUS_NOTFOUND)
+				break;
+		}
+
+		(*ctxt->endautomntent)(&private);
+
+		if (status != NSS_STATUS_SUCCESS) {
+			warn(MODPREFIX "failed to read map %s: %s", ctxt->mapname, nsserr_string(status));
+			goto out_err;
+		}
+
+		cache_update(keys[i], mapent, age);
+	}
+
+	debug(MODPREFIX "%s -> %s", name, mapent);
+
+	return ctxt->parse->parse_mount(root, name, name_len, mapent, ctxt->parse->context);
+
+out_err:
+	warn(MODPREFIX "lookup for %s failed: %d", name, status);
+	return 1;
+}
+
+int lookup_done(void *context)
+{
+	struct lookup_context *ctxt = (struct lookup_context *)context;
+	int ret;
+
+	if (ctxt->nsname != NULL) {
+		free(ctxt->nsname);
+		ctxt->nsname = NULL;
+	}
+
+	if (ctxt->mapname != NULL) {
+		free(ctxt->mapname);
+		ctxt->mapname = NULL;
+	}
+
+	ret = close_parse(ctxt->parse);
+
+	if (ctxt->dlhandle != NULL) {
+		dlclose(ctxt->dlhandle);
+		ctxt->dlhandle = NULL;
+	}
+
+	memset(ctxt, 0, sizeof(*ctxt));
+	free(ctxt);
+
+	return ret;
+}
+
--- autofs-4.1.3/modules/lookup_nssldap.c	2005-06-28 15:13:49.000000000 +0200
+++ autofs-4.1.3/modules/lookup_nssldap.c	2005-07-21 11:32:58.000000000 +0200
@@ -16,6 +16,8 @@
  *
  * ----------------------------------------------------------------------- */
 
+#define _GNU_SOURCE
+#include <stdio.h>
 #include <sys/types.h>
 #include <ctype.h>
 #include <string.h>
@@ -88,7 +90,7 @@
 		return 1;
 	}
 
-	snprintf(buf, sizeof(buf), "/lib/libnss_%s.so.2", NAMESERVICE);
+	snprintf(buf, sizeof(buf), "libnss_%s.so.2", NAMESERVICE);
 
 	context->dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
 	if (context->dlhandle == NULL) {
@@ -184,8 +186,11 @@
 						     &nss_errno);
 		if (status != NSS_STATUS_SUCCESS)
 			break;
-
+#ifdef CHE_FAIL
+                cache_update(root, key, mapent, age);
+#else
 		cache_update(key, mapent, age);
+#endif
 	}
 
 	(*context->endautomntent)(&private);
@@ -194,7 +199,7 @@
 	return 1;
 }
 
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
 {
 	struct lookup_context *ctxt = (struct lookup_context *)context;
 	struct mapent_cache *me;
@@ -284,7 +289,11 @@
 			goto out_err;
 		}
 
+#ifdef CHE_FAIL
+                cache_update(root, keys[i], mapent, age);
+#else
 		cache_update(keys[i], mapent, age);
+#endif
 	}
 
 	debug(MODPREFIX "%s -> %s", name, mapent);
--- autofs-4.1.3/modules/Makefile	2004-04-03 09:14:33.000000000 +0200
+++ autofs-4.1.3/modules/Makefile	2005-07-21 11:39:35.000000000 +0200
@@ -7,13 +7,13 @@
 include ../Makefile.rules
 
 SRCS :=	lookup_yp.c  lookup_file.c  lookup_program.c  lookup_userhome.c \
-	lookup_multi.c \
+	lookup_multi.c lookup_nssldap.c \
 	parse_sun.c    \
 	mount_generic.c  mount_nfs.c  mount_afs.c  mount_autofs.c \
 	mount_changer.c  mount_bind.c
 
 MODS :=	lookup_yp.so lookup_file.so lookup_program.so lookup_userhome.so \
-	lookup_multi.so \
+	lookup_multi.so lookup_nssldap.so \
 	parse_sun.so \
 	mount_generic.so mount_nfs.so mount_afs.so mount_autofs.so \
 	mount_changer.so mount_bind.so
