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_stop_unit[] = "StopUnit";
61 static const char sdbm_start[] = "Start";
62 static const char sdbm_stop[] = "Stop";
63 static const char sdbm_get_unit[] = "GetUnit";
64 static const char sdbm_get_unit_by_pid[] = "GetUnitByPID";
65 static const char sdbm_load_unit[] = "LoadUnit";
66 static const char sdbp_active_state[] = "ActiveState";
67 static const char sdbp_exec_main_pid[] = "ExecMainPID";
69 const char SysD_State_Inactive[] = "inactive";
70 const char SysD_State_Activating[] = "activating";
71 const char SysD_State_Active[] = "active";
72 const char SysD_State_Deactivating[] = "deactivating";
73 const char SysD_State_Reloading[] = "reloading";
74 const char SysD_State_Failed[] = "failed";
76 static struct sd_bus *sysbus;
77 static struct sd_bus *usrbus;
80 * Translate systemd errors to errno errors
82 static int seterrno(int value)
88 static int sderr2errno(int rc)
90 return rc < 0 ? seterrno(-rc) : rc;
93 static int errno2sderr(int rc)
95 return rc < 0 ? -errno : rc;
98 /* Returns in 'ret' either the system bus (if isuser==0)
99 * or the user bus (if isuser!=0).
100 * Returns 0 in case of success or -1 in case of error
102 static int get_bus(int isuser, struct sd_bus **ret)
107 bus = isuser ? usrbus : sysbus;
111 rc = sd_bus_default_user(ret);
116 rc = sd_bus_default_system(ret);
123 return sderr2errno(rc);
127 /********************************************************************
128 * routines for escaping unit names to compute dbus path of units
129 *******************************************************************/
131 * Should the char 'c' be escaped?
133 static inline int should_escape_for_path(char c)
136 return c <= (c >= 'a' ? 'z' : 'Z');
138 return c >= '0' && c <= '9';
143 * ascii char for the hexadecimal digit 'x'
145 static inline char d2h(int x)
147 return (char)(x + (x > 9 ? ('a' - 10) : '0'));
151 * escapes in 'path' of 'pathlen' the 'unit'
152 * returns 0 in case of success or -1 in case of error
154 static int unit_escape_for_path(char *path, size_t pathlen, const char *unit)
161 if (should_escape_for_path(c)) {
162 if (w + 2 >= pathlen)
165 path[w++] = d2h((c >> 4) & 15);;
166 path[w++] = d2h(c & 15);
179 return seterrno(ENAMETOOLONG);
183 /********************************************************************
184 * Routines for getting paths
185 *******************************************************************/
187 static char *get_dpath(struct sd_bus_message *msg)
193 rc = sd_bus_message_read_basic(msg, 'o', &reply);
194 rc = sderr2errno(rc);
198 result = strdup(reply);
202 sd_bus_message_unref(msg);
206 static char *get_unit_dpath(struct sd_bus *bus, const char *unit, int load)
209 struct sd_bus_message *ret = NULL;
210 sd_bus_error err = SD_BUS_ERROR_NULL;
212 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, load ? sdbm_load_unit : sdbm_get_unit, &err, &ret, "s", unit);
216 return get_dpath(ret);
218 sd_bus_message_unref(ret);
222 static char *get_unit_dpath_by_pid(struct sd_bus *bus, unsigned pid)
225 struct sd_bus_message *ret = NULL;
226 sd_bus_error err = SD_BUS_ERROR_NULL;
228 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_get_unit_by_pid, &err, &ret, "u", pid);
232 return get_dpath(ret);
234 sd_bus_message_unref(ret);
238 static int unit_pid(struct sd_bus *bus, const char *dpath)
242 sd_bus_error err = SD_BUS_ERROR_NULL;
244 rc = sd_bus_get_property_trivial(bus, sdb_destination, dpath, sdbi_service, sdbp_exec_main_pid, &err, 'u', &u);
245 return rc < 0 ? rc : (int)u;
248 static const char *unit_state(struct sd_bus *bus, const char *dpath)
253 sd_bus_error err = SD_BUS_ERROR_NULL;
255 rc = sd_bus_get_property_string(bus, sdb_destination, dpath, sdbi_unit, sdbp_active_state, &err, &st);
260 if (!strcmp(st, SysD_State_Active))
261 resu = SysD_State_Active;
262 else if (!strcmp(st, SysD_State_Reloading))
263 resu = SysD_State_Reloading;
264 else if (!strcmp(st, SysD_State_Inactive))
265 resu = SysD_State_Inactive;
266 else if (!strcmp(st, SysD_State_Failed))
267 resu = SysD_State_Failed;
268 else if (!strcmp(st, SysD_State_Activating))
269 resu = SysD_State_Activating;
270 else if (!strcmp(st, SysD_State_Deactivating))
271 resu = SysD_State_Deactivating;
281 static int unit_start(struct sd_bus *bus, const char *dpath)
284 struct sd_bus_message *ret = NULL;
285 sd_bus_error err = SD_BUS_ERROR_NULL;
287 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_start, &err, &ret, "s", "replace");
288 sd_bus_message_unref(ret);
292 static int unit_stop(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_stop, &err, &ret, "s", "replace");
299 sd_bus_message_unref(ret);
303 static int unit_start_name(struct sd_bus *bus, const char *name)
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, sdb_path, sdbi_manager, sdbm_start_unit, &err, &ret, "ss", name, "replace");
310 sd_bus_message_unref(ret);
314 static int unit_stop_name(struct sd_bus *bus, const char *name)
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, sdb_path, sdbi_manager, sdbm_stop_unit, &err, &ret, "ss", name, "replace");
321 sd_bus_message_unref(ret);
325 /********************************************************************
327 *******************************************************************/
329 static int check_snprintf_result(int rc, size_t buflen)
331 return (rc >= 0 && (size_t)rc >= buflen) ? seterrno(ENAMETOOLONG) : rc;
334 int systemd_get_units_dir(char *path, size_t pathlen, int isuser)
336 int rc = snprintf(path, pathlen, "%s/%s",
338 isuser ? "user" : "system");
340 return check_snprintf_result(rc, pathlen);
343 int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *unit, const char *uext)
345 int rc = snprintf(path, pathlen, "%s/%s/%s.%s",
347 isuser ? "user" : "system",
351 return check_snprintf_result(rc, pathlen);
354 int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *wanter, const char *unit, const char *uext)
356 int rc = snprintf(path, pathlen, "%s/%s/%s.wants/%s.%s",
358 isuser ? "user" : "system",
363 return check_snprintf_result(rc, pathlen);
366 int systemd_get_wants_target(char *path, size_t pathlen, const char *unit, const char *uext)
368 int rc = snprintf(path, pathlen, "../%s.%s", unit, uext);
370 return check_snprintf_result(rc, pathlen);
373 int systemd_daemon_reload(int isuser)
377 struct sd_bus_message *ret = NULL;
378 sd_bus_error err = SD_BUS_ERROR_NULL;
380 rc = get_bus(isuser, &bus);
382 /* TODO: asynchronous bind... */
383 /* TODO: more diagnostic... */
384 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_reload, &err, &ret, NULL);
385 sd_bus_message_unref(ret);
390 int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
393 char path[PATH_MAX + 1];
400 rc = systemd_get_units_dir(path, sizeof path - 1, isuser);
405 /* open the directory */
411 path[offset++] = '/';
413 /* read the directory */
425 if (dent->d_type == DT_REG)
427 else if (dent->d_type != DT_UNKNOWN)
430 rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
433 isfile = S_ISREG(st.st_mode);
436 /* calls the callback if is a file */
438 len = strlen(dent->d_name);
439 if (offset + len >= sizeof path) {
440 rc = seterrno(ENAMETOOLONG);
443 memcpy(&path[offset], dent->d_name, 1 + len);
444 rc = callback(closure, &path[offset], path, isuser);
453 int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
455 return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure);
458 char *systemd_unit_dpath_by_name(int isuser, const char *name, int load)
462 return get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath(bus, name, load);
465 char *systemd_unit_dpath_by_pid(int isuser, unsigned pid)
469 return get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath_by_pid(bus, pid);
472 int systemd_unit_start_dpath(int isuser, const char *dpath)
477 rc = get_bus(isuser, &bus);
478 return rc < 0 ? rc : unit_start(bus, dpath);
481 int systemd_unit_stop_dpath(int isuser, const char *dpath)
486 rc = get_bus(isuser, &bus);
487 return rc < 0 ? rc : unit_stop(bus, dpath);
490 int systemd_unit_start_name(int isuser, const char *name)
495 rc = get_bus(isuser, &bus);
497 rc = unit_start_name(bus, name);
501 int systemd_unit_stop_name(int isuser, const char *name)
506 rc = get_bus(isuser, &bus);
508 rc = unit_stop_name(bus, name);
512 int systemd_unit_stop_pid(int isuser, unsigned pid)
518 rc = get_bus(isuser, &bus);
520 dpath = get_unit_dpath_by_pid(bus, pid);
524 rc = unit_stop(bus, dpath);
531 int systemd_unit_pid_of_dpath(int isuser, const char *dpath)
536 rc = get_bus(isuser, &bus);
537 return rc < 0 ? rc : unit_pid(bus, dpath);
540 const char *systemd_unit_state_of_dpath(int isuser, const char *dpath)
545 rc = get_bus(isuser, &bus);
546 return rc < 0 ? NULL : unit_state(bus, dpath);