#include <linux/kd.h>
#include <linux/vt.h>
#include <signal.h>
-#include <stdio_ext.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
#include <unistd.h>
#include "sd-messages.h"
#include "fileio.h"
#include "format-util.h"
#include "io-util.h"
+#include "logind-dbus.h"
+#include "logind-seat-dbus.h"
+#include "logind-session-dbus.h"
#include "logind-session.h"
+#include "logind-user-dbus.h"
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
if (r < 0)
goto fail;
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod(fileno(f), 0644);
fprintf(f,
s->leader,
s->user->slice,
description,
- STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
- STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
+ /* These two have StopWhenUnneeded= set, hence add a dep towards them */
+ STRV_MAKE(s->user->runtime_dir_service,
+ s->user->service),
+ /* And order us after some more */
+ STRV_MAKE("systemd-logind.service",
+ "systemd-user-sessions.service",
+ s->user->runtime_dir_service,
+ s->user->service),
s->user->home,
properties,
error,
&s->scope_job);
if (r < 0)
- return log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(error, r));
+ return log_error_errno(r, "Failed to start session scope %s: %s",
+ scope, bus_error_message(error, r));
s->scope = TAKE_PTR(scope);
}
- if (s->scope)
- (void) hashmap_put(s->manager->session_units, s->scope, s);
+ (void) hashmap_put(s->manager->session_units, s->scope, s);
return 0;
}
}
static void session_restore_vt(Session *s) {
- pid_t pid;
- int r;
-
- if (s->vtnr < 1)
- return;
-
- if (s->vtfd < 0)
- return;
+ int r, vt, old_fd;
- /* The virtual terminal can potentially be entering in hung-up state at any time
- * depending on when the controlling process exits.
- *
- * If the controlling process exits while we're restoring the virtual terminal,
- * the VT will enter in hung-up state and we'll fail at restoring it. To prevent
- * this case, we kick off the current controlling process (if any) in a child
- * process so logind doesn't play around with tty ownership.
- *
- * If the controlling process already exited, getting a fresh handle to the
- * virtual terminal reset the hung-up state. */
- r = safe_fork("(logind)", FORK_REOPEN_LOG|FORK_CLOSE_ALL_FDS|FORK_RESET_SIGNALS|FORK_WAIT|FORK_LOG, &pid);
- if (r == 0) {
- char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
- int vt;
-
- /* We must be a session leader in order to become the controlling process. */
- pid = setsid();
- if (pid < 0) {
- log_error_errno(errno, "Failed to become session leader: %m");
- _exit(EXIT_FAILURE);
- }
+ /* 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 = TAKE_FD(s->vtfd);
- sprintf(path, "/dev/tty%u", s->vtnr);
- vt = acquire_terminal(path, ACQUIRE_TERMINAL_FORCE, USEC_INFINITY);
- if (vt < 0) {
- log_error_errno(vt, "Cannot acquire VT %s of session %s: %m", path, s->id);
- _exit(EXIT_FAILURE);
- }
+ vt = session_open_vt(s);
+ safe_close(old_fd);
- r = vt_restore(vt);
- if (r < 0)
- log_warning_errno(r, "Failed to restore VT, ignoring: %m");
+ if (vt < 0)
+ return;
- /* Give up and release the controlling terminal. */
- safe_close(vt);
- _exit(EXIT_SUCCESS);
- }
+ r = vt_restore(vt);
+ if (r < 0)
+ log_warning_errno(r, "Failed to restore VT, ignoring: %m");
- /* Close the fd in any cases. */
s->vtfd = safe_close(s->vtfd);
}