]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
relicense to LGPLv2.1 (with exceptions)
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4139c1b2
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
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
4139c1b2
LP
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
5430f7f2 16 Lesser General Public License for more details.
4139c1b2 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
23#include <dbus/dbus.h>
82c121a4 24#include <sys/prctl.h>
4139c1b2
LP
25
26#include "dbus-execute.h"
82c121a4
LP
27#include "missing.h"
28#include "ioprio.h"
fe68089d 29#include "strv.h"
bfebab7f 30#include "dbus-common.h"
4139c1b2 31
2e22afe9
LP
32DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_kill_mode, kill_mode, KillMode);
33
4139c1b2
LP
34DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
35DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
82c121a4 36
bfebab7f 37int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
8c7be95e
LP
38 char **env_files = data, **j;
39 DBusMessageIter sub, sub2;
40
8c7be95e
LP
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
bfebab7f 69int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
70 ExecContext *c = data;
71 int32_t n;
72
82c121a4
LP
73 assert(i);
74 assert(property);
75 assert(c);
76
dd6c17b1
LP
77 if (c->oom_score_adjust_set)
78 n = c->oom_score_adjust;
82c121a4
LP
79 else {
80 char *t;
81
82 n = 0;
dd6c17b1 83 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
82c121a4
LP
84 safe_atoi(t, &n);
85 free(t);
dd6c17b1
LP
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;
82c121a4
LP
94 }
95 }
96
97 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
98 return -ENOMEM;
99
100 return 0;
101}
102
bfebab7f 103int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
104 ExecContext *c = data;
105 int32_t n;
106
82c121a4
LP
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
bfebab7f 122int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
123 ExecContext *c = data;
124 int32_t n;
125
82c121a4
LP
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
bfebab7f 141int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
142 ExecContext *c = data;
143 int32_t n;
144
82c121a4
LP
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
bfebab7f 160int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
161 ExecContext *c = data;
162 int32_t n;
163
82c121a4
LP
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
bfebab7f 185int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
186 ExecContext *c = data;
187 dbus_bool_t b;
188 DBusMessageIter sub;
189
82c121a4
LP
190 assert(i);
191 assert(property);
192 assert(c);
193
fe68089d 194 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
82c121a4
LP
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
bfebab7f 211int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
212 ExecContext *c = data;
213 uint64_t u;
214
82c121a4
LP
215 assert(i);
216 assert(property);
217 assert(c);
218
03fae018
LP
219 if (c->timer_slack_nsec_set)
220 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
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
bfebab7f 230int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
260abb78
LP
231 ExecContext *c = data;
232 uint64_t normal, inverted;
233
260abb78
LP
234 assert(i);
235 assert(property);
236 assert(c);
237
7c3d67ef 238 /* We store this negated internally, to match the kernel, but
260abb78
LP
239 * we expose it normalized. */
240
241 normal = *(uint64_t*) data;
242 inverted = ~normal;
243
bfebab7f 244 return bus_property_append_uint64(i, property, &inverted);
260abb78
LP
245}
246
bfebab7f 247int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
248 ExecContext *c = data;
249 char *t = NULL;
250 const char *s;
251 dbus_bool_t b;
252
82c121a4
LP
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
674cdd19 262 if (!s)
82c121a4
LP
263 return -ENOMEM;
264
265 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
674cdd19
LP
266
267 if (t)
268 cap_free(t);
82c121a4
LP
269
270 if (!b)
271 return -ENOMEM;
272
273 return 0;
274}
275
bfebab7f 276int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
277 ExecContext *c = data;
278 int r;
279 uint64_t u;
280
82c121a4
LP
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}
fe68089d 303
bfebab7f 304int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
fe68089d
LP
305 ExecCommand *c = data;
306 DBusMessageIter sub, sub2, sub3;
307
fe68089d
LP
308 assert(i);
309 assert(property);
310
7daa9e6e 311 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
fe68089d
LP
312 return -ENOMEM;
313
314 LIST_FOREACH(command, c, c) {
315 char **l;
316 uint32_t pid;
317 int32_t code, status;
7daa9e6e 318 dbus_bool_t b;
fe68089d
LP
319
320 if (!c->path)
321 continue;
322
323 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
324 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
325 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
326 return -ENOMEM;
327
328 STRV_FOREACH(l, c->argv)
329 if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
330 return -ENOMEM;
331
332 pid = (uint32_t) c->exec_status.pid;
333 code = (int32_t) c->exec_status.code;
334 status = (int32_t) c->exec_status.status;
335
7daa9e6e
LP
336 b = !!c->ignore;
337
fe68089d 338 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
7daa9e6e 339 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
fe68089d 340 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
b21a0ef8 341 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
fe68089d 342 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
b21a0ef8 343 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
e364ad06
LP
344 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
345 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
346 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
fe68089d
LP
347 return -ENOMEM;
348
349 if (!dbus_message_iter_close_container(&sub, &sub2))
350 return -ENOMEM;
351 }
352
353 if (!dbus_message_iter_close_container(i, &sub))
354 return -ENOMEM;
355
356 return 0;
357}
d200735e
MS
358
359const BusProperty bus_exec_context_properties[] = {
360 { "Environment", bus_property_append_strv, "as", offsetof(ExecContext, environment), true },
361 { "EnvironmentFiles", bus_execute_append_env_files, "a(sb)", offsetof(ExecContext, environment_files), true },
362 { "UMask", bus_property_append_mode, "u", offsetof(ExecContext, umask) },
363 { "LimitCPU", bus_execute_append_rlimits, "t", 0 },
364 { "LimitFSIZE", bus_execute_append_rlimits, "t", 0 },
365 { "LimitDATA", bus_execute_append_rlimits, "t", 0 },
366 { "LimitSTACK", bus_execute_append_rlimits, "t", 0 },
367 { "LimitCORE", bus_execute_append_rlimits, "t", 0 },
368 { "LimitRSS", bus_execute_append_rlimits, "t", 0 },
369 { "LimitNOFILE", bus_execute_append_rlimits, "t", 0 },
370 { "LimitAS", bus_execute_append_rlimits, "t", 0 },
371 { "LimitNPROC", bus_execute_append_rlimits, "t", 0 },
372 { "LimitMEMLOCK", bus_execute_append_rlimits, "t", 0 },
373 { "LimitLOCKS", bus_execute_append_rlimits, "t", 0 },
374 { "LimitSIGPENDING", bus_execute_append_rlimits, "t", 0 },
375 { "LimitMSGQUEUE", bus_execute_append_rlimits, "t", 0 },
376 { "LimitNICE", bus_execute_append_rlimits, "t", 0 },
377 { "LimitRTPRIO", bus_execute_append_rlimits, "t", 0 },
378 { "LimitRTTIME", bus_execute_append_rlimits, "t", 0 },
379 { "WorkingDirectory", bus_property_append_string, "s", offsetof(ExecContext, working_directory), true },
380 { "RootDirectory", bus_property_append_string, "s", offsetof(ExecContext, root_directory), true },
381 { "OOMScoreAdjust", bus_execute_append_oom_score_adjust, "i", 0 },
382 { "Nice", bus_execute_append_nice, "i", 0 },
383 { "IOScheduling", bus_execute_append_ioprio, "i", 0 },
384 { "CPUSchedulingPolicy", bus_execute_append_cpu_sched_policy, "i", 0 },
385 { "CPUSchedulingPriority", bus_execute_append_cpu_sched_priority, "i", 0 },
386 { "CPUAffinity", bus_execute_append_affinity, "ay", 0 },
387 { "TimerSlackNSec", bus_execute_append_timer_slack_nsec, "t", 0 },
388 { "CPUSchedulingResetOnFork", bus_property_append_bool, "b", offsetof(ExecContext, cpu_sched_reset_on_fork) },
389 { "NonBlocking", bus_property_append_bool, "b", offsetof(ExecContext, non_blocking) },
390 { "StandardInput", bus_execute_append_input, "s", offsetof(ExecContext, std_input) },
391 { "StandardOutput", bus_execute_append_output, "s", offsetof(ExecContext, std_output) },
392 { "StandardError", bus_execute_append_output, "s", offsetof(ExecContext, std_error) },
393 { "TTYPath", bus_property_append_string, "s", offsetof(ExecContext, tty_path), true },
394 { "TTYReset", bus_property_append_bool, "b", offsetof(ExecContext, tty_reset) },
395 { "TTYVHangup", bus_property_append_bool, "b", offsetof(ExecContext, tty_vhangup) },
396 { "TTYVTDisallocate", bus_property_append_bool, "b", offsetof(ExecContext, tty_vt_disallocate) },
397 { "SyslogPriority", bus_property_append_int, "i", offsetof(ExecContext, syslog_priority) },
398 { "SyslogIdentifier", bus_property_append_string, "s", offsetof(ExecContext, syslog_identifier), true },
399 { "SyslogLevelPrefix", bus_property_append_bool, "b", offsetof(ExecContext, syslog_level_prefix) },
400 { "Capabilities", bus_execute_append_capabilities, "s", 0 },
401 { "SecureBits", bus_property_append_int, "i", offsetof(ExecContext, secure_bits) },
402 { "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", offsetof(ExecContext, capability_bounding_set_drop) },
403 { "User", bus_property_append_string, "s", offsetof(ExecContext, user), true },
404 { "Group", bus_property_append_string, "s", offsetof(ExecContext, group), true },
405 { "SupplementaryGroups", bus_property_append_strv, "as", offsetof(ExecContext, supplementary_groups), true },
406 { "TCPWrapName", bus_property_append_string, "s", offsetof(ExecContext, tcpwrap_name), true },
407 { "PAMName", bus_property_append_string, "s", offsetof(ExecContext, pam_name), true },
408 { "ReadWriteDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_write_dirs), true },
409 { "ReadOnlyDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_only_dirs), true },
410 { "InaccessibleDirectories", bus_property_append_strv, "as", offsetof(ExecContext, inaccessible_dirs), true },
411 { "MountFlags", bus_property_append_ul, "t", offsetof(ExecContext, mount_flags) },
412 { "PrivateTmp", bus_property_append_bool, "b", offsetof(ExecContext, private_tmp) },
413 { "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
414 { "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
415 { "KillMode", bus_execute_append_kill_mode, "s", offsetof(ExecContext, kill_mode) },
416 { "KillSignal", bus_property_append_int, "i", offsetof(ExecContext, kill_signal) },
417 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
418 { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
aa001cd6 419 { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
353e12c2 420 { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe ) },
d200735e
MS
421 { NULL, }
422};