#include "dinit-log.h"
#include "dinit-socket.h"
#include "static-string.h"
+#include "dinit-utmp.h"
#include "mconfig.h"
static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
static void sigquit_cb(eventloop_t &eloop) noexcept;
static void sigterm_cb(eventloop_t &eloop) noexcept;
+static void open_control_socket(bool report_ro_failure = true) noexcept;
static void close_control_socket() noexcept;
static void wait_for_user_input() noexcept;
static void read_env_file(const char *);
static bool am_pid_one = false; // true if we are PID 1
static bool am_system_init = false; // true if we are the system init process
+static bool did_log_boot = false;
static bool control_socket_open = false;
static bool external_log_open = false;
int active_control_conns = 0;
}
}
+// Callback when the root filesystem is read/write:
+void rootfs_is_rw() noexcept
+{
+ open_control_socket(true);
+ if (! did_log_boot) {
+ did_log_boot = log_boot();
+ }
+}
+
// Open/create the control socket, normally /dev/dinitctl, used to allow client programs to connect
// and issue service orders and shutdown commands etc. This can safely be called multiple times;
// once the socket has been successfully opened, further calls have no effect.
-void open_control_socket(bool report_ro_failure) noexcept
+static void open_control_socket(bool report_ro_failure) noexcept
{
if (! control_socket_open) {
const char * saddrname = control_socket_path;
--- /dev/null
+// Wrappers for utmp/wtmp & equivalent database access.
+
+#ifndef DINIT_UTMP_H_INCLUDED
+#define DINIT_UTMP_H_INCLUDED
+
+#ifndef USE_UTMPX
+#define USE_UTMPX 1
+#endif
+
+#ifndef USE_UPDWTMPX
+#ifdef __linux__
+#define USE_UPDWTMPX 1
+#else
+#define USE_UPDWTMPX 0
+#endif
+#endif
+
+#if USE_UTMPX
+
+#include <cstring>
+
+#include <utmpx.h>
+#include <sys/time.h>
+
+// Set the time for a utmpx record to the current time.
+inline void set_current_time(struct utmpx *record)
+{
+#ifdef __linux__
+ // On Linux, ut_tv is not actually a struct timeval:
+ timeval curtime;
+ gettimeofday(&curtime, nullptr);
+ record->ut_tv.tv_sec = curtime.tv_sec;
+ record->ut_tv.tv_usec = curtime.tv_usec;
+#else
+ gettimeofday(&record->ut_tv, nullptr);
+#endif
+}
+
+// Log the boot time to the wtmp database (or equivalent).
+inline bool log_boot()
+{
+ struct utmpx record;
+ memset(&record, 0, sizeof(record));
+ record.ut_type = BOOT_TIME;
+
+ set_current_time(&record);
+
+ // On FreeBSD, putxline will update all appropriate databases. On Linux, it only updates
+ // the utmp database: we need to update the wtmp database explicitly:
+#if USE_UPDWTMPX
+ updwtmpx(_PATH_WTMPX, &record);
+#endif
+
+ setutxent();
+ bool success = (pututxline(&record) != NULL);
+ endutxent();
+
+ return success;
+}
+
+#else // Don't update databases:
+
+static inline void log_boot() { }
+
+#endif
+
+#endif
using rearm = dasynq::rearm;
using time_val = dasynq::time_val;
-void open_control_socket(bool report_ro_failure = true) noexcept;
+void rootfs_is_rw() noexcept;
void setup_external_log() noexcept;
extern eventloop_t event_loop;
notify_listeners(service_event_t::STARTED);
if (onstart_flags.rw_ready) {
- open_control_socket();
+ rootfs_is_rw();
}
if (onstart_flags.log_ready) {
setup_external_log();
std::map<int, fd_watcher *> regd_fd_watchers;
};
-inline void open_control_socket(bool report_ro_failure = true) noexcept
+inline void rootfs_is_rw() noexcept
{
}