chiark / gitweb /
man: fix minor ambuigity
[elogind.git] / src / cgroup-show.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
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>
24 #include <dirent.h>
25 #include <errno.h>
26
27 #include "util.h"
28 #include "macro.h"
29 #include "cgroup-show.h"
30
31 static int compare(const void *a, const void *b) {
32         const pid_t *p = a, *q = b;
33
34         if (*p < *q)
35                 return -1;
36         if (*p > *q)
37                 return 1;
38         return 0;
39 }
40
41 static char *get_cgroup_path(const char *name) {
42
43         if (startswith(name, "name=systemd:"))
44                 name += 13;
45
46         if (path_startswith(name, "/cgroup"))
47                 return strdup(name);
48
49         return strappend("/cgroup/systemd/", name);
50 }
51
52 static unsigned ilog10(unsigned long ul) {
53         int n = 0;
54
55         while (ul > 0) {
56                 n++;
57                 ul /= 10;
58         }
59
60         return n;
61 }
62
63 static int show_cgroup_full(const char *name, const char *prefix, unsigned n_columns, bool more) {
64         char *fn;
65         FILE *f;
66         size_t n = 0, n_allocated = 0;
67         pid_t *pids = NULL;
68         char *p;
69         int r;
70         unsigned long biggest = 0;
71
72         if (n_columns <= 0)
73                 n_columns = columns();
74
75         if (!prefix)
76                 prefix = "";
77
78         if (!(p = get_cgroup_path(name)))
79                 return -ENOMEM;
80
81         r = asprintf(&fn, "%s/cgroup.procs", p);
82         free(p);
83
84         if (r < 0)
85                 return -ENOMEM;
86
87         f = fopen(fn, "re");
88         free(fn);
89
90         if (!f)
91                 return -errno;
92
93         while (!feof(f)) {
94                 unsigned long ul;
95
96                 if (fscanf(f, "%lu", &ul) != 1)
97                         break;
98
99                 if (ul <= 0)
100                         continue;
101
102                 if (n >= n_allocated) {
103                         pid_t *npids;
104
105                         n_allocated = MAX(16U, n*2U);
106
107                         if (!(npids = realloc(pids, sizeof(pid_t) * n_allocated))) {
108                                 r = -ENOMEM;
109                                 goto finish;
110                         }
111
112                         pids = npids;
113                 }
114
115                 assert(n < n_allocated);
116                 pids[n++] = (pid_t) ul;
117
118                 if (ul > biggest)
119                         biggest = ul;
120         }
121
122         if (n > 0) {
123                 unsigned i, m;
124
125                 /* Filter duplicates */
126                 m = 0;
127                 for (i = 0; i < n; i++) {
128                         unsigned j;
129
130                         for (j = i+1; j < n; j++)
131                                 if (pids[i] == pids[j])
132                                         break;
133
134                         if (j >= n)
135                                 pids[m++] = pids[i];
136                 }
137                 n = m;
138
139                 /* And sort */
140                 qsort(pids, n, sizeof(pid_t), compare);
141
142                 if (n_columns > 8)
143                         n_columns -= 8;
144                 else
145                         n_columns = 20;
146
147                 for (i = 0; i < n; i++) {
148                         char *t = NULL;
149
150                         get_process_cmdline(pids[i], n_columns, &t);
151
152                         printf("%s%s %*lu %s\n",
153                                prefix,
154                                (more || i < n-1) ? "\342\224\234" : "\342\224\224",
155                                ilog10(biggest),
156                                (unsigned long) pids[i],
157                                strna(t));
158
159                         free(t);
160                 }
161         }
162
163         r = 0;
164
165 finish:
166         free(pids);
167
168         if (f)
169                 fclose(f);
170
171         return r;
172 }
173
174 int show_cgroup(const char *name, const char *prefix, unsigned n_columns) {
175         return show_cgroup_full(name, prefix, n_columns, false);
176 }
177
178 int show_cgroup_recursive(const char *name, const char *prefix, unsigned n_columns) {
179         DIR *d;
180         char *last = NULL;
181         char *p1 = NULL, *p2 = NULL, *fn = NULL;
182         struct dirent *de;
183         bool shown_pids = false;
184         int r;
185
186         assert(name);
187
188         if (n_columns <= 0)
189                 n_columns = columns();
190
191         if (!prefix)
192                 prefix = "";
193
194         if (!(fn = get_cgroup_path(name)))
195                 return -ENOMEM;
196
197         if (!(d = opendir(fn))) {
198                 free(fn);
199                 return -errno;
200         }
201
202         while ((de = readdir(d))) {
203
204                 if (de->d_type != DT_DIR)
205                         continue;
206
207                 if (ignore_file(de->d_name))
208                         continue;
209
210                 if (!shown_pids) {
211                         show_cgroup_full(name, prefix, n_columns, true);
212                         shown_pids = true;
213                 }
214
215                 if (last) {
216                         printf("%s\342\224\234 %s\n", prefix, file_name_from_path(last));
217
218                         if (!p1)
219                                 if (!(p1 = strappend(prefix, "\342\224\202 "))) {
220                                         r = -ENOMEM;
221                                         goto finish;
222                                 }
223
224                         show_cgroup_recursive(last, p1, n_columns-2);
225
226                         free(last);
227                         last = NULL;
228                 }
229
230                 if (asprintf(&last, "%s/%s", name, de->d_name) < 0) {
231                         r = -ENOMEM;
232                         goto finish;
233                 }
234         }
235
236         if (!shown_pids)
237                 show_cgroup_full(name, prefix, n_columns, !!last);
238
239         if (last) {
240                 printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last));
241
242                 if (!p2)
243                         if (!(p2 = strappend(prefix, "  "))) {
244                                 r = -ENOMEM;
245                                 goto finish;
246                         }
247
248                 show_cgroup_recursive(last, p2, n_columns-2);
249         }
250
251         r = 0;
252
253 finish:
254         free(p1);
255         free(p2);
256         free(last);
257         free(fn);
258
259         closedir(d);
260
261         return r;
262 }