chiark / gitweb /
loginctl: don't show [UACCESS] info in device tree
[elogind.git] / src / login / logind-inhibit.c
index 2f7a758e7cf2bba48efe87b6b500eee00f84b483..f1b9cca834c95eb1b40c68646e5fc45b990d8a5c 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "util.h"
 #include "mkdir.h"
-
+#include "path-util.h"
 #include "logind-inhibit.h"
 
 Inhibitor* inhibitor_new(Manager *m, const char* id) {
@@ -46,7 +46,7 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) {
                 return NULL;
         }
 
-        i->id = file_name_from_path(i->state_file);
+        i->id = path_get_file_name(i->state_file);
 
         if (hashmap_put(m->inhibitors, i->id, i) < 0) {
                 free(i->state_file);
@@ -84,7 +84,7 @@ int inhibitor_save(Inhibitor *i) {
 
         assert(i);
 
-        r = safe_mkdir("/run/systemd/inhibit", 0755, 0, 0);
+        r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
         if (r < 0)
                 goto finish;
 
@@ -97,9 +97,11 @@ int inhibitor_save(Inhibitor *i) {
         fprintf(f,
                 "# This is private data. Do not parse.\n"
                 "WHAT=%s\n"
+                "MODE=%s\n"
                 "UID=%lu\n"
                 "PID=%lu\n",
                 inhibit_what_to_string(i->what),
+                inhibit_mode_to_string(i->mode),
                 (unsigned long) i->uid,
                 (unsigned long) i->pid);
 
@@ -150,15 +152,18 @@ int inhibitor_start(Inhibitor *i) {
         if (i->started)
                 return 0;
 
-        log_debug("Inhibitor %s (%s) pid=%lu uid=%lu started.",
+        dual_timestamp_get(&i->since);
+
+        log_debug("Inhibitor %s (%s) pid=%lu uid=%lu mode=%s started.",
                   strna(i->who), strna(i->why),
-                  (unsigned long) i->pid, (unsigned long) i->uid);
+                  (unsigned long) i->pid, (unsigned long) i->uid,
+                  inhibit_mode_to_string(i->mode));
 
         inhibitor_save(i);
 
         i->started = true;
 
-        manager_send_changed(i->manager, "Inhibited\0");
+        manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
 
         return 0;
 }
@@ -167,29 +172,32 @@ int inhibitor_stop(Inhibitor *i) {
         assert(i);
 
         if (i->started)
-                log_debug("Inhibitor %s (%s) pid=%lu uid=%lu stopped.",
+                log_debug("Inhibitor %s (%s) pid=%lu uid=%lu mode=%s stopped.",
                           strna(i->who), strna(i->why),
-                          (unsigned long) i->pid, (unsigned long) i->uid);
+                          (unsigned long) i->pid, (unsigned long) i->uid,
+                          inhibit_mode_to_string(i->mode));
 
         if (i->state_file)
                 unlink(i->state_file);
 
         i->started = false;
 
-        manager_send_changed(i->manager, "Inhibited\0");
+        manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
 
         return 0;
 }
 
 int inhibitor_load(Inhibitor *i) {
         InhibitWhat w;
+        InhibitMode mm;
         int r;
         char *cc,
                 *what = NULL,
                 *uid = NULL,
                 *pid = NULL,
                 *who = NULL,
-                *why = NULL;
+                *why = NULL,
+                *mode = NULL;
 
         r = parse_env_file(i->state_file, NEWLINE,
                            "WHAT", &what,
@@ -197,17 +205,31 @@ int inhibitor_load(Inhibitor *i) {
                            "PID", &pid,
                            "WHO", &who,
                            "WHY", &why,
+                           "MODE", &mode,
                            "FIFO", &i->fifo_path,
                            NULL);
         if (r < 0)
                 goto finish;
 
-        w = inhibit_what_from_string(what);
+        w = what ? inhibit_what_from_string(what) : 0;
         if (w >= 0)
                 i->what = w;
 
-        parse_uid(uid, &i->uid);
-        parse_pid(pid, &i->pid);
+        mm = mode ? inhibit_mode_from_string(mode) : INHIBIT_BLOCK;
+        if  (mm >= 0)
+                i->mode = mm;
+
+        if (uid) {
+                r = parse_uid(uid, &i->uid);
+                if (r < 0)
+                        goto finish;
+        }
+
+        if (pid) {
+                r = parse_pid(pid, &i->pid);
+                if (r < 0)
+                        goto finish;
+        }
 
         if (who) {
                 cc = cunescape(who);
@@ -256,7 +278,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
 
         /* Create FIFO */
         if (!i->fifo_path) {
-                r = safe_mkdir("/run/systemd/inhibit", 0755, 0, 0);
+                r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
                 if (r < 0)
                         return r;
 
@@ -281,7 +303,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
 
                 zero(ev);
                 ev.events = 0;
-                ev.data.u32 = FD_FIFO_BASE + i->fifo_fd;
+                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;
@@ -312,7 +334,7 @@ void inhibitor_remove_fifo(Inhibitor *i) {
         }
 }
 
-InhibitWhat manager_inhibit_what(Manager *m) {
+InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
         Inhibitor *i;
         Iterator j;
         InhibitWhat what = 0;
@@ -320,28 +342,95 @@ InhibitWhat manager_inhibit_what(Manager *m) {
         assert(m);
 
         HASHMAP_FOREACH(i, m->inhibitor_fds, j)
-                what |= i->what;
+                if (i->mode == mm)
+                        what |= i->what;
 
         return what;
 }
 
-const char *inhibit_what_to_string(InhibitWhat w) {
+static int pid_is_active(Manager *m, pid_t pid) {
+        Session *s;
+        int r;
 
-        static const char* const table[_INHIBIT_WHAT_MAX] = {
-                [0] = "",
-                [INHIBIT_SHUTDOWN] = "shutdown",
-                [INHIBIT_SUSPEND] = "suspend",
-                [INHIBIT_IDLE] = "idle",
-                [INHIBIT_SHUTDOWN|INHIBIT_SUSPEND] = "shutdown:suspend",
-                [INHIBIT_SHUTDOWN|INHIBIT_IDLE] = "shutdown:idle",
-                [INHIBIT_SHUTDOWN|INHIBIT_SUSPEND|INHIBIT_IDLE] = "shutdown:suspend:idle",
-                [INHIBIT_SUSPEND|INHIBIT_IDLE] = "suspend:idle"
-        };
+        r = manager_get_session_by_pid(m, pid, &s);
+        if (r <= 0)
+                return r;
+
+        return session_is_active(s);
+}
+
+bool manager_is_inhibited(
+                Manager *m,
+                InhibitWhat w,
+                InhibitMode mm,
+                dual_timestamp *since,
+                bool ignore_inactive,
+                bool ignore_uid,
+                uid_t uid) {
+
+        Inhibitor *i;
+        Iterator j;
+        struct dual_timestamp ts = { 0, 0 };
+        bool inhibited = false;
+
+        assert(m);
+        assert(w > 0 && w < _INHIBIT_WHAT_MAX);
+
+        HASHMAP_FOREACH(i, m->inhibitor_fds, j) {
+                if (!(i->what & w))
+                        continue;
+
+                if (i->mode != mm)
+                        continue;
+
+                if (ignore_inactive && pid_is_active(m, i->pid) <= 0)
+                        continue;
+
+                if (ignore_uid && i->uid == uid)
+                        continue;
+
+                if (!inhibited ||
+                    i->since.monotonic < ts.monotonic)
+                        ts = i->since;
+
+                inhibited = true;
+        }
+
+        if (since)
+                *since = ts;
+
+        return inhibited;
+}
+
+const char *inhibit_what_to_string(InhibitWhat w) {
+        static __thread char buffer[97];
+        char *p;
 
         if (w < 0 || w >= _INHIBIT_WHAT_MAX)
                 return NULL;
 
-        return table[w];
+        p = buffer;
+        if (w & INHIBIT_SHUTDOWN)
+                p = stpcpy(p, "shutdown:");
+        if (w & INHIBIT_SLEEP)
+                p = stpcpy(p, "sleep:");
+        if (w & INHIBIT_IDLE)
+                p = stpcpy(p, "idle:");
+        if (w & INHIBIT_HANDLE_POWER_KEY)
+                p = stpcpy(p, "handle-power-key:");
+        if (w & INHIBIT_HANDLE_SUSPEND_KEY)
+                p = stpcpy(p, "handle-suspend-key:");
+        if (w & INHIBIT_HANDLE_HIBERNATE_KEY)
+                p = stpcpy(p, "handle-hibernate-key:");
+        if (w & INHIBIT_HANDLE_LID_SWITCH)
+                p = stpcpy(p, "handle-lid-switch:");
+
+        if (p > buffer)
+                *(p-1) = 0;
+        else
+                *p = 0;
+
+        return buffer;
 }
 
 InhibitWhat inhibit_what_from_string(const char *s) {
@@ -352,14 +441,28 @@ InhibitWhat inhibit_what_from_string(const char *s) {
         FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
                 if (l == 8 && strncmp(w, "shutdown", l) == 0)
                         what |= INHIBIT_SHUTDOWN;
-                else if (l == 7 && strncmp(w, "suspend", l) == 0)
-                        what |= INHIBIT_SUSPEND;
+                else if (l == 5 && strncmp(w, "sleep", l) == 0)
+                        what |= INHIBIT_SLEEP;
                 else if (l == 4 && strncmp(w, "idle", l) == 0)
                         what |= INHIBIT_IDLE;
+                else if (l == 16 && strncmp(w, "handle-power-key", l) == 0)
+                        what |= INHIBIT_HANDLE_POWER_KEY;
+                else if (l == 18 && strncmp(w, "handle-suspend-key", l) == 0)
+                        what |= INHIBIT_HANDLE_SUSPEND_KEY;
+                else if (l == 20 && strncmp(w, "handle-hibernate-key", l) == 0)
+                        what |= INHIBIT_HANDLE_HIBERNATE_KEY;
+                else if (l == 17 && strncmp(w, "handle-lid-switch", l) == 0)
+                        what |= INHIBIT_HANDLE_LID_SWITCH;
                 else
                         return _INHIBIT_WHAT_INVALID;
         }
 
         return what;
-
 }
+
+static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = {
+        [INHIBIT_BLOCK] = "block",
+        [INHIBIT_DELAY] = "delay"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(inhibit_mode, InhibitMode);