+void manager_reset_failed(Manager *m) {
+ Unit *u;
+ Iterator i;
+
+ assert(m);
+
+ HASHMAP_FOREACH(u, m->units, i)
+ unit_reset_failed(u);
+}
+
+bool manager_unit_pending_inactive(Manager *m, const char *name) {
+ Unit *u;
+
+ assert(m);
+ assert(name);
+
+ /* Returns true if the unit is inactive or going down */
+ if (!(u = manager_get_unit(m, name)))
+ return true;
+
+ return unit_pending_inactive(u);
+}
+
+void manager_check_finished(Manager *m) {
+ char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
+
+ assert(m);
+
+ if (dual_timestamp_is_set(&m->finish_timestamp))
+ return;
+
+ if (hashmap_size(m->jobs) > 0)
+ return;
+
+ dual_timestamp_get(&m->finish_timestamp);
+
+ if (m->running_as == MANAGER_SYSTEM) {
+ 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),
+ m->initrd_timestamp.monotonic),
+ format_timespan(initrd, sizeof(initrd),
+ m->startup_timestamp.monotonic - m->initrd_timestamp.monotonic),
+ format_timespan(userspace, sizeof(userspace),
+ m->finish_timestamp.monotonic - m->startup_timestamp.monotonic),
+ format_timespan(sum, sizeof(sum),
+ m->finish_timestamp.monotonic));
+ } else
+ log_info("Startup finished in %s (kernel) + %s (userspace) = %s.",
+ format_timespan(kernel, sizeof(kernel),
+ m->startup_timestamp.monotonic),
+ format_timespan(userspace, sizeof(userspace),
+ m->finish_timestamp.monotonic - m->startup_timestamp.monotonic),
+ format_timespan(sum, sizeof(sum),
+ m->finish_timestamp.monotonic));
+ } else
+ log_debug("Startup finished in %s.",
+ format_timespan(userspace, sizeof(userspace),
+ m->finish_timestamp.monotonic - m->startup_timestamp.monotonic));
+
+}
+
+void manager_run_generators(Manager *m) {
+ DIR *d = NULL;
+ const char *generator_path;
+ const char *argv[3];
+
+ assert(m);
+
+ generator_path = m->running_as == MANAGER_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
+ if (!(d = opendir(generator_path))) {
+
+ if (errno == ENOENT)
+ return;
+
+ log_error("Failed to enumerate generator directory: %m");
+ return;
+ }
+
+ if (!m->generator_unit_path) {
+ char *p;
+ char system_path[] = "/dev/.systemd/generator-XXXXXX",
+ user_path[] = "/tmp/systemd-generator-XXXXXX";
+
+ if (!(p = mkdtemp(m->running_as == MANAGER_SYSTEM ? system_path : user_path))) {
+ log_error("Failed to generate generator directory: %m");
+ goto finish;
+ }
+
+ if (!(m->generator_unit_path = strdup(p))) {
+ log_error("Failed to allocate generator unit path.");
+ goto finish;
+ }
+ }
+
+ argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
+ argv[1] = m->generator_unit_path;
+ argv[2] = NULL;
+
+ execute_directory(generator_path, d, (char**) argv);
+
+ 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);
+ }
+
+finish:
+ if (d)
+ closedir(d);
+}
+
+void manager_undo_generators(Manager *m) {
+ assert(m);
+
+ if (!m->generator_unit_path)
+ return;
+
+ strv_remove(m->lookup_paths.unit_path, m->generator_unit_path);
+ rm_rf(m->generator_unit_path, false, true);
+
+ free(m->generator_unit_path);
+ m->generator_unit_path = NULL;
+}
+
+int manager_set_default_controllers(Manager *m, char **controllers) {
+ char **l;
+
+ assert(m);
+
+ if (!(l = strv_copy(controllers)))
+ return -ENOMEM;
+
+ strv_free(m->default_controllers);
+ m->default_controllers = l;
+
+ return 0;
+}
+