static int watchdog_start(const struct sol_platform_linux_micro_module *mod, const char *service) { int err = 0; int timeout = 60; uint32_t timeout_ms; if (watchdog_fd >= 0) return 0; service_name = service; watchdog_fd = open("/dev/watchdog", O_CLOEXEC | O_WRONLY); if (watchdog_fd < 0) { err = -errno; SOL_WRN("could not open /dev/watchdog: %s", sol_util_strerrora(errno)); goto end; } if (ioctl(watchdog_fd, WDIOC_GETTIMEOUT, &timeout) < 0 || timeout < 1) { timeout = WATCHDOG_TIMEOUT_DEFAULT_SECS; SOL_WRN("could not query watchdog timeout, use %ds", timeout); if (ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &timeout) < 0) { SOL_WRN("could not set watchdog timeout to default %ds: %s. Ignored", timeout, sol_util_strerrora(errno)); } } if (timeout > 5) timeout_ms = (uint32_t)(timeout - 5) * 1000U; else timeout_ms = (uint32_t)timeout * 900U; watchdog_timeout = sol_timeout_add(timeout_ms, watchdog_keep_alive, NULL); if (!watchdog_timeout) { err = -ENOMEM; SOL_WRN("could not create watchdog_timeout"); close(watchdog_fd); watchdog_fd = -1; goto end; } watchdog_show_info(); end: if (err == 0) sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_ACTIVE); else sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_FAILED); return err; }
static void on_fork_exit(void *data, uint64_t pid, int status) { SOL_DBG("bluetooth-daemon pid=%" PRIu64 " exited with status=%d", pid, status); if (status) sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_FAILED); else sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_INACTIVE); }
static void on_fork_exit(void *data, uint64_t pid, int status) { if (check_timeout) { sol_timeout_del(check_timeout); check_timeout = NULL; } SOL_DBG("dbus-daemon pid=%" PRIu64 " exited with status=%d", pid, status); if (status) sol_platform_linux_micro_inform_service_state(name, SOL_PLATFORM_SERVICE_STATE_FAILED); else sol_platform_linux_micro_inform_service_state(name, SOL_PLATFORM_SERVICE_STATE_INACTIVE); }
static int run_do(void) { static const char *etc_path = "/etc/machine-id", *run_path = "/run/machine-id"; char id[33]; int r; r = sol_util_read_file(etc_path, "%32s", id); if (r < 0) { /* We can only tolerate the file not existing or being * malformed on /etc/, otherwise it's got more serious * problems and it's better to fail */ if (r != -ENOENT && r != EOF) goto err; } else { r = validate_machine_id(id); /* return if OK here */ SOL_INT_CHECK(r, == 0, 0); } r = sol_util_uuid_gen(false, false, id); SOL_INT_CHECK_GOTO(r, < 0, err); if (write_machine_id(etc_path, id) >= 0) goto end; /* fallback to /run/ */ r = write_machine_id(run_path, id); SOL_INT_CHECK_GOTO(r, < 0, err); end: sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_ACTIVE); done = true; return 0; err: sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_FAILED); return r; }
static int hostname_start(const struct sol_platform_linux_micro_module *mod, const char *service) { struct sol_file_reader *reader; struct sol_str_slice str; const char *s, *p, *end; int err = 0; reader = sol_file_reader_open("/etc/hostname"); SOL_NULL_CHECK_MSG(reader, -errno, "could not read /etc/hostname"); str = sol_file_reader_get_all(reader); s = p = str.data; end = s + str.len; for (; s < end; s++) { if (!isblank(*s)) break; } for (p = end - 1; p > s; p--) { if (!isblank(*p)) break; } if (s >= p) { SOL_WRN("no hostname in /etc/hostname"); err = -ENOENT; } else if (sethostname(s, p - s) < 0) { SOL_WRN("could not set hostname: %s", sol_util_strerrora(errno)); err = -errno; } sol_file_reader_close(reader); if (err == 0) sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_ACTIVE); else sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_FAILED); return err; }
static int fork_run_do(void) { if (fork_run) return 0; fork_run = sol_platform_linux_fork_run(on_fork, on_fork_exit, NULL); if (!fork_run) { sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_FAILED); return -errno; } SOL_DBG("bluetooth-daemon started as pid=%" PRIu64, (uint64_t)sol_platform_linux_fork_run_get_pid(fork_run)); sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_ACTIVE); return 0; }
static bool on_timeout(void *data) { struct stat st; if (stat("/run/dbus/system_bus_socket", &st) < 0) return true; sol_platform_linux_micro_inform_service_state(name, SOL_PLATFORM_SERVICE_STATE_ACTIVE); check_timeout = NULL; return false; }
static void on_fstab_service_state_changed(void *data, const char *service, enum sol_platform_service_state state) { if (state == SOL_PLATFORM_SERVICE_STATE_ACTIVE) run_do(); else if (state == SOL_PLATFORM_SERVICE_STATE_INACTIVE || state == SOL_PLATFORM_SERVICE_STATE_FAILED) sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_FAILED); }
static int machine_id_stop(const struct sol_platform_linux_micro_module *mod, const char *service, bool force_immediate) { static const char *FSTAB = "fstab"; sol_platform_del_service_monitor (on_fstab_service_state_changed, FSTAB, NULL); sol_platform_linux_micro_inform_service_state (name, SOL_PLATFORM_SERVICE_STATE_INACTIVE); return 0; }
static int watchdog_stop(const struct sol_platform_linux_micro_module *module, const char *service, bool force_immediate) { if (watchdog_fd < 0) return 0; sol_timeout_del(watchdog_timeout); watchdog_timeout = NULL; close(watchdog_fd); watchdog_fd = -1; sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_INACTIVE); service_name = NULL; return 0; }
static bool watchdog_keep_alive(void *data) { int reply, err; SOL_DBG("keep watchdog alive"); err = ioctl(watchdog_fd, WDIOC_KEEPALIVE, &reply); if (reply != WDIOF_KEEPALIVEPING) SOL_WRN("unexpected watchdog keepalive reply=%#x, expected=%#x. Ignored.", reply, WDIOF_KEEPALIVEPING); if (err == 0) return true; SOL_WRN("failed to keep watchdog alive: %s", sol_util_strerrora(errno)); close(watchdog_fd); watchdog_fd = -1; watchdog_timeout = NULL; sol_platform_linux_micro_inform_service_state(service_name, SOL_PLATFORM_SERVICE_STATE_FAILED); return false; }
static int dbus_start(const struct sol_platform_linux_micro_module *mod, const char *service) { if (fork_run) return 0; name = service; fork_run = sol_platform_linux_fork_run(on_fork, on_fork_exit, NULL); if (!fork_run) { sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_FAILED); return -errno; } SOL_DBG("dbus-daemon started as pid=%" PRIu64, (uint64_t)sol_platform_linux_fork_run_get_pid(fork_run)); /* TODO: change to use inotify */ check_timeout = sol_timeout_add(200, on_timeout, NULL); return 0; }
static int bluetooth_start(const struct sol_platform_linux_micro_module *mod, const char *service) { int ret = 0; static const char *DBUS = "dbus"; enum sol_platform_service_state state = SOL_PLATFORM_SERVICE_STATE_ACTIVE; name = service; if (fork_run) return 0; ret = sol_platform_add_service_monitor (on_dbus_service_state_changed, DBUS, mod); SOL_INT_CHECK_GOTO(ret, < 0, err); ret = sol_platform_start_service(DBUS); if (ret < 0) { SOL_WRN("D-Bus service is a dependency for bluetooth and could" " not be started"); sol_platform_del_service_monitor (on_dbus_service_state_changed, DBUS, NULL); goto err; } state = sol_platform_get_service_state(DBUS); if (state == SOL_PLATFORM_SERVICE_STATE_ACTIVE) return fork_run_do(); return 0; /* wait for dep to activate */ err: sol_platform_linux_micro_inform_service_state (service, SOL_PLATFORM_SERVICE_STATE_FAILED); return ret; }
static int watchdog_restart(const struct sol_platform_linux_micro_module *module, const char *service) { sol_platform_linux_micro_inform_service_state(service, SOL_PLATFORM_SERVICE_STATE_ACTIVE); return 0; }