logind-core.c revision 2eec67acbb00593e414549a7e5b35eb7dd776b1b
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
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 <fcntl.h>
#include <pwd.h>
#include "strv.h"
#include "cgroup-util.h"
#include "bus-util.h"
#include "bus-error.h"
#include "udev-util.h"
#include "logind.h"
Device *d;
assert(m);
if (d)
/* we support adding master-flags, but not removing them */
else {
if (!d)
return -ENOMEM;
}
if (_device)
*_device = d;
return 0;
}
Seat *s;
assert(m);
if (!s) {
if (!s)
return -ENOMEM;
}
if (_seat)
*_seat = s;
return 0;
}
Session *s;
assert(m);
if (!s) {
s = session_new(m, id);
if (!s)
return -ENOMEM;
}
if (_session)
*_session = s;
return 0;
}
User *u;
assert(m);
if (!u) {
if (!u)
return -ENOMEM;
}
if (_user)
*_user = u;
return 0;
}
int r;
assert(m);
if (r < 0)
return r;
}
struct passwd *p;
assert(m);
errno = 0;
if (!p)
}
Inhibitor *i;
assert(m);
if (i) {
if (_inhibitor)
*_inhibitor = i;
return 0;
}
i = inhibitor_new(m, id);
if (!i)
return -ENOMEM;
if (_inhibitor)
*_inhibitor = i;
return 0;
}
Button *b;
assert(m);
if (!b) {
b = button_new(m, name);
if (!b)
return -ENOMEM;
}
if (_button)
*_button = b;
return 0;
}
char *n;
int r;
assert(m);
return 0;
if (!n)
return -ENOMEM;
if (r < 0) {
free(n);
return r;
}
return 0;
}
Iterator i;
assert(m);
/* keep it if the name still owns a controller */
return;
}
int r;
assert(m);
if (!device)
return 0;
} else {
const char *sn;
bool master;
sn = "seat0";
if (!seat_name_is_valid(sn)) {
return 0;
}
/* Ignore non-master devices for unknown seats */
return 0;
if (r < 0)
return r;
if (!seat) {
if (r < 0) {
return r;
}
}
}
return 0;
}
Button *b;
int r;
assert(m);
if (!b)
return 0;
button_free(b);
} else {
const char *sn;
r = manager_add_button(m, udev_device_get_sysname(d), &b);
if (r < 0)
return r;
sn = "seat0";
button_set_seat(b, sn);
button_open(b);
}
return 0;
}
Session *s;
int r;
assert(m);
if (pid < 1)
return -EINVAL;
if (r < 0)
return 0;
if (!s)
return 0;
*session = s;
return 1;
}
User *u;
int r;
assert(m);
if (pid < 1)
return -EINVAL;
if (r < 0)
return 0;
if (!u)
return 0;
*user = u;
return 1;
}
Session *s;
bool idle_hint;
dual_timestamp ts = { 0, 0 };
Iterator i;
assert(m);
HASHMAP_FOREACH(s, m->sessions, i) {
int ih;
ih = session_get_idle_hint(s, &k);
if (ih < 0)
return ih;
if (!ih) {
if (!idle_hint) {
ts = k;
} else {
idle_hint = false;
ts = k;
}
} else if (idle_hint) {
ts = k;
}
}
if (t)
*t = ts;
return idle_hint;
}
assert(m);
if (!m->kill_user_processes)
return false;
return false;
if (strv_isempty(m->kill_only_users))
return true;
}
static int vt_is_busy(unsigned int vtnr) {
int r = 0;
_cleanup_close_ int fd;
* we'd open the latter we'd open the foreground tty which
* we avoid this. Since tty1 is special and needs to be an
* explicitly loaded getty or DM this is safe. */
if (fd < 0)
return -errno;
r = -errno;
else
return r;
}
int r;
assert(m);
vtnr != m->reserve_vt)
return 0;
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. */
r = vt_is_busy(vtnr);
if (r < 0)
return r;
else if (r > 0)
return -EBUSY;
}
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
&error,
NULL,
if (r < 0)
return r;
}
bool manager_is_docked(Manager *m) {
Iterator i;
Button *b;
HASHMAP_FOREACH(b, m->buttons, i)
if (b->docked)
return true;
return false;
}
int manager_count_displays(Manager *m) {
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;
struct udev_device *p;
const char *status;
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. */
continue;
/* We count any connector which is not explicitly
* "disconnected" as connected. */
n++;
}
return n;
}
bool manager_is_docked_or_multiple_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_displays(m);
if (n < 0)
log_warning_errno(n, "Display counting failed: %m");
else if (n > 1) {
log_debug("Multiple (%i) displays connected.", n);
return true;
}
return false;
}