mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-01-11 06:20:17 +01:00
_dbus_ensure_standard_fds: new function to ensure std* fds are open
This function opens stdin, stdout, stderr pointing to /dev/null if they aren't already open. Optionally, it can also replace whatever is available on those fds with /dev/null. To allow for use in contexts where only async-signal-safe functions should be used, such as between fork() and a following exec(), this function does not use conventional libdbus error handling (which would require malloc). Instead, it sets errno and returns an explanatory string. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=97008 Signed-off-by: Simon McVittie <smcv@debian.org> Reviewed-by: Thiago Macieira <thiago@kde.org>
This commit is contained in:
parent
e3a14eb4fd
commit
69123a6bd2
2 changed files with 86 additions and 0 deletions
|
|
@ -134,6 +134,81 @@
|
|||
|
||||
#endif /* Solaris */
|
||||
|
||||
/**
|
||||
* Ensure that the standard file descriptors stdin, stdout and stderr
|
||||
* are open, by opening /dev/null if necessary.
|
||||
*
|
||||
* This function does not use DBusError, to avoid calling malloc(), so
|
||||
* that it can be used in contexts where an async-signal-safe function
|
||||
* is required (for example after fork()). Instead, on failure it sets
|
||||
* errno and returns something like "Failed to open /dev/null" in
|
||||
* *error_str_p. Callers are expected to combine *error_str_p
|
||||
* with _dbus_strerror (errno) to get a full error report.
|
||||
*
|
||||
* This function can only be called while single-threaded: either during
|
||||
* startup of an executable, or after fork().
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
|
||||
const char **error_str_p)
|
||||
{
|
||||
static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
|
||||
DBUS_FORCE_STDOUT_NULL,
|
||||
DBUS_FORCE_STDERR_NULL };
|
||||
/* Should always get replaced with the real error before use */
|
||||
const char *error_str = "Failed mysteriously";
|
||||
int devnull = -1;
|
||||
int saved_errno;
|
||||
/* This function relies on the standard fds having their POSIX values. */
|
||||
_DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
|
||||
_DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
|
||||
_DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
|
||||
int i;
|
||||
|
||||
for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
|
||||
{
|
||||
/* Because we rely on being single-threaded, and we want the
|
||||
* standard fds to not be close-on-exec, we don't set it
|
||||
* close-on-exec. */
|
||||
if (devnull < i)
|
||||
devnull = open ("/dev/null", O_RDWR);
|
||||
|
||||
if (devnull < 0)
|
||||
{
|
||||
error_str = "Failed to open /dev/null";
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We already opened all fds < i, so the only way this assertion
|
||||
* could fail is if another thread closed one, and we document
|
||||
* this function as not safe for multi-threading. */
|
||||
_dbus_assert (devnull >= i);
|
||||
|
||||
if (devnull != i && (flags & relevant_flag[i]) != 0)
|
||||
{
|
||||
if (dup2 (devnull, i) < 0)
|
||||
{
|
||||
error_str = "Failed to dup2 /dev/null onto a standard fd";
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error_str = NULL;
|
||||
|
||||
out:
|
||||
saved_errno = errno;
|
||||
|
||||
if (devnull > STDERR_FILENO)
|
||||
close (devnull);
|
||||
|
||||
if (error_str_p != NULL)
|
||||
*error_str_p = error_str;
|
||||
|
||||
errno = saved_errno;
|
||||
return (error_str == NULL);
|
||||
}
|
||||
|
||||
static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
|
||||
DBusError *error);
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,17 @@ dbus_bool_t _dbus_append_address_from_socket (DBusSocket fd,
|
|||
DBUS_PRIVATE_EXPORT
|
||||
void _dbus_fd_set_close_on_exec (int fd);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DBUS_FORCE_STDIN_NULL = (1 << 0),
|
||||
DBUS_FORCE_STDOUT_NULL = (1 << 1),
|
||||
DBUS_FORCE_STDERR_NULL = (1 << 2)
|
||||
} DBusEnsureStandardFdsFlags;
|
||||
|
||||
DBUS_PRIVATE_EXPORT
|
||||
dbus_bool_t _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
|
||||
const char **error_str_p);
|
||||
|
||||
/** @} */
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue