diff options
author | Paweł Szewczyk <p.szewczyk@samsung.com> | 2018-05-30 14:31:47 +0200 |
---|---|---|
committer | Paweł Szewczyk <p.szewczyk@samsung.com> | 2018-06-26 15:40:14 +0200 |
commit | 3e5d642ba1a6eba5541e68422120b8ad64bd14a6 (patch) | |
tree | d0304eb838427a0d6372c9ddf403ab908da82c2a /hw | |
parent | 91fd4db10bce6d25e769893d5c81a0e19fac6623 (diff) | |
download | libdevice-node-3e5d642ba1a6eba5541e68422120b8ad64bd14a6.tar.gz libdevice-node-3e5d642ba1a6eba5541e68422120b8ad64bd14a6.tar.bz2 libdevice-node-3e5d642ba1a6eba5541e68422120b8ad64bd14a6.zip |
Add API for controling systemd units
Change-Id: Ic13a69fbf0008ce37c0774b857e718335c0cf921
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/systemd.c | 177 | ||||
-rw-r--r-- | hw/systemd.h | 37 |
2 files changed, 214 insertions, 0 deletions
diff --git a/hw/systemd.c b/hw/systemd.c new file mode 100644 index 0000000..97d32ce --- /dev/null +++ b/hw/systemd.c @@ -0,0 +1,177 @@ +/* + * libdevice-node + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdbool.h> +#include <hw/systemd.h> +#include <systemd/sd-bus.h> + +#define SYSTEMD_DBUS_SERVICE "org.freedesktop.systemd1" +#define SYSTEMD_DBUS_PATH "/org/freedesktop/systemd1" +#define SYSTEMD_DBUS_MANAGER_IFACE "org.freedesktop.systemd1.Manager" + +#define SYSTEMD_SOCKET_SUFFIX ".socket" +#define MAX_SOCKET_NAME 1024 + +#define SYSTEMD_SERVICE_SUFFIX ".service" +#define MAX_SERVICE_NAME 1024 + +#ifndef EXPORT +#define EXPORT __attribute__ ((visibility("default"))) +#endif + +struct bus_ctx { + const char *unit; + sd_event *loop; +}; + +static int socket_started(sd_bus_message *m, void *userdata, + sd_bus_error *ret_error) +{ + struct bus_ctx *ctx = userdata; + char *signal_unit; + int ret; + + ret = sd_bus_message_read(m, "uoss", NULL, NULL, &signal_unit, NULL); + if (ret < 0) { + sd_event_exit(ctx->loop, ret); + return 0; + } + + if (!strcmp(signal_unit, ctx->unit)) + sd_event_exit(ctx->loop, 0); + + return 0; +} + +static int systemd_unit_interface_sync(const char *method, const char *unit, + bool wait) +{ + sd_bus *bus = NULL; + sd_event *loop = NULL; + struct bus_ctx ctx; + int ret; + + ret = sd_bus_open_system(&bus); + if (ret < 0) + return ret; + + if (wait) { + ret = sd_event_new(&loop); + if (ret < 0) + goto unref_bus; + + ctx.loop = loop; + ctx.unit = unit; + + ret = sd_bus_attach_event(bus, loop, SD_EVENT_PRIORITY_NORMAL); + if (ret < 0) + goto unref_loop; + + ret = sd_bus_add_match(bus, NULL, + "type='signal'," + "sender='" SYSTEMD_DBUS_SERVICE "'," + "interface='" SYSTEMD_DBUS_MANAGER_IFACE "'," + "member='JobRemoved'," + "path_namespace='" SYSTEMD_DBUS_PATH "'", + socket_started, + &ctx); + if (ret < 0) + goto unref_loop; + } + + + ret = sd_bus_call_method(bus, + SYSTEMD_DBUS_SERVICE, + SYSTEMD_DBUS_PATH, + SYSTEMD_DBUS_MANAGER_IFACE, + method, + NULL, + NULL, + "ss", + unit, + "replace"); + if (ret < 0) + goto unref_loop; + + if (wait) + ret = sd_event_loop(loop); + +unref_loop: + if (wait) + sd_event_unref(loop); +unref_bus: + sd_bus_unref(bus); + return ret; +} + +EXPORT int systemd_start_service(const char *service_name) +{ + char unit[MAX_SERVICE_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SERVICE_SUFFIX, + service_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + return systemd_unit_interface_sync("StartUnit", unit, true); +} + +EXPORT int systemd_stop_service(const char *service_name) +{ + char unit[MAX_SERVICE_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SERVICE_SUFFIX, + service_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + return systemd_unit_interface_sync("StopUnit", unit, false); +} + +EXPORT int systemd_start_socket(const char *socket_name) +{ + char unit[MAX_SOCKET_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SOCKET_SUFFIX, + socket_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + + return systemd_unit_interface_sync("StartUnit", unit, true); +} + +EXPORT int systemd_stop_socket(const char *socket_name) +{ + char unit[MAX_SOCKET_NAME]; + int ret; + + ret = snprintf(unit, sizeof(unit), "%s" SYSTEMD_SOCKET_SUFFIX, + socket_name); + if (ret < 0 || ret >= sizeof(unit)) + return -ENAMETOOLONG; + + return systemd_unit_interface_sync("StopUnit", unit, false); +} diff --git a/hw/systemd.h b/hw/systemd.h new file mode 100644 index 0000000..28ce944 --- /dev/null +++ b/hw/systemd.h @@ -0,0 +1,37 @@ +/* + * libdevice-node + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __HW_SYSTEMD_H__ +#define __HW_SYSTEMD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int systemd_start_service(const char *service_name); +int systemd_stop_service(const char *service_name); +int systemd_start_socket(const char *socket_name); +int systemd_stop_socket(const char *socket_name); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __HW_SYSTEMD_H__ */ + |