- (djm) [acconfig.h configure.ac openbsd-compat/Makefile.in
   openbsd-compat/bsd-closefrom.c openbsd-compat/bsd-misc.c
   openbsd-compat/bsd-misc.h openbsd-compat/openbsd-compat.h] Use smarter
   closefrom() replacement from sudo; ok dtucker@
diff --git a/ChangeLog b/ChangeLog
index d1936ac..841c9e6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
 20040815
  - (dtucker) [Makefile.in ssh-keysign.c ssh.c] Use permanently_set_uid() since
    it does the right thing on all platforms.  ok djm@
+ - (djm) [acconfig.h configure.ac openbsd-compat/Makefile.in 
+   openbsd-compat/bsd-closefrom.c openbsd-compat/bsd-misc.c 
+   openbsd-compat/bsd-misc.h openbsd-compat/openbsd-compat.h] Use smarter 
+   closefrom() replacement from sudo; ok dtucker@
 
 20040814
  - (dtucker) [auth-krb5.c gss-serv-krb5.c openbsd-compat/xmmap.c]
@@ -1635,4 +1639,4 @@
    - (djm) Trim deprecated options from INSTALL. Mention UsePAM
    - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
 
-$Id: ChangeLog,v 1.3509 2004/08/15 07:23:34 dtucker Exp $
+$Id: ChangeLog,v 1.3510 2004/08/15 08:40:59 djm Exp $
diff --git a/acconfig.h b/acconfig.h
index 4c65582..bb06963 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -1,4 +1,4 @@
-/* $Id: acconfig.h,v 1.178 2004/06/28 06:01:20 dtucker Exp $ */
+/* $Id: acconfig.h,v 1.179 2004/08/15 08:40:59 djm Exp $ */
 
 /*
  * Copyright (c) 1999-2003 Damien Miller.  All rights reserved.
@@ -454,6 +454,9 @@
 /* Define if your resolver libs need this for getrrsetbyname */
 #undef BIND_8_COMPAT
 
+/* Define if you have /proc/$pid/fd */
+#undef HAVE_PROC_PID
+
 @BOTTOM@
 
 /* ******************* Shouldn't need to edit below this line ************** */
diff --git a/configure.ac b/configure.ac
index 1579c8d..6954fb4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-# $Id: configure.ac,v 1.224 2004/07/19 17:19:27 tim Exp $
+# $Id: configure.ac,v 1.225 2004/08/15 08:40:59 djm Exp $
 #
 # Copyright (c) 1999-2004 Damien Miller
 #
@@ -517,16 +517,16 @@
 )
 
 # Checks for header files.
-AC_CHECK_HEADERS(bstring.h crypt.h endian.h features.h floatingpoint.h \
-	getopt.h glob.h ia.h lastlog.h limits.h login.h \
-	login_cap.h maillock.h netdb.h netgroup.h \
+AC_CHECK_HEADERS(bstring.h crypt.h dirent.h endian.h features.h \
+	floatingpoint.h getopt.h glob.h ia.h lastlog.h limits.h login.h \
+	login_cap.h maillock.h ndir.h netdb.h netgroup.h \
 	netinet/in_systm.h pam/pam_appl.h paths.h pty.h readpassphrase.h \
 	rpc/types.h security/pam_appl.h shadow.h stddef.h stdint.h \
-	strings.h sys/strtio.h sys/audit.h sys/bitypes.h sys/bsdtty.h \
-	sys/cdefs.h sys/mman.h sys/prctl.h sys/pstat.h sys/ptms.h \
-	sys/select.h sys/stat.h sys/stream.h sys/stropts.h \
-	sys/sysmacros.h sys/time.h sys/timers.h sys/un.h time.h tmpdir.h \
-	ttyent.h usersec.h util.h utime.h utmp.h utmpx.h vis.h)
+	strings.h sys/dir.h sys/strtio.h sys/audit.h sys/bitypes.h \
+	sys/bsdtty.h sys/cdefs.h sys/mman.h sys/ndir.h sys/prctl.h \
+	sys/pstat.h sys/ptms.h sys/select.h sys/stat.h sys/stream.h \
+	sys/stropts.h sys/sysmacros.h sys/time.h sys/timers.h sys/un.h \
+	time.h tmpdir.h ttyent.h usersec.h util.h utime.h utmp.h utmpx.h vis.h)
 
 # Checks for libraries.
 AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match))
@@ -731,6 +731,14 @@
 	]
 )
 
