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