dbus-service.c revision 6ce270b10ad5538fb60dabcf409a49a9c5fd0e8d
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering/***
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering This file is part of systemd.
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering Copyright 2010 Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering systemd is free software; you can redistribute it and/or modify it
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering under the terms of the GNU Lesser General Public License as published by
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering (at your option) any later version.
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering systemd is distributed in the hope that it will be useful, but
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering Lesser General Public License for more details.
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering You should have received a copy of the GNU Lesser General Public License
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering***/
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "strv.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "path-util.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "unit.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "service.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "dbus-unit.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "dbus-execute.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "dbus-kill.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "dbus-cgroup.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "dbus-service.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "bus-util.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_start_limit_action, start_limit_action, StartLimitAction);
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringconst sd_bus_vtable bus_service_vtable[] = {
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_VTABLE_START(0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_COMMAND_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_COMMAND_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_COMMAND_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_COMMAND_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering BUS_EXEC_COMMAND_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), 0),
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering SD_BUS_VTABLE_END
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering};
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringconst char* const bus_service_changing_properties[] = {
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainStartTimestamp",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainStartTimestampMonotonic",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainExitTimestamp",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainExitTimestampMonotonic",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainPID",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainCode",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ExecMainStatus",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "MainPID",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "ControlPID",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "StatusText",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering "Result",
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering NULL
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering};
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic int bus_service_set_transient_property(
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering Service *s,
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
sd_bus_error *error) {
int r;
assert(s);
assert(name);
assert(message);
if (streq(name, "RemainAfterExit")) {
int b;
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
s->remain_after_exit = b;
unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
}
return 1;
} else if (streq(name, "ExecStart")) {
unsigned n = 0;
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
if (r < 0)
return r;
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
_cleanup_strv_free_ char **argv = NULL;
const char *path;
int b;
r = sd_bus_message_read(message, "s", &path);
if (r < 0)
return r;
if (!path_is_absolute(path))
return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
r = sd_bus_message_read_strv(message, &argv);
if (r < 0)
return r;
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
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;
c->ignore = b;
path_kill_slashes(c->path);
exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
}
n++;
}
if (r < 0)
return r;
r = sd_bus_message_exit_container(message);
if (r < 0)
return r;
if (mode != UNIT_CHECK) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
ExecCommand *c;
size_t size = 0;
if (n == 0) {
exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
s->exec_command[SERVICE_EXEC_START] = NULL;
}
f = open_memstream(&buf, &size);
if (!f)
return -ENOMEM;
fputs("ExecStart=\n", f);
LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
_cleanup_free_ char *a;
a = strv_join_quoted(c->argv);
if (!a)
return -ENOMEM;
fprintf(f, "ExecStart=%s@%s %s\n",
c->ignore ? "-" : "",
c->path,
a);
}
fflush(f);
unit_write_drop_in_private(UNIT(s), mode, name, buf);
}
return 1;
}
return 0;
}
int bus_service_set_property(
Unit *u,
const char *name,
sd_bus_message *message,
UnitSetPropertiesMode mode,
sd_bus_error *error) {
Service *s = SERVICE(u);
int r;
assert(s);
assert(name);
assert(message);
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
if (r != 0)
return r;
if (u->transient && u->load_state == UNIT_STUB) {
/* This is a transient unit, let's load a little more */
r = bus_service_set_transient_property(s, name, message, mode, error);
if (r != 0)
return r;
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
if (r != 0)
return r;
}
return 0;
}
int bus_service_commit_properties(Unit *u) {
assert(u);
unit_realize_cgroup(u);
return 0;
}