]>
Commit | Line | Data |
---|---|---|
20263082 LP |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
3 | /*** | |
4 | This file is part of systemd. | |
5 | ||
6 | Copyright 2011 Lennart Poettering | |
7 | ||
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
21 | ||
22 | #include <errno.h> | |
23 | #include <string.h> | |
24 | #include <unistd.h> | |
25 | ||
90821c93 | 26 | #include "logind-session.h" |
20263082 LP |
27 | #include "strv.h" |
28 | #include "util.h" | |
29 | #include "cgroup-util.h" | |
30 | ||
a185c5aa LP |
31 | #define IDLE_THRESHOLD_USEC (5*USEC_PER_MINUTE) |
32 | ||
20263082 LP |
33 | Session* session_new(Manager *m, User *u, const char *id) { |
34 | Session *s; | |
35 | ||
36 | assert(m); | |
37 | assert(id); | |
38 | ||
14c3baca | 39 | s = new0(Session, 1); |
20263082 LP |
40 | if (!s) |
41 | return NULL; | |
42 | ||
98a28fef | 43 | s->state_file = strappend("/run/systemd/sessions/", id); |
20263082 LP |
44 | if (!s->state_file) { |
45 | free(s); | |
46 | return NULL; | |
47 | } | |
48 | ||
49 | s->id = file_name_from_path(s->state_file); | |
50 | ||
51 | if (hashmap_put(m->sessions, s->id, s) < 0) { | |
52 | free(s->id); | |
53 | free(s); | |
54 | return NULL; | |
55 | } | |
56 | ||
57 | s->manager = m; | |
58 | s->pipe_fd = -1; | |
59 | s->user = u; | |
60 | ||
14c3baca | 61 | LIST_PREPEND(Session, sessions_by_user, u->sessions, s); |
20263082 LP |
62 | |
63 | return s; | |
64 | } | |
65 | ||
66 | void session_free(Session *s) { | |
67 | assert(s); | |
68 | ||
14c3baca LP |
69 | if (s->in_gc_queue) |
70 | LIST_REMOVE(Session, gc_queue, s->manager->session_gc_queue, s); | |
71 | ||
20263082 LP |
72 | if (s->user) { |
73 | LIST_REMOVE(Session, sessions_by_user, s->user->sessions, s); | |
74 | ||
75 | if (s->user->display == s) | |
76 | s->user->display = NULL; | |
77 | } | |
78 | ||
9418f147 LP |
79 | if (s->seat) { |
80 | if (s->seat->active == s) | |
81 | s->seat->active = NULL; | |
82 | ||
20263082 | 83 | LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s); |
9418f147 | 84 | } |
20263082 LP |
85 | |
86 | free(s->cgroup_path); | |
87 | strv_free(s->controllers); | |
88 | ||
89 | free(s->tty); | |
90 | free(s->display); | |
91 | free(s->remote_host); | |
3f49d45a | 92 | free(s->remote_user); |
98a28fef | 93 | free(s->service); |
20263082 LP |
94 | |
95 | hashmap_remove(s->manager->sessions, s->id); | |
96 | ||
98a28fef LP |
97 | if (s->pipe_fd >= 0) |
98 | close_nointr_nofail(s->pipe_fd); | |
99 | ||
d2f92cdf | 100 | free(s->state_file); |
20263082 LP |
101 | free(s); |
102 | } | |
103 | ||
104 | int session_save(Session *s) { | |
105 | FILE *f; | |
106 | int r = 0; | |
14c3baca | 107 | char *temp_path; |
20263082 LP |
108 | |
109 | assert(s); | |
110 | ||
98a28fef | 111 | r = safe_mkdir("/run/systemd/sessions", 0755, 0, 0); |
20263082 | 112 | if (r < 0) |
14c3baca | 113 | goto finish; |
20263082 | 114 | |
14c3baca LP |
115 | r = fopen_temporary(s->state_file, &f, &temp_path); |
116 | if (r < 0) | |
117 | goto finish; | |
20263082 LP |
118 | |
119 | assert(s->user); | |
120 | ||
14c3baca LP |
121 | fchmod(fileno(f), 0644); |
122 | ||
20263082 LP |
123 | fprintf(f, |
124 | "# This is private data. Do not parse.\n" | |
125 | "UID=%lu\n" | |
126 | "USER=%s\n" | |
127 | "ACTIVE=%i\n" | |
128 | "REMOTE=%i\n" | |
129 | "KILL_PROCESSES=%i\n", | |
130 | (unsigned long) s->user->uid, | |
131 | s->user->name, | |
132 | session_is_active(s), | |
133 | s->remote, | |
134 | s->kill_processes); | |
135 | ||
136 | if (s->cgroup_path) | |
137 | fprintf(f, | |
138 | "CGROUP=%s\n", | |
139 | s->cgroup_path); | |
140 | ||
141 | if (s->seat) | |
142 | fprintf(f, | |
143 | "SEAT=%s\n", | |
144 | s->seat->id); | |
145 | ||
146 | if (s->tty) | |
147 | fprintf(f, | |
148 | "TTY=%s\n", | |
149 | s->tty); | |
150 | ||
151 | if (s->display) | |
152 | fprintf(f, | |
153 | "DISPLAY=%s\n", | |
154 | s->display); | |
155 | ||
156 | if (s->remote_host) | |
157 | fprintf(f, | |
158 | "REMOTE_HOST=%s\n", | |
159 | s->remote_host); | |
160 | ||
3f49d45a LP |
161 | if (s->remote_user) |
162 | fprintf(f, | |
163 | "REMOTE_USER=%s\n", | |
164 | s->remote_user); | |
165 | ||
98a28fef LP |
166 | if (s->service) |
167 | fprintf(f, | |
168 | "SERVICE=%s\n", | |
169 | s->service); | |
170 | ||
a185c5aa | 171 | if (s->seat && seat_is_vtconsole(s->seat)) |
20263082 LP |
172 | fprintf(f, |
173 | "VTNR=%i\n", | |
174 | s->vtnr); | |
175 | ||
176 | if (s->leader > 0) | |
177 | fprintf(f, | |
178 | "LEADER=%lu\n", | |
179 | (unsigned long) s->leader); | |
180 | ||
181 | if (s->audit_id > 0) | |
182 | fprintf(f, | |
183 | "AUDIT=%llu\n", | |
184 | (unsigned long long) s->audit_id); | |
185 | ||
186 | fflush(f); | |
14c3baca LP |
187 | |
188 | if (ferror(f) || rename(temp_path, s->state_file) < 0) { | |
20263082 LP |
189 | r = -errno; |
190 | unlink(s->state_file); | |
14c3baca | 191 | unlink(temp_path); |
20263082 LP |
192 | } |
193 | ||
194 | fclose(f); | |
14c3baca LP |
195 | free(temp_path); |
196 | ||
197 | finish: | |
198 | if (r < 0) | |
199 | log_error("Failed to save session data for %s: %s", s->id, strerror(-r)); | |
200 | ||
20263082 LP |
201 | return r; |
202 | } | |
203 | ||
204 | int session_load(Session *s) { | |
a185c5aa LP |
205 | char *remote = NULL, |
206 | *kill_processes = NULL, | |
207 | *seat = NULL, | |
208 | *vtnr = NULL, | |
209 | *leader = NULL, | |
210 | *audit_id = NULL; | |
211 | ||
212 | int k, r; | |
213 | ||
20263082 LP |
214 | assert(s); |
215 | ||
a185c5aa LP |
216 | r = parse_env_file(s->state_file, NEWLINE, |
217 | "REMOTE", &remote, | |
218 | "KILL_PROCESSES", &kill_processes, | |
219 | "CGROUP", &s->cgroup_path, | |
220 | "SEAT", &seat, | |
221 | "TTY", &s->tty, | |
222 | "DISPLAY", &s->display, | |
223 | "REMOTE_HOST", &s->remote_host, | |
224 | "REMOTE_USER", &s->remote_user, | |
98a28fef | 225 | "SERVICE", &s->service, |
a185c5aa LP |
226 | "VTNR", &vtnr, |
227 | "LEADER", &leader, | |
a185c5aa LP |
228 | NULL); |
229 | ||
230 | if (r < 0) | |
231 | goto finish; | |
232 | ||
233 | if (remote) { | |
234 | k = parse_boolean(remote); | |
235 | if (k >= 0) | |
236 | s->remote = k; | |
237 | } | |
238 | ||
239 | if (kill_processes) { | |
240 | k = parse_boolean(kill_processes); | |
241 | if (k >= 0) | |
242 | s->kill_processes = k; | |
243 | } | |
244 | ||
9418f147 | 245 | if (seat && !s->seat) { |
a185c5aa LP |
246 | Seat *o; |
247 | ||
248 | o = hashmap_get(s->manager->seats, seat); | |
249 | if (o) | |
250 | seat_attach_session(o, s); | |
251 | } | |
252 | ||
253 | if (vtnr && s->seat && seat_is_vtconsole(s->seat)) { | |
254 | int v; | |
255 | ||
256 | k = safe_atoi(vtnr, &v); | |
257 | if (k >= 0 && v >= 1) | |
258 | s->vtnr = v; | |
259 | } | |
260 | ||
261 | if (leader) { | |
262 | pid_t pid; | |
263 | ||
264 | k = parse_pid(leader, &pid); | |
98a28fef | 265 | if (k >= 0 && pid >= 1) { |
a185c5aa | 266 | s->leader = pid; |
a185c5aa | 267 | |
98a28fef LP |
268 | audit_session_from_pid(pid, &s->audit_id); |
269 | } | |
a185c5aa LP |
270 | } |
271 | ||
272 | finish: | |
273 | free(remote); | |
274 | free(kill_processes); | |
275 | free(seat); | |
276 | free(vtnr); | |
277 | free(leader); | |
278 | free(audit_id); | |
279 | ||
280 | return r; | |
20263082 LP |
281 | } |
282 | ||
283 | int session_activate(Session *s) { | |
284 | int r; | |
5eda94dd | 285 | Session *old_active; |
20263082 LP |
286 | |
287 | assert(s); | |
288 | ||
289 | if (s->vtnr < 0) | |
290 | return -ENOTSUP; | |
291 | ||
292 | if (!s->seat) | |
293 | return -ENOTSUP; | |
294 | ||
295 | if (s->seat->active == s) | |
296 | return 0; | |
297 | ||
a185c5aa | 298 | assert(seat_is_vtconsole(s->seat)); |
20263082 LP |
299 | |
300 | r = chvt(s->vtnr); | |
301 | if (r < 0) | |
302 | return r; | |
303 | ||
5eda94dd | 304 | old_active = s->seat->active; |
20263082 LP |
305 | s->seat->active = s; |
306 | ||
14c3baca | 307 | return seat_apply_acls(s->seat, old_active); |
20263082 LP |
308 | } |
309 | ||
310 | bool x11_display_is_local(const char *display) { | |
311 | assert(display); | |
312 | ||
313 | return | |
314 | display[0] == ':' && | |
315 | display[1] >= '0' && | |
316 | display[1] <= '9'; | |
317 | } | |
318 | ||
319 | static int session_link_x11_socket(Session *s) { | |
320 | char *t, *f, *c; | |
321 | size_t k; | |
322 | ||
323 | assert(s); | |
324 | assert(s->user); | |
325 | assert(s->user->runtime_path); | |
326 | ||
327 | if (s->user->display) | |
328 | return 0; | |
329 | ||
330 | if (!s->display || !x11_display_is_local(s->display)) | |
331 | return 0; | |
332 | ||
333 | k = strspn(s->display+1, "0123456789"); | |
334 | f = new(char, sizeof("/tmp/.X11-unix/X") + k); | |
335 | if (!f) { | |
336 | log_error("Out of memory"); | |
337 | return -ENOMEM; | |
338 | } | |
339 | ||
340 | c = stpcpy(f, "/tmp/.X11-unix/X"); | |
341 | memcpy(c, s->display+1, k); | |
342 | c[k] = 0; | |
343 | ||
344 | if (access(f, F_OK) < 0) { | |
345 | log_warning("Session %s has display %s with nonexisting socket %s.", s->id, s->display, f); | |
346 | free(f); | |
347 | return -ENOENT; | |
348 | } | |
349 | ||
350 | t = strappend(s->user->runtime_path, "/display"); | |
351 | if (!t) { | |
352 | log_error("Out of memory"); | |
353 | free(f); | |
354 | return -ENOMEM; | |
355 | } | |
356 | ||
357 | if (link(f, t) < 0) { | |
358 | if (errno == EEXIST) { | |
359 | unlink(t); | |
360 | ||
361 | if (link(f, t) >= 0) | |
362 | goto done; | |
363 | } | |
364 | ||
365 | if (symlink(f, t) < 0) { | |
366 | ||
367 | if (errno == EEXIST) { | |
368 | unlink(t); | |
369 | ||
370 | if (symlink(f, t) >= 0) | |
371 | goto done; | |
372 | } | |
373 | ||
374 | log_error("Failed to link %s to %s: %m", f, t); | |
375 | free(f); | |
376 | free(t); | |
377 | return -errno; | |
378 | } | |
379 | } | |
380 | ||
381 | done: | |
382 | log_info("Linked %s to %s.", f, t); | |
383 | free(f); | |
384 | free(t); | |
385 | ||
386 | s->user->display = s; | |
387 | ||
388 | return 0; | |
389 | } | |
390 | ||
98a28fef LP |
391 | static int session_create_one_group(Session *s, const char *controller, const char *path) { |
392 | int r; | |
393 | ||
394 | assert(s); | |
395 | assert(controller); | |
396 | assert(path); | |
397 | ||
398 | if (s->leader > 0) | |
399 | r = cg_create_and_attach(controller, path, s->leader); | |
400 | else | |
401 | r = cg_create(controller, path); | |
402 | ||
403 | if (r < 0) | |
404 | return r; | |
405 | ||
406 | r = cg_set_task_access(controller, path, 0644, s->user->uid, s->user->gid); | |
407 | if (r >= 0) | |
408 | r = cg_set_group_access(controller, path, 0755, s->user->uid, s->user->gid); | |
409 | ||
410 | return r; | |
411 | } | |
412 | ||
20263082 LP |
413 | static int session_create_cgroup(Session *s) { |
414 | char **k; | |
415 | char *p; | |
416 | int r; | |
417 | ||
418 | assert(s); | |
419 | assert(s->user); | |
420 | assert(s->user->cgroup_path); | |
421 | ||
422 | if (!s->cgroup_path) { | |
423 | if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0) { | |
424 | log_error("Out of memory"); | |
425 | return -ENOMEM; | |
426 | } | |
427 | } else | |
428 | p = s->cgroup_path; | |
429 | ||
98a28fef | 430 | r = session_create_one_group(s, SYSTEMD_CGROUP_CONTROLLER, p); |
20263082 LP |
431 | if (r < 0) { |
432 | free(p); | |
433 | s->cgroup_path = NULL; | |
434 | log_error("Failed to create "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r)); | |
435 | return r; | |
436 | } | |
437 | ||
438 | s->cgroup_path = p; | |
439 | ||
98a28fef LP |
440 | STRV_FOREACH(k, s->controllers) { |
441 | ||
442 | if (strv_contains(s->reset_controllers, *k)) | |
443 | continue; | |
444 | ||
445 | r = session_create_one_group(s, *k, p); | |
446 | if (r < 0) | |
447 | log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r)); | |
448 | } | |
449 | ||
20263082 | 450 | STRV_FOREACH(k, s->manager->controllers) { |
20263082 | 451 | |
98a28fef LP |
452 | if (strv_contains(s->reset_controllers, *k) || |
453 | strv_contains(s->controllers, *k)) | |
454 | continue; | |
455 | ||
456 | r = session_create_one_group(s, *k, p); | |
20263082 | 457 | if (r < 0) |
98a28fef LP |
458 | log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r)); |
459 | } | |
460 | ||
461 | if (s->leader > 0) { | |
462 | ||
463 | STRV_FOREACH(k, s->reset_controllers) { | |
464 | r = cg_attach(*k, "/", s->leader); | |
465 | if (r < 0) | |
466 | log_warning("Failed to reset controller %s: %s", *k, strerror(-r)); | |
467 | ||
468 | } | |
20263082 LP |
469 | } |
470 | ||
471 | return 0; | |
472 | } | |
473 | ||
474 | int session_start(Session *s) { | |
475 | int r; | |
476 | ||
477 | assert(s); | |
478 | assert(s->user); | |
479 | ||
9418f147 LP |
480 | if (s->started) |
481 | return 0; | |
482 | ||
98a28fef LP |
483 | log_info("New session %s of user %s.", s->id, s->user->name); |
484 | ||
20263082 LP |
485 | /* Create cgroup */ |
486 | r = session_create_cgroup(s); | |
487 | if (r < 0) | |
488 | return r; | |
489 | ||
490 | /* Create X11 symlink */ | |
491 | session_link_x11_socket(s); | |
14c3baca LP |
492 | |
493 | /* Save session data */ | |
494 | session_save(s); | |
495 | ||
496 | dual_timestamp_get(&s->timestamp); | |
497 | ||
9418f147 LP |
498 | s->started = true; |
499 | ||
da119395 LP |
500 | session_send_signal(s, true); |
501 | ||
9418f147 LP |
502 | if (s->seat) { |
503 | if (s->seat->active == s) | |
504 | seat_send_changed(s->seat, "Sessions\0ActiveSession\0"); | |
505 | else | |
506 | seat_send_changed(s->seat, "Sessions\0"); | |
507 | } | |
508 | ||
509 | user_send_changed(s->user, "Sessions\0"); | |
510 | ||
20263082 LP |
511 | return 0; |
512 | } | |
513 | ||
514 | static bool session_shall_kill(Session *s) { | |
515 | assert(s); | |
516 | ||
517 | return s->kill_processes; | |
518 | } | |
519 | ||
520 | static int session_kill_cgroup(Session *s) { | |
521 | int r; | |
522 | char **k; | |
523 | ||
524 | assert(s); | |
525 | ||
526 | if (!s->cgroup_path) | |
527 | return 0; | |
528 | ||
529 | cg_trim(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false); | |
530 | ||
531 | if (session_shall_kill(s)) { | |
532 | ||
533 | r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true); | |
534 | if (r < 0) | |
535 | log_error("Failed to kill session cgroup: %s", strerror(-r)); | |
536 | ||
537 | } else { | |
538 | r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true); | |
539 | if (r < 0) | |
540 | log_error("Failed to check session cgroup: %s", strerror(-r)); | |
541 | else if (r > 0) { | |
542 | r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path); | |
543 | if (r < 0) | |
544 | log_error("Failed to delete session cgroup: %s", strerror(-r)); | |
545 | } else | |
546 | r = -EBUSY; | |
547 | } | |
548 | ||
549 | STRV_FOREACH(k, s->user->manager->controllers) | |
550 | cg_trim(*k, s->cgroup_path, true); | |
551 | ||
552 | free(s->cgroup_path); | |
553 | s->cgroup_path = NULL; | |
554 | ||
555 | return r; | |
556 | } | |
557 | ||
558 | static int session_unlink_x11_socket(Session *s) { | |
559 | char *t; | |
560 | int r; | |
561 | ||
562 | assert(s); | |
563 | assert(s->user); | |
564 | ||
565 | if (s->user->display != s) | |
566 | return 0; | |
567 | ||
568 | s->user->display = NULL; | |
569 | ||
570 | t = strappend(s->user->runtime_path, "/display"); | |
571 | if (!t) { | |
572 | log_error("Out of memory"); | |
573 | return -ENOMEM; | |
574 | } | |
575 | ||
576 | r = unlink(t); | |
577 | free(t); | |
578 | ||
579 | return r < 0 ? -errno : 0; | |
580 | } | |
581 | ||
582 | int session_stop(Session *s) { | |
583 | int r = 0, k; | |
584 | ||
585 | assert(s); | |
586 | ||
9418f147 LP |
587 | if (!s->started) |
588 | return 0; | |
da119395 | 589 | |
98a28fef LP |
590 | log_info("Removed session %s.", s->id); |
591 | ||
20263082 LP |
592 | /* Kill cgroup */ |
593 | k = session_kill_cgroup(s); | |
594 | if (k < 0) | |
595 | r = k; | |
596 | ||
597 | /* Remove X11 symlink */ | |
598 | session_unlink_x11_socket(s); | |
599 | ||
d2f92cdf LP |
600 | unlink(s->state_file); |
601 | session_add_to_gc_queue(s); | |
14c3baca | 602 | |
9418f147 LP |
603 | session_send_signal(s, false); |
604 | ||
605 | if (s->seat) { | |
606 | if (s->seat->active == s) | |
607 | seat_set_active(s->seat, NULL); | |
608 | ||
609 | seat_send_changed(s->seat, "Sessions\0"); | |
610 | } | |
611 | ||
612 | user_send_changed(s->user, "Sessions\0"); | |
613 | ||
614 | s->started = false; | |
615 | ||
20263082 LP |
616 | return r; |
617 | } | |
618 | ||
619 | bool session_is_active(Session *s) { | |
620 | assert(s); | |
621 | ||
622 | if (!s->seat) | |
623 | return true; | |
624 | ||
625 | return s->seat->active == s; | |
626 | } | |
627 | ||
a185c5aa LP |
628 | int session_get_idle_hint(Session *s, dual_timestamp *t) { |
629 | char *p; | |
630 | struct stat st; | |
631 | usec_t u, n; | |
632 | bool b; | |
633 | int k; | |
634 | ||
635 | assert(s); | |
636 | ||
637 | if (s->idle_hint) { | |
638 | if (t) | |
639 | *t = s->idle_hint_timestamp; | |
640 | ||
641 | return s->idle_hint; | |
642 | } | |
643 | ||
644 | if (isempty(s->tty)) | |
645 | goto dont_know; | |
646 | ||
647 | if (s->tty[0] != '/') { | |
648 | p = strappend("/dev/", s->tty); | |
649 | if (!p) | |
650 | return -ENOMEM; | |
651 | } else | |
652 | p = NULL; | |
653 | ||
654 | if (!startswith(p ? p : s->tty, "/dev/")) { | |
655 | free(p); | |
656 | goto dont_know; | |
657 | } | |
658 | ||
659 | k = lstat(p ? p : s->tty, &st); | |
660 | free(p); | |
661 | ||
662 | if (k < 0) | |
663 | goto dont_know; | |
664 | ||
665 | u = timespec_load(&st.st_atim); | |
666 | n = now(CLOCK_REALTIME); | |
667 | b = u + IDLE_THRESHOLD_USEC < n; | |
668 | ||
669 | if (t) | |
670 | dual_timestamp_from_realtime(t, u + b ? IDLE_THRESHOLD_USEC : 0); | |
671 | ||
672 | return b; | |
673 | ||
674 | dont_know: | |
675 | if (t) | |
676 | *t = s->idle_hint_timestamp; | |
677 | ||
678 | return 0; | |
679 | } | |
680 | ||
bef422ae LP |
681 | void session_set_idle_hint(Session *s, bool b) { |
682 | assert(s); | |
683 | ||
684 | if (s->idle_hint == b) | |
685 | return; | |
686 | ||
687 | s->idle_hint = b; | |
688 | dual_timestamp_get(&s->idle_hint_timestamp); | |
9418f147 LP |
689 | |
690 | session_send_changed(s, | |
691 | "IdleHint\0" | |
692 | "IdleSinceHint\0" | |
693 | "IdleSinceHintMonotonic\0"); | |
694 | ||
695 | if (s->seat) | |
696 | seat_send_changed(s->seat, | |
697 | "IdleHint\0" | |
698 | "IdleSinceHint\0" | |
699 | "IdleSinceHintMonotonic\0"); | |
700 | ||
701 | user_send_changed(s->user, | |
702 | "IdleHint\0" | |
703 | "IdleSinceHint\0" | |
704 | "IdleSinceHintMonotonic\0"); | |
705 | ||
706 | manager_send_changed(s->manager, | |
707 | "IdleHint\0" | |
708 | "IdleSinceHint\0" | |
709 | "IdleSinceHintMonotonic\0"); | |
bef422ae LP |
710 | } |
711 | ||
20263082 LP |
712 | int session_check_gc(Session *s) { |
713 | int r; | |
714 | ||
715 | assert(s); | |
716 | ||
717 | if (s->pipe_fd >= 0) { | |
718 | ||
719 | r = pipe_eof(s->pipe_fd); | |
720 | if (r < 0) | |
721 | return r; | |
722 | ||
14c3baca | 723 | if (r == 0) |
20263082 LP |
724 | return 1; |
725 | } | |
726 | ||
727 | if (s->cgroup_path) { | |
728 | ||
729 | r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false); | |
730 | if (r < 0) | |
731 | return r; | |
732 | ||
733 | if (r <= 0) | |
734 | return 1; | |
735 | } | |
736 | ||
737 | return 0; | |
738 | } | |
739 | ||
14c3baca LP |
740 | void session_add_to_gc_queue(Session *s) { |
741 | assert(s); | |
742 | ||
743 | if (s->in_gc_queue) | |
744 | return; | |
745 | ||
746 | LIST_PREPEND(Session, gc_queue, s->manager->session_gc_queue, s); | |
747 | s->in_gc_queue = true; | |
748 | } | |
749 | ||
20263082 | 750 | static const char* const session_type_table[_SESSION_TYPE_MAX] = { |
3f49d45a | 751 | [SESSION_TTY] = "tty", |
98a28fef LP |
752 | [SESSION_X11] = "x11", |
753 | [SESSION_OTHER] = "other" | |
20263082 LP |
754 | }; |
755 | ||
756 | DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType); |