+AC_MSG_CHECKING([for /proc/pid/fd directory])
+if test -d "/proc/$$/fd" ; then
+	AC_DEFINE(HAVE_PROC_PID)
+	AC_MSG_RESULT(yes)
+else
+	AC_MSG_RESULT(no)
+fi
+
 # Check whether user wants S/Key support
 SKEY_MSG="no"
 AC_ARG_WITH(skey,
@@ -833,8 +841,8 @@
 dnl    Checks for library functions. Please keep in alphabetical order
 AC_CHECK_FUNCS(\
 	arc4random __b64_ntop b64_ntop __b64_pton b64_pton bcopy \
-	bindresvport_sa clock closefrom fchmod fchown freeaddrinfo futimes \
-	getaddrinfo getcwd getgrouplist getnameinfo getopt \
+	bindresvport_sa clock closefrom dirfd fchmod fchown freeaddrinfo \
+	futimes getaddrinfo getcwd getgrouplist getnameinfo getopt \
 	getpeereid _getpty getrlimit getttyent glob inet_aton \
 	inet_ntoa inet_ntop innetgr login_getcapbool md5_crypt memmove \
 	mkdtemp mmap ngetaddrinfo nsleep ogetaddrinfo openlog_r openpty \
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index 5de20ab..0f34f22 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.30 2004/01/21 06:07:23 djm Exp $
+# $Id: Makefile.in,v 1.31 2004/08/15 08:41:00 djm Exp $
 
 sysconfdir=@sysconfdir@
 piddir=@piddir@
@@ -18,7 +18,7 @@
 
 OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtoul.o vis.o
 
-COMPAT=bsd-arc4random.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o xmmap.o xcrypt.o
+COMPAT=bsd-arc4random.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o xmmap.o xcrypt.o
 
 PORTS=port-irix.o port-aix.o
 
diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c
new file mode 100644
index 0000000..61a9fa3
--- /dev/null
+++ b/openbsd-compat/bsd-closefrom.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifndef HAVE_CLOSEFROM
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stddef.h>
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+#ifndef OPEN_MAX
+# define OPEN_MAX	256
+#endif
+
+RCSID("$Id: bsd-closefrom.c,v 1.1 2004/08/15 08:41:00 djm Exp $");
+
+#ifndef lint
+static const char sudorcsid[] = "$Sudo: closefrom.c,v 1.6 2004/06/01 20:51:56 millert Exp $";
+#endif /* lint */
+
+/*
+ * Close all file descriptors greater than or equal to lowfd.
+ */
+void
+closefrom(int lowfd)
+{
+    long fd, maxfd;
+#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+    char fdpath[PATH_MAX], *endp;
+    struct dirent *dent;
+    DIR *dirp;
+    int len;
+
+    /* Check for a /proc/$$/fd directory. */
+    len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
+    if (len != -1 && len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
+	while ((dent = readdir(dirp)) != NULL) {
+	    fd = strtol(dent->d_name, &endp, 10);
+	    if (dent->d_name != endp && *endp == '\0' &&
+		fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
+		(void) close((int) fd);
+	}
+	(void) closedir(dirp);
+    } else
+#endif
+    {
+	/*
+	 * Fall back on sysconf() or getdtablesize().  We avoid checking
+	 * resource limits since it is possible to open a file descriptor
+	 * and then drop the rlimit such that it is below the open fd.
+	 */
+#ifdef HAVE_SYSCONF
+	maxfd = sysconf(_SC_OPEN_MAX);
+#else
+	maxfd = getdtablesize();
+#endif /* HAVE_SYSCONF */
+	if (maxfd < 0)
+	    maxfd = OPEN_MAX;
+
+	for (fd = lowfd; fd < maxfd; fd++)
+	    (void) close((int) fd);
+    }
+}
+
+#endif /* HAVE_CLOSEFROM */
+
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c
index 3a30b6e..1b276b4 100644
--- a/openbsd-compat/bsd-misc.c
+++ b/openbsd-compat/bsd-misc.c
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
  *
@@ -17,7 +18,7 @@
 #include "includes.h"
 #include "xmalloc.h"
 
-RCSID("$Id: bsd-misc.c,v 1.24 2004/08/13 08:37:21 dtucker Exp $");
+RCSID("$Id: bsd-misc.c,v 1.25 2004/08/15 08:41:00 djm Exp $");
 
 #ifndef HAVE___PROGNAME
 char *__progname;
@@ -196,22 +197,6 @@
 }
 #endif /* HAVE_TCSENDBREAK */
 
-#ifndef HAVE_CLOSEFROM
-int
-closefrom(int fd)
-{
-	int i, result = 0, err = 0;
-
-	for (i = fd; i < 128; i++)
-		if (close(i) != 0) {
-			err = errno;
-			result = -1;
-		}
-	errno = err;
-	return result;
-}
-#endif /* HAVE_CLOSEFROM */
-
 mysig_t
 mysignal(int sig, mysig_t act)
 {
diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h
index 7027815..33a1d70 100644
--- a/openbsd-compat/bsd-misc.h
+++ b/openbsd-compat/bsd-misc.h
@@ -1,4 +1,4 @@
-/* $Id: bsd-misc.h,v 1.16 2004/06/25 04:03:34 dtucker Exp $ */
+/* $Id: bsd-misc.h,v 1.17 2004/08/15 08:41:00 djm Exp $ */
 
 /*
  * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
@@ -93,10 +93,6 @@
 void unsetenv(const char *);
 #endif
 
-#ifndef HAVE_CLOSEFROM
-int closefrom(int);
-#endif
-
 /* wrapper for signal interface */
 typedef void (*mysig_t)(int);
 mysig_t mysignal(int sig, mysig_t act);
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h
index 6be1bcd..89d1454 100644
--- a/openbsd-compat/openbsd-compat.h
+++ b/openbsd-compat/openbsd-compat.h
@@ -1,4 +1,4 @@
-/* $Id: openbsd-compat.h,v 1.25 2004/01/21 06:07:23 djm Exp $ */
+/* $Id: openbsd-compat.h,v 1.26 2004/08/15 08:41:00 djm Exp $ */
 
 /*
  * Copyright (c) 1999-2003 Damien Miller.  All rights reserved.
@@ -48,6 +48,10 @@
 int bindresvport_sa(int sd, struct sockaddr *sa);
 #endif
 
+#ifndef HAVE_CLOSEFROM
+void closefrom(int);
+#endif
+
 #ifndef HAVE_GETCWD
 char *getcwd(char *pt, size_t size);
 #endif