chiark / gitweb /
cgls,loginctl,systemctl: fix -l
[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 <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
38 static bool arg_no_pager = false;
39 static bool arg_kernel_threads = false;
40 static bool arg_all = false;
41 static int arg_full = -1;
42 static char* arg_machine = NULL;
43
44 static void help(void) {
45
46         printf("%s [OPTIONS...] [CGROUP...]\n\n"
47                "Recursively show control group contents.\n\n"
48                "  -h --help           Show this help\n"
49                "     --version        Show package version\n"
50                "     --no-pager       Do not pipe output into a pager\n"
51                "  -a --all            Show all groups, including empty\n"
52                "  -l --full           Do not ellipsize output\n"
53                "  -k                  Include kernel threads in output\n"
54                "  -M --machine        Show container\n",
55                program_invocation_short_name);
56 }
57
58 static int parse_argv(int argc, char *argv[]) {
59
60         enum {
61                 ARG_NO_PAGER = 0x100,
62                 ARG_VERSION,
63         };
64
65         static const struct option options[] = {
66                 { "help",      no_argument,       NULL, 'h'          },
67                 { "version",   no_argument,       NULL, ARG_VERSION  },
68                 { "no-pager",  no_argument,       NULL, ARG_NO_PAGER },
69                 { "all",       no_argument,       NULL, 'a'          },
70                 { "full",      no_argument,       NULL, 'l'          },
71                 { "machine",   required_argument, NULL, 'M'          },
72                 { NULL,        0,                 NULL, 0            }
73         };
74
75         int c;
76
77         assert(argc >= 1);
78         assert(argv);
79
80         while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) {
81
82                 switch (c) {
83
84                 case 'h':
85                         help();
86                         return 0;
87
88                 case ARG_VERSION:
89                         puts(PACKAGE_STRING);
90                         puts(SYSTEMD_FEATURES);
91                         return 0;
92
93                 case ARG_NO_PAGER:
94                         arg_no_pager = true;
95                         break;
96
97                 case 'a':
98                         arg_all = true;
99                         break;
100
101                 case 'l':
102                         arg_full = true;
103                         break;
104
105                 case 'k':
106                         arg_kernel_threads = true;
107                         break;
108
109                 case 'M':
110                         arg_machine = optarg;
111                         break;
112
113                 case '?':
114                         return -EINVAL;
115
116                 default:
117                         log_error("Unknown option code %c", c);
118                         return -EINVAL;
119                 }
120         }
121
122         return 1;
123 }
124
125 int main(int argc, char *argv[]) {
126         int r = 0, retval = EXIT_FAILURE;
127         int output_flags;
128         char _cleanup_free_ *root = NULL;
129
130         log_parse_environment();
131         log_open();
132
133         r = parse_argv(argc, argv);
134         if (r < 0)
135                 goto finish;
136         else if (r == 0) {
137                 retval = EXIT_SUCCESS;
138                 goto finish;
139         }
140
141         if (!arg_no_pager) {
142                 r = pager_open(false);
143                 if (r > 0) {
144                         if (arg_full == -1)
145                                 arg_full = true;
146                 }
147         }
148
149         output_flags =
150                 arg_all * OUTPUT_SHOW_ALL |
151                 (arg_full > 0) * OUTPUT_FULL_WIDTH;
152
153         if (optind < argc) {
154                 int i;
155
156                 for (i = optind; i < argc; i++) {
157                         int q;
158                         printf("%s:\n", argv[i]);
159
160                         if (arg_machine)
161                                 root = strjoin("machine/", arg_machine, "/", argv[i], NULL);
162                         else
163                                 root = strdup(argv[i]);
164                         if (!root)
165                                 return log_oom();
166
167                         q = show_cgroup_by_path(root, NULL, 0,
168                                                 arg_kernel_threads, output_flags);
169                         if (q < 0)
170                                 r = q;
171                 }
172
173         } else {
174                 _cleanup_free_ char *p;
175
176                 p = get_current_dir_name();
177                 if (!p) {
178                         log_error("Cannot determine current working directory: %m");
179                         goto finish;
180                 }
181
182                 if (path_startswith(p, "/sys/fs/cgroup") && !arg_machine) {
183                         printf("Working Directory %s:\n", p);
184                         r = show_cgroup_by_path(p, NULL, 0,
185                                                 arg_kernel_threads, output_flags);
186                 } else {
187                         if (arg_machine)
188                                 r = cg_get_machine_path(arg_machine, &root);
189                         else
190                                 r = cg_get_root_path(&root);
191                         if (r < 0) {
192                                 log_error("Failed to get %s path: %s",
193                                           arg_machine ? "machine" : "root", strerror(-r));
194                                 goto finish;
195                         }
196
197                         r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0,
198                                         arg_kernel_threads, output_flags);
199                 }
200         }
201
202         if (r < 0) {
203                 log_error("Failed to list cgroup tree %s: %s", root, strerror(-r));
204                 retval = EXIT_FAILURE;
205         } else
206                 retval = EXIT_SUCCESS;
207
208 finish:
209         pager_close();
210
211         return retval;
212 }