1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/epoll.h>
26 #include <sys/timerfd.h>
33 #include "sd-messages.h"
38 #include "path-util.h"
39 #include "load-fragment.h"
40 #include "load-dropin.h"
42 #include "unit-name.h"
43 #include "dbus-unit.h"
45 #include "cgroup-util.h"
49 #include "fileio-label.h"
50 #include "bus-errors.h"
53 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
54 [UNIT_SERVICE] = &service_vtable,
55 [UNIT_TIMER] = &timer_vtable,
56 [UNIT_SOCKET] = &socket_vtable,
57 [UNIT_TARGET] = &target_vtable,
58 [UNIT_DEVICE] = &device_vtable,
59 [UNIT_MOUNT] = &mount_vtable,
60 [UNIT_AUTOMOUNT] = &automount_vtable,
61 [UNIT_SNAPSHOT] = &snapshot_vtable,
62 [UNIT_SWAP] = &swap_vtable,
63 [UNIT_PATH] = &path_vtable,
64 [UNIT_SLICE] = &slice_vtable,
65 [UNIT_SCOPE] = &scope_vtable
68 Unit *unit_new(Manager *m, size_t size) {
72 assert(size >= sizeof(Unit));
78 u->names = set_new(string_hash_func, string_compare_func);
85 u->type = _UNIT_TYPE_INVALID;
86 u->deserialized_job = _JOB_TYPE_INVALID;
87 u->default_dependencies = true;
88 u->unit_file_state = _UNIT_FILE_STATE_INVALID;
93 bool unit_has_name(Unit *u, const char *name) {
97 return !!set_get(u->names, (char*) name);
100 int unit_add_name(Unit *u, const char *text) {
108 if (unit_name_is_template(text)) {
112 s = unit_name_replace_instance(text, u->instance);
119 if (!unit_name_is_valid(s, false)) {
124 assert_se((t = unit_name_to_type(s)) >= 0);
126 if (u->type != _UNIT_TYPE_INVALID && t != u->type) {
131 r = unit_name_to_instance(s, &i);
135 if (i && unit_vtable[t]->no_instances) {
140 /* Ensure that this unit is either instanced or not instanced,
142 if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) {
147 if (unit_vtable[t]->no_alias &&
148 !set_isempty(u->names) &&
149 !set_get(u->names, s)) {
154 if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) {
159 r = set_put(u->names, s);
166 r = hashmap_put(u->manager->units, s, u);
168 set_remove(u->names, s);
172 if (u->type == _UNIT_TYPE_INVALID) {
178 LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u);
180 if (UNIT_VTABLE(u)->init)
181 UNIT_VTABLE(u)->init(u);
185 unit_add_to_dbus_queue(u);
195 int unit_choose_id(Unit *u, const char *name) {
197 _cleanup_free_ char *t = NULL;
203 if (unit_name_is_template(name)) {
208 t = unit_name_replace_instance(name, u->instance);
215 /* Selects one of the names of this unit as the id */
216 s = set_get(u->names, (char*) name);
221 r = unit_name_to_instance(s, &i);
230 unit_add_to_dbus_queue(u);
235 int unit_set_description(Unit *u, const char *description) {
240 if (isempty(description))
243 s = strdup(description);
248 free(u->description);
251 unit_add_to_dbus_queue(u);
255 bool unit_check_gc(Unit *u) {
258 if (u->load_state == UNIT_STUB)
261 if (UNIT_VTABLE(u)->no_gc)
273 if (unit_active_state(u) != UNIT_INACTIVE)
279 if (UNIT_VTABLE(u)->check_gc)
280 if (UNIT_VTABLE(u)->check_gc(u))
286 void unit_add_to_load_queue(Unit *u) {
288 assert(u->type != _UNIT_TYPE_INVALID);
290 if (u->load_state != UNIT_STUB || u->in_load_queue)
293 LIST_PREPEND(load_queue, u->manager->load_queue, u);
294 u->in_load_queue = true;
297 void unit_add_to_cleanup_queue(Unit *u) {
300 if (u->in_cleanup_queue)
303 LIST_PREPEND(cleanup_queue, u->manager->cleanup_queue, u);
304 u->in_cleanup_queue = true;
307 void unit_add_to_gc_queue(Unit *u) {
310 if (u->in_gc_queue || u->in_cleanup_queue)
313 if (unit_check_gc(u))
316 LIST_PREPEND(gc_queue, u->manager->gc_queue, u);
317 u->in_gc_queue = true;
319 u->manager->n_in_gc_queue ++;
322 void unit_add_to_dbus_queue(Unit *u) {
324 assert(u->type != _UNIT_TYPE_INVALID);
326 if (u->load_state == UNIT_STUB || u->in_dbus_queue)
329 /* Shortcut things if nobody cares */
330 if (set_isempty(u->manager->subscribed)) {
331 u->sent_dbus_new_signal = true;
335 LIST_PREPEND(dbus_queue, u->manager->dbus_unit_queue, u);
336 u->in_dbus_queue = true;
339 static void bidi_set_free(Unit *u, Set *s) {
345 /* Frees the set and makes sure we are dropped from the
346 * inverse pointers */
348 SET_FOREACH(other, s, i) {
351 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
352 set_remove(other->dependencies[d], u);
354 unit_add_to_gc_queue(other);
360 static void unit_remove_transient(Unit *u) {
368 if (u->fragment_path)
369 unlink(u->fragment_path);
371 STRV_FOREACH(i, u->dropin_paths) {
372 _cleanup_free_ char *p = NULL;
377 r = path_get_parent(*i, &p);
383 static void unit_free_requires_mounts_for(Unit *u) {
386 STRV_FOREACH(j, u->requires_mounts_for) {
387 char s[strlen(*j) + 1];
389 PATH_FOREACH_PREFIX_MORE(s, *j) {
393 x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y);
399 if (set_isempty(x)) {
400 hashmap_remove(u->manager->units_requiring_mounts_for, y);
407 strv_free(u->requires_mounts_for);
408 u->requires_mounts_for = NULL;
411 void unit_free(Unit *u) {
418 if (u->manager->n_reloading <= 0)
419 unit_remove_transient(u);
421 bus_unit_send_removed_signal(u);
423 if (u->load_state != UNIT_STUB)
424 if (UNIT_VTABLE(u)->done)
425 UNIT_VTABLE(u)->done(u);
427 unit_free_requires_mounts_for(u);
429 SET_FOREACH(t, u->names, i)
430 hashmap_remove_value(u->manager->units, t, u);
444 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
445 bidi_set_free(u, u->dependencies[d]);
447 if (u->type != _UNIT_TYPE_INVALID)
448 LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u);
450 if (u->in_load_queue)
451 LIST_REMOVE(load_queue, u->manager->load_queue, u);
453 if (u->in_dbus_queue)
454 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
456 if (u->in_cleanup_queue)
457 LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
459 if (u->in_gc_queue) {
460 LIST_REMOVE(gc_queue, u->manager->gc_queue, u);
461 u->manager->n_in_gc_queue--;
464 if (u->in_cgroup_queue)
465 LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u);
467 if (u->cgroup_path) {
468 hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
469 free(u->cgroup_path);
472 free(u->description);
473 strv_free(u->documentation);
474 free(u->fragment_path);
475 free(u->source_path);
476 strv_free(u->dropin_paths);
479 set_free_free(u->names);
481 condition_free_list(u->conditions);
483 unit_ref_unset(&u->slice);
486 unit_ref_unset(u->refs);
491 UnitActiveState unit_active_state(Unit *u) {
494 if (u->load_state == UNIT_MERGED)
495 return unit_active_state(unit_follow_merge(u));
497 /* After a reload it might happen that a unit is not correctly
498 * loaded but still has a process around. That's why we won't
499 * shortcut failed loading to UNIT_INACTIVE_FAILED. */
501 return UNIT_VTABLE(u)->active_state(u);
504 const char* unit_sub_state_to_string(Unit *u) {
507 return UNIT_VTABLE(u)->sub_state_to_string(u);
510 static void complete_move(Set **s, Set **other) {
518 set_move(*s, *other);
525 static void merge_names(Unit *u, Unit *other) {
532 complete_move(&u->names, &other->names);
534 set_free_free(other->names);
538 SET_FOREACH(t, u->names, i)
539 assert_se(hashmap_replace(u->manager->units, t, u) == 0);
542 static void merge_dependencies(Unit *u, Unit *other, UnitDependency d) {
549 assert(d < _UNIT_DEPENDENCY_MAX);
551 /* Fix backwards pointers */
552 SET_FOREACH(back, other->dependencies[d], i) {
555 for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) {
556 r = set_remove_and_put(back->dependencies[k], other, u);
558 set_remove(back->dependencies[k], other);
560 assert(r >= 0 || r == -ENOENT);
564 complete_move(&u->dependencies[d], &other->dependencies[d]);
566 set_free(other->dependencies[d]);
567 other->dependencies[d] = NULL;
570 int unit_merge(Unit *u, Unit *other) {
575 assert(u->manager == other->manager);
576 assert(u->type != _UNIT_TYPE_INVALID);
578 other = unit_follow_merge(other);
583 if (u->type != other->type)
586 if (!u->instance != !other->instance)
589 if (other->load_state != UNIT_STUB &&
590 other->load_state != UNIT_NOT_FOUND)
599 if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other)))
603 merge_names(u, other);
605 /* Redirect all references */
607 unit_ref_set(other->refs, u);
609 /* Merge dependencies */
610 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++)
611 merge_dependencies(u, other, d);
613 other->load_state = UNIT_MERGED;
614 other->merged_into = u;
616 /* If there is still some data attached to the other node, we
617 * don't need it anymore, and can free it. */
618 if (other->load_state != UNIT_STUB)
619 if (UNIT_VTABLE(other)->done)
620 UNIT_VTABLE(other)->done(other);
622 unit_add_to_dbus_queue(u);
623 unit_add_to_cleanup_queue(other);
628 int unit_merge_by_name(Unit *u, const char *name) {
631 _cleanup_free_ char *s = NULL;
636 if (unit_name_is_template(name)) {
640 s = unit_name_replace_instance(name, u->instance);
647 other = manager_get_unit(u->manager, name);
649 r = unit_add_name(u, name);
651 r = unit_merge(u, other);
656 Unit* unit_follow_merge(Unit *u) {
659 while (u->load_state == UNIT_MERGED)
660 assert_se(u = u->merged_into);
665 int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
671 if (c->std_output != EXEC_OUTPUT_KMSG &&
672 c->std_output != EXEC_OUTPUT_SYSLOG &&
673 c->std_output != EXEC_OUTPUT_JOURNAL &&
674 c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
675 c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
676 c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
677 c->std_error != EXEC_OUTPUT_KMSG &&
678 c->std_error != EXEC_OUTPUT_SYSLOG &&
679 c->std_error != EXEC_OUTPUT_JOURNAL &&
680 c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
681 c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
682 c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
685 /* If syslog or kernel logging is requested, make sure our own
686 * logging daemon is run first. */
688 if (u->manager->running_as == SYSTEMD_SYSTEM) {
689 r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, NULL, true);
697 const char *unit_description(Unit *u) {
701 return u->description;
706 void unit_dump(Unit *u, FILE *f, const char *prefix) {
710 _cleanup_free_ char *p2 = NULL;
713 timestamp1[FORMAT_TIMESTAMP_MAX],
714 timestamp2[FORMAT_TIMESTAMP_MAX],
715 timestamp3[FORMAT_TIMESTAMP_MAX],
716 timestamp4[FORMAT_TIMESTAMP_MAX],
717 timespan[FORMAT_TIMESPAN_MAX];
721 assert(u->type >= 0);
725 p2 = strappend(prefix, "\t");
726 prefix2 = p2 ? p2 : prefix;
730 "%s\tDescription: %s\n"
732 "%s\tUnit Load State: %s\n"
733 "%s\tUnit Active State: %s\n"
734 "%s\tInactive Exit Timestamp: %s\n"
735 "%s\tActive Enter Timestamp: %s\n"
736 "%s\tActive Exit Timestamp: %s\n"
737 "%s\tInactive Enter Timestamp: %s\n"
738 "%s\tGC Check Good: %s\n"
739 "%s\tNeed Daemon Reload: %s\n"
740 "%s\tTransient: %s\n"
743 "%s\tCGroup realized: %s\n"
744 "%s\tCGroup mask: 0x%x\n",
746 prefix, unit_description(u),
747 prefix, strna(u->instance),
748 prefix, unit_load_state_to_string(u->load_state),
749 prefix, unit_active_state_to_string(unit_active_state(u)),
750 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)),
751 prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)),
752 prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)),
753 prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)),
754 prefix, yes_no(unit_check_gc(u)),
755 prefix, yes_no(unit_need_daemon_reload(u)),
756 prefix, yes_no(u->transient),
757 prefix, strna(unit_slice_name(u)),
758 prefix, strna(u->cgroup_path),
759 prefix, yes_no(u->cgroup_realized),
760 prefix, u->cgroup_mask);
762 SET_FOREACH(t, u->names, i)
763 fprintf(f, "%s\tName: %s\n", prefix, t);
765 STRV_FOREACH(j, u->documentation)
766 fprintf(f, "%s\tDocumentation: %s\n", prefix, *j);
768 if ((following = unit_following(u)))
769 fprintf(f, "%s\tFollowing: %s\n", prefix, following->id);
771 if (u->fragment_path)
772 fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path);
775 fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path);
777 STRV_FOREACH(j, u->dropin_paths)
778 fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
780 if (u->job_timeout > 0)
781 fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
783 condition_dump_list(u->conditions, f, prefix);
785 if (dual_timestamp_is_set(&u->condition_timestamp))
787 "%s\tCondition Timestamp: %s\n"
788 "%s\tCondition Result: %s\n",
789 prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)),
790 prefix, yes_no(u->condition_result));
792 for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
795 SET_FOREACH(other, u->dependencies[d], i)
796 fprintf(f, "%s\t%s: %s\n", prefix, unit_dependency_to_string(d), other->id);
799 if (!strv_isempty(u->requires_mounts_for)) {
801 "%s\tRequiresMountsFor:", prefix);
803 STRV_FOREACH(j, u->requires_mounts_for)
804 fprintf(f, " %s", *j);
809 if (u->load_state == UNIT_LOADED) {
812 "%s\tStopWhenUnneeded: %s\n"
813 "%s\tRefuseManualStart: %s\n"
814 "%s\tRefuseManualStop: %s\n"
815 "%s\tDefaultDependencies: %s\n"
816 "%s\tOnFailureIsolate: %s\n"
817 "%s\tIgnoreOnIsolate: %s\n"
818 "%s\tIgnoreOnSnapshot: %s\n",
819 prefix, yes_no(u->stop_when_unneeded),
820 prefix, yes_no(u->refuse_manual_start),
821 prefix, yes_no(u->refuse_manual_stop),
822 prefix, yes_no(u->default_dependencies),
823 prefix, yes_no(u->on_failure_isolate),
824 prefix, yes_no(u->ignore_on_isolate),
825 prefix, yes_no(u->ignore_on_snapshot));
827 if (UNIT_VTABLE(u)->dump)
828 UNIT_VTABLE(u)->dump(u, f, prefix2);
830 } else if (u->load_state == UNIT_MERGED)
832 "%s\tMerged into: %s\n",
833 prefix, u->merged_into->id);
834 else if (u->load_state == UNIT_ERROR)
835 fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror(-u->load_error));
839 job_dump(u->job, f, prefix2);
842 job_dump(u->nop_job, f, prefix2);
846 /* Common implementation for multiple backends */
847 int unit_load_fragment_and_dropin(Unit *u) {
852 /* Load a .{service,socket,...} file */
853 r = unit_load_fragment(u);
857 if (u->load_state == UNIT_STUB)
860 /* Load drop-in directory data */
861 r = unit_load_dropin(unit_follow_merge(u));
868 /* Common implementation for multiple backends */
869 int unit_load_fragment_and_dropin_optional(Unit *u) {
874 /* Same as unit_load_fragment_and_dropin(), but whether
875 * something can be loaded or not doesn't matter. */
877 /* Load a .service file */
878 r = unit_load_fragment(u);
882 if (u->load_state == UNIT_STUB)
883 u->load_state = UNIT_LOADED;
885 /* Load drop-in directory data */
886 r = unit_load_dropin(unit_follow_merge(u));
893 int unit_add_default_target_dependency(Unit *u, Unit *target) {
897 if (target->type != UNIT_TARGET)
900 /* Only add the dependency if both units are loaded, so that
901 * that loop check below is reliable */
902 if (u->load_state != UNIT_LOADED ||
903 target->load_state != UNIT_LOADED)
906 /* If either side wants no automatic dependencies, then let's
908 if (!u->default_dependencies ||
909 !target->default_dependencies)
912 /* Don't create loops */
913 if (set_get(target->dependencies[UNIT_BEFORE], u))
916 return unit_add_dependency(target, UNIT_AFTER, u, true);
919 static int unit_add_default_dependencies(Unit *u) {
921 static const UnitDependency deps[] = {
923 UNIT_REQUIRED_BY_OVERRIDABLE,
935 for (k = 0; k < ELEMENTSOF(deps); k++)
936 SET_FOREACH(target, u->dependencies[deps[k]], i) {
937 r = unit_add_default_target_dependency(u, target);
942 if (u->default_dependencies && unit_get_cgroup_context(u)) {
943 if (UNIT_ISSET(u->slice))
944 r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true);
946 r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true);
955 static int unit_add_mount_links(Unit *u) {
961 STRV_FOREACH(i, u->requires_mounts_for) {
962 char prefix[strlen(*i) + 1];
964 PATH_FOREACH_PREFIX_MORE(prefix, *i) {
967 r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m);
975 if (m->load_state != UNIT_LOADED)
978 r = unit_add_dependency(u, UNIT_AFTER, m, true);
982 if (m->fragment_path) {
983 r = unit_add_dependency(u, UNIT_REQUIRES, m, true);
993 int unit_load(Unit *u) {
998 if (u->in_load_queue) {
999 LIST_REMOVE(load_queue, u->manager->load_queue, u);
1000 u->in_load_queue = false;
1003 if (u->type == _UNIT_TYPE_INVALID)
1006 if (u->load_state != UNIT_STUB)
1009 if (UNIT_VTABLE(u)->load) {
1010 r = UNIT_VTABLE(u)->load(u);
1015 if (u->load_state == UNIT_STUB) {
1020 if (u->load_state == UNIT_LOADED) {
1022 if (u->default_dependencies) {
1023 r = unit_add_default_dependencies(u);
1028 r = unit_add_mount_links(u);
1032 if (u->on_failure_isolate &&
1033 set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) {
1035 log_error_unit(u->id,
1036 "More than one OnFailure= dependencies specified for %s but OnFailureIsolate= enabled. Refusing.", u->id);
1043 assert((u->load_state != UNIT_MERGED) == !u->merged_into);
1045 unit_add_to_dbus_queue(unit_follow_merge(u));
1046 unit_add_to_gc_queue(u);
1051 u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : UNIT_ERROR;
1053 unit_add_to_dbus_queue(u);
1054 unit_add_to_gc_queue(u);
1056 log_debug_unit(u->id, "Failed to load configuration for %s: %s",
1057 u->id, strerror(-r));
1062 static bool unit_condition_test(Unit *u) {
1065 dual_timestamp_get(&u->condition_timestamp);
1066 u->condition_result = condition_test_list(u->id, u->conditions);
1068 return u->condition_result;
1071 _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) {
1072 const UnitStatusMessageFormats *format_table;
1076 assert(t < _JOB_TYPE_MAX);
1078 if (t != JOB_START && t != JOB_STOP)
1081 format_table = &UNIT_VTABLE(u)->status_message_formats;
1085 return format_table->starting_stopping[t == JOB_STOP];
1088 _pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) {
1093 assert(t < _JOB_TYPE_MAX);
1095 format = unit_get_status_message_format(u, t);
1099 /* Return generic strings */
1101 return "Starting %s.";
1102 else if (t == JOB_STOP)
1103 return "Stopping %s.";
1104 else if (t == JOB_RELOAD)
1105 return "Reloading %s.";
1110 static void unit_status_print_starting_stopping(Unit *u, JobType t) {
1115 /* We only print status messages for selected units on
1116 * selected operations. */
1118 format = unit_get_status_message_format(u, t);
1122 unit_status_printf(u, "", format);
1125 #pragma GCC diagnostic push
1126 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1127 static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) {
1134 if (t != JOB_START && t != JOB_STOP && t != JOB_RELOAD)
1137 if (log_on_console())
1140 /* We log status messages for all units and all operations. */
1142 format = unit_get_status_message_format_try_harder(u, t);
1146 snprintf(buf, sizeof(buf), format, unit_description(u));
1149 mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING :
1150 t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING :
1151 SD_MESSAGE_UNIT_RELOADING;
1153 log_struct_unit(LOG_INFO,
1159 #pragma GCC diagnostic pop
1162 * -EBADR: This unit type does not support starting.
1163 * -EALREADY: Unit is already started.
1164 * -EAGAIN: An operation is already in progress. Retry later.
1165 * -ECANCELED: Too many requests for now.
1167 int unit_start(Unit *u) {
1168 UnitActiveState state;
1173 if (u->load_state != UNIT_LOADED)
1176 /* If this is already started, then this will succeed. Note
1177 * that this will even succeed if this unit is not startable
1178 * by the user. This is relied on to detect when we need to
1179 * wait for units and when waiting is finished. */
1180 state = unit_active_state(u);
1181 if (UNIT_IS_ACTIVE_OR_RELOADING(state))
1184 /* If the conditions failed, don't do anything at all. If we
1185 * already are activating this call might still be useful to
1186 * speed up activation in case there is some hold-off time,
1187 * but we don't want to recheck the condition in that case. */
1188 if (state != UNIT_ACTIVATING &&
1189 !unit_condition_test(u)) {
1190 log_debug_unit(u->id, "Starting of %s requested but condition failed. Ignoring.", u->id);
1194 /* Forward to the main object, if we aren't it. */
1195 following = unit_following(u);
1197 log_debug_unit(u->id, "Redirecting start request from %s to %s.",
1198 u->id, following->id);
1199 return unit_start(following);
1202 unit_status_log_starting_stopping_reloading(u, JOB_START);
1203 unit_status_print_starting_stopping(u, JOB_START);
1205 /* If it is stopped, but we cannot start it, then fail */
1206 if (!UNIT_VTABLE(u)->start)
1209 /* We don't suppress calls to ->start() here when we are
1210 * already starting, to allow this request to be used as a
1211 * "hurry up" call, for example when the unit is in some "auto
1212 * restart" state where it waits for a holdoff timer to elapse
1213 * before it will start again. */
1215 unit_add_to_dbus_queue(u);
1217 return UNIT_VTABLE(u)->start(u);
1220 bool unit_can_start(Unit *u) {
1223 return !!UNIT_VTABLE(u)->start;
1226 bool unit_can_isolate(Unit *u) {
1229 return unit_can_start(u) &&
1234 * -EBADR: This unit type does not support stopping.
1235 * -EALREADY: Unit is already stopped.
1236 * -EAGAIN: An operation is already in progress. Retry later.
1238 int unit_stop(Unit *u) {
1239 UnitActiveState state;
1244 state = unit_active_state(u);
1245 if (UNIT_IS_INACTIVE_OR_FAILED(state))
1248 if ((following = unit_following(u))) {
1249 log_debug_unit(u->id, "Redirecting stop request from %s to %s.",
1250 u->id, following->id);
1251 return unit_stop(following);
1254 unit_status_log_starting_stopping_reloading(u, JOB_STOP);
1255 unit_status_print_starting_stopping(u, JOB_STOP);
1257 if (!UNIT_VTABLE(u)->stop)
1260 unit_add_to_dbus_queue(u);
1262 return UNIT_VTABLE(u)->stop(u);
1266 * -EBADR: This unit type does not support reloading.
1267 * -ENOEXEC: Unit is not started.
1268 * -EAGAIN: An operation is already in progress. Retry later.
1270 int unit_reload(Unit *u) {
1271 UnitActiveState state;
1276 if (u->load_state != UNIT_LOADED)
1279 if (!unit_can_reload(u))
1282 state = unit_active_state(u);
1283 if (state == UNIT_RELOADING)
1286 if (state != UNIT_ACTIVE)
1289 following = unit_following(u);
1291 log_debug_unit(u->id, "Redirecting reload request from %s to %s.",
1292 u->id, following->id);
1293 return unit_reload(following);
1296 unit_status_log_starting_stopping_reloading(u, JOB_RELOAD);
1298 unit_add_to_dbus_queue(u);
1299 return UNIT_VTABLE(u)->reload(u);
1302 bool unit_can_reload(Unit *u) {
1305 if (!UNIT_VTABLE(u)->reload)
1308 if (!UNIT_VTABLE(u)->can_reload)
1311 return UNIT_VTABLE(u)->can_reload(u);
1314 static void unit_check_unneeded(Unit *u) {
1320 /* If this service shall be shut down when unneeded then do
1323 if (!u->stop_when_unneeded)
1326 if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
1329 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
1330 if (unit_active_or_pending(other))
1333 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
1334 if (unit_active_or_pending(other))
1337 SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i)
1338 if (unit_active_or_pending(other))
1341 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
1342 if (unit_active_or_pending(other))
1345 log_info_unit(u->id, "Service %s is not needed anymore. Stopping.", u->id);
1347 /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
1348 manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL);
1351 static void retroactively_start_dependencies(Unit *u) {
1356 assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)));
1358 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
1359 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
1360 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
1361 manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
1363 SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
1364 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
1365 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
1366 manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
1368 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
1369 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
1370 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
1371 manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
1373 SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
1374 if (!set_get(u->dependencies[UNIT_AFTER], other) &&
1375 !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
1376 manager_add_job(u->manager, JOB_START, other, JOB_FAIL, false, NULL, NULL);
1378 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTS], i)
1379 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1380 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
1382 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
1383 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1384 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
1387 static void retroactively_stop_dependencies(Unit *u) {
1392 assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
1394 /* Pull down units which are bound to us recursively if enabled */
1395 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
1396 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1397 manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL);
1400 static void check_unneeded_dependencies(Unit *u) {
1405 assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)));
1407 /* Garbage collect services that might not be needed anymore, if enabled */
1408 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES], i)
1409 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1410 unit_check_unneeded(other);
1411 SET_FOREACH(other, u->dependencies[UNIT_REQUIRES_OVERRIDABLE], i)
1412 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1413 unit_check_unneeded(other);
1414 SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
1415 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1416 unit_check_unneeded(other);
1417 SET_FOREACH(other, u->dependencies[UNIT_REQUISITE], i)
1418 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1419 unit_check_unneeded(other);
1420 SET_FOREACH(other, u->dependencies[UNIT_REQUISITE_OVERRIDABLE], i)
1421 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1422 unit_check_unneeded(other);
1423 SET_FOREACH(other, u->dependencies[UNIT_BINDS_TO], i)
1424 if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
1425 unit_check_unneeded(other);
1428 void unit_start_on_failure(Unit *u) {
1434 if (set_size(u->dependencies[UNIT_ON_FAILURE]) <= 0)
1437 log_info_unit(u->id, "Triggering OnFailure= dependencies of %s.", u->id);
1439 SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) {
1442 r = manager_add_job(u->manager, JOB_START, other, u->on_failure_isolate ? JOB_ISOLATE : JOB_REPLACE, true, NULL, NULL);
1444 log_error_unit(u->id, "Failed to enqueue OnFailure= job: %s", strerror(-r));
1448 void unit_trigger_notify(Unit *u) {
1454 SET_FOREACH(other, u->dependencies[UNIT_TRIGGERED_BY], i)
1455 if (UNIT_VTABLE(other)->trigger_notify)
1456 UNIT_VTABLE(other)->trigger_notify(other, u);
1459 void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
1464 assert(os < _UNIT_ACTIVE_STATE_MAX);
1465 assert(ns < _UNIT_ACTIVE_STATE_MAX);
1467 /* Note that this is called for all low-level state changes,
1468 * even if they might map to the same high-level
1469 * UnitActiveState! That means that ns == os is OK an expected
1470 * behavior here. For example: if a mount point is remounted
1471 * this function will be called too! */
1475 if (m->n_reloading <= 0) {
1478 dual_timestamp_get(&ts);
1480 if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns))
1481 u->inactive_exit_timestamp = ts;
1482 else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns))
1483 u->inactive_enter_timestamp = ts;
1485 if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns))
1486 u->active_enter_timestamp = ts;
1487 else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
1488 u->active_exit_timestamp = ts;
1491 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
1492 unit_destroy_cgroup(u);
1494 /* Note that this doesn't apply to RemainAfterExit services exiting
1495 * sucessfully, since there's no change of state in that case. Which is
1496 * why it is handled in service_set_state() */
1497 if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
1498 ExecContext *ec = unit_get_exec_context(u);
1499 if (ec && exec_context_may_touch_console(ec)) {
1500 if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
1503 if (m->n_on_console == 0)
1504 /* unset no_console_output flag, since the console is free */
1505 m->no_console_output = false;
1514 if (u->job->state == JOB_WAITING)
1516 /* So we reached a different state for this
1517 * job. Let's see if we can run it now if it
1518 * failed previously due to EAGAIN. */
1519 job_add_to_run_queue(u->job);
1521 /* Let's check whether this state change constitutes a
1522 * finished job, or maybe contradicts a running job and
1523 * hence needs to invalidate jobs. */
1525 switch (u->job->type) {
1528 case JOB_VERIFY_ACTIVE:
1530 if (UNIT_IS_ACTIVE_OR_RELOADING(ns))
1531 job_finish_and_invalidate(u->job, JOB_DONE, true);
1532 else if (u->job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) {
1535 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
1536 job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
1542 case JOB_RELOAD_OR_START:
1544 if (u->job->state == JOB_RUNNING) {
1545 if (ns == UNIT_ACTIVE)
1546 job_finish_and_invalidate(u->job, reload_success ? JOB_DONE : JOB_FAILED, true);
1547 else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) {
1550 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
1551 job_finish_and_invalidate(u->job, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true);
1559 case JOB_TRY_RESTART:
1561 if (UNIT_IS_INACTIVE_OR_FAILED(ns))
1562 job_finish_and_invalidate(u->job, JOB_DONE, true);
1563 else if (u->job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) {
1565 job_finish_and_invalidate(u->job, JOB_FAILED, true);
1571 assert_not_reached("Job type unknown");
1577 if (m->n_reloading <= 0) {
1579 /* If this state change happened without being
1580 * requested by a job, then let's retroactively start
1581 * or stop dependencies. We skip that step when
1582 * deserializing, since we don't want to create any
1583 * additional jobs just because something is already
1587 if (UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns))
1588 retroactively_start_dependencies(u);
1589 else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
1590 retroactively_stop_dependencies(u);
1593 /* stop unneeded units regardless if going down was expected or not */
1594 if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns))
1595 check_unneeded_dependencies(u);
1597 if (ns != os && ns == UNIT_FAILED) {
1598 log_notice_unit(u->id,
1599 "Unit %s entered failed state.", u->id);
1600 unit_start_on_failure(u);
1604 /* Some names are special */
1605 if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
1607 if (unit_has_name(u, SPECIAL_DBUS_SERVICE))
1608 /* The bus just might have become available,
1609 * hence try to connect to it, if we aren't
1613 if (u->type == UNIT_SERVICE &&
1614 !UNIT_IS_ACTIVE_OR_RELOADING(os) &&
1615 m->n_reloading <= 0) {
1616 /* Write audit record if we have just finished starting up */
1617 manager_send_unit_audit(m, u, AUDIT_SERVICE_START, true);
1621 if (!UNIT_IS_ACTIVE_OR_RELOADING(os))
1622 manager_send_unit_plymouth(m, u);
1626 /* We don't care about D-Bus here, since we'll get an
1627 * asynchronous notification for it anyway. */
1629 if (u->type == UNIT_SERVICE &&
1630 UNIT_IS_INACTIVE_OR_FAILED(ns) &&
1631 !UNIT_IS_INACTIVE_OR_FAILED(os) &&
1632 m->n_reloading <= 0) {
1634 /* Hmm, if there was no start record written
1635 * write it now, so that we always have a nice
1638 manager_send_unit_audit(m, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE);
1640 if (ns == UNIT_INACTIVE)
1641 manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, true);
1643 /* Write audit record if we have just finished shutting down */
1644 manager_send_unit_audit(m, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
1646 u->in_audit = false;
1650 manager_recheck_journal(m);
1651 unit_trigger_notify(u);
1653 /* Maybe we finished startup and are now ready for being
1654 * stopped because unneeded? */
1655 if (u->manager->n_reloading <= 0)
1656 unit_check_unneeded(u);
1658 unit_add_to_dbus_queue(u);
1659 unit_add_to_gc_queue(u);
1662 int unit_watch_pid(Unit *u, pid_t pid) {
1666 /* Watch a specific PID. We only support one unit watching
1667 * each PID for now. */
1669 return hashmap_put(u->manager->watch_pids, LONG_TO_PTR(pid), u);
1672 void unit_unwatch_pid(Unit *u, pid_t pid) {
1676 hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
1679 bool unit_job_is_applicable(Unit *u, JobType j) {
1681 assert(j >= 0 && j < _JOB_TYPE_MAX);
1685 case JOB_VERIFY_ACTIVE:
1692 case JOB_TRY_RESTART:
1693 return unit_can_start(u);
1696 return unit_can_reload(u);
1698 case JOB_RELOAD_OR_START:
1699 return unit_can_reload(u) && unit_can_start(u);
1702 assert_not_reached("Invalid job type");
1706 int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference) {
1708 static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = {
1709 [UNIT_REQUIRES] = UNIT_REQUIRED_BY,
1710 [UNIT_REQUIRES_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
1711 [UNIT_WANTS] = UNIT_WANTED_BY,
1712 [UNIT_REQUISITE] = UNIT_REQUIRED_BY,
1713 [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE,
1714 [UNIT_BINDS_TO] = UNIT_BOUND_BY,
1715 [UNIT_PART_OF] = UNIT_CONSISTS_OF,
1716 [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID,
1717 [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID,
1718 [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID,
1719 [UNIT_BOUND_BY] = UNIT_BINDS_TO,
1720 [UNIT_CONSISTS_OF] = UNIT_PART_OF,
1721 [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY,
1722 [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS,
1723 [UNIT_BEFORE] = UNIT_AFTER,
1724 [UNIT_AFTER] = UNIT_BEFORE,
1725 [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
1726 [UNIT_REFERENCES] = UNIT_REFERENCED_BY,
1727 [UNIT_REFERENCED_BY] = UNIT_REFERENCES,
1728 [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY,
1729 [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS,
1730 [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM,
1731 [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO,
1733 int r, q = 0, v = 0, w = 0;
1736 assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
1739 u = unit_follow_merge(u);
1740 other = unit_follow_merge(other);
1742 /* We won't allow dependencies on ourselves. We will not
1743 * consider them an error however. */
1747 if ((r = set_ensure_allocated(&u->dependencies[d], trivial_hash_func, trivial_compare_func)) < 0)
1750 if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
1751 if ((r = set_ensure_allocated(&other->dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
1755 if ((r = set_ensure_allocated(&u->dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func)) < 0 ||
1756 (r = set_ensure_allocated(&other->dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func)) < 0)
1759 if ((q = set_put(u->dependencies[d], other)) < 0)
1762 if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
1763 if ((v = set_put(other->dependencies[inverse_table[d]], u)) < 0) {
1768 if (add_reference) {
1769 if ((w = set_put(u->dependencies[UNIT_REFERENCES], other)) < 0) {
1774 if ((r = set_put(other->dependencies[UNIT_REFERENCED_BY], u)) < 0)
1778 unit_add_to_dbus_queue(u);
1783 set_remove(u->dependencies[d], other);
1786 set_remove(other->dependencies[inverse_table[d]], u);
1789 set_remove(u->dependencies[UNIT_REFERENCES], other);
1794 int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference) {
1799 if ((r = unit_add_dependency(u, d, other, add_reference)) < 0)
1802 if ((r = unit_add_dependency(u, e, other, add_reference)) < 0)
1808 static const char *resolve_template(Unit *u, const char *name, const char*path, char **p) {
1812 assert(name || path);
1816 name = path_get_file_name(path);
1818 if (!unit_name_is_template(name)) {
1824 s = unit_name_replace_instance(name, u->instance);
1826 _cleanup_free_ char *i = NULL;
1828 i = unit_name_to_prefix(u->id);
1832 s = unit_name_replace_instance(name, i);
1842 int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
1845 _cleanup_free_ char *s = NULL;
1848 assert(name || path);
1850 name = resolve_template(u, name, path, &s);
1854 r = manager_load_unit(u->manager, name, path, NULL, &other);
1858 return unit_add_dependency(u, d, other, add_reference);
1861 int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
1864 _cleanup_free_ char *s = NULL;
1867 assert(name || path);
1869 if (!(name = resolve_template(u, name, path, &s)))
1872 if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
1875 r = unit_add_two_dependencies(u, d, e, other, add_reference);
1880 int unit_add_dependency_by_name_inverse(Unit *u, UnitDependency d, const char *name, const char *path, bool add_reference) {
1883 _cleanup_free_ char *s = NULL;
1886 assert(name || path);
1888 if (!(name = resolve_template(u, name, path, &s)))
1891 if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
1894 r = unit_add_dependency(other, d, u, add_reference);
1899 int unit_add_two_dependencies_by_name_inverse(Unit *u, UnitDependency d, UnitDependency e, const char *name, const char *path, bool add_reference) {
1902 _cleanup_free_ char *s = NULL;
1905 assert(name || path);
1907 if (!(name = resolve_template(u, name, path, &s)))
1910 if ((r = manager_load_unit(u->manager, name, path, NULL, &other)) < 0)
1913 if ((r = unit_add_two_dependencies(other, d, e, u, add_reference)) < 0)
1919 int set_unit_path(const char *p) {
1920 _cleanup_free_ char *c = NULL;
1922 /* This is mostly for debug purposes */
1923 c = path_make_absolute_cwd(p);
1924 if (setenv("SYSTEMD_UNIT_PATH", c, 0) < 0)
1930 char *unit_dbus_path(Unit *u) {
1936 return unit_dbus_path_from_name(u->id);
1939 char *unit_default_cgroup_path(Unit *u) {
1940 _cleanup_free_ char *escaped = NULL, *slice = NULL;
1945 if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1946 return strdup(u->manager->cgroup_root);
1948 if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
1949 r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
1954 escaped = cg_escape(u->id);
1959 return strjoin(u->manager->cgroup_root, "/", slice, "/", escaped, NULL);
1961 return strjoin(u->manager->cgroup_root, "/", escaped, NULL);
1964 int unit_add_default_slice(Unit *u) {
1965 _cleanup_free_ char *b = NULL;
1966 const char *slice_name;
1972 if (UNIT_ISSET(u->slice))
1975 if (!unit_get_cgroup_context(u))
1979 _cleanup_free_ char *prefix = NULL, *escaped = NULL;
1981 /* Implicitly place all instantiated units in their
1982 * own per-template slice */
1984 prefix = unit_name_to_prefix(u->id);
1988 /* The prefix is already escaped, but it might include
1989 * "-" which has a special meaning for slice units,
1990 * hence escape it here extra. */
1991 escaped = strreplace(prefix, "-", "\\x2d");
1995 if (u->manager->running_as == SYSTEMD_SYSTEM)
1996 b = strjoin("system-", escaped, ".slice", NULL);
1998 b = strappend(escaped, ".slice");
2005 u->manager->running_as == SYSTEMD_SYSTEM
2006 ? SPECIAL_SYSTEM_SLICE
2007 : SPECIAL_ROOT_SLICE;
2009 r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice);
2013 unit_ref_set(&u->slice, slice);
2017 const char *unit_slice_name(Unit *u) {
2020 if (!UNIT_ISSET(u->slice))
2023 return UNIT_DEREF(u->slice)->id;
2026 int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
2027 _cleanup_free_ char *t = NULL;
2034 t = unit_name_change_suffix(u->id, type);
2038 assert(!unit_has_name(u, t));
2040 r = manager_load_unit(u->manager, t, NULL, NULL, _found);
2041 assert(r < 0 || *_found != u);
2045 int unit_watch_bus_name(Unit *u, const char *name) {
2049 /* Watch a specific name on the bus. We only support one unit
2050 * watching each name for now. */
2052 return hashmap_put(u->manager->watch_bus, name, u);
2055 void unit_unwatch_bus_name(Unit *u, const char *name) {
2059 hashmap_remove_value(u->manager->watch_bus, name, u);
2062 bool unit_can_serialize(Unit *u) {
2065 return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item;
2068 int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
2075 if (!unit_can_serialize(u))
2078 r = UNIT_VTABLE(u)->serialize(u, f, fds);
2083 if (serialize_jobs) {
2085 fprintf(f, "job\n");
2086 job_serialize(u->job, f, fds);
2090 fprintf(f, "job\n");
2091 job_serialize(u->nop_job, f, fds);
2095 dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp);
2096 dual_timestamp_serialize(f, "active-enter-timestamp", &u->active_enter_timestamp);
2097 dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp);
2098 dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp);
2099 dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp);
2101 if (dual_timestamp_is_set(&u->condition_timestamp))
2102 unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result));
2104 unit_serialize_item(u, f, "transient", yes_no(u->transient));
2107 unit_serialize_item(u, f, "cgroup", u->cgroup_path);
2114 void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
2125 va_start(ap, format);
2126 vfprintf(f, format, ap);
2132 void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
2138 fprintf(f, "%s=%s\n", key, value);
2141 int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
2148 if (!unit_can_serialize(u))
2152 char line[LINE_MAX], *l, *v;
2155 if (!fgets(line, sizeof(line), f)) {
2168 k = strcspn(l, "=");
2176 if (streq(l, "job")) {
2178 /* new-style serialized job */
2179 Job *j = job_new_raw(u);
2183 r = job_deserialize(j, f, fds);
2189 r = hashmap_put(u->manager->jobs, UINT32_TO_PTR(j->id), j);
2195 r = job_install_deserialized(j);
2197 hashmap_remove(u->manager->jobs, UINT32_TO_PTR(j->id));
2202 if (j->state == JOB_RUNNING)
2203 u->manager->n_running_jobs++;
2206 JobType type = job_type_from_string(v);
2208 log_debug("Failed to parse job type value %s", v);
2210 u->deserialized_job = type;
2213 } else if (streq(l, "inactive-exit-timestamp")) {
2214 dual_timestamp_deserialize(v, &u->inactive_exit_timestamp);
2216 } else if (streq(l, "active-enter-timestamp")) {
2217 dual_timestamp_deserialize(v, &u->active_enter_timestamp);
2219 } else if (streq(l, "active-exit-timestamp")) {
2220 dual_timestamp_deserialize(v, &u->active_exit_timestamp);
2222 } else if (streq(l, "inactive-enter-timestamp")) {
2223 dual_timestamp_deserialize(v, &u->inactive_enter_timestamp);
2225 } else if (streq(l, "condition-timestamp")) {
2226 dual_timestamp_deserialize(v, &u->condition_timestamp);
2228 } else if (streq(l, "condition-result")) {
2231 b = parse_boolean(v);
2233 log_debug("Failed to parse condition result value %s", v);
2235 u->condition_result = b;
2239 } else if (streq(l, "transient")) {
2242 b = parse_boolean(v);
2244 log_debug("Failed to parse transient bool %s", v);
2249 } else if (streq(l, "cgroup")) {
2256 free(u->cgroup_path);
2259 assert(hashmap_put(u->manager->cgroup_unit, s, u) == 1);
2263 r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds);
2269 int unit_add_node_link(Unit *u, const char *what, bool wants) {
2271 _cleanup_free_ char *e = NULL;
2279 /* Adds in links to the device node that this unit is based on */
2281 if (!is_device_path(what))
2284 e = unit_name_from_path(what, ".device");
2288 r = manager_load_unit(u->manager, e, NULL, NULL, &device);
2293 r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true);
2298 r = unit_add_dependency(device, UNIT_WANTS, u, false);
2306 int unit_coldplug(Unit *u) {
2311 if (UNIT_VTABLE(u)->coldplug)
2312 if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
2316 r = job_coldplug(u->job);
2319 } else if (u->deserialized_job >= 0) {
2321 r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
2325 u->deserialized_job = _JOB_TYPE_INVALID;
2331 #pragma GCC diagnostic push
2332 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2333 void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) {
2334 manager_status_printf(u->manager, false, status, unit_status_msg_format, unit_description(u));
2336 #pragma GCC diagnostic pop
2338 bool unit_need_daemon_reload(Unit *u) {
2339 _cleanup_strv_free_ char **t = NULL;
2342 unsigned loaded_cnt, current_cnt;
2346 if (u->fragment_path) {
2348 if (stat(u->fragment_path, &st) < 0)
2349 /* What, cannot access this anymore? */
2352 if (u->fragment_mtime > 0 &&
2353 timespec_load(&st.st_mtim) != u->fragment_mtime)
2357 if (u->source_path) {
2359 if (stat(u->source_path, &st) < 0)
2362 if (u->source_mtime > 0 &&
2363 timespec_load(&st.st_mtim) != u->source_mtime)
2367 t = unit_find_dropin_paths(u);
2368 loaded_cnt = strv_length(t);
2369 current_cnt = strv_length(u->dropin_paths);
2371 if (loaded_cnt == current_cnt) {
2372 if (loaded_cnt == 0)
2375 if (strv_overlap(u->dropin_paths, t)) {
2376 STRV_FOREACH(path, u->dropin_paths) {
2378 if (stat(*path, &st) < 0)
2381 if (u->dropin_mtime > 0 &&
2382 timespec_load(&st.st_mtim) > u->dropin_mtime)
2393 void unit_reset_failed(Unit *u) {
2396 if (UNIT_VTABLE(u)->reset_failed)
2397 UNIT_VTABLE(u)->reset_failed(u);
2400 Unit *unit_following(Unit *u) {
2403 if (UNIT_VTABLE(u)->following)
2404 return UNIT_VTABLE(u)->following(u);
2409 bool unit_stop_pending(Unit *u) {
2412 /* This call does check the current state of the unit. It's
2413 * hence useful to be called from state change calls of the
2414 * unit itself, where the state isn't updated yet. This is
2415 * different from unit_inactive_or_pending() which checks both
2416 * the current state and for a queued job. */
2418 return u->job && u->job->type == JOB_STOP;
2421 bool unit_inactive_or_pending(Unit *u) {
2424 /* Returns true if the unit is inactive or going down */
2426 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u)))
2429 if (unit_stop_pending(u))
2435 bool unit_active_or_pending(Unit *u) {
2438 /* Returns true if the unit is active or going up */
2440 if (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u)))
2444 (u->job->type == JOB_START ||
2445 u->job->type == JOB_RELOAD_OR_START ||
2446 u->job->type == JOB_RESTART))
2452 int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
2454 assert(w >= 0 && w < _KILL_WHO_MAX);
2456 assert(signo < _NSIG);
2458 if (!UNIT_VTABLE(u)->kill)
2461 return UNIT_VTABLE(u)->kill(u, w, signo, error);
2464 static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
2468 pid_set = set_new(trivial_hash_func, trivial_compare_func);
2472 /* Exclude the main/control pids from being killed via the cgroup */
2474 r = set_put(pid_set, LONG_TO_PTR(main_pid));
2479 if (control_pid > 0) {
2480 r = set_put(pid_set, LONG_TO_PTR(control_pid));
2492 int unit_kill_common(
2498 sd_bus_error *error) {
2502 if (who == KILL_MAIN && main_pid <= 0) {
2504 sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
2506 sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
2510 if (who == KILL_CONTROL && control_pid <= 0) {
2511 if (control_pid < 0)
2512 sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
2514 sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
2518 if (who == KILL_CONTROL || who == KILL_ALL)
2519 if (control_pid > 0)
2520 if (kill(control_pid, signo) < 0)
2523 if (who == KILL_MAIN || who == KILL_ALL)
2525 if (kill(main_pid, signo) < 0)
2528 if (who == KILL_ALL && u->cgroup_path) {
2529 _cleanup_set_free_ Set *pid_set = NULL;
2532 /* Exclude the main/control pids from being killed via the cgroup */
2533 pid_set = unit_pid_set(main_pid, control_pid);
2537 q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
2538 if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
2545 int unit_following_set(Unit *u, Set **s) {
2549 if (UNIT_VTABLE(u)->following_set)
2550 return UNIT_VTABLE(u)->following_set(u, s);
2556 UnitFileState unit_get_unit_file_state(Unit *u) {
2559 if (u->unit_file_state < 0 && u->fragment_path)
2560 u->unit_file_state = unit_file_get_state(
2561 u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
2562 NULL, path_get_file_name(u->fragment_path));
2564 return u->unit_file_state;
2567 Unit* unit_ref_set(UnitRef *ref, Unit *u) {
2572 unit_ref_unset(ref);
2575 LIST_PREPEND(refs, u->refs, ref);
2579 void unit_ref_unset(UnitRef *ref) {
2585 LIST_REMOVE(refs, ref->unit->refs, ref);
2589 int unit_exec_context_defaults(Unit *u, ExecContext *c) {
2596 /* This only copies in the ones that need memory */
2597 for (i = 0; i < RLIMIT_NLIMITS; i++)
2598 if (u->manager->rlimit[i] && !c->rlimit[i]) {
2599 c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1);
2604 if (u->manager->running_as == SYSTEMD_USER &&
2605 !c->working_directory) {
2607 r = get_home_dir(&c->working_directory);
2615 ExecContext *unit_get_exec_context(Unit *u) {
2619 offset = UNIT_VTABLE(u)->exec_context_offset;
2623 return (ExecContext*) ((uint8_t*) u + offset);
2626 KillContext *unit_get_kill_context(Unit *u) {
2630 offset = UNIT_VTABLE(u)->kill_context_offset;
2634 return (KillContext*) ((uint8_t*) u + offset);
2637 CGroupContext *unit_get_cgroup_context(Unit *u) {
2640 offset = UNIT_VTABLE(u)->cgroup_context_offset;
2644 return (CGroupContext*) ((uint8_t*) u + offset);
2647 static int drop_in_file(Unit *u, UnitSetPropertiesMode mode, const char *name, char **_p, char **_q) {
2648 _cleanup_free_ char *b = NULL;
2656 assert(mode & (UNIT_PERSISTENT|UNIT_RUNTIME));
2658 b = xescape(name, "/.");
2662 if (!filename_is_safe(b))
2665 if (u->manager->running_as == SYSTEMD_USER) {
2666 _cleanup_free_ char *c = NULL;
2668 r = user_config_home(&c);
2674 p = strjoin(c, "/", u->id, ".d", NULL);
2675 } else if (mode & UNIT_PERSISTENT)
2676 p = strjoin("/etc/systemd/system/", u->id, ".d", NULL);
2678 p = strjoin("/run/systemd/system/", u->id, ".d", NULL);
2682 q = strjoin(p, "/90-", b, ".conf", NULL);
2693 int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
2694 _cleanup_free_ char *p = NULL, *q = NULL;
2701 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2704 r = drop_in_file(u, mode, name, &p, &q);
2709 return write_string_file_atomic_label(q, data);
2712 int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
2713 _cleanup_free_ char *p = NULL;
2721 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2724 va_start(ap, format);
2725 r = vasprintf(&p, format, ap);
2731 return unit_write_drop_in(u, mode, name, p);
2734 int unit_write_drop_in_private(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) {
2735 _cleanup_free_ char *ndata = NULL;
2741 if (!UNIT_VTABLE(u)->private_section)
2744 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2747 ndata = strjoin("[", UNIT_VTABLE(u)->private_section, "]\n", data, NULL);
2751 return unit_write_drop_in(u, mode, name, ndata);
2754 int unit_write_drop_in_private_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) {
2755 _cleanup_free_ char *p = NULL;
2763 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2766 va_start(ap, format);
2767 r = vasprintf(&p, format, ap);
2773 return unit_write_drop_in_private(u, mode, name, p);
2776 int unit_remove_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name) {
2777 _cleanup_free_ char *p = NULL, *q = NULL;
2782 if (!(mode & (UNIT_PERSISTENT|UNIT_RUNTIME)))
2785 r = drop_in_file(u, mode, name, &p, &q);
2790 r = errno == ENOENT ? 0 : -errno;
2798 int unit_make_transient(Unit *u) {
2803 u->load_state = UNIT_STUB;
2805 u->transient = true;
2807 free(u->fragment_path);
2808 u->fragment_path = NULL;
2810 if (u->manager->running_as == SYSTEMD_USER) {
2811 _cleanup_free_ char *c = NULL;
2813 r = user_config_home(&c);
2819 u->fragment_path = strjoin(c, "/", u->id, NULL);
2820 if (!u->fragment_path)
2825 u->fragment_path = strappend("/run/systemd/system/", u->id);
2826 if (!u->fragment_path)
2829 mkdir_p("/run/systemd/system", 0755);
2832 return write_string_file_atomic_label(u->fragment_path, "# Transient stub");
2835 int unit_kill_context(
2841 bool main_pid_alien) {
2843 int sig, wait_for_exit = 0, r;
2848 if (c->kill_mode == KILL_NONE)
2851 sig = sigkill ? SIGKILL : c->kill_signal;
2854 r = kill_and_sigcont(main_pid, sig);
2856 if (r < 0 && r != -ESRCH) {
2857 _cleanup_free_ char *comm = NULL;
2858 get_process_comm(main_pid, &comm);
2860 log_warning_unit(u->id, "Failed to kill main process %li (%s): %s",
2861 (long) main_pid, strna(comm), strerror(-r));
2863 wait_for_exit = !main_pid_alien;
2866 kill(main_pid, SIGHUP);
2870 if (control_pid > 0) {
2871 r = kill_and_sigcont(control_pid, sig);
2873 if (r < 0 && r != -ESRCH) {
2874 _cleanup_free_ char *comm = NULL;
2875 get_process_comm(control_pid, &comm);
2877 log_warning_unit(u->id,
2878 "Failed to kill control process %li (%s): %s",
2879 (long) control_pid, strna(comm), strerror(-r));
2881 wait_for_exit = true;
2884 kill(control_pid, SIGHUP);
2888 if (c->kill_mode == KILL_CONTROL_GROUP && u->cgroup_path) {
2889 _cleanup_set_free_ Set *pid_set = NULL;
2891 /* Exclude the main/control pids from being killed via the cgroup */
2892 pid_set = unit_pid_set(main_pid, control_pid);
2896 r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set);
2898 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
2899 log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r));
2901 wait_for_exit = true;
2902 if (c->send_sighup) {
2905 pid_set = unit_pid_set(main_pid, control_pid);
2909 cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, SIGHUP, true, true, false, pid_set);
2914 return wait_for_exit;
2917 int unit_require_mounts_for(Unit *u, const char *path) {
2918 char prefix[strlen(path) + 1], *p;
2924 /* Registers a unit for requiring a certain path and all its
2925 * prefixes. We keep a simple array of these paths in the
2926 * unit, since its usually short. However, we build a prefix
2927 * table for all possible prefixes so that new appearing mount
2928 * units can easily determine which units to make themselves a
2935 path_kill_slashes(p);
2937 if (!path_is_absolute(p)) {
2942 if (!path_is_safe(p)) {
2947 if (strv_contains(u->requires_mounts_for, p)) {
2952 r = strv_push(&u->requires_mounts_for, p);
2958 PATH_FOREACH_PREFIX_MORE(prefix, p) {
2961 x = hashmap_get(u->manager->units_requiring_mounts_for, prefix);
2965 if (!u->manager->units_requiring_mounts_for) {
2966 u->manager->units_requiring_mounts_for = hashmap_new(string_hash_func, string_compare_func);
2967 if (!u->manager->units_requiring_mounts_for)
2975 x = set_new(NULL, NULL);
2981 r = hashmap_put(u->manager->units_requiring_mounts_for, q, x);
2997 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
2998 [UNIT_ACTIVE] = "active",
2999 [UNIT_RELOADING] = "reloading",
3000 [UNIT_INACTIVE] = "inactive",
3001 [UNIT_FAILED] = "failed",
3002 [UNIT_ACTIVATING] = "activating",
3003 [UNIT_DEACTIVATING] = "deactivating"
3006 DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
3008 static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
3009 [UNIT_REQUIRES] = "Requires",
3010 [UNIT_REQUIRES_OVERRIDABLE] = "RequiresOverridable",
3011 [UNIT_REQUISITE] = "Requisite",
3012 [UNIT_REQUISITE_OVERRIDABLE] = "RequisiteOverridable",
3013 [UNIT_WANTS] = "Wants",
3014 [UNIT_BINDS_TO] = "BindsTo",
3015 [UNIT_PART_OF] = "PartOf",
3016 [UNIT_REQUIRED_BY] = "RequiredBy",
3017 [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable",
3018 [UNIT_WANTED_BY] = "WantedBy",
3019 [UNIT_BOUND_BY] = "BoundBy",
3020 [UNIT_CONSISTS_OF] = "ConsistsOf",
3021 [UNIT_CONFLICTS] = "Conflicts",
3022 [UNIT_CONFLICTED_BY] = "ConflictedBy",
3023 [UNIT_BEFORE] = "Before",
3024 [UNIT_AFTER] = "After",
3025 [UNIT_ON_FAILURE] = "OnFailure",
3026 [UNIT_TRIGGERS] = "Triggers",
3027 [UNIT_TRIGGERED_BY] = "TriggeredBy",
3028 [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
3029 [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom",
3030 [UNIT_REFERENCES] = "References",
3031 [UNIT_REFERENCED_BY] = "ReferencedBy",
3034 DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);