1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
29 #include "path-util.h"
30 #include "cgroup-util.h"
31 #include "cgroup-show.h"
33 static int compare(const void *a, const void *b) {
34 const pid_t *p = a, *q = b;
43 static unsigned ilog10(unsigned long ul) {
54 static void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
55 unsigned i, m, pid_width;
58 /* Filter duplicates */
60 for (i = 0; i < n_pids; i++) {
63 if (pids[i] > biggest)
66 for (j = i+1; j < n_pids; j++)
67 if (pids[i] == pids[j])
74 pid_width = ilog10(biggest);
77 qsort(pids, n_pids, sizeof(pid_t), compare);
79 if(flags & OUTPUT_FULL_WIDTH)
82 if (n_columns > pid_width+2)
83 n_columns -= pid_width+2;
87 for (i = 0; i < n_pids; i++) {
90 get_process_cmdline(pids[i], n_columns, true, &t);
92 printf("%s%s%*lu %s\n",
94 draw_special_char(extra ? DRAW_TRIANGULAR_BULLET :
95 ((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)),
97 (unsigned long) pids[i],
105 static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) {
108 size_t n = 0, n_allocated = 0;
114 r = cg_fix_path(path, &p);
118 r = asprintf(&fn, "%s/cgroup.procs", p);
128 while ((r = cg_read_pid(f, &pid)) > 0) {
130 if (!kernel_threads && is_kernel_thread(pid) > 0)
133 if (n >= n_allocated) {
136 n_allocated = MAX(16U, n*2U);
138 npids = realloc(pids, sizeof(pid_t) * n_allocated);
147 assert(n < n_allocated);
155 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags);
168 int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
171 char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL;
172 bool shown_pids = false;
178 n_columns = columns();
183 r = cg_fix_path(path, &fn);
193 while ((r = cg_read_subgroup(d, &gn)) > 0) {
196 r = asprintf(&k, "%s/%s", fn, gn);
203 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k, false) > 0) {
209 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags);
214 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH),
215 path_get_file_name(last));
218 p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERT));
226 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags);
237 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags);
240 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT),
241 path_get_file_name(last));
244 p2 = strappend(prefix, " ");
251 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags);
267 int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
274 r = cg_get_path(controller, path, NULL, &p);
278 r = show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags);
284 static 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) {
296 n_columns = columns();
301 copy = new(pid_t, n_pids);
305 for (i = 0, j = 0; i < n_pids; i++) {
308 r = cg_get_by_pid(controller, pids[i], &k);
314 if (path_startswith(k, path))
320 show_pid_array(copy, j, prefix, n_columns, true, false, false, flags);
326 int 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) {
332 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags);
336 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
339 int 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) {
341 _cleanup_free_ char *controller = NULL, *path = NULL;
345 r = cg_split_spec(spec, &controller, &path);
349 return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags);