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