Bug Summary

File:build-scan/../src/login/logind-session.c
Warning:line 1193, column 9
Value stored to 'name' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name logind-session.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/login/liblogind-core.a.p -I src/login -I ../src/login -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/login/logind-session.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <fcntl.h>
5#include <linux1/kd.h>
6#include <linux1/vt.h>
7#include <signal.h>
8#include <string.h>
9#include <sys/ioctl.h>
10#include <unistd.h>
11
12#include "sd-messages.h"
13
14#include "alloc-util.h"
15#include "audit-util.h"
16#include "bus-error.h"
17#include "bus-util.h"
18#include "escape.h"
19#include "fd-util.h"
20#include "fileio.h"
21#include "format-util.h"
22#include "io-util.h"
23#include "logind-session.h"
24#include "mkdir.h"
25#include "parse-util.h"
26#include "path-util.h"
27#include "string-table.h"
28#include "terminal-util.h"
29#include "user-util.h"
30#include "util.h"
31#include "process-util.h"
32
33#define RELEASE_USEC(20*((usec_t) 1000000ULL)) (20*USEC_PER_SEC((usec_t) 1000000ULL))
34
35static void session_remove_fifo(Session *s);
36
37Session* session_new(Manager *m, const char *id) {
38 Session *s;
39
40 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/login/logind-session.c", 40
, __PRETTY_FUNCTION__); } while (0)
;
41 assert(id)do { if ((__builtin_expect(!!(!(id)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("id"), "../src/login/logind-session.c", 41
, __PRETTY_FUNCTION__); } while (0)
;
42 assert(session_id_valid(id))do { if ((__builtin_expect(!!(!(session_id_valid(id))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("session_id_valid(id)"), "../src/login/logind-session.c"
, 42, __PRETTY_FUNCTION__); } while (0)
;
43
44 s = new0(Session, 1)((Session*) calloc((1), sizeof(Session)));
45 if (!s)
46 return NULL((void*)0);
47
48 s->state_file = strappend("/run/systemd/sessions/", id);
49 if (!s->state_file)
50 return mfree(s);
51
52 s->devices = hashmap_new(&devt_hash_ops)internal_hashmap_new(&uint64_hash_ops );
53 if (!s->devices) {
54 free(s->state_file);
55 return mfree(s);
56 }
57
58 s->id = basename(s->state_file);
59
60 if (hashmap_put(m->sessions, s->id, s) < 0) {
61 hashmap_free(s->devices);
62 free(s->state_file);
63 return mfree(s);
64 }
65
66 s->manager = m;
67 s->fifo_fd = -1;
68 s->vtfd = -1;
69 s->audit_id = AUDIT_SESSION_INVALID((uint32_t) -1);
70
71 return s;
72}
73
74void session_free(Session *s) {
75 SessionDevice *sd;
76
77 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 77
, __PRETTY_FUNCTION__); } while (0)
;
78
79 if (s->in_gc_queue)
80 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s)do { typeof(*(s->manager->session_gc_queue)) **_head = &
(s->manager->session_gc_queue), *_item = (s); do { if (
(__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_item"), "../src/login/logind-session.c", 80, __PRETTY_FUNCTION__
); } while (0); if (_item->gc_queue_next) _item->gc_queue_next
->gc_queue_prev = _item->gc_queue_prev; if (_item->gc_queue_prev
) _item->gc_queue_prev->gc_queue_next = _item->gc_queue_next
; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0)
)) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item"
), "../src/login/logind-session.c", 80, __PRETTY_FUNCTION__);
} while (0); *_head = _item->gc_queue_next; } _item->gc_queue_next
= _item->gc_queue_prev = ((void*)0); } while (0)
;
81
82 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
83
84 session_remove_fifo(s);
85
86 session_drop_controller(s);
87
88 while ((sd = hashmap_first(s->devices)))
89 session_device_free(sd);
90
91 hashmap_free(s->devices);
92
93 if (s->user) {
94 LIST_REMOVE(sessions_by_user, s->user->sessions, s)do { typeof(*(s->user->sessions)) **_head = &(s->
user->sessions), *_item = (s); do { if ((__builtin_expect(
!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"_item"), "../src/login/logind-session.c", 94, __PRETTY_FUNCTION__
); } while (0); if (_item->sessions_by_user_next) _item->
sessions_by_user_next->sessions_by_user_prev = _item->sessions_by_user_prev
; if (_item->sessions_by_user_prev) _item->sessions_by_user_prev
->sessions_by_user_next = _item->sessions_by_user_next;
else { do { if ((__builtin_expect(!!(!(*_head == _item)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item"
), "../src/login/logind-session.c", 94, __PRETTY_FUNCTION__);
} while (0); *_head = _item->sessions_by_user_next; } _item
->sessions_by_user_next = _item->sessions_by_user_prev =
((void*)0); } while (0)
;
95
96 if (s->user->display == s)
97 s->user->display = NULL((void*)0);
98 }
99
100 if (s->seat) {
101 if (s->seat->active == s)
102 s->seat->active = NULL((void*)0);
103 if (s->seat->pending_switch == s)
104 s->seat->pending_switch = NULL((void*)0);
105
106 seat_evict_position(s->seat, s);
107 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s)do { typeof(*(s->seat->sessions)) **_head = &(s->
seat->sessions), *_item = (s); do { if ((__builtin_expect(
!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"_item"), "../src/login/logind-session.c", 107, __PRETTY_FUNCTION__
); } while (0); if (_item->sessions_by_seat_next) _item->
sessions_by_seat_next->sessions_by_seat_prev = _item->sessions_by_seat_prev
; if (_item->sessions_by_seat_prev) _item->sessions_by_seat_prev
->sessions_by_seat_next = _item->sessions_by_seat_next;
else { do { if ((__builtin_expect(!!(!(*_head == _item)),0))
) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item"
), "../src/login/logind-session.c", 107, __PRETTY_FUNCTION__)
; } while (0); *_head = _item->sessions_by_seat_next; } _item
->sessions_by_seat_next = _item->sessions_by_seat_prev =
((void*)0); } while (0)
;
108 }
109
110 if (s->scope) {
111 hashmap_remove(s->manager->session_units, s->scope);
112 free(s->scope);
113 }
114
115 free(s->scope_job);
116
117 sd_bus_message_unref(s->create_message);
118
119 free(s->tty);
120 free(s->display);
121 free(s->remote_host);
122 free(s->remote_user);
123 free(s->service);
124 free(s->desktop);
125
126 hashmap_remove(s->manager->sessions, s->id);
127
128 free(s->state_file);
129 free(s);
130}
131
132void session_set_user(Session *s, User *u) {
133 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 133
, __PRETTY_FUNCTION__); } while (0)
;
134 assert(!s->user)do { if ((__builtin_expect(!!(!(!s->user)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("!s->user"), "../src/login/logind-session.c"
, 134, __PRETTY_FUNCTION__); } while (0)
;
135
136 s->user = u;
137 LIST_PREPEND(sessions_by_user, u->sessions, s)do { typeof(*(u->sessions)) **_head = &(u->sessions
), *_item = (s); do { if ((__builtin_expect(!!(!(_item)),0)))
log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/login/logind-session.c"
, 137, __PRETTY_FUNCTION__); } while (0); if ((_item->sessions_by_user_next
= *_head)) _item->sessions_by_user_next->sessions_by_user_prev
= _item; _item->sessions_by_user_prev = ((void*)0); *_head
= _item; } while (0)
;
138}
139
140static void session_save_devices(Session *s, FILE *f) {
141 SessionDevice *sd;
142 Iterator i;
143
144 if (!hashmap_isempty(s->devices)) {
145 fprintf(f, "DEVICES=");
146 HASHMAP_FOREACH(sd, s->devices, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); hashmap_iterate((s->devices), &
(i), (void**)&(sd), ((void*)0)); )
147 fprintf(f, "%u:%u ", major(sd->dev)gnu_dev_major (sd->dev), minor(sd->dev)gnu_dev_minor (sd->dev));
148 fprintf(f, "\n");
149 }
150}
151
152int session_save(Session *s) {
153 _cleanup_free___attribute__((cleanup(freep))) char *temp_path = NULL((void*)0);
154 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
155 int r = 0;
156
157 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 157
, __PRETTY_FUNCTION__); } while (0)
;
158
159 if (!s->user)
160 return -ESTALE116;
161
162 if (!s->started)
163 return 0;
164
165 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
166 if (r < 0)
167 goto fail;
168
169 r = fopen_temporary(s->state_file, &f, &temp_path);
170 if (r < 0)
171 goto fail;
172
173 assert(s->user)do { if ((__builtin_expect(!!(!(s->user)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s->user"), "../src/login/logind-session.c"
, 173, __PRETTY_FUNCTION__); } while (0)
;
174
175 fchmod(fileno(f), 0644);
176
177 fprintf(f,
178 "# This is private data. Do not parse.\n"
179 "UID="UID_FMT"%" "u""\n"
180 "USER=%s\n"
181 "ACTIVE=%i\n"
182 "STATE=%s\n"
183 "REMOTE=%i\n",
184 s->user->uid,
185 s->user->name,
186 session_is_active(s),
187 session_state_to_string(session_get_state(s)),
188 s->remote);
189
190 if (s->type >= 0)
191 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
192
193 if (s->class >= 0)
194 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
195
196 if (s->scope)
197 fprintf(f, "SCOPE=%s\n", s->scope);
198 if (s->scope_job)
199 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
200
201 if (s->fifo_path)
202 fprintf(f, "FIFO=%s\n", s->fifo_path);
203
204 if (s->seat)
205 fprintf(f, "SEAT=%s\n", s->seat->id);
206
207 if (s->tty)
208 fprintf(f, "TTY=%s\n", s->tty);
209
210 if (s->display)
211 fprintf(f, "DISPLAY=%s\n", s->display);
212
213 if (s->remote_host) {
214 _cleanup_free___attribute__((cleanup(freep))) char *escaped;
215
216 escaped = cescape(s->remote_host);
217 if (!escaped) {
218 r = -ENOMEM12;
219 goto fail;
220 }
221
222 fprintf(f, "REMOTE_HOST=%s\n", escaped);
223 }
224
225 if (s->remote_user) {
226 _cleanup_free___attribute__((cleanup(freep))) char *escaped;
227
228 escaped = cescape(s->remote_user);
229 if (!escaped) {
230 r = -ENOMEM12;
231 goto fail;
232 }
233
234 fprintf(f, "REMOTE_USER=%s\n", escaped);
235 }
236
237 if (s->service) {
238 _cleanup_free___attribute__((cleanup(freep))) char *escaped;
239
240 escaped = cescape(s->service);
241 if (!escaped) {
242 r = -ENOMEM12;
243 goto fail;
244 }
245
246 fprintf(f, "SERVICE=%s\n", escaped);
247 }
248
249 if (s->desktop) {
250 _cleanup_free___attribute__((cleanup(freep))) char *escaped;
251
252 escaped = cescape(s->desktop);
253 if (!escaped) {
254 r = -ENOMEM12;
255 goto fail;
256 }
257
258 fprintf(f, "DESKTOP=%s\n", escaped);
259 }
260
261 if (s->seat && seat_has_vts(s->seat))
262 fprintf(f, "VTNR=%u\n", s->vtnr);
263
264 if (!s->vtnr)
265 fprintf(f, "POSITION=%u\n", s->position);
266
267 if (pid_is_valid(s->leader))
268 fprintf(f, "LEADER="PID_FMT"%" "i""\n", s->leader);
269
270 if (audit_session_is_valid(s->audit_id))
271 fprintf(f, "AUDIT=%"PRIu32"u""\n", s->audit_id);
272
273 if (dual_timestamp_is_set(&s->timestamp))
274 fprintf(f,
275 "REALTIME="USEC_FMT"%" "l" "u""\n"
276 "MONOTONIC="USEC_FMT"%" "l" "u""\n",
277 s->timestamp.realtime,
278 s->timestamp.monotonic);
279
280 if (s->controller) {
281 fprintf(f, "CONTROLLER=%s\n", s->controller);
282 session_save_devices(s, f);
283 }
284
285 r = fflush_and_check(f);
286 if (r < 0)
287 goto fail;
288
289 if (rename(temp_path, s->state_file) < 0) {
290 r = -errno(*__errno_location ());
291 goto fail;
292 }
293
294 return 0;
295
296fail:
297 (void) unlink(s->state_file);
298
299 if (temp_path)
300 (void) unlink(temp_path);
301
302 return log_error_errno(r, "Failed to save session data %s: %m", s->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 302, __func__, "Failed to save session data %s: %m"
, s->state_file) : -abs(_e); })
;
303}
304
305static int session_load_devices(Session *s, const char *devices) {
306 const char *p;
307 int r = 0;
308
309 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 309
, __PRETTY_FUNCTION__); } while (0)
;
310
311 for (p = devices;;) {
312 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0);
313 SessionDevice *sd;
314 dev_t dev;
315 int k;
316
317 k = extract_first_word(&p, &word, NULL((void*)0), 0);
318 if (k == 0)
319 break;
320 if (k < 0) {
321 r = k;
322 break;
323 }
324
325 k = parse_dev(word, &dev);
326 if (k < 0) {
327 r = k;
328 continue;
329 }
330
331 /* The file descriptors for loaded devices will be reattached later. */
332 k = session_device_new(s, dev, false0, &sd);
333 if (k < 0)
334 r = k;
335 }
336
337 if (r < 0)
338 log_error_errno(r, "Loading session devices for session %s failed: %m", s->id)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 338, __func__, "Loading session devices for session %s failed: %m"
, s->id) : -abs(_e); })
;
339
340 return r;
341}
342
343int session_load(Session *s) {
344 _cleanup_free___attribute__((cleanup(freep))) char *remote = NULL((void*)0),
345 *seat = NULL((void*)0),
346 *vtnr = NULL((void*)0),
347 *state = NULL((void*)0),
348 *position = NULL((void*)0),
349 *leader = NULL((void*)0),
350 *type = NULL((void*)0),
351 *class = NULL((void*)0),
352 *uid = NULL((void*)0),
353 *realtime = NULL((void*)0),
354 *monotonic = NULL((void*)0),
355 *controller = NULL((void*)0),
356 *active = NULL((void*)0),
357 *devices = NULL((void*)0);
358
359 int k, r;
360
361 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 361
, __PRETTY_FUNCTION__); } while (0)
;
362
363 r = parse_env_file(NULL((void*)0), s->state_file, NEWLINE"\n\r",
364 "REMOTE", &remote,
365 "SCOPE", &s->scope,
366 "SCOPE_JOB", &s->scope_job,
367 "FIFO", &s->fifo_path,
368 "SEAT", &seat,
369 "TTY", &s->tty,
370 "DISPLAY", &s->display,
371 "REMOTE_HOST", &s->remote_host,
372 "REMOTE_USER", &s->remote_user,
373 "SERVICE", &s->service,
374 "DESKTOP", &s->desktop,
375 "VTNR", &vtnr,
376 "STATE", &state,
377 "POSITION", &position,
378 "LEADER", &leader,
379 "TYPE", &type,
380 "CLASS", &class,
381 "UID", &uid,
382 "REALTIME", &realtime,
383 "MONOTONIC", &monotonic,
384 "CONTROLLER", &controller,
385 "ACTIVE", &active,
386 "DEVICES", &devices,
387 NULL((void*)0));
388
389 if (r < 0)
390 return log_error_errno(r, "Failed to read %s: %m", s->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 390, __func__, "Failed to read %s: %m"
, s->state_file) : -abs(_e); })
;
391
392 if (!s->user) {
393 uid_t u;
394 User *user;
395
396 if (!uid) {
397 log_error("UID not specified for session %s", s->id)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 397, __func__, "UID not specified for session %s"
, s->id) : -abs(_e); })
;
398 return -ENOENT2;
399 }
400
401 r = parse_uid(uid, &u);
402 if (r < 0) {
403 log_error("Failed to parse UID value %s for session %s.", uid, s->id)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 403, __func__, "Failed to parse UID value %s for session %s."
, uid, s->id) : -abs(_e); })
;
404 return r;
405 }
406
407 user = hashmap_get(s->manager->users, UID_TO_PTR(u)((void*) (((uintptr_t) (u))+1)));
408 if (!user) {
409 log_error("User of session %s not known.", s->id)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 409, __func__, "User of session %s not known."
, s->id) : -abs(_e); })
;
410 return -ENOENT2;
411 }
412
413 session_set_user(s, user);
414 }
415
416 if (remote) {
417 k = parse_boolean(remote);
418 if (k >= 0)
419 s->remote = k;
420 }
421
422 if (vtnr)
423 safe_atou(vtnr, &s->vtnr);
424
425 if (seat && !s->seat) {
426 Seat *o;
427
428 o = hashmap_get(s->manager->seats, seat);
429 if (o)
430 r = seat_attach_session(o, s);
431 if (!o || r < 0)
432 log_error("Cannot attach session %s to seat %s", s->id, seat)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 432, __func__, "Cannot attach session %s to seat %s"
, s->id, seat) : -abs(_e); })
;
433 }
434
435 if (!s->seat || !seat_has_vts(s->seat))
436 s->vtnr = 0;
437
438 if (position && s->seat) {
439 unsigned int npos;
440
441 safe_atou(position, &npos);
442 seat_claim_position(s->seat, s, npos);
443 }
444
445 if (leader) {
446 if (parse_pid(leader, &s->leader) >= 0)
447 (void) audit_session_from_pid(s->leader, &s->audit_id);
448 }
449
450 if (type) {
451 SessionType t;
452
453 t = session_type_from_string(type);
454 if (t >= 0)
455 s->type = t;
456 }
457
458 if (class) {
459 SessionClass c;
460
461 c = session_class_from_string(class);
462 if (c >= 0)
463 s->class = c;
464 }
465
466 if (state && streq(state, "closing")(strcmp((state),("closing")) == 0))
467 s->stopping = true1;
468
469 if (s->fifo_path) {
470 int fd;
471
472 /* If we open an unopened pipe for reading we will not
473 get an EOF. to trigger an EOF we hence open it for
474 writing, but close it right away which then will
475 trigger the EOF. This will happen immediately if no
476 other process has the FIFO open for writing, i. e.
477 when the session died before logind (re)started. */
478
479 fd = session_create_fifo(s);
480 safe_close(fd);
481 }
482
483 if (realtime)
484 timestamp_deserialize(realtime, &s->timestamp.realtime);
485 if (monotonic)
486 timestamp_deserialize(monotonic, &s->timestamp.monotonic);
487
488 if (active) {
489 k = parse_boolean(active);
490 if (k >= 0)
491 s->was_active = k;
492 }
493
494 if (controller) {
495 if (bus_name_has_owner(s->manager->bus, controller, NULL((void*)0)) > 0) {
496 session_set_controller(s, controller, false0, false0);
497 session_load_devices(s, devices);
498 } else
499 session_restore_vt(s);
500 }
501
502 return r;
503}
504
505int session_activate(Session *s) {
506 unsigned int num_pending;
507
508 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 508
, __PRETTY_FUNCTION__); } while (0)
;
509 assert(s->user)do { if ((__builtin_expect(!!(!(s->user)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s->user"), "../src/login/logind-session.c"
, 509, __PRETTY_FUNCTION__); } while (0)
;
510
511 if (!s->seat)
512 return -EOPNOTSUPP95;
513
514 if (s->seat->active == s)
515 return 0;
516
517 /* on seats with VTs, we let VTs manage session-switching */
518 if (seat_has_vts(s->seat)) {
519 if (!s->vtnr)
520 return -EOPNOTSUPP95;
521
522 return chvt(s->vtnr);
523 }
524
525 /* On seats without VTs, we implement session-switching in logind. We
526 * try to pause all session-devices and wait until the session
527 * controller acknowledged them. Once all devices are asleep, we simply
528 * switch the active session and be done.
529 * We save the session we want to switch to in seat->pending_switch and
530 * seat_complete_switch() will perform the final switch. */
531
532 s->seat->pending_switch = s;
533
534 /* if no devices are running, immediately perform the session switch */
535 num_pending = session_device_try_pause_all(s);
536 if (!num_pending)
537 seat_complete_switch(s->seat);
538
539 return 0;
540}
541
542static int session_start_scope(Session *s, sd_bus_message *properties) {
543 int r;
544
545 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 545
, __PRETTY_FUNCTION__); } while (0)
;
546 assert(s->user)do { if ((__builtin_expect(!!(!(s->user)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s->user"), "../src/login/logind-session.c"
, 546, __PRETTY_FUNCTION__); } while (0)
;
547
548 if (!s->scope) {
549 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
550 char *scope, *job = NULL((void*)0);
551 const char *description;
552
553 scope = strjoin("session-", s->id, ".scope")strjoin_real(("session-"), s->id, ".scope", ((void*)0));
554 if (!scope)
555 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/login/logind-session.c"
, 555, __func__)
;
556
557 description = strjoina("Session ", s->id, " of user ", s->user->name)({ const char *_appendees_[] = { "Session ", s->id, " of user "
, s->user->name }; char *_d_, *_p_; size_t _len_ = 0; size_t
_i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _len_ += strlen
(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1);
for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr(
!__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
558
559 r = manager_start_scope(
560 s->manager,
561 scope,
562 s->leader,
563 s->user->slice,
564 description,
565 "systemd-logind.service",
566 "systemd-user-sessions.service",
567 properties,
568 &error,
569 &job);
570 if (r < 0) {
571 log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 571, __func__, "Failed to start session scope %s: %s"
, scope, bus_error_message(&error, r)) : -abs(_e); })
;
572 free(scope);
573 return r;
574 } else {
575 s->scope = scope;
576
577 free(s->scope_job);
578 s->scope_job = job;
579 }
580 }
581
582 if (s->scope)
583 (void) hashmap_put(s->manager->session_units, s->scope, s);
584
585 return 0;
586}
587
588int session_start(Session *s, sd_bus_message *properties) {
589 int r;
590
591 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 591
, __PRETTY_FUNCTION__); } while (0)
;
592
593 if (!s->user)
594 return -ESTALE116;
595
596 if (s->started)
597 return 0;
598
599 r = user_start(s->user);
600 if (r < 0)
601 return r;
602
603 /* Create cgroup */
604 r = session_start_scope(s, properties);
605 if (r < 0)
606 return r;
607
608 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 613, __func__, "MESSAGE_ID=" "8d" "45" "62" "0c" "1a" "43" "48"
"db" "b1" "74" "10" "da" "57" "c6" "0c" "66", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "New session %s of user %s.", s->
id, s->user->name, ((void*)0))
609 "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 613, __func__, "MESSAGE_ID=" "8d" "45" "62" "0c" "1a" "43" "48"
"db" "b1" "74" "10" "da" "57" "c6" "0c" "66", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "New session %s of user %s.", s->
id, s->user->name, ((void*)0))
610 "SESSION_ID=%s", s->id,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 613, __func__, "MESSAGE_ID=" "8d" "45" "62" "0c" "1a" "43" "48"
"db" "b1" "74" "10" "da" "57" "c6" "0c" "66", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "New session %s of user %s.", s->
id, s->user->name, ((void*)0))
611 "USER_ID=%s", s->user->name,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 613, __func__, "MESSAGE_ID=" "8d" "45" "62" "0c" "1a" "43" "48"
"db" "b1" "74" "10" "da" "57" "c6" "0c" "66", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "New session %s of user %s.", s->
id, s->user->name, ((void*)0))
612 "LEADER="PID_FMT, s->leader,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 613, __func__, "MESSAGE_ID=" "8d" "45" "62" "0c" "1a" "43" "48"
"db" "b1" "74" "10" "da" "57" "c6" "0c" "66", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "New session %s of user %s.", s->
id, s->user->name, ((void*)0))
613 LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 613, __func__, "MESSAGE_ID=" "8d" "45" "62" "0c" "1a" "43" "48"
"db" "b1" "74" "10" "da" "57" "c6" "0c" "66", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "New session %s of user %s.", s->
id, s->user->name, ((void*)0))
;
614
615 if (!dual_timestamp_is_set(&s->timestamp))
616 dual_timestamp_get(&s->timestamp);
617
618 if (s->seat)
619 seat_read_active_vt(s->seat);
620
621 s->started = true1;
622
623 user_elect_display(s->user);
624
625 /* Save data */
626 session_save(s);
627 user_save(s->user);
628 if (s->seat)
629 seat_save(s->seat);
630
631 /* Send signals */
632 session_send_signal(s, true1);
633 user_send_changed(s->user, "Display", NULL((void*)0));
634 if (s->seat) {
635 if (s->seat->active == s)
636 seat_send_changed(s->seat, "ActiveSession", NULL((void*)0));
637 }
638
639 return 0;
640}
641
642static int session_stop_scope(Session *s, bool_Bool force) {
643 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
644 int r;
645
646 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 646
, __PRETTY_FUNCTION__); } while (0)
;
647
648 if (!s->scope)
649 return 0;
650
651 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
652 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
653 * when killing any processes left after this point. */
654 r = manager_abandon_scope(s->manager, s->scope, &error);
655 if (r < 0)
656 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r))({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 656, __func__, "Failed to abandon session scope, ignoring: %s"
, bus_error_message(&error, r)) : -abs(_e); })
;
657
658 /* Optionally, let's kill everything that's left now. */
659 if (force || manager_shall_kill(s->manager, s->user->name)) {
660 char *job = NULL((void*)0);
661
662 r = manager_stop_unit(s->manager, s->scope, &error, &job);
663 if (r < 0)
664 return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r))({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 664, __func__, "Failed to stop session scope: %s"
, bus_error_message(&error, r)) : -abs(_e); })
;
665
666 free(s->scope_job);
667 s->scope_job = job;
668 } else {
669 s->scope_job = mfree(s->scope_job);
670
671 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
672 * Therefore session stop and session removal may be two distinct events.
673 * Session stop is quite significant on its own, let's log it. */
674 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 678, __func__, "SESSION_ID=%s", s->id, "USER_ID=%s", s->
user->name, "LEADER=""%" "i", s->leader, "MESSAGE=" "Session %s logged out. Waiting for processes to exit."
, s->id, ((void*)0))
675 "SESSION_ID=%s", s->id,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 678, __func__, "SESSION_ID=%s", s->id, "USER_ID=%s", s->
user->name, "LEADER=""%" "i", s->leader, "MESSAGE=" "Session %s logged out. Waiting for processes to exit."
, s->id, ((void*)0))
676 "USER_ID=%s", s->user->name,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 678, __func__, "SESSION_ID=%s", s->id, "USER_ID=%s", s->
user->name, "LEADER=""%" "i", s->leader, "MESSAGE=" "Session %s logged out. Waiting for processes to exit."
, s->id, ((void*)0))
677 "LEADER="PID_FMT, s->leader,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 678, __func__, "SESSION_ID=%s", s->id, "USER_ID=%s", s->
user->name, "LEADER=""%" "i", s->leader, "MESSAGE=" "Session %s logged out. Waiting for processes to exit."
, s->id, ((void*)0))
678 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 678, __func__, "SESSION_ID=%s", s->id, "USER_ID=%s", s->
user->name, "LEADER=""%" "i", s->leader, "MESSAGE=" "Session %s logged out. Waiting for processes to exit."
, s->id, ((void*)0))
;
679 }
680
681 return 0;
682}
683
684int session_stop(Session *s, bool_Bool force) {
685 int r;
686
687 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 687
, __PRETTY_FUNCTION__); } while (0)
;
688
689 if (!s->user)
690 return -ESTALE116;
691
692 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
693
694 if (s->seat)
695 seat_evict_position(s->seat, s);
696
697 /* We are going down, don't care about FIFOs anymore */
698 session_remove_fifo(s);
699
700 /* Kill cgroup */
701 r = session_stop_scope(s, force);
702
703 s->stopping = true1;
704
705 user_elect_display(s->user);
706
707 session_save(s);
708 user_save(s->user);
709
710 return r;
711}
712
713int session_finalize(Session *s) {
714 SessionDevice *sd;
715
716 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 716
, __PRETTY_FUNCTION__); } while (0)
;
717
718 if (!s->user)
719 return -ESTALE116;
720
721 if (s->started)
722 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 727, __func__, "MESSAGE_ID=" "33" "54" "93" "94" "24" "b4" "45"
"6d" "98" "02" "ca" "83" "33" "ed" "42" "4a", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "Removed session %s.", s->id, (
(void*)0))
723 "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 727, __func__, "MESSAGE_ID=" "33" "54" "93" "94" "24" "b4" "45"
"6d" "98" "02" "ca" "83" "33" "ed" "42" "4a", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "Removed session %s.", s->id, (
(void*)0))
724 "SESSION_ID=%s", s->id,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 727, __func__, "MESSAGE_ID=" "33" "54" "93" "94" "24" "b4" "45"
"6d" "98" "02" "ca" "83" "33" "ed" "42" "4a", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "Removed session %s.", s->id, (
(void*)0))
725 "USER_ID=%s", s->user->name,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 727, __func__, "MESSAGE_ID=" "33" "54" "93" "94" "24" "b4" "45"
"6d" "98" "02" "ca" "83" "33" "ed" "42" "4a", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "Removed session %s.", s->id, (
(void*)0))
726 "LEADER="PID_FMT, s->leader,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 727, __func__, "MESSAGE_ID=" "33" "54" "93" "94" "24" "b4" "45"
"6d" "98" "02" "ca" "83" "33" "ed" "42" "4a", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "Removed session %s.", s->id, (
(void*)0))
727 LOG_MESSAGE("Removed session %s.", s->id))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (s->
class == SESSION_BACKGROUND ? 7 : 6)), 0, "../src/login/logind-session.c"
, 727, __func__, "MESSAGE_ID=" "33" "54" "93" "94" "24" "b4" "45"
"6d" "98" "02" "ca" "83" "33" "ed" "42" "4a", "SESSION_ID=%s"
, s->id, "USER_ID=%s", s->user->name, "LEADER=""%" "i"
, s->leader, "MESSAGE=" "Removed session %s.", s->id, (
(void*)0))
;
728
729 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
730
731 if (s->seat)
732 seat_evict_position(s->seat, s);
733
734 /* Kill session devices */
735 while ((sd = hashmap_first(s->devices)))
736 session_device_free(sd);
737
738 (void) unlink(s->state_file);
739 session_add_to_gc_queue(s);
740 user_add_to_gc_queue(s->user);
741
742 if (s->started) {
743 session_send_signal(s, false0);
744 s->started = false0;
745 }
746
747 if (s->seat) {
748 if (s->seat->active == s)
749 seat_set_active(s->seat, NULL((void*)0));
750
751 seat_save(s->seat);
752 }
753
754 user_save(s->user);
755 user_send_changed(s->user, "Display", NULL((void*)0));
756
757 return 0;
758}
759
760static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
761 Session *s = userdata;
762
763 assert(es)do { if ((__builtin_expect(!!(!(es)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("es"), "../src/login/logind-session.c", 763
, __PRETTY_FUNCTION__); } while (0)
;
764 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 764
, __PRETTY_FUNCTION__); } while (0)
;
765
766 session_stop(s, false0);
767 return 0;
768}
769
770int session_release(Session *s) {
771 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 771
, __PRETTY_FUNCTION__); } while (0)
;
772
773 if (!s->started || s->stopping)
774 return 0;
775
776 if (s->timer_event_source)
777 return 0;
778
779 return sd_event_add_time(s->manager->event,
780 &s->timer_event_source,
781 CLOCK_MONOTONIC1,
782 now(CLOCK_MONOTONIC1) + RELEASE_USEC(20*((usec_t) 1000000ULL)), 0,
783 release_timeout_callback, s);
784}
785
786bool_Bool session_is_active(Session *s) {
787 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 787
, __PRETTY_FUNCTION__); } while (0)
;
788
789 if (!s->seat)
790 return true1;
791
792 return s->seat->active == s;
793}
794
795static int get_tty_atime(const char *tty, usec_t *atime) {
796 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
797 struct stat st;
798
799 assert(tty)do { if ((__builtin_expect(!!(!(tty)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("tty"), "../src/login/logind-session.c",
799, __PRETTY_FUNCTION__); } while (0)
;
800 assert(atime)do { if ((__builtin_expect(!!(!(atime)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("atime"), "../src/login/logind-session.c"
, 800, __PRETTY_FUNCTION__); } while (0)
;
801
802 if (!path_is_absolute(tty)) {
803 p = strappend("/dev/", tty);
804 if (!p)
805 return -ENOMEM12;
806
807 tty = p;
808 } else if (!path_startswith(tty, "/dev/"))
809 return -ENOENT2;
810
811 if (lstat(tty, &st) < 0)
812 return -errno(*__errno_location ());
813
814 *atime = timespec_load(&st.st_atim);
815 return 0;
816}
817
818static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
819 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
820 int r;
821
822 assert(pid > 0)do { if ((__builtin_expect(!!(!(pid > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pid > 0"), "../src/login/logind-session.c"
, 822, __PRETTY_FUNCTION__); } while (0)
;
823 assert(atime)do { if ((__builtin_expect(!!(!(atime)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("atime"), "../src/login/logind-session.c"
, 823, __PRETTY_FUNCTION__); } while (0)
;
824
825 r = get_ctty(pid, NULL((void*)0), &p);
826 if (r < 0)
827 return r;
828
829 return get_tty_atime(p, atime);
830}
831
832int session_get_idle_hint(Session *s, dual_timestamp *t) {
833 usec_t atime = 0, n;
834 int r;
835
836 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 836
, __PRETTY_FUNCTION__); } while (0)
;
837
838 /* Explicit idle hint is set */
839 if (s->idle_hint) {
840 if (t)
841 *t = s->idle_hint_timestamp;
842
843 return s->idle_hint;
844 }
845
846 /* Graphical sessions should really implement a real
847 * idle hint logic */
848 if (SESSION_TYPE_IS_GRAPHICAL(s->type)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){SESSION_X11, SESSION_WAYLAND, SESSION_MIR
})/sizeof(int)]; switch(s->type) { case SESSION_X11: case SESSION_WAYLAND
: case SESSION_MIR: _found = 1; break; default: break; } _found
; })
)
849 goto dont_know;
850
851 /* For sessions with an explicitly configured tty, let's check
852 * its atime */
853 if (s->tty) {
854 r = get_tty_atime(s->tty, &atime);
855 if (r >= 0)
856 goto found_atime;
857 }
858
859 /* For sessions with a leader but no explicitly configured
860 * tty, let's check the controlling tty of the leader */
861 if (s->leader > 0) {
862 r = get_process_ctty_atime(s->leader, &atime);
863 if (r >= 0)
864 goto found_atime;
865 }
866
867dont_know:
868 if (t)
869 *t = s->idle_hint_timestamp;
870
871 return 0;
872
873found_atime:
874 if (t)
875 dual_timestamp_from_realtime(t, atime);
876
877 n = now(CLOCK_REALTIME0);
878
879 if (s->manager->idle_action_usec <= 0)
880 return 0;
881
882 return atime + s->manager->idle_action_usec <= n;
883}
884
885void session_set_idle_hint(Session *s, bool_Bool b) {
886 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 886
, __PRETTY_FUNCTION__); } while (0)
;
887
888 if (s->idle_hint == b)
889 return;
890
891 s->idle_hint = b;
892 dual_timestamp_get(&s->idle_hint_timestamp);
893
894 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL((void*)0));
895
896 if (s->seat)
897 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL((void*)0));
898
899 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL((void*)0));
900 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL((void*)0));
901}
902
903int session_get_locked_hint(Session *s) {
904 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 904
, __PRETTY_FUNCTION__); } while (0)
;
905
906 return s->locked_hint;
907}
908
909void session_set_locked_hint(Session *s, bool_Bool b) {
910 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 910
, __PRETTY_FUNCTION__); } while (0)
;
911
912 if (s->locked_hint == b)
913 return;
914
915 s->locked_hint = b;
916
917 session_send_changed(s, "LockedHint", NULL((void*)0));
918}
919
920static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
921 Session *s = userdata;
922
923 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 923
, __PRETTY_FUNCTION__); } while (0)
;
924 assert(s->fifo_fd == fd)do { if ((__builtin_expect(!!(!(s->fifo_fd == fd)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s->fifo_fd == fd"), "../src/login/logind-session.c"
, 924, __PRETTY_FUNCTION__); } while (0)
;
925
926 /* EOF on the FIFO means the session died abnormally. */
927
928 session_remove_fifo(s);
929 session_stop(s, false0);
930
931 return 1;
932}
933
934int session_create_fifo(Session *s) {
935 int r;
936
937 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 937
, __PRETTY_FUNCTION__); } while (0)
;
938
939 /* Create FIFO */
940 if (!s->fifo_path) {
941 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
942 if (r < 0)
943 return r;
944
945 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
946 return -ENOMEM12;
947
948 if (mkfifo(s->fifo_path, 0600) < 0 && errno(*__errno_location ()) != EEXIST17)
949 return -errno(*__errno_location ());
950 }
951
952 /* Open reading side */
953 if (s->fifo_fd < 0) {
954 s->fifo_fd = open(s->fifo_path, O_RDONLY00|O_CLOEXEC02000000|O_NONBLOCK04000);
955 if (s->fifo_fd < 0)
956 return -errno(*__errno_location ());
957
958 }
959
960 if (!s->fifo_event_source) {
961 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
962 if (r < 0)
963 return r;
964
965 /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
966 * sessions). */
967 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
968 if (r < 0)
969 return r;
970 }
971
972 /* Open writing side */
973 r = open(s->fifo_path, O_WRONLY01|O_CLOEXEC02000000|O_NONBLOCK04000);
974 if (r < 0)
975 return -errno(*__errno_location ());
976
977 return r;
978}
979
980static void session_remove_fifo(Session *s) {
981 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 981
, __PRETTY_FUNCTION__); } while (0)
;
982
983 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
984 s->fifo_fd = safe_close(s->fifo_fd);
985
986 if (s->fifo_path) {
987 unlink(s->fifo_path);
988 s->fifo_path = mfree(s->fifo_path);
989 }
990}
991
992bool_Bool session_may_gc(Session *s, bool_Bool drop_not_started) {
993 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 993
, __PRETTY_FUNCTION__); } while (0)
;
994
995 if (drop_not_started && !s->started)
996 return true1;
997
998 if (!s->user)
999 return true1;
1000
1001 if (s->fifo_fd >= 0) {
1002 if (pipe_eof(s->fifo_fd) <= 0)
1003 return false0;
1004 }
1005
1006 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
1007 return false0;
1008
1009 if (s->scope && manager_unit_is_active(s->manager, s->scope))
1010 return false0;
1011
1012 return true1;
1013}
1014
1015void session_add_to_gc_queue(Session *s) {
1016 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1016
, __PRETTY_FUNCTION__); } while (0)
;
1017
1018 if (s->in_gc_queue)
1019 return;
1020
1021 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s)do { typeof(*(s->manager->session_gc_queue)) **_head = &
(s->manager->session_gc_queue), *_item = (s); do { if (
(__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("_item"), "../src/login/logind-session.c", 1021, __PRETTY_FUNCTION__
); } while (0); if ((_item->gc_queue_next = *_head)) _item
->gc_queue_next->gc_queue_prev = _item; _item->gc_queue_prev
= ((void*)0); *_head = _item; } while (0)
;
1022 s->in_gc_queue = true1;
1023}
1024
1025SessionState session_get_state(Session *s) {
1026 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1026
, __PRETTY_FUNCTION__); } while (0)
;
1027
1028 /* always check closing first */
1029 if (s->stopping || s->timer_event_source)
1030 return SESSION_CLOSING;
1031
1032 if (s->scope_job || s->fifo_fd < 0)
1033 return SESSION_OPENING;
1034
1035 if (session_is_active(s))
1036 return SESSION_ACTIVE;
1037
1038 return SESSION_ONLINE;
1039}
1040
1041int session_kill(Session *s, KillWho who, int signo) {
1042 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1042
, __PRETTY_FUNCTION__); } while (0)
;
1043
1044 if (!s->scope)
1045 return -ESRCH3;
1046
1047 return manager_kill_unit(s->manager, s->scope, who, signo, NULL((void*)0));
1048}
1049
1050static int session_open_vt(Session *s) {
1051 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)(2+(sizeof(s->vtnr) <= 1 ? 3 : sizeof(s->vtnr) <=
2 ? 5 : sizeof(s->vtnr) <= 4 ? 10 : sizeof(s->vtnr)
<= 8 ? 20 : sizeof(int[-2*(sizeof(s->vtnr) > 8)])))
];
1052
1053 if (s->vtnr < 1)
1054 return -ENODEV19;
1055
1056 if (s->vtfd >= 0)
1057 return s->vtfd;
1058
1059 sprintf(path, "/dev/tty%u", s->vtnr);
1060 s->vtfd = open_terminal(path, O_RDWR02 | O_CLOEXEC02000000 | O_NONBLOCK04000 | O_NOCTTY0400);
1061 if (s->vtfd < 0)
1062 return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id)({ int _level = ((3)), _e = ((s->vtfd)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/login/logind-session.c", 1062, __func__, "cannot open VT %s of session %s: %m"
, path, s->id) : -abs(_e); })
;
1063
1064 return s->vtfd;
1065}
1066
1067int session_prepare_vt(Session *s) {
1068 int vt, r;
1069 struct vt_mode mode = { 0 };
1070
1071 if (s->vtnr < 1)
1072 return 0;
1073
1074 vt = session_open_vt(s);
1075 if (vt < 0)
1076 return vt;
1077
1078 r = fchown(vt, s->user->uid, -1);
1079 if (r < 0) {
1080 r = log_error_errno(errno,({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1082, __func__
, "Cannot change owner of /dev/tty%u: %m", s->vtnr) : -abs
(_e); })
1081 "Cannot change owner of /dev/tty%u: %m",({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1082, __func__
, "Cannot change owner of /dev/tty%u: %m", s->vtnr) : -abs
(_e); })
1082 s->vtnr)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1082, __func__
, "Cannot change owner of /dev/tty%u: %m", s->vtnr) : -abs
(_e); })
;
1083 goto error;
1084 }
1085
1086 r = ioctl(vt, KDSKBMODE0x4B45, K_OFF0x04);
1087 if (r < 0) {
1088 r = log_error_errno(errno,({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1090, __func__
, "Cannot set K_OFF on /dev/tty%u: %m", s->vtnr) : -abs(_e
); })
1089 "Cannot set K_OFF on /dev/tty%u: %m",({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1090, __func__
, "Cannot set K_OFF on /dev/tty%u: %m", s->vtnr) : -abs(_e
); })
1090 s->vtnr)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1090, __func__
, "Cannot set K_OFF on /dev/tty%u: %m", s->vtnr) : -abs(_e
); })
;
1091 goto error;
1092 }
1093
1094 r = ioctl(vt, KDSETMODE0x4B3A, KD_GRAPHICS0x01);
1095 if (r < 0) {
1096 r = log_error_errno(errno,({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1098, __func__
, "Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr) : -
abs(_e); })
1097 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1098, __func__
, "Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr) : -
abs(_e); })
1098 s->vtnr)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1098, __func__
, "Cannot set KD_GRAPHICS on /dev/tty%u: %m", s->vtnr) : -
abs(_e); })
;
1099 goto error;
1100 }
1101
1102 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1103 * So we need a dummy handler here which just acknowledges *all* VT
1104 * switch requests. */
1105 mode.mode = VT_PROCESS0x01;
1106 mode.relsig = SIGRTMIN(__libc_current_sigrtmin ());
1107 mode.acqsig = SIGRTMIN(__libc_current_sigrtmin ()) + 1;
1108 r = ioctl(vt, VT_SETMODE0x5602, &mode);
1109 if (r < 0) {
1110 r = log_error_errno(errno,({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1112, __func__
, "Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr) : -abs
(_e); })
1111 "Cannot set VT_PROCESS on /dev/tty%u: %m",({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1112, __func__
, "Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr) : -abs
(_e); })
1112 s->vtnr)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1112, __func__
, "Cannot set VT_PROCESS on /dev/tty%u: %m", s->vtnr) : -abs
(_e); })
;
1113 goto error;
1114 }
1115
1116 return 0;
1117
1118error:
1119 session_restore_vt(s);
1120 return r;
1121}
1122
1123void session_restore_vt(Session *s) {
1124
1125 static const struct vt_mode mode = {
1126 .mode = VT_AUTO0x00,
1127 };
1128
1129 int vt, old_fd;
1130
1131 /* We need to get a fresh handle to the virtual terminal,
1132 * since the old file-descriptor is potentially in a hung-up
1133 * state after the controlling process exited; we do a
1134 * little dance to avoid having the terminal be available
1135 * for reuse before we've cleaned it up.
1136 */
1137 old_fd = TAKE_FD(s->vtfd)({ int _fd_ = (s->vtfd); (s->vtfd) = -1; _fd_; });
1138
1139 vt = session_open_vt(s);
1140 safe_close(old_fd);
1141
1142 if (vt < 0)
1143 return;
1144
1145 (void) ioctl(vt, KDSETMODE0x4B3A, KD_TEXT0x00);
1146
1147 (void) vt_reset_keyboard(vt);
1148
1149 (void) ioctl(vt, VT_SETMODE0x5602, &mode);
1150 (void) fchown(vt, 0, (gid_t) -1);
1151
1152 s->vtfd = safe_close(s->vtfd);
1153}
1154
1155void session_leave_vt(Session *s) {
1156 int r;
1157
1158 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1158
, __PRETTY_FUNCTION__); } while (0)
;
1159
1160 /* This is called whenever we get a VT-switch signal from the kernel.
1161 * We acknowledge all of them unconditionally. Note that session are
1162 * free to overwrite those handlers and we only register them for
1163 * sessions with controllers. Legacy sessions are not affected.
1164 * However, if we switch from a non-legacy to a legacy session, we must
1165 * make sure to pause all device before acknowledging the switch. We
1166 * process the real switch only after we are notified via sysfs, so the
1167 * legacy session might have already started using the devices. If we
1168 * don't pause the devices before the switch, we might confuse the
1169 * session we switch to. */
1170
1171 if (s->vtfd < 0)
1172 return;
1173
1174 session_device_pause_all(s);
1175 r = ioctl(s->vtfd, VT_RELDISP0x5605, 1);
1176 if (r < 0)
1177 log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id)({ int _level = ((7)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/login/logind-session.c", 1177, __func__
, "Cannot release VT of session %s: %m", s->id) : -abs(_e)
; })
;
1178}
1179
1180bool_Bool session_is_controller(Session *s, const char *sender) {
1181 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1181
, __PRETTY_FUNCTION__); } while (0)
;
1182
1183 return streq_ptr(s->controller, sender);
1184}
1185
1186static void session_release_controller(Session *s, bool_Bool notify) {
1187 _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0);
1188 SessionDevice *sd;
1189
1190 if (!s->controller)
1191 return;
1192
1193 name = s->controller;
Value stored to 'name' is never read
1194
1195 /* By resetting the controller before releasing the devices, we won't
1196 * send notification signals. This avoids sending useless notifications
1197 * if the controller is released on disconnects. */
1198 if (!notify)
1199 s->controller = NULL((void*)0);
1200
1201 while ((sd = hashmap_first(s->devices)))
1202 session_device_free(sd);
1203
1204 s->controller = NULL((void*)0);
1205 s->track = sd_bus_track_unref(s->track);
1206}
1207
1208static int on_bus_track(sd_bus_track *track, void *userdata) {
1209 Session *s = userdata;
1210
1211 assert(track)do { if ((__builtin_expect(!!(!(track)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("track"), "../src/login/logind-session.c"
, 1211, __PRETTY_FUNCTION__); } while (0)
;
1212 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1212
, __PRETTY_FUNCTION__); } while (0)
;
1213
1214 session_drop_controller(s);
1215
1216 return 0;
1217}
1218
1219int session_set_controller(Session *s, const char *sender, bool_Bool force, bool_Bool prepare) {
1220 _cleanup_free___attribute__((cleanup(freep))) char *name = NULL((void*)0);
1221 int r;
1222
1223 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1223
, __PRETTY_FUNCTION__); } while (0)
;
1224 assert(sender)do { if ((__builtin_expect(!!(!(sender)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sender"), "../src/login/logind-session.c"
, 1224, __PRETTY_FUNCTION__); } while (0)
;
1225
1226 if (session_is_controller(s, sender))
1227 return 0;
1228 if (s->controller && !force)
1229 return -EBUSY16;
1230
1231 name = strdup(sender);
1232 if (!name)
1233 return -ENOMEM12;
1234
1235 s->track = sd_bus_track_unref(s->track);
1236 r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1237 if (r < 0)
1238 return r;
1239
1240 r = sd_bus_track_add_name(s->track, name);
1241 if (r < 0)
1242 return r;
1243
1244 /* When setting a session controller, we forcibly mute the VT and set
1245 * it into graphics-mode. Applications can override that by changing
1246 * VT state after calling TakeControl(). However, this serves as a good
1247 * default and well-behaving controllers can now ignore VTs entirely.
1248 * Note that we reset the VT on ReleaseControl() and if the controller
1249 * exits.
1250 * If logind crashes/restarts, we restore the controller during restart
1251 * (without preparing the VT since the controller has probably overridden
1252 * VT state by now) or reset the VT in case it crashed/exited, too. */
1253 if (prepare) {
1254 r = session_prepare_vt(s);
1255 if (r < 0) {
1256 s->track = sd_bus_track_unref(s->track);
1257 return r;
1258 }
1259 }
1260
1261 session_release_controller(s, true1);
1262 s->controller = TAKE_PTR(name)({ typeof(name) _ptr_ = (name); (name) = ((void*)0); _ptr_; }
)
;
1263 session_save(s);
1264
1265 return 0;
1266}
1267
1268void session_drop_controller(Session *s) {
1269 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/login/logind-session.c", 1269
, __PRETTY_FUNCTION__); } while (0)
;
1270
1271 if (!s->controller)
1272 return;
1273
1274 s->track = sd_bus_track_unref(s->track);
1275 session_release_controller(s, false0);
1276 session_save(s);
1277 session_restore_vt(s);
1278}
1279
1280static const char* const session_state_table[_SESSION_STATE_MAX] = {
1281 [SESSION_OPENING] = "opening",
1282 [SESSION_ONLINE] = "online",
1283 [SESSION_ACTIVE] = "active",
1284 [SESSION_CLOSING] = "closing"
1285};
1286
1287DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState)const char *session_state_to_string(SessionState i) { if (i <
0 || i >= (SessionState) __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(session_state_table), typeof
(&*(session_state_table))), sizeof(session_state_table)/sizeof
((session_state_table)[0]), ((void)0)))) return ((void*)0); return
session_state_table[i]; } SessionState session_state_from_string
(const char *s) { return (SessionState) string_table_lookup(session_state_table
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(session_state_table), typeof(&*(session_state_table
))), sizeof(session_state_table)/sizeof((session_state_table)
[0]), ((void)0))), s); }
;
1288
1289static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1290 [SESSION_UNSPECIFIED] = "unspecified",
1291 [SESSION_TTY] = "tty",
1292 [SESSION_X11] = "x11",
1293 [SESSION_WAYLAND] = "wayland",
1294 [SESSION_MIR] = "mir",
1295 [SESSION_WEB] = "web",
1296};
1297
1298DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType)const char *session_type_to_string(SessionType i) { if (i <
0 || i >= (SessionType) __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(session_type_table), typeof
(&*(session_type_table))), sizeof(session_type_table)/sizeof
((session_type_table)[0]), ((void)0)))) return ((void*)0); return
session_type_table[i]; } SessionType session_type_from_string
(const char *s) { return (SessionType) string_table_lookup(session_type_table
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(session_type_table), typeof(&*(session_type_table
))), sizeof(session_type_table)/sizeof((session_type_table)[0
]), ((void)0))), s); }
;
1299
1300static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1301 [SESSION_USER] = "user",
1302 [SESSION_GREETER] = "greeter",
1303 [SESSION_LOCK_SCREEN] = "lock-screen",
1304 [SESSION_BACKGROUND] = "background"
1305};
1306
1307DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass)const char *session_class_to_string(SessionClass i) { if (i <
0 || i >= (SessionClass) __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(session_class_table), typeof
(&*(session_class_table))), sizeof(session_class_table)/sizeof
((session_class_table)[0]), ((void)0)))) return ((void*)0); return
session_class_table[i]; } SessionClass session_class_from_string
(const char *s) { return (SessionClass) string_table_lookup(session_class_table
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(session_class_table), typeof(&*(session_class_table
))), sizeof(session_class_table)/sizeof((session_class_table)
[0]), ((void)0))), s); }
;
1308
1309static const char* const kill_who_table[_KILL_WHO_MAX] = {
1310 [KILL_LEADER] = "leader",
1311 [KILL_ALL] = "all"
1312};
1313
1314DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho)const char *kill_who_to_string(KillWho i) { if (i < 0 || i
>= (KillWho) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(kill_who_table), typeof(&*(kill_who_table))), sizeof
(kill_who_table)/sizeof((kill_who_table)[0]), ((void)0)))) return
((void*)0); return kill_who_table[i]; } KillWho kill_who_from_string
(const char *s) { return (KillWho) string_table_lookup(kill_who_table
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(kill_who_table), typeof(&*(kill_who_table))), sizeof
(kill_who_table)/sizeof((kill_who_table)[0]), ((void)0))), s)
; }
;