]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/cgroup-show.c
login/sd-login.c: make use of _cleanup_free_ and friends
[thirdparty/systemd.git] / src / shared / cgroup-show.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ab35fb1b
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
ab35fb1b
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.
ab35fb1b 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
ab35fb1b
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <stdio.h>
23#include <string.h>
fa776d8e
LP
24#include <dirent.h>
25#include <errno.h>
ab35fb1b
LP
26
27#include "util.h"
28#include "macro.h"
9eb977db 29#include "path-util.h"
c6c18be3 30#include "cgroup-util.h"
ab35fb1b
LP
31#include "cgroup-show.h"
32
33static int compare(const void *a, const void *b) {
34 const pid_t *p = a, *q = b;
35
36 if (*p < *q)
37 return -1;
38 if (*p > *q)
39 return 1;
40 return 0;
41}
42
9bdbc2e2 43static void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
4278aa27 44 unsigned i, m, pid_width;
b69d29ce
LP
45 pid_t biggest = 0;
46
47 /* Filter duplicates */
48 m = 0;
49 for (i = 0; i < n_pids; i++) {
50 unsigned j;
51
52 if (pids[i] > biggest)
53 biggest = pids[i];
54
55 for (j = i+1; j < n_pids; j++)
56 if (pids[i] == pids[j])
57 break;
58
59 if (j >= n_pids)
60 pids[m++] = pids[i];
61 }
62 n_pids = m;
82da66fb 63 pid_width = DECIMAL_STR_WIDTH(biggest);
b69d29ce
LP
64
65 /* And sort */
66 qsort(pids, n_pids, sizeof(pid_t), compare);
67
9bdbc2e2
LN
68 if(flags & OUTPUT_FULL_WIDTH)
69 n_columns = 0;
70 else {
71 if (n_columns > pid_width+2)
72 n_columns -= pid_width+2;
73 else
74 n_columns = 20;
75 }
b69d29ce
LP
76 for (i = 0; i < n_pids; i++) {
77 char *t = NULL;
78
79 get_process_cmdline(pids[i], n_columns, true, &t);
80
45a5ff0d 81 printf("%s%s%*lu %s\n",
b69d29ce 82 prefix,
c339d977 83 draw_special_char(extra ? DRAW_TRIANGULAR_BULLET :
45a5ff0d 84 ((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)),
4278aa27 85 pid_width,
b69d29ce
LP
86 (unsigned long) pids[i],
87 strna(t));
88
89 free(t);
90 }
91}
92
93
9bdbc2e2 94static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) {
ab35fb1b 95 char *fn;
7027ff61 96 _cleanup_fclose_ FILE *f = NULL;
ab35fb1b 97 size_t n = 0, n_allocated = 0;
7027ff61
LP
98 _cleanup_free_ pid_t *pids = NULL;
99 char *p = NULL;
b69d29ce 100 pid_t pid;
fa776d8e 101 int r;
ab35fb1b 102
7027ff61 103 r = cg_mangle_path(path, &p);
b69d29ce 104 if (r < 0)
35d2e7ec 105 return r;
ab35fb1b 106
7027ff61 107 fn = strappend(p, "/cgroup.procs");
fa776d8e 108 free(p);
7027ff61 109 if (!fn)
fa776d8e
LP
110 return -ENOMEM;
111
112 f = fopen(fn, "re");
ab35fb1b 113 free(fn);
ab35fb1b 114 if (!f)
fa776d8e 115 return -errno;
ab35fb1b 116
c6c18be3 117 while ((r = cg_read_pid(f, &pid)) > 0) {
ab35fb1b 118
1e5678d0
LP
119 if (!kernel_threads && is_kernel_thread(pid) > 0)
120 continue;
121
ab35fb1b
LP
122 if (n >= n_allocated) {
123 pid_t *npids;
124
125 n_allocated = MAX(16U, n*2U);
126
b69d29ce 127 npids = realloc(pids, sizeof(pid_t) * n_allocated);
7027ff61
LP
128 if (!npids)
129 return -ENOMEM;
ab35fb1b
LP
130
131 pids = npids;
132 }
133
134 assert(n < n_allocated);
c6c18be3 135 pids[n++] = pid;
ab35fb1b
LP
136 }
137
c6c18be3 138 if (r < 0)
7027ff61 139 return r;
c6c18be3 140
b69d29ce 141 if (n > 0)
9bdbc2e2 142 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags);
ab35fb1b 143
7027ff61 144 return 0;
fa776d8e
LP
145}
146
9bdbc2e2 147int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61
LP
148 _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
149 _cleanup_closedir_ DIR *d = NULL;
150 char *gn = NULL;
fa776d8e
LP
151 bool shown_pids = false;
152 int r;
153
b69d29ce
LP
154 assert(path);
155
fa776d8e
LP
156 if (n_columns <= 0)
157 n_columns = columns();
158
159 if (!prefix)
160 prefix = "";
161
7027ff61 162 r = cg_mangle_path(path, &fn);
c3175a7f 163 if (r < 0)
35d2e7ec 164 return r;
fa776d8e 165
c3175a7f 166 d = opendir(fn);
7027ff61 167 if (!d)
fa776d8e 168 return -errno;
fa776d8e 169
35d2e7ec 170 while ((r = cg_read_subgroup(d, &gn)) > 0) {
7027ff61 171 _cleanup_free_ char *k = NULL;
c3175a7f 172
7027ff61 173 k = strjoin(fn, "/", gn, NULL);
c3175a7f 174 free(gn);
7027ff61
LP
175 if (!k)
176 return -ENOMEM;
c3175a7f 177
7027ff61 178 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k, false) > 0)
c3175a7f 179 continue;
fa776d8e
LP
180
181 if (!shown_pids) {
9bdbc2e2 182 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags);
fa776d8e
LP
183 shown_pids = true;
184 }
185
186 if (last) {
45a5ff0d
MS
187 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH),
188 path_get_file_name(last));
fa776d8e 189
c3175a7f 190 if (!p1) {
45a5ff0d 191 p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERT));
7027ff61
LP
192 if (!p1)
193 return -ENOMEM;
c3175a7f 194 }
fa776d8e 195
9bdbc2e2 196 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags);
fa776d8e 197 free(last);
fa776d8e
LP
198 }
199
c3175a7f 200 last = k;
7027ff61 201 k = NULL;
fa776d8e
LP
202 }
203
35d2e7ec 204 if (r < 0)
7027ff61 205 return r;
35d2e7ec 206
fa776d8e 207 if (!shown_pids)
9bdbc2e2 208 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags);
fa776d8e
LP
209
210 if (last) {
45a5ff0d
MS
211 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT),
212 path_get_file_name(last));
fa776d8e 213
c3175a7f
LP
214 if (!p2) {
215 p2 = strappend(prefix, " ");
7027ff61
LP
216 if (!p2)
217 return -ENOMEM;
c3175a7f 218 }
fa776d8e 219
9bdbc2e2 220 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags);
fa776d8e
LP
221 }
222
7027ff61 223 return 0;
ab35fb1b 224}
35d2e7ec 225
9bdbc2e2 226int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61 227 _cleanup_free_ char *p = NULL;
35d2e7ec
LP
228 int r;
229
35d2e7ec
LP
230 assert(path);
231
1e5678d0
LP
232 r = cg_get_path(controller, path, NULL, &p);
233 if (r < 0)
35d2e7ec
LP
234 return r;
235
7027ff61 236 return show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags);
35d2e7ec 237}
b69d29ce 238
9bdbc2e2 239static int show_extra_pids(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t pids[], unsigned n_pids, OutputFlags flags) {
050fbdb8 240 pid_t _cleanup_free_ *copy = NULL;
b69d29ce
LP
241 unsigned i, j;
242 int r;
243
244 assert(controller);
245 assert(path);
246
247 if (n_pids <= 0)
248 return 0;
249
250 if (n_columns <= 0)
251 n_columns = columns();
252
7027ff61 253 prefix = strempty(prefix);
b69d29ce
LP
254
255 copy = new(pid_t, n_pids);
256 if (!copy)
257 return -ENOMEM;
258
259 for (i = 0, j = 0; i < n_pids; i++) {
050fbdb8 260 char _cleanup_free_ *k = NULL;
b69d29ce 261
7027ff61 262 r = cg_pid_get_path(controller, pids[i], &k);
050fbdb8 263 if (r < 0)
b69d29ce 264 return r;
b69d29ce
LP
265
266 if (path_startswith(k, path))
267 continue;
268
269 copy[j++] = pids[i];
270 }
271
9bdbc2e2 272 show_pid_array(copy, j, prefix, n_columns, true, false, false, flags);
b69d29ce 273
b69d29ce
LP
274 return 0;
275}
276
9bdbc2e2 277int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags) {
b69d29ce
LP
278 int r;
279
b69d29ce
LP
280 assert(path);
281
9bdbc2e2 282 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags);
b69d29ce
LP
283 if (r < 0)
284 return r;
285
9bdbc2e2 286 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
b69d29ce
LP
287}
288
9bdbc2e2 289int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags) {
b08121d0 290 _cleanup_free_ char *controller = NULL, *path = NULL;
7027ff61 291 int r;
b69d29ce
LP
292
293 assert(spec);
294
295 r = cg_split_spec(spec, &controller, &path);
296 if (r < 0)
297 return r;
298
9bdbc2e2 299 return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags);
b69d29ce 300}