1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <sys/reboot.h>
10 #include "ask-password-agent.h"
11 #include "bus-common-errors.h"
12 #include "bus-locator.h"
13 #include "bus-map-properties.h"
14 #include "bus-unit-util.h"
19 #include "exit-status.h"
20 #include "format-table.h"
21 #include "format-util.h"
22 #include "glob-util.h"
24 #include "output-mode.h"
25 #include "path-lookup.h"
26 #include "path-util.h"
28 #include "polkit-agent.h"
29 #include "process-util.h"
30 #include "reboot-util.h"
31 #include "runtime-scope.h"
33 #include "string-util.h"
35 #include "systemctl.h"
36 #include "systemctl-util.h"
37 #include "unit-file.h"
38 #include "unit-name.h"
41 static sd_bus
*buses
[_BUS_FOCUS_MAX
] = {};
43 int acquire_bus_full(BusFocus focus
, bool graceful
, sd_bus
**ret
) {
46 assert(focus
< _BUS_FOCUS_MAX
);
49 if (!IN_SET(arg_runtime_scope
, RUNTIME_SCOPE_SYSTEM
, RUNTIME_SCOPE_USER
))
50 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "--global is not supported for this operation.");
52 /* We only go directly to the manager, if we are using a local transport */
53 if (!IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_CAPSULE
))
56 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
60 if (focus
== BUS_MANAGER
)
61 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, arg_runtime_scope
, &buses
[focus
]);
63 r
= bus_connect_transport(arg_transport
, arg_host
, arg_runtime_scope
, &buses
[focus
]);
65 return bus_log_connect_full(graceful
&& focus
== BUS_FULL
&& r
== -ECONNREFUSED
? LOG_DEBUG
: LOG_ERR
,
66 r
, arg_transport
, arg_runtime_scope
);
68 (void) sd_bus_set_allow_interactive_authorization(buses
[focus
], arg_ask_password
);
75 void release_busses(void) {
76 FOREACH_ARRAY(w
, buses
, _BUS_FOCUS_MAX
)
77 *w
= sd_bus_flush_close_unref(*w
);
80 void ask_password_agent_open_maybe(void) {
81 /* Open the password agent as a child process if necessary */
86 if (arg_runtime_scope
!= RUNTIME_SCOPE_SYSTEM
)
89 ask_password_agent_open_if_enabled(arg_transport
, arg_ask_password
);
92 void polkit_agent_open_maybe(void) {
93 /* Open the polkit agent as a child process if necessary */
95 if (arg_runtime_scope
!= RUNTIME_SCOPE_SYSTEM
)
98 (void) polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
101 int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
104 if (!sd_bus_error_is_set(error
))
107 if (sd_bus_error_has_names(error
, SD_BUS_ERROR_ACCESS_DENIED
,
108 BUS_ERROR_ONLY_BY_DEPENDENCY
,
109 BUS_ERROR_NO_ISOLATION
,
110 BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
111 return EXIT_NOPERMISSION
;
113 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
114 return EXIT_NOTINSTALLED
;
116 if (sd_bus_error_has_names(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
,
117 SD_BUS_ERROR_NOT_SUPPORTED
))
118 return EXIT_NOTIMPLEMENTED
;
120 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
121 return EXIT_NOTCONFIGURED
;
129 int get_state_one_unit(sd_bus
*bus
, const char *unit
, UnitActiveState
*ret_active_state
) {
130 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
131 _cleanup_free_
char *buf
= NULL
, *dbus_path
= NULL
;
132 UnitActiveState state
;
137 assert(ret_active_state
);
139 dbus_path
= unit_dbus_path_from_name(unit
);
143 r
= sd_bus_get_property_string(
145 "org.freedesktop.systemd1",
147 "org.freedesktop.systemd1.Unit",
152 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
154 state
= unit_active_state_from_string(buf
);
156 return log_error_errno(state
, "Invalid unit state '%s' for: %s", buf
, unit
);
158 *ret_active_state
= state
;
162 int get_sub_state_one_unit(sd_bus
*bus
, const char *unit
, char **ret_sub_state
) {
163 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
164 _cleanup_free_
char *sub_state
= NULL
, *dbus_path
= NULL
;
169 assert(ret_sub_state
);
171 dbus_path
= unit_dbus_path_from_name(unit
);
175 r
= sd_bus_get_property_string(
177 "org.freedesktop.systemd1",
179 "org.freedesktop.systemd1.Unit",
184 return log_error_errno(r
, "Failed to retrieve unit sub state: %s", bus_error_message(&error
, r
));
186 *ret_sub_state
= TAKE_PTR(sub_state
);
194 UnitInfo
**unit_infos
,
196 sd_bus_message
**ret_reply
) {
198 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
199 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
200 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
202 bool fallback
= false;
208 r
= bus_message_new_method_call(bus
, &m
, bus_systemd_mgr
, "ListUnitsByPatterns");
210 return bus_log_create_error(r
);
212 r
= sd_bus_message_append_strv(m
, arg_states
);
214 return bus_log_create_error(r
);
216 r
= sd_bus_message_append_strv(m
, patterns
);
218 return bus_log_create_error(r
);
220 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
221 if (r
< 0 && (sd_bus_error_has_names(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
,
222 SD_BUS_ERROR_ACCESS_DENIED
))) {
223 /* Fallback to legacy ListUnitsFiltered method */
225 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
226 m
= sd_bus_message_unref(m
);
227 sd_bus_error_free(&error
);
229 r
= bus_message_new_method_call(bus
, &m
, bus_systemd_mgr
, "ListUnitsFiltered");
231 return bus_log_create_error(r
);
233 r
= sd_bus_message_append_strv(m
, arg_states
);
235 return bus_log_create_error(r
);
237 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
240 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
242 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
244 return bus_log_parse_error(r
);
249 r
= bus_parse_unit_info(reply
, &u
);
251 return bus_log_parse_error(r
);
257 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
260 if (!GREEDY_REALLOC(*unit_infos
, c
+1))
263 (*unit_infos
)[c
++] = u
;
266 r
= sd_bus_message_exit_container(reply
);
268 return bus_log_parse_error(r
);
270 *ret_reply
= TAKE_PTR(reply
);
274 int expand_unit_names(
279 bool *ret_expanded
) {
281 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
287 STRV_FOREACH(name
, names
) {
288 UnitNameMangle options
= UNIT_NAME_MANGLE_GLOB
| (arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
);
291 r
= unit_name_mangle_with_suffix(*name
, NULL
, options
, suffix
?: ".service", &t
);
293 return log_error_errno(r
, "Failed to mangle name: %m");
295 if (string_is_glob(t
))
296 r
= strv_consume(&globs
, t
);
298 r
= strv_consume(&mangled
, t
);
303 /* Query the manager only if any of the names are a glob, since this is fairly expensive */
304 bool expanded
= !strv_isempty(globs
);
306 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
307 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
309 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
313 FOREACH_ARRAY(info
, unit_infos
, r
)
314 if (strv_extend(&mangled
, info
->id
) < 0)
318 *ret
= TAKE_PTR(mangled
);
320 *ret_expanded
= expanded
;
325 int get_active_triggering_units(sd_bus
*bus
, const char *unit
, bool ignore_masked
, char ***ret
) {
326 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
327 _cleanup_strv_free_
char **triggered_by
= NULL
, **active
= NULL
;
328 _cleanup_free_
char *name
= NULL
, *dbus_path
= NULL
;
335 r
= unit_name_mangle(unit
, 0, &name
);
339 if (unit_name_is_valid(name
, UNIT_NAME_TEMPLATE
))
343 r
= unit_is_masked(bus
, name
);
350 dbus_path
= unit_dbus_path_from_name(name
);
354 r
= sd_bus_get_property_strv(
356 "org.freedesktop.systemd1",
358 "org.freedesktop.systemd1.Unit",
363 return log_debug_errno(r
, "Failed to get TriggeredBy property of unit '%s': %s",
364 name
, bus_error_message(&error
, r
));
366 STRV_FOREACH(i
, triggered_by
) {
367 UnitActiveState active_state
;
369 r
= get_state_one_unit(bus
, *i
, &active_state
);
373 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
, UNIT_REFRESHING
))
376 r
= strv_extend(&active
, *i
);
381 *ret
= TAKE_PTR(active
);
389 void warn_triggering_units(sd_bus
*bus
, const char *unit
, const char *operation
, bool ignore_masked
) {
390 _cleanup_strv_free_
char **triggered_by
= NULL
;
391 _cleanup_free_
char *joined
= NULL
;
398 r
= get_active_triggering_units(bus
, unit
, ignore_masked
, &triggered_by
);
400 if (r
!= -ENOENT
) /* A linked unit might have disappeared after disabling */
401 log_warning_errno(r
, "Failed to get triggering units for '%s', ignoring: %m", unit
);
405 if (strv_isempty(triggered_by
))
408 joined
= strv_join(triggered_by
, ", ");
410 return (void) log_oom();
412 log_warning("%s '%s', but its triggering units are still active:\n"
414 operation
, unit
, joined
);
417 int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
418 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
422 /* We ignore all errors here, since this is used to show a
425 /* We don't use unit_dbus_path_from_name() directly since we
426 * don't want to load the unit if it isn't loaded. */
428 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnit", NULL
, &reply
, "s", unit
);
432 r
= sd_bus_message_read(reply
, "o", &path
);
436 r
= sd_bus_get_property_trivial(
438 "org.freedesktop.systemd1",
440 "org.freedesktop.systemd1.Unit",
450 void warn_unit_file_changed(const char *unit
) {
456 log_warning("Warning: The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
458 arg_runtime_scope
== RUNTIME_SCOPE_SYSTEM
? "" : " --user");
461 int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **ret_unit_path
) {
465 STRV_FOREACH(p
, lp
->search_path
) {
466 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
469 path
= path_join(*p
, unit_name
);
473 r
= chase(path
, arg_root
, 0, &lpath
, NULL
);
479 return log_error_errno(r
, "Failed to access path \"%s\": %m", path
);
482 *ret_unit_path
= TAKE_PTR(lpath
);
488 *ret_unit_path
= NULL
;
495 const char *unit_name
,
497 bool force_client_side
,
498 Hashmap
**cached_id_map
,
499 Hashmap
**cached_name_map
,
500 char **ret_fragment_path
,
501 char ***ret_dropin_paths
) {
503 _cleanup_strv_free_
char **dropins
= NULL
;
504 _cleanup_free_
char *path
= NULL
;
508 * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is
511 * - the path to the unit in *ret_frament_path, if it exists on disk,
513 * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins
516 * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for
517 * some reason (the latter only applies if we are going through the service manager). As special
518 * exception it won't log for these two error cases.
522 assert(ret_fragment_path
);
525 /* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */
526 if (!force_client_side
&&
527 !install_client_side() &&
528 !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
529 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
530 _cleanup_free_
char *load_state
= NULL
, *dbus_path
= NULL
;
532 dbus_path
= unit_dbus_path_from_name(unit_name
);
536 r
= sd_bus_get_property_string(
538 "org.freedesktop.systemd1",
540 "org.freedesktop.systemd1.Unit",
545 return log_error_errno(r
, "Failed to get LoadState: %s", bus_error_message(&error
, r
));
547 if (streq(load_state
, "masked"))
548 return -ERFKILL
; /* special case: no logging */
549 if (streq(load_state
, "not-found")) {
553 if (!STR_IN_SET(load_state
, "loaded", "bad-setting"))
554 return -EKEYREJECTED
; /* special case: no logging */
556 r
= sd_bus_get_property_string(
558 "org.freedesktop.systemd1",
560 "org.freedesktop.systemd1.Unit",
565 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
567 if (ret_dropin_paths
) {
568 r
= sd_bus_get_property_strv(
570 "org.freedesktop.systemd1",
572 "org.freedesktop.systemd1.Unit",
577 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
580 if (!*cached_name_map
) {
581 r
= unit_file_build_name_map(lp
, NULL
, cached_id_map
, cached_name_map
, NULL
);
587 _cleanup_set_free_ Set
*names
= NULL
;
588 r
= unit_file_find_fragment(*cached_id_map
, *cached_name_map
, unit_name
, &_path
, &names
);
590 return log_error_errno(r
, "Failed to find fragment for '%s': %m", unit_name
);
593 path
= strdup(_path
);
598 if (ret_dropin_paths
) {
599 r
= unit_file_find_dropin_paths(arg_root
, lp
->search_path
, NULL
,
601 NULL
, names
, &dropins
);
609 *ret_fragment_path
= NULL
;
612 *ret_fragment_path
= TAKE_PTR(path
);
616 if (ret_dropin_paths
) {
617 if (!strv_isempty(dropins
)) {
618 *ret_dropin_paths
= TAKE_PTR(dropins
);
621 *ret_dropin_paths
= NULL
;
624 if (r
== 0 && !arg_force
)
625 log_error("No files found for %s.", unit_name
);
630 static int unit_find_template_path(
631 const char *unit_name
,
633 char **ret_fragment_path
,
634 char **ret_template
) {
636 _cleanup_free_
char *t
= NULL
, *f
= NULL
;
639 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
641 r
= unit_file_find_path(lp
, unit_name
, &f
);
645 if (ret_fragment_path
)
646 *ret_fragment_path
= TAKE_PTR(f
);
648 *ret_template
= NULL
;
649 return r
; /* found a real unit */
652 r
= unit_name_template(unit_name
, &t
);
654 if (ret_fragment_path
)
655 *ret_fragment_path
= NULL
;
657 *ret_template
= NULL
;
659 return 0; /* not a template, does not exist */
662 return log_error_errno(r
, "Failed to determine template name: %m");
664 r
= unit_file_find_path(lp
, t
, ret_fragment_path
);
669 *ret_template
= r
> 0 ? TAKE_PTR(t
) : NULL
;
674 int unit_is_masked(sd_bus
*bus
, const char *unit
) {
675 _cleanup_free_
char *load_state
= NULL
;
681 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
)) {
682 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
683 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
686 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnitFileState", &error
, &reply
, "s", unit
);
688 return log_debug_errno(r
, "Failed to get UnitFileState for '%s': %s",
689 unit
, bus_error_message(&error
, r
));
691 r
= sd_bus_message_read(reply
, "s", &state
);
693 return bus_log_parse_error_debug(r
);
695 return STR_IN_SET(state
, "masked", "masked-runtime");
698 r
= unit_load_state(bus
, unit
, &load_state
);
702 return streq(load_state
, "masked");
705 int unit_exists(LookupPaths
*lp
, const char *unit
) {
706 typedef struct UnitStateInfo
{
707 const char *load_state
;
708 const char *active_state
;
711 static const struct bus_properties_map property_map
[] = {
712 { "LoadState", "s", NULL
, offsetof(UnitStateInfo
, load_state
) },
713 { "ActiveState", "s", NULL
, offsetof(UnitStateInfo
, active_state
) },
717 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
718 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
719 _cleanup_free_
char *path
= NULL
;
720 UnitStateInfo info
= {};
724 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
725 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
727 path
= unit_dbus_path_from_name(unit
);
731 r
= acquire_bus(BUS_MANAGER
, &bus
);
735 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", path
, property_map
, 0, &error
, &m
, &info
);
737 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
739 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
742 int append_unit_dependencies(sd_bus
*bus
, char **names
, char ***ret
) {
743 _cleanup_strv_free_
char **with_deps
= NULL
;
748 STRV_FOREACH(name
, names
) {
751 if (strv_extend(&with_deps
, *name
) < 0)
754 (void) unit_get_dependencies(bus
, *name
, &deps
);
756 if (strv_extend_strv_consume(&with_deps
, deps
, /* filter_duplicates = */ true) < 0)
760 *ret
= TAKE_PTR(with_deps
);
765 int maybe_extend_with_unit_dependencies(sd_bus
*bus
, char ***list
) {
766 _cleanup_strv_free_
char **list_with_deps
= NULL
;
772 if (!arg_with_dependencies
)
775 r
= append_unit_dependencies(bus
, *list
, &list_with_deps
);
777 return log_error_errno(r
, "Failed to append unit dependencies: %m");
779 return strv_free_and_replace(*list
, list_with_deps
);
782 int unit_get_dependencies(sd_bus
*bus
, const char *name
, char ***ret
) {
783 _cleanup_strv_free_
char **deps
= NULL
;
785 static const struct bus_properties_map map
[_DEPENDENCY_MAX
][7] = {
786 [DEPENDENCY_FORWARD
] = {
787 { "Requires", "as", NULL
, 0 },
788 { "Requisite", "as", NULL
, 0 },
789 { "Wants", "as", NULL
, 0 },
790 { "ConsistsOf", "as", NULL
, 0 },
791 { "BindsTo", "as", NULL
, 0 },
792 { "Upholds", "as", NULL
, 0 },
795 [DEPENDENCY_REVERSE
] = {
796 { "RequiredBy", "as", NULL
, 0 },
797 { "RequisiteOf", "as", NULL
, 0 },
798 { "WantedBy", "as", NULL
, 0 },
799 { "PartOf", "as", NULL
, 0 },
800 { "BoundBy", "as", NULL
, 0 },
801 { "UpheldBy", "as", NULL
, 0 },
804 [DEPENDENCY_AFTER
] = {
805 { "After", "as", NULL
, 0 },
808 [DEPENDENCY_BEFORE
] = {
809 { "Before", "as", NULL
, 0 },
814 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
815 _cleanup_free_
char *dbus_path
= NULL
;
822 dbus_path
= unit_dbus_path_from_name(name
);
826 r
= bus_map_all_properties(bus
,
827 "org.freedesktop.systemd1",
835 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
837 strv_uniq(deps
); /* Sometimes a unit might have multiple deps on the other unit,
838 * but we still want to show it just once. */
839 *ret
= TAKE_PTR(deps
);
844 const char* unit_type_suffix(const char *unit
) {
847 dot
= strrchr(unit
, '.');
854 bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
857 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
860 if (arg_types
&& !strv_contains(arg_types
, unit_type_suffix(u
->id
)))
866 /* Note that '--all' is not purely a state filter, but also a filter that hides units that "follow"
867 * other units (which is used for device units that appear under different names). */
868 if (!isempty(u
->following
))
871 if (!strv_isempty(arg_states
))
874 /* By default show all units except the ones in inactive state and with no pending job */
878 if (streq(u
->active_state
, "inactive"))
884 bool install_client_side(void) {
885 /* Decides when to execute enable/disable/... operations client-side rather than server-side. */
887 if (running_in_chroot_or_offline())
890 if (sd_booted() <= 0)
893 if (!isempty(arg_root
))
896 if (arg_runtime_scope
== RUNTIME_SCOPE_GLOBAL
)
899 /* Unsupported environment variable, mostly for debugging purposes */
900 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
906 int output_table(Table
*table
) {
911 if (OUTPUT_MODE_IS_JSON(arg_output
))
912 r
= table_print_json(table
, NULL
, output_mode_to_json_format_flags(arg_output
) | SD_JSON_FORMAT_COLOR_AUTO
);
914 r
= table_print(table
, NULL
);
916 return table_log_print_error(r
);
921 bool show_preset_for_state(UnitFileState state
) {
922 /* Don't show preset state in those unit file states, it'll only confuse users. */
923 return !IN_SET(state
,
927 UNIT_FILE_TRANSIENT
);
930 UnitFileFlags
unit_file_flags_from_args(void) {
931 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
932 (arg_force
? UNIT_FILE_FORCE
: 0);
935 int mangle_names(const char *operation
, char * const *original_names
, char ***ret
) {
936 _cleanup_strv_free_
char **l
= NULL
;
942 STRV_FOREACH(name
, original_names
) {
946 /* When enabling units qualified path names are OK, too, hence allow them explicitly. */
947 r
= path_make_absolute_cwd(*name
, &mangled
);
949 r
= unit_name_mangle_with_suffix(*name
, operation
,
950 arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
,
951 ".service", &mangled
);
953 return log_error_errno(r
, "Failed to mangle unit name or path '%s': %m", *name
);
955 if (strv_consume(&l
, mangled
) < 0)
964 int halt_now(enum action a
) {
965 /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need
966 * to be synced explicitly in advance. */
967 if (!arg_no_sync
&& !arg_dry_run
)
970 /* Make sure C-A-D is handled by the kernel from this point on... */
972 (void) reboot(RB_ENABLE_CAD
);
978 log_info("Halting.");
981 (void) reboot(RB_HALT_SYSTEM
);
984 case ACTION_POWEROFF
:
986 log_info("Powering off.");
989 (void) reboot(RB_POWER_OFF
);
994 return reboot_with_parameter(REBOOT_FALLBACK
|
995 (arg_quiet
? 0 : REBOOT_LOG
) |
996 (arg_dry_run
? REBOOT_DRY_RUN
: 0));
999 assert_not_reached();
1003 int get_unit_by_pid(sd_bus
*bus
, pid_t pid
, char **ret_unit
, char **ret_path
) {
1004 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1005 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1009 assert(pid
>= 0); /* 0 is accepted by GetUnitByPID for querying our own process. */
1011 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnitByPID", &error
, &reply
, "u", (uint32_t) pid
);
1013 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_UNIT_FOR_PID
))
1014 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
1016 return log_error_errno(r
,
1017 "Failed to get unit that PID " PID_FMT
" belongs to: %s",
1018 pid
> 0 ? pid
: getpid_cached(),
1019 bus_error_message(&error
, r
));
1022 _cleanup_free_
char *u
= NULL
, *p
= NULL
;
1025 r
= sd_bus_message_read_basic(reply
, 'o', &path
);
1027 return bus_log_parse_error(r
);
1030 r
= unit_name_from_dbus_path(path
, &u
);
1032 return log_error_errno(r
,
1033 "Failed to extract unit name from D-Bus object path '%s': %m",
1044 *ret_unit
= TAKE_PTR(u
);
1046 *ret_path
= TAKE_PTR(p
);
1051 static int get_unit_by_pidfd(sd_bus
*bus
, const PidRef
*pid
, char **ret_unit
, char **ret_path
) {
1052 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1053 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1057 assert(pidref_is_set(pid
));
1062 r
= bus_call_method(bus
, bus_systemd_mgr
, "GetUnitByPIDFD", &error
, &reply
, "h", pid
->fd
);
1064 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
))
1067 if (sd_bus_error_has_names(&error
, BUS_ERROR_NO_UNIT_FOR_PID
, BUS_ERROR_NO_SUCH_PROCESS
))
1068 return log_error_errno(r
, "%s", bus_error_message(&error
, r
));
1070 return log_error_errno(r
,
1071 "Failed to get unit that PID " PID_FMT
" belongs to: %s",
1072 pid
->pid
, bus_error_message(&error
, r
));
1075 _cleanup_free_
char *u
= NULL
, *p
= NULL
;
1076 const char *path
, *unit
;
1078 r
= sd_bus_message_read(reply
, "os", &path
, &unit
);
1080 return bus_log_parse_error(r
);
1095 *ret_unit
= TAKE_PTR(u
);
1097 *ret_path
= TAKE_PTR(p
);
1102 int lookup_unit_by_pidref(sd_bus
*bus
, pid_t pid
, char **ret_unit
, char **ret_path
) {
1106 assert(pid
>= 0); /* 0 means our own process */
1108 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
1109 return get_unit_by_pid(bus
, pid
, ret_unit
, ret_path
);
1111 static bool use_pidfd
= true;
1112 _cleanup_(pidref_done
) PidRef pidref
= PIDREF_NULL
;
1114 r
= pidref_set_pid(&pidref
, pid
);
1116 return log_error_errno(r
,
1118 "PID " PID_FMT
" doesn't exist or is already gone." :
1119 "Failed to create reference to PID " PID_FMT
": %m",
1123 r
= get_unit_by_pidfd(bus
, &pidref
, ret_unit
, ret_path
);
1124 if (r
!= -EOPNOTSUPP
)
1128 log_debug_errno(r
, "Unable to look up process using pidfd, falling back to pid.");
1131 _cleanup_free_
char *u
= NULL
, *p
= NULL
;
1133 r
= get_unit_by_pid(bus
, pidref
.pid
, ret_unit
? &u
: NULL
, ret_path
? &p
: NULL
);
1137 r
= pidref_verify(&pidref
);
1139 return log_error_errno(r
, "Failed to verify our reference to PID " PID_FMT
": %m", pidref
.pid
);
1142 *ret_unit
= TAKE_PTR(u
);
1144 *ret_path
= TAKE_PTR(p
);