#include <grp.h>
#include <errno.h>
#include <string.h>
+#include <fcntl.h>
#include <string>
#include <stdexcept>
return sid;
}
+/**
+ * @brief reopen standard file descriptors as ``/dev/null``.
+ *
+ * Disable stdin, stdout and stderr to ensure no output can be read from or
+ * written to those descriptors. This assumes the process will interact with
+ * the outside world through other means like syslog and sockets.
+ *
+ * Raises ``runtime_error`` in case of errors.
+ */
+void null_fds () {
+ int devnull;
+
+ errno = 0;
+ if ((devnull = open ("/dev/null", O_RDWR)) == -1)
+ {
+ throw std::runtime_error
+ ((std::string)
+ "null_fds: open(/dev/null) returned an error ("
+ + I2n::to_string (errno)
+ + "): " + strerror (errno));
+ }
+
+ for (int fd = 0; fd != 3; ++fd)
+ {
+ errno = 0;
+ if (dup2 (devnull, fd) == -1)
+ {
+ throw std::runtime_error
+ ((std::string)
+ "null_fds: dup2(/dev/null, "
+ + I2n::to_string (fd)
+ + ") returned an error ("
+ + I2n::to_string (errno)
+ + "): " + strerror (errno));
+ }
+ }
+
+ errno = 0;
+ if (close (devnull) == -1)
+ {
+ throw std::runtime_error
+ ((std::string)
+ "null_fds: close(/dev/null) returned an error ("
+ + I2n::to_string (errno)
+ + "): " + strerror (errno));
+ }
+}
+
+/**
+ * @brief convert the current process into a background process.
+ *
+ * This convenience wrapper combines forking, creation of a new session and
+ * disabling stdio.
+ *
+ * Raises ``runtime_error`` in case of errors.
+ */
+void daemonize_full (void)
+{
+ daemonize ();
+ (void)create_session ();
+ null_fds ();
+}
+
}
}
namespace Daemon
{
void daemonize();
+void daemonize_full();
bool drop_root_privileges(const std::string &username,
const std::string &group, bool get_group_from_user=false);
bool pid_of(const std::string& name, std::vector< pid_t >& result);
pid_t create_session (void);
+void null_fds (void);
}
}