diff --git a/COPYING b/COPYING index e275e4b..a69e7b6 100644 --- a/COPYING +++ b/COPYING @@ -174,6 +174,33 @@ -- + Copyright (c) 2009 Advanced Computing Technologies LLC + Written by: John H. Baldwin + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + -- + Copyright © 1998, M. Warner Losh All rights reserved. @@ -349,7 +376,8 @@ -- - Copyright © 2000-2002, 2007 Todd C. Miller + Copyright © 2000-2002, 2004-2005, 2007, 2010 + Todd C. Miller Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/configure.ac b/configure.ac index ab7f96a..ce697a3 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ AC_PROG_LN_S # Checks for libraries. # Checks for header files. +AC_CHECK_HEADERS([sys/ndir.h sys/dir.h dir.h dirent.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T @@ -36,6 +37,13 @@ AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T +AC_CHECK_DECL([F_CLOSEM], + [AC_DEFINE([HAVE_FCNTL_CLOSEM], [1], + [Define to 1 if you have fcntl(F_CLOSEM)])], + [], + [#include + #include ]) + # Checks for library functions. AC_MSG_CHECKING([for __progname]) AC_LINK_IFELSE( @@ -46,7 +54,7 @@ AC_LINK_IFELSE( AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) -AC_CHECK_FUNCS([getexecname]) +AC_CHECK_FUNCS([dirfd getexecname sysconf]) AC_CONFIG_FILES([ Makefile diff --git a/include/bsd/unistd.h b/include/bsd/unistd.h index b6f070a..713a8d7 100644 --- a/include/bsd/unistd.h +++ b/include/bsd/unistd.h @@ -54,6 +54,8 @@ int bsd_getopt(int argc, char * const argv[], const char *shortopts); mode_t getmode(const void *set, mode_t mode); void *setmode(const char *mode_str); +void closefrom(int lowfd); + void setproctitle(const char *fmt, ...); int getpeereid(int s, uid_t *euid, gid_t *egid); diff --git a/man/Makefile.am b/man/Makefile.am index 129949a..8188488 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -19,6 +19,7 @@ dist_man_MANS = \ arc4random_buf.3 \ arc4random_stir.3 \ arc4random_uniform.3 \ + closefrom.3 \ dehumanize_number.3 \ fgetln.3 \ flopen.3 \ diff --git a/man/closefrom.3 b/man/closefrom.3 new file mode 100644 index 0000000..472c985 --- /dev/null +++ b/man/closefrom.3 @@ -0,0 +1,54 @@ +.\" Copyright (c) 2009 Advanced Computing Technologies LLC +.\" Written by: John H. Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd June 12, 2009 +.Dt CLOSEFROM 3 +.Os +.Sh NAME +.Nm closefrom +.Nd delete open file descriptors +.Sh LIBRARY +.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd) +.Lb libbsd +.Sh SYNOPSIS +.In bsd/unistd.h +.Ft void +.Fn closefrom "int lowfd" +.Sh DESCRIPTION +The +.Fn closefrom +system call deletes all open file descriptors greater than or equal to +.Fa lowfd +from the per-process object reference table. +Any errors encountered while closing file descriptors are ignored. +.Sh SEE ALSO +.Xr close 2 +.Sh HISTORY +The +.Fn closefrom +function first appeared in +.Fx 8.0 . diff --git a/src/Makefile.am b/src/Makefile.am index 2713e8b..98fae97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,7 @@ libbsd_la_LDFLAGS = \ libbsd_la_SOURCES = \ arc4random.c \ bsd_getopt.c \ + closefrom.c \ dehumanize_number.c \ err.c \ fgetln.c \ diff --git a/src/closefrom.c b/src/closefrom.c new file mode 100644 index 0000000..b7e2ad5 --- /dev/null +++ b/src/closefrom.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2004-2005, 2007, 2010 + * Todd C. Miller + * + * 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 + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#include +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + +#ifndef OPEN_MAX +# define OPEN_MAX 256 +#endif + +#ifndef HAVE_FCNTL_CLOSEM +# ifndef HAVE_DIRFD +# define closefrom_fallback closefrom +# endif +#endif + +/* + * Close all file descriptors greater than or equal to lowfd. + * This is the expensive (ballback) method. + */ +void +closefrom_fallback(int lowfd) +{ + long fd, maxfd; + + /* + * 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); +} + +/* + * Close all file descriptors greater than or equal to lowfd. + * We try the fast way first, falling back on the slow method. + */ +#ifdef HAVE_FCNTL_CLOSEM +void +closefrom(int lowfd) +{ + if (fcntl(lowfd, F_CLOSEM, 0) == -1) + closefrom_fallback(lowfd); +} +#else +# ifdef HAVE_DIRFD +void +closefrom(int lowfd) +{ + struct dirent *dent; + DIR *dirp; + char *endp; + long fd; + + /* Use /proc/self/fd directory if it exists. */ + dirp = opendir("/proc/self/fd"); + if (dirp != NULL) { + 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 + closefrom_fallback(lowfd); +} +#endif /* HAVE_DIRFD */ +#endif /* HAVE_FCNTL_CLOSEM */ diff --git a/src/libbsd.map b/src/libbsd.map index 39e6ea9..1fa4619 100644 --- a/src/libbsd.map +++ b/src/libbsd.map @@ -89,3 +89,7 @@ LIBBSD_0.3 { fpurge; } LIBBSD_0.2; + +LIBBSD_0.4 { + closefrom; +} LIBBSD_0.3;