]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/cgls/cgls.c
util: rework strappenda(), and rename it strjoina()
[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
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"
c6c18be3 30#include "cgroup-util.h"
fa776d8e 31#include "log.h"
9eb977db 32#include "path-util.h"
fa776d8e 33#include "util.h"
1968a360 34#include "pager.h"
c3175a7f 35#include "build.h"
9bdbc2e2 36#include "output-mode.h"
9444b1f2 37#include "fileio.h"
13be4979
LN
38#include "sd-bus.h"
39#include "bus-util.h"
40#include "bus-error.h"
41#include "unit-name.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"
601185b4
ZJS
58 " -M --machine Show container\n"
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
LP
92 case ARG_VERSION:
93 puts(PACKAGE_STRING);
c3175a7f
LP
94 puts(SYSTEMD_FEATURES);
95 return 0;
96
1968a360
LP
97 case ARG_NO_PAGER:
98 arg_no_pager = true;
99 break;
100
c3175a7f
LP
101 case 'a':
102 arg_all = true;
103 break;
104
98a6e132 105 case 'l':
9bdbc2e2
LN
106 arg_full = true;
107 break;
108
1e5678d0
LP
109 case 'k':
110 arg_kernel_threads = true;
111 break;
112
38158b92
ZJS
113 case 'M':
114 arg_machine = optarg;
115 break;
116
fa776d8e
LP
117 case '?':
118 return -EINVAL;
119
120 default:
eb9da376 121 assert_not_reached("Unhandled option");
fa776d8e 122 }
fa776d8e
LP
123
124 return 1;
125}
126
127int main(int argc, char *argv[]) {
22f4096c 128 int r = 0, retval = EXIT_FAILURE;
9bdbc2e2 129 int output_flags;
c8b32e11 130 _cleanup_free_ char *root = NULL;
24996861 131 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
fa776d8e
LP
132
133 log_parse_environment();
2396fb04 134 log_open();
fa776d8e 135
1e5678d0
LP
136 r = parse_argv(argc, argv);
137 if (r < 0)
fa776d8e
LP
138 goto finish;
139 else if (r == 0) {
22f4096c 140 retval = EXIT_SUCCESS;
fa776d8e
LP
141 goto finish;
142 }
143
9bdbc2e2 144 if (!arg_no_pager) {
1b12a7b5 145 r = pager_open(false);
9bdbc2e2
LN
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;
1968a360 155
13be4979
LN
156 r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
157 if (r < 0) {
da927ba9 158 log_error_errno(r, "Failed to create bus connection: %m");
13be4979
LN
159 goto finish;
160 }
161
fa776d8e 162 if (optind < argc) {
38158b92 163 int i;
fa776d8e 164
38158b92 165 for (i = optind; i < argc; i++) {
fa776d8e 166 int q;
baa89da4
LP
167
168 fprintf(stdout, "%s:\n", argv[i]);
169 fflush(stdout);
fa776d8e 170
38158b92
ZJS
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,
9bdbc2e2 179 arg_kernel_threads, output_flags);
1e5678d0 180 if (q < 0)
fa776d8e
LP
181 r = q;
182 }
183
184 } else {
7fd1b19b 185 _cleanup_free_ char *p;
fa776d8e 186
1e5678d0
LP
187 p = get_current_dir_name();
188 if (!p) {
56f64d95 189 log_error_errno(errno, "Cannot determine current working directory: %m");
fa776d8e
LP
190 goto finish;
191 }
192
38158b92 193 if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) {
fa776d8e 194 printf("Working Directory %s:\n", p);
9bdbc2e2
LN
195 r = show_cgroup_by_path(p, NULL, 0,
196 arg_kernel_threads, output_flags);
1f16b4a6 197 } else {
9444b1f2
LP
198 if (arg_machine) {
199 char *m;
13be4979
LN
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
63c372cb 206 m = strjoina("/run/systemd/machines/", arg_machine);
13be4979
LN
207 r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL);
208 if (r < 0) {
da927ba9 209 log_error_errno(r, "Failed to get machine path: %m");
13be4979
LN
210 goto finish;
211 }
212
213 path = unit_dbus_path_from_name(scope);
214 if (!path) {
5706b3e7 215 log_oom();
13be4979
LN
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) {
5706b3e7 242 log_oom();
13be4979
LN
243 goto finish;
244 }
245
9444b1f2 246 } else
38158b92 247 r = cg_get_root_path(&root);
7027ff61 248 if (r < 0) {
c33b3297
MS
249 log_error_errno(r, "Failed to get %s path: %m",
250 arg_machine ? "machine" : "root");
7027ff61 251 goto finish;
b9a8e638 252 }
1f16b4a6 253
7027ff61 254 r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0,
9bdbc2e2 255 arg_kernel_threads, output_flags);
1f16b4a6 256 }
fa776d8e
LP
257 }
258
38158b92 259 if (r < 0) {
da927ba9 260 log_error_errno(r, "Failed to list cgroup tree %s: %m", root);
38158b92
ZJS
261 retval = EXIT_FAILURE;
262 } else
263 retval = EXIT_SUCCESS;
fa776d8e
LP
264
265finish:
1968a360 266 pager_close();
fa776d8e
LP
267
268 return retval;
269}