chiark / gitweb /
yay, we can start socket units
[elogind.git] / unit.c
diff --git a/unit.c b/unit.c
index 15401e24fe0660cd3540b146e00b84ffcf439715..e6e5574312161668f8b7133010cd815bc2267d85 100644 (file)
--- a/unit.c
+++ b/unit.c
@@ -6,6 +6,8 @@
 #include <sys/epoll.h>
 #include <sys/timerfd.h>
 #include <sys/poll.h>
 #include <sys/epoll.h>
 #include <sys/timerfd.h>
 #include <sys/poll.h>
+#include <stdlib.h>
+#include <unistd.h>
 
 #include "set.h"
 #include "unit.h"
 
 #include "set.h"
 #include "unit.h"
@@ -206,6 +208,7 @@ void unit_free(Unit *u) {
                 bidi_set_free(u, u->meta.dependencies[d]);
 
         free(u->meta.description);
                 bidi_set_free(u, u->meta.dependencies[d]);
 
         free(u->meta.description);
+        free(u->meta.load_path);
 
         while ((t = set_steal_first(u->meta.names)))
                 free(t);
 
         while ((t = set_steal_first(u->meta.names)))
                 free(t);
@@ -338,6 +341,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, load_state_table[u->meta.load_state],
                 prefix, active_state_table[unit_active_state(u)]);
 
                 prefix, load_state_table[u->meta.load_state],
                 prefix, active_state_table[unit_active_state(u)]);
 
+        if (u->meta.load_path)
+                fprintf(f, "%s\tLoad Path: %s\n", prefix, u->meta.load_path);
+
         SET_FOREACH(t, u->meta.names, i)
                 fprintf(f, "%s\tName: %s\n", prefix, t);
 
         SET_FOREACH(t, u->meta.names, i)
                 fprintf(f, "%s\tName: %s\n", prefix, t);
 
@@ -621,33 +627,44 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
                 retroactively_stop_dependencies(u);
 }
 
                 retroactively_stop_dependencies(u);
 }
 
-int unit_watch_fd(Unit *u, int fd, uint32_t events) {
+int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
         struct epoll_event ev;
 
         assert(u);
         assert(fd >= 0);
         struct epoll_event ev;
 
         assert(u);
         assert(fd >= 0);
+        assert(w);
+        assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->unit == u));
 
         zero(ev);
 
         zero(ev);
-        ev.data.fd = fd;
-        ev.data.ptr = u;
-        ev.data.u32 = MANAGER_FD;
+        ev.data.ptr = w;
         ev.events = events;
 
         ev.events = events;
 
-        if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) >= 0)
-                return 0;
+        if (epoll_ctl(u->meta.manager->epoll_fd,
+                      w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
+                      fd,
+                      &ev) < 0)
+                return -errno;
 
 
-        if (errno == EEXIST)
-                if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_MOD, fd, &ev) >= 0)
-                        return 0;
+        w->fd = fd;
+        w->type = WATCH_FD;
+        w->unit = u;
 
 
-        return -errno;
+        return 0;
 }
 
 }
 
-void unit_unwatch_fd(Unit *u, int fd) {
+void unit_unwatch_fd(Unit *u, Watch *w) {
         assert(u);
         assert(u);
-        assert(fd >= 0);
+        assert(w);
+
+        if (w->type == WATCH_INVALID)
+                return;
 
 
-        assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, fd, NULL) >= 0 || errno == ENOENT);
+        assert(w->type == WATCH_FD && w->unit == u);
+        assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
+
+        w->fd = -1;
+        w->type = WATCH_INVALID;
+        w->unit = NULL;
 }
 
 int unit_watch_pid(Unit *u, pid_t pid) {
 }
 
 int unit_watch_pid(Unit *u, pid_t pid) {
@@ -664,25 +681,22 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
         hashmap_remove(u->meta.manager->watch_pids, UINT32_TO_PTR(pid));
 }
 
         hashmap_remove(u->meta.manager->watch_pids, UINT32_TO_PTR(pid));
 }
 
-int unit_watch_timer(Unit *u, usec_t delay, int *id) {
-        struct epoll_event ev;
-        int fd;
+int unit_watch_timer(Unit *u, usec_t delay, Watch *w) {
         struct itimerspec its;
         struct itimerspec its;
-        int flags;
+        int flags, fd;
         bool ours;
 
         assert(u);
         bool ours;
 
         assert(u);
-        assert(id);
+        assert(w);
+        assert(w->type == WATCH_INVALID || (w->type == WATCH_TIMER && w->unit == u));
 
         /* This will try to reuse the old timer if there is one */
 
 
         /* This will try to reuse the old timer if there is one */
 
-        if (*id >= 0) {
+        if (w->type == WATCH_TIMER) {
                 ours = false;
                 ours = false;
-                fd = *id;
-
+                fd = w->fd;
         } else {
                 ours = true;
         } else {
                 ours = true;
-
                 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
                         return -errno;
         }
                 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
                         return -errno;
         }
@@ -705,16 +719,21 @@ int unit_watch_timer(Unit *u, usec_t delay, int *id) {
         if (timerfd_settime(fd, flags, &its, NULL) < 0)
                 goto fail;
 
         if (timerfd_settime(fd, flags, &its, NULL) < 0)
                 goto fail;
 
-        zero(ev);
-        ev.data.fd = fd;
-        ev.data.ptr = u;
-        ev.data.u32 = MANAGER_TIMER;
-        ev.events = POLLIN;
+        if (w->type == WATCH_INVALID) {
+                struct epoll_event ev;
 
 
-        if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
-                goto fail;
+                zero(ev);
+                ev.data.ptr = w;
+                ev.events = POLLIN;
+
+                if (epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
+                        goto fail;
+        }
+
+        w->fd = fd;
+        w->type = WATCH_TIMER;
+        w->unit = u;
 
 
-        *id = fd;
         return 0;
 
 fail:
         return 0;
 
 fail:
@@ -724,16 +743,21 @@ fail:
         return -errno;
 }
 
         return -errno;
 }
 
-void unit_unwatch_timer(Unit *u, int *id) {
+void unit_unwatch_timer(Unit *u, Watch *w) {
         assert(u);
         assert(u);
-        assert(id);
+        assert(w);
 
 
-        if (*id < 0)
+        if (w->type == WATCH_INVALID)
                 return;
 
                 return;
 
-        assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, *id, NULL) >= 0);
-        assert_se(close_nointr(*id) == 0);
-        *id = -1;
+        assert(w->type == WATCH_TIMER && w->unit == u);
+
+        assert_se(epoll_ctl(u->meta.manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
+        assert_se(close_nointr(w->fd) == 0);
+
+        w->fd = -1;
+        w->type = WATCH_INVALID;
+        w->unit = NULL;
 }
 
 bool unit_job_is_applicable(Unit *u, JobType j) {
 }
 
 bool unit_job_is_applicable(Unit *u, JobType j) {
@@ -805,3 +829,42 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other) {
 
         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;
+
+        /* This is mostly for debug purposes */
+
+        if (path_is_absolute(p)) {
+                if (!(c = strdup(p)))
+                        return -ENOMEM;
+        } else {
+                if (!(cwd = get_current_dir_name()))
+                        return -errno;
+
+                r = asprintf(&c, "%s/%s", cwd, p);
+                free(cwd);
+
+                if (r < 0)
+                        return -ENOMEM;
+        }
+
+        if (setenv("UNIT_PATH", c, 0) < 0) {
+                r = -errno;
+                free(c);
+                return r;
+        }
+
+        return 0;
+}