1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/epoll.h>
31 #include "path-util.h"
32 #include "logind-inhibit.h"
34 Inhibitor* inhibitor_new(Manager *m, const char* id) {
39 i = new0(Inhibitor, 1);
43 i->state_file = strappend("/run/systemd/inhibit/", id);
49 i->id = path_get_file_name(i->state_file);
51 if (hashmap_put(m->inhibitors, i->id, i) < 0) {
63 void inhibitor_free(Inhibitor *i) {
69 hashmap_remove(i->manager->inhibitors, i->id);
70 inhibitor_remove_fifo(i);
73 unlink(i->state_file);
80 int inhibitor_save(Inhibitor *i) {
87 r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
91 r = fopen_temporary(i->state_file, &f, &temp_path);
95 fchmod(fileno(f), 0644);
98 "# This is private data. Do not parse.\n"
103 inhibit_what_to_string(i->what),
104 inhibit_mode_to_string(i->mode),
105 (unsigned long) i->uid,
106 (unsigned long) i->pid);
109 cc = cescape(i->who);
113 fprintf(f, "WHO=%s\n", cc);
119 cc = cescape(i->why);
123 fprintf(f, "WHY=%s\n", cc);
129 fprintf(f, "FIFO=%s\n", i->fifo_path);
133 if (ferror(f) || rename(temp_path, i->state_file) < 0) {
135 unlink(i->state_file);
144 log_error("Failed to save inhibit data for %s: %s", i->id, strerror(-r));
149 int inhibitor_start(Inhibitor *i) {
155 dual_timestamp_get(&i->since);
157 log_debug("Inhibitor %s (%s) pid=%lu uid=%lu mode=%s started.",
158 strna(i->who), strna(i->why),
159 (unsigned long) i->pid, (unsigned long) i->uid,
160 inhibit_mode_to_string(i->mode));
166 manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
171 int inhibitor_stop(Inhibitor *i) {
175 log_debug("Inhibitor %s (%s) pid=%lu uid=%lu mode=%s stopped.",
176 strna(i->who), strna(i->why),
177 (unsigned long) i->pid, (unsigned long) i->uid,
178 inhibit_mode_to_string(i->mode));
181 unlink(i->state_file);
185 manager_send_changed(i->manager, i->mode == INHIBIT_BLOCK ? "BlockInhibited\0" : "DelayInhibited\0");
190 int inhibitor_load(Inhibitor *i) {
202 r = parse_env_file(i->state_file, NEWLINE,
209 "FIFO", &i->fifo_path,
214 w = what ? inhibit_what_from_string(what) : 0;
218 mm = mode ? inhibit_mode_from_string(mode) : INHIBIT_BLOCK;
223 r = parse_uid(uid, &i->uid);
229 r = parse_pid(pid, &i->pid);
259 fd = inhibitor_create_fifo(i);
261 close_nointr_nofail(fd);
274 int inhibitor_create_fifo(Inhibitor *i) {
281 r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0);
285 if (asprintf(&i->fifo_path, "/run/systemd/inhibit/%s.ref", i->id) < 0)
288 if (mkfifo(i->fifo_path, 0600) < 0 && errno != EEXIST)
292 /* Open reading side */
293 if (i->fifo_fd < 0) {
294 struct epoll_event ev;
296 i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
300 r = hashmap_put(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1), i);
306 ev.data.u32 = FD_OTHER_BASE + i->fifo_fd;
308 if (epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_ADD, i->fifo_fd, &ev) < 0)
312 /* Open writing side */
313 r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
320 void inhibitor_remove_fifo(Inhibitor *i) {
323 if (i->fifo_fd >= 0) {
324 assert_se(hashmap_remove(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1)) == i);
325 assert_se(epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_DEL, i->fifo_fd, NULL) == 0);
326 close_nointr_nofail(i->fifo_fd);
331 unlink(i->fifo_path);
337 InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) {
340 InhibitWhat what = 0;
344 HASHMAP_FOREACH(i, m->inhibitor_fds, j)
351 static int pid_is_active(Manager *m, pid_t pid) {
355 r = manager_get_session_by_pid(m, pid, &s);
359 return session_is_active(s);
362 bool manager_is_inhibited(
366 dual_timestamp *since,
371 struct dual_timestamp ts = { 0, 0 };
372 bool inhibited = false;
375 assert(w > 0 && w < _INHIBIT_WHAT_MAX);
377 HASHMAP_FOREACH(i, m->inhibitor_fds, j) {
384 if (only_active && pid_is_active(m, i->pid) <= 0)
388 i->since.monotonic < ts.monotonic)
400 const char *inhibit_what_to_string(InhibitWhat w) {
401 static __thread char buffer[73];
404 if (w < 0 || w >= _INHIBIT_WHAT_MAX)
408 if (w & INHIBIT_SHUTDOWN)
409 p = stpcpy(p, "shutdown:");
410 if (w & INHIBIT_SLEEP)
411 p = stpcpy(p, "sleep:");
412 if (w & INHIBIT_IDLE)
413 p = stpcpy(p, "idle:");
414 if (w & INHIBIT_HANDLE_POWER_KEY)
415 p = stpcpy(p, "handle-power-key:");
416 if (w & INHIBIT_HANDLE_SLEEP_KEY)
417 p = stpcpy(p, "handle-sleep-key:");
418 if (w & INHIBIT_HANDLE_LID_SWITCH)
419 p = stpcpy(p, "handle-lid-switch:");
429 InhibitWhat inhibit_what_from_string(const char *s) {
430 InhibitWhat what = 0;
434 FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
435 if (l == 8 && strncmp(w, "shutdown", l) == 0)
436 what |= INHIBIT_SHUTDOWN;
437 else if (l == 5 && strncmp(w, "sleep", l) == 0)
438 what |= INHIBIT_SLEEP;
439 else if (l == 4 && strncmp(w, "idle", l) == 0)
440 what |= INHIBIT_IDLE;
441 else if (l == 16 && strncmp(w, "handle-power-key", l) == 0)
442 what |= INHIBIT_HANDLE_POWER_KEY;
443 else if (l == 16 && strncmp(w, "handle-sleep-key", l) == 0)
444 what |= INHIBIT_HANDLE_SLEEP_KEY;
445 else if (l == 17 && strncmp(w, "handle-lid-switch", l) == 0)
446 what |= INHIBIT_HANDLE_LID_SWITCH;
448 return _INHIBIT_WHAT_INVALID;
454 static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = {
455 [INHIBIT_BLOCK] = "block",
456 [INHIBIT_DELAY] = "delay"
459 DEFINE_STRING_TABLE_LOOKUP(inhibit_mode, InhibitMode);