1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "locale-util.h"
6 #include "systemctl-list-dependencies.h"
7 #include "systemctl-util.h"
9 #include "terminal-util.h"
11 static int list_dependencies_print(const char *name
, int level
, unsigned branches
, bool last
) {
12 _cleanup_free_
char *n
= NULL
;
13 size_t max_len
= MAX(columns(),20u);
18 for (int i
= level
- 1; i
>= 0; i
--) {
20 if (len
> max_len
- 3 && !arg_full
) {
21 printf("%s...\n",max_len
% 2 ? "" : " ");
24 printf("%s", special_glyph(branches
& (1 << i
) ? SPECIAL_GLYPH_TREE_VERTICAL
: SPECIAL_GLYPH_TREE_SPACE
));
28 if (len
> max_len
- 3 && !arg_full
) {
29 printf("%s...\n",max_len
% 2 ? "" : " ");
33 printf("%s", special_glyph(last
? SPECIAL_GLYPH_TREE_RIGHT
: SPECIAL_GLYPH_TREE_BRANCH
));
41 n
= ellipsize(name
, max_len
-len
, 100);
49 static int list_dependencies_compare(char * const *a
, char * const *b
) {
50 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
52 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
55 return strcasecmp(*a
, *b
);
58 static int list_dependencies_one(
65 _cleanup_strv_free_
char **deps
= NULL
;
72 r
= strv_extend(units
, name
);
76 r
= unit_get_dependencies(bus
, name
, &deps
);
80 typesafe_qsort(deps
, strv_length(deps
), list_dependencies_compare
);
82 STRV_FOREACH(c
, deps
) {
83 if (strv_contains(*units
, *c
)) {
86 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
96 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
99 (void) get_state_one_unit(bus
, *c
, &active_state
);
101 switch (active_state
) {
104 case UNIT_ACTIVATING
:
105 on
= ansi_highlight_green();
109 case UNIT_DEACTIVATING
:
114 on
= ansi_highlight_red();
118 printf("%s%s%s ", on
, special_glyph(unit_active_state_to_glyph(active_state
)), ansi_normal());
121 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
125 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
126 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
133 strv_remove(*units
, name
);
138 int verb_list_dependencies(int argc
, char *argv
[], void *userdata
) {
139 _cleanup_strv_free_
char **units
= NULL
, **done
= NULL
;
144 r
= acquire_bus(BUS_MANAGER
, &bus
);
148 patterns
= strv_skip(argv
, 1);
149 if (strv_isempty(patterns
)) {
150 units
= strv_new(SPECIAL_DEFAULT_TARGET
);
154 r
= expand_unit_names(bus
, patterns
, NULL
, &units
, NULL
);
156 return log_error_errno(r
, "Failed to expand names: %m");
159 pager_open(arg_pager_flags
);
161 STRV_FOREACH(u
, units
) {
166 r
= list_dependencies_one(bus
, *u
, 0, &done
, 0);