#include "audit-util.h"
#include "bus-error.h"
#include "bus-util.h"
+#include "env-file.h"
#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "serialize.h"
#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
#define RELEASE_USEC (20*USEC_PER_SEC)
static void session_remove_fifo(Session *s);
+static void session_restore_vt(Session *s);
int session_new(Session **ret, Manager *m, const char *id) {
_cleanup_(session_freep) Session *s = NULL;
.fifo_fd = -1,
.vtfd = -1,
.audit_id = AUDIT_SESSION_INVALID,
+ .tty_validity = _TTY_VALIDITY_INVALID,
};
s->state_file = strappend("/run/systemd/sessions/", id);
if (s->user->display == s)
s->user->display = NULL;
+
+ user_update_last_session_timer(s->user);
}
if (s->seat) {
free(s->scope);
}
+ if (pid_is_valid(s->leader))
+ (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s);
+
free(s->scope_job);
sd_bus_message_unref(s->create_message);
s->user = u;
LIST_PREPEND(sessions_by_user, u->sessions, s);
+
+ user_update_last_session_timer(u);
+}
+
+int session_set_leader(Session *s, pid_t pid) {
+ int r;
+
+ assert(s);
+
+ if (!pid_is_valid(pid))
+ return -EINVAL;
+
+ if (s->leader == pid)
+ return 0;
+
+ r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pid), s);
+ if (r < 0)
+ return r;
+
+ if (pid_is_valid(s->leader))
+ (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s);
+
+ s->leader = pid;
+ (void) audit_session_from_pid(pid, &s->audit_id);
+
+ return 1;
}
static void session_save_devices(Session *s, FILE *f) {
if (s->tty)
fprintf(f, "TTY=%s\n", s->tty);
+ if (s->tty_validity >= 0)
+ fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity));
+
if (s->display)
fprintf(f, "DISPLAY=%s\n", s->display);
int session_load(Session *s) {
_cleanup_free_ char *remote = NULL,
*seat = NULL,
+ *tty_validity = NULL,
*vtnr = NULL,
*state = NULL,
*position = NULL,
assert(s);
- r = parse_env_file(NULL, s->state_file, NEWLINE,
+ r = parse_env_file(NULL, s->state_file,
"REMOTE", &remote,
"SCOPE", &s->scope,
"SCOPE_JOB", &s->scope_job,
"FIFO", &s->fifo_path,
"SEAT", &seat,
"TTY", &s->tty,
+ "TTY_VALIDITY", &tty_validity,
"DISPLAY", &s->display,
"REMOTE_HOST", &s->remote_host,
"REMOTE_USER", &s->remote_user,
"CONTROLLER", &controller,
"ACTIVE", &active,
"DEVICES", &devices,
- "IS_DISPLAY", &is_display,
- NULL);
+ "IS_DISPLAY", &is_display);
if (r < 0)
return log_error_errno(r, "Failed to read %s: %m", s->state_file);
uid_t u;
User *user;
- if (!uid) {
- log_error("UID not specified for session %s", s->id);
- return -ENOENT;
- }
+ if (!uid)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+ "UID not specified for session %s",
+ s->id);
r = parse_uid(uid, &u);
if (r < 0) {
}
user = hashmap_get(s->manager->users, UID_TO_PTR(u));
- if (!user) {
- log_error("User of session %s not known.", s->id);
- return -ENOENT;
- }
+ if (!user)
+ return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+ "User of session %s not known.",
+ s->id);
session_set_user(s, user);
}
s->vtnr = 0;
if (position && s->seat) {
- unsigned int npos;
+ unsigned npos;
safe_atou(position, &npos);
seat_claim_position(s->seat, s, npos);
}
+ if (tty_validity) {
+ TTYValidity v;
+
+ v = tty_validity_from_string(tty_validity);
+ if (v < 0)
+ log_debug("Failed to parse TTY validity: %s", tty_validity);
+ else
+ s->tty_validity = v;
+ }
+
if (leader) {
- if (parse_pid(leader, &s->leader) >= 0)
- (void) audit_session_from_pid(s->leader, &s->audit_id);
+ pid_t pid;
+
+ r = parse_pid(leader, &pid);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse leader PID of session: %s", leader);
+ else {
+ r = session_set_leader(s, pid);
+ if (r < 0)
+ log_warning_errno(r, "Failed to set session leader PID, ignoring: %m");
+ }
}
if (type) {
}
if (realtime)
- timestamp_deserialize(realtime, &s->timestamp.realtime);
+ (void) deserialize_usec(realtime, &s->timestamp.realtime);
if (monotonic)
- timestamp_deserialize(monotonic, &s->timestamp.monotonic);
+ (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
if (active) {
k = parse_boolean(active);
}
int session_activate(Session *s) {
- unsigned int num_pending;
+ unsigned num_pending;
assert(s);
assert(s->user);
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 */
+ s->user->home,
properties,
error,
&s->scope_job);
/* For sessions with a leader but no explicitly configured
* tty, let's check the controlling tty of the leader */
- if (s->leader > 0) {
+ if (pid_is_valid(s->leader)) {
r = get_process_ctty_atime(s->leader, &atime);
if (r >= 0)
goto found_atime;
return r;
}
-void session_restore_vt(Session *s) {
-
- static const struct vt_mode mode = {
- .mode = VT_AUTO,
- };
-
- int vt, old_fd;
+static void session_restore_vt(Session *s) {
+ int r, vt, old_fd;
/* We need to get a fresh handle to the virtual terminal,
* since the old file-descriptor is potentially in a hung-up
if (vt < 0)
return;
- (void) ioctl(vt, KDSETMODE, KD_TEXT);
-
- (void) vt_reset_keyboard(vt);
-
- (void) ioctl(vt, VT_SETMODE, &mode);
- (void) fchown(vt, 0, (gid_t) -1);
+ r = vt_restore(vt);
+ if (r < 0)
+ log_warning_errno(r, "Failed to restore VT, ignoring: %m");
s->vtfd = safe_close(s->vtfd);
}
return;
session_device_pause_all(s);
- r = ioctl(s->vtfd, VT_RELDISP, 1);
+ r = vt_release(s->vtfd, false);
if (r < 0)
- log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
+ log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
}
bool session_is_controller(Session *s, const char *sender) {
};
DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
+
+static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
+ [TTY_FROM_PAM] = "from-pam",
+ [TTY_FROM_UTMP] = "from-utmp",
+ [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);