]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/cgroup-show.c
2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "alloc-util.h"
28 #include "cgroup-show.h"
29 #include "cgroup-util.h"
31 #include "formats-util.h"
32 #include "locale-util.h"
34 #include "output-mode.h"
35 #include "path-util.h"
36 #include "process-util.h"
37 #include "string-util.h"
38 #include "terminal-util.h"
40 static int compare(const void *a
, const void *b
) {
41 const pid_t
*p
= a
, *q
= b
;
50 static 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
) {
51 unsigned i
, j
, pid_width
;
56 qsort(pids
, n_pids
, sizeof(pid_t
), compare
);
58 /* Filter duplicates */
59 for (j
= 0, i
= 1; i
< n_pids
; i
++) {
60 if (pids
[i
] == pids
[j
])
65 pid_width
= DECIMAL_STR_WIDTH(pids
[j
]);
67 if (flags
& OUTPUT_FULL_WIDTH
)
70 if (n_columns
> pid_width
+2)
71 n_columns
-= pid_width
+2;
75 for (i
= 0; i
< n_pids
; i
++) {
76 _cleanup_free_
char *t
= NULL
;
78 get_process_cmdline(pids
[i
], n_columns
, true, &t
);
81 printf("%s%s ", prefix
, draw_special_char(DRAW_TRIANGULAR_BULLET
));
83 printf("%s%s", prefix
, draw_special_char(((more
|| i
< n_pids
-1) ? DRAW_TREE_BRANCH
: DRAW_TREE_RIGHT
)));
85 printf("%*"PID_PRI
" %s\n", pid_width
, pids
[i
], strna(t
));
90 static int show_cgroup_one_by_path(const char *path
, const char *prefix
, unsigned n_columns
, bool more
, bool kernel_threads
, OutputFlags flags
) {
92 _cleanup_fclose_
FILE *f
= NULL
;
93 size_t n
= 0, n_allocated
= 0;
94 _cleanup_free_ pid_t
*pids
= NULL
;
95 _cleanup_free_
char *p
= NULL
;
99 r
= cg_mangle_path(path
, &p
);
103 fn
= strjoina(p
, "/cgroup.procs");
108 while ((r
= cg_read_pid(f
, &pid
)) > 0) {
110 if (!kernel_threads
&& is_kernel_thread(pid
) > 0)
113 if (!GREEDY_REALLOC(pids
, n_allocated
, n
+ 1))
116 assert(n
< n_allocated
);
123 show_pid_array(pids
, n
, prefix
, n_columns
, false, more
, kernel_threads
, flags
);
128 int show_cgroup_by_path(const char *path
, const char *prefix
, unsigned n_columns
, bool kernel_threads
, OutputFlags flags
) {
129 _cleanup_free_
char *fn
= NULL
, *p1
= NULL
, *last
= NULL
, *p2
= NULL
;
130 _cleanup_closedir_
DIR *d
= NULL
;
132 bool shown_pids
= false;
138 n_columns
= columns();
143 r
= cg_mangle_path(path
, &fn
);
151 while ((r
= cg_read_subgroup(d
, &gn
)) > 0) {
152 _cleanup_free_
char *k
= NULL
;
154 k
= strjoin(fn
, "/", gn
, NULL
);
159 if (!(flags
& OUTPUT_SHOW_ALL
) && cg_is_empty_recursive(NULL
, k
) > 0)
163 show_cgroup_one_by_path(path
, prefix
, n_columns
, true, kernel_threads
, flags
);
168 printf("%s%s%s\n", prefix
, draw_special_char(DRAW_TREE_BRANCH
), cg_unescape(basename(last
)));
171 p1
= strappend(prefix
, draw_special_char(DRAW_TREE_VERTICAL
));
176 show_cgroup_by_path(last
, p1
, n_columns
-2, kernel_threads
, flags
);
188 show_cgroup_one_by_path(path
, prefix
, n_columns
, !!last
, kernel_threads
, flags
);
191 printf("%s%s%s\n", prefix
, draw_special_char(DRAW_TREE_RIGHT
), cg_unescape(basename(last
)));
194 p2
= strappend(prefix
, " ");
199 show_cgroup_by_path(last
, p2
, n_columns
-2, kernel_threads
, flags
);
205 int show_cgroup(const char *controller
, const char *path
, const char *prefix
, unsigned n_columns
, bool kernel_threads
, OutputFlags flags
) {
206 _cleanup_free_
char *p
= NULL
;
211 r
= cg_get_path(controller
, path
, NULL
, &p
);
215 return show_cgroup_by_path(p
, prefix
, n_columns
, kernel_threads
, flags
);
218 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
) {
219 _cleanup_free_ pid_t
*copy
= NULL
;
229 n_columns
= columns();
231 prefix
= strempty(prefix
);
233 copy
= new(pid_t
, n_pids
);
237 for (i
= 0, j
= 0; i
< n_pids
; i
++) {
238 _cleanup_free_
char *k
= NULL
;
240 r
= cg_pid_get_path(controller
, pids
[i
], &k
);
244 if (path_startswith(k
, path
))
250 show_pid_array(copy
, j
, prefix
, n_columns
, true, false, false, flags
);
255 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
) {
260 r
= show_cgroup(controller
, path
, prefix
, n_columns
, kernel_threads
, flags
);
264 return show_extra_pids(controller
, path
, prefix
, n_columns
, extra_pids
, n_extra_pids
, flags
);
267 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
) {
268 _cleanup_free_
char *controller
= NULL
, *path
= NULL
;
273 r
= cg_split_spec(spec
, &controller
, &path
);
277 return show_cgroup_and_extra(controller
, path
, prefix
, n_columns
, kernel_threads
, extra_pids
, n_extra_pids
, flags
);