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