chiark / gitweb /
__thread --> thread_local for C11 compat
[elogind.git] / src / login / logind-inhibit.c
index f1b9cca834c95eb1b40c68646e5fc45b990d8a5c..042586d0738c9268ae54bc8ce07a04c0b3465293 100644 (file)
 
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/epoll.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
 
 #include "util.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "logind-inhibit.h"
+#include "fileio.h"
 
 Inhibitor* inhibitor_new(Manager *m, const char* id) {
         Inhibitor *i;
@@ -46,7 +45,7 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) {
                 return NULL;
         }
 
-        i->id = path_get_file_name(i->state_file);
+        i->id = basename(i->state_file);
 
         if (hashmap_put(m->inhibitors, i->id, i) < 0) {
                 free(i->state_file);
@@ -63,12 +62,13 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) {
 void inhibitor_free(Inhibitor *i) {
         assert(i);
 
-        free(i->who);
-        free(i->why);
-
         hashmap_remove(i->manager->inhibitors, i->id);
+
         inhibitor_remove_fifo(i);
 
+        free(i->who);
+        free(i->why);
+
         if (i->state_file) {
                 unlink(i->state_file);
                 free(i->state_file);
@@ -78,9 +78,9 @@ void inhibitor_free(Inhibitor *i) {
 }
 
 int inhibitor_save(Inhibitor *i) {
-        char *temp_path, *cc;
+        _cleanup_free_ char *temp_path = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
         int r;
-        FILE *f;
 
         assert(i);
 
@@ -106,23 +106,23 @@ int inhibitor_save(Inhibitor *i) {
                 (unsigned long) i->pid);
 
         if (i->who) {
+                _cleanup_free_ char *cc = NULL;
+
                 cc = cescape(i->who);
                 if (!cc)
                         r = -ENOMEM;
-                else {
+                else
                         fprintf(f, "WHO=%s\n", cc);
-                        free(cc);
-                }
         }
 
         if (i->why) {
+                _cleanup_free_ char *cc = NULL;
+
                 cc = cescape(i->why);
                 if (!cc)
                         r = -ENOMEM;
-                else {
+                else
                         fprintf(f, "WHY=%s\n", cc);
-                        free(cc);
-                }
         }
 
         if (i->fifo_path)
@@ -136,9 +136,6 @@ int inhibitor_save(Inhibitor *i) {
                 unlink(temp_path);
         }
 
-        fclose(f);
-        free(temp_path);
-
 finish:
         if (r < 0)
                 log_error("Failed to save inhibit data for %s: %s", i->id, strerror(-r));
@@ -163,7 +160,7 @@ int inhibitor_start(Inhibitor *i) {
 
         i->started = true;
 
-        manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
+        manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited" : "DelayInhibited", NULL);
 
         return 0;
 }
@@ -182,16 +179,14 @@ int inhibitor_stop(Inhibitor *i) {
 
         i->started = false;
 
-        manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
+        manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited" : "DelayInhibited", NULL);
 
         return 0;
 }
 
 int inhibitor_load(Inhibitor *i) {
-        InhibitWhat w;
-        InhibitMode mm;
-        int r;
-        char *cc,
+
+        _cleanup_free_ char
                 *what = NULL,
                 *uid = NULL,
                 *pid = NULL,
@@ -199,6 +194,11 @@ int inhibitor_load(Inhibitor *i) {
                 *why = NULL,
                 *mode = NULL;
 
+        InhibitWhat w;
+        InhibitMode mm;
+        char *cc;
+        int r;
+
         r = parse_env_file(i->state_file, NEWLINE,
                            "WHAT", &what,
                            "UID", &uid,
@@ -209,7 +209,7 @@ int inhibitor_load(Inhibitor *i) {
                            "FIFO", &i->fifo_path,
                            NULL);
         if (r < 0)
-                goto finish;
+                return r;
 
         w = what ? inhibit_what_from_string(what) : 0;
         if (w >= 0)
@@ -222,21 +222,19 @@ int inhibitor_load(Inhibitor *i) {
         if (uid) {
                 r = parse_uid(uid, &i->uid);
                 if (r < 0)
-                        goto finish;
+                        return r;
         }
 
         if (pid) {
                 r = parse_pid(pid, &i->pid);
                 if (r < 0)
-                        goto finish;
+                        return r;
         }
 
         if (who) {
                 cc = cunescape(who);
-                if (!cc) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
+                if (!cc)
+                        return -ENOMEM;
 
                 free(i->who);
                 i->who = cc;
@@ -244,10 +242,8 @@ int inhibitor_load(Inhibitor *i) {
 
         if (why) {
                 cc = cunescape(why);
-                if (!cc) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
+                if (!cc)
+                        return -ENOMEM;
 
                 free(i->why);
                 i->why = cc;
@@ -261,14 +257,20 @@ int inhibitor_load(Inhibitor *i) {
                         close_nointr_nofail(fd);
         }
 
-finish:
-        free(what);
-        free(uid);
-        free(pid);
-        free(who);
-        free(why);
+        return 0;
+}
 
-        return r;
+static int inhibitor_dispatch_fifo(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Inhibitor *i = userdata;
+
+        assert(s);
+        assert(fd == i->fifo_fd);
+        assert(i);
+
+        inhibitor_stop(i);
+        inhibitor_free(i);
+
+        return 0;
 }
 
 int inhibitor_create_fifo(Inhibitor *i) {
@@ -282,7 +284,8 @@ int inhibitor_create_fifo(Inhibitor *i) {
                 if (r < 0)
                         return r;
 
-                if (asprintf(&i->fifo_path, "/run/systemd/inhibit/%s.ref", i->id) < 0)
+                i->fifo_path = strjoin("/run/systemd/inhibit/", i->id, ".ref", NULL);
+                if (!i->fifo_path)
                         return -ENOMEM;
 
                 if (mkfifo(i->fifo_path, 0600) < 0 && errno != EEXIST)
@@ -291,22 +294,19 @@ int inhibitor_create_fifo(Inhibitor *i) {
 
         /* Open reading side */
         if (i->fifo_fd < 0) {
-                struct epoll_event ev;
-
                 i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
                 if (i->fifo_fd < 0)
                         return -errno;
+        }
 
-                r = hashmap_put(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1), i);
+        if (!i->event_source) {
+                r = sd_event_add_io(i->manager->event, i->fifo_fd, 0, inhibitor_dispatch_fifo, i, &i->event_source);
                 if (r < 0)
                         return r;
 
-                zero(ev);
-                ev.events = 0;
-                ev.data.u32 = FD_OTHER_BASE + i->fifo_fd;
-
-                if (epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_ADD, i->fifo_fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
+                if (r < 0)
+                        return r;
         }
 
         /* Open writing side */
@@ -320,9 +320,10 @@ int inhibitor_create_fifo(Inhibitor *i) {
 void inhibitor_remove_fifo(Inhibitor *i) {
         assert(i);
 
+        if (i->event_source)
+                i->event_source = sd_event_source_unref(i->event_source);
+
         if (i->fifo_fd >= 0) {
-                assert_se(hashmap_remove(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1)) == i);
-                assert_se(epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_DEL, i->fifo_fd, NULL) == 0);
                 close_nointr_nofail(i->fifo_fd);
                 i->fifo_fd = -1;
         }
@@ -341,7 +342,7 @@ InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
 
         assert(m);
 
-        HASHMAP_FOREACH(i, m->inhibitor_fds, j)
+        HASHMAP_FOREACH(i, m->inhibitors, j)
                 if (i->mode == mm)
                         what |= i->what;
 
@@ -353,9 +354,14 @@ static int pid_is_active(Manager *m, pid_t pid) {
         int r;
 
         r = manager_get_session_by_pid(m, pid, &s);
-        if (r <= 0)
+        if (r < 0)
                 return r;
 
+        /* If there's no session assigned to it, then it's globally
+         * active on all ttys */
+        if (r == 0)
+                return 1;
+
         return session_is_active(s);
 }
 
@@ -366,7 +372,8 @@ bool manager_is_inhibited(
                 dual_timestamp *since,
                 bool ignore_inactive,
                 bool ignore_uid,
-                uid_t uid) {
+                uid_t uid,
+                Inhibitor **offending) {
 
         Inhibitor *i;
         Iterator j;
@@ -376,7 +383,7 @@ bool manager_is_inhibited(
         assert(m);
         assert(w > 0 && w < _INHIBIT_WHAT_MAX);
 
-        HASHMAP_FOREACH(i, m->inhibitor_fds, j) {
+        HASHMAP_FOREACH(i, m->inhibitors, j) {
                 if (!(i->what & w))
                         continue;
 
@@ -394,6 +401,9 @@ bool manager_is_inhibited(
                         ts = i->since;
 
                 inhibited = true;
+
+                if (offending)
+                        *offending = i;
         }
 
         if (since)
@@ -403,7 +413,7 @@ bool manager_is_inhibited(
 }
 
 const char *inhibit_what_to_string(InhibitWhat w) {
-        static __thread char buffer[97];
+        static thread_local char buffer[97];
         char *p;
 
         if (w < 0 || w >= _INHIBIT_WHAT_MAX)
@@ -439,19 +449,19 @@ InhibitWhat inhibit_what_from_string(const char *s) {
         size_t l;
 
         FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
-                if (l == 8 && strncmp(w, "shutdown", l) == 0)
+                if (l == 8 && strneq(w, "shutdown", l))
                         what |= INHIBIT_SHUTDOWN;
-                else if (l == 5 && strncmp(w, "sleep", l) == 0)
+                else if (l == 5 && strneq(w, "sleep", l))
                         what |= INHIBIT_SLEEP;
-                else if (l == 4 && strncmp(w, "idle", l) == 0)
+                else if (l == 4 && strneq(w, "idle", l))
                         what |= INHIBIT_IDLE;
-                else if (l == 16 && strncmp(w, "handle-power-key", l) == 0)
+                else if (l == 16 && strneq(w, "handle-power-key", l))
                         what |= INHIBIT_HANDLE_POWER_KEY;
-                else if (l == 18 && strncmp(w, "handle-suspend-key", l) == 0)
+                else if (l == 18 && strneq(w, "handle-suspend-key", l))
                         what |= INHIBIT_HANDLE_SUSPEND_KEY;
-                else if (l == 20 && strncmp(w, "handle-hibernate-key", l) == 0)
+                else if (l == 20 && strneq(w, "handle-hibernate-key", l))
                         what |= INHIBIT_HANDLE_HIBERNATE_KEY;
-                else if (l == 17 && strncmp(w, "handle-lid-switch", l) == 0)
+                else if (l == 17 && strneq(w, "handle-lid-switch", l))
                         what |= INHIBIT_HANDLE_LID_SWITCH;
                 else
                         return _INHIBIT_WHAT_INVALID;