-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
- This file is part of systemd.
-
Copyright 2011 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 <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
#include <fcntl.h>
#include <pwd.h>
-#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
#include <linux/vt.h>
-#include "strv.h"
-#include "cgroup-util.h"
-#include "audit.h"
-#include "bus-util.h"
+#include "alloc-util.h"
#include "bus-error.h"
-#include "udev-util.h"
+#include "bus-util.h"
+#include "cgroup-util.h"
+//#include "conf-parser.h"
+#include "fd-util.h"
#include "logind.h"
+#include "parse-util.h"
+#include "process-util.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "udev-util.h"
+#include "user-util.h"
+
+void manager_reset_config(Manager *m) {
+ assert(m);
+
+ m->n_autovts = 6;
+ m->reserve_vt = 6;
+ m->remove_ipc = true;
+ m->inhibit_delay_max = 5 * USEC_PER_SEC;
+ m->handle_power_key = HANDLE_POWEROFF;
+ m->handle_suspend_key = HANDLE_SUSPEND;
+ m->handle_hibernate_key = HANDLE_HIBERNATE;
+ m->handle_lid_switch = HANDLE_SUSPEND;
+ m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
+ m->handle_lid_switch_docked = HANDLE_IGNORE;
+ m->power_key_ignore_inhibited = false;
+ m->suspend_key_ignore_inhibited = false;
+ m->hibernate_key_ignore_inhibited = false;
+ 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;
+
+ m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
+ m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
+ m->sessions_max = 8192;
+ m->inhibitors_max = 8192;
+
+ m->kill_user_processes = KILL_USER_PROCESSES;
+
+ m->kill_only_users = strv_free(m->kill_only_users);
+ m->kill_exclude_users = strv_free(m->kill_exclude_users);
+}
+
+int manager_parse_config_file(Manager *m) {
+ assert(m);
+
+ return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
+ CONF_PATHS_NULSTR("elogind/logind.conf.d"),
+ "Login\0",
+ config_item_perf_lookup, logind_gperf_lookup,
+ CONFIG_PARSE_WARN, m);
+}
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
Device *d;
int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
User *u;
+ int r;
assert(m);
assert(name);
- u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+ u = hashmap_get(m->users, UID_TO_PTR(uid));
if (!u) {
- u = user_new(m, uid, gid, name);
- if (!u)
- return -ENOMEM;
+ r = user_new(&u, m, uid, gid, name);
+ if (r < 0)
+ return r;
}
if (_user)
errno = 0;
p = getpwuid(uid);
if (!p)
- return errno ? -errno : -ENOENT;
+ return errno > 0 ? -errno : -ENOENT;
return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
}
return 0;
}
-int manager_watch_busname(Manager *m, const char *name) {
- char *n;
- int r;
-
- assert(m);
- assert(name);
-
- if (set_get(m->busnames, (char*) name))
- return 0;
-
- n = strdup(name);
- if (!n)
- return -ENOMEM;
-
- r = set_put(m->busnames, n);
- if (r < 0) {
- free(n);
- return r;
- }
-
- return 0;
-}
-
-void manager_drop_busname(Manager *m, const char *name) {
- Session *session;
- Iterator i;
-
- assert(m);
- assert(name);
-
- /* keep it if the name still owns a controller */
- HASHMAP_FOREACH(session, m->sessions, i)
- if (session_is_controller(session, name))
- return;
-
- free(set_remove(m->busnames, (char*) name));
-}
-
int manager_process_seat_device(Manager *m, struct udev_device *d) {
Device *device;
int r;
sn = "seat0";
button_set_seat(b, sn);
- button_open(b);
+
+ r = button_open(b);
+ if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error
+ * opening the device?) let's close the button again. */
+ button_free(b);
}
return 0;
}
-int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
+int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) {
+#if 0 /// elogind does not support systemd units, but its own session system
_cleanup_free_ char *unit = NULL;
+#else
+ _cleanup_free_ char *session_name = NULL;
+#endif // 0
Session *s;
int r;
assert(m);
- assert(session);
- if (pid < 1)
+ if (!pid_is_valid(pid))
return -EINVAL;
+#if 0 /// elogind does not support systemd units, but its own session system
r = cg_pid_get_unit(pid, &unit);
if (r < 0)
- return 0;
+ goto not_found;
s = hashmap_get(m->session_units, unit);
if (!s)
+ goto not_found;
+
+ if (ret)
+ *ret = s;
+#else
+ log_debug_elogind("Searching session for PID %u", pid);
+ r = cg_pid_get_session(pid, &session_name);
+ if (r < 0)
return 0;
- *session = s;
+ s = hashmap_get(m->sessions, session_name);
+ log_debug_elogind("Session Name \"%s\" -> Session \"%s\"",
+ session_name, s && s->id ? s->id : "NULL");
+#endif // 0
+
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+ return 0;
}
-int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
+int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) {
+#if 0 /// elogind does not support systemd units, but its own session system
_cleanup_free_ char *unit = NULL;
User *u;
+#else
+ Session *s;
+#endif // 0
int r;
assert(m);
- assert(user);
- if (pid < 1)
+ if (!pid_is_valid(pid))
return -EINVAL;
+#if 0 /// elogind does not support systemd units, but its own session system
r = cg_pid_get_slice(pid, &unit);
if (r < 0)
- return 0;
+ goto not_found;
u = hashmap_get(m->user_units, unit);
if (!u)
- return 0;
+ goto not_found;
+
+ if (ret)
+ *ret = u;
- *user = u;
return 1;
+
+not_found:
+ if (ret)
+ *ret = NULL;
+
+ return 0;
+#else
+ r = manager_get_session_by_pid (m, pid, &s);
+ if (r <= 0)
+ return r;
+ if (ret)
+ *ret = u;
+
+ *user = s->user;
+#endif // 0
}
int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
Session *s;
bool idle_hint;
- dual_timestamp ts = { 0, 0 };
+ dual_timestamp ts = DUAL_TIMESTAMP_NULL;
Iterator i;
assert(m);
assert(m);
assert(user);
- if (!m->kill_user_processes)
+ if (!m->kill_exclude_users && streq(user, "root"))
return false;
if (strv_contains(m->kill_exclude_users, user))
return false;
- if (strv_isempty(m->kill_only_users))
- return true;
+ if (!strv_isempty(m->kill_only_users))
+ return strv_contains(m->kill_only_users, user);
- return strv_contains(m->kill_only_users, user);
+ return m->kill_user_processes;
+}
+
+#if 0 /// UNNEEDED by elogind
+int config_parse_n_autovts(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ unsigned *n = data;
+ unsigned o;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou(rvalue, &o);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse number of autovts, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (o > 15) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "A maximum of 15 autovts are supported, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *n = o;
+ return 0;
}
static int vt_is_busy(unsigned int vtnr) {
assert(vtnr >= 1);
+ /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */
+ assert(vtnr <= 15);
+
/* We explicitly open /dev/tty1 here instead of /dev/tty0. If
* we'd open the latter we'd open the foreground tty which
* hence would be unconditionally busy. By opening /dev/tty1
}
int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)];
int r;
return r;
}
+#endif // 0
-bool manager_is_docked(Manager *m) {
+static bool manager_is_docked(Manager *m) {
Iterator i;
Button *b;
return false;
}
-int manager_count_displays(Manager *m) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+static int manager_count_external_displays(Manager *m) {
+ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
int n = 0;
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
struct udev_device *p;
- const char *status;
+ const char *status, *enabled, *dash, *nn, *i;
+ bool external = false;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
if (!d)
if (!streq_ptr(udev_device_get_subsystem(p), "drm"))
continue;
+ nn = udev_device_get_sysname(d);
+ if (!nn)
+ continue;
+
+ /* Ignore internal displays: the type is encoded in
+ * the sysfs name, as the second dash separated item
+ * (the first is the card name, the last the connector
+ * number). We implement a whitelist of external
+ * displays here, rather than a whitelist, to ensure
+ * we don't block suspends too eagerly. */
+ dash = strchr(nn, '-');
+ if (!dash)
+ continue;
+
+ dash++;
+ FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
+ "Composite-", "SVIDEO-", "Component-",
+ "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") {
+
+ if (startswith(dash, i)) {
+ external = true;
+ break;
+ }
+ }
+ if (!external)
+ continue;
+
+ /* Ignore ports that are not enabled */
+ enabled = udev_device_get_sysattr_value(d, "enabled");
+ if (!enabled)
+ continue;
+ if (!streq_ptr(enabled, "enabled"))
+ continue;
+
/* We count any connector which is not explicitly
* "disconnected" as connected. */
status = udev_device_get_sysattr_value(d, "status");
return n;
}
-bool manager_is_docked_or_multiple_displays(Manager *m) {
+bool manager_is_docked_or_external_displays(Manager *m) {
int n;
/* If we are docked don't react to lid closing */
/* If we have more than one display connected,
* assume that we are docked. */
- n = manager_count_displays(m);
+ n = manager_count_external_displays(m);
if (n < 0)
- log_warning_errno(-n, "Display counting failed: %m");
- else if (n > 1) {
- log_debug("Multiple (%i) displays connected.", n);
+ log_warning_errno(n, "Display counting failed: %m");
+ else if (n >= 1) {
+ log_debug("External (%i) displays connected.", n);
return true;
}
return false;
}
+
+bool manager_is_on_external_power(void) {
+ int r;
+
+ /* For now we only check for AC power, but 'external power' can apply
+ * to anything that isn't an internal battery */
+ r = on_ac_power();
+ if (r < 0)
+ log_warning_errno(r, "Failed to read AC power status: %m");
+ else if (r > 0)
+ return true;
+
+ return false;
+}
+
+bool manager_all_buttons_ignored(Manager *m) {
+ assert(m);
+
+ if (m->handle_power_key != HANDLE_IGNORE)
+ return false;
+ if (m->handle_suspend_key != HANDLE_IGNORE)
+ return false;
+ if (m->handle_hibernate_key != HANDLE_IGNORE)
+ return false;
+ if (m->handle_lid_switch != HANDLE_IGNORE)
+ return false;
+ if (m->handle_lid_switch_ep != _HANDLE_ACTION_INVALID &&
+ m->handle_lid_switch_ep != HANDLE_IGNORE)
+ return false;
+ if (m->handle_lid_switch_docked != HANDLE_IGNORE)
+ return false;
+
+ return true;
+}