+ 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;
+ 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_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;
+}
+
+static int unit_stop(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_stop, &err, &ret, "s", "replace");
+ sd_bus_message_unref(ret);
+ return rc;
+}
+
+static int unit_start_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_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);