]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/cgroup-show.c
util-lib: split our string related calls from util.[ch] into its own file string...
[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
fa776d8e
LP
22#include <dirent.h>
23#include <errno.h>
07630cea
LP
24#include <stdio.h>
25#include <string.h>
ab35fb1b 26
07630cea 27#include "cgroup-util.h"
6482f626 28#include "formats-util.h"
ab35fb1b 29#include "macro.h"
9eb977db 30#include "path-util.h"
07630cea
LP
31#include "process-util.h"
32#include "string-util.h"
288a74cc 33#include "terminal-util.h"
07630cea
LP
34#include "util.h"
35#include "cgroup-show.h"
ab35fb1b
LP
36
37static int compare(const void *a, const void *b) {
38 const pid_t *p = a, *q = b;
39
40 if (*p < *q)
41 return -1;
42 if (*p > *q)
43 return 1;
44 return 0;
45}
46
3da7a50f
ZJS
47static void show_pid_array(pid_t pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
48 unsigned i, j, pid_width;
b69d29ce 49
da41abc5 50 if (n_pids == 0)
3637713a
LP
51 return;
52
3da7a50f 53 qsort(pids, n_pids, sizeof(pid_t), compare);
b69d29ce 54
3da7a50f
ZJS
55 /* Filter duplicates */
56 for (j = 0, i = 1; i < n_pids; i++) {
57 if (pids[i] == pids[j])
58 continue;
59 pids[++j] = pids[i];
b69d29ce 60 }
3da7a50f
ZJS
61 n_pids = j + 1;
62 pid_width = DECIMAL_STR_WIDTH(pids[j]);
b69d29ce 63
b47d419c 64 if (flags & OUTPUT_FULL_WIDTH)
9bdbc2e2
LN
65 n_columns = 0;
66 else {
67 if (n_columns > pid_width+2)
68 n_columns -= pid_width+2;
69 else
70 n_columns = 20;
71 }
b69d29ce 72 for (i = 0; i < n_pids; i++) {
b47d419c 73 _cleanup_free_ char *t = NULL;
b69d29ce
LP
74
75 get_process_cmdline(pids[i], n_columns, true, &t);
76
6b01f1d3
LP
77 if (extra)
78 printf("%s%s ", prefix, draw_special_char(DRAW_TRIANGULAR_BULLET));
79 else
80 printf("%s%s", prefix, draw_special_char(((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)));
81
3da7a50f 82 printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
b69d29ce
LP
83 }
84}
85
86
9bdbc2e2 87static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) {
ab35fb1b 88 char *fn;
7027ff61 89 _cleanup_fclose_ FILE *f = NULL;
ab35fb1b 90 size_t n = 0, n_allocated = 0;
7027ff61 91 _cleanup_free_ pid_t *pids = NULL;
b47d419c 92 _cleanup_free_ char *p = NULL;
b69d29ce 93 pid_t pid;
fa776d8e 94 int r;
ab35fb1b 95
7027ff61 96 r = cg_mangle_path(path, &p);
b69d29ce 97 if (r < 0)
35d2e7ec 98 return r;
ab35fb1b 99
63c372cb 100 fn = strjoina(p, "/cgroup.procs");
fa776d8e 101 f = fopen(fn, "re");
ab35fb1b 102 if (!f)
fa776d8e 103 return -errno;
ab35fb1b 104
c6c18be3 105 while ((r = cg_read_pid(f, &pid)) > 0) {
ab35fb1b 106
1e5678d0
LP
107 if (!kernel_threads && is_kernel_thread(pid) > 0)
108 continue;
109
3da7a50f
ZJS
110 if (!GREEDY_REALLOC(pids, n_allocated, n + 1))
111 return -ENOMEM;
ab35fb1b
LP
112
113 assert(n < n_allocated);
c6c18be3 114 pids[n++] = pid;
ab35fb1b
LP
115 }
116
c6c18be3 117 if (r < 0)
7027ff61 118 return r;
c6c18be3 119
da41abc5 120 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags);
ab35fb1b 121
7027ff61 122 return 0;
fa776d8e
LP
123}
124
9bdbc2e2 125int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61
LP
126 _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
127 _cleanup_closedir_ DIR *d = NULL;
128 char *gn = NULL;
fa776d8e
LP
129 bool shown_pids = false;
130 int r;
131
b69d29ce
LP
132 assert(path);
133
fa776d8e
LP
134 if (n_columns <= 0)
135 n_columns = columns();
136
137 if (!prefix)
138 prefix = "";
139
7027ff61 140 r = cg_mangle_path(path, &fn);
c3175a7f 141 if (r < 0)
35d2e7ec 142 return r;
fa776d8e 143
c3175a7f 144 d = opendir(fn);
7027ff61 145 if (!d)
fa776d8e 146 return -errno;
fa776d8e 147
35d2e7ec 148 while ((r = cg_read_subgroup(d, &gn)) > 0) {
7027ff61 149 _cleanup_free_ char *k = NULL;
c3175a7f 150
7027ff61 151 k = strjoin(fn, "/", gn, NULL);
c3175a7f 152 free(gn);
7027ff61
LP
153 if (!k)
154 return -ENOMEM;
c3175a7f 155
6f883237 156 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0)
c3175a7f 157 continue;
fa776d8e
LP
158
159 if (!shown_pids) {
9bdbc2e2 160 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags);
fa776d8e
LP
161 shown_pids = true;
162 }
163
164 if (last) {
3d9495a8 165 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH), cg_unescape(basename(last)));
fa776d8e 166
c3175a7f 167 if (!p1) {
6b01f1d3 168 p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERTICAL));
7027ff61
LP
169 if (!p1)
170 return -ENOMEM;
c3175a7f 171 }
fa776d8e 172
9bdbc2e2 173 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags);
fa776d8e 174 free(last);
fa776d8e
LP
175 }
176
c3175a7f 177 last = k;
7027ff61 178 k = NULL;
fa776d8e
LP
179 }
180
35d2e7ec 181 if (r < 0)
7027ff61 182 return r;
35d2e7ec 183
fa776d8e 184 if (!shown_pids)
9bdbc2e2 185 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags);
fa776d8e
LP
186
187 if (last) {
3d9495a8 188 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT), cg_unescape(basename(last)));
fa776d8e 189
c3175a7f
LP
190 if (!p2) {
191 p2 = strappend(prefix, " ");
7027ff61
LP
192 if (!p2)
193 return -ENOMEM;
c3175a7f 194 }
fa776d8e 195
9bdbc2e2 196 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags);
fa776d8e
LP
197 }
198
7027ff61 199 return 0;
ab35fb1b 200}
35d2e7ec 201
9bdbc2e2 202int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
7027ff61 203 _cleanup_free_ char *p = NULL;
35d2e7ec
LP
204 int r;
205
35d2e7ec
LP
206 assert(path);
207
1e5678d0
LP
208 r = cg_get_path(controller, path, NULL, &p);
209 if (r < 0)
35d2e7ec
LP
210 return r;
211
7027ff61 212 return show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags);
35d2e7ec 213}
b69d29ce 214
9bdbc2e2 215static 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) {
7fd1b19b 216 _cleanup_free_ pid_t *copy = NULL;
b69d29ce
LP
217 unsigned i, j;
218 int r;
219
b69d29ce
LP
220 assert(path);
221
222 if (n_pids <= 0)
223 return 0;
224
225 if (n_columns <= 0)
226 n_columns = columns();
227
7027ff61 228 prefix = strempty(prefix);
b69d29ce
LP
229
230 copy = new(pid_t, n_pids);
231 if (!copy)
232 return -ENOMEM;
233
234 for (i = 0, j = 0; i < n_pids; i++) {
7fd1b19b 235 _cleanup_free_ char *k = NULL;
b69d29ce 236
7027ff61 237 r = cg_pid_get_path(controller, pids[i], &k);
050fbdb8 238 if (r < 0)
b69d29ce 239 return r;
b69d29ce
LP
240
241 if (path_startswith(k, path))
242 continue;
243
244 copy[j++] = pids[i];
245 }
246
9bdbc2e2 247 show_pid_array(copy, j, prefix, n_columns, true, false, false, flags);
b69d29ce 248
b69d29ce
LP
249 return 0;
250}
251
9bdbc2e2 252int 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
253 int r;
254
b69d29ce
LP
255 assert(path);
256
9bdbc2e2 257 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags);
b69d29ce
LP
258 if (r < 0)
259 return r;
260
9bdbc2e2 261 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
b69d29ce
LP
262}
263
9bdbc2e2 264int 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 265 _cleanup_free_ char *controller = NULL, *path = NULL;
7027ff61 266 int r;
b69d29ce
LP
267
268 assert(spec);
269
270 r = cg_split_spec(spec, &controller, &path);
271 if (r < 0)
272 return r;
273
9bdbc2e2 274 return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags);
b69d29ce 275}