#include "escape.h"
#include "fd-util.h"
#include "fileio.h"
-#include "formats-util.h"
+#include "format-util.h"
#include "io-util.h"
#include "logind-session.h"
#include "mkdir.h"
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
+#include "process-util.h"
#define RELEASE_USEC (20*USEC_PER_SEC)
s->manager = m;
s->fifo_fd = -1;
s->vtfd = -1;
+ s->audit_id = AUDIT_SESSION_INVALID;
return s;
}
LIST_PREPEND(sessions_by_user, u->sessions, s);
}
+static void session_save_devices(Session *s, FILE *f) {
+ SessionDevice *sd;
+ Iterator i;
+
+ if (!hashmap_isempty(s->devices)) {
+ fprintf(f, "DEVICES=");
+ HASHMAP_FOREACH(sd, s->devices, i)
+ fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev));
+ fprintf(f, "\n");
+ }
+}
+
int session_save(Session *s) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
if (!s->vtnr)
fprintf(f, "POSITION=%u\n", s->position);
- if (s->leader > 0)
+ if (pid_is_valid(s->leader))
fprintf(f, "LEADER="PID_FMT"\n", s->leader);
- if (s->audit_id > 0)
+ if (audit_session_is_valid(s->audit_id))
fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
if (dual_timestamp_is_set(&s->timestamp))
s->timestamp.realtime,
s->timestamp.monotonic);
- if (s->controller)
+ if (s->controller) {
fprintf(f, "CONTROLLER=%s\n", s->controller);
+ session_save_devices(s, f);
+ }
r = fflush_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
}
+static int session_load_devices(Session *s, const char *devices) {
+ const char *p;
+ int r = 0;
+
+ assert(s);
+
+ for (p = devices;;) {
+ _cleanup_free_ char *word = NULL;
+ SessionDevice *sd;
+ dev_t dev;
+ int k;
+
+ k = extract_first_word(&p, &word, NULL, 0);
+ if (k == 0)
+ break;
+ if (k < 0) {
+ r = k;
+ break;
+ }
+
+ k = parse_dev(word, &dev);
+ if (k < 0) {
+ r = k;
+ continue;
+ }
+
+ /* The file descriptors for loaded devices will be reattached later. */
+ k = session_device_new(s, dev, false, &sd);
+ if (k < 0)
+ r = k;
+ }
+
+ if (r < 0)
+ log_error_errno(r, "Loading session devices for session %s failed: %m", s->id);
+
+ return r;
+}
int session_load(Session *s) {
_cleanup_free_ char *remote = NULL,
*uid = NULL,
*realtime = NULL,
*monotonic = NULL,
- *controller = NULL;
+ *controller = NULL,
+ *active = NULL,
+ *devices = NULL;
int k, r;
"REALTIME", &realtime,
"MONOTONIC", &monotonic,
"CONTROLLER", &controller,
+ "ACTIVE", &active,
+ "DEVICES", &devices,
NULL);
if (r < 0)
}
if (leader) {
- k = parse_pid(leader, &s->leader);
- if (k >= 0)
- audit_session_from_pid(s->leader, &s->audit_id);
+ if (parse_pid(leader, &s->leader) >= 0)
+ (void) audit_session_from_pid(s->leader, &s->audit_id);
}
if (type) {
if (monotonic)
timestamp_deserialize(monotonic, &s->timestamp.monotonic);
+ if (active) {
+ k = parse_boolean(active);
+ if (k >= 0)
+ s->was_active = k;
+ }
+
if (controller) {
- if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
- session_set_controller(s, controller, false);
- else
+ if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
+ session_set_controller(s, controller, false, false);
+ session_load_devices(s, devices);
+ } else
session_restore_vt(s);
}
return r;
log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
- LOG_MESSAGE_ID(SD_MESSAGE_SESSION_START),
+ "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER="PID_FMT, s->leader,
/* Send signals */
session_send_signal(s, true);
- user_send_changed(s->user, "Sessions", "Display", NULL);
+ user_send_changed(s->user, "Display", NULL);
if (s->seat) {
if (s->seat->active == s)
- seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
- else
- seat_send_changed(s->seat, "Sessions", NULL);
+ seat_send_changed(s->seat, "ActiveSession", NULL);
}
return 0;
if (s->started)
log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
- LOG_MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
+ "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
"SESSION_ID=%s", s->id,
"USER_ID=%s", s->user->name,
"LEADER="PID_FMT, s->leader,
seat_set_active(s->seat, NULL);
seat_save(s->seat);
- seat_send_changed(s->seat, "Sessions", NULL);
}
user_save(s->user);
- user_send_changed(s->user, "Sessions", "Display", NULL);
+ user_send_changed(s->user, "Display", NULL);
return 0;
}
(void) ioctl(vt, KDSETMODE, KD_TEXT);
- if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
- kb = K_UNICODE;
- else
+ if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && parse_boolean(utf8) == 0)
kb = K_XLATE;
+ else
+ kb = K_UNICODE;
(void) ioctl(vt, KDSKBMODE, kb);
return 0;
}
-int session_set_controller(Session *s, const char *sender, bool force) {
+int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
_cleanup_free_ char *name = NULL;
int r;
* Note that we reset the VT on ReleaseControl() and if the controller
* exits.
* If logind crashes/restarts, we restore the controller during restart
- * or reset the VT in case it crashed/exited, too. */
- r = session_prepare_vt(s);
- if (r < 0) {
- s->track = sd_bus_track_unref(s->track);
- return r;
+ * (without preparing the VT since the controller has probably overridden
+ * VT state by now) or reset the VT in case it crashed/exited, too. */
+ if (prepare) {
+ r = session_prepare_vt(s);
+ if (r < 0) {
+ s->track = sd_bus_track_unref(s->track);
+ return r;
+ }
}
session_release_controller(s, true);