]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/cgls/cgls.c
treewide: no need to negate errno for log_*_errno()
[thirdparty/systemd.git] / src / cgls / cgls.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <limits.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <getopt.h>
27 #include <string.h>
28
29 #include "cgroup-show.h"
30 #include "cgroup-util.h"
31 #include "log.h"
32 #include "path-util.h"
33 #include "util.h"
34 #include "pager.h"
35 #include "build.h"
36 #include "output-mode.h"
37 #include "fileio.h"
38 #include "sd-bus.h"
39 #include "bus-util.h"
40 #include "bus-error.h"
41 #include "unit-name.h"
42
43 static bool arg_no_pager = false;
44 static bool arg_kernel_threads = false;
45 static bool arg_all = false;
46 static int arg_full = -1;
47 static char* arg_machine = NULL;
48
49 static void help(void) {
50 printf("%s [OPTIONS...] [CGROUP...]\n\n"
51 "Recursively show control group contents.\n\n"
52 " -h --help Show this help\n"
53 " --version Show package version\n"
54 " --no-pager Do not pipe output into a pager\n"
55 " -a --all Show all groups, including empty\n"
56 " -l --full Do not ellipsize output\n"
57 " -k Include kernel threads in output\n"
58 " -M --machine Show container\n"
59 , program_invocation_short_name);
60 }
61
62 static int parse_argv(int argc, char *argv[]) {
63
64 enum {
65 ARG_NO_PAGER = 0x100,
66 ARG_VERSION,
67 };
68
69 static const struct option options[] = {
70 { "help", no_argument, NULL, 'h' },
71 { "version", no_argument, NULL, ARG_VERSION },
72 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
73 { "all", no_argument, NULL, 'a' },
74 { "full", no_argument, NULL, 'l' },
75 { "machine", required_argument, NULL, 'M' },
76 {}
77 };
78
79 int c;
80
81 assert(argc >= 1);
82 assert(argv);
83
84 while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0)
85
86 switch (c) {
87
88 case 'h':
89 help();
90 return 0;
91
92 case ARG_VERSION:
93 puts(PACKAGE_STRING);
94 puts(SYSTEMD_FEATURES);
95 return 0;
96
97 case ARG_NO_PAGER:
98 arg_no_pager = true;
99 break;
100
101 case 'a':
102 arg_all = true;
103 break;
104
105 case 'l':
106 arg_full = true;
107 break;
108
109 case 'k':
110 arg_kernel_threads = true;
111 break;
112
113 case 'M':
114 arg_machine = optarg;
115 break;
116
117 case '?':
118 return -EINVAL;
119
120 default:
121 assert_not_reached("Unhandled option");
122 }
123
124 return 1;
125 }
126
127 int main(int argc, char *argv[]) {
128 int r = 0, retval = EXIT_FAILURE;
129 int output_flags;
130 _cleanup_free_ char *root = NULL;
131 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
132
133 log_parse_environment();
134 log_open();
135
136 r = parse_argv(argc, argv);
137 if (r < 0)
138 goto finish;
139 else if (r == 0) {
140 retval = EXIT_SUCCESS;
141 goto finish;
142 }
143
144 if (!arg_no_pager) {
145 r = pager_open(false);
146 if (r > 0) {
147 if (arg_full == -1)
148 arg_full = true;
149 }
150 }
151
152 output_flags =
153 arg_all * OUTPUT_SHOW_ALL |
154 (arg_full > 0) * OUTPUT_FULL_WIDTH;
155
156 r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
157 if (r < 0) {
158 log_error_errno(r, "Failed to create bus connection: %m");
159 goto finish;
160 }
161
162 if (optind < argc) {
163 int i;
164
165 for (i = optind; i < argc; i++) {
166 int q;
167
168 fprintf(stdout, "%s:\n", argv[i]);
169 fflush(stdout);
170
171 if (arg_machine)
172 root = strjoin("machine/", arg_machine, "/", argv[i], NULL);
173 else
174 root = strdup(argv[i]);
175 if (!root)
176 return log_oom();
177
178 q = show_cgroup_by_path(root, NULL, 0,
179 arg_kernel_threads, output_flags);
180 if (q < 0)
181 r = q;
182 }
183
184 } else {
185 _cleanup_free_ char *p;
186
187 p = get_current_dir_name();
188 if (!p) {
189 log_error("Cannot determine current working directory: %m");
190 goto finish;
191 }
192
193 if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) {
194 printf("Working Directory %s:\n", p);
195 r = show_cgroup_by_path(p, NULL, 0,
196 arg_kernel_threads, output_flags);
197 } else {
198 if (arg_machine) {
199 char *m;
200 const char *cgroup;
201 _cleanup_free_ char *scope = NULL;
202 _cleanup_free_ char *path = NULL;
203 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
204 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
205
206 m = strappenda("/run/systemd/machines/", arg_machine);
207 r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL);
208 if (r < 0) {
209 log_error_errno(r, "Failed to get machine path: %m");
210 goto finish;
211 }
212
213 path = unit_dbus_path_from_name(scope);
214 if (!path) {
215 log_oom();
216 goto finish;
217 }
218
219 r = sd_bus_get_property(
220 bus,
221 "org.freedesktop.systemd1",
222 path,
223 "org.freedesktop.systemd1.Scope",
224 "ControlGroup",
225 &error,
226 &reply,
227 "s");
228
229 if (r < 0) {
230 log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r));
231 goto finish;
232 }
233
234 r = sd_bus_message_read(reply, "s", &cgroup);
235 if (r < 0) {
236 bus_log_parse_error(r);
237 goto finish;
238 }
239
240 root = strdup(cgroup);
241 if (!root) {
242 log_oom();
243 goto finish;
244 }
245
246 } else
247 r = cg_get_root_path(&root);
248 if (r < 0) {
249 log_error("Failed to get %s path: %s",
250 arg_machine ? "machine" : "root", strerror(-r));
251 goto finish;
252 }
253
254 r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0,
255 arg_kernel_threads, output_flags);
256 }
257 }
258
259 if (r < 0) {
260 log_error_errno(r, "Failed to list cgroup tree %s: %m", root);
261 retval = EXIT_FAILURE;
262 } else
263 retval = EXIT_SUCCESS;
264
265 finish:
266 pager_close();
267
268 return retval;
269 }