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