4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
27 #include <sys/types.h>
31 # include <systemd/sd-bus.h>
32 # include <systemd/sd-bus-protocol.h>
35 struct sd_bus_message;
36 typedef struct { const char *name; const char *message; } sd_bus_error;
37 # define sd_bus_default_user(p) ((*(p)=NULL),(-ENOTSUP))
38 # define sd_bus_default_system(p) ((*(p)=NULL),(-ENOTSUP))
39 # define sd_bus_call_method(...) (-ENOTSUP)
40 # define SD_BUS_ERROR_NULL {NULL,NULL}
41 # define sd_bus_message_read_basic(...) (-ENOTSUP)
42 # define sd_bus_message_unref(...) (NULL)
43 # define sd_bus_get_property_string(...) (-ENOTSUP)
44 # define sd_bus_get_property_trivial(...) (-ENOTSUP)
47 #include "utils-systemd.h"
49 #if !defined(SYSTEMD_UNITS_ROOT)
50 # define SYSTEMD_UNITS_ROOT "/usr/local/lib/systemd"
53 static const char sdb_path[] = "/org/freedesktop/systemd1";
54 static const char sdb_destination[] = "org.freedesktop.systemd1";
55 static const char sdbi_manager[] = "org.freedesktop.systemd1.Manager";
56 static const char sdbi_unit[] = "org.freedesktop.systemd1.Unit";
57 static const char sdbi_service[] = "org.freedesktop.systemd1.Service";
58 static const char sdbm_reload[] = "Reload";
59 static const char sdbm_start_unit[] = "StartUnit";
60 static const char sdbm_restart_unit[] = "RestartUnit";
61 static const char sdbm_stop_unit[] = "StopUnit";
62 static const char sdbm_start[] = "Start";
63 static const char sdbm_restart[] = "Restart";
64 static const char sdbm_stop[] = "Stop";
65 static const char sdbm_get_unit[] = "GetUnit";
66 static const char sdbm_get_unit_by_pid[] = "GetUnitByPID";
67 static const char sdbm_load_unit[] = "LoadUnit";
68 static const char sdbp_active_state[] = "ActiveState";
69 static const char sdbp_exec_main_pid[] = "ExecMainPID";
71 const char SysD_State_Inactive[] = "inactive";
72 const char SysD_State_Activating[] = "activating";
73 const char SysD_State_Active[] = "active";
74 const char SysD_State_Deactivating[] = "deactivating";
75 const char SysD_State_Reloading[] = "reloading";
76 const char SysD_State_Failed[] = "failed";
78 static struct sd_bus *sysbus;
79 static struct sd_bus *usrbus;
82 * Translate systemd errors to errno errors
84 static int seterrno(int value)
90 static int sderr2errno(int rc)
92 return rc < 0 ? seterrno(-rc) : rc;
95 static int errno2sderr(int rc)
97 return rc < 0 ? -errno : rc;
101 * Returns in 'ret' either the system bus (if isuser==0)
102 * or the user bus (if isuser!=0).
103 * Returns 0 in case of success or -1 in case of error
105 int systemd_get_bus(int isuser, struct sd_bus **ret)
110 bus = isuser ? usrbus : sysbus;
114 rc = sd_bus_default_user(ret);
119 rc = sd_bus_default_system(ret);
126 return sderr2errno(rc);
129 void systemd_set_bus(int isuser, struct sd_bus *bus)
131 struct sd_bus **target = isuser ? &usrbus : &sysbus;
133 sd_bus_unref(*target);
138 /********************************************************************
139 * routines for escaping unit names to compute dbus path of units
140 *******************************************************************/
142 * Should the char 'c' be escaped?
144 static inline int should_escape_for_path(char c)
147 return c <= (c >= 'a' ? 'z' : 'Z');
149 return c >= '0' && c <= '9';
154 * ascii char for the hexadecimal digit 'x'
156 static inline char d2h(int x)
158 return (char)(x + (x > 9 ? ('a' - 10) : '0'));
162 * escapes in 'path' of 'pathlen' the 'unit'
163 * returns 0 in case of success or -1 in case of error
165 static int unit_escape_for_path(char *path, size_t pathlen, const char *unit)
172 if (should_escape_for_path(c)) {
173 if (w + 2 >= pathlen)
176 path[w++] = d2h((c >> 4) & 15);;
177 path[w++] = d2h(c & 15);
190 return seterrno(ENAMETOOLONG);
194 /********************************************************************
195 * Routines for getting paths
196 *******************************************************************/
198 static char *get_dpath(struct sd_bus_message *msg)
204 rc = sd_bus_message_read_basic(msg, 'o', &reply);
205 rc = sderr2errno(rc);
209 result = strdup(reply);
213 sd_bus_message_unref(msg);
217 static char *get_unit_dpath(struct sd_bus *bus, const char *unit, int load)
220 struct sd_bus_message *ret = NULL;
221 sd_bus_error err = SD_BUS_ERROR_NULL;
223 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, load ? sdbm_load_unit : sdbm_get_unit, &err, &ret, "s", unit);
227 return get_dpath(ret);
229 sd_bus_message_unref(ret);
233 static char *get_unit_dpath_by_pid(struct sd_bus *bus, unsigned pid)
236 struct sd_bus_message *ret = NULL;
237 sd_bus_error err = SD_BUS_ERROR_NULL;
239 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_get_unit_by_pid, &err, &ret, "u", pid);
243 return get_dpath(ret);
245 sd_bus_message_unref(ret);
249 static int unit_pid(struct sd_bus *bus, const char *dpath)
253 sd_bus_error err = SD_BUS_ERROR_NULL;
255 rc = sd_bus_get_property_trivial(bus, sdb_destination, dpath, sdbi_service, sdbp_exec_main_pid, &err, 'u', &u);
256 return rc < 0 ? rc : (int)u;
259 static const char *unit_state(struct sd_bus *bus, const char *dpath)
264 sd_bus_error err = SD_BUS_ERROR_NULL;
266 rc = sd_bus_get_property_string(bus, sdb_destination, dpath, sdbi_unit, sdbp_active_state, &err, &st);
271 if (!strcmp(st, SysD_State_Active))
272 resu = SysD_State_Active;
273 else if (!strcmp(st, SysD_State_Reloading))
274 resu = SysD_State_Reloading;
275 else if (!strcmp(st, SysD_State_Inactive))
276 resu = SysD_State_Inactive;
277 else if (!strcmp(st, SysD_State_Failed))
278 resu = SysD_State_Failed;
279 else if (!strcmp(st, SysD_State_Activating))
280 resu = SysD_State_Activating;
281 else if (!strcmp(st, SysD_State_Deactivating))
282 resu = SysD_State_Deactivating;
292 static int unit_start(struct sd_bus *bus, const char *dpath)
295 struct sd_bus_message *ret = NULL;
296 sd_bus_error err = SD_BUS_ERROR_NULL;
298 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_start, &err, &ret, "s", "replace");
299 sd_bus_message_unref(ret);
303 static int unit_restart(struct sd_bus *bus, const char *dpath)
306 struct sd_bus_message *ret = NULL;
307 sd_bus_error err = SD_BUS_ERROR_NULL;
309 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_restart, &err, &ret, "s", "replace");
310 sd_bus_message_unref(ret);
314 static int unit_stop(struct sd_bus *bus, const char *dpath)
317 struct sd_bus_message *ret = NULL;
318 sd_bus_error err = SD_BUS_ERROR_NULL;
320 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_stop, &err, &ret, "s", "replace");
321 sd_bus_message_unref(ret);
325 static int unit_start_name(struct sd_bus *bus, const char *name)
328 struct sd_bus_message *ret = NULL;
329 sd_bus_error err = SD_BUS_ERROR_NULL;
331 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_start_unit, &err, &ret, "ss", name, "replace");
332 sd_bus_message_unref(ret);
336 static int unit_restart_name(struct sd_bus *bus, const char *name)
339 struct sd_bus_message *ret = NULL;
340 sd_bus_error err = SD_BUS_ERROR_NULL;
342 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_restart_unit, &err, &ret, "ss", name, "replace");
343 sd_bus_message_unref(ret);
347 static int unit_stop_name(struct sd_bus *bus, const char *name)
350 struct sd_bus_message *ret = NULL;
351 sd_bus_error err = SD_BUS_ERROR_NULL;
353 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_stop_unit, &err, &ret, "ss", name, "replace");
354 sd_bus_message_unref(ret);
358 /********************************************************************
360 *******************************************************************/
362 static int check_snprintf_result(int rc, size_t buflen)
364 return (rc >= 0 && (size_t)rc >= buflen) ? seterrno(ENAMETOOLONG) : rc;
367 int systemd_get_units_dir(char *path, size_t pathlen, int isuser)
369 int rc = snprintf(path, pathlen, "%s/%s",
371 isuser ? "user" : "system");
373 return check_snprintf_result(rc, pathlen);
376 int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *unit, const char *uext)
378 int rc = snprintf(path, pathlen, "%s/%s/%s.%s",
380 isuser ? "user" : "system",
384 return check_snprintf_result(rc, pathlen);
387 int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *wanter, const char *unit, const char *uext)
389 int rc = snprintf(path, pathlen, "%s/%s/%s.wants/%s.%s",
391 isuser ? "user" : "system",
396 return check_snprintf_result(rc, pathlen);
399 int systemd_get_wants_target(char *path, size_t pathlen, const char *unit, const char *uext)
401 int rc = snprintf(path, pathlen, "../%s.%s", unit, uext);
403 return check_snprintf_result(rc, pathlen);
406 int systemd_daemon_reload(int isuser)
410 struct sd_bus_message *ret = NULL;
411 sd_bus_error err = SD_BUS_ERROR_NULL;
413 rc = systemd_get_bus(isuser, &bus);
415 /* TODO: asynchronous bind... */
416 /* TODO: more diagnostic... */
417 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_reload, &err, &ret, NULL);
418 sd_bus_message_unref(ret);
423 int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
426 char path[PATH_MAX + 1];
433 rc = systemd_get_units_dir(path, sizeof path - 1, isuser);
438 /* open the directory */
444 path[offset++] = '/';
446 /* read the directory */
458 if (dent->d_type == DT_REG)
460 else if (dent->d_type != DT_UNKNOWN)
463 rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
466 isfile = S_ISREG(st.st_mode);
469 /* calls the callback if is a file */
471 len = strlen(dent->d_name);
472 if (offset + len >= sizeof path) {
473 rc = seterrno(ENAMETOOLONG);
476 memcpy(&path[offset], dent->d_name, 1 + len);
477 rc = callback(closure, &path[offset], path, isuser);
486 int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
488 return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure);
491 char *systemd_unit_dpath_by_name(int isuser, const char *name, int load)
495 return systemd_get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath(bus, name, load);
498 char *systemd_unit_dpath_by_pid(int isuser, unsigned pid)
502 return systemd_get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath_by_pid(bus, pid);
505 int systemd_unit_start_dpath(int isuser, const char *dpath)
510 rc = systemd_get_bus(isuser, &bus);
511 return rc < 0 ? rc : unit_start(bus, dpath);
514 int systemd_unit_restart_dpath(int isuser, const char *dpath)
519 rc = systemd_get_bus(isuser, &bus);
520 return rc < 0 ? rc : unit_restart(bus, dpath);
523 int systemd_unit_stop_dpath(int isuser, const char *dpath)
528 rc = systemd_get_bus(isuser, &bus);
529 return rc < 0 ? rc : unit_stop(bus, dpath);
532 int systemd_unit_start_name(int isuser, const char *name)
537 rc = systemd_get_bus(isuser, &bus);
539 rc = unit_start_name(bus, name);
543 int systemd_unit_restart_name(int isuser, const char *name)
548 rc = systemd_get_bus(isuser, &bus);
550 rc = unit_restart_name(bus, name);
554 int systemd_unit_stop_name(int isuser, const char *name)
559 rc = systemd_get_bus(isuser, &bus);
561 rc = unit_stop_name(bus, name);
565 int systemd_unit_stop_pid(int isuser, unsigned pid)
571 rc = systemd_get_bus(isuser, &bus);
573 dpath = get_unit_dpath_by_pid(bus, pid);
577 rc = unit_stop(bus, dpath);
584 int systemd_unit_pid_of_dpath(int isuser, const char *dpath)
589 rc = systemd_get_bus(isuser, &bus);
590 return rc < 0 ? rc : unit_pid(bus, dpath);
593 const char *systemd_unit_state_of_dpath(int isuser, const char *dpath)
598 rc = systemd_get_bus(isuser, &bus);
599 return rc < 0 ? NULL : unit_state(bus, dpath);