#include "array.h"
#include "env-util.h"
#include "hostpid.h"
+#include "fd-close-on-exec.h"
#include "ipwd.h"
#include "process-title.h"
+#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
static bool lib_initialized = FALSE;
+int dev_null_fd = -1;
struct atexit_callback {
int priority;
}
}
+static void lib_open_non_stdio_dev_null(void)
+{
+ dev_null_fd = open("/dev/null", O_WRONLY);
+ if (dev_null_fd == -1)
+ i_fatal("open(/dev/null) failed: %m");
+ /* Make sure stdin, stdout and stderr fds exist. We especially rely on
+ stderr being available and a lot of code doesn't like fd being 0.
+ We'll open /dev/null as write-only also for stdin, since if any
+ reads are attempted from it we'll want them to fail. */
+ while (dev_null_fd < STDERR_FILENO) {
+ dev_null_fd = dup(dev_null_fd);
+ if (dev_null_fd == -1)
+ i_fatal("dup(/dev/null) failed: %m");
+ }
+ /* close the actual /dev/null fd on exec*(), but keep it in stdio fds */
+ fd_close_on_exec(dev_null_fd, TRUE);
+}
+
void lib_init(void)
{
struct timeval tv;
data_stack_init();
hostpid_init();
+ lib_open_non_stdio_dev_null();
+
lib_initialized = TRUE;
}
lib_atexit_run();
ipwd_deinit();
hostpid_deinit();
+ i_close_fd(&dev_null_fd);
data_stack_deinit();
env_deinit();
failures_deinit();
#define LIB_ATEXIT_PRIORITY_DEFAULT 0
#define LIB_ATEXIT_PRIORITY_LOW 10
+/* /dev/null opened as O_WRONLY. Opened at lib_init(), so it can be accessed
+ also inside chroots. */
+extern int dev_null_fd;
+
int close_keep_errno(int *fd);
/* Call unlink(). If it fails, log an error including the source filename
and line number. */