chiark / gitweb /
service: 'pidfile:' in SysV chkconfig header implies a real daemon
[elogind.git] / src / dbus-execute.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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 <errno.h>
23 #include <dbus/dbus.h>
24 #include <sys/prctl.h>
25
26 #include "dbus-execute.h"
27 #include "missing.h"
28 #include "ioprio.h"
29 #include "strv.h"
30 #include "dbus-common.h"
31
32 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_kill_mode, kill_mode, KillMode);
33
34 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
35 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
36
37 int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
38         char **env_files = data, **j;
39         DBusMessageIter sub, sub2;
40
41         assert(i);
42         assert(property);
43
44         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
45                 return -ENOMEM;
46
47         STRV_FOREACH(j, env_files) {
48                 dbus_bool_t b = false;
49                 char *fn = *j;
50
51                 if (fn[0] == '-') {
52                         b = true;
53                         fn++;
54                 }
55
56                 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
57                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
58                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
59                     !dbus_message_iter_close_container(&sub, &sub2))
60                         return -ENOMEM;
61         }
62
63         if (!dbus_message_iter_close_container(i, &sub))
64                 return -ENOMEM;
65
66         return 0;
67 }
68
69 int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
70         ExecContext *c = data;
71         int32_t n;
72
73         assert(i);
74         assert(property);
75         assert(c);
76
77         if (c->oom_score_adjust_set)
78                 n = c->oom_score_adjust;
79         else {
80                 char *t;
81
82                 n = 0;
83                 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
84                         safe_atoi(t, &n);
85                         free(t);
86                 } else if (read_one_line_file("/proc/self/oom_adj", &t) >= 0) {
87                         safe_atoi(t, &n);
88                         free(t);
89
90                         if (n == OOM_ADJUST_MAX)
91                                 n = OOM_SCORE_ADJ_MAX;
92                         else
93                                 n = (n * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
94                 }
95         }
96
97         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
98                 return -ENOMEM;
99
100         return 0;
101 }
102
103 int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
104         ExecContext *c = data;
105         int32_t n;
106
107         assert(i);
108         assert(property);
109         assert(c);
110
111         if (c->nice_set)
112                 n = c->nice;
113         else
114                 n = getpriority(PRIO_PROCESS, 0);
115
116         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
117                 return -ENOMEM;
118
119         return 0;
120 }
121
122 int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
123         ExecContext *c = data;
124         int32_t n;
125
126         assert(i);
127         assert(property);
128         assert(c);
129
130         if (c->ioprio_set)
131                 n = c->ioprio;
132         else
133                 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
134
135         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
136                 return -ENOMEM;
137
138         return 0;
139 }
140
141 int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
142         ExecContext *c = data;
143         int32_t n;
144
145         assert(i);
146         assert(property);
147         assert(c);
148
149         if (c->cpu_sched_set)
150                 n = c->cpu_sched_policy;
151         else
152                 n = sched_getscheduler(0);
153
154         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
155                 return -ENOMEM;
156
157         return 0;
158 }
159
160 int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
161         ExecContext *c = data;
162         int32_t n;
163
164         assert(i);
165         assert(property);
166         assert(c);
167
168         if (c->cpu_sched_set)
169                 n = c->cpu_sched_priority;
170         else {
171                 struct sched_param p;
172                 n = 0;
173
174                 zero(p);
175                 if (sched_getparam(0, &p) >= 0)
176                         n = p.sched_priority;
177         }
178
179         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
180                 return -ENOMEM;
181
182         return 0;
183 }
184
185 int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
186         ExecContext *c = data;
187         dbus_bool_t b;
188         DBusMessageIter sub;
189
190         assert(i);
191         assert(property);
192         assert(c);
193
194         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
195                 return -ENOMEM;
196
197         if (c->cpuset)
198                 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
199         else
200                 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
201
202         if (!b)
203                 return -ENOMEM;
204
205         if (!dbus_message_iter_close_container(i, &sub))
206                 return -ENOMEM;
207
208         return 0;
209 }
210
211 int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
212         ExecContext *c = data;
213         uint64_t u;
214
215         assert(i);
216         assert(property);
217         assert(c);
218
219         if (c->timer_slack_nsec_set)
220                 u = (uint64_t) c->timer_slack_nsec;
221         else
222                 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
223
224         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
225                 return -ENOMEM;
226
227         return 0;
228 }
229
230 int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
231         ExecContext *c = data;
232         uint64_t normal, inverted;
233
234         assert(i);
235         assert(property);
236         assert(c);
237
238         /* We store this negated internally, to match the kernel, but
239          * we expose it normalized. */
240
241         normal = *(uint64_t*) data;
242         inverted = ~normal;
243
244         return bus_property_append_uint64(i, property, &inverted);
245 }
246
247 int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
248         ExecContext *c = data;
249         char *t = NULL;
250         const char *s;
251         dbus_bool_t b;
252
253         assert(i);
254         assert(property);
255         assert(c);
256
257         if (c->capabilities)
258                 s = t = cap_to_text(c->capabilities, NULL);
259         else
260                 s = "";
261
262         if (!s)
263                 return -ENOMEM;
264
265         b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
266
267         if (t)
268                 cap_free(t);
269
270         if (!b)
271                 return -ENOMEM;
272
273         return 0;
274 }
275
276 int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
277         ExecContext *c = data;
278         int r;
279         uint64_t u;
280
281         assert(i);
282         assert(property);
283         assert(c);
284
285         assert_se((r = rlimit_from_string(property)) >= 0);
286
287         if (c->rlimit[r])
288                 u = (uint64_t) c->rlimit[r]->rlim_max;
289         else {
290                 struct rlimit rl;
291
292                 zero(rl);
293                 getrlimit(r, &rl);
294
295                 u = (uint64_t) rl.rlim_max;
296         }
297
298         if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
299                 return -ENOMEM;
300
301         return 0;
302 }
303
304 int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
305         ExecCommand *c = data;
306         DBusMessageIter sub, sub2, sub3;
307
308         assert(i);
309         assert(property);
310
311         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttuii)", &sub))
312                 return -ENOMEM;
313
314         LIST_FOREACH(command, c, c) {
315                 char **l;
316                 uint32_t pid;
317                 int32_t code, status;
318
319                 if (!c->path)
320                         continue;
321
322                 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
323                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
324                     !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
325                         return -ENOMEM;
326
327                 STRV_FOREACH(l, c->argv)
328                         if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
329                                 return -ENOMEM;
330
331                 pid = (uint32_t) c->exec_status.pid;
332                 code = (int32_t) c->exec_status.code;
333                 status = (int32_t) c->exec_status.status;
334
335                 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
336                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &c->ignore) ||
337                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
338                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
339                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
340                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
341                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
342                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
343                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
344                         return -ENOMEM;
345
346                 if (!dbus_message_iter_close_container(&sub, &sub2))
347                         return -ENOMEM;
348         }
349
350         if (!dbus_message_iter_close_container(i, &sub))
351                 return -ENOMEM;
352
353         return 0;
354 }