]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl-list-dependencies.c
0a45a017e68f37bb9ba6c842597ebbe87d2fd359
[thirdparty/systemd.git] / src / systemctl / systemctl-list-dependencies.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "locale-util.h"
4 #include "sort-util.h"
5 #include "special.h"
6 #include "systemctl-list-dependencies.h"
7 #include "systemctl-util.h"
8 #include "systemctl.h"
9 #include "terminal-util.h"
10
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);
14 size_t len = 0;
15
16 if (!arg_plain) {
17
18 for (int i = level - 1; i >= 0; i--) {
19 len += 2;
20 if (len > max_len - 3 && !arg_full) {
21 printf("%s...\n",max_len % 2 ? "" : " ");
22 return 0;
23 }
24 printf("%s", special_glyph(branches & (1 << i) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
25 }
26 len += 2;
27
28 if (len > max_len - 3 && !arg_full) {
29 printf("%s...\n",max_len % 2 ? "" : " ");
30 return 0;
31 }
32
33 printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
34 }
35
36 if (arg_full) {
37 printf("%s\n", name);
38 return 0;
39 }
40
41 n = ellipsize(name, max_len-len, 100);
42 if (!n)
43 return log_oom();
44
45 printf("%s\n", n);
46 return 0;
47 }
48
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)
51 return 1;
52 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
53 return -1;
54
55 return strcasecmp(*a, *b);
56 }
57
58 static int list_dependencies_one(
59 sd_bus *bus,
60 const char *name,
61 int level,
62 char ***units,
63 unsigned branches) {
64
65 _cleanup_strv_free_ char **deps = NULL;
66 char **c;
67 int r;
68
69 assert(bus);
70 assert(name);
71 assert(units);
72
73 r = strv_extend(units, name);
74 if (r < 0)
75 return log_oom();
76
77 r = unit_get_dependencies(bus, name, &deps);
78 if (r < 0)
79 return r;
80
81 typesafe_qsort(deps, strv_length(deps), list_dependencies_compare);
82
83 STRV_FOREACH(c, deps) {
84 if (strv_contains(*units, *c)) {
85 if (!arg_plain) {
86 printf(" ");
87 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
88 if (r < 0)
89 return r;
90 }
91 continue;
92 }
93
94 if (arg_plain)
95 printf(" ");
96 else {
97 UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
98 const char *on;
99
100 (void) get_state_one_unit(bus, *c, &active_state);
101
102 switch (active_state) {
103 case UNIT_ACTIVE:
104 case UNIT_RELOADING:
105 case UNIT_ACTIVATING:
106 on = ansi_highlight_green();
107 break;
108
109 case UNIT_INACTIVE:
110 case UNIT_DEACTIVATING:
111 on = ansi_normal();
112 break;
113
114 default:
115 on = ansi_highlight_red();
116 break;
117 }
118
119 printf("%s%s%s ", on, special_glyph(unit_active_state_to_glyph(active_state)), ansi_normal());
120 }
121
122 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
123 if (r < 0)
124 return r;
125
126 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
127 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
128 if (r < 0)
129 return r;
130 }
131 }
132
133 if (!arg_plain)
134 strv_remove(*units, name);
135
136 return 0;
137 }
138
139 int verb_list_dependencies(int argc, char *argv[], void *userdata) {
140 _cleanup_strv_free_ char **units = NULL, **done = NULL;
141 char **u, **patterns;
142 sd_bus *bus;
143 int r;
144
145 r = acquire_bus(BUS_MANAGER, &bus);
146 if (r < 0)
147 return r;
148
149 patterns = strv_skip(argv, 1);
150 if (strv_isempty(patterns)) {
151 units = strv_new(SPECIAL_DEFAULT_TARGET);
152 if (!units)
153 return log_oom();
154 } else {
155 r = expand_unit_names(bus, patterns, NULL, &units, NULL);
156 if (r < 0)
157 return log_error_errno(r, "Failed to expand names: %m");
158 }
159
160 pager_open(arg_pager_flags);
161
162 STRV_FOREACH(u, units) {
163 if (u != units)
164 puts("");
165
166 puts(*u);
167 r = list_dependencies_one(bus, *u, 0, &done, 0);
168 if (r < 0)
169 return r;
170 }
171
172 return 0;
173 }