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