chiark / gitweb /
logind: properly clean up user cgroups when they run empty
[elogind.git] / src / login / logind.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 <pwd.h>
24 #include <libudev.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/epoll.h>
29 #include <sys/ioctl.h>
30 #include <linux/vt.h>
31
32 #include <systemd/sd-daemon.h>
33
34 #include "logind.h"
35 #include "dbus-common.h"
36 #include "dbus-loop.h"
37 #include "strv.h"
38 #include "conf-parser.h"
39
40 Manager *manager_new(void) {
41         Manager *m;
42
43         m = new0(Manager, 1);
44         if (!m)
45                 return NULL;
46
47         m->console_active_fd = -1;
48         m->bus_fd = -1;
49         m->udev_seat_fd = -1;
50         m->udev_vcsa_fd = -1;
51         m->udev_button_fd = -1;
52         m->epoll_fd = -1;
53
54         m->n_autovts = 6;
55         m->inhibit_delay_max = 5 * USEC_PER_SEC;
56         m->handle_power_key = HANDLE_NO_SESSION;
57         m->handle_sleep_key = HANDLE_TTY_SESSION;
58         m->handle_lid_switch = HANDLE_OFF;
59
60         m->devices = hashmap_new(string_hash_func, string_compare_func);
61         m->seats = hashmap_new(string_hash_func, string_compare_func);
62         m->sessions = hashmap_new(string_hash_func, string_compare_func);
63         m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
64         m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
65         m->buttons = hashmap_new(string_hash_func, string_compare_func);
66
67         m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
68         m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
69
70         m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
71         m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
72         m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
73
74         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
75             !m->user_cgroups || !m->session_cgroups ||
76             !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
77                 manager_free(m);
78                 return NULL;
79         }
80
81         m->reset_controllers = strv_new("cpu", NULL);
82         m->kill_exclude_users = strv_new("root", NULL);
83         if (!m->reset_controllers || !m->kill_exclude_users) {
84                 manager_free(m);
85                 return NULL;
86         }
87
88         m->udev = udev_new();
89         if (!m->udev) {
90                 manager_free(m);
91                 return NULL;
92         }
93
94         if (cg_get_user_path(&m->cgroup_path) < 0) {
95                 manager_free(m);
96                 return NULL;
97         }
98
99         return m;
100 }
101
102 void manager_free(Manager *m) {
103         Session *session;
104         User *u;
105         Device *d;
106         Seat *s;
107         Inhibitor *i;
108         Button *b;
109
110         assert(m);
111
112         while ((session = hashmap_first(m->sessions)))
113                 session_free(session);
114
115         while ((u = hashmap_first(m->users)))
116                 user_free(u);
117
118         while ((d = hashmap_first(m->devices)))
119                 device_free(d);
120
121         while ((s = hashmap_first(m->seats)))
122                 seat_free(s);
123
124         while ((i = hashmap_first(m->inhibitors)))
125                 inhibitor_free(i);
126
127         while ((b = hashmap_first(m->buttons)))
128                 button_free(b);
129
130         hashmap_free(m->devices);
131         hashmap_free(m->seats);
132         hashmap_free(m->sessions);
133         hashmap_free(m->users);
134         hashmap_free(m->inhibitors);
135         hashmap_free(m->buttons);
136
137         hashmap_free(m->user_cgroups);
138         hashmap_free(m->session_cgroups);
139
140         hashmap_free(m->session_fds);
141         hashmap_free(m->inhibitor_fds);
142         hashmap_free(m->button_fds);
143
144         if (m->console_active_fd >= 0)
145                 close_nointr_nofail(m->console_active_fd);
146
147         if (m->udev_seat_monitor)
148                 udev_monitor_unref(m->udev_seat_monitor);
149         if (m->udev_vcsa_monitor)
150                 udev_monitor_unref(m->udev_vcsa_monitor);
151         if (m->udev_button_monitor)
152                 udev_monitor_unref(m->udev_button_monitor);
153
154         if (m->udev)
155                 udev_unref(m->udev);
156
157         if (m->bus) {
158                 dbus_connection_flush(m->bus);
159                 dbus_connection_close(m->bus);
160                 dbus_connection_unref(m->bus);
161         }
162
163         if (m->bus_fd >= 0)
164                 close_nointr_nofail(m->bus_fd);
165
166         if (m->epoll_fd >= 0)
167                 close_nointr_nofail(m->epoll_fd);
168
169         strv_free(m->controllers);
170         strv_free(m->reset_controllers);
171         strv_free(m->kill_only_users);
172         strv_free(m->kill_exclude_users);
173
174         free(m->cgroup_path);
175         free(m);
176 }
177
178 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
179         Device *d;
180
181         assert(m);
182         assert(sysfs);
183
184         d = hashmap_get(m->devices, sysfs);
185         if (d) {
186                 if (_device)
187                         *_device = d;
188
189                 return 0;
190         }
191
192         d = device_new(m, sysfs);
193         if (!d)
194                 return -ENOMEM;
195
196         if (_device)
197                 *_device = d;
198
199         return 0;
200 }
201
202 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
203         Seat *s;
204
205         assert(m);
206         assert(id);
207
208         s = hashmap_get(m->seats, id);
209         if (s) {
210                 if (_seat)
211                         *_seat = s;
212
213                 return 0;
214         }
215
216         s = seat_new(m, id);
217         if (!s)
218                 return -ENOMEM;
219
220         if (_seat)
221                 *_seat = s;
222
223         return 0;
224 }
225
226 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
227         Session *s;
228
229         assert(m);
230         assert(id);
231
232         s = hashmap_get(m->sessions, id);
233         if (s) {
234                 if (_session)
235                         *_session = s;
236
237                 return 0;
238         }
239
240         s = session_new(m, u, id);
241         if (!s)
242                 return -ENOMEM;
243
244         if (_session)
245                 *_session = s;
246
247         return 0;
248 }
249
250 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
251         User *u;
252
253         assert(m);
254         assert(name);
255
256         u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
257         if (u) {
258                 if (_user)
259                         *_user = u;
260
261                 return 0;
262         }
263
264         u = user_new(m, uid, gid, name);
265         if (!u)
266                 return -ENOMEM;
267
268         if (_user)
269                 *_user = u;
270
271         return 0;
272 }
273
274 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
275         uid_t uid;
276         gid_t gid;
277         int r;
278
279         assert(m);
280         assert(name);
281
282         r = get_user_creds(&name, &uid, &gid, NULL);
283         if (r < 0)
284                 return r;
285
286         return manager_add_user(m, uid, gid, name, _user);
287 }
288
289 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
290         struct passwd *p;
291
292         assert(m);
293
294         errno = 0;
295         p = getpwuid(uid);
296         if (!p)
297                 return errno ? -errno : -ENOENT;
298
299         return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
300 }
301
302 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
303         Inhibitor *i;
304
305         assert(m);
306         assert(id);
307
308         i = hashmap_get(m->inhibitors, id);
309         if (i) {
310                 if (_inhibitor)
311                         *_inhibitor = i;
312
313                 return 0;
314         }
315
316         i = inhibitor_new(m, id);
317         if (!i)
318                 return -ENOMEM;
319
320         if (_inhibitor)
321                 *_inhibitor = i;
322
323         return 0;
324 }
325
326 int manager_add_button(Manager *m, const char *name, Button **_button) {
327         Button *b;
328
329         assert(m);
330         assert(name);
331
332         b = hashmap_get(m->buttons, name);
333         if (b) {
334                 if (_button)
335                         *_button = b;
336
337                 return 0;
338         }
339
340         b = button_new(m, name);
341         if (!b)
342                 return -ENOMEM;
343
344         if (_button)
345                 *_button = b;
346
347         return 0;
348 }
349
350 int manager_process_seat_device(Manager *m, struct udev_device *d) {
351         Device *device;
352         int r;
353
354         assert(m);
355
356         if (streq_ptr(udev_device_get_action(d), "remove")) {
357
358                 device = hashmap_get(m->devices, udev_device_get_syspath(d));
359                 if (!device)
360                         return 0;
361
362                 seat_add_to_gc_queue(device->seat);
363                 device_free(device);
364
365         } else {
366                 const char *sn;
367                 Seat *seat;
368
369                 sn = udev_device_get_property_value(d, "ID_SEAT");
370                 if (isempty(sn))
371                         sn = "seat0";
372
373                 if (!seat_name_is_valid(sn)) {
374                         log_warning("Device with invalid seat name %s found, ignoring.", sn);
375                         return 0;
376                 }
377
378                 r = manager_add_device(m, udev_device_get_syspath(d), &device);
379                 if (r < 0)
380                         return r;
381
382                 r = manager_add_seat(m, sn, &seat);
383                 if (r < 0) {
384                         if (!device->seat)
385                                 device_free(device);
386
387                         return r;
388                 }
389
390                 device_attach(device, seat);
391                 seat_start(seat);
392         }
393
394         return 0;
395 }
396
397 int manager_process_button_device(Manager *m, struct udev_device *d) {
398         Button *b;
399
400         int r;
401
402         assert(m);
403
404         if (streq_ptr(udev_device_get_action(d), "remove")) {
405
406                 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
407                 if (!b)
408                         return 0;
409
410                 button_free(b);
411
412         } else {
413                 const char *sn;
414
415                 r = manager_add_button(m, udev_device_get_sysname(d), &b);
416                 if (r < 0)
417                         return r;
418
419                 sn = udev_device_get_property_value(d, "ID_SEAT");
420                 if (isempty(sn))
421                         sn = "seat0";
422
423                 button_set_seat(b, sn);
424                 button_open(b);
425         }
426
427         return 0;
428 }
429
430 int manager_enumerate_devices(Manager *m) {
431         struct udev_list_entry *item = NULL, *first = NULL;
432         struct udev_enumerate *e;
433         int r;
434
435         assert(m);
436
437         /* Loads devices from udev and creates seats for them as
438          * necessary */
439
440         e = udev_enumerate_new(m->udev);
441         if (!e) {
442                 r = -ENOMEM;
443                 goto finish;
444         }
445
446         r = udev_enumerate_add_match_subsystem(e, "graphics");
447         if (r < 0)
448                 goto finish;
449
450         r = udev_enumerate_add_match_tag(e, "seat");
451         if (r < 0)
452                 goto finish;
453
454         r = udev_enumerate_scan_devices(e);
455         if (r < 0)
456                 goto finish;
457
458         first = udev_enumerate_get_list_entry(e);
459         udev_list_entry_foreach(item, first) {
460                 struct udev_device *d;
461                 int k;
462
463                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
464                 if (!d) {
465                         r = -ENOMEM;
466                         goto finish;
467                 }
468
469                 k = manager_process_seat_device(m, d);
470                 udev_device_unref(d);
471
472                 if (k < 0)
473                         r = k;
474         }
475
476 finish:
477         if (e)
478                 udev_enumerate_unref(e);
479
480         return r;
481 }
482
483 int manager_enumerate_buttons(Manager *m) {
484         struct udev_list_entry *item = NULL, *first = NULL;
485         struct udev_enumerate *e;
486         int r;
487
488         assert(m);
489
490         /* Loads buttons from udev */
491
492         if (m->handle_power_key == HANDLE_OFF &&
493             m->handle_sleep_key == HANDLE_OFF &&
494             m->handle_lid_switch == HANDLE_OFF)
495                 return 0;
496
497         e = udev_enumerate_new(m->udev);
498         if (!e) {
499                 r = -ENOMEM;
500                 goto finish;
501         }
502
503         r = udev_enumerate_add_match_subsystem(e, "input");
504         if (r < 0)
505                 goto finish;
506
507         r = udev_enumerate_add_match_tag(e, "power-switch");
508         if (r < 0)
509                 goto finish;
510
511         r = udev_enumerate_scan_devices(e);
512         if (r < 0)
513                 goto finish;
514
515         first = udev_enumerate_get_list_entry(e);
516         udev_list_entry_foreach(item, first) {
517                 struct udev_device *d;
518                 int k;
519
520                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
521                 if (!d) {
522                         r = -ENOMEM;
523                         goto finish;
524                 }
525
526                 k = manager_process_button_device(m, d);
527                 udev_device_unref(d);
528
529                 if (k < 0)
530                         r = k;
531         }
532
533 finish:
534         if (e)
535                 udev_enumerate_unref(e);
536
537         return r;
538 }
539
540 int manager_enumerate_seats(Manager *m) {
541         DIR *d;
542         struct dirent *de;
543         int r = 0;
544
545         assert(m);
546
547         /* This loads data about seats stored on disk, but does not
548          * actually create any seats. Removes data of seats that no
549          * longer exist. */
550
551         d = opendir("/run/systemd/seats");
552         if (!d) {
553                 if (errno == ENOENT)
554                         return 0;
555
556                 log_error("Failed to open /run/systemd/seats: %m");
557                 return -errno;
558         }
559
560         while ((de = readdir(d))) {
561                 Seat *s;
562                 int k;
563
564                 if (!dirent_is_file(de))
565                         continue;
566
567                 s = hashmap_get(m->seats, de->d_name);
568                 if (!s) {
569                         unlinkat(dirfd(d), de->d_name, 0);
570                         continue;
571                 }
572
573                 k = seat_load(s);
574                 if (k < 0)
575                         r = k;
576         }
577
578         closedir(d);
579
580         return r;
581 }
582
583 static int manager_enumerate_users_from_cgroup(Manager *m) {
584         int r = 0, k;
585         char *name;
586         DIR *d;
587
588         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
589         if (r < 0) {
590                 if (r == -ENOENT)
591                         return 0;
592
593                 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
594                 return r;
595         }
596
597         while ((k = cg_read_subgroup(d, &name)) > 0) {
598                 User *user;
599
600                 k = manager_add_user_by_name(m, name, &user);
601                 if (k < 0) {
602                         free(name);
603                         r = k;
604                         continue;
605                 }
606
607                 user_add_to_gc_queue(user);
608
609                 if (!user->cgroup_path)
610                         if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
611                                 r = -ENOMEM;
612                                 free(name);
613                                 break;
614                         }
615
616                 free(name);
617         }
618
619         if (r >= 0 && k < 0)
620                 r = k;
621
622         closedir(d);
623
624         return r;
625 }
626
627 static int manager_enumerate_linger_users(Manager *m) {
628         DIR *d;
629         struct dirent *de;
630         int r = 0;
631
632         d = opendir("/var/lib/systemd/linger");
633         if (!d) {
634                 if (errno == ENOENT)
635                         return 0;
636
637                 log_error("Failed to open /var/lib/systemd/linger/: %m");
638                 return -errno;
639         }
640
641         while ((de = readdir(d))) {
642                 int k;
643
644                 if (!dirent_is_file(de))
645                         continue;
646
647                 k = manager_add_user_by_name(m, de->d_name, NULL);
648                 if (k < 0) {
649                         log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
650                         r = k;
651                 }
652         }
653
654         closedir(d);
655
656         return r;
657 }
658
659 int manager_enumerate_users(Manager *m) {
660         DIR *d;
661         struct dirent *de;
662         int r, k;
663
664         assert(m);
665
666         /* First, enumerate user cgroups */
667         r = manager_enumerate_users_from_cgroup(m);
668
669         /* Second, add lingering users on top */
670         k = manager_enumerate_linger_users(m);
671         if (k < 0)
672                 r = k;
673
674         /* Third, read in user data stored on disk */
675         d = opendir("/run/systemd/users");
676         if (!d) {
677                 if (errno == ENOENT)
678                         return 0;
679
680                 log_error("Failed to open /run/systemd/users: %m");
681                 return -errno;
682         }
683
684         while ((de = readdir(d))) {
685                 uid_t uid;
686                 User *u;
687
688                 if (!dirent_is_file(de))
689                         continue;
690
691                 k = parse_uid(de->d_name, &uid);
692                 if (k < 0) {
693                         log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
694                         continue;
695                 }
696
697                 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
698                 if (!u) {
699                         unlinkat(dirfd(d), de->d_name, 0);
700                         continue;
701                 }
702
703                 k = user_load(u);
704                 if (k < 0)
705                         r = k;
706         }
707
708         closedir(d);
709
710         return r;
711 }
712
713 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
714         User *u;
715         Iterator i;
716         int r = 0;
717
718         HASHMAP_FOREACH(u, m->users, i) {
719                 DIR *d;
720                 char *name;
721                 int k;
722
723                 if (!u->cgroup_path)
724                         continue;
725
726                 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
727                 if (k < 0) {
728                         if (k == -ENOENT)
729                                 continue;
730
731                         log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
732                         r = k;
733                         continue;
734                 }
735
736                 while ((k = cg_read_subgroup(d, &name)) > 0) {
737                         Session *session;
738
739                         if (streq(name, "shared"))
740                                 continue;
741
742                         k = manager_add_session(m, u, name, &session);
743                         if (k < 0) {
744                                 free(name);
745                                 break;
746                         }
747
748                         session_add_to_gc_queue(session);
749
750                         if (!session->cgroup_path)
751                                 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
752                                         k = -ENOMEM;
753                                         free(name);
754                                         break;
755                                 }
756
757                         free(name);
758                 }
759
760                 closedir(d);
761
762                 if (k < 0)
763                         r = k;
764         }
765
766         return r;
767 }
768
769 int manager_enumerate_sessions(Manager *m) {
770         DIR *d;
771         struct dirent *de;
772         int r = 0;
773
774         assert(m);
775
776         /* First enumerate session cgroups */
777         r = manager_enumerate_sessions_from_cgroup(m);
778
779         /* Second, read in session data stored on disk */
780         d = opendir("/run/systemd/sessions");
781         if (!d) {
782                 if (errno == ENOENT)
783                         return 0;
784
785                 log_error("Failed to open /run/systemd/sessions: %m");
786                 return -errno;
787         }
788
789         while ((de = readdir(d))) {
790                 struct Session *s;
791                 int k;
792
793                 if (!dirent_is_file(de))
794                         continue;
795
796                 s = hashmap_get(m->sessions, de->d_name);
797                 if (!s) {
798                         unlinkat(dirfd(d), de->d_name, 0);
799                         continue;
800                 }
801
802                 k = session_load(s);
803                 if (k < 0)
804                         r = k;
805         }
806
807         closedir(d);
808
809         return r;
810 }
811
812 int manager_enumerate_inhibitors(Manager *m) {
813         DIR *d;
814         struct dirent *de;
815         int r = 0;
816
817         assert(m);
818
819         d = opendir("/run/systemd/inhibit");
820         if (!d) {
821                 if (errno == ENOENT)
822                         return 0;
823
824                 log_error("Failed to open /run/systemd/inhibit: %m");
825                 return -errno;
826         }
827
828         while ((de = readdir(d))) {
829                 int k;
830                 Inhibitor *i;
831
832                 if (!dirent_is_file(de))
833                         continue;
834
835                 k = manager_add_inhibitor(m, de->d_name, &i);
836                 if (k < 0) {
837                         log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
838                         r = k;
839                         continue;
840                 }
841
842                 k = inhibitor_load(i);
843                 if (k < 0)
844                         r = k;
845         }
846
847         closedir(d);
848
849         return r;
850 }
851
852 int manager_dispatch_seat_udev(Manager *m) {
853         struct udev_device *d;
854         int r;
855
856         assert(m);
857
858         d = udev_monitor_receive_device(m->udev_seat_monitor);
859         if (!d)
860                 return -ENOMEM;
861
862         r = manager_process_seat_device(m, d);
863         udev_device_unref(d);
864
865         return r;
866 }
867
868 int manager_dispatch_vcsa_udev(Manager *m) {
869         struct udev_device *d;
870         int r = 0;
871         const char *name;
872
873         assert(m);
874
875         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
876         if (!d)
877                 return -ENOMEM;
878
879         name = udev_device_get_sysname(d);
880
881         /* Whenever a VCSA device is removed try to reallocate our
882          * VTs, to make sure our auto VTs never go away. */
883
884         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
885                 r = seat_preallocate_vts(m->vtconsole);
886
887         udev_device_unref(d);
888
889         return r;
890 }
891
892 int manager_dispatch_button_udev(Manager *m) {
893         struct udev_device *d;
894         int r;
895
896         assert(m);
897
898         d = udev_monitor_receive_device(m->udev_button_monitor);
899         if (!d)
900                 return -ENOMEM;
901
902         r = manager_process_button_device(m, d);
903         udev_device_unref(d);
904
905         return r;
906 }
907
908 int manager_dispatch_console(Manager *m) {
909         assert(m);
910
911         if (m->vtconsole)
912                 seat_read_active_vt(m->vtconsole);
913
914         return 0;
915 }
916
917 static int vt_is_busy(int vtnr) {
918         struct vt_stat vt_stat;
919         int r = 0, fd;
920
921         assert(vtnr >= 1);
922
923         /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
924          * we'd open the latter we'd open the foreground tty which
925          * hence would be unconditionally busy. By opening /dev/tty1
926          * we avoid this. Since tty1 is special and needs to be an
927          * explicitly loaded getty or DM this is safe. */
928
929         fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
930         if (fd < 0)
931                 return -errno;
932
933         if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
934                 r = -errno;
935         else
936                 r = !!(vt_stat.v_state & (1 << vtnr));
937
938         close_nointr_nofail(fd);
939
940         return r;
941 }
942
943 int manager_spawn_autovt(Manager *m, int vtnr) {
944         int r;
945         DBusMessage *message = NULL, *reply = NULL;
946         char *name = NULL;
947         const char *mode = "fail";
948         DBusError error;
949
950         assert(m);
951         assert(vtnr >= 1);
952
953         dbus_error_init(&error);
954
955         if ((unsigned) vtnr > m->n_autovts)
956                 return 0;
957
958         r = vt_is_busy(vtnr);
959         if (r < 0)
960                 return r;
961         else if (r > 0)
962                 return -EBUSY;
963
964         message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
965         if (!message) {
966                 log_error("Could not allocate message.");
967                 r = -ENOMEM;
968                 goto finish;
969         }
970
971         if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
972                 log_error("Could not allocate service name.");
973                 r = -ENOMEM;
974                 goto finish;
975         }
976
977         if (!dbus_message_append_args(message,
978                                       DBUS_TYPE_STRING, &name,
979                                       DBUS_TYPE_STRING, &mode,
980                                       DBUS_TYPE_INVALID)) {
981                 log_error("Could not attach target and flag information to message.");
982                 r = -ENOMEM;
983                 goto finish;
984         }
985
986         reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
987         if (!reply) {
988                 log_error("Failed to start unit: %s", bus_error_message(&error));
989                 goto finish;
990         }
991
992         r = 0;
993
994 finish:
995         free(name);
996
997         if (message)
998                 dbus_message_unref(message);
999
1000         if (reply)
1001                 dbus_message_unref(reply);
1002
1003         dbus_error_free(&error);
1004
1005         return r;
1006 }
1007
1008 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1009         Session *s;
1010         char *p;
1011
1012         assert(m);
1013         assert(cgroup);
1014         assert(session);
1015
1016         s = hashmap_get(m->session_cgroups, cgroup);
1017         if (s) {
1018                 *session = s;
1019                 return 1;
1020         }
1021
1022         p = strdup(cgroup);
1023         if (!p) {
1024                 log_error("Out of memory.");
1025                 return -ENOMEM;
1026         }
1027
1028         for (;;) {
1029                 char *e;
1030
1031                 e = strrchr(p, '/');
1032                 if (!e || e == p) {
1033                         free(p);
1034                         *session = NULL;
1035                         return 0;
1036                 }
1037
1038                 *e = 0;
1039
1040                 s = hashmap_get(m->session_cgroups, p);
1041                 if (s) {
1042                         free(p);
1043                         *session = s;
1044                         return 1;
1045                 }
1046         }
1047 }
1048
1049 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1050         User *u;
1051         char *p;
1052
1053         assert(m);
1054         assert(cgroup);
1055         assert(user);
1056
1057         u = hashmap_get(m->user_cgroups, cgroup);
1058         if (u) {
1059                 *user = u;
1060                 return 1;
1061         }
1062
1063         p = strdup(cgroup);
1064         if (!p) {
1065                 log_error("Out of memory.");
1066                 return -ENOMEM;
1067         }
1068
1069         for (;;) {
1070                 char *e;
1071
1072                 e = strrchr(p, '/');
1073                 if (!e || e == p) {
1074                         free(p);
1075                         *user = NULL;
1076                         return 0;
1077                 }
1078
1079                 *e = 0;
1080
1081                 u = hashmap_get(m->user_cgroups, p);
1082                 if (u) {
1083                         free(p);
1084                         *user = u;
1085                         return 1;
1086                 }
1087         }
1088 }
1089
1090 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1091         char *p;
1092         int r;
1093
1094         assert(m);
1095         assert(pid >= 1);
1096         assert(session);
1097
1098         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1099         if (r < 0)
1100                 return r;
1101
1102         r = manager_get_session_by_cgroup(m, p, session);
1103         free(p);
1104
1105         return r;
1106 }
1107
1108 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1109         Session *s;
1110         User *u;
1111         int r;
1112
1113         r = manager_get_session_by_cgroup(m, cgroup, &s);
1114         if (r > 0)
1115                 session_add_to_gc_queue(s);
1116
1117         r = manager_get_user_by_cgroup(m, cgroup, &u);
1118         if (r > 0)
1119                 user_add_to_gc_queue(u);
1120 }
1121
1122 static void manager_dispatch_other(Manager *m, int fd) {
1123         Session *s;
1124         Inhibitor *i;
1125         Button *b;
1126
1127         assert_se(m);
1128         assert_se(fd >= 0);
1129
1130         s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1131         if (s) {
1132                 assert(s->fifo_fd == fd);
1133                 session_remove_fifo(s);
1134                 session_stop(s);
1135                 return;
1136         }
1137
1138         i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1139         if (i) {
1140                 assert(i->fifo_fd == fd);
1141                 inhibitor_stop(i);
1142                 inhibitor_free(i);
1143                 return;
1144         }
1145
1146         b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1147         if (b) {
1148                 assert(b->fd == fd);
1149                 button_process(b);
1150                 return;
1151         }
1152
1153         assert_not_reached("Got event for unknown fd");
1154 }
1155
1156 static int manager_connect_bus(Manager *m) {
1157         DBusError error;
1158         int r;
1159         struct epoll_event ev;
1160
1161         assert(m);
1162         assert(!m->bus);
1163         assert(m->bus_fd < 0);
1164
1165         dbus_error_init(&error);
1166
1167         m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1168         if (!m->bus) {
1169                 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1170                 r = -ECONNREFUSED;
1171                 goto fail;
1172         }
1173
1174         if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1175             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1176             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1177             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1178             !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1179                 log_error("Not enough memory");
1180                 r = -ENOMEM;
1181                 goto fail;
1182         }
1183
1184         dbus_bus_add_match(m->bus,
1185                            "type='signal',"
1186                            "interface='org.freedesktop.systemd1.Agent',"
1187                            "member='Released',"
1188                            "path='/org/freedesktop/systemd1/agent'",
1189                            &error);
1190
1191         if (dbus_error_is_set(&error)) {
1192                 log_error("Failed to register match: %s", bus_error_message(&error));
1193                 r = -EIO;
1194                 goto fail;
1195         }
1196
1197         r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1198         if (dbus_error_is_set(&error)) {
1199                 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1200                 r = -EIO;
1201                 goto fail;
1202         }
1203
1204         if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
1205                 log_error("Failed to acquire name.");
1206                 r = -EEXIST;
1207                 goto fail;
1208         }
1209
1210         m->bus_fd = bus_loop_open(m->bus);
1211         if (m->bus_fd < 0) {
1212                 r = m->bus_fd;
1213                 goto fail;
1214         }
1215
1216         zero(ev);
1217         ev.events = EPOLLIN;
1218         ev.data.u32 = FD_BUS;
1219
1220         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1221                 goto fail;
1222
1223         return 0;
1224
1225 fail:
1226         dbus_error_free(&error);
1227
1228         return r;
1229 }
1230
1231 static int manager_connect_console(Manager *m) {
1232         struct epoll_event ev;
1233
1234         assert(m);
1235         assert(m->console_active_fd < 0);
1236
1237         /* On certain architectures (S390 and Xen, and containers),
1238            /dev/tty0 does not exist, so don't fail if we can't open
1239            it. */
1240         if (access("/dev/tty0", F_OK) < 0) {
1241                 m->console_active_fd = -1;
1242                 return 0;
1243         }
1244
1245         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1246         if (m->console_active_fd < 0) {
1247                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1248                 return -errno;
1249         }
1250
1251         zero(ev);
1252         ev.events = 0;
1253         ev.data.u32 = FD_CONSOLE;
1254
1255         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1256                 return -errno;
1257
1258         return 0;
1259 }
1260
1261 static int manager_connect_udev(Manager *m) {
1262         struct epoll_event ev;
1263         int r;
1264
1265         assert(m);
1266         assert(!m->udev_seat_monitor);
1267         assert(!m->udev_vcsa_monitor);
1268         assert(!m->udev_button_monitor);
1269
1270         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1271         if (!m->udev_seat_monitor)
1272                 return -ENOMEM;
1273
1274         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1275         if (r < 0)
1276                 return r;
1277
1278         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1279         if (r < 0)
1280                 return r;
1281
1282         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1283         if (r < 0)
1284                 return r;
1285
1286         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1287
1288         zero(ev);
1289         ev.events = EPOLLIN;
1290         ev.data.u32 = FD_SEAT_UDEV;
1291         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1292                 return -errno;
1293
1294         /* Don't watch keys if nobody cares */
1295         if (m->handle_power_key != HANDLE_OFF ||
1296             m->handle_sleep_key != HANDLE_OFF ||
1297             m->handle_lid_switch != HANDLE_OFF) {
1298
1299                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1300                 if (!m->udev_button_monitor)
1301                         return -ENOMEM;
1302
1303                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1304                 if (r < 0)
1305                         return r;
1306
1307                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1308                 if (r < 0)
1309                         return r;
1310
1311                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1312                 if (r < 0)
1313                         return r;
1314
1315                 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1316
1317                 zero(ev);
1318                 ev.events = EPOLLIN;
1319                 ev.data.u32 = FD_BUTTON_UDEV;
1320                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1321                         return -errno;
1322         }
1323
1324         /* Don't bother watching VCSA devices, if nobody cares */
1325         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1326
1327                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1328                 if (!m->udev_vcsa_monitor)
1329                         return -ENOMEM;
1330
1331                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1332                 if (r < 0)
1333                         return r;
1334
1335                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1336                 if (r < 0)
1337                         return r;
1338
1339                 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1340
1341                 zero(ev);
1342                 ev.events = EPOLLIN;
1343                 ev.data.u32 = FD_VCSA_UDEV;
1344                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1345                         return -errno;
1346         }
1347
1348         return 0;
1349 }
1350
1351 void manager_gc(Manager *m, bool drop_not_started) {
1352         Seat *seat;
1353         Session *session;
1354         User *user;
1355
1356         assert(m);
1357
1358         while ((seat = m->seat_gc_queue)) {
1359                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1360                 seat->in_gc_queue = false;
1361
1362                 if (seat_check_gc(seat, drop_not_started) == 0) {
1363                         seat_stop(seat);
1364                         seat_free(seat);
1365                 }
1366         }
1367
1368         while ((session = m->session_gc_queue)) {
1369                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1370                 session->in_gc_queue = false;
1371
1372                 if (session_check_gc(session, drop_not_started) == 0) {
1373                         session_stop(session);
1374                         session_free(session);
1375                 }
1376         }
1377
1378         while ((user = m->user_gc_queue)) {
1379                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1380                 user->in_gc_queue = false;
1381
1382                 if (user_check_gc(user, drop_not_started) == 0) {
1383                         user_stop(user);
1384                         user_free(user);
1385                 }
1386         }
1387 }
1388
1389 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1390         Session *s;
1391         bool idle_hint;
1392         dual_timestamp ts = { 0, 0 };
1393         Iterator i;
1394
1395         assert(m);
1396
1397         idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1398
1399         HASHMAP_FOREACH(s, m->sessions, i) {
1400                 dual_timestamp k;
1401                 int ih;
1402
1403                 ih = session_get_idle_hint(s, &k);
1404                 if (ih < 0)
1405                         return ih;
1406
1407                 if (!ih) {
1408                         if (!idle_hint) {
1409                                 if (k.monotonic < ts.monotonic)
1410                                         ts = k;
1411                         } else {
1412                                 idle_hint = false;
1413                                 ts = k;
1414                         }
1415                 } else if (idle_hint) {
1416
1417                         if (k.monotonic > ts.monotonic)
1418                                 ts = k;
1419                 }
1420         }
1421
1422         if (t)
1423                 *t = ts;
1424
1425         return idle_hint;
1426 }
1427
1428 int manager_startup(Manager *m) {
1429         int r;
1430         Seat *seat;
1431         Session *session;
1432         User *user;
1433         Inhibitor *inhibitor;
1434         Iterator i;
1435
1436         assert(m);
1437         assert(m->epoll_fd <= 0);
1438
1439         cg_shorten_controllers(m->reset_controllers);
1440         cg_shorten_controllers(m->controllers);
1441
1442         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1443         if (m->epoll_fd < 0)
1444                 return -errno;
1445
1446         /* Connect to console */
1447         r = manager_connect_console(m);
1448         if (r < 0)
1449                 return r;
1450
1451         /* Connect to udev */
1452         r = manager_connect_udev(m);
1453         if (r < 0)
1454                 return r;
1455
1456         /* Connect to the bus */
1457         r = manager_connect_bus(m);
1458         if (r < 0)
1459                 return r;
1460
1461         /* Instantiate magic seat 0 */
1462         r = manager_add_seat(m, "seat0", &m->vtconsole);
1463         if (r < 0)
1464                 return r;
1465
1466         /* Deserialize state */
1467         manager_enumerate_devices(m);
1468         manager_enumerate_seats(m);
1469         manager_enumerate_users(m);
1470         manager_enumerate_sessions(m);
1471         manager_enumerate_inhibitors(m);
1472         manager_enumerate_buttons(m);
1473
1474         /* Remove stale objects before we start them */
1475         manager_gc(m, false);
1476
1477         /* And start everything */
1478         HASHMAP_FOREACH(seat, m->seats, i)
1479                 seat_start(seat);
1480
1481         HASHMAP_FOREACH(user, m->users, i)
1482                 user_start(user);
1483
1484         HASHMAP_FOREACH(session, m->sessions, i)
1485                 session_start(session);
1486
1487         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1488                 inhibitor_start(inhibitor);
1489
1490         return 0;
1491 }
1492
1493 int manager_run(Manager *m) {
1494         assert(m);
1495
1496         for (;;) {
1497                 struct epoll_event event;
1498                 int n;
1499                 int msec = -1;
1500
1501                 manager_gc(m, true);
1502
1503                 if (manager_dispatch_delayed(m) > 0)
1504                         continue;
1505
1506                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1507                         continue;
1508
1509                 manager_gc(m, true);
1510
1511                 if (m->delayed_unit) {
1512                         usec_t x, y;
1513
1514                         x = now(CLOCK_MONOTONIC);
1515                         y = m->delayed_timestamp + m->inhibit_delay_max;
1516
1517                         msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1518                 }
1519
1520                 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1521                 if (n < 0) {
1522                         if (errno == EINTR || errno == EAGAIN)
1523                                 continue;
1524
1525                         log_error("epoll() failed: %m");
1526                         return -errno;
1527                 }
1528
1529                 if (n == 0)
1530                         continue;
1531
1532                 switch (event.data.u32) {
1533
1534                 case FD_SEAT_UDEV:
1535                         manager_dispatch_seat_udev(m);
1536                         break;
1537
1538                 case FD_VCSA_UDEV:
1539                         manager_dispatch_vcsa_udev(m);
1540                         break;
1541
1542                 case FD_BUTTON_UDEV:
1543                         manager_dispatch_button_udev(m);
1544                         break;
1545
1546                 case FD_CONSOLE:
1547                         manager_dispatch_console(m);
1548                         break;
1549
1550                 case FD_BUS:
1551                         bus_loop_dispatch(m->bus_fd);
1552                         break;
1553
1554                 default:
1555                         if (event.data.u32 >= FD_OTHER_BASE)
1556                                 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1557                 }
1558         }
1559
1560         return 0;
1561 }
1562
1563 static int manager_parse_config_file(Manager *m) {
1564         FILE *f;
1565         const char *fn;
1566         int r;
1567
1568         assert(m);
1569
1570         fn = "/etc/systemd/logind.conf";
1571         f = fopen(fn, "re");
1572         if (!f) {
1573                 if (errno == ENOENT)
1574                         return 0;
1575
1576                 log_warning("Failed to open configuration file %s: %m", fn);
1577                 return -errno;
1578         }
1579
1580         r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1581         if (r < 0)
1582                 log_warning("Failed to parse configuration file: %s", strerror(-r));
1583
1584         fclose(f);
1585
1586         return r;
1587 }
1588
1589 int main(int argc, char *argv[]) {
1590         Manager *m = NULL;
1591         int r;
1592
1593         log_set_target(LOG_TARGET_AUTO);
1594         log_set_facility(LOG_AUTH);
1595         log_parse_environment();
1596         log_open();
1597
1598         umask(0022);
1599
1600         if (argc != 1) {
1601                 log_error("This program takes no arguments.");
1602                 r = -EINVAL;
1603                 goto finish;
1604         }
1605
1606         m = manager_new();
1607         if (!m) {
1608                 log_error("Out of memory");
1609                 r = -ENOMEM;
1610                 goto finish;
1611         }
1612
1613         manager_parse_config_file(m);
1614
1615         r = manager_startup(m);
1616         if (r < 0) {
1617                 log_error("Failed to fully start up daemon: %s", strerror(-r));
1618                 goto finish;
1619         }
1620
1621         log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1622
1623         sd_notify(false,
1624                   "READY=1\n"
1625                   "STATUS=Processing requests...");
1626
1627         r = manager_run(m);
1628
1629         log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1630
1631 finish:
1632         sd_notify(false,
1633                   "STATUS=Shutting down...");
1634
1635         if (m)
1636                 manager_free(m);
1637
1638         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1639 }