#include <errno.h>
#include <fcntl.h>
-#include <linux/vt.h>
#include <linux/kd.h>
+#include <linux/vt.h>
#include <signal.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "sd-messages.h"
-#include "util.h"
-#include "mkdir.h"
-#include "path-util.h"
-#include "fileio.h"
+
#include "audit.h"
-#include "bus-util.h"
#include "bus-error.h"
-#include "logind-session.h"
+#include "bus-util.h"
+#include "escape.h"
+#include "fd-util.h"
+#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
+#include "io-util.h"
+#include "logind-session.h"
+#include "mkdir.h"
+#include "parse-util.h"
+#include "path-util.h"
#include "terminal-util.h"
+#include "user-util.h"
+#include "util.h"
#define RELEASE_USEC (20*USEC_PER_SEC)
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+ if (s->seat)
+ seat_evict_position(s->seat, s);
+
/* We are going down, don't care about FIFOs anymore */
session_remove_fifo(s);
}
int session_finalize(Session *s) {
- int r = 0;
SessionDevice *sd;
assert(s);
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+ if (s->seat)
+ seat_evict_position(s->seat, s);
+
/* Kill session devices */
while ((sd = hashmap_first(s->devices)))
session_device_free(sd);
- unlink(s->state_file);
+ (void) unlink(s->state_file);
session_add_to_gc_queue(s);
user_add_to_gc_queue(s->user);
user_save(s->user);
user_send_changed(s->user, "Sessions", "Display", NULL);
- return r;
+ return 0;
}
static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
if (s->fifo_path) {
unlink(s->fifo_path);
- free(s->fifo_path);
- s->fifo_path = NULL;
+ s->fifo_path = mfree(s->fifo_path);
}
}
return s->vtfd;
sprintf(path, "/dev/tty%u", s->vtnr);
- s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
+ s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
if (s->vtfd < 0)
return log_error_errno(errno, "cannot open VT %s of session %s: %m", path, s->id);
r = fchown(vt, s->user->uid, -1);
if (r < 0) {
- r = -errno;
- log_error_errno(errno, "Cannot change owner of /dev/tty%u: %m", s->vtnr);
+ r = log_error_errno(errno,
+ "Cannot change owner of /dev/tty%u: %m",
+ s->vtnr);
goto error;
}
r = ioctl(vt, KDSKBMODE, K_OFF);
if (r < 0) {
- r = -errno;
- log_error_errno(errno, "Cannot set K_OFF on /dev/tty%u: %m", s->vtnr);
+ r = log_error_errno(errno,
+ "Cannot set K_OFF on /dev/tty%u: %m",
+ s->vtnr);
goto error;
}
r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
if (r < 0) {
- r = -errno;
- log_error_errno(errno, "Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr);
+ r = log_error_errno(errno,
+ "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
+ s->vtnr);
goto error;
}
mode.acqsig = SIGRTMIN + 1;
r = ioctl(vt, VT_SETMODE, &mode);
if (r < 0) {
- r = -errno;
- log_error_errno(errno, "Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr);
+ r = log_error_errno(errno,
+ "Cannot set VT_PROCESS on /dev/tty%u: %m",
+ s->vtnr);
goto error;
}
}
void session_restore_vt(Session *s) {
+
+ static const struct vt_mode mode = {
+ .mode = VT_AUTO,
+ };
+
_cleanup_free_ char *utf8 = NULL;
- int vt, kb = K_XLATE;
- struct vt_mode mode = { 0 };
+ int vt, kb, old_fd;
+
+ /* We need to get a fresh handle to the virtual terminal,
+ * since the old file-descriptor is potentially in a hung-up
+ * state after the controlling process exited; we do a
+ * little dance to avoid having the terminal be available
+ * for reuse before we've cleaned it up.
+ */
+ old_fd = s->vtfd;
+ s->vtfd = -1;
vt = session_open_vt(s);
+ safe_close(old_fd);
+
if (vt < 0)
return;
if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
kb = K_UNICODE;
+ else
+ kb = K_XLATE;
(void) ioctl(vt, KDSKBMODE, kb);
- mode.mode = VT_AUTO;
(void) ioctl(vt, VT_SETMODE, &mode);
-
- fchown(vt, 0, -1);
+ (void) fchown(vt, 0, (gid_t) -1);
s->vtfd = safe_close(s->vtfd);
}
session_device_free(sd);
s->controller = NULL;
- manager_drop_busname(s->manager, name);
+ s->track = sd_bus_track_unref(s->track);
+}
+
+static int on_bus_track(sd_bus_track *track, void *userdata) {
+ Session *s = userdata;
+
+ assert(track);
+ assert(s);
+
+ session_drop_controller(s);
+
+ return 0;
}
int session_set_controller(Session *s, const char *sender, bool force) {
if (!name)
return -ENOMEM;
- r = manager_watch_busname(s->manager, name);
- if (r)
+ s->track = sd_bus_track_unref(s->track);
+ r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_track_add_name(s->track, name);
+ if (r < 0)
return r;
/* When setting a session controller, we forcibly mute the VT and set
* or reset the VT in case it crashed/exited, too. */
r = session_prepare_vt(s);
if (r < 0) {
- manager_drop_busname(s->manager, name);
+ s->track = sd_bus_track_unref(s->track);
return r;
}
if (!s->controller)
return;
+ s->track = sd_bus_track_unref(s->track);
session_release_controller(s, false);
session_save(s);
session_restore_vt(s);