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;
100 /* Returns in 'ret' either the system bus (if isuser==0)
101 * or the user bus (if isuser!=0).
102 * Returns 0 in case of success or -1 in case of error
104 static int get_bus(int isuser, struct sd_bus **ret)
109 bus = isuser ? usrbus : sysbus;
113 rc = sd_bus_default_user(ret);
118 rc = sd_bus_default_system(ret);
125 return sderr2errno(rc);
129 /********************************************************************
130 * routines for escaping unit names to compute dbus path of units
131 *******************************************************************/
133 * Should the char 'c' be escaped?
135 static inline int should_escape_for_path(char c)
138 return c <= (c >= 'a' ? 'z' : 'Z');
140 return c >= '0' && c <= '9';
145 * ascii char for the hexadecimal digit 'x'
147 static inline char d2h(int x)
149 return (char)(x + (x > 9 ? ('a' - 10) : '0'));
153 * escapes in 'path' of 'pathlen' the 'unit'
154 * returns 0 in case of success or -1 in case of error
156 static int unit_escape_for_path(char *path, size_t pathlen, const char *unit)
163 if (should_escape_for_path(c)) {
164 if (w + 2 >= pathlen)
167 path[w++] = d2h((c >> 4) & 15);;
168 path[w++] = d2h(c & 15);
181 return seterrno(ENAMETOOLONG);
185 /********************************************************************
186 * Routines for getting paths
187 *******************************************************************/
189 static char *get_dpath(struct sd_bus_message *msg)
195 rc = sd_bus_message_read_basic(msg, 'o', &reply);
196 rc = sderr2errno(rc);
200 result = strdup(reply);
204 sd_bus_message_unref(msg);
208 static char *get_unit_dpath(struct sd_bus *bus, const char *unit, int load)
211 struct sd_bus_message *ret = NULL;
212 sd_bus_error err = SD_BUS_ERROR_NULL;
214 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, load ? sdbm_load_unit : sdbm_get_unit, &err, &ret, "s", unit);
218 return get_dpath(ret);
220 sd_bus_message_unref(ret);
224 static char *get_unit_dpath_by_pid(struct sd_bus *bus, unsigned pid)
227 struct sd_bus_message *ret = NULL;
228 sd_bus_error err = SD_BUS_ERROR_NULL;
230 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_get_unit_by_pid, &err, &ret, "u", pid);
234 return get_dpath(ret);
236 sd_bus_message_unref(ret);
240 static int unit_pid(struct sd_bus *bus, const char *dpath)
244 sd_bus_error err = SD_BUS_ERROR_NULL;
246 rc = sd_bus_get_property_trivial(bus, sdb_destination, dpath, sdbi_service, sdbp_exec_main_pid, &err, 'u', &u);
247 return rc < 0 ? rc : (int)u;
250 static const char *unit_state(struct sd_bus *bus, const char *dpath)
255 sd_bus_error err = SD_BUS_ERROR_NULL;
257 rc = sd_bus_get_property_string(bus, sdb_destination, dpath, sdbi_unit, sdbp_active_state, &err, &st);
262 if (!strcmp(st, SysD_State_Active))
263 resu = SysD_State_Active;
264 else if (!strcmp(st, SysD_State_Reloading))
265 resu = SysD_State_Reloading;
266 else if (!strcmp(st, SysD_State_Inactive))
267 resu = SysD_State_Inactive;
268 else if (!strcmp(st, SysD_State_Failed))
269 resu = SysD_State_Failed;
270 else if (!strcmp(st, SysD_State_Activating))
271 resu = SysD_State_Activating;
272 else if (!strcmp(st, SysD_State_Deactivating))
273 resu = SysD_State_Deactivating;
283 static int unit_start(struct sd_bus *bus, const char *dpath)
286 struct sd_bus_message *ret = NULL;
287 sd_bus_error err = SD_BUS_ERROR_NULL;
289 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_start, &err, &ret, "s", "replace");
290 sd_bus_message_unref(ret);
294 static int unit_restart(struct sd_bus *bus, const char *dpath)
297 struct sd_bus_message *ret = NULL;
298 sd_bus_error err = SD_BUS_ERROR_NULL;
300 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_restart, &err, &ret, "s", "replace");
301 sd_bus_message_unref(ret);
305 static int unit_stop(struct sd_bus *bus, const char *dpath)
308 struct sd_bus_message *ret = NULL;
309 sd_bus_error err = SD_BUS_ERROR_NULL;
311 rc = sd_bus_call_method(bus, sdb_destination, dpath, sdbi_unit, sdbm_stop, &err, &ret, "s", "replace");
312 sd_bus_message_unref(ret);
316 static int unit_start_name(struct sd_bus *bus, const char *name)
319 struct sd_bus_message *ret = NULL;
320 sd_bus_error err = SD_BUS_ERROR_NULL;
322 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_start_unit, &err, &ret, "ss", name, "replace");
323 sd_bus_message_unref(ret);
327 static int unit_restart_name(struct sd_bus *bus, const char *name)
330 struct sd_bus_message *ret = NULL;
331 sd_bus_error err = SD_BUS_ERROR_NULL;
333 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_restart_unit, &err, &ret, "ss", name, "replace");
334 sd_bus_message_unref(ret);
338 static int unit_stop_name(struct sd_bus *bus, const char *name)
341 struct sd_bus_message *ret = NULL;
342 sd_bus_error err = SD_BUS_ERROR_NULL;
344 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_stop_unit, &err, &ret, "ss", name, "replace");
345 sd_bus_message_unref(ret);
349 /********************************************************************
351 *******************************************************************/
353 static int check_snprintf_result(int rc, size_t buflen)
355 return (rc >= 0 && (size_t)rc >= buflen) ? seterrno(ENAMETOOLONG) : rc;
358 int systemd_get_units_dir(char *path, size_t pathlen, int isuser)
360 int rc = snprintf(path, pathlen, "%s/%s",
362 isuser ? "user" : "system");
364 return check_snprintf_result(rc, pathlen);
367 int systemd_get_unit_path(char *path, size_t pathlen, int isuser, const char *unit, const char *uext)
369 int rc = snprintf(path, pathlen, "%s/%s/%s.%s",
371 isuser ? "user" : "system",
375 return check_snprintf_result(rc, pathlen);
378 int systemd_get_wants_path(char *path, size_t pathlen, int isuser, const char *wanter, const char *unit, const char *uext)
380 int rc = snprintf(path, pathlen, "%s/%s/%s.wants/%s.%s",
382 isuser ? "user" : "system",
387 return check_snprintf_result(rc, pathlen);
390 int systemd_get_wants_target(char *path, size_t pathlen, const char *unit, const char *uext)
392 int rc = snprintf(path, pathlen, "../%s.%s", unit, uext);
394 return check_snprintf_result(rc, pathlen);
397 int systemd_daemon_reload(int isuser)
401 struct sd_bus_message *ret = NULL;
402 sd_bus_error err = SD_BUS_ERROR_NULL;
404 rc = get_bus(isuser, &bus);
406 /* TODO: asynchronous bind... */
407 /* TODO: more diagnostic... */
408 rc = sd_bus_call_method(bus, sdb_destination, sdb_path, sdbi_manager, sdbm_reload, &err, &ret, NULL);
409 sd_bus_message_unref(ret);
414 int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
417 char path[PATH_MAX + 1];
424 rc = systemd_get_units_dir(path, sizeof path - 1, isuser);
429 /* open the directory */
435 path[offset++] = '/';
437 /* read the directory */
449 if (dent->d_type == DT_REG)
451 else if (dent->d_type != DT_UNKNOWN)
454 rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
457 isfile = S_ISREG(st.st_mode);
460 /* calls the callback if is a file */
462 len = strlen(dent->d_name);
463 if (offset + len >= sizeof path) {
464 rc = seterrno(ENAMETOOLONG);
467 memcpy(&path[offset], dent->d_name, 1 + len);
468 rc = callback(closure, &path[offset], path, isuser);
477 int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
479 return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure);
482 char *systemd_unit_dpath_by_name(int isuser, const char *name, int load)
486 return get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath(bus, name, load);
489 char *systemd_unit_dpath_by_pid(int isuser, unsigned pid)
493 return get_bus(isuser, &bus) < 0 ? NULL : get_unit_dpath_by_pid(bus, pid);
496 int systemd_unit_start_dpath(int isuser, const char *dpath)
501 rc = get_bus(isuser, &bus);
502 return rc < 0 ? rc : unit_start(bus, dpath);
505 int systemd_unit_restart_dpath(int isuser, const char *dpath)
510 rc = get_bus(isuser, &bus);
511 return rc < 0 ? rc : unit_restart(bus, dpath);
514 int systemd_unit_stop_dpath(int isuser, const char *dpath)
519 rc = get_bus(isuser, &bus);
520 return rc < 0 ? rc : unit_stop(bus, dpath);
523 int systemd_unit_start_name(int isuser, const char *name)
528 rc = get_bus(isuser, &bus);
530 rc = unit_start_name(bus, name);
534 int systemd_unit_restart_name(int isuser, const char *name)
539 rc = get_bus(isuser, &bus);
541 rc = unit_restart_name(bus, name);
545 int systemd_unit_stop_name(int isuser, const char *name)
550 rc = get_bus(isuser, &bus);
552 rc = unit_stop_name(bus, name);
556 int systemd_unit_stop_pid(int isuser, unsigned pid)
562 rc = get_bus(isuser, &bus);
564 dpath = get_unit_dpath_by_pid(bus, pid);
568 rc = unit_stop(bus, dpath);
575 int systemd_unit_pid_of_dpath(int isuser, const char *dpath)
580 rc = get_bus(isuser, &bus);
581 return rc < 0 ? rc : unit_pid(bus, dpath);
584 const char *systemd_unit_state_of_dpath(int isuser, const char *dpath)
589 rc = get_bus(isuser, &bus);
590 return rc < 0 ? NULL : unit_state(bus, dpath);