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>
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 = file_name_from_path(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 = safe_mkdir("/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"
102 inhibit_what_to_string(i->what),
103 (unsigned long) i->uid,
104 (unsigned long) i->pid);
107 cc = cescape(i->who);
111 fprintf(f, "WHO=%s\n", cc);
117 cc = cescape(i->why);
121 fprintf(f, "WHY=%s\n", cc);
127 fprintf(f, "FIFO=%s\n", i->fifo_path);
131 if (ferror(f) || rename(temp_path, i->state_file) < 0) {
133 unlink(i->state_file);
142 log_error("Failed to save inhibit data for %s: %s", i->id, strerror(-r));
147 int inhibitor_start(Inhibitor *i) {
153 log_debug("Inhibitor %s (%s) pid=%lu uid=%lu started.",
154 strna(i->who), strna(i->why),
155 (unsigned long) i->pid, (unsigned long) i->uid);
161 manager_send_changed(i->manager, "Inhibited\0");
166 int inhibitor_stop(Inhibitor *i) {
170 log_debug("Inhibitor %s (%s) pid=%lu uid=%lu stopped.",
171 strna(i->who), strna(i->why),
172 (unsigned long) i->pid, (unsigned long) i->uid);
175 unlink(i->state_file);
179 manager_send_changed(i->manager, "Inhibited\0");
184 int inhibitor_load(Inhibitor *i) {
194 r = parse_env_file(i->state_file, NEWLINE,
200 "FIFO", &i->fifo_path,
205 w = inhibit_what_from_string(what);
209 parse_uid(uid, &i->uid);
210 parse_pid(pid, &i->pid);
237 fd = inhibitor_create_fifo(i);
239 close_nointr_nofail(fd);
252 int inhibitor_create_fifo(Inhibitor *i) {
259 r = safe_mkdir("/run/systemd/inhibit", 0755, 0, 0);
263 if (asprintf(&i->fifo_path, "/run/systemd/inhibit/%s.ref", i->id) < 0)
266 if (mkfifo(i->fifo_path, 0600) < 0 && errno != EEXIST)
270 /* Open reading side */
271 if (i->fifo_fd < 0) {
272 struct epoll_event ev;
274 i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
278 r = hashmap_put(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1), i);
284 ev.data.u32 = FD_FIFO_BASE + i->fifo_fd;
286 if (epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_ADD, i->fifo_fd, &ev) < 0)
290 /* Open writing side */
291 r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
298 void inhibitor_remove_fifo(Inhibitor *i) {
301 if (i->fifo_fd >= 0) {
302 assert_se(hashmap_remove(i->manager->inhibitor_fds, INT_TO_PTR(i->fifo_fd + 1)) == i);
303 assert_se(epoll_ctl(i->manager->epoll_fd, EPOLL_CTL_DEL, i->fifo_fd, NULL) == 0);
304 close_nointr_nofail(i->fifo_fd);
309 unlink(i->fifo_path);
315 InhibitWhat manager_inhibit_what(Manager *m) {
318 InhibitWhat what = 0;
322 HASHMAP_FOREACH(i, m->inhibitor_fds, j)
328 const char *inhibit_what_to_string(InhibitWhat w) {
330 static const char* const table[_INHIBIT_WHAT_MAX] = {
332 [INHIBIT_SHUTDOWN] = "shutdown",
333 [INHIBIT_SUSPEND] = "suspend",
334 [INHIBIT_IDLE] = "idle",
335 [INHIBIT_SHUTDOWN|INHIBIT_SUSPEND] = "shutdown:suspend",
336 [INHIBIT_SHUTDOWN|INHIBIT_IDLE] = "shutdown:idle",
337 [INHIBIT_SHUTDOWN|INHIBIT_SUSPEND|INHIBIT_IDLE] = "shutdown:suspend:idle",
338 [INHIBIT_SUSPEND|INHIBIT_IDLE] = "suspend:idle"
341 if (w < 0 || w >= _INHIBIT_WHAT_MAX)
347 InhibitWhat inhibit_what_from_string(const char *s) {
348 InhibitWhat what = 0;
352 FOREACH_WORD_SEPARATOR(w, l, s, ":", state) {
353 if (l == 8 && strncmp(w, "shutdown", l) == 0)
354 what |= INHIBIT_SHUTDOWN;
355 else if (l == 7 && strncmp(w, "suspend", l) == 0)
356 what |= INHIBIT_SUSPEND;
357 else if (l == 4 && strncmp(w, "idle", l) == 0)
358 what |= INHIBIT_IDLE;
360 return _INHIBIT_WHAT_INVALID;