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 void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads, OutputFlags flags) {
44 unsigned i, m, pid_width;
47 /* Filter duplicates */
49 for (i = 0; i < n_pids; i++) {
52 if (pids[i] > biggest)
55 for (j = i+1; j < n_pids; j++)
56 if (pids[i] == pids[j])
63 pid_width = DECIMAL_STR_WIDTH(biggest);
66 qsort(pids, n_pids, sizeof(pid_t), compare);
68 if(flags & OUTPUT_FULL_WIDTH)
71 if (n_columns > pid_width+2)
72 n_columns -= pid_width+2;
76 for (i = 0; i < n_pids; i++) {
79 get_process_cmdline(pids[i], n_columns, true, &t);
81 printf("%s%s%*lu %s\n",
83 draw_special_char(extra ? DRAW_TRIANGULAR_BULLET :
84 ((more || i < n_pids-1) ? DRAW_TREE_BRANCH : DRAW_TREE_RIGHT)),
86 (unsigned long) pids[i],
94 static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads, OutputFlags flags) {
96 _cleanup_fclose_ FILE *f = NULL;
97 size_t n = 0, n_allocated = 0;
98 _cleanup_free_ pid_t *pids = NULL;
103 r = cg_mangle_path(path, &p);
107 fn = strappend(p, "/cgroup.procs");
117 while ((r = cg_read_pid(f, &pid)) > 0) {
119 if (!kernel_threads && is_kernel_thread(pid) > 0)
122 if (n >= n_allocated) {
125 n_allocated = MAX(16U, n*2U);
127 npids = realloc(pids, sizeof(pid_t) * n_allocated);
134 assert(n < n_allocated);
142 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads, flags);
147 int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
148 _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
149 _cleanup_closedir_ DIR *d = NULL;
151 bool shown_pids = false;
157 n_columns = columns();
162 r = cg_mangle_path(path, &fn);
170 while ((r = cg_read_subgroup(d, &gn)) > 0) {
171 _cleanup_free_ char *k = NULL;
173 k = strjoin(fn, "/", gn, NULL);
178 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k, false) > 0)
182 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads, flags);
187 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_BRANCH),
188 path_get_file_name(last));
191 p1 = strappend(prefix, draw_special_char(DRAW_TREE_VERT));
196 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, flags);
208 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads, flags);
211 printf("%s%s%s\n", prefix, draw_special_char(DRAW_TREE_RIGHT),
212 path_get_file_name(last));
215 p2 = strappend(prefix, " ");
220 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, flags);
226 int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, OutputFlags flags) {
227 _cleanup_free_ char *p = NULL;
232 r = cg_get_path(controller, path, NULL, &p);
236 return show_cgroup_by_path(p, prefix, n_columns, kernel_threads, flags);
239 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) {
240 _cleanup_free_ pid_t *copy = NULL;
251 n_columns = columns();
253 prefix = strempty(prefix);
255 copy = new(pid_t, n_pids);
259 for (i = 0, j = 0; i < n_pids; i++) {
260 _cleanup_free_ char *k = NULL;
262 r = cg_pid_get_path(controller, pids[i], &k);
266 if (path_startswith(k, path))
272 show_pid_array(copy, j, prefix, n_columns, true, false, false, flags);
277 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) {
282 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, flags);
286 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
289 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) {
290 _cleanup_free_ char *controller = NULL, *path = NULL;
295 r = cg_split_spec(spec, &controller, &path);
299 return show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, extra_pids, n_extra_pids, flags);