chiark / gitweb /
systemctl: filter and sort member pid of cgroup
[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
25 #include "util.h"
26 #include "macro.h"
27 #include "cgroup-show.h"
28
29 static int compare(const void *a, const void *b) {
30         const pid_t *p = a, *q = b;
31
32         if (*p < *q)
33                 return -1;
34         if (*p > *q)
35                 return 1;
36         return 0;
37 }
38
39 void show_cgroup(const char *name, const char *prefix, unsigned columns) {
40         char *fn;
41         FILE *f;
42         size_t n = 0, n_allocated = 0;
43         pid_t *pids = NULL;
44
45         if (!startswith(name, "name=systemd:"))
46                 return;
47
48         if (asprintf(&fn, "/cgroup/systemd/%s/cgroup.procs", name + 13) < 0) {
49                 log_error("Out of memory");
50                 return;
51         }
52
53         f = fopen(fn, "r");
54         free(fn);
55
56         if (!f)
57                 return;
58
59         while (!feof(f)) {
60                 unsigned long ul;
61
62                 if (fscanf(f, "%lu", &ul) != 1)
63                         break;
64
65                 if (ul <= 0)
66                         continue;
67
68                 if (n >= n_allocated) {
69                         pid_t *npids;
70
71                         n_allocated = MAX(16U, n*2U);
72
73                         if (!(npids = realloc(pids, sizeof(pid_t) * n_allocated))) {
74                                 log_error("Out of memory");
75                                 goto finish;
76                         }
77
78                         pids = npids;
79                 }
80
81                 assert(n < n_allocated);
82                 pids[n++] = (pid_t) ul;
83         }
84
85         if (n > 0) {
86                 unsigned i, m;
87
88                 /* Filter duplicates */
89                 m = 0;
90                 for (i = 0; i < n; i++) {
91                         unsigned j;
92
93                         for (j = i+1; j < n; j++)
94                                 if (pids[i] == pids[j])
95                                         break;
96
97                         if (j >= n)
98                                 pids[m++] = pids[i];
99                 }
100                 n = m;
101
102                 /* And sort */
103                 qsort(pids, n, sizeof(pid_t), compare);
104
105                 if (!prefix)
106                         prefix = "";
107
108                 if (columns > 8)
109                         columns -= 8;
110                 else
111                         columns = 20;
112
113                 printf("%s\342\224\202\n", prefix);
114
115                 for (i = 0; i < n; i++) {
116                         char *t = NULL;
117
118                         get_process_cmdline(pids[i], columns, &t);
119
120                         printf("%s%s %5lu %s\n",
121                                prefix,
122                                i < n-1 ? "\342\224\234" : "\342\224\224",
123                                (unsigned long) pids[i], strna(t));
124
125                         free(t);
126                 }
127         }
128
129 finish:
130         free(pids);
131
132         if (f)
133                 fclose(f);
134 }