X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fmanager.c;h=e4d03681ab089a06a0d278c90ae8c7aef5927ac4;hp=91c3d59d2b1f75394f119e1b956b85c292fe5f42;hb=517d56b1d0f67dcf76710bc1e17b05518b8cabe6;hpb=43d03a83766a0d63f535e2afa6aeb6e6acbe83b2 diff --git a/src/core/manager.c b/src/core/manager.c index 91c3d59d2..e4d03681a 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -80,8 +80,8 @@ #define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC) /* Initial delay and the interval for printing status messages about running jobs */ -#define JOBS_IN_PROGRESS_WAIT_SEC 5 -#define JOBS_IN_PROGRESS_PERIOD_SEC 1 +#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) +#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3) #define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3 /* Where clients shall send notification messages to */ @@ -97,12 +97,15 @@ static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t use static int manager_dispatch_run_queue(sd_event_source *source, void *userdata); static int manager_watch_jobs_in_progress(Manager *m) { + usec_t next; + assert(m); if (m->jobs_in_progress_event_source) return 0; - return sd_event_add_monotonic(m->event, JOBS_IN_PROGRESS_WAIT_SEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source); + next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC; + return sd_event_add_monotonic(m->event, &m->jobs_in_progress_event_source, next, 0, manager_dispatch_jobs_in_progress, m); } #define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1)) @@ -136,6 +139,16 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po } } +void manager_flip_auto_status(Manager *m, bool enable) { + if (enable) { + if (m->show_status == SHOW_STATUS_AUTO) + manager_set_show_status(m, SHOW_STATUS_TEMPORARY); + } else { + if (m->show_status == SHOW_STATUS_TEMPORARY) + manager_set_show_status(m, SHOW_STATUS_AUTO); + } +} + static void manager_print_jobs_in_progress(Manager *m) { _cleanup_free_ char *job_of_n = NULL; Iterator i; @@ -143,9 +156,13 @@ static void manager_print_jobs_in_progress(Manager *m) { unsigned counter = 0, print_nr; char cylon[6 + CYLON_BUFFER_EXTRA + 1]; unsigned cylon_pos; + char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit"; + uint64_t x; assert(m); + manager_flip_auto_status(m, true); + print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs; HASHMAP_FOREACH(j, m->jobs, i) @@ -162,14 +179,23 @@ static void manager_print_jobs_in_progress(Manager *m) { cylon_pos = 14 - cylon_pos; draw_cylon(cylon, sizeof(cylon), 6, cylon_pos); + m->jobs_in_progress_iteration++; + if (m->n_running_jobs > 1) if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0) job_of_n = NULL; - manager_status_printf(m, true, cylon, "%sA %s job is running for %s", - strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit)); + format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC); + if (job_get_timeout(j, &x) > 0) + format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC); + + manager_status_printf(m, true, cylon, + "%sA %s job is running for %s (%s / %s)", + strempty(job_of_n), + job_type_to_string(j->type), + unit_description(j->unit), + time, limit); - m->jobs_in_progress_iteration++; } static int manager_watch_idle_pipe(Manager *m) { @@ -183,7 +209,7 @@ static int manager_watch_idle_pipe(Manager *m) { if (m->idle_pipe[2] < 0) return 0; - r = sd_event_add_io(m->event, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m, &m->idle_pipe_event_source); + r = sd_event_add_io(m->event, &m->idle_pipe_event_source, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m); if (r < 0) { log_error("Failed to watch idle pipe: %s", strerror(-r)); return r; @@ -227,7 +253,7 @@ static int manager_setup_time_change(Manager *m) { return 0; } - r = sd_event_add_io(m->event, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m, &m->time_change_event_source); + r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m); if (r < 0) { log_error("Failed to create time change event source: %s", strerror(-r)); return r; @@ -314,7 +340,7 @@ static int manager_setup_signals(Manager *m) { if (m->signal_fd < 0) return -errno; - r = sd_event_add_io(m->event, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m, &m->signal_event_source); + r = sd_event_add_io(m->event, &m->signal_event_source, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m); if (r < 0) return r; @@ -332,6 +358,23 @@ static int manager_setup_signals(Manager *m) { return 0; } +static void manager_clean_environment(Manager *m) { + assert(m); + + /* Let's remove some environment variables that we + * need ourselves to communicate with our clients */ + strv_env_unset_many( + m->environment, + "NOTIFY_SOCKET", + "MAINPID", + "MANAGERPID", + "LISTEN_PID", + "LISTEN_FDS", + "WATCHDOG_PID", + "WATCHDOG_USEC", + NULL); +} + static int manager_default_environment(Manager *m) { assert(m); @@ -352,24 +395,12 @@ static int manager_default_environment(Manager *m) { /* The user manager passes its own environment * along to its children. */ m->environment = strv_copy(environ); - - /* Let's remove some environment variables that we - * need ourselves to communicate with our clients */ - strv_env_unset_many( - m->environment, - "NOTIFY_SOCKET", - "MAINPID", - "MANAGERPID", - "LISTEN_PID", - "LISTEN_FDS", - "WATCHDOG_PID", - "WATCHDOG_USEC", - NULL); } if (!m->environment) return -ENOMEM; + manager_clean_environment(m); strv_sort(m->environment); return 0; @@ -416,10 +447,6 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) { if (r < 0) goto fail; - r = hashmap_ensure_allocated(&m->watch_pids, trivial_hash_func, trivial_compare_func); - if (r < 0) - goto fail; - r = hashmap_ensure_allocated(&m->watch_bus, string_hash_func, string_compare_func); if (r < 0) goto fail; @@ -428,7 +455,7 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) { if (r < 0) goto fail; - r = sd_event_add_defer(m->event, manager_dispatch_run_queue, m, &m->run_queue_event_source); + r = sd_event_add_defer(m->event, &m->run_queue_event_source, manager_dispatch_run_queue, m); if (r < 0) goto fail; @@ -525,7 +552,7 @@ static int manager_setup_notify(Manager *m) { } if (!m->notify_event_source) { - r = sd_event_add_io(m->event, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m, &m->notify_event_source); + r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m); if (r < 0) { log_error("Failed to allocate notify event source: %s", strerror(-r)); return -errno; @@ -567,7 +594,7 @@ static int manager_setup_kdbus(Manager *m) { * necessary to ensure that users cannot get access to busses * of virtualized users when no UID namespacing is used. */ if (m->running_as == SYSTEMD_SYSTEM) - mkdir_p_label("/dev/kdbus/ns", 0700); + mkdir_p_label("/dev/kdbus/domain", 0700); #endif return 0; @@ -747,7 +774,8 @@ void manager_free(Manager *m) { hashmap_free(m->units); hashmap_free(m->jobs); - hashmap_free(m->watch_pids); + hashmap_free(m->watch_pids1); + hashmap_free(m->watch_pids2); hashmap_free(m->watch_bus); sd_event_source_unref(m->signal_event_source); @@ -782,7 +810,7 @@ void manager_free(Manager *m) { free(m->switch_root); free(m->switch_root_init); - for (i = 0; i < RLIMIT_NLIMITS; i++) + for (i = 0; i < _RLIMIT_MAX; i++) free(m->rlimit[i]); assert(hashmap_isempty(m->units_requiring_mounts_for)); @@ -811,7 +839,7 @@ int manager_enumerate(Manager *m) { } static int manager_coldplug(Manager *m) { - int r = 0, q; + int r = 0; Iterator i; Unit *u; char *k; @@ -820,12 +848,14 @@ static int manager_coldplug(Manager *m) { /* Then, let's set up their initial state. */ HASHMAP_FOREACH_KEY(u, k, m->units, i) { + int q; /* ignore aliases */ if (u->id != k) continue; - if ((q = unit_coldplug(u)) < 0) + q = unit_coldplug(u); + if (q < 0) r = q; } @@ -968,6 +998,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { * didn't, then let's create the bus now. */ manager_setup_kdbus(m); manager_connect_bus(m, !!serialization); + bus_track_coldplug(m, &m->subscribed, &m->deserialized_subscribed); /* Third, fire things up! */ q = manager_coldplug(m); @@ -1288,6 +1319,26 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) { return n; } +static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n) { + _cleanup_strv_free_ char **tags = NULL; + + assert(m); + assert(u); + assert(buf); + assert(n > 0); + + tags = strv_split(buf, "\n\r"); + if (!tags) { + log_oom(); + return; + } + + log_debug_unit(u->id, "Got notification message for unit %s", u->id); + + if (UNIT_VTABLE(u)->notify_message) + UNIT_VTABLE(u)->notify_message(u, pid, tags); +} + static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { Manager *m = userdata; ssize_t n; @@ -1306,6 +1357,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t .iov_base = buf, .iov_len = sizeof(buf)-1, }; + bool found = false; union { struct cmsghdr cmsghdr; @@ -1320,7 +1372,6 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t }; struct ucred *ucred; Unit *u; - _cleanup_strv_free_ char **tags = NULL; n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT); if (n <= 0) { @@ -1343,36 +1394,50 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); - u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid)); - if (!u) { - u = manager_get_unit_by_pid(m, ucred->pid); - if (!u) { - log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); - continue; - } - } - assert((size_t) n < sizeof(buf)); buf[n] = 0; - tags = strv_split(buf, "\n\r"); - if (!tags) - return log_oom(); - log_debug_unit(u->id, "Got notification message for unit %s", u->id); + u = manager_get_unit_by_pid(m, ucred->pid); + if (u) { + manager_invoke_notify_message(m, u, ucred->pid, buf, n); + found = true; + } + + u = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid)); + if (u) { + manager_invoke_notify_message(m, u, ucred->pid, buf, n); + found = true; + } + + u = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid)); + if (u) { + manager_invoke_notify_message(m, u, ucred->pid, buf, n); + found = true; + } - if (UNIT_VTABLE(u)->notify_message) - UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags); + if (!found) + log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); } return 0; } +static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) { + assert(m); + assert(u); + assert(si); + + log_debug_unit(u->id, "Child "PID_FMT" belongs to %s", si->si_pid, u->id); + + unit_unwatch_pid(u, si->si_pid); + UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status); +} + static int manager_dispatch_sigchld(Manager *m) { assert(m); for (;;) { siginfo_t si = {}; - Unit *u; /* First we call waitd() for a PID and do not reap the * zombie. That way we can still access /proc/$PID for @@ -1393,15 +1458,30 @@ static int manager_dispatch_sigchld(Manager *m) { if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) { _cleanup_free_ char *name = NULL; + Unit *u; get_process_comm(si.si_pid, &name); - log_debug("Got SIGCHLD for process "PID_FMT" (%s)", si.si_pid, strna(name)); - } - /* And now figure out the unit this belongs to */ - u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid)); - if (!u) + log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)", + si.si_pid, strna(name), + sigchld_code_to_string(si.si_code), + si.si_status, + strna(si.si_code == CLD_EXITED + ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) + : signal_to_string(si.si_status))); + + /* And now figure out the unit this belongs + * to, it might be multiple... */ u = manager_get_unit_by_pid(m, si.si_pid); + if (u) + invoke_sigchld_event(m, u, &si); + u = hashmap_get(m->watch_pids1, LONG_TO_PTR(si.si_pid)); + if (u) + invoke_sigchld_event(m, u, &si); + u = hashmap_get(m->watch_pids2, LONG_TO_PTR(si.si_pid)); + if (u) + invoke_sigchld_event(m, u, &si); + } /* And now, we actually reap the zombie. */ if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) { @@ -1410,26 +1490,6 @@ static int manager_dispatch_sigchld(Manager *m) { return -errno; } - - if (si.si_code != CLD_EXITED && si.si_code != CLD_KILLED && si.si_code != CLD_DUMPED) - continue; - - log_debug("Child %lu died (code=%s, status=%i/%s)", - (long unsigned) si.si_pid, - sigchld_code_to_string(si.si_code), - si.si_status, - strna(si.si_code == CLD_EXITED - ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) - : signal_to_string(si.si_status))); - - if (!u) - continue; - - log_debug_unit(u->id, - "Child %lu belongs to %s", (long unsigned) si.si_pid, u->id); - - hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid)); - UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status); } return 0; @@ -1475,23 +1535,10 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t return -errno; } - if (sfsi.ssi_pid > 0) { - _cleanup_free_ char *p = NULL; - - get_process_comm(sfsi.ssi_pid, &p); - - log_full(sfsi.ssi_signo == SIGCHLD || - (sfsi.ssi_signo == SIGTERM && m->running_as == SYSTEMD_USER) - ? LOG_DEBUG : LOG_INFO, - "Received SIG%s from PID "PID_FMT" (%s).", - signal_to_string(sfsi.ssi_signo), - sfsi.ssi_pid, strna(p)); - } else - log_full(sfsi.ssi_signo == SIGCHLD || - (sfsi.ssi_signo == SIGTERM && m->running_as == SYSTEMD_USER) - ? LOG_DEBUG : LOG_INFO, - "Received SIG%s.", - signal_to_string(sfsi.ssi_signo)); + log_received_signal(sfsi.ssi_signo == SIGCHLD || + (sfsi.ssi_signo == SIGTERM && m->running_as == SYSTEMD_USER) + ? LOG_DEBUG : LOG_INFO, + &sfsi); switch (sfsi.ssi_signo) { @@ -1621,12 +1668,12 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t case 20: log_debug("Enabling showing of status."); - manager_set_show_status(m, true); + manager_set_show_status(m, SHOW_STATUS_YES); break; case 21: log_debug("Disabling showing of status."); - manager_set_show_status(m, false); + manager_set_show_status(m, SHOW_STATUS_NO); break; case 22: @@ -1725,11 +1772,20 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32 static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) { Manager *m = userdata; + int r; + uint64_t next; assert(m); + assert(source); manager_print_jobs_in_progress(m); - return 0; + + next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC; + r = sd_event_source_set_time(source, next); + if (r < 0) + return r; + + return sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); } int manager_loop(Manager *m) { @@ -1850,7 +1906,7 @@ int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) { void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { #ifdef HAVE_AUDIT - char *p; + _cleanup_free_ char *p = NULL; int audit_fd; audit_fd = get_audit_fd(); @@ -1883,17 +1939,19 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { } else log_warning("Failed to send audit message: %m"); } - - free(p); #endif } void manager_send_unit_plymouth(Manager *m, Unit *u) { - int fd = -1; - union sockaddr_union sa; + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "\0/org/freedesktop/plymouthd", + }; + int n = 0; - char *message = NULL; + _cleanup_free_ char *message = NULL; + _cleanup_close_ int fd = -1; /* Don't generate plymouth events if the service was already * started and we're just deserializing */ @@ -1919,46 +1977,22 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) { return; } - zero(sa); - sa.sa.sa_family = AF_UNIX; - strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1); if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) { - if (errno != EPIPE && - errno != EAGAIN && - errno != ENOENT && - errno != ECONNREFUSED && - errno != ECONNRESET && - errno != ECONNABORTED) + if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) log_error("connect() failed: %m"); - - goto finish; + return; } if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { log_oom(); - goto finish; + return; } errno = 0; - if (write(fd, message, n + 1) != n + 1) { - - if (errno != EPIPE && - errno != EAGAIN && - errno != ENOENT && - errno != ECONNREFUSED && - errno != ECONNRESET && - errno != ECONNABORTED) + if (write(fd, message, n + 1) != n + 1) + if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED)) log_error("Failed to write Plymouth message: %m"); - - goto finish; - } - -finish: - if (fd >= 0) - close_nointr_nofail(fd); - - free(message); } void manager_dispatch_bus_name_owner_changed( @@ -1980,28 +2014,17 @@ void manager_dispatch_bus_name_owner_changed( } int manager_open_serialization(Manager *m, FILE **_f) { - _cleanup_free_ char *path = NULL; + const char *path; int fd = -1; FILE *f; assert(_f); - if (m->running_as == SYSTEMD_SYSTEM) - asprintf(&path, "/run/systemd/dump-"PID_FMT"-XXXXXX", getpid()); - else - asprintf(&path, "/tmp/systemd-dump-"PID_FMT"-XXXXXX", getpid()); - - if (!path) - return -ENOMEM; - - RUN_WITH_UMASK(0077) { - fd = mkostemp(path, O_RDWR|O_CLOEXEC); - } - + path = m->running_as == SYSTEMD_SYSTEM ? "/run/systemd" : "/tmp"; + fd = open_tmpfile(path, O_RDWR|O_CLOEXEC); if (fd < 0) return -errno; - unlink(path); log_debug("Serializing state to %s", path); f = fdopen(fd, "w+"); @@ -2082,7 +2105,7 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { fprintf(f, "kdbus-fd=%i\n", copy); } - bus_serialize(m, f); + bus_track_serialize(m->subscribed, f); fputc('\n', f); @@ -2259,7 +2282,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { m->kdbus_fd = fdset_remove(fds, fd); } - } else if (bus_deserialize_item(m, l) == 0) + } else if (bus_track_deserialize_item(&m->deserialized_subscribed, l) == 0) log_debug("Unknown serialization item '%s'", l); } @@ -2435,11 +2458,15 @@ void manager_check_finished(Manager *m) { m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source); if (hashmap_size(m->jobs) > 0) { - if (m->jobs_in_progress_event_source) - sd_event_source_set_time(m->jobs_in_progress_event_source, JOBS_IN_PROGRESS_PERIOD_SEC); + if (m->jobs_in_progress_event_source) { + uint64_t next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC; + sd_event_source_set_time(m->jobs_in_progress_event_source, next); + } return; } + manager_flip_auto_status(m, false); + /* Notify Type=idle units that we are done now */ m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); manager_close_idle_pipe(m); @@ -2689,7 +2716,10 @@ int manager_environment_add(Manager *m, char **minus, char **plus) { if (b != l) strv_free(b); - m->environment = strv_sort(l); + m->environment = l; + manager_clean_environment(m); + strv_sort(m->environment); + return 0; } @@ -2698,7 +2728,7 @@ int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { assert(m); - for (i = 0; i < RLIMIT_NLIMITS; i++) { + for (i = 0; i < _RLIMIT_MAX; i++) { if (!default_rlimit[i]) continue; @@ -2735,15 +2765,16 @@ void manager_recheck_journal(Manager *m) { log_open(); } -void manager_set_show_status(Manager *m, bool b) { +void manager_set_show_status(Manager *m, ShowStatus mode) { assert(m); + assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY)); if (m->running_as != SYSTEMD_SYSTEM) return; - m->show_status = b; + m->show_status = mode; - if (b) + if (mode > 0) touch("/run/systemd/show-status"); else unlink("/run/systemd/show-status"); @@ -2758,7 +2789,7 @@ static bool manager_get_show_status(Manager *m) { if (m->no_console_output) return false; - if (m->show_status) + if (m->show_status > 0) return true; /* If Plymouth is running make sure we show the status, so @@ -2820,3 +2851,10 @@ Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); } + +const char *manager_get_runtime_prefix(Manager *m) { + + return m->running_as == SYSTEMD_SYSTEM ? + "/run" : + getenv("XDG_RUNTIME_DIR"); +}