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);
19 for (i
= level
- 1; i
>= 0; i
--) {
21 if (len
> max_len
- 3 && !arg_full
) {
22 printf("%s...\n",max_len
% 2 ? "" : " ");
25 printf("%s", special_glyph(branches
& (1 << i
) ? SPECIAL_GLYPH_TREE_VERTICAL
: SPECIAL_GLYPH_TREE_SPACE
));
29 if (len
> max_len
- 3 && !arg_full
) {
30 printf("%s...\n",max_len
% 2 ? "" : " ");
34 printf("%s", special_glyph(last
? SPECIAL_GLYPH_TREE_RIGHT
: SPECIAL_GLYPH_TREE_BRANCH
));
42 n
= ellipsize(name
, max_len
-len
, 100);
50 static int list_dependencies_compare(char * const *a
, char * const *b
) {
51 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
53 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
56 return strcasecmp(*a
, *b
);
59 static int list_dependencies_one(
66 _cleanup_strv_free_
char **deps
= NULL
;
74 r
= strv_extend(units
, name
);
78 r
= unit_get_dependencies(bus
, name
, &deps
);
82 typesafe_qsort(deps
, strv_length(deps
), list_dependencies_compare
);
84 STRV_FOREACH(c
, deps
) {
85 if (strv_contains(*units
, *c
)) {
88 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
98 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
101 (void) get_state_one_unit(bus
, *c
, &active_state
);
103 switch (active_state
) {
106 case UNIT_ACTIVATING
:
107 on
= ansi_highlight_green();
111 case UNIT_DEACTIVATING
:
116 on
= ansi_highlight_red();
120 printf("%s%s%s ", on
, special_glyph(unit_active_state_to_glyph(active_state
)), ansi_normal());
123 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
127 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
128 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
135 strv_remove(*units
, name
);
140 int list_dependencies(int argc
, char *argv
[], void *userdata
) {
141 _cleanup_strv_free_
char **units
= NULL
, **done
= NULL
;
142 char **u
, **patterns
;
146 r
= acquire_bus(BUS_MANAGER
, &bus
);
150 patterns
= strv_skip(argv
, 1);
151 if (strv_isempty(patterns
)) {
152 units
= strv_new(SPECIAL_DEFAULT_TARGET
);
156 r
= expand_unit_names(bus
, patterns
, NULL
, &units
, NULL
);
158 return log_error_errno(r
, "Failed to expand names: %m");
161 (void) pager_open(arg_pager_flags
);
163 STRV_FOREACH(u
, units
) {
168 r
= list_dependencies_one(bus
, *u
, 0, &done
, 0);