]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/cgls/cgls.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / cgls / cgls.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
fa776d8e
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
fa776d8e
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
fa776d8e 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
fa776d8e
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
fa776d8e
LP
22#include <errno.h>
23#include <getopt.h>
3f6fd1ba 24#include <stdio.h>
fa776d8e 25#include <string.h>
3f6fd1ba
LP
26#include <unistd.h>
27
28#include "sd-bus.h"
fa776d8e 29
b5efdb8a 30#include "alloc-util.h"
3f6fd1ba
LP
31#include "bus-error.h"
32#include "bus-util.h"
fa776d8e 33#include "cgroup-show.h"
c6c18be3 34#include "cgroup-util.h"
3f6fd1ba 35#include "fileio.h"
fa776d8e 36#include "log.h"
9bdbc2e2 37#include "output-mode.h"
3f6fd1ba
LP
38#include "pager.h"
39#include "path-util.h"
13be4979 40#include "unit-name.h"
3f6fd1ba 41#include "util.h"
1968a360
LP
42
43static bool arg_no_pager = false;
1e5678d0 44static bool arg_kernel_threads = false;
c3175a7f 45static bool arg_all = false;
9bdbc2e2 46static int arg_full = -1;
38158b92 47static char* arg_machine = NULL;
fa776d8e 48
601185b4 49static void help(void) {
fa776d8e
LP
50 printf("%s [OPTIONS...] [CGROUP...]\n\n"
51 "Recursively show control group contents.\n\n"
69fc152f 52 " -h --help Show this help\n"
c3175a7f 53 " --version Show package version\n"
1e5678d0 54 " --no-pager Do not pipe output into a pager\n"
c3175a7f 55 " -a --all Show all groups, including empty\n"
98a6e132 56 " -l --full Do not ellipsize output\n"
38158b92 57 " -k Include kernel threads in output\n"
e049fa16 58 " -M --machine= Show container\n"
601185b4 59 , program_invocation_short_name);
fa776d8e
LP
60}
61
62static int parse_argv(int argc, char *argv[]) {
63
1968a360 64 enum {
c3175a7f 65 ARG_NO_PAGER = 0x100,
9bdbc2e2 66 ARG_VERSION,
1968a360
LP
67 };
68
fa776d8e 69 static const struct option options[] = {
1968a360 70 { "help", no_argument, NULL, 'h' },
c3175a7f 71 { "version", no_argument, NULL, ARG_VERSION },
1968a360 72 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
c3175a7f 73 { "all", no_argument, NULL, 'a' },
98a6e132 74 { "full", no_argument, NULL, 'l' },
38158b92 75 { "machine", required_argument, NULL, 'M' },
eb9da376 76 {}
fa776d8e
LP
77 };
78
79 int c;
80
81 assert(argc >= 1);
82 assert(argv);
83
601185b4 84 while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0)
fa776d8e
LP
85
86 switch (c) {
87
88 case 'h':
601185b4
ZJS
89 help();
90 return 0;
fa776d8e 91
c3175a7f 92 case ARG_VERSION:
3f6fd1ba 93 return version();
c3175a7f 94
1968a360
LP
95 case ARG_NO_PAGER:
96 arg_no_pager = true;
97 break;
98
c3175a7f
LP
99 case 'a':
100 arg_all = true;
101 break;
102
98a6e132 103 case 'l':
9bdbc2e2
LN
104 arg_full = true;
105 break;
106
1e5678d0
LP
107 case 'k':
108 arg_kernel_threads = true;
109 break;
110
38158b92
ZJS
111 case 'M':
112 arg_machine = optarg;
113 break;
114
fa776d8e
LP
115 case '?':
116 return -EINVAL;
117
118 default:
eb9da376 119 assert_not_reached("Unhandled option");
fa776d8e 120 }
fa776d8e
LP
121
122 return 1;
123}
124
e049fa16
LP
125static int get_cgroup_root(char **ret) {
126 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
03976f7b 127 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
e049fa16
LP
128 _cleanup_free_ char *unit = NULL, *path = NULL;
129 const char *m;
130 int r;
131
132 if (!arg_machine) {
133 r = cg_get_root_path(ret);
134 if (r < 0)
135 return log_error_errno(r, "Failed to get root control group path: %m");
136
137 return 0;
138 }
139
140 m = strjoina("/run/systemd/machines/", arg_machine);
141 r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL);
142 if (r < 0)
143 return log_error_errno(r, "Failed to load machine data: %m");
144
145 path = unit_dbus_path_from_name(unit);
146 if (!path)
147 return log_oom();
148
266f3e26 149 r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
e049fa16
LP
150 if (r < 0)
151 return log_error_errno(r, "Failed to create bus connection: %m");
152
153 r = sd_bus_get_property_string(
154 bus,
155 "org.freedesktop.systemd1",
156 path,
157 unit_dbus_interface_from_name(unit),
158 "ControlGroup",
159 &error,
160 ret);
161 if (r < 0)
cb88a0a4 162 return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r));
e049fa16
LP
163
164 return 0;
165}
166
58033c91
EV
167static void show_cg_info(const char *controller, const char *path) {
168 if (cg_unified() <= 0)
169 printf("Controller %s; ", controller);
170 printf("Control group %s:\n", isempty(path) ? "/" : path);
171 fflush(stdout);
172}
173
e049fa16
LP
174int main(int argc, char *argv[]) {
175 int r, output_flags;
fa776d8e
LP
176
177 log_parse_environment();
2396fb04 178 log_open();
fa776d8e 179
1e5678d0 180 r = parse_argv(argc, argv);
e049fa16 181 if (r <= 0)
fa776d8e 182 goto finish;
fa776d8e 183
9bdbc2e2 184 if (!arg_no_pager) {
1b12a7b5 185 r = pager_open(false);
e049fa16
LP
186 if (r > 0 && arg_full < 0)
187 arg_full = true;
9bdbc2e2
LN
188 }
189
190 output_flags =
191 arg_all * OUTPUT_SHOW_ALL |
192 (arg_full > 0) * OUTPUT_FULL_WIDTH;
1968a360 193
fa776d8e 194 if (optind < argc) {
e049fa16 195 _cleanup_free_ char *root = NULL;
38158b92 196 int i;
fa776d8e 197
e049fa16
LP
198 r = get_cgroup_root(&root);
199 if (r < 0)
200 goto finish;
201
38158b92 202 for (i = optind; i < argc; i++) {
fa776d8e 203 int q;
baa89da4 204
e049fa16 205 if (path_startswith(argv[i], "/sys/fs/cgroup")) {
fa776d8e 206
e049fa16
LP
207 printf("Directory %s:\n", argv[i]);
208 fflush(stdout);
fa776d8e 209
e049fa16
LP
210 q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, output_flags);
211 } else {
212 _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL;
213 const char *controller, *path;
fa776d8e 214
e049fa16 215 r = cg_split_spec(argv[i], &c, &p);
13be4979 216 if (r < 0) {
e049fa16 217 log_error_errno(r, "Failed to split argument %s: %m", argv[i]);
13be4979
LN
218 goto finish;
219 }
220
e049fa16
LP
221 controller = c ?: SYSTEMD_CGROUP_CONTROLLER;
222 if (p) {
223 j = strjoin(root, "/", p, NULL);
224 if (!j) {
225 r = log_oom();
226 goto finish;
227 }
13be4979 228
e049fa16
LP
229 path_kill_slashes(j);
230 path = j;
231 } else
232 path = root;
13be4979 233
58033c91 234 show_cg_info(controller, path);
13be4979 235
e049fa16
LP
236 q = show_cgroup(controller, path, NULL, 0, arg_kernel_threads, output_flags);
237 }
13be4979 238
e049fa16
LP
239 if (q < 0)
240 r = q;
241 }
242
243 } else {
244 bool done = false;
13be4979 245
e049fa16
LP
246 if (!arg_machine) {
247 _cleanup_free_ char *cwd = NULL;
248
249 cwd = get_current_dir_name();
250 if (!cwd) {
251 r = log_error_errno(errno, "Cannot determine current working directory: %m");
7027ff61 252 goto finish;
b9a8e638 253 }
1f16b4a6 254
e049fa16
LP
255 if (path_startswith(cwd, "/sys/fs/cgroup")) {
256 printf("Working directory %s:\n", cwd);
257 fflush(stdout);
258
259 r = show_cgroup_by_path(cwd, NULL, 0, arg_kernel_threads, output_flags);
260 done = true;
261 }
262 }
263
264 if (!done) {
265 _cleanup_free_ char *root = NULL;
266
267 r = get_cgroup_root(&root);
268 if (r < 0)
269 goto finish;
270
58033c91 271 show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root);
e049fa16
LP
272
273 r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, arg_kernel_threads, output_flags);
1f16b4a6 274 }
fa776d8e
LP
275 }
276
e049fa16
LP
277 if (r < 0)
278 log_error_errno(r, "Failed to list cgroup tree: %m");
fa776d8e
LP
279
280finish:
1968a360 281 pager_close();
fa776d8e 282
e049fa16 283 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
fa776d8e 284}