2010-04-18 03:08:16 +02:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
2012-04-12 00:20:58 +02:00
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
2010-04-18 03:08:16 +02:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2012-04-12 00:20:58 +02:00
|
|
|
Lesser General Public License for more details.
|
2010-04-18 03:08:16 +02:00
|
|
|
|
2012-04-12 00:20:58 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
2010-04-18 03:08:16 +02:00
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-10-07 23:07:39 +02:00
|
|
|
#include "async.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "bus-util.h"
|
|
|
|
#include "dbus-cgroup.h"
|
2010-04-18 03:08:16 +02:00
|
|
|
#include "dbus-execute.h"
|
2012-07-19 23:47:10 +02:00
|
|
|
#include "dbus-kill.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "dbus-service.h"
|
|
|
|
#include "fd-util.h"
|
2015-10-26 18:05:03 +01:00
|
|
|
#include "fileio.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "path-util.h"
|
|
|
|
#include "service.h"
|
|
|
|
#include "string-util.h"
|
|
|
|
#include "strv.h"
|
|
|
|
#include "unit.h"
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
|
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
|
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
|
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
|
2016-10-20 15:27:37 +02:00
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
const sd_bus_vtable bus_service_vtable[] = {
|
|
|
|
SD_BUS_VTABLE_START(0),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
core: rework unit timeout handling, and add new setting RuntimeMaxSec=
This clean-ups timeout handling in PID 1. Specifically, instead of storing 0 in internal timeout variables as
indication for a disabled timeout, use USEC_INFINITY which is in-line with how we do this in the rest of our code
(following the logic that 0 means "no", and USEC_INFINITY means "never").
This also replace all usec_t additions with invocations to usec_add(), so that USEC_INFINITY is properly propagated,
and sd-event considers it has indication for turning off the event source.
This also alters the deserialization of the units to restart timeouts from the time they were originally started from.
Before this patch timeouts would be restarted beginning with the time of the deserialization, which could lead to
artificially prolonged timeouts if a daemon reload took place.
Finally, a new RuntimeMaxSec= setting is introduced for service units, that specifies a maximum runtime after which a
specific service is forcibly terminated. This is useful to put time limits on time-intensive processing jobs.
This also simplifies the various xyz_spawn() calls of the various types in that explicit distruction of the timers is
removed, as that is done anyway by the state change handlers, and a state change is always done when the xyz_spawn()
calls fail.
Fixes: #2249
2016-02-01 21:48:10 +01:00
|
|
|
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-11-19 21:12:59 +01:00
|
|
|
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
|
2016-10-20 15:27:37 +02:00
|
|
|
SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Service, emergency_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-12-22 02:24:05 +01:00
|
|
|
SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
|
2015-11-02 23:09:06 +01:00
|
|
|
SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
|
SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2014-07-07 14:20:36 +02:00
|
|
|
SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2015-09-04 12:23:51 +02:00
|
|
|
SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2016-08-01 19:24:40 +02:00
|
|
|
SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
2013-12-22 02:24:05 +01:00
|
|
|
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
|
|
|
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
|
|
|
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
|
|
|
BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
|
|
|
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
|
|
|
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
2016-08-01 17:40:37 +02:00
|
|
|
|
|
|
|
/* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
|
|
|
|
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
|
|
|
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
2016-10-20 15:27:37 +02:00
|
|
|
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
2016-08-01 17:40:37 +02:00
|
|
|
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_VTABLE_END
|
2012-01-16 00:23:59 +01:00
|
|
|
};
|
|
|
|
|
2013-07-01 00:40:56 +02:00
|
|
|
static int bus_service_set_transient_property(
|
2013-06-28 04:12:58 +02:00
|
|
|
Service *s,
|
|
|
|
const char *name,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_message *message,
|
2013-06-28 04:12:58 +02:00
|
|
|
UnitSetPropertiesMode mode,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error *error) {
|
2013-06-28 04:12:58 +02:00
|
|
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(s);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(name);
|
|
|
|
assert(message);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-07-26 16:09:25 +02:00
|
|
|
if (streq(name, "RemainAfterExit")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
int b;
|
2013-07-26 16:09:25 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-26 16:09:25 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (mode != UNIT_CHECK) {
|
2013-07-26 16:09:25 +02:00
|
|
|
s->remain_after_exit = b;
|
2016-05-28 22:21:47 +02:00
|
|
|
unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s", yes_no(b));
|
2013-07-26 16:09:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2014-02-05 02:02:00 +01:00
|
|
|
} else if (streq(name, "Type")) {
|
|
|
|
const char *t;
|
|
|
|
ServiceType k;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "s", &t);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
k = service_type_from_string(t);
|
|
|
|
if (k < 0)
|
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
s->type = k;
|
2016-05-28 22:21:47 +02:00
|
|
|
unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s", service_type_to_string(s->type));
|
2014-02-05 02:02:00 +01:00
|
|
|
}
|
|
|
|
|
core: rework unit timeout handling, and add new setting RuntimeMaxSec=
This clean-ups timeout handling in PID 1. Specifically, instead of storing 0 in internal timeout variables as
indication for a disabled timeout, use USEC_INFINITY which is in-line with how we do this in the rest of our code
(following the logic that 0 means "no", and USEC_INFINITY means "never").
This also replace all usec_t additions with invocations to usec_add(), so that USEC_INFINITY is properly propagated,
and sd-event considers it has indication for turning off the event source.
This also alters the deserialization of the units to restart timeouts from the time they were originally started from.
Before this patch timeouts would be restarted beginning with the time of the deserialization, which could lead to
artificially prolonged timeouts if a daemon reload took place.
Finally, a new RuntimeMaxSec= setting is introduced for service units, that specifies a maximum runtime after which a
specific service is forcibly terminated. This is useful to put time limits on time-intensive processing jobs.
This also simplifies the various xyz_spawn() calls of the various types in that explicit distruction of the timers is
removed, as that is done anyway by the state change handlers, and a state change is always done when the xyz_spawn()
calls fail.
Fixes: #2249
2016-02-01 21:48:10 +01:00
|
|
|
return 1;
|
|
|
|
} else if (streq(name, "RuntimeMaxUSec")) {
|
|
|
|
usec_t u;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "t", &u);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
s->runtime_max_usec = u;
|
2016-05-28 22:21:47 +02:00
|
|
|
unit_write_drop_in_private_format(UNIT(s), mode, name, "RuntimeMaxSec=" USEC_FMT "us", u);
|
core: rework unit timeout handling, and add new setting RuntimeMaxSec=
This clean-ups timeout handling in PID 1. Specifically, instead of storing 0 in internal timeout variables as
indication for a disabled timeout, use USEC_INFINITY which is in-line with how we do this in the rest of our code
(following the logic that 0 means "no", and USEC_INFINITY means "never").
This also replace all usec_t additions with invocations to usec_add(), so that USEC_INFINITY is properly propagated,
and sd-event considers it has indication for turning off the event source.
This also alters the deserialization of the units to restart timeouts from the time they were originally started from.
Before this patch timeouts would be restarted beginning with the time of the deserialization, which could lead to
artificially prolonged timeouts if a daemon reload took place.
Finally, a new RuntimeMaxSec= setting is introduced for service units, that specifies a maximum runtime after which a
specific service is forcibly terminated. This is useful to put time limits on time-intensive processing jobs.
This also simplifies the various xyz_spawn() calls of the various types in that explicit distruction of the timers is
removed, as that is done anyway by the state change handlers, and a state change is always done when the xyz_spawn()
calls fail.
Fixes: #2249
2016-02-01 21:48:10 +01:00
|
|
|
}
|
|
|
|
|
2014-02-05 02:02:00 +01:00
|
|
|
return 1;
|
|
|
|
|
2016-11-24 00:44:57 +01:00
|
|
|
} else if (streq(name, "Restart")) {
|
|
|
|
ServiceRestart sr;
|
|
|
|
const char *v;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "s", &v);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (isempty(v))
|
|
|
|
sr = SERVICE_RESTART_NO;
|
|
|
|
else {
|
|
|
|
sr = service_restart_from_string(v);
|
|
|
|
if (sr < 0)
|
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid restart setting: %s", v);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
s->restart = sr;
|
|
|
|
unit_write_drop_in_private_format(UNIT(s), mode, name, "Restart=%s", service_restart_to_string(sr));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2015-10-07 23:07:39 +02:00
|
|
|
} else if (STR_IN_SET(name,
|
|
|
|
"StandardInputFileDescriptor",
|
|
|
|
"StandardOutputFileDescriptor",
|
|
|
|
"StandardErrorFileDescriptor")) {
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "h", &fd);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
int copy;
|
|
|
|
|
|
|
|
copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
|
|
|
if (copy < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
if (streq(name, "StandardInputFileDescriptor")) {
|
|
|
|
asynchronous_close(s->stdin_fd);
|
|
|
|
s->stdin_fd = copy;
|
|
|
|
} else if (streq(name, "StandardOutputFileDescriptor")) {
|
|
|
|
asynchronous_close(s->stdout_fd);
|
|
|
|
s->stdout_fd = copy;
|
|
|
|
} else {
|
|
|
|
asynchronous_close(s->stderr_fd);
|
|
|
|
s->stderr_fd = copy;
|
|
|
|
}
|
2016-01-28 16:25:39 +01:00
|
|
|
|
|
|
|
s->exec_context.stdio_as_fds = true;
|
2015-10-07 23:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2013-07-26 16:09:25 +02:00
|
|
|
} else if (streq(name, "ExecStart")) {
|
2013-06-28 04:12:58 +02:00
|
|
|
unsigned n = 0;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
|
2013-06-28 04:12:58 +02:00
|
|
|
_cleanup_strv_free_ char **argv = NULL;
|
|
|
|
const char *path;
|
2013-11-19 21:12:59 +01:00
|
|
|
int b;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "s", &path);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!path_is_absolute(path))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read_strv(message, &argv);
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
ExecCommand *c;
|
|
|
|
|
|
|
|
c = new0(ExecCommand, 1);
|
|
|
|
if (!c)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c->path = strdup(path);
|
|
|
|
if (!c->path) {
|
|
|
|
free(c);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
c->argv = argv;
|
|
|
|
argv = NULL;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
c->ignore = b;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
|
|
|
path_kill_slashes(c->path);
|
|
|
|
exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
|
|
|
|
}
|
|
|
|
|
|
|
|
n++;
|
|
|
|
}
|
2014-02-05 02:02:00 +01:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-11-21 20:49:04 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-06-28 04:12:58 +02:00
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
_cleanup_free_ char *buf = NULL;
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
ExecCommand *c;
|
|
|
|
size_t size = 0;
|
|
|
|
|
2014-12-18 18:29:24 +01:00
|
|
|
if (n == 0)
|
|
|
|
s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
|
2013-06-28 04:12:58 +02:00
|
|
|
|
|
|
|
f = open_memstream(&buf, &size);
|
|
|
|
if (!f)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
fputs("ExecStart=\n", f);
|
|
|
|
|
|
|
|
LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
|
2013-08-31 20:28:09 +02:00
|
|
|
_cleanup_free_ char *a;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-08-31 20:28:09 +02:00
|
|
|
a = strv_join_quoted(c->argv);
|
|
|
|
if (!a)
|
|
|
|
return -ENOMEM;
|
2013-06-28 04:12:58 +02:00
|
|
|
|
2013-08-31 20:28:09 +02:00
|
|
|
fprintf(f, "ExecStart=%s@%s %s\n",
|
|
|
|
c->ignore ? "-" : "",
|
|
|
|
c->path,
|
|
|
|
a);
|
2013-06-28 04:12:58 +02:00
|
|
|
}
|
|
|
|
|
2015-10-21 18:17:12 +02:00
|
|
|
r = fflush_and_check(f);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private(UNIT(s), mode, name, buf);
|
2013-06-28 04:12:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-27 23:21:21 +02:00
|
|
|
int bus_service_set_property(
|
|
|
|
Unit *u,
|
|
|
|
const char *name,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_message *message,
|
2013-06-27 23:21:21 +02:00
|
|
|
UnitSetPropertiesMode mode,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error *error) {
|
2013-06-27 23:21:21 +02:00
|
|
|
|
|
|
|
Service *s = SERVICE(u);
|
|
|
|
int r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(s);
|
2013-06-27 23:21:21 +02:00
|
|
|
assert(name);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(message);
|
2013-06-27 23:21:21 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
|
2013-06-27 23:21:21 +02:00
|
|
|
if (r != 0)
|
|
|
|
return r;
|
|
|
|
|
2013-06-28 04:12:58 +02:00
|
|
|
if (u->transient && u->load_state == UNIT_STUB) {
|
|
|
|
/* This is a transient unit, let's load a little more */
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = bus_service_set_transient_property(s, name, message, mode, error);
|
2013-06-28 04:12:58 +02:00
|
|
|
if (r != 0)
|
|
|
|
return r;
|
2013-07-30 02:28:22 +02:00
|
|
|
|
2014-02-05 02:02:00 +01:00
|
|
|
r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
|
|
|
|
if (r != 0)
|
|
|
|
return r;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
|
2013-07-30 02:28:22 +02:00
|
|
|
if (r != 0)
|
|
|
|
return r;
|
2013-06-28 04:12:58 +02:00
|
|
|
}
|
|
|
|
|
2013-06-27 23:21:21 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bus_service_commit_properties(Unit *u) {
|
|
|
|
assert(u);
|
|
|
|
|
2014-02-14 19:11:07 +01:00
|
|
|
unit_update_cgroup_members_masks(u);
|
2013-06-27 23:21:21 +02:00
|
|
|
unit_realize_cgroup(u);
|
2014-02-14 19:11:07 +01:00
|
|
|
|
2013-06-27 23:21:21 +02:00
|
|
|
return 0;
|
|
|
|
}
|