if (!u->meta.id)
u->meta.id = s;
+ unit_add_to_dbus_queue(u);
return 0;
}
return -ENOENT;
u->meta.id = s;
+
+ unit_add_to_dbus_queue(u);
return 0;
}
free(u->meta.description);
u->meta.description = s;
+
+ unit_add_to_dbus_queue(u);
return 0;
}
u->meta.in_load_queue = true;
}
+void unit_add_to_dbus_queue(Unit *u) {
+ assert(u);
+
+ if (u->meta.load_state == UNIT_STUB || u->meta.in_dbus_queue || set_isempty(u->meta.manager->subscribed))
+ return;
+
+ LIST_PREPEND(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta);
+ u->meta.in_dbus_queue = true;
+}
+
static void bidi_set_free(Unit *u, Set *s) {
Iterator i;
Unit *other;
assert(u);
+ bus_unit_send_removed_signal(u);
+
/* Detach from next 'bigger' objects */
SET_FOREACH(t, u->meta.names, i)
if (u->meta.in_load_queue)
LIST_REMOVE(Meta, load_queue, u->meta.manager->load_queue, &u->meta);
+ if (u->meta.in_dbus_queue)
+ LIST_REMOVE(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta);
+
if (u->meta.load_state == UNIT_LOADED)
if (UNIT_VTABLE(u)->done)
UNIT_VTABLE(u)->done(u);
bidi_set_free(u, u->meta.dependencies[d]);
free(u->meta.description);
- free(u->meta.load_path);
+ free(u->meta.fragment_path);
while ((t = set_steal_first(u->meta.names)))
free(t);
if ((r = ensure_merge(&u->meta.dependencies[d], other->meta.dependencies[d])) < 0)
return r;
+ unit_add_to_dbus_queue(u);
+
return 0;
}
char *t;
UnitDependency d;
Iterator i;
- char *prefix2;
+ char *p2;
+ const char *prefix2;
assert(u);
if (!prefix)
prefix = "";
- prefix2 = strappend(prefix, "\t");
- if (!prefix2)
- prefix2 = "";
+ p2 = strappend(prefix, "\t");
+ prefix2 = p2 ? p2 : prefix;
fprintf(f,
"%s→ Unit %s:\n"
prefix, yes_no(u->meta.recursive_stop),
prefix, yes_no(u->meta.stop_when_unneeded));
- if (u->meta.load_path)
- fprintf(f, "%s\tLoad Path: %s\n", prefix, u->meta.load_path);
+ if (u->meta.fragment_path)
+ fprintf(f, "%s\tFragment Path: %s\n", prefix, u->meta.fragment_path);
SET_FOREACH(t, u->meta.names, i)
fprintf(f, "%s\tName: %s\n", prefix, t);
if (u->meta.job)
job_dump(u->meta.job, f, prefix2);
- free(prefix2);
+ free(p2);
}
/* Common implementation for multiple backends */
goto fail;
u->meta.load_state = UNIT_LOADED;
+ unit_add_to_dbus_queue(u);
return 0;
fail:
u->meta.load_state = UNIT_FAILED;
+ unit_add_to_dbus_queue(u);
return r;
}
assert(u);
- if (!UNIT_VTABLE(u)->start)
- return -EBADR;
-
+ /* If this is already (being) started, then this will
+ * succeed. Note that this will even succeed if this unit is
+ * not startable by the user. This is relied on to detect when
+ * we need to wait for units and when waiting is finished. */
state = unit_active_state(u);
if (UNIT_IS_ACTIVE_OR_RELOADING(state))
return -EALREADY;
+ /* If it is stopped, but we cannot start it, then fail */
+ if (!UNIT_VTABLE(u)->start)
+ return -EBADR;
+
/* We don't suppress calls to ->start() here when we are
* already starting, to allow this request to be used as a
* "hurry up" call, for example when the unit is in some "auto
* restart" state where it waits for a holdoff timer to elapse
* before it will start again. */
+ unit_add_to_dbus_queue(u);
return UNIT_VTABLE(u)->start(u);
}
assert(u);
- if (!UNIT_VTABLE(u)->stop)
- return -EBADR;
-
state = unit_active_state(u);
if (state == UNIT_INACTIVE)
return -EALREADY;
+ if (!UNIT_VTABLE(u)->stop)
+ return -EBADR;
+
if (state == UNIT_DEACTIVATING)
return 0;
+ unit_add_to_dbus_queue(u);
return UNIT_VTABLE(u)->stop(u);
}
if (unit_active_state(u) != UNIT_ACTIVE)
return -ENOEXEC;
+ unit_add_to_dbus_queue(u);
return UNIT_VTABLE(u)->reload(u);
}
/* So we reached a different state for this
* job. Let's see if we can run it now if it
* failed previously due to EAGAIN. */
- job_schedule_run(u->meta.job);
+ job_add_to_run_queue(u->meta.job);
else {
assert(u->meta.job->state == JOB_RUNNING);
/* Maybe we finished startup and are now ready for being
* stopped because unneeded? */
unit_check_uneeded(u);
+
+ unit_add_to_dbus_queue(u);
}
int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
return r;
}
+ unit_add_to_dbus_queue(u);
return 0;
}
return 0;
}
-const char *unit_path(void) {
- char *e;
-
- if ((e = getenv("UNIT_PATH")))
- if (path_is_absolute(e))
- return e;
-
- return UNIT_PATH;
-}
-
int set_unit_path(const char *p) {
char *cwd, *c;
int r;
return -ENOMEM;
}
- if (setenv("UNIT_PATH", c, 0) < 0) {
+ if (setenv("SYSTEMD_UNIT_PATH", c, 0) < 0) {
r = -errno;
free(c);
return r;
return 0;
}
-char *unit_name_escape_path(const char *prefix, const char *path, const char *suffix) {
+char *unit_name_escape_path(const char *path, const char *suffix) {
char *r, *t;
const char *f;
- size_t a, b, c;
+ size_t a, b;
assert(path);
* escaping is hence reversible.
*/
- if (!prefix)
- prefix = "";
-
if (!suffix)
suffix = "";
- a = strlen(prefix);
- b = strlen(path);
- c = strlen(suffix);
+ a = strlen(path);
+ b = strlen(suffix);
- if (!(r = new(char, a+b*4+c+1)))
+ if (!(r = new(char, a*4+b+1)))
return NULL;
- memcpy(r, prefix, a);
-
- for (f = path, t = r+a; *f; f++) {
+ for (f = path, t = r; *f; f++) {
if (*f == '/')
*(t++) = '.';
else if (*f == '.' || *f == '\\' || !strchr(VALID_CHARS, *f)) {
*(t++) = *f;
}
- memcpy(t, suffix, c+1);
+ memcpy(t, suffix, b+1);
return r;
}