Improve use of systemd's states
[src/app-framework-main.git] / src / utils-systemd.c
index 830fec6..0c22810 100644 (file)
@@ -1,5 +1,5 @@
 /*
- Copyright 2017 IoT.bzh
+ Copyright (C) 2015-2020 IoT.bzh
 
  author: José Bollo <jose.bollo@iot.bzh>
 
@@ -34,6 +34,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)
@@ -57,8 +58,10 @@ static const char sdbi_unit[] = "org.freedesktop.systemd1.Unit";
 static const char sdbi_service[] = "org.freedesktop.systemd1.Service";
 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 +69,15 @@ 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 struct sd_bus *sysbus;
 static struct sd_bus *usrbus;
@@ -95,11 +101,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 +130,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,34 +260,46 @@ 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;
@@ -289,6 +316,17 @@ static int unit_start(struct sd_bus *bus, const char *dpath)
        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");
+       sd_bus_message_unref(ret);
+       return rc;
+}
+
 static int unit_stop(struct sd_bus *bus, const char *dpath)
 {
        int rc;
@@ -311,6 +349,17 @@ static int unit_start_name(struct sd_bus *bus, const char *name)
        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");
+       sd_bus_message_unref(ret);
+       return rc;
+}
+
 static int unit_stop_name(struct sd_bus *bus, const char *name)
 {
        int rc;
@@ -377,7 +426,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 +508,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 +523,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 +550,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 +584,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 +602,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];
+}