]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session.c
util: don't require libcap when building libsystemd-shared
[thirdparty/systemd.git] / src / login / logind-session.c
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 Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser 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 #include <sys/epoll.h>
26 #include <fcntl.h>
27
28 #include "strv.h"
29 #include "util.h"
30 #include "mkdir.h"
31 #include "path-util.h"
32 #include "cgroup-util.h"
33 #include "logind-session.h"
34
35 #define IDLE_THRESHOLD_USEC (5*USEC_PER_MINUTE)
36
37 Session* session_new(Manager *m, User *u, const char *id) {
38 Session *s;
39
40 assert(m);
41 assert(id);
42
43 s = new0(Session, 1);
44 if (!s)
45 return NULL;
46
47 s->state_file = strappend("/run/systemd/sessions/", id);
48 if (!s->state_file) {
49 free(s);
50 return NULL;
51 }
52
53 s->id = path_get_file_name(s->state_file);
54
55 if (hashmap_put(m->sessions, s->id, s) < 0) {
56 free(s->state_file);
57 free(s);
58 return NULL;
59 }
60
61 s->manager = m;
62 s->fifo_fd = -1;
63 s->user = u;
64
65 LIST_PREPEND(Session, sessions_by_user, u->sessions, s);
66
67 return s;
68 }
69
70 void session_free(Session *s) {
71 assert(s);
72
73 if (s->in_gc_queue)
74 LIST_REMOVE(Session, gc_queue, s->manager->session_gc_queue, s);
75
76 if (s->user) {
77 LIST_REMOVE(Session, sessions_by_user, s->user->sessions, s);
78
79 if (s->user->display == s)
80 s->user->display = NULL;
81 }
82
83 if (s->seat) {
84 if (s->seat->active == s)
85 s->seat->active = NULL;
86
87 LIST_REMOVE(Session, sessions_by_seat, s->seat->sessions, s);
88 }
89
90 if (s->cgroup_path)
91 hashmap_remove(s->manager->cgroups, s->cgroup_path);
92
93 free(s->cgroup_path);
94 strv_free(s->controllers);
95
96 free(s->tty);
97 free(s->display);
98 free(s->remote_host);
99 free(s->remote_user);
100 free(s->service);
101
102 hashmap_remove(s->manager->sessions, s->id);
103 session_remove_fifo(s);
104
105 free(s->state_file);
106 free(s);
107 }
108
109 int session_save(Session *s) {
110 FILE *f;
111 int r = 0;
112 char *temp_path;
113
114 assert(s);
115
116 if (!s->started)
117 return 0;
118
119 r = safe_mkdir("/run/systemd/sessions", 0755, 0, 0);
120 if (r < 0)
121 goto finish;
122
123 r = fopen_temporary(s->state_file, &f, &temp_path);
124 if (r < 0)
125 goto finish;
126
127 assert(s->user);
128
129 fchmod(fileno(f), 0644);
130
131 fprintf(f,
132 "# This is private data. Do not parse.\n"
133 "UID=%lu\n"
134 "USER=%s\n"
135 "ACTIVE=%i\n"
136 "REMOTE=%i\n"
137 "KILL_PROCESSES=%i\n",
138 (unsigned long) s->user->uid,
139 s->user->name,
140 session_is_active(s),
141 s->remote,
142 s->kill_processes);
143
144 if (s->type >= 0)
145 fprintf(f,
146 "TYPE=%s\n",
147 session_type_to_string(s->type));
148
149 if (s->class >= 0)
150 fprintf(f,
151 "CLASS=%s\n",
152 session_class_to_string(s->class));
153
154 if (s->cgroup_path)
155 fprintf(f,
156 "CGROUP=%s\n",
157 s->cgroup_path);
158
159 if (s->fifo_path)
160 fprintf(f,
161 "FIFO=%s\n",
162 s->fifo_path);
163
164 if (s->seat)
165 fprintf(f,
166 "SEAT=%s\n",
167 s->seat->id);
168
169 if (s->tty)
170 fprintf(f,
171 "TTY=%s\n",
172 s->tty);
173
174 if (s->display)
175 fprintf(f,
176 "DISPLAY=%s\n",
177 s->display);
178
179 if (s->remote_host)
180 fprintf(f,
181 "REMOTE_HOST=%s\n",
182 s->remote_host);
183
184 if (s->remote_user)
185 fprintf(f,
186 "REMOTE_USER=%s\n",
187 s->remote_user);
188
189 if (s->service)
190 fprintf(f,
191 "SERVICE=%s\n",
192 s->service);
193
194 if (s->seat && seat_can_multi_session(s->seat))
195 fprintf(f,
196 "VTNR=%i\n",
197 s->vtnr);
198
199 if (s->leader > 0)
200 fprintf(f,
201 "LEADER=%lu\n",
202 (unsigned long) s->leader);
203
204 if (s->audit_id > 0)
205 fprintf(f,
206 "AUDIT=%llu\n",
207 (unsigned long long) s->audit_id);
208
209 fflush(f);
210
211 if (ferror(f) || rename(temp_path, s->state_file) < 0) {
212 r = -errno;
213 unlink(s->state_file);
214 unlink(temp_path);
215 }
216
217 fclose(f);
218 free(temp_path);
219
220 finish:
221 if (r < 0)
222 log_error("Failed to save session data for %s: %s", s->id, strerror(-r));
223
224 return r;
225 }
226
227 int session_load(Session *s) {
228 char *remote = NULL,
229 *kill_processes = NULL,
230 *seat = NULL,
231 *vtnr = NULL,
232 *leader = NULL,
233 *audit_id = NULL,
234 *type = NULL,
235 *class = NULL;
236
237 int k, r;
238
239 assert(s);
240
241 r = parse_env_file(s->state_file, NEWLINE,
242 "REMOTE", &remote,
243 "KILL_PROCESSES", &kill_processes,
244 "CGROUP", &s->cgroup_path,
245 "FIFO", &s->fifo_path,
246 "SEAT", &seat,
247 "TTY", &s->tty,
248 "DISPLAY", &s->display,
249 "REMOTE_HOST", &s->remote_host,
250 "REMOTE_USER", &s->remote_user,
251 "SERVICE", &s->service,
252 "VTNR", &vtnr,
253 "LEADER", &leader,
254 "TYPE", &type,
255 "CLASS", &class,
256 NULL);
257
258 if (r < 0)
259 goto finish;
260
261 if (remote) {
262 k = parse_boolean(remote);
263 if (k >= 0)
264 s->remote = k;
265 }
266
267 if (kill_processes) {
268 k = parse_boolean(kill_processes);
269 if (k >= 0)
270 s->kill_processes = k;
271 }
272
273 if (seat && !s->seat) {
274 Seat *o;
275
276 o = hashmap_get(s->manager->seats, seat);
277 if (o)
278 seat_attach_session(o, s);
279 }
280
281 if (vtnr && s->seat && seat_can_multi_session(s->seat)) {
282 int v;
283
284 k = safe_atoi(vtnr, &v);
285 if (k >= 0 && v >= 1)
286 s->vtnr = v;
287 }
288
289 if (leader) {
290 k = parse_pid(leader, &s->leader);
291 if (k >= 0)
292 audit_session_from_pid(s->leader, &s->audit_id);
293 }
294
295 if (type) {
296 SessionType t;
297
298 t = session_type_from_string(type);
299 if (t >= 0)
300 s->type = t;
301 }
302
303 if (class) {
304 SessionClass c;
305
306 c = session_class_from_string(class);
307 if (c >= 0)
308 s->class = c;
309 }
310
311 if (s->fifo_path) {
312 int fd;
313
314 /* If we open an unopened pipe for reading we will not
315 get an EOF. to trigger an EOF we hence open it for
316 reading, but close it right-away which then will
317 trigger the EOF. */
318
319 fd = session_create_fifo(s);
320 if (fd >= 0)
321 close_nointr_nofail(fd);
322 }
323
324 finish:
325 free(remote);
326 free(kill_processes);
327 free(seat);
328 free(vtnr);
329 free(leader);
330 free(audit_id);
331 free(class);
332
333 return r;
334 }
335
336 int session_activate(Session *s) {
337 int r;
338
339 assert(s);
340
341 if (s->vtnr < 0)
342 return -ENOTSUP;
343
344 if (!s->seat)
345 return -ENOTSUP;
346
347 if (s->seat->active == s)
348 return 0;
349
350 assert(seat_is_vtconsole(s->seat));
351
352 r = chvt(s->vtnr);
353 if (r < 0)
354 return r;
355
356 return seat_set_active(s->seat, s);
357 }
358
359 static int session_link_x11_socket(Session *s) {
360 char *t, *f, *c;
361 size_t k;
362
363 assert(s);
364 assert(s->user);
365 assert(s->user->runtime_path);
366
367 if (s->user->display)
368 return 0;
369
370 if (!s->display || !display_is_local(s->display))
371 return 0;
372
373 k = strspn(s->display+1, "0123456789");
374 f = new(char, sizeof("/tmp/.X11-unix/X") + k);
375 if (!f) {
376 log_error("Out of memory");
377 return -ENOMEM;
378 }
379
380 c = stpcpy(f, "/tmp/.X11-unix/X");
381 memcpy(c, s->display+1, k);
382 c[k] = 0;
383
384 if (access(f, F_OK) < 0) {
385 log_warning("Session %s has display %s with non-existing socket %s.", s->id, s->display, f);
386 free(f);
387 return -ENOENT;
388 }
389
390 /* Note that this cannot be in a subdir to avoid
391 * vulnerabilities since we are privileged but the runtime
392 * path is owned by the user */
393
394 t = strappend(s->user->runtime_path, "/X11-display");
395 if (!t) {
396 log_error("Out of memory");
397 free(f);
398 return -ENOMEM;
399 }
400
401 if (link(f, t) < 0) {
402 if (errno == EEXIST) {
403 unlink(t);
404
405 if (link(f, t) >= 0)
406 goto done;
407 }
408
409 if (symlink(f, t) < 0) {
410
411 if (errno == EEXIST) {
412 unlink(t);
413
414 if (symlink(f, t) >= 0)
415 goto done;
416 }
417
418 log_error("Failed to link %s to %s: %m", f, t);
419 free(f);
420 free(t);
421 return -errno;
422 }
423 }
424
425 done:
426 log_info("Linked %s to %s.", f, t);
427 free(f);
428 free(t);
429
430 s->user->display = s;
431
432 return 0;
433 }
434
435 static int session_create_one_group(Session *s, const char *controller, const char *path) {
436 int r;
437
438 assert(s);
439 assert(controller);
440 assert(path);
441
442 if (s->leader > 0) {
443 r = cg_create_and_attach(controller, path, s->leader);
444 if (r < 0)
445 r = cg_create(controller, path);
446 } else
447 r = cg_create(controller, path);
448
449 if (r < 0)
450 return r;
451
452 r = cg_set_task_access(controller, path, 0644, s->user->uid, s->user->gid, -1);
453 if (r >= 0)
454 r = cg_set_group_access(controller, path, 0755, s->user->uid, s->user->gid);
455
456 return r;
457 }
458
459 static int session_create_cgroup(Session *s) {
460 char **k;
461 char *p;
462 int r;
463
464 assert(s);
465 assert(s->user);
466 assert(s->user->cgroup_path);
467
468 if (!s->cgroup_path) {
469 if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0) {
470 log_error("Out of memory");
471 return -ENOMEM;
472 }
473 } else
474 p = s->cgroup_path;
475
476 r = session_create_one_group(s, SYSTEMD_CGROUP_CONTROLLER, p);
477 if (r < 0) {
478 log_error("Failed to create "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
479 free(p);
480 s->cgroup_path = NULL;
481 return r;
482 }
483
484 s->cgroup_path = p;
485
486 STRV_FOREACH(k, s->controllers) {
487
488 if (strv_contains(s->reset_controllers, *k))
489 continue;
490
491 r = session_create_one_group(s, *k, p);
492 if (r < 0)
493 log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r));
494 }
495
496 STRV_FOREACH(k, s->manager->controllers) {
497
498 if (strv_contains(s->reset_controllers, *k) ||
499 strv_contains(s->manager->reset_controllers, *k) ||
500 strv_contains(s->controllers, *k))
501 continue;
502
503 r = session_create_one_group(s, *k, p);
504 if (r < 0)
505 log_warning("Failed to create %s:%s: %s", *k, p, strerror(-r));
506 }
507
508 if (s->leader > 0) {
509
510 STRV_FOREACH(k, s->reset_controllers) {
511 r = cg_attach(*k, "/", s->leader);
512 if (r < 0)
513 log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
514
515 }
516
517 STRV_FOREACH(k, s->manager->reset_controllers) {
518
519 if (strv_contains(s->reset_controllers, *k) ||
520 strv_contains(s->controllers, *k))
521 continue;
522
523 r = cg_attach(*k, "/", s->leader);
524 if (r < 0)
525 log_warning("Failed to reset controller %s: %s", *k, strerror(-r));
526
527 }
528 }
529
530 hashmap_put(s->manager->cgroups, s->cgroup_path, s);
531
532 return 0;
533 }
534
535 int session_start(Session *s) {
536 int r;
537
538 assert(s);
539 assert(s->user);
540
541 if (s->started)
542 return 0;
543
544 r = user_start(s->user);
545 if (r < 0)
546 return r;
547
548 log_full(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
549 "New session %s of user %s.", s->id, s->user->name);
550
551 /* Create cgroup */
552 r = session_create_cgroup(s);
553 if (r < 0)
554 return r;
555
556 /* Create X11 symlink */
557 session_link_x11_socket(s);
558
559 dual_timestamp_get(&s->timestamp);
560
561 if (s->seat)
562 seat_read_active_vt(s->seat);
563
564 s->started = true;
565
566 /* Save session data */
567 session_save(s);
568 user_save(s->user);
569
570 session_send_signal(s, true);
571
572 if (s->seat) {
573 seat_save(s->seat);
574
575 if (s->seat->active == s)
576 seat_send_changed(s->seat, "Sessions\0ActiveSession\0");
577 else
578 seat_send_changed(s->seat, "Sessions\0");
579 }
580
581 user_send_changed(s->user, "Sessions\0");
582
583 return 0;
584 }
585
586 static bool session_shall_kill(Session *s) {
587 assert(s);
588
589 if (!s->kill_processes)
590 return false;
591
592 if (strv_contains(s->manager->kill_exclude_users, s->user->name))
593 return false;
594
595 if (strv_isempty(s->manager->kill_only_users))
596 return true;
597
598 return strv_contains(s->manager->kill_only_users, s->user->name);
599 }
600
601 static int session_terminate_cgroup(Session *s) {
602 int r;
603 char **k;
604
605 assert(s);
606
607 if (!s->cgroup_path)
608 return 0;
609
610 cg_trim(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false);
611
612 if (session_shall_kill(s)) {
613
614 r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
615 if (r < 0)
616 log_error("Failed to kill session cgroup: %s", strerror(-r));
617
618 } else {
619 if (s->leader > 0) {
620 Session *t;
621
622 /* We still send a HUP to the leader process,
623 * even if we are not supposed to kill the
624 * whole cgroup. But let's first check the
625 * leader still exists and belongs to our
626 * session... */
627
628 r = manager_get_session_by_pid(s->manager, s->leader, &t);
629 if (r > 0 && t == s) {
630 kill(s->leader, SIGTERM); /* for normal processes */
631 kill(s->leader, SIGHUP); /* for shells */
632 kill(s->leader, SIGCONT); /* in case they are stopped */
633 }
634 }
635
636 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, true);
637 if (r < 0)
638 log_error("Failed to check session cgroup: %s", strerror(-r));
639 else if (r > 0) {
640 r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path);
641 if (r < 0)
642 log_error("Failed to delete session cgroup: %s", strerror(-r));
643 }
644 }
645
646 STRV_FOREACH(k, s->user->manager->controllers)
647 cg_trim(*k, s->cgroup_path, true);
648
649 hashmap_remove(s->manager->cgroups, s->cgroup_path);
650
651 free(s->cgroup_path);
652 s->cgroup_path = NULL;
653
654 return 0;
655 }
656
657 static int session_unlink_x11_socket(Session *s) {
658 char *t;
659 int r;
660
661 assert(s);
662 assert(s->user);
663
664 if (s->user->display != s)
665 return 0;
666
667 s->user->display = NULL;
668
669 t = strappend(s->user->runtime_path, "/X11-display");
670 if (!t) {
671 log_error("Out of memory");
672 return -ENOMEM;
673 }
674
675 r = unlink(t);
676 free(t);
677
678 return r < 0 ? -errno : 0;
679 }
680
681 int session_stop(Session *s) {
682 int r = 0, k;
683
684 assert(s);
685
686 if (s->started)
687 log_full(s->type == SESSION_TTY || s->type == SESSION_X11 ? LOG_INFO : LOG_DEBUG,
688 "Removed session %s.", s->id);
689
690 /* Kill cgroup */
691 k = session_terminate_cgroup(s);
692 if (k < 0)
693 r = k;
694
695 /* Remove X11 symlink */
696 session_unlink_x11_socket(s);
697
698 unlink(s->state_file);
699 session_add_to_gc_queue(s);
700 user_add_to_gc_queue(s->user);
701
702 if (s->started)
703 session_send_signal(s, false);
704
705 if (s->seat) {
706 if (s->seat->active == s)
707 seat_set_active(s->seat, NULL);
708
709 seat_send_changed(s->seat, "Sessions\0");
710 }
711
712 user_send_changed(s->user, "Sessions\0");
713
714 s->started = false;
715
716 return r;
717 }
718
719 bool session_is_active(Session *s) {
720 assert(s);
721
722 if (!s->seat)
723 return true;
724
725 return s->seat->active == s;
726 }
727
728 int session_get_idle_hint(Session *s, dual_timestamp *t) {
729 char *p;
730 struct stat st;
731 usec_t u, n;
732 bool b;
733 int k;
734
735 assert(s);
736
737 if (s->idle_hint) {
738 if (t)
739 *t = s->idle_hint_timestamp;
740
741 return s->idle_hint;
742 }
743
744 if (isempty(s->tty))
745 goto dont_know;
746
747 if (s->tty[0] != '/') {
748 p = strappend("/dev/", s->tty);
749 if (!p)
750 return -ENOMEM;
751 } else
752 p = NULL;
753
754 if (!startswith(p ? p : s->tty, "/dev/")) {
755 free(p);
756 goto dont_know;
757 }
758
759 k = lstat(p ? p : s->tty, &st);
760 free(p);
761
762 if (k < 0)
763 goto dont_know;
764
765 u = timespec_load(&st.st_atim);
766 n = now(CLOCK_REALTIME);
767 b = u + IDLE_THRESHOLD_USEC < n;
768
769 if (t)
770 dual_timestamp_from_realtime(t, u + b ? IDLE_THRESHOLD_USEC : 0);
771
772 return b;
773
774 dont_know:
775 if (t)
776 *t = s->idle_hint_timestamp;
777
778 return 0;
779 }
780
781 void session_set_idle_hint(Session *s, bool b) {
782 assert(s);
783
784 if (s->idle_hint == b)
785 return;
786
787 s->idle_hint = b;
788 dual_timestamp_get(&s->idle_hint_timestamp);
789
790 session_send_changed(s,
791 "IdleHint\0"
792 "IdleSinceHint\0"
793 "IdleSinceHintMonotonic\0");
794
795 if (s->seat)
796 seat_send_changed(s->seat,
797 "IdleHint\0"
798 "IdleSinceHint\0"
799 "IdleSinceHintMonotonic\0");
800
801 user_send_changed(s->user,
802 "IdleHint\0"
803 "IdleSinceHint\0"
804 "IdleSinceHintMonotonic\0");
805
806 manager_send_changed(s->manager,
807 "IdleHint\0"
808 "IdleSinceHint\0"
809 "IdleSinceHintMonotonic\0");
810 }
811
812 int session_create_fifo(Session *s) {
813 int r;
814
815 assert(s);
816
817 /* Create FIFO */
818 if (!s->fifo_path) {
819 r = safe_mkdir("/run/systemd/sessions", 0755, 0, 0);
820 if (r < 0)
821 return r;
822
823 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
824 return -ENOMEM;
825
826 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
827 return -errno;
828 }
829
830 /* Open reading side */
831 if (s->fifo_fd < 0) {
832 struct epoll_event ev;
833
834 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
835 if (s->fifo_fd < 0)
836 return -errno;
837
838 r = hashmap_put(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1), s);
839 if (r < 0)
840 return r;
841
842 zero(ev);
843 ev.events = 0;
844 ev.data.u32 = FD_OTHER_BASE + s->fifo_fd;
845
846 if (epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_ADD, s->fifo_fd, &ev) < 0)
847 return -errno;
848 }
849
850 /* Open writing side */
851 r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
852 if (r < 0)
853 return -errno;
854
855 return r;
856 }
857
858 void session_remove_fifo(Session *s) {
859 assert(s);
860
861 if (s->fifo_fd >= 0) {
862 assert_se(hashmap_remove(s->manager->session_fds, INT_TO_PTR(s->fifo_fd + 1)) == s);
863 assert_se(epoll_ctl(s->manager->epoll_fd, EPOLL_CTL_DEL, s->fifo_fd, NULL) == 0);
864 close_nointr_nofail(s->fifo_fd);
865 s->fifo_fd = -1;
866 }
867
868 if (s->fifo_path) {
869 unlink(s->fifo_path);
870 free(s->fifo_path);
871 s->fifo_path = NULL;
872 }
873 }
874
875 int session_check_gc(Session *s, bool drop_not_started) {
876 int r;
877
878 assert(s);
879
880 if (drop_not_started && !s->started)
881 return 0;
882
883 if (s->fifo_fd >= 0) {
884
885 r = pipe_eof(s->fifo_fd);
886 if (r < 0)
887 return r;
888
889 if (r == 0)
890 return 1;
891 }
892
893 if (s->cgroup_path) {
894
895 r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, false);
896 if (r < 0)
897 return r;
898
899 if (r <= 0)
900 return 1;
901 }
902
903 return 0;
904 }
905
906 void session_add_to_gc_queue(Session *s) {
907 assert(s);
908
909 if (s->in_gc_queue)
910 return;
911
912 LIST_PREPEND(Session, gc_queue, s->manager->session_gc_queue, s);
913 s->in_gc_queue = true;
914 }
915
916 int session_kill(Session *s, KillWho who, int signo) {
917 int r = 0;
918 Set *pid_set = NULL;
919
920 assert(s);
921
922 if (!s->cgroup_path)
923 return -ESRCH;
924
925 if (s->leader <= 0 && who == KILL_LEADER)
926 return -ESRCH;
927
928 if (s->leader > 0)
929 if (kill(s->leader, signo) < 0)
930 r = -errno;
931
932 if (who == KILL_ALL) {
933 int q;
934
935 pid_set = set_new(trivial_hash_func, trivial_compare_func);
936 if (!pid_set)
937 return -ENOMEM;
938
939 if (s->leader > 0) {
940 q = set_put(pid_set, LONG_TO_PTR(s->leader));
941 if (q < 0)
942 r = q;
943 }
944
945 q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, s->cgroup_path, signo, false, true, false, pid_set);
946 if (q < 0)
947 if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
948 r = q;
949 }
950
951 if (pid_set)
952 set_free(pid_set);
953
954 return r;
955 }
956
957 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
958 [SESSION_TTY] = "tty",
959 [SESSION_X11] = "x11",
960 [SESSION_UNSPECIFIED] = "unspecified"
961 };
962
963 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
964
965 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
966 [SESSION_USER] = "user",
967 [SESSION_GREETER] = "greeter",
968 [SESSION_LOCK_SCREEN] = "lock-screen"
969 };
970
971 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
972
973 static const char* const kill_who_table[_KILL_WHO_MAX] = {
974 [KILL_LEADER] = "leader",
975 [KILL_ALL] = "all"
976 };
977
978 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);