summaryrefslogtreecommitdiff
path: root/lib/stdopen.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2005-08-24 15:25:29 +0000
committerJim Meyering <jim@meyering.net>2005-08-24 15:25:29 +0000
commitf80cc28124928d6f7ae0c535f8f40598e20cefb2 (patch)
tree61ace69212c25ce0f48c7aed7d557f4b8dae9a9d /lib/stdopen.c
parent55fb58f426465e2348150cf373fa6a5a592e8d8e (diff)
downloadcoreutils-f80cc28124928d6f7ae0c535f8f40598e20cefb2.tar.xz
(stdopen): Revert to iterating over descriptors, but
rather than using fstat, use fcntl with its F_GETFD flag, which is more efficient. Unlike the 2-syscall dup-close approach, this one doesn't apply any unnecessary pressure on the file descriptor pool -- thus there is one fewer way to fail.
Diffstat (limited to 'lib/stdopen.c')
-rw-r--r--lib/stdopen.c52
1 files changed, 22 insertions, 30 deletions
diff --git a/lib/stdopen.c b/lib/stdopen.c
index 00914307d..c9d674fb6 100644
--- a/lib/stdopen.c
+++ b/lib/stdopen.c
@@ -30,18 +30,6 @@
#include <unistd.h>
#include <errno.h>
-#ifndef STDIN_FILENO
-# define STDIN_FILENO 0
-#endif
-
-#ifndef STDOUT_FILENO
-# define STDOUT_FILENO 1
-#endif
-
-#ifndef STDERR_FILENO
-# define STDERR_FILENO 2
-#endif
-
/* Try to ensure that each of the standard file numbers (0, 1, 2)
is in use. Without this, each application would have to guard
every call to open, dup, fopen, etc. with tests to ensure they
@@ -51,25 +39,29 @@
bool
stdopen (void)
{
- int fd = dup (STDIN_FILENO);
-
- if (0 <= fd)
- close (fd);
- else if (errno == EBADF)
- fd = open ("/dev/null", O_WRONLY);
- else
- return false;
+ int fd;
+ bool ok = true;
- if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+ for (fd = 0; fd <= 2; fd++)
{
- fd = open ("/dev/null", O_RDONLY);
- if (fd == STDOUT_FILENO)
- fd = dup (fd);
- if (fd < 0)
- return false;
-
- if (STDERR_FILENO < fd)
- close (fd);
+ if (fcntl (fd, F_GETFD) < 0)
+ {
+ if (errno != EBADF)
+ ok = false;
+ else
+ {
+ static const int contrary_mode[]
+ = { O_WRONLY, O_RDONLY, O_RDONLY };
+ int new_fd = open ("/dev/null", contrary_mode[fd]);
+ if (new_fd != fd)
+ {
+ if (0 <= new_fd)
+ close (new_fd);
+ ok = false;
+ }
+ }
+ }
}
- return true;
+
+ return ok;
}