X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Futils-systemd.c;h=54385001b7d6dd24aaef10da99048be81d0f7060;hb=af8db35cc01c57b7d1d2e4fa7815df8c16f8454f;hp=830fec6bda6d9ae52fc3d40dabd4df28a979311a;hpb=b6afa1aa893544b459cb767cc5a2ad8d2148228c;p=src%2Fapp-framework-main.git diff --git a/src/utils-systemd.c b/src/utils-systemd.c index 830fec6..5438500 100644 --- a/src/utils-systemd.c +++ b/src/utils-systemd.c @@ -1,5 +1,5 @@ /* - Copyright 2017 IoT.bzh + Copyright (C) 2015-2020 IoT.bzh author: José Bollo @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef NO_LIBSYSTEMD # include @@ -34,6 +35,7 @@ struct sd_bus; struct sd_bus_message; typedef struct { const char *name; const char *message; } sd_bus_error; +# define sd_bus_unref(...) ((void)0) # define sd_bus_default_user(p) ((*(p)=NULL),(-ENOTSUP)) # define sd_bus_default_system(p) ((*(p)=NULL),(-ENOTSUP)) # define sd_bus_call_method(...) (-ENOTSUP) @@ -55,10 +57,14 @@ static const char sdb_destination[] = "org.freedesktop.systemd1"; static const char sdbi_manager[] = "org.freedesktop.systemd1.Manager"; static const char sdbi_unit[] = "org.freedesktop.systemd1.Unit"; static const char sdbi_service[] = "org.freedesktop.systemd1.Service"; +static const char sdbi_job[] = "org.freedesktop.systemd1.Job"; +static const char sdbj_state[] = "State"; static const char sdbm_reload[] = "Reload"; static const char sdbm_start_unit[] = "StartUnit"; +static const char sdbm_restart_unit[] = "RestartUnit"; static const char sdbm_stop_unit[] = "StopUnit"; static const char sdbm_start[] = "Start"; +static const char sdbm_restart[] = "Restart"; static const char sdbm_stop[] = "Stop"; static const char sdbm_get_unit[] = "GetUnit"; static const char sdbm_get_unit_by_pid[] = "GetUnitByPID"; @@ -66,12 +72,21 @@ static const char sdbm_load_unit[] = "LoadUnit"; static const char sdbp_active_state[] = "ActiveState"; static const char sdbp_exec_main_pid[] = "ExecMainPID"; -const char SysD_State_Inactive[] = "inactive"; -const char SysD_State_Activating[] = "activating"; -const char SysD_State_Active[] = "active"; -const char SysD_State_Deactivating[] = "deactivating"; -const char SysD_State_Reloading[] = "reloading"; -const char SysD_State_Failed[] = "failed"; +static const char *sds_state_names[] = { + NULL, + "inactive", + "activating", + "active", + "deactivating", + "reloading", + "failed" +}; + +static const char *sds_job_state_names[] = { + NULL, + "waiting", + "running" +}; static struct sd_bus *sysbus; static struct sd_bus *usrbus; @@ -95,11 +110,12 @@ static int errno2sderr(int rc) return rc < 0 ? -errno : rc; } -/* Returns in 'ret' either the system bus (if isuser==0) +/* + * Returns in 'ret' either the system bus (if isuser==0) * or the user bus (if isuser!=0). * Returns 0 in case of success or -1 in case of error */ -static int get_bus(int isuser, struct sd_bus **ret) +int systemd_get_bus(int isuser, struct sd_bus **ret) { int rc; struct sd_bus *bus; @@ -123,6 +139,14 @@ error: return sderr2errno(rc); } +void systemd_set_bus(int isuser, struct sd_bus *bus) +{ + struct sd_bus **target = isuser ? &usrbus : &sysbus; + if (*target) + sd_bus_unref(*target); + *target = bus; +} + #if 0 /******************************************************************** * routines for escaping unit names to compute dbus path of units @@ -245,39 +269,91 @@ static int unit_pid(struct sd_bus *bus, const char *dpath) return rc < 0 ? rc : (int)u; } -static const char *unit_state(struct sd_bus *bus, const char *dpath) +static enum SysD_State unit_state(struct sd_bus *bus, const char *dpath) { int rc; char *st; - const char *resu; + enum SysD_State resu; sd_bus_error err = SD_BUS_ERROR_NULL; + resu = SysD_State_INVALID; rc = sd_bus_get_property_string(bus, sdb_destination, dpath, sdbi_unit, sdbp_active_state, &err, &st); if (rc < 0) { errno = -rc; - resu = NULL; } else { - if (!strcmp(st, SysD_State_Active)) - resu = SysD_State_Active; - else if (!strcmp(st, SysD_State_Reloading)) - resu = SysD_State_Reloading; - else if (!strcmp(st, SysD_State_Inactive)) - resu = SysD_State_Inactive; - else if (!strcmp(st, SysD_State_Failed)) - resu = SysD_State_Failed; - else if (!strcmp(st, SysD_State_Activating)) - resu = SysD_State_Activating; - else if (!strcmp(st, SysD_State_Deactivating)) - resu = SysD_State_Deactivating; - else { - errno = EBADMSG; - resu = NULL; + switch (st[0]) { + case 'a': + if (!strcmp(st, sds_state_names[SysD_State_Active])) + resu = SysD_State_Active; + else if (!strcmp(st, sds_state_names[SysD_State_Activating])) + resu = SysD_State_Activating; + break; + case 'd': + if (!strcmp(st, sds_state_names[SysD_State_Deactivating])) + resu = SysD_State_Deactivating; + break; + case 'f': + if (!strcmp(st, sds_state_names[SysD_State_Failed])) + resu = SysD_State_Failed; + break; + case 'i': + if (!strcmp(st, sds_state_names[SysD_State_Inactive])) + resu = SysD_State_Inactive; + break; + case 'r': + if (!strcmp(st, sds_state_names[SysD_State_Reloading])) + resu = SysD_State_Reloading; + break; + default: + break; } + if (resu == NULL) + errno = EBADMSG; free(st); } return resu; } +static int job_wait(struct sd_bus *bus, struct sd_bus_message *job) +{ + int rc; + sd_bus_error err = SD_BUS_ERROR_NULL; + const char *jpath = NULL; + char *jstate; + struct timespec tispec; + const int period_ms = 10; + const int trial_s = 10; + const int trial_count = (trial_s * 1000) / period_ms; + const int period_ns = period_ms * 1000000; + int trial; + + /* Get job path */ + rc = sd_bus_message_read_basic(job, 'o', &jpath); + if (rc < 0) + return rc; + + /* Wait for job to enter "running" state */ + rc = 0; + for (trial = 1 ; trial <= trial_count ; trial++) { + jstate = NULL; + if(sd_bus_get_property_string(bus, sdb_destination, jpath, sdbi_job, sdbj_state, &err, &jstate) >= 0) { + if(jstate && strcmp(jstate, sds_job_state_names[SysD_Job_State_Running]) == 0) { + free(jstate); + break; + } else { + tispec.tv_sec = 0; + tispec.tv_nsec = period_ns; + nanosleep(&tispec, NULL); + } + free(jstate); + } + } + if(trial > trial_count) + rc = -1; + + return rc; +} + static int unit_start(struct sd_bus *bus, const char *dpath) { int rc; @@ -285,6 +361,23 @@ static int unit_start(struct sd_bus *bus, const char *dpath) sd_bus_error err = SD_BUS_ERROR_NULL; rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_start, &err, &ret, "s", "replace"); + if(ret) { + rc = job_wait(bus, ret); + } + sd_bus_message_unref(ret); + return rc; +} + +static int unit_restart(struct sd_bus *bus, const char *dpath) +{ + int rc; + struct sd_bus_message *ret = NULL; + sd_bus_error err = SD_BUS_ERROR_NULL; + + rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_restart, &err, &ret, "s", "replace"); + if(ret) { + rc = job_wait(bus, ret); + } sd_bus_message_unref(ret); return rc; } @@ -307,6 +400,23 @@ static int unit_start_name(struct sd_bus *bus, const char *name) sd_bus_error err = SD_BUS_ERROR_NULL; rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_start_unit, &err, &ret, "ss", name, "replace"); + if(ret) { + rc = job_wait(bus, ret); + } + sd_bus_message_unref(ret); + return rc; +} + +static int unit_restart_name(struct sd_bus *bus, const char *name) +{ + int rc; + struct sd_bus_message *ret = NULL; + sd_bus_error err = SD_BUS_ERROR_NULL; + + rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_restart_unit, &err, &ret, "ss", name, "replace"); + if(ret) { + rc = job_wait(bus, ret); + } sd_bus_message_unref(ret); return rc; } @@ -377,7 +487,7 @@ int systemd_daemon_reload(int isuser) struct sd_bus_message *ret = NULL; sd_bus_error err = SD_BUS_ERROR_NULL; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); if (rc >= 0) { /* TODO: asynchronous bind... */ /* TODO: more diagnostic... */ @@ -459,14 +569,14 @@ char *systemd_unit_dpath_by_name(int isuser, const char *name, int load) { struct sd_bus *bus; - return get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath(bus, name, load); + return systemd_get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath(bus, name, load); } char *systemd_unit_dpath_by_pid(int isuser, unsigned pid) { struct sd_bus *bus; - return get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath_by_pid(bus, pid); + return systemd_get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath_by_pid(bus, pid); } int systemd_unit_start_dpath(int isuser, const char *dpath) @@ -474,16 +584,25 @@ int systemd_unit_start_dpath(int isuser, const char *dpath) int rc; struct sd_bus *bus; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); return rc < 0 ? rc : unit_start(bus, dpath); } +int systemd_unit_restart_dpath(int isuser, const char *dpath) +{ + int rc; + struct sd_bus *bus; + + rc = systemd_get_bus(isuser, &bus); + return rc < 0 ? rc : unit_restart(bus, dpath); +} + int systemd_unit_stop_dpath(int isuser, const char *dpath) { int rc; struct sd_bus *bus; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); return rc < 0 ? rc : unit_stop(bus, dpath); } @@ -492,18 +611,29 @@ int systemd_unit_start_name(int isuser, const char *name) int rc; struct sd_bus *bus; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); if (rc >= 0) rc = unit_start_name(bus, name); return rc; } +int systemd_unit_restart_name(int isuser, const char *name) +{ + int rc; + struct sd_bus *bus; + + rc = systemd_get_bus(isuser, &bus); + if (rc >= 0) + rc = unit_restart_name(bus, name); + return rc; +} + int systemd_unit_stop_name(int isuser, const char *name) { int rc; struct sd_bus *bus; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); if (rc >= 0) rc = unit_stop_name(bus, name); return rc; @@ -515,7 +645,7 @@ int systemd_unit_stop_pid(int isuser, unsigned pid) struct sd_bus *bus; char *dpath; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); if (rc >= 0) { dpath = get_unit_dpath_by_pid(bus, pid); if (!dpath) @@ -533,16 +663,20 @@ int systemd_unit_pid_of_dpath(int isuser, const char *dpath) int rc; struct sd_bus *bus; - rc = get_bus(isuser, &bus); + rc = systemd_get_bus(isuser, &bus); return rc < 0 ? rc : unit_pid(bus, dpath); } -const char *systemd_unit_state_of_dpath(int isuser, const char *dpath) +enum SysD_State systemd_unit_state_of_dpath(int isuser, const char *dpath) { int rc; struct sd_bus *bus; - rc = get_bus(isuser, &bus); - return rc < 0 ? NULL : unit_state(bus, dpath); + rc = systemd_get_bus(isuser, &bus); + return rc < 0 ? SysD_State_INVALID : unit_state(bus, dpath); } +const char *systemd_state_name(enum SysD_State state) +{ + return sds_state_names[state]; +}