diff --git a/CHANGELOG b/CHANGELOG
index 3baff69..c0c6dd6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,8 @@
 - cthon fix expire of various forms of nested mounts.
 - cthon fix some shutdown races.
 - cthon corrections for above patch and fix shutdown expire.
+- cthon fix expire of wildcard and program mounts broken by above
+  patches.
 
 13/7/2006 autofs-5.0.1 rc1
 --------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index ff05ae2..9c3f1e9 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -375,7 +375,7 @@ int umount_multi(struct autofs_point *ap
 
 	is_autofs_fs = fs.f_type == AUTOFS_SUPER_MAGIC ? 1 : 0;
 
-	me = lookup_source_mapent(ap, path);
+	me = lookup_source_mapent(ap, path, LKP_DISTINCT);
 	if (!me) {
 		char *ind_key;
 
@@ -383,7 +383,7 @@ int umount_multi(struct autofs_point *ap
 		if (ind_key)
 			ind_key++;
 
-		me = lookup_source_mapent(ap, ind_key);
+		me = lookup_source_mapent(ap, ind_key, LKP_DISTINCT);
 		if (!me) {
 			warn(ap->logopt, "map entry not found for %s", path);
 			return 0;
diff --git a/daemon/direct.c b/daemon/direct.c
index c155617..974a50e 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -721,10 +721,10 @@ out_err:
 	return -1;
 }
 
-static int expire_direct(int ioctlfd, const char *path, unsigned int when, int count, unsigned int logopt)
+static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt)
 {
 	char *estr, buf[MAX_ERR_BUF];
-	int ret, retries = count;
+	int ret, retries = EXPIRE_RETRIES;
 
 	while (retries--) {
 		struct timespec tm = {0, 100000000};
@@ -733,7 +733,7 @@ static int expire_direct(int ioctlfd, co
 		ret = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &busy);
 		if (ret == -1) {
 			/* Mount has gone away */
-			if (errno == EBADF)
+			if (errno == EBADF || errno == EINVAL)
 				return 1;
 
 			estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -751,7 +751,7 @@ static int expire_direct(int ioctlfd, co
 		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when);
 		if (ret == -1) {
 			/* Mount has gone away */
-			if (errno == EBADF)
+			if (errno == EBADF || errno == EINVAL)
 				return 1;
 
 			/* Need to wait for the kernel ? */
@@ -766,11 +766,9 @@ static int expire_direct(int ioctlfd, co
 
 void *expire_proc_direct(void *arg)
 {
-	struct map_source *map;
 	struct mnt_list *mnts, *next;
 	struct expire_args *ea;
 	struct autofs_point *ap;
-	struct mapent_cache *mc = NULL;
 	struct mapent *me = NULL;
 	unsigned int now;
 	int ioctlfd = -1;
@@ -819,35 +817,22 @@ void *expire_proc_direct(void *arg)
 		 * All direct mounts must be present in the map
 		 * entry cache.
 		 */
-		master_source_readlock(ap->entry);
-		map = ap->entry->first;
-		while (map) {
-			mc = map->mc;
-			cache_readlock(mc);
-			me = cache_lookup_distinct(mc, next->path);
-			if (me)
-				break;
-			cache_unlock(mc);
-			map = map->next;
-		}
-		master_source_unlock(ap->entry);
-
+		me = lookup_source_mapent(ap, next->path, LKP_DISTINCT);
 		if (!me)
 			continue;
 
 		if (me->ioctlfd >= 0) {
 			/* Real mounts have an open ioctl fd */
 			ioctlfd = me->ioctlfd;
-			cache_unlock(mc);
+			cache_unlock(me->source->mc);
 		} else {
-			cache_unlock(mc);
+			cache_unlock(me->source->mc);
 			continue;
 		}
 
 		debug(ap->logopt, "send expire to trigger %s", next->path);
 
-		ret = expire_direct(ioctlfd, next->path,
-				    now, EXPIRE_RETRIES, ap->logopt);
+		ret = expire_direct(ioctlfd, next->path, now, ap->logopt);
 		if (!ret) {
 			debug(ap->logopt,
 			     "failed to expire mount %s", next->path);
@@ -926,7 +911,7 @@ static void *do_expire_direct(void *arg)
 		send_fail(mt->ioctlfd, mt->wait_queue_token);
 	else {
 		struct mapent *me;
-		me = lookup_source_mapent(ap, mt->name);
+		me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT);
 		me->ioctlfd = -1;
 		cache_unlock(me->source->mc);
 		send_ready(mt->ioctlfd, mt->wait_queue_token);
@@ -1225,7 +1210,7 @@ cont:
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 	if (status) {
 		struct mapent *me;
-		me = lookup_source_mapent(ap, mt->name);
+		me = lookup_source_mapent(ap, mt->name, LKP_DISTINCT);
 		me->ioctlfd = mt->ioctlfd;
 		cache_unlock(me->source->mc);
 		send_ready(mt->ioctlfd, mt->wait_queue_token);
diff --git a/daemon/indirect.c b/daemon/indirect.c
index af84629..b57bbd1 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -294,7 +294,7 @@ int umount_autofs_indirect(struct autofs
 
 	/* If we are trying to shutdown make sure we can umount */
 	rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret);
-	if (rv) {
+	if (rv == -1) {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		error(ap->logopt, "ioctl failed: %s", estr);
 		return 1;
@@ -364,7 +364,7 @@ force_umount:
 	return rv;
 }
 
-static int expire_indirect(int ioctlfd, const char *path, unsigned int when, int count, unsigned int logopt)
+static int expire_indirect(int ioctlfd, const char *path, unsigned int when, unsigned int count, unsigned int logopt)
 {
 	char *estr, buf[MAX_ERR_BUF];
 	int ret, retries = count;
@@ -376,7 +376,7 @@ static int expire_indirect(int ioctlfd, 
 		ret = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &busy);
 		if (ret == -1) {
 			/* Mount has gone away */
-			if (errno == EBADF)
+			if (errno == EBADF || errno == EINVAL)
 				return 1;
 
 			estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -394,7 +394,7 @@ static int expire_indirect(int ioctlfd, 
 		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when);
 		if (ret == -1) {
 			/* Mount has gone away */
-			if (errno == EBADF)
+			if (errno == EBADF || errno == EINVAL)
 				return 1;
 
 			/* Need to wait for the kernel ? */
@@ -410,9 +410,7 @@ static int expire_indirect(int ioctlfd, 
 
 void *expire_proc_indirect(void *arg)
 {
-	struct map_source *map;
 	struct autofs_point *ap;
-	struct mapent_cache *mc = NULL;
 	struct mapent *me = NULL;
 	struct mnt_list *mnts, *next;
 	struct expire_args *ea;
@@ -420,6 +418,7 @@ void *expire_proc_indirect(void *arg)
 	int offsets, submnts, count;
 	int ioctlfd, limit;
 	int status, ret;
+	unsigned int retries = EXPIRE_RETRIES;
 
 	ea = (struct expire_args *) arg;
 
@@ -473,36 +472,23 @@ void *expire_proc_indirect(void *arg)
 		 * Otherwise it's a top level indirect mount (possibly
 		 * with offsets in it) and we use the usual ioctlfd.
 		 */
-		master_source_readlock(ap->entry);
-		map = ap->entry->first;
-		while (map) {
-			mc = map->mc;
-			cache_readlock(mc);
-			me = cache_lookup_distinct(mc, next->path);
-			if (!me)
-				me = cache_lookup_distinct(mc, ind_key);
-			if (me)
-				break;
-			cache_unlock(mc);
-			map = map->next;
-		}
-		master_source_unlock(ap->entry);
-
+		me = lookup_source_mapent(ap, next->path, LKP_DISTINCT);
+		if (!me && ind_key)
+			lookup_source_mapent(ap, ind_key, LKP_NORMAL);
 		if (!me)
 			continue;
 
 		if (*me->key == '/') {
 			ioctlfd = me->ioctlfd;
-			cache_unlock(mc);
+			cache_unlock(me->source->mc);
 		} else {
 			ioctlfd = ap->ioctlfd;
-			cache_unlock(mc);
+			cache_unlock(me->source->mc);
 		}
 
 		debug(ap->logopt, "expire %s", next->path);
 
-		ret = expire_indirect(ioctlfd, next->path,
-				      now, EXPIRE_RETRIES, ap->logopt);
+		ret = expire_indirect(ioctlfd, next->path, now, retries, ap->logopt);
 		if (!ret) {
 			debug(ap->logopt,
 			      "failed to expire mount %s", next->path);
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 6942121..87be647 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -931,15 +931,15 @@ int lookup_prune_cache(struct autofs_poi
 				free(path);
 				goto next;
 			}
-			status = CHE_FAIL;
-			if (this->ioctlfd == -1)
-				status = cache_delete(mc, key);
-			cache_unlock(mc);
 
-			if (status != CHE_FAIL) {
-				if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS))
+			if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) {
+				status = CHE_FAIL;
+				if (this->ioctlfd == -1)
+					status = cache_delete(mc, key);
+				if (status != CHE_FAIL)
 					rmdir_path(ap, path);
 			}
+			cache_unlock(mc);
 
 			if (!next_key) {
 				free(key);
@@ -965,7 +965,7 @@ next:
 }
 
 /* Return with cache readlock held */
-struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key)
+struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type)
 {
 	struct master_mapent *entry = ap->entry;
 	struct map_source *map;
@@ -978,7 +978,10 @@ struct mapent *lookup_source_mapent(stru
 	while (map) {
 		mc = map->mc;
 		cache_readlock(mc);
-		me = cache_lookup_distinct(mc, key);
+		if (type == LKP_DISTINCT)
+			me = cache_lookup_distinct(mc, key);
+		else
+			me = cache_lookup_distinct(mc, key);
 		if (me)
 			break;
 		cache_unlock(mc);
diff --git a/include/automount.h b/include/automount.h
index 800e7b0..f7345c5 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -95,8 +95,8 @@ #define LKP_WILD	0x0100
 #define LKP_LOOKUP	0x0200
 #define LKP_GHOST	0x0400
 #define LKP_REREAD	0x0800
-#define LKP_EMPTY	0x1000
-#define LKP_ERR_FORMAT	0x2000
+#define LKP_NORMAL	0x1000
+#define LKP_DISTINCT	0x2000
 #define LKP_ERR_MOUNT	0x4000
 #define LKP_NOTSUP	0x8000
 
@@ -228,7 +228,7 @@ int lookup_ghost(struct autofs_point *ap
 int lookup_nss_mount(struct autofs_point *ap, const char *name, int name_len);
 void lookup_close_lookup(struct autofs_point *ap);
 int lookup_prune_cache(struct autofs_point *ap, time_t age);
-struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key);
+struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type);
 int lookup_source_close_ioctlfd(struct autofs_point *ap, const char *key);
 
 #ifdef MODULE_LOOKUP
diff --git a/modules/lookup_hesiod.c b/modules/lookup_hesiod.c
index 1664afc..f30e9b2 100644
--- a/modules/lookup_hesiod.c
+++ b/modules/lookup_hesiod.c
@@ -100,15 +100,20 @@ int lookup_read_map(struct autofs_point 
  */
 int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
 {
+	struct map_source *source;
+	struct mapent_cache *mc;
 	char **hes_result;
 	struct lookup_context *ctxt = (struct lookup_context *) context;
 	int status, rv;
 	char **record, *best_record = NULL, *p;
 	int priority, lowest_priority = INT_MAX;	
 
+	source = ap->entry->current;
 	ap->entry->current = NULL;
 	master_source_current_signal(ap->entry);
 
+	mc = source->mc;
+
 	debug(ap->logopt,
 	      MODPREFIX "looking up root=\"%s\", name=\"%s\"",
 	      ap->path, name);
@@ -148,6 +153,12 @@ int lookup_mount(struct autofs_point *ap
 	    }
 	}
 
+	cache_writelock(mc);
+	rv = cache_update(mc, source, name, best_record, time(NULL));
+	cache_unlock(mc);
+	if (rv == CHE_FAIL)
+		return NSS_STATUS_UNAVAIL;
+
 	debug(ap->logopt,
 	      MODPREFIX "lookup for \"%s\" gave \"%s\"",
 	      name, best_record);
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
index c589d05..0076596 100644
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -346,6 +346,12 @@ int lookup_mount(struct autofs_point *ap
 		goto out_free;
 	}
 
+	cache_writelock(mc);
+	ret = cache_update(mc, source, name, mapent, time(NULL));
+	cache_unlock(mc);
+	if (ret == CHE_FAIL)
+		return NSS_STATUS_UNAVAIL;
+
 	debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent);
 
 	master_source_current_wait(ap->entry);
diff --git a/modules/lookup_userhome.c b/modules/lookup_userhome.c
index cc0b4fa..efcab0b 100644
--- a/modules/lookup_userhome.c
+++ b/modules/lookup_userhome.c
@@ -49,11 +49,18 @@ int lookup_read_map(struct autofs_point 
 
 int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
 {
+	struct map_source *source;
+	struct mapent_cache *mc;
 	struct passwd *pw;
 	char buf[MAX_ERR_BUF];
+	int ret;
 
+	source = ap->entry->current;
 	ap->entry->current = NULL;
 	master_source_current_signal(ap->entry);
+
+	mc = source->mc;
+
 	debug(ap->logopt, MODPREFIX "looking up %s", name);
 
 	/* Get the equivalent username */
@@ -70,12 +77,23 @@ int lookup_mount(struct autofs_point *ap
 		return NSS_STATUS_UNAVAIL;
 	}
 
+	cache_writelock(mc);
+	ret = cache_update(mc, source, name, NULL, time(NULL));
+	cache_unlock(mc);
+
+	if (ret == CHE_FAIL) {
+		ret = chdir("/");
+		return NSS_STATUS_UNAVAIL;
+	}
+
 	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);
 		return NSS_STATUS_UNAVAIL;
 	}
 
+	ret = chdir("/");
+
 	return NSS_STATUS_SUCCESS;
 }
 
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index 0f2c3ab..25d2eda 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -1215,7 +1215,7 @@ int parse_mount(struct autofs_point *ap,
 		if (ap->submount)
 			oap = ap->parent;
 
-		me = lookup_source_mapent(oap, name);
+		me = lookup_source_mapent(oap, name, LKP_DISTINCT);
 		if (me) {
 			char *m_key;
 			int start;