summaryrefslogtreecommitdiffstats
path: root/gl/lib/stdopen.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/lib/stdopen.c')
-rw-r--r--gl/lib/stdopen.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/gl/lib/stdopen.c b/gl/lib/stdopen.c
new file mode 100644
index 0000000..841e410
--- /dev/null
+++ b/gl/lib/stdopen.c
@@ -0,0 +1,66 @@
+/* stdopen.c - ensure that the three standard file descriptors are in use
+
+ Copyright (C) 2005-2006, 2019-2022 Free Software Foundation, Inc.
+
+ 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, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert and Jim Meyering. */
+
+#include <config.h>
+
+#include "stdopen.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Try to ensure that all of the standard file numbers (0, 1, 2)
+ are in use. Without this, each application would have to guard
+ every call to open, dup, fopen, etc. with tests to ensure they
+ don't use one of the special file numbers when opening a file.
+ Return zero if successful, an errno value if at least one of
+ the file descriptors is initially closed and could not be opened. */
+
+int
+stdopen (void)
+{
+ int fd;
+ for (fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++)
+ {
+ if (fcntl (fd, F_GETFD) < 0)
+ {
+ /* Open /dev/null with the contrary mode so that the typical
+ read (stdin) or write (stdout, stderr) operation will fail.
+ With descriptor 0, we can do even better on systems that
+ have /dev/full, by opening that write-only instead of
+ /dev/null. The only drawback is that a write-provoked
+ failure comes with a misleading errno value, ENOSPC. */
+ int mode = fd == STDIN_FILENO ? O_WRONLY : O_RDONLY;
+ int full_fd = fd == STDIN_FILENO ? open ("/dev/full", mode) : -1;
+ int new_fd = full_fd < 0 ? open ("/dev/null", mode) : full_fd;
+ if (new_fd < 0)
+ return errno;
+ if (STDERR_FILENO < new_fd)
+ {
+ /* 0, 1, and 2 are already open somehow.
+ Our is not to reason why. */
+ close (new_fd);
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}