chiark / gitweb /
1eb745adcecfafb9166ca506bb75da5a26cc6a52
[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
1248                 /* On some systems the device node /dev/tty0 may exist
1249                  * even though /sys/class/tty/tty0 does not. */
1250                 if (errno == ENOENT)
1251                         return 0;
1252
1253                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1254                 return -errno;
1255         }
1256
1257         zero(ev);
1258         ev.events = 0;
1259         ev.data.u32 = FD_CONSOLE;
1260
1261         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1262                 return -errno;
1263
1264         return 0;
1265 }
1266
1267 static int manager_connect_udev(Manager *m) {
1268         struct epoll_event ev;
1269         int r;
1270
1271         assert(m);
1272         assert(!m->udev_seat_monitor);
1273         assert(!m->udev_vcsa_monitor);
1274         assert(!m->udev_button_monitor);
1275
1276         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1277         if (!m->udev_seat_monitor)
1278                 return -ENOMEM;
1279
1280         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1281         if (r < 0)
1282                 return r;
1283
1284         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1285         if (r < 0)
1286                 return r;
1287
1288         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1289         if (r < 0)
1290                 return r;
1291
1292         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1293
1294         zero(ev);
1295         ev.events = EPOLLIN;
1296         ev.data.u32 = FD_SEAT_UDEV;
1297         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1298                 return -errno;
1299
1300         /* Don't watch keys if nobody cares */
1301         if (m->handle_power_key != HANDLE_OFF ||
1302             m->handle_sleep_key != HANDLE_OFF ||
1303             m->handle_lid_switch != HANDLE_OFF) {
1304
1305                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1306                 if (!m->udev_button_monitor)
1307                         return -ENOMEM;
1308
1309                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1310                 if (r < 0)
1311                         return r;
1312
1313                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1314                 if (r < 0)
1315                         return r;
1316
1317                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1318                 if (r < 0)
1319                         return r;
1320
1321                 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1322
1323                 zero(ev);
1324                 ev.events = EPOLLIN;
1325                 ev.data.u32 = FD_BUTTON_UDEV;
1326                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1327                         return -errno;
1328         }
1329
1330         /* Don't bother watching VCSA devices, if nobody cares */
1331         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1332
1333                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1334                 if (!m->udev_vcsa_monitor)
1335                         return -ENOMEM;
1336
1337                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1338                 if (r < 0)
1339                         return r;
1340
1341                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1342                 if (r < 0)
1343                         return r;
1344
1345                 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1346
1347                 zero(ev);
1348                 ev.events = EPOLLIN;
1349                 ev.data.u32 = FD_VCSA_UDEV;
1350                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1351                         return -errno;
1352         }
1353
1354         return 0;
1355 }
1356
1357 void manager_gc(Manager *m, bool drop_not_started) {
1358         Seat *seat;
1359         Session *session;
1360         User *user;
1361
1362         assert(m);
1363
1364         while ((seat = m->seat_gc_queue)) {
1365                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1366                 seat->in_gc_queue = false;
1367
1368                 if (seat_check_gc(seat, drop_not_started) == 0) {
1369                         seat_stop(seat);
1370                         seat_free(seat);
1371                 }
1372         }
1373
1374         while ((session = m->session_gc_queue)) {
1375                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1376                 session->in_gc_queue = false;
1377
1378                 if (session_check_gc(session, drop_not_started) == 0) {
1379                         session_stop(session);
1380                         session_free(session);
1381                 }
1382         }
1383
1384         while ((user = m->user_gc_queue)) {
1385                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1386                 user->in_gc_queue = false;
1387
1388                 if (user_check_gc(user, drop_not_started) == 0) {
1389                         user_stop(user);
1390                         user_free(user);
1391                 }
1392         }
1393 }
1394
1395 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1396         Session *s;
1397         bool idle_hint;
1398         dual_timestamp ts = { 0, 0 };
1399         Iterator i;
1400
1401         assert(m);
1402
1403         idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1404
1405         HASHMAP_FOREACH(s, m->sessions, i) {
1406                 dual_timestamp k;
1407                 int ih;
1408
1409                 ih = session_get_idle_hint(s, &k);
1410                 if (ih < 0)
1411                         return ih;
1412
1413                 if (!ih) {
1414                         if (!idle_hint) {
1415                                 if (k.monotonic < ts.monotonic)
1416                                         ts = k;
1417                         } else {
1418                                 idle_hint = false;
1419                                 ts = k;
1420                         }
1421                 } else if (idle_hint) {
1422
1423                         if (k.monotonic > ts.monotonic)
1424                                 ts = k;
1425                 }
1426         }
1427
1428         if (t)
1429                 *t = ts;
1430
1431         return idle_hint;
1432 }
1433
1434 int manager_startup(Manager *m) {
1435         int r;
1436         Seat *seat;
1437         Session *session;
1438         User *user;
1439         Inhibitor *inhibitor;
1440         Iterator i;
1441
1442         assert(m);
1443         assert(m->epoll_fd <= 0);
1444
1445         cg_shorten_controllers(m->reset_controllers);
1446         cg_shorten_controllers(m->controllers);
1447
1448         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1449         if (m->epoll_fd < 0)
1450                 return -errno;
1451
1452         /* Connect to console */
1453         r = manager_connect_console(m);
1454         if (r < 0)
1455                 return r;
1456
1457         /* Connect to udev */
1458         r = manager_connect_udev(m);
1459         if (r < 0)
1460                 return r;
1461
1462         /* Connect to the bus */
1463         r = manager_connect_bus(m);
1464         if (r < 0)
1465                 return r;
1466
1467         /* Instantiate magic seat 0 */
1468         r = manager_add_seat(m, "seat0", &m->vtconsole);
1469         if (r < 0)
1470                 return r;
1471
1472         /* Deserialize state */
1473         manager_enumerate_devices(m);
1474         manager_enumerate_seats(m);
1475         manager_enumerate_users(m);
1476         manager_enumerate_sessions(m);
1477         manager_enumerate_inhibitors(m);
1478         manager_enumerate_buttons(m);
1479
1480         /* Remove stale objects before we start them */
1481         manager_gc(m, false);
1482
1483         /* And start everything */
1484         HASHMAP_FOREACH(seat, m->seats, i)
1485                 seat_start(seat);
1486
1487         HASHMAP_FOREACH(user, m->users, i)
1488                 user_start(user);
1489
1490         HASHMAP_FOREACH(session, m->sessions, i)
1491                 session_start(session);
1492
1493         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1494                 inhibitor_start(inhibitor);
1495
1496         return 0;
1497 }
1498
1499 int manager_run(Manager *m) {
1500         assert(m);
1501
1502         for (;;) {
1503                 struct epoll_event event;
1504                 int n;
1505                 int msec = -1;
1506
1507                 manager_gc(m, true);
1508
1509                 if (manager_dispatch_delayed(m) > 0)
1510                         continue;
1511
1512                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1513                         continue;
1514
1515                 manager_gc(m, true);
1516
1517                 if (m->delayed_unit) {
1518                         usec_t x, y;
1519
1520                         x = now(CLOCK_MONOTONIC);
1521                         y = m->delayed_timestamp + m->inhibit_delay_max;
1522
1523                         msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1524                 }
1525
1526                 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1527                 if (n < 0) {
1528                         if (errno == EINTR || errno == EAGAIN)
1529                                 continue;
1530
1531                         log_error("epoll() failed: %m");
1532                         return -errno;
1533                 }
1534
1535                 if (n == 0)
1536                         continue;
1537
1538                 switch (event.data.u32) {
1539
1540                 case FD_SEAT_UDEV:
1541                         manager_dispatch_seat_udev(m);
1542                         break;
1543
1544                 case FD_VCSA_UDEV:
1545                         manager_dispatch_vcsa_udev(m);
1546                         break;
1547
1548                 case FD_BUTTON_UDEV:
1549                         manager_dispatch_button_udev(m);
1550                         break;
1551
1552                 case FD_CONSOLE:
1553                         manager_dispatch_console(m);
1554                         break;
1555
1556                 case FD_BUS:
1557                         bus_loop_dispatch(m->bus_fd);
1558                         break;
1559
1560                 default:
1561                         if (event.data.u32 >= FD_OTHER_BASE)
1562                                 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1563                 }
1564         }
1565
1566         return 0;
1567 }
1568
1569 static int manager_parse_config_file(Manager *m) {
1570         FILE *f;
1571         const char *fn;
1572         int r;
1573
1574         assert(m);
1575
1576         fn = "/etc/systemd/logind.conf";
1577         f = fopen(fn, "re");
1578         if (!f) {
1579                 if (errno == ENOENT)
1580                         return 0;
1581
1582                 log_warning("Failed to open configuration file %s: %m", fn);
1583                 return -errno;
1584         }
1585
1586         r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1587         if (r < 0)
1588                 log_warning("Failed to parse configuration file: %s", strerror(-r));
1589
1590         fclose(f);
1591
1592         return r;
1593 }
1594
1595 int main(int argc, char *argv[]) {
1596         Manager *m = NULL;
1597         int r;
1598
1599         log_set_target(LOG_TARGET_AUTO);
1600         log_set_facility(LOG_AUTH);
1601         log_parse_environment();
1602         log_open();
1603
1604         umask(0022);
1605
1606         if (argc != 1) {
1607                 log_error("This program takes no arguments.");
1608                 r = -EINVAL;
1609                 goto finish;
1610         }
1611
1612         m = manager_new();
1613         if (!m) {
1614                 log_error("Out of memory");
1615                 r = -ENOMEM;
1616                 goto finish;
1617         }
1618
1619         manager_parse_config_file(m);
1620
1621         r = manager_startup(m);
1622         if (r < 0) {
1623                 log_error("Failed to fully start up daemon: %s", strerror(-r));
1624                 goto finish;
1625         }
1626
1627         log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1628
1629         sd_notify(false,
1630                   "READY=1\n"
1631                   "STATUS=Processing requests...");
1632
1633         r = manager_run(m);
1634
1635         log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1636
1637 finish:
1638         sd_notify(false,
1639                   "STATUS=Shutting down...");
1640
1641         if (m)
1642                 manager_free(m);
1643
1644         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1645 }