chiark / gitweb /
cgls: don't show empty cgroups by default
[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 "util.h"
33 #include "pager.h"
34 #include "build.h"
35
36 static bool arg_no_pager = false;
37 static bool arg_kernel_threads = false;
38 static bool arg_all = false;
39
40 static void help(void) {
41
42         printf("%s [OPTIONS...] [CGROUP...]\n\n"
43                "Recursively show control group contents.\n\n"
44                "  -h --help           Show this help\n"
45                "     --version        Show package version\n"
46                "     --no-pager       Do not pipe output into a pager\n"
47                "  -a --all            Show all groups, including empty\n"
48                "  -k                  Include kernel threads in output\n",
49                program_invocation_short_name);
50 }
51
52 static int parse_argv(int argc, char *argv[]) {
53
54         enum {
55                 ARG_NO_PAGER = 0x100,
56                 ARG_VERSION
57         };
58
59         static const struct option options[] = {
60                 { "help",      no_argument,       NULL, 'h'          },
61                 { "version",   no_argument,       NULL, ARG_VERSION  },
62                 { "no-pager",  no_argument,       NULL, ARG_NO_PAGER },
63                 { "all",       no_argument,       NULL, 'a'          },
64                 { NULL,        0,                 NULL, 0            }
65         };
66
67         int c;
68
69         assert(argc >= 1);
70         assert(argv);
71
72         while ((c = getopt_long(argc, argv, "hka", options, NULL)) >= 0) {
73
74                 switch (c) {
75
76                 case 'h':
77                         help();
78                         return 0;
79
80                 case ARG_VERSION:
81                         puts(PACKAGE_STRING);
82                         puts(DISTRIBUTION);
83                         puts(SYSTEMD_FEATURES);
84                         return 0;
85
86                 case ARG_NO_PAGER:
87                         arg_no_pager = true;
88                         break;
89
90                 case 'a':
91                         arg_all = true;
92                         break;
93
94                 case 'k':
95                         arg_kernel_threads = true;
96                         break;
97
98                 case '?':
99                         return -EINVAL;
100
101                 default:
102                         log_error("Unknown option code %c", c);
103                         return -EINVAL;
104                 }
105         }
106
107         return 1;
108 }
109
110 int main(int argc, char *argv[]) {
111         int r = 0, retval = EXIT_FAILURE;
112
113         log_parse_environment();
114         log_open();
115
116         r = parse_argv(argc, argv);
117         if (r < 0)
118                 goto finish;
119         else if (r == 0) {
120                 retval = EXIT_SUCCESS;
121                 goto finish;
122         }
123
124         if (!arg_no_pager)
125                 pager_open();
126
127         if (optind < argc) {
128                 unsigned i;
129
130                 for (i = (unsigned) optind; i < (unsigned) argc; i++) {
131                         int q;
132                         printf("%s:\n", argv[i]);
133
134                         q = show_cgroup_by_path(argv[i], NULL, 0, arg_kernel_threads, arg_all);
135                         if (q < 0)
136                                 r = q;
137                 }
138
139         } else {
140                 char *p;
141
142                 p = get_current_dir_name();
143                 if (!p) {
144                         log_error("Cannot determine current working directory: %m");
145                         goto finish;
146                 }
147
148                 if (path_startswith(p, "/sys/fs/cgroup")) {
149                         printf("Working Directory %s:\n", p);
150                         r = show_cgroup_by_path(p, NULL, 0, arg_kernel_threads, arg_all);
151                 } else {
152                         char *root = NULL;
153                         const char *t = NULL;
154
155                         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
156                         if (r < 0)
157                                 t = "/";
158                         else {
159                                 if (endswith(root, "/system"))
160                                         root[strlen(root)-7] = 0;
161
162                                 t = root[0] ? root : "/";
163                         }
164
165                         r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, t, NULL, 0, arg_kernel_threads, arg_all);
166                         free(root);
167                 }
168
169                 free(p);
170         }
171
172         if (r < 0)
173                 log_error("Failed to list cgroup tree: %s", strerror(-r));
174
175         retval = EXIT_SUCCESS;
176
177 finish:
178         pager_close();
179
180         return retval;
181 }