-
- /* Adds in the default cgroups, if they weren't specified
- * otherwise. */
-
- if (!u->manager->cgroup_hierarchy)
- return 0;
-
- if ((r = unit_add_one_default_cgroup(u, NULL)) < 0)
- return r;
-
- STRV_FOREACH(c, u->manager->default_controllers)
- unit_add_one_default_cgroup(u, *c);
-
- LIST_FOREACH(by_unit, a, u->cgroup_attributes)
- unit_add_one_default_cgroup(u, a->controller);
-
- return 0;
-}
-
-CGroupBonding* unit_get_default_cgroup(Unit *u) {
- assert(u);
-
- return cgroup_bonding_find_list(u->cgroup_bondings, SYSTEMD_CGROUP_CONTROLLER);
-}
-
-int unit_add_cgroup_attribute(Unit *u, const char *controller, const char *name, const char *value, CGroupAttributeMapCallback map_callback) {
- int r;
- char *c = NULL;
- CGroupAttribute *a;
-
- assert(u);
- assert(name);
- assert(value);
-
- if (!controller) {
- const char *dot;
-
- dot = strchr(name, '.');
- if (!dot)
- return -EINVAL;
-
- c = strndup(name, dot - name);
- if (!c)
- return -ENOMEM;
-
- controller = c;
- }
-
- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) {
- r = -EINVAL;
- goto finish;
- }
-
- a = new0(CGroupAttribute, 1);
- if (!a) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (c) {
- a->controller = c;
- c = NULL;
- } else
- a->controller = strdup(controller);
-
- a->name = strdup(name);
- a->value = strdup(value);
-
- if (!a->controller || !a->name || !a->value) {
- free(a->controller);
- free(a->name);
- free(a->value);
- free(a);
-
- return -ENOMEM;
- }
-
- a->map_callback = map_callback;
-
- LIST_PREPEND(CGroupAttribute, by_unit, u->cgroup_attributes, a);
-
- r = 0;
-
-finish:
- free(c);
- return r;
-}
-
-int unit_load_related_unit(Unit *u, const char *type, Unit **_found) {
- char *t;
- int r;
-
- assert(u);
- assert(type);
- assert(_found);
-
- if (!(t = unit_name_change_suffix(u->id, type)))
- return -ENOMEM;
-
- assert(!unit_has_name(u, t));
-
- r = manager_load_unit(u->manager, t, NULL, NULL, _found);
- free(t);
-
- assert(r < 0 || *_found != u);
-
- return r;
-}
-
-int unit_get_related_unit(Unit *u, const char *type, Unit **_found) {
- Unit *found;
- char *t;
-
- assert(u);
- assert(type);
- assert(_found);
-
- if (!(t = unit_name_change_suffix(u->id, type)))
- return -ENOMEM;
-
- assert(!unit_has_name(u, t));
-
- found = manager_get_unit(u->manager, t);
- free(t);
-
- if (!found)
- return -ENOENT;
-
- *_found = found;
- return 0;
-}
-
-static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- return unit_name_to_prefix_and_instance(u->id);
-}
-
-static char *specifier_prefix(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- return unit_name_to_prefix(u->id);
-}
-
-static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- char *p, *r;
-
- assert(u);
-
- if (!(p = unit_name_to_prefix(u->id)))
- return NULL;
-
- r = unit_name_unescape(p);
- free(p);
-
- return r;
-}
-
-static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- if (u->instance)
- return unit_name_unescape(u->instance);
-
- return strdup("");
-}
-
-static char *specifier_filename(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- if (u->instance)
- return unit_name_path_unescape(u->instance);
-
- return unit_name_to_path(u->instance);
-}
-
-static char *specifier_cgroup(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- return default_cgroup_path(u);
-}
-
-static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- char *p;
- assert(u);
-
- if (specifier == 'r')
- return strdup(u->manager->cgroup_hierarchy);
-
- if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
- return strdup("");
-
- if (streq(p, "/")) {
- free(p);
- return strdup("");
- }
-
- return p;
-}
-
-static char *specifier_runtime(char specifier, void *data, void *userdata) {
- Unit *u = userdata;
- assert(u);
-
- if (u->manager->running_as == MANAGER_USER) {
- const char *e;
-
- e = getenv("XDG_RUNTIME_DIR");
- if (e)
- return strdup(e);
- }
-
- return strdup("/run");
-}
-
-char *unit_name_printf(Unit *u, const char* format) {
-
- /*
- * This will use the passed string as format string and
- * replace the following specifiers:
- *
- * %n: the full id of the unit (foo@bar.waldo)
- * %N: the id of the unit without the suffix (foo@bar)
- * %p: the prefix (foo)
- * %i: the instance (bar)
- */
-
- const Specifier table[] = {
- { 'n', specifier_string, u->id },
- { 'N', specifier_prefix_and_instance, NULL },
- { 'p', specifier_prefix, NULL },
- { 'i', specifier_string, u->instance },
- { 0, NULL, NULL }
- };
-
- assert(u);
- assert(format);
-
- return specifier_printf(format, table, u);
-}
-
-char *unit_full_printf(Unit *u, const char *format) {
-
- /* This is similar to unit_name_printf() but also supports
- * unescaping. Also, adds a couple of additional codes:
- *
- * %c cgroup path of unit
- * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
- * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
- * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
- */
-
- const Specifier table[] = {
- { 'n', specifier_string, u->id },
- { 'N', specifier_prefix_and_instance, NULL },
- { 'p', specifier_prefix, NULL },
- { 'P', specifier_prefix_unescaped, NULL },
- { 'i', specifier_string, u->instance },
- { 'I', specifier_instance_unescaped, NULL },
- { 'f', specifier_filename, NULL },
- { 'c', specifier_cgroup, NULL },
- { 'r', specifier_cgroup_root, NULL },
- { 'R', specifier_cgroup_root, NULL },
- { 't', specifier_runtime, NULL },
- { 0, NULL, NULL }
- };
-
- assert(u);
- assert(format);
-
- return specifier_printf(format, table, u);
-}
-
-char **unit_full_printf_strv(Unit *u, char **l) {
- size_t n;
- char **r, **i, **j;
-
- /* Applies unit_full_printf to every entry in l */
-
- assert(u);
-
- n = strv_length(l);
- if (!(r = new(char*, n+1)))
- return NULL;
-
- for (i = l, j = r; *i; i++, j++)
- if (!(*j = unit_full_printf(u, *i)))
- goto fail;
-
- *j = NULL;
- return r;
-
-fail:
- for (j--; j >= r; j--)
- free(*j);
-
- free(r);
-
- return NULL;
-}
-
-int unit_watch_bus_name(Unit *u, const char *name) {
- assert(u);
- assert(name);