]>
Commit | Line | Data |
---|---|---|
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 | |
9 | under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
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 | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
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" | |
c6c18be3 | 29 | #include "cgroup-util.h" |
ab35fb1b LP |
30 | #include "cgroup-show.h" |
31 | ||
32 | static int compare(const void *a, const void *b) { | |
33 | const pid_t *p = a, *q = b; | |
34 | ||
35 | if (*p < *q) | |
36 | return -1; | |
37 | if (*p > *q) | |
38 | return 1; | |
39 | return 0; | |
40 | } | |
41 | ||
fa776d8e LP |
42 | static unsigned ilog10(unsigned long ul) { |
43 | int n = 0; | |
44 | ||
45 | while (ul > 0) { | |
46 | n++; | |
47 | ul /= 10; | |
48 | } | |
49 | ||
50 | return n; | |
51 | } | |
52 | ||
35d2e7ec | 53 | static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more) { |
ab35fb1b LP |
54 | char *fn; |
55 | FILE *f; | |
56 | size_t n = 0, n_allocated = 0; | |
57 | pid_t *pids = NULL; | |
fa776d8e | 58 | char *p; |
c6c18be3 | 59 | pid_t pid, biggest = 0; |
fa776d8e | 60 | int r; |
ab35fb1b | 61 | |
fa776d8e LP |
62 | if (n_columns <= 0) |
63 | n_columns = columns(); | |
ab35fb1b | 64 | |
fa776d8e LP |
65 | if (!prefix) |
66 | prefix = ""; | |
67 | ||
35d2e7ec LP |
68 | if ((r = cg_fix_path(path, &p)) < 0) |
69 | return r; | |
ab35fb1b | 70 | |
fa776d8e LP |
71 | r = asprintf(&fn, "%s/cgroup.procs", p); |
72 | free(p); | |
73 | ||
74 | if (r < 0) | |
75 | return -ENOMEM; | |
76 | ||
77 | f = fopen(fn, "re"); | |
ab35fb1b LP |
78 | free(fn); |
79 | ||
80 | if (!f) | |
fa776d8e | 81 | return -errno; |
ab35fb1b | 82 | |
c6c18be3 | 83 | while ((r = cg_read_pid(f, &pid)) > 0) { |
ab35fb1b LP |
84 | |
85 | if (n >= n_allocated) { | |
86 | pid_t *npids; | |
87 | ||
88 | n_allocated = MAX(16U, n*2U); | |
89 | ||
90 | if (!(npids = realloc(pids, sizeof(pid_t) * n_allocated))) { | |
fa776d8e | 91 | r = -ENOMEM; |
ab35fb1b LP |
92 | goto finish; |
93 | } | |
94 | ||
95 | pids = npids; | |
96 | } | |
97 | ||
98 | assert(n < n_allocated); | |
c6c18be3 | 99 | pids[n++] = pid; |
fa776d8e | 100 | |
c6c18be3 LP |
101 | if (pid > biggest) |
102 | biggest = pid; | |
ab35fb1b LP |
103 | } |
104 | ||
c6c18be3 LP |
105 | if (r < 0) |
106 | goto finish; | |
107 | ||
ab35fb1b LP |
108 | if (n > 0) { |
109 | unsigned i, m; | |
110 | ||
111 | /* Filter duplicates */ | |
112 | m = 0; | |
113 | for (i = 0; i < n; i++) { | |
114 | unsigned j; | |
115 | ||
116 | for (j = i+1; j < n; j++) | |
117 | if (pids[i] == pids[j]) | |
118 | break; | |
119 | ||
120 | if (j >= n) | |
121 | pids[m++] = pids[i]; | |
122 | } | |
123 | n = m; | |
124 | ||
125 | /* And sort */ | |
126 | qsort(pids, n, sizeof(pid_t), compare); | |
127 | ||
fa776d8e LP |
128 | if (n_columns > 8) |
129 | n_columns -= 8; | |
ab35fb1b | 130 | else |
fa776d8e | 131 | n_columns = 20; |
ab35fb1b LP |
132 | |
133 | for (i = 0; i < n; i++) { | |
134 | char *t = NULL; | |
135 | ||
87d2c1ff | 136 | get_process_cmdline(pids[i], n_columns, true, &t); |
ab35fb1b | 137 | |
fa776d8e | 138 | printf("%s%s %*lu %s\n", |
ab35fb1b | 139 | prefix, |
fa776d8e | 140 | (more || i < n-1) ? "\342\224\234" : "\342\224\224", |
e364ad06 | 141 | (int) ilog10(biggest), |
fa776d8e LP |
142 | (unsigned long) pids[i], |
143 | strna(t)); | |
ab35fb1b LP |
144 | |
145 | free(t); | |
146 | } | |
147 | } | |
148 | ||
fa776d8e LP |
149 | r = 0; |
150 | ||
ab35fb1b LP |
151 | finish: |
152 | free(pids); | |
153 | ||
154 | if (f) | |
155 | fclose(f); | |
fa776d8e LP |
156 | |
157 | return r; | |
158 | } | |
159 | ||
35d2e7ec | 160 | int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns) { |
fa776d8e LP |
161 | DIR *d; |
162 | char *last = NULL; | |
35d2e7ec | 163 | char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL; |
fa776d8e LP |
164 | bool shown_pids = false; |
165 | int r; | |
166 | ||
fa776d8e LP |
167 | if (n_columns <= 0) |
168 | n_columns = columns(); | |
169 | ||
170 | if (!prefix) | |
171 | prefix = ""; | |
172 | ||
35d2e7ec LP |
173 | if ((r = cg_fix_path(path, &fn)) < 0) |
174 | return r; | |
fa776d8e LP |
175 | |
176 | if (!(d = opendir(fn))) { | |
177 | free(fn); | |
178 | return -errno; | |
179 | } | |
180 | ||
35d2e7ec | 181 | while ((r = cg_read_subgroup(d, &gn)) > 0) { |
fa776d8e LP |
182 | |
183 | if (!shown_pids) { | |
35d2e7ec | 184 | show_cgroup_one_by_path(path, prefix, n_columns, true); |
fa776d8e LP |
185 | shown_pids = true; |
186 | } | |
187 | ||
188 | if (last) { | |
189 | printf("%s\342\224\234 %s\n", prefix, file_name_from_path(last)); | |
190 | ||
191 | if (!p1) | |
192 | if (!(p1 = strappend(prefix, "\342\224\202 "))) { | |
193 | r = -ENOMEM; | |
194 | goto finish; | |
195 | } | |
196 | ||
35d2e7ec | 197 | show_cgroup_by_path(last, p1, n_columns-2); |
fa776d8e LP |
198 | |
199 | free(last); | |
200 | last = NULL; | |
201 | } | |
202 | ||
35d2e7ec LP |
203 | r = asprintf(&last, "%s/%s", fn, gn); |
204 | free(gn); | |
205 | ||
206 | if (r < 0) { | |
e34b6159 | 207 | r = -ENOMEM; |
fa776d8e LP |
208 | goto finish; |
209 | } | |
210 | } | |
211 | ||
35d2e7ec LP |
212 | if (r < 0) |
213 | goto finish; | |
214 | ||
fa776d8e | 215 | if (!shown_pids) |
35d2e7ec | 216 | show_cgroup_one_by_path(path, prefix, n_columns, !!last); |
fa776d8e LP |
217 | |
218 | if (last) { | |
219 | printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last)); | |
220 | ||
221 | if (!p2) | |
222 | if (!(p2 = strappend(prefix, " "))) { | |
223 | r = -ENOMEM; | |
224 | goto finish; | |
225 | } | |
226 | ||
35d2e7ec | 227 | show_cgroup_by_path(last, p2, n_columns-2); |
fa776d8e LP |
228 | } |
229 | ||
230 | r = 0; | |
231 | ||
232 | finish: | |
233 | free(p1); | |
234 | free(p2); | |
235 | free(last); | |
236 | free(fn); | |
237 | ||
238 | closedir(d); | |
239 | ||
240 | return r; | |
ab35fb1b | 241 | } |
35d2e7ec LP |
242 | |
243 | int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns) { | |
244 | char *p; | |
245 | int r; | |
246 | ||
247 | assert(controller); | |
248 | assert(path); | |
249 | ||
250 | if ((r = cg_get_path(controller, path, NULL, &p)) < 0) | |
251 | return r; | |
252 | ||
253 | r = show_cgroup_by_path(p, prefix, n_columns); | |
254 | free(p); | |
255 | ||
256 | return r; | |
257 | } |