#include "signal-util.h"
static int run(int argc, char *argv[]) {
- _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r;
log_setup_service();
#include "alloc-util.h"
#include "bus-error.h"
#include "bus-util.h"
+#include "daemon-util.h"
#include "def.h"
#include "fd-util.h"
#include "format-util.h"
#include "initreq.h"
#include "list.h"
#include "log.h"
+#include "main-func.h"
#include "memory-util.h"
#include "process-util.h"
#include "special.h"
{ '6', SPECIAL_REBOOT_TARGET, false },
};
- unsigned i;
-
assert(isolate);
- for (i = 0; i < ELEMENTSOF(table); i++)
+ for (size_t i = 0; i < ELEMENTSOF(table); i++)
if (table[i].runlevel == runlevel) {
*isolate = table[i].isolate;
if (runlevel == '6' && kexec_loaded())
free(f);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(Fifo*, fifo_free);
static void server_done(Server *s) {
assert(s);
static int server_init(Server *s, unsigned n_sockets) {
int r;
- unsigned i;
+
+ /* This function will leave s partially initialized on failure. Caller needs to clean up. */
assert(s);
assert(n_sockets > 0);
- *s = (struct Server) {
- .epoll_fd = epoll_create1(EPOLL_CLOEXEC),
- };
-
- if (s->epoll_fd < 0) {
- r = log_error_errno(errno,
- "Failed to create epoll object: %m");
- goto fail;
- }
-
- for (i = 0; i < n_sockets; i++) {
- Fifo *f;
- int fd;
+ s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
+ if (s->epoll_fd < 0)
+ return log_error_errno(errno, "Failed to create epoll object: %m");
- fd = SD_LISTEN_FDS_START+i;
+ for (unsigned i = 0; i < n_sockets; i++) {
+ _cleanup_(fifo_freep) Fifo *f = NULL;
+ int fd = SD_LISTEN_FDS_START + i;
r = sd_is_fifo(fd, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to determine file descriptor type: %m");
- goto fail;
- }
-
- if (!r) {
- log_error("Wrong file descriptor type.");
- r = -EINVAL;
- goto fail;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine file descriptor type: %m");
+ if (!r)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong file descriptor type.");
f = new0(Fifo, 1);
- if (!f) {
- r = -ENOMEM;
- log_error_errno(errno, "Failed to create fifo object: %m");
- goto fail;
- }
-
- f->fd = -1;
+ if (!f)
+ return log_oom();
struct epoll_event ev = {
.events = EPOLLIN,
.data.ptr = f,
};
- if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
- r = -errno;
- fifo_free(f);
- log_error_errno(errno, "Failed to add fifo fd to epoll object: %m");
- goto fail;
- }
+ if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
+ return log_error_errno(errno, "Failed to add fifo fd to epoll object: %m");
f->fd = fd;
- LIST_PREPEND(fifo, s->fifos, f);
f->server = s;
+ LIST_PREPEND(fifo, s->fifos, TAKE_PTR(f));
s->n_fifos++;
}
r = bus_connect_system_systemd(&s->bus);
- if (r < 0) {
- log_error_errno(r, "Failed to get D-Bus connection: %m");
- r = -EIO;
- goto fail;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get D-Bus connection: %m");
return 0;
-
-fail:
- server_done(s);
-
- return r;
}
static int process_event(Server *s, struct epoll_event *ev) {
return 0;
}
-int main(int argc, char *argv[]) {
- Server server;
- int r = EXIT_FAILURE, n;
-
- if (getppid() != 1) {
- log_error("This program should be invoked by init only.");
- return EXIT_FAILURE;
- }
+static int run(int argc, char *argv[]) {
+ _cleanup_(server_done) Server server = { .epoll_fd = -1 };
+ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
+ int r, n;
- if (argc > 1) {
- log_error("This program does not take arguments.");
- return EXIT_FAILURE;
- }
+ if (argc > 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This program does not take arguments.");
log_setup_service();
umask(0022);
n = sd_listen_fds(true);
- if (n < 0) {
- log_error_errno(r, "Failed to read listening file descriptors from environment: %m");
- return EXIT_FAILURE;
- }
-
- if (n <= 0 || n > SERVER_FD_MAX) {
- log_error("No or too many file descriptors passed.");
- return EXIT_FAILURE;
- }
+ if (n < 0)
+ return log_error_errno(errno,
+ "Failed to read listening file descriptors from environment: %m");
- if (server_init(&server, (unsigned) n) < 0)
- return EXIT_FAILURE;
+ if (n <= 0 || n > SERVER_FD_MAX)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "No or too many file descriptors passed.");
- log_debug("systemd-initctl running as pid "PID_FMT, getpid_cached());
+ r = server_init(&server, (unsigned) n);
+ if (r < 0)
+ return r;
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
+ notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
while (!server.quit) {
struct epoll_event event;
if (k < 0) {
if (errno == EINTR)
continue;
- log_error_errno(errno, "epoll_wait() failed: %m");
- goto fail;
+ return log_error_errno(errno, "epoll_wait() failed: %m");
}
-
- if (k <= 0)
+ if (k == 0)
break;
- if (process_event(&server, &event) < 0)
- goto fail;
+ r = process_event(&server, &event);
+ if (r < 0)
+ return r;
}
- r = EXIT_SUCCESS;
-
- log_debug("systemd-initctl stopped as pid "PID_FMT, getpid_cached());
-
-fail:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- server_done(&server);
-
- return r;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);
}
static int run(int argc, char **argv) {
- _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(journal_remote_server_destroy) RemoteServer s = {};
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
int r;
}
static int run(int argc, char **argv) {
- _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(destroy_uploader) Uploader u = {};
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
bool use_journal;
int r;
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/vt.h>
-#if ENABLE_UTMP
-#include <utmpx.h>
-#endif
#include "sd-device.h"
#include "udev-util.h"
#include "user-util.h"
#include "userdb.h"
+#include "utmp-wtmp.h"
void manager_reset_config(Manager *m) {
assert(m);
int manager_read_utmp(Manager *m) {
#if ENABLE_UTMP
int r;
+ _cleanup_(utxent_cleanup) bool utmpx = false;
assert(m);
if (utmpxname(_PATH_UTMPX) < 0)
return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m");
- setutxent();
+ utmpx = utxent_start();
for (;;) {
_cleanup_free_ char *t = NULL;
if (!u) {
if (errno != 0)
log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m");
- r = 0;
- break;
+ return 0;
}
if (u->ut_type != USER_PROCESS)
continue;
t = strndup(u->ut_line, sizeof(u->ut_line));
- if (!t) {
- r = log_oom();
- break;
- }
+ if (!t)
+ return log_oom();
c = path_startswith(t, "/dev/");
if (c) {
r = free_and_strdup(&t, c);
- if (r < 0) {
- log_oom();
- break;
- }
+ if (r < 0)
+ return log_oom();
}
if (isempty(t))
log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
}
- endutxent();
- return r;
#else
return 0;
#endif
#include "user-util.h"
static int run(int argc, char *argv[]) {
- _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
int r;
log_setup_service();
}
static int run(int argc, char *argv[]) {
- _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
int r;
log_setup_service();
#include "user-util.h"
static int run(int argc, char *argv[]) {
- _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r;
log_setup_service();
#include "utmp-wtmp.h"
int utmp_get_runlevel(int *runlevel, int *previous) {
+ _cleanup_(utxent_cleanup) bool utmpx = false;
struct utmpx *found, lookup = { .ut_type = RUN_LVL };
- int r;
const char *e;
assert(runlevel);
* precedence. Presumably, sysvinit does this to work around a
* race condition that would otherwise exist where we'd always
* go to disk and hence might read runlevel data that might be
- * very new and does not apply to the current script being
- * executed. */
+ * very new and not apply to the current script being executed. */
e = getenv("RUNLEVEL");
if (e && e[0] > 0) {
if (utmpxname(_PATH_UTMPX) < 0)
return -errno;
- setutxent();
+ utmpx = utxent_start();
found = getutxid(&lookup);
if (!found)
- r = -errno;
- else {
- int a, b;
-
- a = found->ut_pid & 0xFF;
- b = (found->ut_pid >> 8) & 0xFF;
-
- *runlevel = a;
- if (previous)
- *previous = b;
-
- r = 0;
- }
+ return -errno;
- endutxent();
+ *runlevel = found->ut_pid & 0xFF;
+ if (previous)
+ *previous = (found->ut_pid >> 8) & 0xFF;
- return r;
+ return 0;
}
static void init_timestamp(struct utmpx *store, usec_t t) {
}
static int write_entry_utmp(const struct utmpx *store) {
- int r;
+ _cleanup_(utxent_cleanup) bool utmpx = false;
assert(store);
if (utmpxname(_PATH_UTMPX) < 0)
return -errno;
- setutxent();
-
- if (!pututxline(store))
- r = -errno;
- else
- r = 0;
-
- endutxent();
+ utmpx = utxent_start();
- return r;
+ if (pututxline(store))
+ return 0;
+ if (errno == ENOENT) {
+ /* If utmp/wtmp have been disabled, that's a good thing, hence ignore the error. */
+ log_debug_errno(errno, "Not writing utmp: %m");
+ return 0;
+ }
+ return -errno;
}
static int write_entry_wtmp(const struct utmpx *store) {
assert(store);
/* wtmp is a simple append-only file where each entry is
- simply appended to the end; i.e. basically a log. */
+ * simply appended to the end; i.e. basically a log. */
errno = 0;
updwtmpx(_PATH_WTMPX, store);
+ if (errno == ENOENT) {
+ /* If utmp/wtmp have been disabled, that's a good thing, hence ignore the error. */
+ log_debug_errno(errno, "Not writing wtmp: %m");
+ return 0;
+ }
+ if (errno == EROFS) {
+ log_warning_errno(errno, "Failed to write wtmp record, ignoring: %m");
+ return 0;
+ }
return -errno;
}
r = write_entry_utmp(store_utmp);
s = write_entry_wtmp(store_wtmp);
-
- if (r >= 0)
- r = s;
-
- /* If utmp/wtmp have been disabled, that's a good thing, hence
- * ignore the errors */
- if (r == -ENOENT)
- r = 0;
-
- return r;
+ return r < 0 ? r : s;
}
static int write_entry_both(const struct utmpx *store) {
#include "util.h"
#if ENABLE_UTMP
+#include <utmpx.h>
+
int utmp_get_runlevel(int *runlevel, int *previous);
int utmp_put_shutdown(void);
bool (*match_tty)(const char *tty, void *userdata),
void *userdata);
+static inline bool utxent_start(void) {
+ setutxent();
+ return true;
+}
+static inline void utxent_cleanup(bool *initialized) {
+ if (initialized)
+ endutxent();
+}
+
#else /* ENABLE_UTMP */
static inline int utmp_get_runlevel(int *runlevel, int *previous) {
}
static int run(int argc, char *argv[]) {
- _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_message = NULL;
const char *user = "systemd-timesync";
uid_t uid, uid_current;
gid_t gid;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
- unsigned i;
assert(c);
- for (i = 0; i < ELEMENTSOF(table); i++) {
+ for (size_t i = 0; i < ELEMENTSOF(table); i++) {
_cleanup_free_ char *state = NULL, *path = NULL;
path = unit_dbus_path_from_name(table[i].special);
};
int r;
- if (getppid() != 1)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "This program should be invoked by init only.");
if (argc != 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"This program requires one argument.");
*/
static int run(int argc, char *argv[]) {
- _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
+ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r;
log_setup_service();