chiark / gitweb /
update TODO
[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, 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                 return log_oom();
1025
1026         for (;;) {
1027                 char *e;
1028
1029                 e = strrchr(p, '/');
1030                 if (!e || e == p) {
1031                         free(p);
1032                         *session = NULL;
1033                         return 0;
1034                 }
1035
1036                 *e = 0;
1037
1038                 s = hashmap_get(m->session_cgroups, p);
1039                 if (s) {
1040                         free(p);
1041                         *session = s;
1042                         return 1;
1043                 }
1044         }
1045 }
1046
1047 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1048         User *u;
1049         char *p;
1050
1051         assert(m);
1052         assert(cgroup);
1053         assert(user);
1054
1055         u = hashmap_get(m->user_cgroups, cgroup);
1056         if (u) {
1057                 *user = u;
1058                 return 1;
1059         }
1060
1061         p = strdup(cgroup);
1062         if (!p)
1063                 return log_oom();
1064
1065         for (;;) {
1066                 char *e;
1067
1068                 e = strrchr(p, '/');
1069                 if (!e || e == p) {
1070                         free(p);
1071                         *user = NULL;
1072                         return 0;
1073                 }
1074
1075                 *e = 0;
1076
1077                 u = hashmap_get(m->user_cgroups, p);
1078                 if (u) {
1079                         free(p);
1080                         *user = u;
1081                         return 1;
1082                 }
1083         }
1084 }
1085
1086 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1087         char *p;
1088         int r;
1089
1090         assert(m);
1091         assert(pid >= 1);
1092         assert(session);
1093
1094         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1095         if (r < 0)
1096                 return r;
1097
1098         r = manager_get_session_by_cgroup(m, p, session);
1099         free(p);
1100
1101         return r;
1102 }
1103
1104 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1105         Session *s;
1106         User *u;
1107         int r;
1108
1109         r = manager_get_session_by_cgroup(m, cgroup, &s);
1110         if (r > 0)
1111                 session_add_to_gc_queue(s);
1112
1113         r = manager_get_user_by_cgroup(m, cgroup, &u);
1114         if (r > 0)
1115                 user_add_to_gc_queue(u);
1116 }
1117
1118 static void manager_dispatch_other(Manager *m, int fd) {
1119         Session *s;
1120         Inhibitor *i;
1121         Button *b;
1122
1123         assert_se(m);
1124         assert_se(fd >= 0);
1125
1126         s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1127         if (s) {
1128                 assert(s->fifo_fd == fd);
1129                 session_remove_fifo(s);
1130                 session_stop(s);
1131                 return;
1132         }
1133
1134         i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1135         if (i) {
1136                 assert(i->fifo_fd == fd);
1137                 inhibitor_stop(i);
1138                 inhibitor_free(i);
1139                 return;
1140         }
1141
1142         b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1143         if (b) {
1144                 assert(b->fd == fd);
1145                 button_process(b);
1146                 return;
1147         }
1148
1149         assert_not_reached("Got event for unknown fd");
1150 }
1151
1152 static int manager_connect_bus(Manager *m) {
1153         DBusError error;
1154         int r;
1155         struct epoll_event ev;
1156
1157         assert(m);
1158         assert(!m->bus);
1159         assert(m->bus_fd < 0);
1160
1161         dbus_error_init(&error);
1162
1163         m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1164         if (!m->bus) {
1165                 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1166                 r = -ECONNREFUSED;
1167                 goto fail;
1168         }
1169
1170         if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1171             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1172             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1173             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1174             !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1175                 r = log_oom();
1176                 goto fail;
1177         }
1178
1179         dbus_bus_add_match(m->bus,
1180                            "type='signal',"
1181                            "interface='org.freedesktop.systemd1.Agent',"
1182                            "member='Released',"
1183                            "path='/org/freedesktop/systemd1/agent'",
1184                            &error);
1185
1186         if (dbus_error_is_set(&error)) {
1187                 log_error("Failed to register match: %s", bus_error_message(&error));
1188                 r = -EIO;
1189                 goto fail;
1190         }
1191
1192         r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1193         if (dbus_error_is_set(&error)) {
1194                 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1195                 r = -EIO;
1196                 goto fail;
1197         }
1198
1199         if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
1200                 log_error("Failed to acquire name.");
1201                 r = -EEXIST;
1202                 goto fail;
1203         }
1204
1205         m->bus_fd = bus_loop_open(m->bus);
1206         if (m->bus_fd < 0) {
1207                 r = m->bus_fd;
1208                 goto fail;
1209         }
1210
1211         zero(ev);
1212         ev.events = EPOLLIN;
1213         ev.data.u32 = FD_BUS;
1214
1215         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1216                 goto fail;
1217
1218         return 0;
1219
1220 fail:
1221         dbus_error_free(&error);
1222
1223         return r;
1224 }
1225
1226 static int manager_connect_console(Manager *m) {
1227         struct epoll_event ev;
1228
1229         assert(m);
1230         assert(m->console_active_fd < 0);
1231
1232         /* On certain architectures (S390 and Xen, and containers),
1233            /dev/tty0 does not exist, so don't fail if we can't open
1234            it. */
1235         if (access("/dev/tty0", F_OK) < 0) {
1236                 m->console_active_fd = -1;
1237                 return 0;
1238         }
1239
1240         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1241         if (m->console_active_fd < 0) {
1242
1243                 /* On some systems the device node /dev/tty0 may exist
1244                  * even though /sys/class/tty/tty0 does not. */
1245                 if (errno == ENOENT)
1246                         return 0;
1247
1248                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1249                 return -errno;
1250         }
1251
1252         zero(ev);
1253         ev.events = 0;
1254         ev.data.u32 = FD_CONSOLE;
1255
1256         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1257                 return -errno;
1258
1259         return 0;
1260 }
1261
1262 static int manager_connect_udev(Manager *m) {
1263         struct epoll_event ev;
1264         int r;
1265
1266         assert(m);
1267         assert(!m->udev_seat_monitor);
1268         assert(!m->udev_vcsa_monitor);
1269         assert(!m->udev_button_monitor);
1270
1271         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1272         if (!m->udev_seat_monitor)
1273                 return -ENOMEM;
1274
1275         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1276         if (r < 0)
1277                 return r;
1278
1279         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1280         if (r < 0)
1281                 return r;
1282
1283         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1284         if (r < 0)
1285                 return r;
1286
1287         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1288
1289         zero(ev);
1290         ev.events = EPOLLIN;
1291         ev.data.u32 = FD_SEAT_UDEV;
1292         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1293                 return -errno;
1294
1295         /* Don't watch keys if nobody cares */
1296         if (m->handle_power_key != HANDLE_OFF ||
1297             m->handle_sleep_key != HANDLE_OFF ||
1298             m->handle_lid_switch != HANDLE_OFF) {
1299
1300                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1301                 if (!m->udev_button_monitor)
1302                         return -ENOMEM;
1303
1304                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1305                 if (r < 0)
1306                         return r;
1307
1308                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1309                 if (r < 0)
1310                         return r;
1311
1312                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1313                 if (r < 0)
1314                         return r;
1315
1316                 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1317
1318                 zero(ev);
1319                 ev.events = EPOLLIN;
1320                 ev.data.u32 = FD_BUTTON_UDEV;
1321                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1322                         return -errno;
1323         }
1324
1325         /* Don't bother watching VCSA devices, if nobody cares */
1326         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1327
1328                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1329                 if (!m->udev_vcsa_monitor)
1330                         return -ENOMEM;
1331
1332                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1333                 if (r < 0)
1334                         return r;
1335
1336                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1337                 if (r < 0)
1338                         return r;
1339
1340                 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1341
1342                 zero(ev);
1343                 ev.events = EPOLLIN;
1344                 ev.data.u32 = FD_VCSA_UDEV;
1345                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1346                         return -errno;
1347         }
1348
1349         return 0;
1350 }
1351
1352 void manager_gc(Manager *m, bool drop_not_started) {
1353         Seat *seat;
1354         Session *session;
1355         User *user;
1356
1357         assert(m);
1358
1359         while ((seat = m->seat_gc_queue)) {
1360                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1361                 seat->in_gc_queue = false;
1362
1363                 if (seat_check_gc(seat, drop_not_started) == 0) {
1364                         seat_stop(seat);
1365                         seat_free(seat);
1366                 }
1367         }
1368
1369         while ((session = m->session_gc_queue)) {
1370                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1371                 session->in_gc_queue = false;
1372
1373                 if (session_check_gc(session, drop_not_started) == 0) {
1374                         session_stop(session);
1375                         session_free(session);
1376                 }
1377         }
1378
1379         while ((user = m->user_gc_queue)) {
1380                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1381                 user->in_gc_queue = false;
1382
1383                 if (user_check_gc(user, drop_not_started) == 0) {
1384                         user_stop(user);
1385                         user_free(user);
1386                 }
1387         }
1388 }
1389
1390 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1391         Session *s;
1392         bool idle_hint;
1393         dual_timestamp ts = { 0, 0 };
1394         Iterator i;
1395
1396         assert(m);
1397
1398         idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1399
1400         HASHMAP_FOREACH(s, m->sessions, i) {
1401                 dual_timestamp k;
1402                 int ih;
1403
1404                 ih = session_get_idle_hint(s, &k);
1405                 if (ih < 0)
1406                         return ih;
1407
1408                 if (!ih) {
1409                         if (!idle_hint) {
1410                                 if (k.monotonic < ts.monotonic)
1411                                         ts = k;
1412                         } else {
1413                                 idle_hint = false;
1414                                 ts = k;
1415                         }
1416                 } else if (idle_hint) {
1417
1418                         if (k.monotonic > ts.monotonic)
1419                                 ts = k;
1420                 }
1421         }
1422
1423         if (t)
1424                 *t = ts;
1425
1426         return idle_hint;
1427 }
1428
1429 int manager_startup(Manager *m) {
1430         int r;
1431         Seat *seat;
1432         Session *session;
1433         User *user;
1434         Inhibitor *inhibitor;
1435         Iterator i;
1436
1437         assert(m);
1438         assert(m->epoll_fd <= 0);
1439
1440         cg_shorten_controllers(m->reset_controllers);
1441         cg_shorten_controllers(m->controllers);
1442
1443         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1444         if (m->epoll_fd < 0)
1445                 return -errno;
1446
1447         /* Connect to console */
1448         r = manager_connect_console(m);
1449         if (r < 0)
1450                 return r;
1451
1452         /* Connect to udev */
1453         r = manager_connect_udev(m);
1454         if (r < 0)
1455                 return r;
1456
1457         /* Connect to the bus */
1458         r = manager_connect_bus(m);
1459         if (r < 0)
1460                 return r;
1461
1462         /* Instantiate magic seat 0 */
1463         r = manager_add_seat(m, "seat0", &m->vtconsole);
1464         if (r < 0)
1465                 return r;
1466
1467         /* Deserialize state */
1468         manager_enumerate_devices(m);
1469         manager_enumerate_seats(m);
1470         manager_enumerate_users(m);
1471         manager_enumerate_sessions(m);
1472         manager_enumerate_inhibitors(m);
1473         manager_enumerate_buttons(m);
1474
1475         /* Remove stale objects before we start them */
1476         manager_gc(m, false);
1477
1478         /* And start everything */
1479         HASHMAP_FOREACH(seat, m->seats, i)
1480                 seat_start(seat);
1481
1482         HASHMAP_FOREACH(user, m->users, i)
1483                 user_start(user);
1484
1485         HASHMAP_FOREACH(session, m->sessions, i)
1486                 session_start(session);
1487
1488         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1489                 inhibitor_start(inhibitor);
1490
1491         return 0;
1492 }
1493
1494 int manager_run(Manager *m) {
1495         assert(m);
1496
1497         for (;;) {
1498                 struct epoll_event event;
1499                 int n;
1500                 int msec = -1;
1501
1502                 manager_gc(m, true);
1503
1504                 if (manager_dispatch_delayed(m) > 0)
1505                         continue;
1506
1507                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1508                         continue;
1509
1510                 manager_gc(m, true);
1511
1512                 if (m->delayed_unit) {
1513                         usec_t x, y;
1514
1515                         x = now(CLOCK_MONOTONIC);
1516                         y = m->delayed_timestamp + m->inhibit_delay_max;
1517
1518                         msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1519                 }
1520
1521                 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1522                 if (n < 0) {
1523                         if (errno == EINTR || errno == EAGAIN)
1524                                 continue;
1525
1526                         log_error("epoll() failed: %m");
1527                         return -errno;
1528                 }
1529
1530                 if (n == 0)
1531                         continue;
1532
1533                 switch (event.data.u32) {
1534
1535                 case FD_SEAT_UDEV:
1536                         manager_dispatch_seat_udev(m);
1537                         break;
1538
1539                 case FD_VCSA_UDEV:
1540                         manager_dispatch_vcsa_udev(m);
1541                         break;
1542
1543                 case FD_BUTTON_UDEV:
1544                         manager_dispatch_button_udev(m);
1545                         break;
1546
1547                 case FD_CONSOLE:
1548                         manager_dispatch_console(m);
1549                         break;
1550
1551                 case FD_BUS:
1552                         bus_loop_dispatch(m->bus_fd);
1553                         break;
1554
1555                 default:
1556                         if (event.data.u32 >= FD_OTHER_BASE)
1557                                 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1558                 }
1559         }
1560
1561         return 0;
1562 }
1563
1564 static int manager_parse_config_file(Manager *m) {
1565         FILE *f;
1566         const char *fn;
1567         int r;
1568
1569         assert(m);
1570
1571         fn = "/etc/systemd/logind.conf";
1572         f = fopen(fn, "re");
1573         if (!f) {
1574                 if (errno == ENOENT)
1575                         return 0;
1576
1577                 log_warning("Failed to open configuration file %s: %m", fn);
1578                 return -errno;
1579         }
1580
1581         r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1582         if (r < 0)
1583                 log_warning("Failed to parse configuration file: %s", strerror(-r));
1584
1585         fclose(f);
1586
1587         return r;
1588 }
1589
1590 int main(int argc, char *argv[]) {
1591         Manager *m = NULL;
1592         int r;
1593
1594         log_set_target(LOG_TARGET_AUTO);
1595         log_set_facility(LOG_AUTH);
1596         log_parse_environment();
1597         log_open();
1598
1599         umask(0022);
1600
1601         if (argc != 1) {
1602                 log_error("This program takes no arguments.");
1603                 r = -EINVAL;
1604                 goto finish;
1605         }
1606
1607         m = manager_new();
1608         if (!m) {
1609                 r = log_oom();
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 }