X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind-core.c;h=0e7786f10395f373bca521b9bfa8a694eee0babe;hb=da22b4dccb157393d36cfce6656ddbd9f224f5e3;hp=6506f22f36352feb16d9f33768480bd7613ec050;hpb=cc3773810855956bad92337cee8fa193584ab62e;p=elogind.git
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 6506f22f3..0e7786f10 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,20 +17,22 @@
along with systemd; If not, see .
***/
-#include
-#include
-#include
#include
#include
-#include
+#include
+#include
#include
-#include "strv.h"
-#include "cgroup-util.h"
-#include "audit.h"
-#include "bus-util.h"
+#include "alloc-util.h"
#include "bus-error.h"
+#include "bus-util.h"
+#include "cgroup-util.h"
+#include "fd-util.h"
#include "logind.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "udev-util.h"
+#include "user-util.h"
int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
Device *d;
@@ -41,20 +41,15 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
assert(sysfs);
d = hashmap_get(m->devices, sysfs);
- if (d) {
- if (_device)
- *_device = d;
-
+ if (d)
/* we support adding master-flags, but not removing them */
d->master = d->master || master;
-
- return 0;
+ else {
+ d = device_new(m, sysfs, master);
+ if (!d)
+ return -ENOMEM;
}
- d = device_new(m, sysfs, master);
- if (!d)
- return -ENOMEM;
-
if (_device)
*_device = d;
@@ -68,17 +63,12 @@ int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
assert(id);
s = hashmap_get(m->seats, id);
- if (s) {
- if (_seat)
- *_seat = s;
-
- return 0;
+ if (!s) {
+ s = seat_new(m, id);
+ if (!s)
+ return -ENOMEM;
}
- s = seat_new(m, id);
- if (!s)
- return -ENOMEM;
-
if (_seat)
*_seat = s;
@@ -92,17 +82,12 @@ int manager_add_session(Manager *m, const char *id, Session **_session) {
assert(id);
s = hashmap_get(m->sessions, id);
- if (s) {
- if (_session)
- *_session = s;
-
- return 0;
+ if (!s) {
+ s = session_new(m, id);
+ if (!s)
+ return -ENOMEM;
}
- s = session_new(m, id);
- if (!s)
- return -ENOMEM;
-
if (_session)
*_session = s;
@@ -111,22 +96,18 @@ int manager_add_session(Manager *m, const char *id, Session **_session) {
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));
- if (u) {
- if (_user)
- *_user = u;
-
- return 0;
+ u = hashmap_get(m->users, UID_TO_PTR(uid));
+ if (!u) {
+ r = user_new(&u, m, uid, gid, name);
+ if (r < 0)
+ return r;
}
- u = user_new(m, uid, gid, name);
- if (!u)
- return -ENOMEM;
-
if (_user)
*_user = u;
@@ -156,7 +137,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_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);
}
@@ -192,61 +173,18 @@ int manager_add_button(Manager *m, const char *name, Button **_button) {
assert(name);
b = hashmap_get(m->buttons, name);
- if (b) {
- if (_button)
- *_button = b;
-
- return 0;
+ if (!b) {
+ b = button_new(m, name);
+ if (!b)
+ return -ENOMEM;
}
- b = button_new(m, name);
- if (!b)
- return -ENOMEM;
-
if (_button)
*_button = b;
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;
@@ -276,9 +214,11 @@ int manager_process_seat_device(Manager *m, struct udev_device *d) {
return 0;
}
- /* ignore non-master devices for unknown seats */
+ seat = hashmap_get(m->seats, sn);
master = udev_device_has_tag(d, "master-of-seat");
- if (!master && !(seat = hashmap_get(m->seats, sn)))
+
+ /* Ignore non-master devices for unknown seats */
+ if (!master && !seat)
return 0;
r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
@@ -336,31 +276,50 @@ int manager_process_button_device(Manager *m, struct udev_device *d) {
}
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
+#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)
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 r;
+ return 0;
s = hashmap_get(m->session_units, unit);
+#else
+ log_debug_elogind("Searching session for PID %u", pid);
+ r = cg_pid_get_session(pid, &session_name);
+ if (r < 0)
+ return 0;
+
+ 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
if (!s)
return 0;
- *session = s;
+ if (session)
+ *session = s;
return 1;
}
int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
+#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);
@@ -369,27 +328,35 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
if (pid < 1)
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 r;
+ return 0;
u = hashmap_get(m->user_units, unit);
if (!u)
return 0;
*user = u;
+#else
+ r = manager_get_session_by_pid (m, pid, &s);
+ if (r <= 0)
+ return r;
+
+ *user = s->user;
+#endif // 0
return 1;
}
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);
- idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
+ idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
HASHMAP_FOREACH(s, m->sessions, i) {
dual_timestamp k;
@@ -424,21 +391,23 @@ bool manager_shall_kill(Manager *m, const char *user) {
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;
}
-static int vt_is_busy(int vtnr) {
+#if 0 /// UNNEEDED by elogind
+static int vt_is_busy(unsigned int vtnr) {
struct vt_stat vt_stat;
- int r = 0, fd;
+ int r = 0;
+ _cleanup_close_ int fd;
assert(vtnr >= 1);
@@ -457,24 +426,22 @@ static int vt_is_busy(int vtnr) {
else
r = !!(vt_stat.v_state & (1 << vtnr));
- close_nointr_nofail(fd);
-
return r;
}
-int manager_spawn_autovt(Manager *m, int vtnr) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *name = NULL;
+int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
+ _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;
assert(m);
assert(vtnr >= 1);
- if ((unsigned) vtnr > m->n_autovts &&
- (unsigned) vtnr != m->reserve_vt)
+ if (vtnr > m->n_autovts &&
+ vtnr != m->reserve_vt)
return 0;
- if ((unsigned) vtnr != m->reserve_vt) {
+ if (vtnr != m->reserve_vt) {
/* If this is the reserved TTY, we'll start the getty
* on it in any case, but otherwise only if it is not
* busy. */
@@ -486,14 +453,12 @@ int manager_spawn_autovt(Manager *m, int vtnr) {
return -EBUSY;
}
- if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0)
- return log_oom();
-
+ snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
+ "org.freedesktop.systemd.Manager",
"StartUnit",
&error,
NULL,
@@ -503,3 +468,120 @@ int manager_spawn_autovt(Manager *m, int vtnr) {
return r;
}
+#endif // 0
+
+static bool manager_is_docked(Manager *m) {
+ Iterator i;
+ Button *b;
+
+ HASHMAP_FOREACH(b, m->buttons, i)
+ if (b->docked)
+ return true;
+
+ return false;
+}
+
+static int manager_count_external_displays(Manager *m) {
+ _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
+ struct udev_list_entry *item = NULL, *first = NULL;
+ int r;
+ int n = 0;
+
+ e = udev_enumerate_new(m->udev);
+ if (!e)
+ return -ENOMEM;
+
+ r = udev_enumerate_add_match_subsystem(e, "drm");
+ if (r < 0)
+ return r;
+
+ r = udev_enumerate_scan_devices(e);
+ if (r < 0)
+ return r;
+
+ first = udev_enumerate_get_list_entry(e);
+ udev_list_entry_foreach(item, first) {
+ _cleanup_udev_device_unref_ struct udev_device *d = NULL;
+ struct udev_device *p;
+ 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)
+ return -ENOMEM;
+
+ p = udev_device_get_parent(d);
+ if (!p)
+ continue;
+
+ /* If the parent shares the same subsystem as the
+ * device we are looking at then it is a connector,
+ * which is what we are interested in. */
+ 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");
+ if (!streq_ptr(status, "disconnected"))
+ n++;
+ }
+
+ return n;
+}
+
+bool manager_is_docked_or_external_displays(Manager *m) {
+ int n;
+
+ /* If we are docked don't react to lid closing */
+ if (manager_is_docked(m)) {
+ log_debug("System is docked.");
+ return true;
+ }
+
+ /* If we have more than one display connected,
+ * assume that we are docked. */
+ n = manager_count_external_displays(m);
+ if (n < 0)
+ log_warning_errno(n, "Display counting failed: %m");
+ else if (n >= 1) {
+ log_debug("External (%i) displays connected.", n);
+ return true;
+ }
+
+ return false;
+}