#include <libaudit.h>
#endif
-#include <systemd/sd-daemon.h>
+#include "systemd/sd-daemon.h"
+#include "systemd/sd-id128.h"
+#include "systemd/sd-messages.h"
#include "manager.h"
#include "transaction.h"
#include "watchdog.h"
#include "cgroup-util.h"
#include "path-util.h"
+#include "audit-fd.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
#define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
/* Where clients shall send notification messages to */
-#define NOTIFY_SOCKET_SYSTEM "/run/systemd/notify"
-#define NOTIFY_SOCKET_USER "@/org/freedesktop/systemd1/notify"
+#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
static int manager_setup_notify(Manager *m) {
union {
struct sockaddr_un un;
} sa;
struct epoll_event ev;
- int one = 1, r;
- mode_t u;
+ int one = 1;
assert(m);
m->notify_watch.type = WATCH_NOTIFY;
- if ((m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
+ m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ if (m->notify_watch.fd < 0) {
log_error("Failed to allocate notification socket: %m");
return -errno;
}
zero(sa);
sa.sa.sa_family = AF_UNIX;
- if (getpid() != 1)
- snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET_USER "/%llu", random_ull());
- else {
- unlink(NOTIFY_SOCKET_SYSTEM);
- strncpy(sa.un.sun_path, NOTIFY_SOCKET_SYSTEM, sizeof(sa.un.sun_path));
- }
-
- if (sa.un.sun_path[0] == '@')
- sa.un.sun_path[0] = 0;
+ if (getpid() != 1 || detect_container(NULL) > 0)
+ snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
+ else
+ strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
- u = umask(0111);
- r = bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
- umask(u);
+ sa.un.sun_path[0] = 0;
- if (r < 0) {
+ if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
log_error("bind() failed: %m");
return -errno;
}
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
return -errno;
- if (sa.un.sun_path[0] == 0)
- sa.un.sun_path[0] = '@';
-
- if (!(m->notify_socket = strdup(sa.un.sun_path)))
+ sa.un.sun_path[0] = '@';
+ m->notify_socket = strdup(sa.un.sun_path);
+ if (!m->notify_socket)
return -ENOMEM;
log_debug("Using notification socket %s", m->notify_socket);
assert(m);
/* Enable that we get SIGINT on control-alt-del. In containers
- * this will fail with EPERM, so ignore that. */
- if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM)
+ * this will fail with EPERM (older) or EINVAL (newer), so
+ * ignore that. */
+ if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM && errno != EINVAL)
log_warning("Failed to enable ctrl-alt-del handling: %m");
fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
SIGRTMIN+21, /* systemd: disable status messages */
SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
+ SIGRTMIN+24, /* systemd: Immediate exit (--user only) */
SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
SIGRTMIN+27, /* systemd: set log target to console */
SIGRTMIN+28, /* systemd: set log target to kmsg */
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
return -errno;
- if (m->running_as == MANAGER_SYSTEM)
+ if (m->running_as == SYSTEMD_SYSTEM)
return enable_special_signals(m);
return 0;
strv_remove_prefix(m->environment, "RD_");
}
-int manager_new(ManagerRunningAs running_as, Manager **_m) {
+int manager_new(SystemdRunningAs running_as, Manager **_m) {
Manager *m;
int r = -ENOMEM;
assert(_m);
assert(running_as >= 0);
- assert(running_as < _MANAGER_RUNNING_AS_MAX);
+ assert(running_as < _SYSTEMD_RUNNING_AS_MAX);
- if (!(m = new0(Manager, 1)))
+ m = new0(Manager, 1);
+ if (!m)
return -ENOMEM;
- dual_timestamp_get(&m->startup_timestamp);
+ dual_timestamp_get(&m->userspace_timestamp);
m->running_as = running_as;
m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
m->pin_cgroupfs_fd = -1;
m->idle_pipe[0] = m->idle_pipe[1] = -1;
-#ifdef HAVE_AUDIT
- m->audit_fd = -1;
-#endif
-
m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = m->swap_watch.fd = -1;
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
manager_strip_environment(m);
- if (running_as == MANAGER_SYSTEM) {
+ if (running_as == SYSTEMD_SYSTEM) {
m->default_controllers = strv_new("cpu", NULL);
if (!m->default_controllers)
goto fail;
if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
goto fail;
- if ((r = lookup_paths_init(&m->lookup_paths, m->running_as, true)) < 0)
- goto fail;
-
if ((r = manager_setup_signals(m)) < 0)
goto fail;
goto fail;
/* Try to connect to the busses, if possible. */
- if ((r = bus_init(m, running_as != MANAGER_SYSTEM)) < 0)
+ if ((r = bus_init(m, running_as != SYSTEMD_SYSTEM)) < 0)
goto fail;
-#ifdef HAVE_AUDIT
- if ((m->audit_fd = audit_open()) < 0 &&
- /* If the kernel lacks netlink or audit support,
- * don't worry about it. */
- errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
- log_error("Failed to connect to audit log: %m");
-#endif
-
m->taint_usr = dir_is_empty("/usr") > 0;
*_m = m;
void manager_free(Manager *m) {
UnitType c;
+ int i;
assert(m);
if (m->notify_watch.fd >= 0)
close_nointr_nofail(m->notify_watch.fd);
-#ifdef HAVE_AUDIT
- if (m->audit_fd >= 0)
- audit_close(m->audit_fd);
-#endif
-
free(m->notify_socket);
lookup_paths_free(&m->lookup_paths);
free(m->switch_root);
free(m->switch_root_init);
+ for (i = 0; i < RLIMIT_NLIMITS; i++)
+ free(m->rlimit[i]);
+
free(m);
}
if (ignore_file(de->d_name))
continue;
- p = join(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
+ p = strjoin(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
if (!p) {
r = -ENOMEM;
goto fail;
manager_run_generators(m);
+ r = lookup_paths_init(
+ &m->lookup_paths, m->running_as, true,
+ m->generator_unit_path,
+ m->generator_unit_path_early,
+ m->generator_unit_path_late);
+ if (r < 0)
+ return r;
+
manager_build_unit_path_cache(m);
/* If we will deserialize make sure that during enumeration
r = manager_enumerate(m);
/* Second, deserialize if there is something to deserialize */
- if (serialization)
- if ((q = manager_deserialize(m, serialization, fds)) < 0)
+ if (serialization) {
+ q = manager_deserialize(m, serialization, fds);
+ if (q < 0)
r = q;
+ }
/* Third, fire things up! */
- if ((q = manager_coldplug(m)) < 0)
+ q = manager_coldplug(m);
+ if (q < 0)
r = q;
if (serialization) {
assert(name);
assert(mode < _JOB_MODE_MAX);
- if ((r = manager_load_unit(m, name, NULL, NULL, &unit)) < 0)
+ r = manager_load_unit(m, name, NULL, NULL, &unit);
+ if (r < 0)
return r;
return manager_add_job(m, type, unit, mode, override, e, _ret);
t = unit_name_to_type(name);
- if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid_no_type(name, false)) {
+ if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) {
dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
return -EINVAL;
}
/* This will load the service information files, but not actually
* start any services or anything. */
- if ((r = manager_load_unit_prepare(m, name, path, e, _ret)) != 0)
+ r = manager_load_unit_prepare(m, name, path, e, _ret);
+ if (r != 0)
return r;
manager_dispatch_load_queue(m);
break;
case SIGTERM:
- if (m->running_as == MANAGER_SYSTEM) {
+ if (m->running_as == SYSTEMD_SYSTEM) {
/* This is for compatibility with the
* original sysvinit */
m->exit_code = MANAGER_REEXECUTE;
/* Fall through */
case SIGINT:
- if (m->running_as == MANAGER_SYSTEM) {
+ if (m->running_as == SYSTEMD_SYSTEM) {
manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE);
break;
}
break;
case SIGWINCH:
- if (m->running_as == MANAGER_SYSTEM)
+ if (m->running_as == SYSTEMD_SYSTEM)
manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
/* This is a nop on non-init */
break;
case SIGPWR:
- if (m->running_as == MANAGER_SYSTEM)
+ if (m->running_as == SYSTEMD_SYSTEM)
manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
/* This is a nop on non-init */
log_notice("Setting log level to info.");
break;
+ case 24:
+ if (m->running_as == SYSTEMD_USER) {
+ m->exit_code = MANAGER_EXIT;
+ return 0;
+ }
+
+ /* This is a nop on init */
+ break;
+
case 26:
log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
log_notice("Setting log target to journal-or-kmsg.");
int n;
int wait_msec = -1;
- if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM)
+ if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
watchdog_ping();
if (!ratelimit_test(&rl)) {
continue;
/* Sleep for half the watchdog time */
- if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) {
+ if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
if (wait_msec <= 0)
wait_msec = 1;
#ifdef HAVE_AUDIT
char *p;
+ int audit_fd;
- if (m->audit_fd < 0)
+ audit_fd = get_audit_fd();
+ if (audit_fd < 0)
return;
/* Don't generate audit events if the service was already
if (m->n_reloading > 0)
return;
- if (m->running_as != MANAGER_SYSTEM)
+ if (m->running_as != SYSTEMD_SYSTEM)
return;
if (u->type != UNIT_SERVICE)
return;
}
- if (audit_log_user_comm_message(m->audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
+ if (audit_log_user_comm_message(audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
if (errno == EPERM) {
/* We aren't allowed to send audit messages?
* Then let's not retry again. */
- audit_close(m->audit_fd);
- m->audit_fd = -1;
+ close_audit_fd();
} else
log_warning("Failed to send audit message: %m");
}
if (m->n_reloading > 0)
return;
- if (m->running_as != MANAGER_SYSTEM)
+ if (m->running_as != SYSTEMD_SYSTEM)
return;
if (u->type != UNIT_SERVICE &&
}
if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) {
- log_error("Out of memory");
+ log_oom();
goto finish;
}
assert(_f);
- if (m->running_as == MANAGER_SYSTEM)
+ if (m->running_as == SYSTEMD_SYSTEM)
asprintf(&path, "/run/systemd/dump-%lu-XXXXXX", (unsigned long) getpid());
else
asprintf(&path, "/tmp/systemd-dump-%lu-XXXXXX", (unsigned long) getpid());
return 0;
}
-int manager_serialize(Manager *m, FILE *f, FDSet *fds) {
+int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool serialize_jobs) {
Iterator i;
Unit *u;
const char *t;
fprintf(f, "current-job-id=%i\n", m->current_job_id);
fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
+ fprintf(f, "n-installed-jobs=%u\n", m->n_installed_jobs);
+ fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
+ dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
+ dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
+ dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
- dual_timestamp_serialize(f, "startup-timestamp", &m->startup_timestamp);
- dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
+
+ if (!in_initrd()) {
+ dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp);
+ dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
+ }
fputc('\n', f);
fputs(u->id, f);
fputc('\n', f);
- if ((r = unit_serialize(u, f, fds)) < 0) {
+ if ((r = unit_serialize(u, f, fds, serialize_jobs)) < 0) {
m->n_reloading --;
return r;
}
log_debug("Failed to parse current job id value %s", l+15);
else
m->current_job_id = MAX(m->current_job_id, id);
+ } else if (startswith(l, "n-installed-jobs=")) {
+ uint32_t n;
+
+ if (safe_atou32(l+17, &n) < 0)
+ log_debug("Failed to parse installed jobs counter %s", l+17);
+ else
+ m->n_installed_jobs += n;
+ } else if (startswith(l, "n-failed-jobs=")) {
+ uint32_t n;
+
+ if (safe_atou32(l+14, &n) < 0)
+ log_debug("Failed to parse failed jobs counter %s", l+14);
+ else
+ m->n_failed_jobs += n;
} else if (startswith(l, "taint-usr=")) {
int b;
log_debug("Failed to parse taint /usr flag %s", l+10);
else
m->taint_usr = m->taint_usr || b;
- } else if (startswith(l, "initrd-timestamp="))
+ } else if (startswith(l, "firmware-timestamp="))
+ dual_timestamp_deserialize(l+19, &m->firmware_timestamp);
+ else if (startswith(l, "loader-timestamp="))
+ dual_timestamp_deserialize(l+17, &m->loader_timestamp);
+ else if (startswith(l, "kernel-timestamp="))
+ dual_timestamp_deserialize(l+17, &m->kernel_timestamp);
+ else if (startswith(l, "initrd-timestamp="))
dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
- else if (startswith(l, "startup-timestamp="))
- dual_timestamp_deserialize(l+18, &m->startup_timestamp);
+ else if (startswith(l, "userspace-timestamp="))
+ dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
else if (startswith(l, "finish-timestamp="))
dual_timestamp_deserialize(l+17, &m->finish_timestamp);
else
assert(m);
- if ((r = manager_open_serialization(m, &f)) < 0)
+ r = manager_open_serialization(m, &f);
+ if (r < 0)
return r;
m->n_reloading ++;
- if (!(fds = fdset_new())) {
+ fds = fdset_new();
+ if (!fds) {
m->n_reloading --;
r = -ENOMEM;
goto finish;
}
- if ((r = manager_serialize(m, f, fds)) < 0) {
+ r = manager_serialize(m, f, fds, true);
+ if (r < 0) {
m->n_reloading --;
goto finish;
}
/* From here on there is no way back. */
manager_clear_jobs_and_units(m);
manager_undo_generators(m);
-
- /* Find new unit paths */
lookup_paths_free(&m->lookup_paths);
- if ((q = lookup_paths_init(&m->lookup_paths, m->running_as, true)) < 0)
- r = q;
+ /* Find new unit paths */
manager_run_generators(m);
+ q = lookup_paths_init(
+ &m->lookup_paths, m->running_as, true,
+ m->generator_unit_path,
+ m->generator_unit_path_early,
+ m->generator_unit_path_late);
+ if (q < 0)
+ r = q;
+
manager_build_unit_path_cache(m);
/* First, enumerate what we can from all config files */
- if ((q = manager_enumerate(m)) < 0)
+ q = manager_enumerate(m);
+ if (q < 0)
r = q;
/* Second, deserialize our stored data */
- if ((q = manager_deserialize(m, f, fds)) < 0)
+ q = manager_deserialize(m, f, fds);
+ if (q < 0)
r = q;
fclose(f);
f = NULL;
/* Third, fire things up! */
- if ((q = manager_coldplug(m)) < 0)
+ q = manager_coldplug(m);
+ if (q < 0)
r = q;
assert(m->n_reloading > 0);
void manager_check_finished(Manager *m) {
char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
- usec_t kernel_usec, initrd_usec, userspace_usec, total_usec;
+ usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec;
assert(m);
/* Notify Type=idle units that we are done now */
close_pipe(m->idle_pipe);
+ /* Turn off confirm spawn now */
+ m->confirm_spawn = false;
+
if (dual_timestamp_is_set(&m->finish_timestamp))
return;
dual_timestamp_get(&m->finish_timestamp);
- if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) {
+ if (m->running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) {
- userspace_usec = m->finish_timestamp.monotonic - m->startup_timestamp.monotonic;
- total_usec = m->finish_timestamp.monotonic;
+ /* Note that m->kernel_usec.monotonic is always at 0,
+ * and m->firmware_usec.monotonic and
+ * m->loader_usec.monotonic should be considered
+ * negative values. */
- if (dual_timestamp_is_set(&m->initrd_timestamp)) {
+ firmware_usec = m->firmware_timestamp.monotonic - m->loader_timestamp.monotonic;
+ loader_usec = m->loader_timestamp.monotonic - m->kernel_timestamp.monotonic;
+ userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
+ total_usec = m->firmware_timestamp.monotonic + m->finish_timestamp.monotonic;
- kernel_usec = m->initrd_timestamp.monotonic;
- initrd_usec = m->startup_timestamp.monotonic - m->initrd_timestamp.monotonic;
+ if (dual_timestamp_is_set(&m->initrd_timestamp)) {
- log_info("Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
- format_timespan(kernel, sizeof(kernel), kernel_usec),
- format_timespan(initrd, sizeof(initrd), initrd_usec),
- format_timespan(userspace, sizeof(userspace), userspace_usec),
- format_timespan(sum, sizeof(sum), total_usec));
+ kernel_usec = m->initrd_timestamp.monotonic - m->kernel_timestamp.monotonic;
+ initrd_usec = m->userspace_timestamp.monotonic - m->initrd_timestamp.monotonic;
+
+ if (!log_on_console())
+ log_struct(LOG_INFO,
+ MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
+ "KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
+ "INITRD_USEC=%llu", (unsigned long long) initrd_usec,
+ "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
+ "MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
+ format_timespan(kernel, sizeof(kernel), kernel_usec),
+ format_timespan(initrd, sizeof(initrd), initrd_usec),
+ format_timespan(userspace, sizeof(userspace), userspace_usec),
+ format_timespan(sum, sizeof(sum), total_usec),
+ NULL);
} else {
- kernel_usec = m->startup_timestamp.monotonic;
+ kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic;
initrd_usec = 0;
- log_info("Startup finished in %s (kernel) + %s (userspace) = %s.",
- format_timespan(kernel, sizeof(kernel), kernel_usec),
- format_timespan(userspace, sizeof(userspace), userspace_usec),
- format_timespan(sum, sizeof(sum), total_usec));
+ if (!log_on_console())
+ log_struct(LOG_INFO,
+ MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
+ "KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
+ "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
+ "MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.",
+ format_timespan(kernel, sizeof(kernel), kernel_usec),
+ format_timespan(userspace, sizeof(userspace), userspace_usec),
+ format_timespan(sum, sizeof(sum), total_usec),
+ NULL);
}
} else {
- userspace_usec = initrd_usec = kernel_usec = 0;
- total_usec = m->finish_timestamp.monotonic - m->startup_timestamp.monotonic;
-
- log_debug("Startup finished in %s.",
- format_timespan(sum, sizeof(sum), total_usec));
+ firmware_usec = loader_usec = initrd_usec = kernel_usec = 0;
+ total_usec = userspace_usec = m->finish_timestamp.monotonic - m->userspace_timestamp.monotonic;
+
+ if (!log_on_console())
+ log_struct(LOG_INFO,
+ MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
+ "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
+ "MESSAGE=Startup finished in %s.",
+ format_timespan(sum, sizeof(sum), total_usec),
+ NULL);
}
- bus_broadcast_finished(m, kernel_usec, initrd_usec, userspace_usec, total_usec);
+ bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
sd_notifyf(false,
"READY=1\nSTATUS=Startup finished in %s.",
format_timespan(sum, sizeof(sum), total_usec));
}
+static int create_generator_dir(Manager *m, char **generator, const char *name) {
+ char *p;
+ int r;
+
+ assert(m);
+ assert(generator);
+ assert(name);
+
+ if (*generator)
+ return 0;
+
+ if (m->running_as == SYSTEMD_SYSTEM && getpid() == 1) {
+
+ p = strappend("/run/systemd/", name);
+ if (!p)
+ return log_oom();
+
+ r = mkdir_p_label(p, 0755);
+ if (r < 0) {
+ log_error("Failed to create generator directory: %s", strerror(-r));
+ free(p);
+ return r;
+ }
+ } else {
+ p = strjoin("/tmp/systemd-", name, ".XXXXXX", NULL);
+ if (!p)
+ return log_oom();
+
+ if (!mkdtemp(p)) {
+ free(p);
+ log_error("Failed to create generator directory: %m");
+ return -errno;
+ }
+ }
+
+ *generator = p;
+ return 0;
+}
+
+static void trim_generator_dir(Manager *m, char **generator) {
+ assert(m);
+ assert(generator);
+
+ if (!*generator)
+ return;
+
+ if (rmdir(*generator) >= 0) {
+ free(*generator);
+ *generator = NULL;
+ }
+
+ return;
+}
+
void manager_run_generators(Manager *m) {
DIR *d = NULL;
const char *generator_path;
- const char *argv[3];
+ const char *argv[5];
mode_t u;
+ int r;
assert(m);
- generator_path = m->running_as == MANAGER_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
- if (!(d = opendir(generator_path))) {
-
+ generator_path = m->running_as == SYSTEMD_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
+ d = opendir(generator_path);
+ if (!d) {
if (errno == ENOENT)
return;
return;
}
- if (!m->generator_unit_path) {
- const char *p;
- char user_path[] = "/tmp/systemd-generator-XXXXXX";
-
- if (m->running_as == MANAGER_SYSTEM && getpid() == 1) {
- p = "/run/systemd/generator";
-
- if (mkdir_p(p, 0755) < 0) {
- log_error("Failed to create generator directory: %m");
- goto finish;
- }
+ r = create_generator_dir(m, &m->generator_unit_path, "generator");
+ if (r < 0)
+ goto finish;
- } else {
- if (!(p = mkdtemp(user_path))) {
- log_error("Failed to create generator directory: %m");
- goto finish;
- }
- }
+ r = create_generator_dir(m, &m->generator_unit_path_early, "generator.early");
+ if (r < 0)
+ goto finish;
- if (!(m->generator_unit_path = strdup(p))) {
- log_error("Failed to allocate generator unit path.");
- goto finish;
- }
- }
+ r = create_generator_dir(m, &m->generator_unit_path_late, "generator.late");
+ if (r < 0)
+ goto finish;
argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
argv[1] = m->generator_unit_path;
- argv[2] = NULL;
+ argv[2] = m->generator_unit_path_early;
+ argv[3] = m->generator_unit_path_late;
+ argv[4] = NULL;
u = umask(0022);
execute_directory(generator_path, d, (char**) argv);
umask(u);
- if (rmdir(m->generator_unit_path) >= 0) {
- /* Uh? we were able to remove this dir? I guess that
- * means the directory was empty, hence let's shortcut
- * this */
-
- free(m->generator_unit_path);
- m->generator_unit_path = NULL;
- goto finish;
- }
-
- if (!strv_find(m->lookup_paths.unit_path, m->generator_unit_path)) {
- char **l;
-
- if (!(l = strv_append(m->lookup_paths.unit_path, m->generator_unit_path))) {
- log_error("Failed to add generator directory to unit search path: %m");
- goto finish;
- }
-
- strv_free(m->lookup_paths.unit_path);
- m->lookup_paths.unit_path = l;
-
- log_debug("Added generator unit path %s to search path.", m->generator_unit_path);
- }
+ trim_generator_dir(m, &m->generator_unit_path);
+ trim_generator_dir(m, &m->generator_unit_path_early);
+ trim_generator_dir(m, &m->generator_unit_path_late);
finish:
if (d)
closedir(d);
}
-void manager_undo_generators(Manager *m) {
+static void remove_generator_dir(Manager *m, char **generator) {
assert(m);
+ assert(generator);
- if (!m->generator_unit_path)
+ if (!*generator)
return;
- strv_remove(m->lookup_paths.unit_path, m->generator_unit_path);
- rm_rf(m->generator_unit_path, false, true, false);
+ strv_remove(m->lookup_paths.unit_path, *generator);
+ rm_rf(*generator, false, true, false);
- free(m->generator_unit_path);
- m->generator_unit_path = NULL;
+ free(*generator);
+ *generator = NULL;
+}
+
+void manager_undo_generators(Manager *m) {
+ assert(m);
+
+ remove_generator_dir(m, &m->generator_unit_path);
+ remove_generator_dir(m, &m->generator_unit_path_early);
+ remove_generator_dir(m, &m->generator_unit_path_late);
}
int manager_set_default_controllers(Manager *m, char **controllers) {
return 0;
}
+int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) {
+ int i;
+
+ assert(m);
+
+ for (i = 0; i < RLIMIT_NLIMITS; i++) {
+ if (!default_rlimit[i])
+ continue;
+
+ m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1);
+ if (!m->rlimit[i])
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
void manager_recheck_journal(Manager *m) {
Unit *u;
assert(m);
- if (m->running_as != MANAGER_SYSTEM)
+ if (m->running_as != SYSTEMD_SYSTEM)
return;
u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET);
void manager_set_show_status(Manager *m, bool b) {
assert(m);
- if (m->running_as != MANAGER_SYSTEM)
+ if (m->running_as != SYSTEMD_SYSTEM)
return;
m->show_status = b;
bool manager_get_show_status(Manager *m) {
assert(m);
- if (m->running_as != MANAGER_SYSTEM)
+ if (m->running_as != SYSTEMD_SYSTEM)
return false;
if (m->show_status)
return plymouth_running();
}
-
-static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
- [MANAGER_SYSTEM] = "system",
- [MANAGER_USER] = "user"
-};
-
-DEFINE_STRING_TABLE_LOOKUP(manager_running_as, ManagerRunningAs);