]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
strbuf: replace quick sort with bubble sort
[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"
8351ceae 31#include "syscall-list.h"
a5c32cff 32#include "fileio.h"
4139c1b2
LP
33
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);
86 }
87 }
88
89 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
90 return -ENOMEM;
91
92 return 0;
93}
94
bfebab7f 95int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
96 ExecContext *c = data;
97 int32_t n;
98
82c121a4
LP
99 assert(i);
100 assert(property);
101 assert(c);
102
103 if (c->nice_set)
104 n = c->nice;
105 else
106 n = getpriority(PRIO_PROCESS, 0);
107
108 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
109 return -ENOMEM;
110
111 return 0;
112}
113
bfebab7f 114int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
115 ExecContext *c = data;
116 int32_t n;
117
82c121a4
LP
118 assert(i);
119 assert(property);
120 assert(c);
121
122 if (c->ioprio_set)
123 n = c->ioprio;
124 else
125 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
126
127 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
128 return -ENOMEM;
129
130 return 0;
131}
132
bfebab7f 133int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
134 ExecContext *c = data;
135 int32_t n;
136
82c121a4
LP
137 assert(i);
138 assert(property);
139 assert(c);
140
141 if (c->cpu_sched_set)
142 n = c->cpu_sched_policy;
143 else
144 n = sched_getscheduler(0);
145
146 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
147 return -ENOMEM;
148
149 return 0;
150}
151
bfebab7f 152int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
153 ExecContext *c = data;
154 int32_t n;
155
82c121a4
LP
156 assert(i);
157 assert(property);
158 assert(c);
159
160 if (c->cpu_sched_set)
161 n = c->cpu_sched_priority;
162 else {
163 struct sched_param p;
164 n = 0;
165
166 zero(p);
167 if (sched_getparam(0, &p) >= 0)
168 n = p.sched_priority;
169 }
170
171 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
172 return -ENOMEM;
173
174 return 0;
175}
176
bfebab7f 177int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
178 ExecContext *c = data;
179 dbus_bool_t b;
180 DBusMessageIter sub;
181
82c121a4
LP
182 assert(i);
183 assert(property);
184 assert(c);
185
fe68089d 186 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
82c121a4
LP
187 return -ENOMEM;
188
189 if (c->cpuset)
190 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
191 else
192 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
193
194 if (!b)
195 return -ENOMEM;
196
197 if (!dbus_message_iter_close_container(i, &sub))
198 return -ENOMEM;
199
200 return 0;
201}
202
bfebab7f 203int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
204 ExecContext *c = data;
205 uint64_t u;
206
82c121a4
LP
207 assert(i);
208 assert(property);
209 assert(c);
210
d88a251b 211 if (c->timer_slack_nsec != (nsec_t) -1)
03fae018 212 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
213 else
214 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
215
216 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
217 return -ENOMEM;
218
219 return 0;
220}
221
bfebab7f 222int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
260abb78
LP
223 ExecContext *c = data;
224 uint64_t normal, inverted;
225
260abb78
LP
226 assert(i);
227 assert(property);
228 assert(c);
229
7c3d67ef 230 /* We store this negated internally, to match the kernel, but
260abb78
LP
231 * we expose it normalized. */
232
233 normal = *(uint64_t*) data;
234 inverted = ~normal;
235
bfebab7f 236 return bus_property_append_uint64(i, property, &inverted);
260abb78
LP
237}
238
bfebab7f 239int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
240 ExecContext *c = data;
241 char *t = NULL;
242 const char *s;
243 dbus_bool_t b;
244
82c121a4
LP
245 assert(i);
246 assert(property);
247 assert(c);
248
249 if (c->capabilities)
250 s = t = cap_to_text(c->capabilities, NULL);
251 else
252 s = "";
253
674cdd19 254 if (!s)
82c121a4
LP
255 return -ENOMEM;
256
257 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
674cdd19
LP
258
259 if (t)
260 cap_free(t);
82c121a4
LP
261
262 if (!b)
263 return -ENOMEM;
264
265 return 0;
266}
267
bfebab7f 268int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
269 ExecContext *c = data;
270 int r;
271 uint64_t u;
272
82c121a4
LP
273 assert(i);
274 assert(property);
275 assert(c);
276
277 assert_se((r = rlimit_from_string(property)) >= 0);
278
279 if (c->rlimit[r])
280 u = (uint64_t) c->rlimit[r]->rlim_max;
281 else {
282 struct rlimit rl;
283
284 zero(rl);
285 getrlimit(r, &rl);
286
287 u = (uint64_t) rl.rlim_max;
288 }
289
290 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
291 return -ENOMEM;
292
293 return 0;
294}
fe68089d 295
bfebab7f 296int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
fe68089d
LP
297 ExecCommand *c = data;
298 DBusMessageIter sub, sub2, sub3;
299
fe68089d
LP
300 assert(i);
301 assert(property);
302
7daa9e6e 303 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
fe68089d
LP
304 return -ENOMEM;
305
306 LIST_FOREACH(command, c, c) {
307 char **l;
308 uint32_t pid;
309 int32_t code, status;
7daa9e6e 310 dbus_bool_t b;
fe68089d
LP
311
312 if (!c->path)
313 continue;
314
315 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
316 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
317 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
318 return -ENOMEM;
319
320 STRV_FOREACH(l, c->argv)
321 if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
322 return -ENOMEM;
323
324 pid = (uint32_t) c->exec_status.pid;
325 code = (int32_t) c->exec_status.code;
326 status = (int32_t) c->exec_status.status;
327
7daa9e6e
LP
328 b = !!c->ignore;
329
fe68089d 330 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
7daa9e6e 331 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
fe68089d 332 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
b21a0ef8 333 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
fe68089d 334 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
b21a0ef8 335 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
e364ad06
LP
336 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
337 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
338 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
fe68089d
LP
339 return -ENOMEM;
340
341 if (!dbus_message_iter_close_container(&sub, &sub2))
342 return -ENOMEM;
343 }
344
345 if (!dbus_message_iter_close_container(i, &sub))
346 return -ENOMEM;
347
348 return 0;
349}
d200735e 350
8351ceae
LP
351int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
352 ExecContext *c = data;
353 dbus_bool_t b;
354 DBusMessageIter sub;
355
356 assert(i);
357 assert(property);
358 assert(c);
359
360 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "u", &sub))
361 return -ENOMEM;
362
363 if (c->syscall_filter)
364 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, (syscall_max() + 31) >> 4);
365 else
366 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, 0);
367
368 if (!b)
369 return -ENOMEM;
370
371 if (!dbus_message_iter_close_container(i, &sub))
372 return -ENOMEM;
373
374 return 0;
375}
376
d200735e
MS
377const BusProperty bus_exec_context_properties[] = {
378 { "Environment", bus_property_append_strv, "as", offsetof(ExecContext, environment), true },
379 { "EnvironmentFiles", bus_execute_append_env_files, "a(sb)", offsetof(ExecContext, environment_files), true },
380 { "UMask", bus_property_append_mode, "u", offsetof(ExecContext, umask) },
381 { "LimitCPU", bus_execute_append_rlimits, "t", 0 },
382 { "LimitFSIZE", bus_execute_append_rlimits, "t", 0 },
383 { "LimitDATA", bus_execute_append_rlimits, "t", 0 },
384 { "LimitSTACK", bus_execute_append_rlimits, "t", 0 },
385 { "LimitCORE", bus_execute_append_rlimits, "t", 0 },
386 { "LimitRSS", bus_execute_append_rlimits, "t", 0 },
387 { "LimitNOFILE", bus_execute_append_rlimits, "t", 0 },
388 { "LimitAS", bus_execute_append_rlimits, "t", 0 },
389 { "LimitNPROC", bus_execute_append_rlimits, "t", 0 },
390 { "LimitMEMLOCK", bus_execute_append_rlimits, "t", 0 },
391 { "LimitLOCKS", bus_execute_append_rlimits, "t", 0 },
392 { "LimitSIGPENDING", bus_execute_append_rlimits, "t", 0 },
393 { "LimitMSGQUEUE", bus_execute_append_rlimits, "t", 0 },
394 { "LimitNICE", bus_execute_append_rlimits, "t", 0 },
395 { "LimitRTPRIO", bus_execute_append_rlimits, "t", 0 },
396 { "LimitRTTIME", bus_execute_append_rlimits, "t", 0 },
397 { "WorkingDirectory", bus_property_append_string, "s", offsetof(ExecContext, working_directory), true },
398 { "RootDirectory", bus_property_append_string, "s", offsetof(ExecContext, root_directory), true },
399 { "OOMScoreAdjust", bus_execute_append_oom_score_adjust, "i", 0 },
400 { "Nice", bus_execute_append_nice, "i", 0 },
401 { "IOScheduling", bus_execute_append_ioprio, "i", 0 },
402 { "CPUSchedulingPolicy", bus_execute_append_cpu_sched_policy, "i", 0 },
403 { "CPUSchedulingPriority", bus_execute_append_cpu_sched_priority, "i", 0 },
404 { "CPUAffinity", bus_execute_append_affinity, "ay", 0 },
405 { "TimerSlackNSec", bus_execute_append_timer_slack_nsec, "t", 0 },
406 { "CPUSchedulingResetOnFork", bus_property_append_bool, "b", offsetof(ExecContext, cpu_sched_reset_on_fork) },
407 { "NonBlocking", bus_property_append_bool, "b", offsetof(ExecContext, non_blocking) },
408 { "StandardInput", bus_execute_append_input, "s", offsetof(ExecContext, std_input) },
409 { "StandardOutput", bus_execute_append_output, "s", offsetof(ExecContext, std_output) },
410 { "StandardError", bus_execute_append_output, "s", offsetof(ExecContext, std_error) },
411 { "TTYPath", bus_property_append_string, "s", offsetof(ExecContext, tty_path), true },
412 { "TTYReset", bus_property_append_bool, "b", offsetof(ExecContext, tty_reset) },
413 { "TTYVHangup", bus_property_append_bool, "b", offsetof(ExecContext, tty_vhangup) },
414 { "TTYVTDisallocate", bus_property_append_bool, "b", offsetof(ExecContext, tty_vt_disallocate) },
415 { "SyslogPriority", bus_property_append_int, "i", offsetof(ExecContext, syslog_priority) },
416 { "SyslogIdentifier", bus_property_append_string, "s", offsetof(ExecContext, syslog_identifier), true },
417 { "SyslogLevelPrefix", bus_property_append_bool, "b", offsetof(ExecContext, syslog_level_prefix) },
418 { "Capabilities", bus_execute_append_capabilities, "s", 0 },
419 { "SecureBits", bus_property_append_int, "i", offsetof(ExecContext, secure_bits) },
420 { "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", offsetof(ExecContext, capability_bounding_set_drop) },
421 { "User", bus_property_append_string, "s", offsetof(ExecContext, user), true },
422 { "Group", bus_property_append_string, "s", offsetof(ExecContext, group), true },
423 { "SupplementaryGroups", bus_property_append_strv, "as", offsetof(ExecContext, supplementary_groups), true },
424 { "TCPWrapName", bus_property_append_string, "s", offsetof(ExecContext, tcpwrap_name), true },
425 { "PAMName", bus_property_append_string, "s", offsetof(ExecContext, pam_name), true },
426 { "ReadWriteDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_write_dirs), true },
427 { "ReadOnlyDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_only_dirs), true },
428 { "InaccessibleDirectories", bus_property_append_strv, "as", offsetof(ExecContext, inaccessible_dirs), true },
429 { "MountFlags", bus_property_append_ul, "t", offsetof(ExecContext, mount_flags) },
430 { "PrivateTmp", bus_property_append_bool, "b", offsetof(ExecContext, private_tmp) },
431 { "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
432 { "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
d200735e
MS
433 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
434 { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
aa001cd6 435 { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
8351ceae
LP
436 { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe) },
437 { "NoNewPrivileges", bus_property_append_bool, "b", offsetof(ExecContext, no_new_privileges) },
438 { "SystemCallFilter", bus_execute_append_syscall_filter, "au", 0 },
d200735e
MS
439 { NULL, }
440};