summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
Diffstat (limited to 'src/login')
-rw-r--r--src/login/inhibit.c5
-rw-r--r--src/login/loginctl.c20
-rw-r--r--src/login/logind-acl.c5
-rw-r--r--src/login/logind-action.c6
-rw-r--r--src/login/logind-action.h1
-rw-r--r--src/login/logind-button.c3
-rw-r--r--src/login/logind-button.h2
-rw-r--r--src/login/logind-core.c4
-rw-r--r--src/login/logind-dbus.c822
-rw-r--r--src/login/logind-device.c1
-rw-r--r--src/login/logind-device.h2
-rw-r--r--src/login/logind-gperf.gperf1
-rw-r--r--src/login/logind-inhibit.c14
-rw-r--r--src/login/logind-inhibit.h3
-rw-r--r--src/login/logind-seat-dbus.c30
-rw-r--r--src/login/logind-seat.c7
-rw-r--r--src/login/logind-seat.h5
-rw-r--r--src/login/logind-session-dbus.c81
-rw-r--r--src/login/logind-session-device.c4
-rw-r--r--src/login/logind-session-device.h4
-rw-r--r--src/login/logind-session.c32
-rw-r--r--src/login/logind-session.h11
-rw-r--r--src/login/logind-user-dbus.c37
-rw-r--r--src/login/logind-user.c17
-rw-r--r--src/login/logind-user.h5
-rw-r--r--src/login/logind-utmp.c182
-rw-r--r--src/login/logind.c48
-rw-r--r--src/login/logind.conf8
-rw-r--r--src/login/logind.h45
-rw-r--r--src/login/org.freedesktop.login1.conf8
-rw-r--r--src/login/org.freedesktop.login1.policy.in30
-rw-r--r--src/login/pam_systemd.c5
-rw-r--r--src/login/sysfs-show.c1
-rw-r--r--src/login/test-inhibit.c1
-rw-r--r--src/login/user-sessions.c81
35 files changed, 1040 insertions, 491 deletions
diff --git a/src/login/inhibit.c b/src/login/inhibit.c
index 44bda34aff..57cfb5d0b5 100644
--- a/src/login/inhibit.c
+++ b/src/login/inhibit.c
@@ -20,7 +20,6 @@
***/
#include <getopt.h>
-#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -32,6 +31,8 @@
#include "util.h"
#include "build.h"
#include "strv.h"
+#include "formats-util.h"
+#include "process-util.h"
static const char* arg_what = "idle:sleep:shutdown";
static const char* arg_who = NULL;
@@ -260,7 +261,7 @@ int main(int argc, char *argv[]) {
fd = inhibit(bus, &error);
if (fd < 0) {
- log_error("Failed to inhibit: %s", bus_error_message(&error, -r));
+ log_error("Failed to inhibit: %s", bus_error_message(&error, fd));
return EXIT_FAILURE;
}
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index b0eede9a34..02d240c704 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -23,7 +23,6 @@
#include <errno.h>
#include <string.h>
#include <getopt.h>
-#include <pwd.h>
#include <locale.h>
#include "sd-bus.h"
@@ -42,6 +41,9 @@
#include "cgroup-util.h"
#include "spawn-polkit-agent.h"
#include "verbs.h"
+#include "process-util.h"
+#include "terminal-util.h"
+#include "signal-util.h"
static char **arg_property = NULL;
static bool arg_all = false;
@@ -869,7 +871,7 @@ static int activate(int argc, char *argv[], void *userdata) {
for (i = 1; i < argc; i++) {
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -904,7 +906,7 @@ static int kill_session(int argc, char *argv[], void *userdata) {
for (i = 1; i < argc; i++) {
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -954,7 +956,7 @@ static int enable_linger(int argc, char *argv[], void *userdata) {
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
}
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -988,7 +990,7 @@ static int terminate_user(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1025,7 +1027,7 @@ static int kill_user(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1054,7 +1056,7 @@ static int attach(int argc, char *argv[], void *userdata) {
for (i = 2; i < argc; i++) {
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1082,7 +1084,7 @@ static int flush_devices(int argc, char *argv[], void *userdata) {
polkit_agent_open_if_enabled();
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1375,6 +1377,8 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
+
r = loginctl_main(argc, argv, bus);
finish:
diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c
index 5856f9079d..466225d69c 100644
--- a/src/login/logind-acl.c
+++ b/src/login/logind-acl.c
@@ -19,11 +19,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <errno.h>
#include <string.h>
#include "util.h"
+#include "formats-util.h"
#include "acl-util.h"
#include "set.h"
#include "logind-acl.h"
@@ -254,8 +254,7 @@ int devnode_acl_all(struct udev *udev,
FOREACH_DIRENT(dent, dir, return -errno) {
_cleanup_free_ char *unescaped_devname = NULL;
- unescaped_devname = cunescape(dent->d_name);
- if (!unescaped_devname)
+ if (cunescape(dent->d_name, UNESCAPE_RELAX, &unescaped_devname) < 0)
return -ENOMEM;
n = strappend("/dev/", unescaped_devname);
diff --git a/src/login/logind-action.c b/src/login/logind-action.c
index 0844df20a9..f635fb1b63 100644
--- a/src/login/logind-action.c
+++ b/src/login/logind-action.c
@@ -21,13 +21,15 @@
#include <unistd.h>
-#include "sd-messages.h"
#include "conf-parser.h"
#include "special.h"
#include "sleep-config.h"
#include "bus-util.h"
#include "bus-error.h"
#include "logind-action.h"
+#include "formats-util.h"
+#include "process-util.h"
+#include "terminal-util.h"
int manager_handle_action(
Manager *m,
@@ -113,7 +115,7 @@ int manager_handle_action(
if (!supported) {
log_warning("Requested operation not supported, ignoring.");
- return -ENOTSUP;
+ return -EOPNOTSUPP;
}
if (m->action_what) {
diff --git a/src/login/logind-action.h b/src/login/logind-action.h
index e9b424b5f6..ff98065371 100644
--- a/src/login/logind-action.h
+++ b/src/login/logind-action.h
@@ -36,7 +36,6 @@ typedef enum HandleAction {
} HandleAction;
#include "logind.h"
-#include "logind-inhibit.h"
int manager_handle_action(
Manager *m,
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index d7211e66ce..610adc513e 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -19,7 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
@@ -28,9 +27,7 @@
#include <linux/input.h>
#include "sd-messages.h"
-#include "conf-parser.h"
#include "util.h"
-#include "special.h"
#include "logind-button.h"
Button* button_new(Manager *m, const char *name) {
diff --git a/src/login/logind-button.h b/src/login/logind-button.h
index 72a612e914..80d93c7e6b 100644
--- a/src/login/logind-button.h
+++ b/src/login/logind-button.h
@@ -23,8 +23,6 @@
typedef struct Button Button;
-#include "list.h"
-#include "util.h"
#include "logind.h"
struct Button {
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index a6ff5add95..440c32aa2c 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -20,20 +20,18 @@
***/
#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <pwd.h>
-#include <unistd.h>
#include <linux/vt.h>
#include "strv.h"
#include "cgroup-util.h"
-#include "audit.h"
#include "bus-util.h"
#include "bus-error.h"
#include "udev-util.h"
#include "logind.h"
+#include "terminal-util.h"
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
Device *d;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 8b0bafd49e..10a9df0961 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -24,7 +24,6 @@
#include <unistd.h>
#include <pwd.h>
-#include "sd-id128.h"
#include "sd-messages.h"
#include "strv.h"
#include "mkdir.h"
@@ -32,17 +31,19 @@
#include "special.h"
#include "sleep-config.h"
#include "fileio-label.h"
-#include "label.h"
-#include "utf8.h"
#include "unit-name.h"
-#include "virt.h"
#include "audit.h"
#include "bus-util.h"
#include "bus-error.h"
#include "bus-common-errors.h"
#include "udev-util.h"
#include "selinux-util.h"
+#include "efivars.h"
#include "logind.h"
+#include "formats-util.h"
+#include "process-util.h"
+#include "terminal-util.h"
+#include "utmp-wtmp.h"
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
@@ -213,16 +214,42 @@ static int property_get_preparing(
return sd_bus_message_append(reply, "b", b);
}
+static int property_get_scheduled_shutdown(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Manager *m = userdata;
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(m);
+
+ r = sd_bus_message_open_container(reply, 'r', "st");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_close_container(reply);
+}
+
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
-static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
Manager *m = userdata;
const char *name;
Session *session;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -241,14 +268,13 @@ static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userda
return sd_bus_reply_method_return(message, "o", p);
}
-static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
Session *session = NULL;
Manager *m = userdata;
pid_t pid;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -278,14 +304,13 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
return sd_bus_reply_method_return(message, "o", p);
}
-static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
Manager *m = userdata;
uint32_t uid;
User *user;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -304,14 +329,13 @@ static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata,
return sd_bus_reply_method_return(message, "o", p);
}
-static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
Manager *m = userdata;
User *user = NULL;
pid_t pid;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -340,14 +364,13 @@ static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *us
return sd_bus_reply_method_return(message, "o", p);
}
-static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
Manager *m = userdata;
const char *name;
Seat *seat;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -366,14 +389,13 @@ static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata,
return sd_bus_reply_method_return(message, "o", p);
}
-static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
Session *session;
Iterator i;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -406,17 +428,16 @@ static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *user
if (r < 0)
return r;
- return sd_bus_send(bus, reply, NULL);
+ return sd_bus_send(NULL, reply, NULL);
}
-static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
User *user;
Iterator i;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -447,17 +468,16 @@ static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdat
if (r < 0)
return r;
- return sd_bus_send(bus, reply, NULL);
+ return sd_bus_send(NULL, reply, NULL);
}
-static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
Seat *seat;
Iterator i;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -485,16 +505,19 @@ static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdat
if (r < 0)
return r;
- return sd_bus_send(bus, reply, NULL);
+ return sd_bus_send(NULL, reply, NULL);
}
-static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
Manager *m = userdata;
Inhibitor *inhibitor;
Iterator i;
int r;
+ assert(message);
+ assert(m);
+
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
@@ -520,10 +543,10 @@ static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *us
if (r < 0)
return r;
- return sd_bus_send(bus, reply, NULL);
+ return sd_bus_send(NULL, reply, NULL);
}
-static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
uint32_t uid, leader, audit_id = 0;
_cleanup_free_ char *id = NULL;
@@ -537,7 +560,6 @@ static int method_create_session(sd_bus *bus, sd_bus_message *message, void *use
SessionClass c;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -813,13 +835,12 @@ fail:
return r;
}
-static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
Session *session;
const char *name;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -831,18 +852,19 @@ static int method_release_session(sd_bus *bus, sd_bus_message *message, void *us
if (r < 0)
return r;
- session_release(session);
+ r = session_release(session);
+ if (r < 0)
+ return r;
return sd_bus_reply_method_return(message, NULL);
}
-static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
Session *session;
const char *name;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -854,21 +876,16 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u
if (r < 0)
return r;
- r = session_activate(session);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_session_method_activate(message, session, error);
}
-static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *session_name, *seat_name;
Manager *m = userdata;
Session *session;
Seat *seat;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -897,13 +914,12 @@ static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message,
return sd_bus_reply_method_return(message, NULL);
}
-static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
Session *session;
const char *name;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -915,21 +931,29 @@ static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userd
if (r < 0)
return r;
- r = session_send_lock(session, streq(sd_bus_message_get_member(message), "LockSession"));
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_session_method_lock(message, session, error);
}
-static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int r;
- assert(bus);
assert(message);
assert(m);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.lock-sessions",
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
if (r < 0)
return r;
@@ -937,80 +961,52 @@ static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *user
return sd_bus_reply_method_return(message, NULL);
}
-static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
- const char *name, *swho;
+static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ const char *name;
Manager *m = userdata;
Session *session;
- int32_t signo;
- KillWho who;
int r;
- assert(bus);
assert(message);
assert(m);
- r = sd_bus_message_read(message, "ssi", &name, &swho, &signo);
+ r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
- if (isempty(swho))
- who = KILL_ALL;
- else {
- who = kill_who_from_string(swho);
- if (who < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
- }
-
- if (signo <= 0 || signo >= _NSIG)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
-
r = manager_get_session_from_creds(m, message, name, error, &session);
if (r < 0)
return r;
- r = session_kill(session, who, signo);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_session_method_kill(message, session, error);
}
-static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
uint32_t uid;
- int32_t signo;
User *user;
int r;
- assert(bus);
assert(message);
assert(m);
- r = sd_bus_message_read(message, "ui", &uid, &signo);
+ r = sd_bus_message_read(message, "u", &uid);
if (r < 0)
return r;
- if (signo <= 0 || signo >= _NSIG)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
-
r = manager_get_user_from_creds(m, message, uid, error, &user);
if (r < 0)
return r;
- r = user_kill(user, signo);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_user_method_kill(message, user, error);
}
-static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
Session *session;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -1022,20 +1018,15 @@ static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *
if (r < 0)
return r;
- r = session_stop(session, true);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_session_method_terminate(message, session, error);
}
-static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
uint32_t uid;
User *user;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -1047,20 +1038,15 @@ static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *use
if (r < 0)
return r;
- r = user_stop(user, true);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_user_method_terminate(message, user, error);
}
-static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
const char *name;
Seat *seat;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -1072,14 +1058,10 @@ static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *use
if (r < 0)
return r;
- r = seat_stop_sessions(seat, true);
- if (r < 0)
- return r;
-
- return sd_bus_reply_method_return(message, NULL);
+ return bus_seat_method_terminate(message, seat, error);
}
-static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *cc = NULL;
Manager *m = userdata;
int b, r;
@@ -1088,7 +1070,6 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us
uint32_t uid;
int interactive;
- assert(bus);
assert(message);
assert(m);
@@ -1119,6 +1100,7 @@ static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *us
CAP_SYS_ADMIN,
"org.freedesktop.login1.set-user-linger",
interactive,
+ UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
@@ -1267,12 +1249,11 @@ static int flush_devices(Manager *m) {
return trigger_device(m, NULL);
}
-static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *sysfs, *seat;
Manager *m = userdata;
int interactive, r;
- assert(bus);
assert(message);
assert(m);
@@ -1291,6 +1272,7 @@ static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *user
CAP_SYS_ADMIN,
"org.freedesktop.login1.attach-device",
interactive,
+ UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
@@ -1305,11 +1287,10 @@ static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *user
return sd_bus_reply_method_return(message, NULL);
}
-static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int interactive, r;
- assert(bus);
assert(message);
assert(m);
@@ -1322,6 +1303,7 @@ static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *user
CAP_SYS_ADMIN,
"org.freedesktop.login1.flush-devices",
interactive,
+ UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
@@ -1481,7 +1463,46 @@ static int execute_shutdown_or_sleep(
m->action_what = w;
/* Make sure the lid switch is ignored for a while */
- manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + IGNORE_LID_SWITCH_SUSPEND_USEC);
+ manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
+
+ return 0;
+}
+
+static int manager_inhibit_timeout_handler(
+ sd_event_source *s,
+ uint64_t usec,
+ void *userdata) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ Inhibitor *offending = NULL;
+ Manager *manager = userdata;
+ int r;
+
+ assert(manager);
+ assert(manager->inhibit_timeout_source == s);
+
+ if (manager->action_what == 0 || manager->action_job)
+ return 0;
+
+ if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
+ _cleanup_free_ char *comm = NULL, *u = NULL;
+
+ (void) get_process_comm(offending->pid, &comm);
+ u = uid_to_name(offending->uid);
+
+ log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
+ offending->uid, strna(u),
+ offending->pid, strna(comm));
+ }
+
+ /* Actually do the operation */
+ r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
+ if (r < 0) {
+ log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
+
+ manager->action_unit = NULL;
+ manager->action_what = 0;
+ }
return 0;
}
@@ -1491,12 +1512,31 @@ static int delay_shutdown_or_sleep(
InhibitWhat w,
const char *unit_name) {
+ int r;
+ usec_t timeout_val;
+
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
assert(unit_name);
- m->action_timestamp = now(CLOCK_MONOTONIC);
+ timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
+
+ if (m->inhibit_timeout_source) {
+ r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_time() failed: %m");
+
+ r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
+ } else {
+ r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
+ timeout_val, 0, manager_inhibit_timeout_handler, m);
+ if (r < 0)
+ return r;
+ }
+
m->action_unit = unit_name;
m->action_what = w;
@@ -1559,49 +1599,25 @@ int bus_manager_shutdown_or_sleep_now_or_later(
return r;
}
-static int method_do_shutdown_or_sleep(
+static int verify_shutdown_creds(
Manager *m,
sd_bus_message *message,
- const char *unit_name,
InhibitWhat w,
+ bool interactive,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
- const char *sleep_verb,
- sd_bus_message_handler_t method,
sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
bool multiple_sessions, blocked;
- int interactive, r;
uid_t uid;
+ int r;
assert(m);
assert(message);
- assert(unit_name);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
- assert(action);
- assert(action_multiple_sessions);
- assert(action_ignore_inhibit);
- assert(method);
-
- r = sd_bus_message_read(message, "b", &interactive);
- if (r < 0)
- return r;
-
- /* Don't allow multiple jobs being executed at the same time */
- if (m->action_what)
- return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
-
- if (sleep_verb) {
- r = can_sleep(sleep_verb);
- if (r < 0)
- return r;
-
- if (r == 0)
- return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
- }
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
if (r < 0)
@@ -1618,30 +1634,74 @@ static int method_do_shutdown_or_sleep(
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
- if (multiple_sessions) {
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, &m->polkit_registry, error);
+ if (multiple_sessions && action_multiple_sessions) {
+ r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
- if (blocked) {
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, &m->polkit_registry, error);
+ if (blocked && action_ignore_inhibit) {
+ r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
- if (!multiple_sessions && !blocked) {
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, &m->polkit_registry, error);
+ if (!multiple_sessions && !blocked && action) {
+ r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
+ return 0;
+}
+
+static int method_do_shutdown_or_sleep(
+ Manager *m,
+ sd_bus_message *message,
+ const char *unit_name,
+ InhibitWhat w,
+ const char *action,
+ const char *action_multiple_sessions,
+ const char *action_ignore_inhibit,
+ const char *sleep_verb,
+ sd_bus_error *error) {
+
+ int interactive, r;
+
+ assert(m);
+ assert(message);
+ assert(unit_name);
+ assert(w >= 0);
+ assert(w <= _INHIBIT_WHAT_MAX);
+
+ r = sd_bus_message_read(message, "b", &interactive);
+ if (r < 0)
+ return r;
+
+ /* Don't allow multiple jobs being executed at the same time */
+ if (m->action_what)
+ return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
+
+ if (sleep_verb) {
+ r = can_sleep(sleep_verb);
+ if (r < 0)
+ return r;
+
+ if (r == 0)
+ return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
+ }
+
+ r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
+ action_ignore_inhibit, error);
+ if (r != 0)
+ return r;
+
r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
if (r < 0)
return r;
@@ -1649,7 +1709,7 @@ static int method_do_shutdown_or_sleep(
return sd_bus_reply_method_return(message, NULL);
}
-static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
@@ -1660,11 +1720,10 @@ static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata,
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
- method_poweroff,
error);
}
-static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
@@ -1675,11 +1734,10 @@ static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, s
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
- method_reboot,
error);
}
-static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
@@ -1690,11 +1748,247 @@ static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata,
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"suspend",
- method_suspend,
error);
}
-static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int nologin_timeout_handler(
+ sd_event_source *s,
+ uint64_t usec,
+ void *userdata) {
+
+ Manager *m = userdata;
+ int r;
+
+ log_info("Creating /run/nologin, blocking further logins...");
+
+ r = write_string_file_atomic("/run/nologin", "System is going down.");
+ if (r < 0)
+ log_error_errno(r, "Failed to create /run/nologin: %m");
+ else
+ m->unlink_nologin = true;
+
+ return 0;
+}
+
+static int update_schedule_file(Manager *m) {
+
+ int r;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *t = NULL, *temp_path = NULL;
+
+ assert(m);
+
+ r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
+
+ t = cescape(m->wall_message);
+ if (!t)
+ return log_oom();
+
+ r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
+
+ (void) fchmod(fileno(f), 0644);
+
+ fprintf(f,
+ "USEC="USEC_FMT"\n"
+ "WARN_WALL=%i\n"
+ "MODE=%s\n",
+ m->scheduled_shutdown_timeout,
+ m->enable_wall_messages,
+ m->scheduled_shutdown_type);
+
+ if (!isempty(m->wall_message))
+ fprintf(f, "WALL_MESSAGE=%s\n", t);
+
+ (void) fflush_and_check(f);
+
+ if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
+ log_error_errno(errno, "Failed to write information about scheduled shutdowns: %m");
+ r = -errno;
+
+ (void) unlink(temp_path);
+ (void) unlink("/run/systemd/shutdown/scheduled");
+ }
+
+ return r;
+}
+
+static int manager_scheduled_shutdown_handler(
+ sd_event_source *s,
+ uint64_t usec,
+ void *userdata) {
+
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ Manager *m = userdata;
+ const char *target;
+ int r;
+
+ assert(m);
+
+ if (isempty(m->scheduled_shutdown_type))
+ return 0;
+
+ if (streq(m->scheduled_shutdown_type, "halt"))
+ target = SPECIAL_HALT_TARGET;
+ else if (streq(m->scheduled_shutdown_type, "poweroff"))
+ target = SPECIAL_POWEROFF_TARGET;
+ else
+ target = SPECIAL_REBOOT_TARGET;
+
+ r = execute_shutdown_or_sleep(m, 0, target, &error);
+ if (r < 0)
+ return log_error_errno(r, "Unable to execute transition to %s: %m", target);
+
+ return 0;
+}
+
+static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ const char *action_multiple_sessions = NULL;
+ const char *action_ignore_inhibit = NULL;
+ const char *action = NULL;
+ uint64_t elapse;
+ char *type;
+ int r;
+
+ assert(m);
+ assert(message);
+
+ r = sd_bus_message_read(message, "st", &type, &elapse);
+ if (r < 0)
+ return r;
+
+ if (streq(type, "reboot")) {
+ action = "org.freedesktop.login1.reboot";
+ action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
+ action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
+ } else if (streq(type, "halt")) {
+ action = "org.freedesktop.login1.halt";
+ action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
+ action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
+ } else if (streq(type, "poweroff")) {
+ action = "org.freedesktop.login1.poweroff";
+ action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
+ action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
+ } else
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
+
+ r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
+ action, action_multiple_sessions, action_ignore_inhibit, error);
+ if (r != 0)
+ return r;
+
+ if (m->scheduled_shutdown_timeout_source) {
+ r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_time() failed: %m");
+
+ r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
+ } else {
+ r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
+ CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_add_time() failed: %m");
+ }
+
+ r = free_and_strdup(&m->scheduled_shutdown_type, type);
+ if (r < 0) {
+ m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+ return log_oom();
+ }
+
+ if (m->nologin_timeout_source) {
+ r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_time() failed: %m");
+
+ r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
+ } else {
+ r = sd_event_add_time(m->event, &m->nologin_timeout_source,
+ CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_add_time() failed: %m");
+ }
+
+ m->scheduled_shutdown_timeout = elapse;
+
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
+ if (r >= 0) {
+ const char *tty;
+
+ (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
+ (void) sd_bus_creds_get_tty(creds, &tty);
+
+ r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
+ if (r < 0) {
+ m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+ return log_oom();
+ }
+ }
+
+ r = manager_setup_wall_message_timer(m);
+ if (r < 0)
+ return r;
+
+ if (!isempty(type)) {
+ r = update_schedule_file(m);
+ if (r < 0)
+ return r;
+ } else
+ (void) unlink("/run/systemd/shutdown/scheduled");
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Manager *m = userdata;
+ bool cancelled;
+
+ assert(m);
+ assert(message);
+
+ cancelled = m->scheduled_shutdown_type != NULL;
+
+ m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+ m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
+ m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
+ free(m->scheduled_shutdown_type);
+ m->scheduled_shutdown_type = NULL;
+ m->scheduled_shutdown_timeout = 0;
+
+ if (m->unlink_nologin) {
+ (void) unlink("/run/nologin");
+ m->unlink_nologin = false;
+ }
+
+ if (cancelled) {
+ _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+ const char *tty = NULL;
+ uid_t uid = 0;
+ int r;
+
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
+ if (r >= 0) {
+ (void) sd_bus_creds_get_uid(creds, &uid);
+ (void) sd_bus_creds_get_tty(creds, &tty);
+ }
+
+ utmp_wall("The system shutdown has been cancelled",
+ lookup_uid(uid), tty, logind_wall_tty_filter, m);
+ }
+
+ return sd_bus_reply_method_return(message, "b", cancelled);
+}
+
+static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
@@ -1705,11 +1999,10 @@ static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hibernate",
- method_hibernate,
error);
}
-static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
@@ -1720,7 +2013,6 @@ static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userd
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
- method_hybrid_sleep,
error);
}
@@ -1772,7 +2064,7 @@ static int method_can_shutdown_or_sleep(
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
if (multiple_sessions) {
- r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, &challenge, error);
+ r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
if (r < 0)
return r;
@@ -1785,7 +2077,7 @@ static int method_can_shutdown_or_sleep(
}
if (blocked) {
- r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, &challenge, error);
+ r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
if (r < 0)
return r;
@@ -1801,7 +2093,7 @@ static int method_can_shutdown_or_sleep(
/* If neither inhibit nor multiple sessions
* apply then just check the normal policy */
- r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, &challenge, error);
+ r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
if (r < 0)
return r;
@@ -1816,7 +2108,7 @@ static int method_can_shutdown_or_sleep(
return sd_bus_reply_method_return(message, "s", result);
}
-static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
@@ -1829,7 +2121,7 @@ static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userd
error);
}
-static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
@@ -1842,7 +2134,7 @@ static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdat
error);
}
-static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
@@ -1855,7 +2147,7 @@ static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userda
error);
}
-static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
@@ -1868,7 +2160,7 @@ static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *user
error);
}
-static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
@@ -1881,7 +2173,100 @@ static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *u
error);
}
-static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int property_get_reboot_to_firmware_setup(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+ int r;
+
+ assert(bus);
+ assert(reply);
+ assert(userdata);
+
+ r = efi_get_reboot_to_firmware();
+ if (r < 0 && r != -EOPNOTSUPP)
+ return r;
+
+ return sd_bus_message_append(reply, "b", r > 0);
+}
+
+static int method_set_reboot_to_firmware_setup(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int b, r;
+ Manager *m = userdata;
+
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "b", &b);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-firmware-setup",
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ r = efi_set_reboot_to_firmware(b);
+ if (r < 0)
+ return r;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
+static int method_can_reboot_to_firmware_setup(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int r;
+ bool challenge;
+ const char *result;
+ Manager *m = userdata;
+
+ assert(message);
+ assert(m);
+
+ r = efi_reboot_to_firmware_supported();
+ if (r == -EOPNOTSUPP)
+ return sd_bus_reply_method_return(message, "s", "na");
+ else if (r < 0)
+ return r;
+
+ r = bus_test_polkit(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-reboot-to-firmware-setup",
+ UID_INVALID,
+ &challenge,
+ error);
+ if (r < 0)
+ return r;
+
+ if (r > 0)
+ result = "yes";
+ else if (challenge)
+ result = "challenge";
+ else
+ result = "no";
+
+ return sd_bus_reply_method_return(message, "s", result);
+}
+
+static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *who, *why, *what, *mode;
_cleanup_free_ char *id = NULL;
@@ -1894,7 +2279,6 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata,
uid_t uid;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -1921,15 +2305,20 @@ static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata,
if (m->action_what & w)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT,
- w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
- w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
- w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
- w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
- w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
- w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
- "org.freedesktop.login1.inhibit-handle-lid-switch",
- false, &m->polkit_registry, error);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_BOOT,
+ w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
+ w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
+ w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
+ w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
+ w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
+ w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
+ "org.freedesktop.login1.inhibit-handle-lid-switch",
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
if (r < 0)
return r;
if (r == 0)
@@ -1992,10 +2381,14 @@ fail:
const sd_bus_vtable manager_vtable[] = {
SD_BUS_VTABLE_START(0),
+ SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
+ SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
+
SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
@@ -2007,10 +2400,12 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
+ SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2025,21 +2420,23 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, 0),
- SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, 0),
- SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, 0),
- SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, 0),
- SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
+ SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -2048,6 +2445,8 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("SessionNew", "so", 0),
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
@@ -2082,7 +2481,7 @@ static int session_jobs_reply(Session *s, const char *unit, const char *result)
return r;
}
-int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *path, *result, *unit;
Manager *m = userdata;
Session *session;
@@ -2090,7 +2489,6 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
User *user;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -2151,14 +2549,13 @@ int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_b
return 0;
}
-int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *path, *unit;
Manager *m = userdata;
Session *session;
User *user;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -2179,7 +2576,7 @@ int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
return 0;
}
-int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *unit = NULL;
Manager *m = userdata;
const char *path;
@@ -2187,7 +2584,6 @@ int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdat
User *user;
int r;
- assert(bus);
assert(message);
assert(m);
@@ -2212,13 +2608,14 @@ int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdat
return 0;
}
-int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
Session *session;
Iterator i;
int b, r;
- assert(bus);
+ assert(message);
+ assert(m);
r = sd_bus_message_read(message, "b", &b);
if (r < 0) {
@@ -2238,16 +2635,17 @@ int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus
return 0;
}
-int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int match_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name, *old, *new;
Manager *m = userdata;
Session *session;
Iterator i;
int r;
-
-
char *key;
+ assert(message);
+ assert(m);
+
r = sd_bus_message_read(message, "sss", &name, &old, &new);
if (r < 0) {
bus_log_parse_error(r);
@@ -2286,44 +2684,6 @@ int manager_send_changed(Manager *manager, const char *property, ...) {
l);
}
-int manager_dispatch_delayed(Manager *manager) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- Inhibitor *offending = NULL;
- int r;
-
- assert(manager);
-
- if (manager->action_what == 0 || manager->action_job)
- return 0;
-
- /* Continue delay? */
- if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
- _cleanup_free_ char *comm = NULL, *u = NULL;
-
- get_process_comm(offending->pid, &comm);
- u = uid_to_name(offending->uid);
-
- if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
- return 0;
-
- log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
- offending->uid, strna(u),
- offending->pid, strna(comm));
- }
-
- /* Actually do the operation */
- r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
- if (r < 0) {
- log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
-
- manager->action_unit = NULL;
- manager->action_what = 0;
- return r;
- }
-
- return 1;
-}
-
int manager_start_scope(
Manager *manager,
const char *scope,
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
index 76c5a5c88f..ee4c45fb8d 100644
--- a/src/login/logind-device.c
+++ b/src/login/logind-device.c
@@ -19,7 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <string.h>
#include "util.h"
diff --git a/src/login/logind-device.h b/src/login/logind-device.h
index c273d2bfa0..6b2728586c 100644
--- a/src/login/logind-device.h
+++ b/src/login/logind-device.h
@@ -24,8 +24,6 @@
typedef struct Device Device;
#include "list.h"
-#include "util.h"
-#include "logind.h"
#include "logind-seat.h"
#include "logind-session-device.h"
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index 62460673b9..9218d098e0 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -29,6 +29,7 @@ Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manag
Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited)
Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited)
Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited)
+Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec)
Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action)
Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec)
Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size)
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 84fee0e773..68304a1610 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -26,9 +26,9 @@
#include "util.h"
#include "mkdir.h"
-#include "path-util.h"
#include "logind-inhibit.h"
#include "fileio.h"
+#include "formats-util.h"
Inhibitor* inhibitor_new(Manager *m, const char* id) {
Inhibitor *i;
@@ -232,18 +232,18 @@ int inhibitor_load(Inhibitor *i) {
}
if (who) {
- cc = cunescape(who);
- if (!cc)
- return -ENOMEM;
+ r = cunescape(who, 0, &cc);
+ if (r < 0)
+ return r;
free(i->who);
i->who = cc;
}
if (why) {
- cc = cunescape(why);
- if (!cc)
- return -ENOMEM;
+ r = cunescape(why, 0, &cc);
+ if (r < 0)
+ return r;
free(i->why);
i->why = cc;
diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h
index f767876a4c..1b77fc1e9e 100644
--- a/src/login/logind-inhibit.h
+++ b/src/login/logind-inhibit.h
@@ -23,8 +23,6 @@
typedef struct Inhibitor Inhibitor;
-#include "list.h"
-#include "util.h"
typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1,
@@ -46,7 +44,6 @@ typedef enum InhibitMode {
} InhibitMode;
#include "logind.h"
-#include "logind-seat.h"
struct Inhibitor {
Manager *manager;
diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c
index 50b0b8842f..ce67ffde37 100644
--- a/src/login/logind-seat-dbus.c
+++ b/src/login/logind-seat-dbus.c
@@ -193,14 +193,26 @@ static int property_get_idle_since_hint(
return sd_bus_message_append(reply, "t", u);
}
-static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Seat *s = userdata;
int r;
- assert(bus);
assert(message);
assert(s);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_KILL,
+ "org.freedesktop.login1.manage",
+ false,
+ UID_INVALID,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = seat_stop_sessions(s, true);
if (r < 0)
return r;
@@ -208,13 +220,12 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata
return sd_bus_reply_method_return(message, NULL);
}
-static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Seat *s = userdata;
const char *name;
Session *session;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -236,12 +247,11 @@ static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *u
return sd_bus_reply_method_return(message, NULL);
}
-static int method_switch_to(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Seat *s = userdata;
unsigned int to;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -259,11 +269,10 @@ static int method_switch_to(sd_bus *bus, sd_bus_message *message, void *userdata
return sd_bus_reply_method_return(message, NULL);
}
-static int method_switch_to_next(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Seat *s = userdata;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -274,11 +283,10 @@ static int method_switch_to_next(sd_bus *bus, sd_bus_message *message, void *use
return sd_bus_reply_method_return(message, NULL);
}
-static int method_switch_to_previous(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Seat *s = userdata;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -302,7 +310,7 @@ const sd_bus_vtable seat_vtable[] = {
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
+ SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SwitchTo", "u", NULL, method_switch_to, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 126c5b84cc..11d24ce5b4 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -19,21 +19,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/vt.h>
#include <string.h>
-#include "sd-id128.h"
#include "sd-messages.h"
#include "logind-seat.h"
#include "logind-acl.h"
#include "util.h"
#include "mkdir.h"
-#include "path-util.h"
+#include "formats-util.h"
+#include "terminal-util.h"
Seat *seat_new(Manager *m, const char *id) {
Seat *s;
diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
index 9e469d41c6..248dbeb9d7 100644
--- a/src/login/logind-seat.h
+++ b/src/login/logind-seat.h
@@ -24,9 +24,6 @@
typedef struct Seat Seat;
#include "list.h"
-#include "util.h"
-#include "logind.h"
-#include "logind-device.h"
#include "logind-session.h"
struct Seat {
@@ -96,3 +93,5 @@ char *seat_bus_path(Seat *s);
int seat_send_signal(Seat *s, bool new_seat);
int seat_send_changed(Seat *s, const char *properties, ...) _sentinel_;
+
+int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 4e7edef52d..debaa31a29 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -180,14 +180,26 @@ static int property_get_idle_since_hint(
return sd_bus_message_append(reply, "t", u);
}
-static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
int r;
- assert(bus);
assert(message);
assert(s);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_KILL,
+ "org.freedesktop.login1.manage",
+ false,
+ s->user->uid,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = session_stop(s, true);
if (r < 0)
return r;
@@ -195,11 +207,10 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata
return sd_bus_reply_method_return(message, NULL);
}
-static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -210,28 +221,39 @@ static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata,
return sd_bus_reply_method_return(message, NULL);
}
-static int method_lock(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
int r;
- assert(bus);
assert(message);
assert(s);
- r = session_send_lock(s, streq(sd_bus_message_get_member(message), "Lock"));
+ r = bus_verify_polkit_async(
+ message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.lock-sessions",
+ false,
+ s->user->uid,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
-static int method_set_idle_hint(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
Session *s = userdata;
uid_t uid;
int r, b;
- assert(bus);
assert(message);
assert(s);
@@ -255,14 +277,13 @@ static int method_set_idle_hint(sd_bus *bus, sd_bus_message *message, void *user
return sd_bus_reply_method_return(message, NULL);
}
-static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
const char *swho;
int32_t signo;
KillWho who;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -281,6 +302,19 @@ static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
if (signo <= 0 || signo >= _NSIG)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_KILL,
+ "org.freedesktop.login1.manage",
+ false,
+ s->user->uid,
+ &s->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = session_kill(s, who, signo);
if (r < 0)
return r;
@@ -288,13 +322,12 @@ static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_
return sd_bus_reply_method_return(message, NULL);
}
-static int method_take_control(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
Session *s = userdata;
int r, force;
uid_t uid;
- assert(bus);
assert(message);
assert(s);
@@ -320,10 +353,9 @@ static int method_take_control(sd_bus *bus, sd_bus_message *message, void *userd
return sd_bus_reply_method_return(message, NULL);
}
-static int method_release_control(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
- assert(bus);
assert(message);
assert(s);
@@ -335,14 +367,13 @@ static int method_release_control(sd_bus *bus, sd_bus_message *message, void *us
return sd_bus_reply_method_return(message, NULL);
}
-static int method_take_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
uint32_t major, minor;
SessionDevice *sd;
dev_t dev;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -374,14 +405,13 @@ static int method_take_device(sd_bus *bus, sd_bus_message *message, void *userda
return r;
}
-static int method_release_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
uint32_t major, minor;
SessionDevice *sd;
dev_t dev;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -401,14 +431,13 @@ static int method_release_device(sd_bus *bus, sd_bus_message *message, void *use
return sd_bus_reply_method_return(message, NULL);
}
-static int method_pause_device_complete(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Session *s = userdata;
uint32_t major, minor;
SessionDevice *sd;
dev_t dev;
int r;
- assert(bus);
assert(message);
assert(s);
@@ -456,12 +485,12 @@ const sd_bus_vtable session_vtable[] = {
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("Activate", NULL, NULL, method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Lock", NULL, NULL, method_lock, 0),
- SD_BUS_METHOD("Unlock", NULL, NULL, method_lock, 0),
+ SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Kill", "si", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
+ SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c
index c2de862250..656f268dba 100644
--- a/src/login/logind-session-device.c
+++ b/src/login/logind-session-device.c
@@ -19,16 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <fcntl.h>
#include <libudev.h>
#include <linux/input.h>
-#include <linux/ioctl.h>
#include <string.h>
#include <sys/ioctl.h>
-#include <sys/stat.h>
#include <sys/types.h>
-#include <unistd.h>
#include "util.h"
#include "missing.h"
diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h
index 61a843d09d..1c9f998371 100644
--- a/src/login/logind-session-device.h
+++ b/src/login/logind-session-device.h
@@ -25,11 +25,7 @@ typedef enum DeviceType DeviceType;
typedef struct SessionDevice SessionDevice;
#include "list.h"
-#include "util.h"
#include "logind.h"
-#include "logind-device.h"
-#include "logind-seat.h"
-#include "logind-session.h"
enum DeviceType {
DEVICE_TYPE_UNKNOWN,
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index a02a537f7c..6a450b02a0 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -28,9 +28,7 @@
#include <sys/ioctl.h>
#include <unistd.h>
-#include "sd-id128.h"
#include "sd-messages.h"
-#include "strv.h"
#include "util.h"
#include "mkdir.h"
#include "path-util.h"
@@ -39,6 +37,8 @@
#include "bus-util.h"
#include "bus-error.h"
#include "logind-session.h"
+#include "formats-util.h"
+#include "terminal-util.h"
#define RELEASE_USEC (20*USEC_PER_SEC)
@@ -463,7 +463,7 @@ int session_activate(Session *s) {
assert(s->user);
if (!s->seat)
- return -ENOTSUP;
+ return -EOPNOTSUPP;
if (s->seat->active == s)
return 0;
@@ -471,7 +471,7 @@ int session_activate(Session *s) {
/* on seats with VTs, we let VTs manage session-switching */
if (seat_has_vts(s->seat)) {
if (!s->vtnr)
- return -ENOTSUP;
+ return -EOPNOTSUPP;
return chvt(s->vtnr);
}
@@ -703,18 +703,20 @@ static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *us
return 0;
}
-void session_release(Session *s) {
+int session_release(Session *s) {
assert(s);
if (!s->started || s->stopping)
- return;
+ return 0;
+
+ if (s->timer_event_source)
+ return 0;
- if (!s->timer_event_source)
- sd_event_add_time(s->manager->event,
- &s->timer_event_source,
- CLOCK_MONOTONIC,
- now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
- release_timeout_callback, s);
+ return sd_event_add_time(s->manager->event,
+ &s->timer_event_source,
+ CLOCK_MONOTONIC,
+ now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
+ release_timeout_callback, s);
}
bool session_is_active(Session *s) {
@@ -1041,15 +1043,15 @@ void session_restore_vt(Session *s) {
if (vt < 0)
return;
- ioctl(vt, KDSETMODE, KD_TEXT);
+ (void) ioctl(vt, KDSETMODE, KD_TEXT);
if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
kb = K_UNICODE;
- ioctl(vt, KDSKBMODE, kb);
+ (void) ioctl(vt, KDSKBMODE, kb);
mode.mode = VT_AUTO;
- ioctl(vt, VT_SETMODE, &mode);
+ (void) ioctl(vt, VT_SETMODE, &mode);
fchown(vt, 0, -1);
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index a007fb5e84..7a329b94ad 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -25,10 +25,6 @@ typedef struct Session Session;
typedef enum KillWho KillWho;
#include "list.h"
-#include "util.h"
-#include "logind.h"
-#include "logind-seat.h"
-#include "logind-session-device.h"
#include "logind-user.h"
#include "login-shared.h"
@@ -141,7 +137,7 @@ int session_create_fifo(Session *s);
int session_start(Session *s);
int session_stop(Session *s, bool force);
int session_finalize(Session *s);
-void session_release(Session *s);
+int session_release(Session *s);
int session_save(Session *s);
int session_load(Session *s);
int session_kill(Session *s, KillWho who, int signo);
@@ -179,3 +175,8 @@ void session_leave_vt(Session *s);
bool session_is_controller(Session *s, const char *sender);
int session_set_controller(Session *s, const char *sender, bool force);
void session_drop_controller(Session *s);
+
+int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c
index 5cfaac0d4f..8a710cef13 100644
--- a/src/login/logind-user-dbus.c
+++ b/src/login/logind-user-dbus.c
@@ -26,6 +26,7 @@
#include "bus-util.h"
#include "logind.h"
#include "logind-user.h"
+#include "formats-util.h"
static int property_get_display(
sd_bus *bus,
@@ -171,14 +172,26 @@ static int property_get_linger(
return sd_bus_message_append(reply, "b", r > 0);
}
-static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
User *u = userdata;
int r;
- assert(bus);
assert(message);
assert(u);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_KILL,
+ "org.freedesktop.login1.manage",
+ false,
+ u->uid,
+ &u->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = user_stop(u, true);
if (r < 0)
return r;
@@ -186,15 +199,27 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata
return sd_bus_reply_method_return(message, NULL);
}
-static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
User *u = userdata;
int32_t signo;
int r;
- assert(bus);
assert(message);
assert(u);
+ r = bus_verify_polkit_async(
+ message,
+ CAP_KILL,
+ "org.freedesktop.login1.manage",
+ false,
+ u->uid,
+ &u->manager->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
r = sd_bus_message_read(message, "i", &signo);
if (r < 0)
return r;
@@ -227,8 +252,8 @@ const sd_bus_vtable user_vtable[] = {
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0),
- SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
- SD_BUS_METHOD("Kill", "i", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
+ SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("Kill", "i", NULL, bus_user_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index f4c4490e8f..dc3db9abda 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -26,8 +26,8 @@
#include "util.h"
#include "mkdir.h"
+#include "rm-rf.h"
#include "hashmap.h"
-#include "strv.h"
#include "fileio.h"
#include "path-util.h"
#include "special.h"
@@ -38,6 +38,7 @@
#include "clean-ipc.h"
#include "logind-user.h"
#include "smack-util.h"
+#include "formats-util.h"
User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
User *u;
@@ -319,7 +320,7 @@ static int user_mkdir_runtime_path(User *u) {
} else
p = u->runtime_path;
- if (path_is_mount_point(p, false) <= 0) {
+ if (path_is_mount_point(p, 0) <= 0) {
_cleanup_free_ char *t = NULL;
(void) mkdir(p, 0700);
@@ -377,7 +378,7 @@ static int user_start_slice(User *u) {
char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
sprintf(lu, UID_FMT, u->uid);
- r = build_subslice(SPECIAL_USER_SLICE, lu, &slice);
+ r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &slice);
if (r < 0)
return r;
@@ -410,9 +411,9 @@ static int user_start_service(User *u) {
char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
sprintf(lu, UID_FMT, u->uid);
- service = unit_name_build("user", lu, ".service");
- if (!service)
- return log_oom();
+ r = unit_name_build("user", lu, ".service", &service);
+ if (r < 0)
+ return log_error_errno(r, "Failed to build service name: %m");
r = manager_start_unit(u->manager, service, &error, &job);
if (r < 0) {
@@ -522,7 +523,7 @@ static int user_remove_runtime_path(User *u) {
if (!u->runtime_path)
return 0;
- r = rm_rf(u->runtime_path, false, false, false);
+ r = rm_rf(u->runtime_path, 0);
if (r < 0)
log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
@@ -533,7 +534,7 @@ static int user_remove_runtime_path(User *u) {
if (r < 0 && errno != EINVAL && errno != ENOENT)
log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
- r = rm_rf(u->runtime_path, false, true, false);
+ r = rm_rf(u->runtime_path, REMOVE_ROOT);
if (r < 0)
log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 4e0568fea9..722247806b 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -24,9 +24,7 @@
typedef struct User User;
#include "list.h"
-#include "util.h"
#include "logind.h"
-#include "logind-session.h"
typedef enum UserState {
USER_OFFLINE, /* Not logged in at all */
@@ -92,3 +90,6 @@ int user_send_changed(User *u, const char *properties, ...) _sentinel_;
const char* user_state_to_string(UserState s) _const_;
UserState user_state_from_string(const char *s) _pure_;
+
+int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c
new file mode 100644
index 0000000000..1e13ff01de
--- /dev/null
+++ b/src/login/logind-utmp.c
@@ -0,0 +1,182 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2015 Daniel Mack
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "sd-messages.h"
+#include "strv.h"
+#include "special.h"
+#include "unit-name.h"
+#include "audit.h"
+#include "bus-util.h"
+#include "bus-error.h"
+#include "bus-common-errors.h"
+#include "logind.h"
+#include "formats-util.h"
+#include "utmp-wtmp.h"
+
+_const_ static usec_t when_wall(usec_t n, usec_t elapse) {
+
+ usec_t left;
+ unsigned int i;
+ static const int wall_timers[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 25, 40, 55, 70, 100, 130, 150, 180,
+ };
+
+ /* If the time is already passed, then don't announce */
+ if (n >= elapse)
+ return 0;
+
+ left = elapse - n;
+
+ for (i = 1; i < ELEMENTSOF(wall_timers); i++)
+ if (wall_timers[i] * USEC_PER_MINUTE >= left)
+ return left - wall_timers[i-1] * USEC_PER_MINUTE;
+
+ return left % USEC_PER_HOUR;
+}
+
+bool logind_wall_tty_filter(const char *tty, void *userdata) {
+
+ Manager *m = userdata;
+
+ assert(m);
+
+ if (!startswith(tty, "/dev/"))
+ return true;
+
+ return !streq(tty + 5, m->scheduled_shutdown_tty);
+}
+
+static int warn_wall(Manager *m, usec_t n) {
+ char date[FORMAT_TIMESTAMP_MAX] = {};
+ _cleanup_free_ char *l = NULL;
+ usec_t left;
+ int r;
+
+ assert(m);
+
+ if (!m->enable_wall_messages)
+ return 0;
+
+ left = m->scheduled_shutdown_timeout > n;
+
+ r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
+ strempty(m->wall_message),
+ isempty(m->wall_message) ? "" : "\n",
+ m->scheduled_shutdown_type,
+ left ? "at " : "NOW",
+ left ? format_timestamp(date, sizeof(date), m->scheduled_shutdown_timeout) : "");
+ if (r < 0) {
+ log_oom();
+ return 0;
+ }
+
+ utmp_wall(l, lookup_uid(m->scheduled_shutdown_uid),
+ m->scheduled_shutdown_tty, logind_wall_tty_filter, m);
+
+ return 1;
+}
+
+static int wall_message_timeout_handler(
+ sd_event_source *s,
+ uint64_t usec,
+ void *userdata) {
+
+ Manager *m = userdata;
+ usec_t n, next;
+ int r;
+
+ assert(m);
+ assert(s == m->wall_message_timeout_source);
+
+ n = now(CLOCK_REALTIME);
+
+ r = warn_wall(m, n);
+ if (r == 0)
+ return 0;
+
+ next = when_wall(n, m->scheduled_shutdown_timeout);
+ if (next > 0) {
+ r = sd_event_source_set_time(s, n + next);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_time() failed. %m");
+
+ r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_enabled() failed. %m");
+ }
+
+ return 0;
+}
+
+int manager_setup_wall_message_timer(Manager *m) {
+
+ usec_t n, elapse;
+ int r;
+
+ assert(m);
+
+ n = now(CLOCK_REALTIME);
+ elapse = m->scheduled_shutdown_timeout;
+
+ /* wall message handling */
+
+ if (isempty(m->scheduled_shutdown_type)) {
+ warn_wall(m, n);
+ return 0;
+ }
+
+ if (elapse < n)
+ return 0;
+
+ /* Warn immediately if less than 15 minutes are left */
+ if (elapse - n < 15 * USEC_PER_MINUTE) {
+ r = warn_wall(m, n);
+ if (r == 0)
+ return 0;
+ }
+
+ elapse = when_wall(n, elapse);
+ if (elapse == 0)
+ return 0;
+
+ if (m->wall_message_timeout_source) {
+ r = sd_event_source_set_time(m->wall_message_timeout_source, n + elapse);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_time() failed. %m");
+
+ r = sd_event_source_set_enabled(m->wall_message_timeout_source, SD_EVENT_ONESHOT);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_source_set_enabled() failed. %m");
+ } else {
+ r = sd_event_add_time(m->event, &m->wall_message_timeout_source,
+ CLOCK_REALTIME, n + elapse, 0, wall_message_timeout_handler, m);
+ if (r < 0)
+ return log_error_errno(r, "sd_event_add_time() failed. %m");
+ }
+
+ return 0;
+}
diff --git a/src/login/logind.c b/src/login/logind.c
index b44f376427..00f8dbdab2 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -24,19 +24,20 @@
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
-#include <linux/vt.h>
-#include <sys/timerfd.h>
#include "sd-daemon.h"
#include "strv.h"
#include "conf-parser.h"
-#include "mkdir.h"
#include "bus-util.h"
#include "bus-error.h"
-#include "logind.h"
#include "udev-util.h"
+#include "formats-util.h"
+#include "signal-util.h"
+#include "logind.h"
+
+static void manager_free(Manager *m);
-Manager *manager_new(void) {
+static Manager *manager_new(void) {
Manager *m;
int r;
@@ -57,6 +58,7 @@ Manager *manager_new(void) {
m->handle_lid_switch = HANDLE_SUSPEND;
m->handle_lid_switch_docked = HANDLE_IGNORE;
m->lid_switch_ignore_inhibited = true;
+ m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
m->idle_action_usec = 30 * USEC_PER_MINUTE;
m->idle_action = HANDLE_IGNORE;
@@ -101,7 +103,7 @@ fail:
return NULL;
}
-void manager_free(Manager *m) {
+static void manager_free(Manager *m) {
Session *session;
User *u;
Device *d;
@@ -142,6 +144,10 @@ void manager_free(Manager *m) {
set_free_free(m->busnames);
sd_event_source_unref(m->idle_action_event_source);
+ sd_event_source_unref(m->inhibit_timeout_source);
+ sd_event_source_unref(m->scheduled_shutdown_timeout_source);
+ sd_event_source_unref(m->nologin_timeout_source);
+ sd_event_source_unref(m->wall_message_timeout_source);
sd_event_source_unref(m->console_active_event_source);
sd_event_source_unref(m->udev_seat_event_source);
@@ -164,6 +170,9 @@ void manager_free(Manager *m) {
if (m->udev)
udev_unref(m->udev);
+ if (m->unlink_nologin)
+ (void) unlink("/run/nologin");
+
bus_verify_polkit_async_registry_free(m->polkit_registry);
sd_bus_unref(m->bus);
@@ -174,6 +183,9 @@ void manager_free(Manager *m) {
strv_free(m->kill_only_users);
strv_free(m->kill_exclude_users);
+ free(m->scheduled_shutdown_type);
+ free(m->scheduled_shutdown_tty);
+ free(m->wall_message);
free(m->action_job);
free(m);
}
@@ -890,7 +902,7 @@ static int manager_connect_udev(Manager *m) {
return 0;
}
-void manager_gc(Manager *m, bool drop_not_started) {
+static void manager_gc(Manager *m, bool drop_not_started) {
Seat *seat;
Session *session;
User *user;
@@ -1001,7 +1013,7 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
return 0;
}
-int manager_startup(Manager *m) {
+static int manager_startup(Manager *m) {
int r;
Seat *seat;
Session *session;
@@ -1032,7 +1044,7 @@ int manager_startup(Manager *m) {
if (r < 0)
return log_error_errno(r, "Failed to add seat0: %m");
- r = manager_set_lid_switch_ignore(m, 0 + IGNORE_LID_SWITCH_STARTUP_USEC);
+ r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
if (r < 0)
log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
@@ -1088,14 +1100,12 @@ int manager_startup(Manager *m) {
return 0;
}
-int manager_run(Manager *m) {
+static int manager_run(Manager *m) {
int r;
assert(m);
for (;;) {
- usec_t us = (uint64_t) -1;
-
r = sd_event_get_state(m->event);
if (r < 0)
return r;
@@ -1104,19 +1114,7 @@ int manager_run(Manager *m) {
manager_gc(m, true);
- if (manager_dispatch_delayed(m) > 0)
- continue;
-
- if (m->action_what != 0 && !m->action_job) {
- usec_t x, y;
-
- x = now(CLOCK_MONOTONIC);
- y = m->action_timestamp + m->inhibit_delay_max;
-
- us = x >= y ? 0 : y - x;
- }
-
- r = sd_event_run(m->event, us);
+ r = sd_event_run(m->event, (uint64_t) -1);
if (r < 0)
return r;
}
diff --git a/src/login/logind.conf b/src/login/logind.conf
index 6b1943a2d1..6df6f04c77 100644
--- a/src/login/logind.conf
+++ b/src/login/logind.conf
@@ -5,10 +5,11 @@
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
-# You can override the directives in this file by creating files in
-# /etc/systemd/logind.conf.d/*.conf.
+# Entries in this file show the compile time defaults.
+# You can change settings by editing this file.
+# Defaults can be restored by simply deleting this file.
#
-# See logind.conf(5) for details
+# See logind.conf(5) for details.
[Login]
#NAutoVTs=6
@@ -26,6 +27,7 @@
#SuspendKeyIgnoreInhibited=no
#HibernateKeyIgnoreInhibited=no
#LidSwitchIgnoreInhibited=yes
+#HoldoffTimeoutSec=30s
#IdleAction=ignore
#IdleActionSec=30min
#RuntimeDirectorySize=10%
diff --git a/src/login/logind.h b/src/login/logind.h
index e0cb7d0238..cd226f55fc 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -22,12 +22,10 @@
***/
#include <stdbool.h>
-#include <inttypes.h>
#include <libudev.h>
#include "sd-event.h"
#include "sd-bus.h"
-#include "util.h"
#include "list.h"
#include "hashmap.h"
#include "set.h"
@@ -35,16 +33,10 @@
typedef struct Manager Manager;
#include "logind-device.h"
-#include "logind-seat.h"
-#include "logind-session.h"
-#include "logind-user.h"
#include "logind-inhibit.h"
#include "logind-button.h"
#include "logind-action.h"
-#define IGNORE_LID_SWITCH_STARTUP_USEC (3 * USEC_PER_MINUTE)
-#define IGNORE_LID_SWITCH_SUSPEND_USEC (30 * USEC_PER_SEC)
-
struct Manager {
sd_event *event;
sd_bus *bus;
@@ -103,7 +95,19 @@ struct Manager {
/* If a shutdown/suspend is currently executed, then this is
* the job of it */
char *action_job;
- usec_t action_timestamp;
+ sd_event_source *inhibit_timeout_source;
+
+ char *scheduled_shutdown_type;
+ usec_t scheduled_shutdown_timeout;
+ sd_event_source *scheduled_shutdown_timeout_source;
+ uid_t scheduled_shutdown_uid;
+ char *scheduled_shutdown_tty;
+ sd_event_source *nologin_timeout_source;
+ bool unlink_nologin;
+
+ char *wall_message;
+ unsigned enable_wall_messages;
+ sd_event_source *wall_message_timeout_source;
sd_event_source *idle_action_event_source;
usec_t idle_action_usec;
@@ -125,14 +129,12 @@ struct Manager {
Hashmap *polkit_registry;
+ usec_t holdoff_timeout_usec;
sd_event_source *lid_switch_ignore_event_source;
size_t runtime_dir_size;
};
-Manager *manager_new(void);
-void manager_free(Manager *m);
-
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device);
int manager_add_button(Manager *m, const char *name, Button **_button);
int manager_add_seat(Manager *m, const char *id, Seat **_seat);
@@ -145,12 +147,8 @@ int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor);
int manager_process_seat_device(Manager *m, struct udev_device *d);
int manager_process_button_device(Manager *m, struct udev_device *d);
-int manager_startup(Manager *m);
-int manager_run(Manager *m);
int manager_spawn_autovt(Manager *m, unsigned int vtnr);
-void manager_gc(Manager *m, bool drop_not_started);
-
bool manager_shall_kill(Manager *m, const char *user);
int manager_get_idle_hint(Manager *m, dual_timestamp *t);
@@ -164,18 +162,16 @@ bool manager_is_docked_or_multiple_displays(Manager *m);
extern const sd_bus_vtable manager_vtable[];
-int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
-int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
-int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
-int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
-int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error);
+int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error);
+int match_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error);
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
-int manager_dispatch_delayed(Manager *manager);
-
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
@@ -197,3 +193,6 @@ int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned lin
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);
+
+int manager_setup_wall_message_timer(Manager *m);
+bool logind_wall_tty_filter(const char *tty, void *userdata);
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index 1318328aa0..0ad78802dd 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -130,6 +130,14 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="CanRebootToFirmwareSetup"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="SetRebootToFirmwareSetup"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="AttachDevice"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 49094eeddb..83e7183323 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -270,4 +270,34 @@
<annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.hibernate</annotate>
</action>
+ <action id="org.freedesktop.login1.manage">
+ <_description>Manage active sessions, users and seats</_description>
+ <_message>Authentication is required for managing active sessions, users and seats.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.lock-sessions">
+ <_description>Lock or unlock active sessions</_description>
+ <_message>Authentication is required to lock or unlock active sessions.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
+ <action id="org.freedesktop.login1.set-reboot-to-firmware-setup">
+ <_description>Allow indication to the firmware to boot to setup interface</_description>
+ <_message>Authentication is required to indicate to the firmware to boot to setup interface.</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index d7a708fd0a..b5d419000c 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -40,6 +40,9 @@
#include "socket-util.h"
#include "fileio.h"
#include "bus-error.h"
+#include "formats-util.h"
+#include "terminal-util.h"
+#include "hostname-util.h"
static int parse_argv(
pam_handle_t *handle,
@@ -334,7 +337,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
/* If this fails vtnr will be 0, that's intended */
if (!isempty(cvtnr))
- safe_atou32(cvtnr, &vtnr);
+ (void) safe_atou32(cvtnr, &vtnr);
if (!isempty(display) && !vtnr) {
if (isempty(seat))
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
index 9bd9152bed..9a9fb7622d 100644
--- a/src/login/sysfs-show.c
+++ b/src/login/sysfs-show.c
@@ -27,6 +27,7 @@
#include "sysfs-show.h"
#include "path-util.h"
#include "udev-util.h"
+#include "terminal-util.h"
static int show_sysfs_one(
struct udev *udev,
diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c
index 274687d20f..03516de916 100644
--- a/src/login/test-inhibit.c
+++ b/src/login/test-inhibit.c
@@ -25,7 +25,6 @@
#include "util.h"
#include "sd-bus.h"
#include "bus-util.h"
-#include "bus-error.h"
static int inhibit(sd_bus *bus, const char *what) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
diff --git a/src/login/user-sessions.c b/src/login/user-sessions.c
deleted file mode 100644
index 6edb823e8c..0000000000
--- a/src/login/user-sessions.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "log.h"
-#include "util.h"
-#include "fileio.h"
-
-int main(int argc, char*argv[]) {
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (streq(argv[1], "start")) {
- int r = 0;
-
- if (unlink("/run/nologin") < 0 && errno != ENOENT) {
- log_error_errno(errno, "Failed to remove /run/nologin file: %m");
- r = -errno;
- }
-
- if (unlink("/etc/nologin") < 0 && errno != ENOENT) {
- /* If the file doesn't exist and /etc simply
- * was read-only (in which case unlink()
- * returns EROFS even if the file doesn't
- * exist), don't complain */
-
- if (errno != EROFS || access("/etc/nologin", F_OK) >= 0) {
- log_error_errno(errno, "Failed to remove /etc/nologin file: %m");
- return EXIT_FAILURE;
- }
- }
-
- if (r < 0)
- return EXIT_FAILURE;
-
- } else if (streq(argv[1], "stop")) {
- int r;
-
- r = write_string_file_atomic("/run/nologin", "System is going down.");
- if (r < 0) {
- log_error_errno(r, "Failed to create /run/nologin: %m");
- return EXIT_FAILURE;
- }
-
- } else {
- log_error("Unknown verb %s.", argv[1]);
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}