chiark / gitweb /
Move /var/lib/systemd/linger to /var/lib/elogind/.
[elogind.git] / src / login / logind-dbus.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2011 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <pwd.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "sd-messages.h"
27
28 #include "alloc-util.h"
29 #include "audit-util.h"
30 #include "bus-common-errors.h"
31 #include "bus-error.h"
32 #include "bus-util.h"
33 #include "dirent-util.h"
34 //#include "efivars.h"
35 #include "escape.h"
36 #include "fd-util.h"
37 #include "fileio-label.h"
38 #include "format-util.h"
39 #include "fs-util.h"
40 #include "logind.h"
41 #include "mkdir.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 #include "selinux-util.h"
45 #include "sleep-config.h"
46 //#include "special.h"
47 #include "strv.h"
48 #include "terminal-util.h"
49 #include "udev-util.h"
50 #include "unit-name.h"
51 #include "user-util.h"
52 #include "utmp-wtmp.h"
53
54 /// Additional includes needed by elogind
55 #include "elogind-dbus.h"
56 static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
57
58         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
59         const char *name;
60         Session *session;
61         int r;
62
63         /* Get client login session.  This is not what you are looking for these days,
64          * as apps may instead belong to a user service unit.  This includes terminal
65          * emulators and hence command-line apps. */
66         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
67         if (r < 0)
68                 return r;
69
70         r = sd_bus_creds_get_session(creds, &name);
71         if (r == -ENXIO)
72                 goto err_no_session;
73         if (r < 0)
74                 return r;
75
76         session = hashmap_get(m->sessions, name);
77         if (!session)
78                 goto err_no_session;
79
80         *ret = session;
81         return 0;
82
83 err_no_session:
84         return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
85                                  "Caller does not belong to any known session");
86 }
87
88 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
89         Session *session;
90
91         assert(m);
92         assert(message);
93         assert(ret);
94
95         if (isempty(name))
96                 return get_sender_session(m, message, error, ret);
97
98         session = hashmap_get(m->sessions, name);
99         if (!session)
100                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
101
102         *ret = session;
103         return 0;
104 }
105
106 static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
107
108         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
109         uid_t uid;
110         User *user;
111         int r;
112
113         /* Note that we get the owner UID of the session, not the actual client UID here! */
114         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
115         if (r < 0)
116                 return r;
117
118         r = sd_bus_creds_get_owner_uid(creds, &uid);
119         if (r == -ENXIO)
120                 goto err_no_user;
121         if (r < 0)
122                 return r;
123
124         user = hashmap_get(m->users, UID_TO_PTR(uid));
125         if (!user)
126                 goto err_no_user;
127
128         *ret = user;
129         return 0;
130
131 err_no_user:
132         return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "Caller does not belong to any logged in user or lingering user");
133 }
134
135 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
136         User *user;
137
138         assert(m);
139         assert(message);
140         assert(ret);
141
142         if (!uid_is_valid(uid))
143                 return get_sender_user(m, message, error, ret);
144
145         user = hashmap_get(m->users, UID_TO_PTR(uid));
146         if (!user)
147                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "User ID "UID_FMT" is not logged in or lingering", uid);
148
149         *ret = user;
150         return 0;
151 }
152
153 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
154         Seat *seat;
155         int r;
156
157         assert(m);
158         assert(message);
159         assert(ret);
160
161         if (isempty(name)) {
162                 Session *session;
163
164                 r = manager_get_session_from_creds(m, message, NULL, error, &session);
165                 if (r < 0)
166                         return r;
167
168                 seat = session->seat;
169                 if (!seat)
170                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
171         } else {
172                 seat = hashmap_get(m->seats, name);
173                 if (!seat)
174                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
175         }
176
177         *ret = seat;
178         return 0;
179 }
180
181 static int property_get_idle_hint(
182                 sd_bus *bus,
183                 const char *path,
184                 const char *interface,
185                 const char *property,
186                 sd_bus_message *reply,
187                 void *userdata,
188                 sd_bus_error *error) {
189
190         Manager *m = userdata;
191
192         assert(bus);
193         assert(reply);
194         assert(m);
195
196         return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
197 }
198
199 static int property_get_idle_since_hint(
200                 sd_bus *bus,
201                 const char *path,
202                 const char *interface,
203                 const char *property,
204                 sd_bus_message *reply,
205                 void *userdata,
206                 sd_bus_error *error) {
207
208         Manager *m = userdata;
209         dual_timestamp t = DUAL_TIMESTAMP_NULL;
210
211         assert(bus);
212         assert(reply);
213         assert(m);
214
215         manager_get_idle_hint(m, &t);
216
217         return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
218 }
219
220 static int property_get_inhibited(
221                 sd_bus *bus,
222                 const char *path,
223                 const char *interface,
224                 const char *property,
225                 sd_bus_message *reply,
226                 void *userdata,
227                 sd_bus_error *error) {
228
229         Manager *m = userdata;
230         InhibitWhat w;
231
232         assert(bus);
233         assert(reply);
234         assert(m);
235
236         w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
237
238         return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
239 }
240
241 static int property_get_preparing(
242                 sd_bus *bus,
243                 const char *path,
244                 const char *interface,
245                 const char *property,
246                 sd_bus_message *reply,
247                 void *userdata,
248                 sd_bus_error *error) {
249
250         Manager *m = userdata;
251         bool b;
252
253         assert(bus);
254         assert(reply);
255         assert(m);
256
257         if (streq(property, "PreparingForShutdown"))
258                 b = !!(m->action_what & INHIBIT_SHUTDOWN);
259         else
260                 b = !!(m->action_what & INHIBIT_SLEEP);
261
262         return sd_bus_message_append(reply, "b", b);
263 }
264
265 static int property_get_scheduled_shutdown(
266                 sd_bus *bus,
267                 const char *path,
268                 const char *interface,
269                 const char *property,
270                 sd_bus_message *reply,
271                 void *userdata,
272                 sd_bus_error *error) {
273
274         Manager *m = userdata;
275         int r;
276
277         assert(bus);
278         assert(reply);
279         assert(m);
280
281         r = sd_bus_message_open_container(reply, 'r', "st");
282         if (r < 0)
283                 return r;
284
285         r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
286         if (r < 0)
287                 return r;
288
289         return sd_bus_message_close_container(reply);
290 }
291
292 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
293
294 static int property_get_docked(
295                 sd_bus *bus,
296                 const char *path,
297                 const char *interface,
298                 const char *property,
299                 sd_bus_message *reply,
300                 void *userdata,
301                 sd_bus_error *error) {
302
303         Manager *m = userdata;
304
305         assert(bus);
306         assert(reply);
307         assert(m);
308
309         return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
310 }
311
312 static int property_get_current_sessions(
313                 sd_bus *bus,
314                 const char *path,
315                 const char *interface,
316                 const char *property,
317                 sd_bus_message *reply,
318                 void *userdata,
319                 sd_bus_error *error) {
320
321         Manager *m = userdata;
322
323         assert(bus);
324         assert(reply);
325         assert(m);
326
327         return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
328 }
329
330 static int property_get_current_inhibitors(
331                 sd_bus *bus,
332                 const char *path,
333                 const char *interface,
334                 const char *property,
335                 sd_bus_message *reply,
336                 void *userdata,
337                 sd_bus_error *error) {
338
339         Manager *m = userdata;
340
341         assert(bus);
342         assert(reply);
343         assert(m);
344
345         return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
346 }
347
348 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
349         _cleanup_free_ char *p = NULL;
350         Manager *m = userdata;
351         const char *name;
352         Session *session;
353         int r;
354
355         assert(message);
356         assert(m);
357
358         r = sd_bus_message_read(message, "s", &name);
359         if (r < 0)
360                 return r;
361
362         r = manager_get_session_from_creds(m, message, name, error, &session);
363         if (r < 0)
364                 return r;
365
366         p = session_bus_path(session);
367         if (!p)
368                 return -ENOMEM;
369
370         return sd_bus_reply_method_return(message, "o", p);
371 }
372
373 /* Get login session of a process.  This is not what you are looking for these days,
374  * as apps may instead belong to a user service unit.  This includes terminal
375  * emulators and hence command-line apps. */
376 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
377         _cleanup_free_ char *p = NULL;
378         Session *session = NULL;
379         Manager *m = userdata;
380         pid_t pid;
381         int r;
382
383         assert(message);
384         assert(m);
385
386         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
387
388         r = sd_bus_message_read(message, "u", &pid);
389         if (r < 0)
390                 return r;
391         if (pid < 0)
392                 return -EINVAL;
393
394         if (pid == 0) {
395                 r = manager_get_session_from_creds(m, message, NULL, error, &session);
396                 if (r < 0)
397                         return r;
398         } else {
399                 r = manager_get_session_by_pid(m, pid, &session);
400                 if (r < 0)
401                         return r;
402
403                 if (!session)
404                         return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
405         }
406
407         p = session_bus_path(session);
408         if (!p)
409                 return -ENOMEM;
410
411         return sd_bus_reply_method_return(message, "o", p);
412 }
413
414 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
415         _cleanup_free_ char *p = NULL;
416         Manager *m = userdata;
417         uint32_t uid;
418         User *user;
419         int r;
420
421         assert(message);
422         assert(m);
423
424         r = sd_bus_message_read(message, "u", &uid);
425         if (r < 0)
426                 return r;
427
428         r = manager_get_user_from_creds(m, message, uid, error, &user);
429         if (r < 0)
430                 return r;
431
432         p = user_bus_path(user);
433         if (!p)
434                 return -ENOMEM;
435
436         return sd_bus_reply_method_return(message, "o", p);
437 }
438
439 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
440         _cleanup_free_ char *p = NULL;
441         Manager *m = userdata;
442         User *user = NULL;
443         pid_t pid;
444         int r;
445
446         assert(message);
447         assert(m);
448
449         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
450
451         r = sd_bus_message_read(message, "u", &pid);
452         if (r < 0)
453                 return r;
454         if (pid < 0)
455                 return -EINVAL;
456
457         if (pid == 0) {
458                 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
459                 if (r < 0)
460                         return r;
461         } else {
462                 r = manager_get_user_by_pid(m, pid, &user);
463                 if (r < 0)
464                         return r;
465                 if (!user)
466                         return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
467                                                  "PID "PID_FMT" does not belong to any logged in user or lingering user",
468                                                  pid);
469         }
470
471         p = user_bus_path(user);
472         if (!p)
473                 return -ENOMEM;
474
475         return sd_bus_reply_method_return(message, "o", p);
476 }
477
478 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
479         _cleanup_free_ char *p = NULL;
480         Manager *m = userdata;
481         const char *name;
482         Seat *seat;
483         int r;
484
485         assert(message);
486         assert(m);
487
488         r = sd_bus_message_read(message, "s", &name);
489         if (r < 0)
490                 return r;
491
492         r = manager_get_seat_from_creds(m, message, name, error, &seat);
493         if (r < 0)
494                 return r;
495
496         p = seat_bus_path(seat);
497         if (!p)
498                 return -ENOMEM;
499
500         return sd_bus_reply_method_return(message, "o", p);
501 }
502
503 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
504         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
505         Manager *m = userdata;
506         Session *session;
507         Iterator i;
508         int r;
509
510         assert(message);
511         assert(m);
512
513         r = sd_bus_message_new_method_return(message, &reply);
514         if (r < 0)
515                 return r;
516
517         r = sd_bus_message_open_container(reply, 'a', "(susso)");
518         if (r < 0)
519                 return r;
520
521         HASHMAP_FOREACH(session, m->sessions, i) {
522                 _cleanup_free_ char *p = NULL;
523
524                 p = session_bus_path(session);
525                 if (!p)
526                         return -ENOMEM;
527
528                 r = sd_bus_message_append(reply, "(susso)",
529                                           session->id,
530                                           (uint32_t) session->user->uid,
531                                           session->user->name,
532                                           session->seat ? session->seat->id : "",
533                                           p);
534                 if (r < 0)
535                         return r;
536         }
537
538         r = sd_bus_message_close_container(reply);
539         if (r < 0)
540                 return r;
541
542         return sd_bus_send(NULL, reply, NULL);
543 }
544
545 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
546         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
547         Manager *m = userdata;
548         User *user;
549         Iterator i;
550         int r;
551
552         assert(message);
553         assert(m);
554
555         r = sd_bus_message_new_method_return(message, &reply);
556         if (r < 0)
557                 return r;
558
559         r = sd_bus_message_open_container(reply, 'a', "(uso)");
560         if (r < 0)
561                 return r;
562
563         HASHMAP_FOREACH(user, m->users, i) {
564                 _cleanup_free_ char *p = NULL;
565
566                 p = user_bus_path(user);
567                 if (!p)
568                         return -ENOMEM;
569
570                 r = sd_bus_message_append(reply, "(uso)",
571                                           (uint32_t) user->uid,
572                                           user->name,
573                                           p);
574                 if (r < 0)
575                         return r;
576         }
577
578         r = sd_bus_message_close_container(reply);
579         if (r < 0)
580                 return r;
581
582         return sd_bus_send(NULL, reply, NULL);
583 }
584
585 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
586         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
587         Manager *m = userdata;
588         Seat *seat;
589         Iterator i;
590         int r;
591
592         assert(message);
593         assert(m);
594
595         r = sd_bus_message_new_method_return(message, &reply);
596         if (r < 0)
597                 return r;
598
599         r = sd_bus_message_open_container(reply, 'a', "(so)");
600         if (r < 0)
601                 return r;
602
603         HASHMAP_FOREACH(seat, m->seats, i) {
604                 _cleanup_free_ char *p = NULL;
605
606                 p = seat_bus_path(seat);
607                 if (!p)
608                         return -ENOMEM;
609
610                 r = sd_bus_message_append(reply, "(so)", seat->id, p);
611                 if (r < 0)
612                         return r;
613         }
614
615         r = sd_bus_message_close_container(reply);
616         if (r < 0)
617                 return r;
618
619         return sd_bus_send(NULL, reply, NULL);
620 }
621
622 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
623         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
624         Manager *m = userdata;
625         Inhibitor *inhibitor;
626         Iterator i;
627         int r;
628
629         assert(message);
630         assert(m);
631
632         r = sd_bus_message_new_method_return(message, &reply);
633         if (r < 0)
634                 return r;
635
636         r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
637         if (r < 0)
638                 return r;
639
640         HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
641
642                 r = sd_bus_message_append(reply, "(ssssuu)",
643                                           strempty(inhibit_what_to_string(inhibitor->what)),
644                                           strempty(inhibitor->who),
645                                           strempty(inhibitor->why),
646                                           strempty(inhibit_mode_to_string(inhibitor->mode)),
647                                           (uint32_t) inhibitor->uid,
648                                           (uint32_t) inhibitor->pid);
649                 if (r < 0)
650                         return r;
651         }
652
653         r = sd_bus_message_close_container(reply);
654         if (r < 0)
655                 return r;
656
657         return sd_bus_send(NULL, reply, NULL);
658 }
659
660 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
661         const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
662         uint32_t audit_id = 0;
663         _cleanup_free_ char *id = NULL;
664         Session *session = NULL;
665         Manager *m = userdata;
666         User *user = NULL;
667         Seat *seat = NULL;
668         pid_t leader;
669         uid_t uid;
670         int remote;
671         uint32_t vtnr = 0;
672         SessionType t;
673         SessionClass c;
674         int r;
675
676         assert(message);
677         assert(m);
678
679         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
680         assert_cc(sizeof(uid_t) == sizeof(uint32_t));
681
682         r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
683         if (r < 0)
684                 return r;
685
686         if (!uid_is_valid(uid))
687                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
688         if (leader < 0 || leader == 1)
689                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
690
691         if (isempty(type))
692                 t = _SESSION_TYPE_INVALID;
693         else {
694                 t = session_type_from_string(type);
695                 if (t < 0)
696                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
697         }
698
699         if (isempty(class))
700                 c = _SESSION_CLASS_INVALID;
701         else {
702                 c = session_class_from_string(class);
703                 if (c < 0)
704                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
705         }
706
707         if (isempty(desktop))
708                 desktop = NULL;
709         else {
710                 if (!string_is_safe(desktop))
711                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
712         }
713
714         if (isempty(cseat))
715                 seat = NULL;
716         else {
717                 seat = hashmap_get(m->seats, cseat);
718                 if (!seat)
719                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
720         }
721
722         if (tty_is_vc(tty)) {
723                 int v;
724
725                 if (!seat)
726                         seat = m->seat0;
727                 else if (seat != m->seat0)
728                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
729
730                 v = vtnr_from_tty(tty);
731                 if (v <= 0)
732                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
733
734                 if (!vtnr)
735                         vtnr = (uint32_t) v;
736                 else if (vtnr != (uint32_t) v)
737                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
738
739         } else if (tty_is_console(tty)) {
740
741                 if (!seat)
742                         seat = m->seat0;
743                 else if (seat != m->seat0)
744                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
745
746                 if (vtnr != 0)
747                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
748         }
749
750         if (seat) {
751                 if (seat_has_vts(seat)) {
752                         if (!vtnr || vtnr > 63)
753                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
754                 } else {
755                         if (vtnr != 0)
756                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
757                 }
758         }
759
760         r = sd_bus_message_enter_container(message, 'a', "(sv)");
761         if (r < 0)
762                 return r;
763
764         if (t == _SESSION_TYPE_INVALID) {
765                 if (!isempty(display))
766                         t = SESSION_X11;
767                 else if (!isempty(tty))
768                         t = SESSION_TTY;
769                 else
770                         t = SESSION_UNSPECIFIED;
771         }
772
773         if (c == _SESSION_CLASS_INVALID) {
774                 if (t == SESSION_UNSPECIFIED)
775                         c = SESSION_BACKGROUND;
776                 else
777                         c = SESSION_USER;
778         }
779
780         if (leader == 0) {
781                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
782
783                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
784                 if (r < 0)
785                         return r;
786
787                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
788                 if (r < 0)
789                         return r;
790         }
791
792         r = manager_get_session_by_pid(m, leader, NULL);
793         if (r > 0)
794                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
795
796         /*
797          * Old gdm and lightdm start the user-session on the same VT as
798          * the greeter session. But they destroy the greeter session
799          * after the user-session and want the user-session to take
800          * over the VT. We need to support this for
801          * backwards-compatibility, so make sure we allow new sessions
802          * on a VT that a greeter is running on. Furthermore, to allow
803          * re-logins, we have to allow a greeter to take over a used VT for
804          * the exact same reasons.
805          */
806         if (c != SESSION_GREETER &&
807             vtnr > 0 &&
808             vtnr < m->seat0->position_count &&
809             m->seat0->positions[vtnr] &&
810             m->seat0->positions[vtnr]->class != SESSION_GREETER)
811                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
812
813         if (hashmap_size(m->sessions) >= m->sessions_max)
814                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
815
816         (void) audit_session_from_pid(leader, &audit_id);
817         if (audit_session_is_valid(audit_id)) {
818                 /* Keep our session IDs and the audit session IDs in sync */
819
820                 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
821                         return -ENOMEM;
822
823                 /* Wut? There's already a session by this name and we
824                  * didn't find it above? Weird, then let's not trust
825                  * the audit data and let's better register a new
826                  * ID */
827                 if (hashmap_get(m->sessions, id)) {
828                         log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
829                         audit_id = AUDIT_SESSION_INVALID;
830
831                         id = mfree(id);
832                 }
833         }
834
835         if (!id) {
836                 do {
837                         id = mfree(id);
838
839                         if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
840                                 return -ENOMEM;
841
842                 } while (hashmap_get(m->sessions, id));
843         }
844
845         r = manager_add_user_by_uid(m, uid, &user);
846         if (r < 0)
847                 goto fail;
848
849         r = manager_add_session(m, id, &session);
850         if (r < 0)
851                 goto fail;
852
853         session_set_user(session, user);
854
855         session->leader = leader;
856         session->audit_id = audit_id;
857         session->type = t;
858         session->class = c;
859         session->remote = remote;
860         session->vtnr = vtnr;
861
862         if (!isempty(tty)) {
863                 session->tty = strdup(tty);
864                 if (!session->tty) {
865                         r = -ENOMEM;
866                         goto fail;
867                 }
868         }
869
870         if (!isempty(display)) {
871                 session->display = strdup(display);
872                 if (!session->display) {
873                         r = -ENOMEM;
874                         goto fail;
875                 }
876         }
877
878         if (!isempty(remote_user)) {
879                 session->remote_user = strdup(remote_user);
880                 if (!session->remote_user) {
881                         r = -ENOMEM;
882                         goto fail;
883                 }
884         }
885
886         if (!isempty(remote_host)) {
887                 session->remote_host = strdup(remote_host);
888                 if (!session->remote_host) {
889                         r = -ENOMEM;
890                         goto fail;
891                 }
892         }
893
894         if (!isempty(service)) {
895                 session->service = strdup(service);
896                 if (!session->service) {
897                         r = -ENOMEM;
898                         goto fail;
899                 }
900         }
901
902         if (!isempty(desktop)) {
903                 session->desktop = strdup(desktop);
904                 if (!session->desktop) {
905                         r = -ENOMEM;
906                         goto fail;
907                 }
908         }
909
910         if (seat) {
911                 r = seat_attach_session(seat, session);
912                 if (r < 0)
913                         goto fail;
914         }
915
916         r = session_start(session);
917         if (r < 0)
918                 goto fail;
919
920         session->create_message = sd_bus_message_ref(message);
921
922 #if 0 /// UNNEEDED by elogind
923         /* Now, let's wait until the slice unit and stuff got
924          * created. We send the reply back from
925          * session_send_create_reply(). */
926 #else
927         /* We reply directly. */
928
929         r = session_send_create_reply(session, NULL);
930         if (r < 0)
931                 goto fail;
932 #endif // 0
933
934         return 1;
935
936 fail:
937         if (session)
938                 session_add_to_gc_queue(session);
939
940         if (user)
941                 user_add_to_gc_queue(user);
942
943         return r;
944 }
945
946 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
947         Manager *m = userdata;
948         Session *session;
949         const char *name;
950         int r;
951
952         assert(message);
953         assert(m);
954
955         r = sd_bus_message_read(message, "s", &name);
956         if (r < 0)
957                 return r;
958
959         r = manager_get_session_from_creds(m, message, name, error, &session);
960         if (r < 0)
961                 return r;
962
963         r = session_release(session);
964         if (r < 0)
965                 return r;
966
967 #if 1 /// elogind must queue this session
968         session_add_to_gc_queue(session);
969 #endif // 1
970         return sd_bus_reply_method_return(message, NULL);
971 }
972
973 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
974         Manager *m = userdata;
975         Session *session;
976         const char *name;
977         int r;
978
979         assert(message);
980         assert(m);
981
982         r = sd_bus_message_read(message, "s", &name);
983         if (r < 0)
984                 return r;
985
986         r = manager_get_session_from_creds(m, message, name, error, &session);
987         if (r < 0)
988                 return r;
989
990         return bus_session_method_activate(message, session, error);
991 }
992
993 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
994         const char *session_name, *seat_name;
995         Manager *m = userdata;
996         Session *session;
997         Seat *seat;
998         int r;
999
1000         assert(message);
1001         assert(m);
1002
1003         /* Same as ActivateSession() but refuses to work if
1004          * the seat doesn't match */
1005
1006         r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
1007         if (r < 0)
1008                 return r;
1009
1010         r = manager_get_session_from_creds(m, message, session_name, error, &session);
1011         if (r < 0)
1012                 return r;
1013
1014         r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1015         if (r < 0)
1016                 return r;
1017
1018         if (session->seat != seat)
1019                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
1020
1021         r = session_activate(session);
1022         if (r < 0)
1023                 return r;
1024
1025         return sd_bus_reply_method_return(message, NULL);
1026 }
1027
1028 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1029         Manager *m = userdata;
1030         Session *session;
1031         const char *name;
1032         int r;
1033
1034         assert(message);
1035         assert(m);
1036
1037         r = sd_bus_message_read(message, "s", &name);
1038         if (r < 0)
1039                 return r;
1040
1041         r = manager_get_session_from_creds(m, message, name, error, &session);
1042         if (r < 0)
1043                 return r;
1044
1045         return bus_session_method_lock(message, session, error);
1046 }
1047
1048 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1049         Manager *m = userdata;
1050         int r;
1051
1052         assert(message);
1053         assert(m);
1054
1055         r = bus_verify_polkit_async(
1056                         message,
1057                         CAP_SYS_ADMIN,
1058                         "org.freedesktop.login1.lock-sessions",
1059                         NULL,
1060                         false,
1061                         UID_INVALID,
1062                         &m->polkit_registry,
1063                         error);
1064         if (r < 0)
1065                 return r;
1066         if (r == 0)
1067                 return 1; /* Will call us back */
1068
1069         r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1070         if (r < 0)
1071                 return r;
1072
1073         return sd_bus_reply_method_return(message, NULL);
1074 }
1075
1076 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1077         const char *name;
1078         Manager *m = userdata;
1079         Session *session;
1080         int r;
1081
1082         assert(message);
1083         assert(m);
1084
1085         r = sd_bus_message_read(message, "s", &name);
1086         if (r < 0)
1087                 return r;
1088
1089         r = manager_get_session_from_creds(m, message, name, error, &session);
1090         if (r < 0)
1091                 return r;
1092
1093         return bus_session_method_kill(message, session, error);
1094 }
1095
1096 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1097         Manager *m = userdata;
1098         uint32_t uid;
1099         User *user;
1100         int r;
1101
1102         assert(message);
1103         assert(m);
1104
1105         r = sd_bus_message_read(message, "u", &uid);
1106         if (r < 0)
1107                 return r;
1108
1109         r = manager_get_user_from_creds(m, message, uid, error, &user);
1110         if (r < 0)
1111                 return r;
1112
1113         return bus_user_method_kill(message, user, error);
1114 }
1115
1116 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1117         Manager *m = userdata;
1118         const char *name;
1119         Session *session;
1120         int r;
1121
1122         assert(message);
1123         assert(m);
1124
1125         r = sd_bus_message_read(message, "s", &name);
1126         if (r < 0)
1127                 return r;
1128
1129         r = manager_get_session_from_creds(m, message, name, error, &session);
1130         if (r < 0)
1131                 return r;
1132
1133         return bus_session_method_terminate(message, session, error);
1134 }
1135
1136 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1137         Manager *m = userdata;
1138         uint32_t uid;
1139         User *user;
1140         int r;
1141
1142         assert(message);
1143         assert(m);
1144
1145         r = sd_bus_message_read(message, "u", &uid);
1146         if (r < 0)
1147                 return r;
1148
1149         r = manager_get_user_from_creds(m, message, uid, error, &user);
1150         if (r < 0)
1151                 return r;
1152
1153         return bus_user_method_terminate(message, user, error);
1154 }
1155
1156 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1157         Manager *m = userdata;
1158         const char *name;
1159         Seat *seat;
1160         int r;
1161
1162         assert(message);
1163         assert(m);
1164
1165         r = sd_bus_message_read(message, "s", &name);
1166         if (r < 0)
1167                 return r;
1168
1169         r = manager_get_seat_from_creds(m, message, name, error, &seat);
1170         if (r < 0)
1171                 return r;
1172
1173         return bus_seat_method_terminate(message, seat, error);
1174 }
1175
1176 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1177         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1178         _cleanup_free_ char *cc = NULL;
1179         Manager *m = userdata;
1180         int r, b, interactive;
1181         struct passwd *pw;
1182         const char *path;
1183         uint32_t uid, auth_uid;
1184
1185         assert(message);
1186         assert(m);
1187
1188         r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1189         if (r < 0)
1190                 return r;
1191
1192         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1193                                                SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1194         if (r < 0)
1195                 return r;
1196
1197         if (!uid_is_valid(uid)) {
1198                 /* Note that we get the owner UID of the session or user unit,
1199                  * not the actual client UID here! */
1200                 r = sd_bus_creds_get_owner_uid(creds, &uid);
1201                 if (r < 0)
1202                         return r;
1203         }
1204
1205         /* owner_uid is racy, so for authorization we must use euid */
1206         r = sd_bus_creds_get_euid(creds, &auth_uid);
1207         if (r < 0)
1208                 return r;
1209
1210         errno = 0;
1211         pw = getpwuid(uid);
1212         if (!pw)
1213                 return errno > 0 ? -errno : -ENOENT;
1214
1215         r = bus_verify_polkit_async(
1216                         message,
1217                         CAP_SYS_ADMIN,
1218                         uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1219                                           "org.freedesktop.login1.set-user-linger",
1220                         NULL,
1221                         interactive,
1222                         UID_INVALID,
1223                         &m->polkit_registry,
1224                         error);
1225         if (r < 0)
1226                 return r;
1227         if (r == 0)
1228                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1229
1230         mkdir_p_label("/var/lib/elogind", 0755);
1231
1232         r = mkdir_safe_label("/var/lib/elogind/linger", 0755, 0, 0, false);
1233         if (r < 0)
1234                 return r;
1235
1236         cc = cescape(pw->pw_name);
1237         if (!cc)
1238                 return -ENOMEM;
1239
1240         path = strjoina("/var/lib/elogind/linger/", cc);
1241         if (b) {
1242                 User *u;
1243
1244                 r = touch(path);
1245                 if (r < 0)
1246                         return r;
1247
1248                 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1249                         user_start(u);
1250
1251         } else {
1252                 User *u;
1253
1254                 r = unlink(path);
1255                 if (r < 0 && errno != ENOENT)
1256                         return -errno;
1257
1258                 u = hashmap_get(m->users, UID_TO_PTR(uid));
1259                 if (u)
1260                         user_add_to_gc_queue(u);
1261         }
1262
1263         return sd_bus_reply_method_return(message, NULL);
1264 }
1265
1266 static int trigger_device(Manager *m, struct udev_device *d) {
1267         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1268         struct udev_list_entry *first, *item;
1269         int r;
1270
1271         assert(m);
1272
1273         e = udev_enumerate_new(m->udev);
1274         if (!e)
1275                 return -ENOMEM;
1276
1277         if (d) {
1278                 r = udev_enumerate_add_match_parent(e, d);
1279                 if (r < 0)
1280                         return r;
1281         }
1282
1283         r = udev_enumerate_scan_devices(e);
1284         if (r < 0)
1285                 return r;
1286
1287         first = udev_enumerate_get_list_entry(e);
1288         udev_list_entry_foreach(item, first) {
1289                 _cleanup_free_ char *t = NULL;
1290                 const char *p;
1291
1292                 p = udev_list_entry_get_name(item);
1293
1294                 t = strappend(p, "/uevent");
1295                 if (!t)
1296                         return -ENOMEM;
1297
1298                 (void) write_string_file(t, "change", 0);
1299         }
1300
1301         return 0;
1302 }
1303
1304 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1305         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1306         _cleanup_free_ char *rule = NULL, *file = NULL;
1307         const char *id_for_seat;
1308         int r;
1309
1310         assert(m);
1311         assert(seat);
1312         assert(sysfs);
1313
1314         d = udev_device_new_from_syspath(m->udev, sysfs);
1315         if (!d)
1316                 return -ENODEV;
1317
1318         if (!udev_device_has_tag(d, "seat"))
1319                 return -ENODEV;
1320
1321         id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1322         if (!id_for_seat)
1323                 return -ENODEV;
1324
1325         if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1326                 return -ENOMEM;
1327
1328         if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1329                 return -ENOMEM;
1330
1331         mkdir_p_label("/etc/udev/rules.d", 0755);
1332         r = write_string_file_atomic_label(file, rule);
1333         if (r < 0)
1334                 return r;
1335
1336         return trigger_device(m, d);
1337 }
1338
1339 static int flush_devices(Manager *m) {
1340         _cleanup_closedir_ DIR *d;
1341
1342         assert(m);
1343
1344         d = opendir("/etc/udev/rules.d");
1345         if (!d) {
1346                 if (errno != ENOENT)
1347                         log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1348         } else {
1349                 struct dirent *de;
1350
1351                 FOREACH_DIRENT_ALL(de, d, break) {
1352                         if (!dirent_is_file(de))
1353                                 continue;
1354
1355                         if (!startswith(de->d_name, "72-seat-"))
1356                                 continue;
1357
1358                         if (!endswith(de->d_name, ".rules"))
1359                                 continue;
1360
1361                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1362                                 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1363                 }
1364         }
1365
1366         return trigger_device(m, NULL);
1367 }
1368
1369 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1370         const char *sysfs, *seat;
1371         Manager *m = userdata;
1372         int interactive, r;
1373
1374         assert(message);
1375         assert(m);
1376
1377         r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1378         if (r < 0)
1379                 return r;
1380
1381         if (!path_startswith(sysfs, "/sys"))
1382                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1383
1384         if (!seat_name_is_valid(seat))
1385                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1386
1387         r = bus_verify_polkit_async(
1388                         message,
1389                         CAP_SYS_ADMIN,
1390                         "org.freedesktop.login1.attach-device",
1391                         NULL,
1392                         interactive,
1393                         UID_INVALID,
1394                         &m->polkit_registry,
1395                         error);
1396         if (r < 0)
1397                 return r;
1398         if (r == 0)
1399                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1400
1401         r = attach_device(m, seat, sysfs);
1402         if (r < 0)
1403                 return r;
1404
1405         return sd_bus_reply_method_return(message, NULL);
1406 }
1407
1408 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1409         Manager *m = userdata;
1410         int interactive, r;
1411
1412         assert(message);
1413         assert(m);
1414
1415         r = sd_bus_message_read(message, "b", &interactive);
1416         if (r < 0)
1417                 return r;
1418
1419         r = bus_verify_polkit_async(
1420                         message,
1421                         CAP_SYS_ADMIN,
1422                         "org.freedesktop.login1.flush-devices",
1423                         NULL,
1424                         interactive,
1425                         UID_INVALID,
1426                         &m->polkit_registry,
1427                         error);
1428         if (r < 0)
1429                 return r;
1430         if (r == 0)
1431                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1432
1433         r = flush_devices(m);
1434         if (r < 0)
1435                 return r;
1436
1437         return sd_bus_reply_method_return(message, NULL);
1438 }
1439
1440 static int have_multiple_sessions(
1441                 Manager *m,
1442                 uid_t uid) {
1443
1444         Session *session;
1445         Iterator i;
1446
1447         assert(m);
1448
1449         /* Check for other users' sessions. Greeter sessions do not
1450          * count, and non-login sessions do not count either. */
1451         HASHMAP_FOREACH(session, m->sessions, i)
1452                 if (session->class == SESSION_USER &&
1453                     session->user->uid != uid)
1454                         return true;
1455
1456         return false;
1457 }
1458
1459 #if 0 /// elogind has its own variant in elogind-dbus.c
1460 static int bus_manager_log_shutdown(
1461                 Manager *m,
1462                 const char *unit_name) {
1463
1464         const char *p, *q;
1465
1466         assert(m);
1467         assert(unit_name);
1468
1469         if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1470                 p = "MESSAGE=System is powering down";
1471                 q = "SHUTDOWN=power-off";
1472         } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1473                 p = "MESSAGE=System is rebooting";
1474                 q = "SHUTDOWN=reboot";
1475         } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1476                 p = "MESSAGE=System is halting";
1477                 q = "SHUTDOWN=halt";
1478         } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1479                 p = "MESSAGE=System is rebooting with kexec";
1480                 q = "SHUTDOWN=kexec";
1481         } else {
1482                 p = "MESSAGE=System is shutting down";
1483                 q = NULL;
1484         }
1485
1486         if (isempty(m->wall_message))
1487                 p = strjoina(p, ".");
1488         else
1489                 p = strjoina(p, " (", m->wall_message, ").");
1490
1491         return log_struct(LOG_NOTICE,
1492                           "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
1493                           p,
1494                           q,
1495                           NULL);
1496 }
1497 #endif // 0
1498
1499 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1500         Manager *m = userdata;
1501
1502         assert(e);
1503         assert(m);
1504
1505         m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1506         return 0;
1507 }
1508
1509 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1510         int r;
1511
1512         assert(m);
1513
1514         if (until <= now(CLOCK_MONOTONIC))
1515                 return 0;
1516
1517         /* We want to ignore the lid switch for a while after each
1518          * suspend, and after boot-up. Hence let's install a timer for
1519          * this. As long as the event source exists we ignore the lid
1520          * switch. */
1521
1522         if (m->lid_switch_ignore_event_source) {
1523                 usec_t u;
1524
1525                 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1526                 if (r < 0)
1527                         return r;
1528
1529                 if (until <= u)
1530                         return 0;
1531
1532                 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1533         } else
1534                 r = sd_event_add_time(
1535                                 m->event,
1536                                 &m->lid_switch_ignore_event_source,
1537                                 CLOCK_MONOTONIC,
1538                                 until, 0,
1539                                 lid_switch_ignore_handler, m);
1540
1541         return r;
1542 }
1543
1544 #if 0 /// elogind-dbus.c needs to access this
1545 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1546 #else
1547 int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1548 #endif // 0
1549
1550         static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1551                 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1552                 [INHIBIT_SLEEP] = "PrepareForSleep"
1553         };
1554
1555         int active = _active;
1556
1557         assert(m);
1558         assert(w >= 0);
1559         assert(w < _INHIBIT_WHAT_MAX);
1560         assert(signal_name[w]);
1561
1562         return sd_bus_emit_signal(m->bus,
1563                                   "/org/freedesktop/login1",
1564                                   "org.freedesktop.login1.Manager",
1565                                   signal_name[w],
1566                                   "b",
1567                                   active);
1568 }
1569
1570 #if 0 /// elogind has its own variant in elogind-dbus.c
1571 static int execute_shutdown_or_sleep(
1572                 Manager *m,
1573                 InhibitWhat w,
1574                 const char *unit_name,
1575                 sd_bus_error *error) {
1576
1577         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1578         char *c = NULL;
1579         const char *p;
1580         int r;
1581
1582         assert(m);
1583         assert(w > 0);
1584         assert(w < _INHIBIT_WHAT_MAX);
1585         assert(unit_name);
1586
1587         if (w == INHIBIT_SHUTDOWN)
1588                 bus_manager_log_shutdown(m, unit_name);
1589
1590         r = sd_bus_call_method(
1591                         m->bus,
1592                         "org.freedesktop.systemd1",
1593                         "/org/freedesktop/systemd1",
1594                         "org.freedesktop.systemd1.Manager",
1595                         "StartUnit",
1596                         error,
1597                         &reply,
1598                         "ss", unit_name, "replace-irreversibly");
1599         if (r < 0)
1600                 goto error;
1601
1602         r = sd_bus_message_read(reply, "o", &p);
1603         if (r < 0)
1604                 goto error;
1605
1606         c = strdup(p);
1607         if (!c) {
1608                 r = -ENOMEM;
1609                 goto error;
1610         }
1611
1612         m->action_unit = unit_name;
1613         free(m->action_job);
1614         m->action_job = c;
1615         m->action_what = w;
1616
1617         /* Make sure the lid switch is ignored for a while */
1618         manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1619
1620         return 0;
1621
1622 error:
1623         /* Tell people that they now may take a lock again */
1624         (void) send_prepare_for(m, w, false);
1625
1626         return r;
1627 }
1628
1629 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1630
1631         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1632         Inhibitor *offending = NULL;
1633         int r;
1634
1635         assert(manager);
1636
1637         if (manager->action_what == 0 || manager->action_job)
1638                 return 0;
1639
1640         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1641                 _cleanup_free_ char *comm = NULL, *u = NULL;
1642
1643                 if (!timeout)
1644                         return 0;
1645
1646                 (void) get_process_comm(offending->pid, &comm);
1647                 u = uid_to_name(offending->uid);
1648
1649                 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1650                            offending->uid, strna(u),
1651                            offending->pid, strna(comm));
1652         }
1653
1654         /* Actually do the operation */
1655         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1656         if (r < 0) {
1657                 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1658                             bus_error_message(&error, r));
1659
1660                 manager->action_unit = NULL;
1661                 manager->action_what = 0;
1662                 return r;
1663         }
1664
1665         return 1;
1666 }
1667 #endif // 0
1668
1669 #if 0 /// elogind-dbus.c needs to access this
1670 static int manager_inhibit_timeout_handler(
1671 #else
1672 int manager_inhibit_timeout_handler(
1673 #endif // 0
1674                         sd_event_source *s,
1675                         uint64_t usec,
1676                         void *userdata) {
1677
1678         Manager *manager = userdata;
1679         int r;
1680
1681         assert(manager);
1682         assert(manager->inhibit_timeout_source == s);
1683
1684         r = manager_dispatch_delayed(manager, true);
1685         return (r < 0) ? r : 0;
1686 }
1687
1688 #if 0 /// elogind has its own variant in elogind-dbus.c
1689 static int delay_shutdown_or_sleep(
1690                 Manager *m,
1691                 InhibitWhat w,
1692                 const char *unit_name) {
1693
1694         int r;
1695         usec_t timeout_val;
1696
1697         assert(m);
1698         assert(w >= 0);
1699         assert(w < _INHIBIT_WHAT_MAX);
1700         assert(unit_name);
1701
1702         timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1703
1704         if (m->inhibit_timeout_source) {
1705                 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1706                 if (r < 0)
1707                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1708
1709                 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1710                 if (r < 0)
1711                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1712         } else {
1713                 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1714                                       timeout_val, 0, manager_inhibit_timeout_handler, m);
1715                 if (r < 0)
1716                         return r;
1717         }
1718
1719         m->action_unit = unit_name;
1720         m->action_what = w;
1721
1722         return 0;
1723 }
1724 #endif // 0
1725
1726 #if 0 /// elogind has its own variant in elogind-dbus.c
1727 int bus_manager_shutdown_or_sleep_now_or_later(
1728                 Manager *m,
1729                 const char *unit_name,
1730                 InhibitWhat w,
1731                 sd_bus_error *error) {
1732
1733         bool delayed;
1734         int r;
1735
1736         assert(m);
1737         assert(unit_name);
1738         assert(w > 0);
1739         assert(w <= _INHIBIT_WHAT_MAX);
1740         assert(!m->action_job);
1741
1742         /* Tell everybody to prepare for shutdown/sleep */
1743         (void) send_prepare_for(m, w, true);
1744
1745         delayed =
1746                 m->inhibit_delay_max > 0 &&
1747                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1748
1749         log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
1750                           handle_action_to_string(action),
1751                           delayed ? "" : "NOT ");
1752         if (delayed)
1753                 /* Shutdown is delayed, keep in mind what we
1754                  * want to do, and start a timeout */
1755                 r = delay_shutdown_or_sleep(m, w, unit_name);
1756         else
1757                 /* Shutdown is not delayed, execute it
1758                  * immediately */
1759                 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1760
1761         return r;
1762 }
1763 #endif // 0
1764
1765 #if 0 /// elogind-dbus.c needs to access this
1766 static int verify_shutdown_creds(
1767 #else
1768 int verify_shutdown_creds(
1769 #endif // 0
1770                 Manager *m,
1771                 sd_bus_message *message,
1772                 InhibitWhat w,
1773                 bool interactive,
1774                 const char *action,
1775                 const char *action_multiple_sessions,
1776                 const char *action_ignore_inhibit,
1777                 sd_bus_error *error) {
1778
1779         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1780         bool multiple_sessions, blocked;
1781         uid_t uid;
1782         int r;
1783
1784         assert(m);
1785         assert(message);
1786         assert(w >= 0);
1787         assert(w <= _INHIBIT_WHAT_MAX);
1788
1789         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1790         if (r < 0)
1791                 return r;
1792
1793         r = sd_bus_creds_get_euid(creds, &uid);
1794         if (r < 0)
1795                 return r;
1796
1797         r = have_multiple_sessions(m, uid);
1798         if (r < 0)
1799                 return r;
1800
1801         multiple_sessions = r > 0;
1802         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1803
1804         if (multiple_sessions && action_multiple_sessions) {
1805                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1806                 if (r < 0)
1807                         return r;
1808                 if (r == 0)
1809                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1810         }
1811
1812         if (blocked && action_ignore_inhibit) {
1813                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1814                 if (r < 0)
1815                         return r;
1816                 if (r == 0)
1817                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1818         }
1819
1820         if (!multiple_sessions && !blocked && action) {
1821                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1822                 if (r < 0)
1823                         return r;
1824                 if (r == 0)
1825                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1826         }
1827
1828         return 0;
1829 }
1830
1831 #if 0 /// elogind has its own variant in elogind-dbus.c
1832 static int method_do_shutdown_or_sleep(
1833                 Manager *m,
1834                 sd_bus_message *message,
1835                 const char *unit_name,
1836                 InhibitWhat w,
1837                 const char *action,
1838                 const char *action_multiple_sessions,
1839                 const char *action_ignore_inhibit,
1840                 const char *sleep_verb,
1841                 sd_bus_error *error) {
1842
1843         int interactive, r;
1844
1845         assert(m);
1846         assert(message);
1847         assert(unit_name);
1848         assert(w >= 0);
1849         assert(w <= _INHIBIT_WHAT_MAX);
1850
1851         r = sd_bus_message_read(message, "b", &interactive);
1852         if (r < 0)
1853                 return r;
1854
1855         /* Don't allow multiple jobs being executed at the same time */
1856         if (m->action_what)
1857                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1858
1859         if (sleep_verb) {
1860                 r = can_sleep(sleep_verb);
1861                 if (r < 0)
1862                         return r;
1863
1864                 if (r == 0)
1865                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1866         }
1867
1868         r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1869                                   action_ignore_inhibit, error);
1870         log_debug_elogind("verify_shutdown_creds() returned %d", r);
1871         if (r != 0)
1872                 return r;
1873
1874         r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1875         if (r < 0)
1876                 return r;
1877
1878         return sd_bus_reply_method_return(message, NULL);
1879 }
1880
1881 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1882         Manager *m = userdata;
1883
1884         return method_do_shutdown_or_sleep(
1885                         m, message,
1886                         SPECIAL_POWEROFF_TARGET,
1887                         INHIBIT_SHUTDOWN,
1888                         "org.freedesktop.login1.power-off",
1889                         "org.freedesktop.login1.power-off-multiple-sessions",
1890                         "org.freedesktop.login1.power-off-ignore-inhibit",
1891                         NULL,
1892                         error);
1893 }
1894
1895 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1896         Manager *m = userdata;
1897
1898         return method_do_shutdown_or_sleep(
1899                         m, message,
1900                         SPECIAL_REBOOT_TARGET,
1901                         INHIBIT_SHUTDOWN,
1902                         "org.freedesktop.login1.reboot",
1903                         "org.freedesktop.login1.reboot-multiple-sessions",
1904                         "org.freedesktop.login1.reboot-ignore-inhibit",
1905                         NULL,
1906                         error);
1907 }
1908
1909 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1910         Manager *m = userdata;
1911
1912         return method_do_shutdown_or_sleep(
1913                         m, message,
1914                         SPECIAL_HALT_TARGET,
1915                         INHIBIT_SHUTDOWN,
1916                         "org.freedesktop.login1.halt",
1917                         "org.freedesktop.login1.halt-multiple-sessions",
1918                         "org.freedesktop.login1.halt-ignore-inhibit",
1919                         NULL,
1920                         error);
1921 }
1922
1923 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1924         Manager *m = userdata;
1925
1926         return method_do_shutdown_or_sleep(
1927                         m, message,
1928                         SPECIAL_SUSPEND_TARGET,
1929                         INHIBIT_SLEEP,
1930                         "org.freedesktop.login1.suspend",
1931                         "org.freedesktop.login1.suspend-multiple-sessions",
1932                         "org.freedesktop.login1.suspend-ignore-inhibit",
1933                         "suspend",
1934                         error);
1935 }
1936
1937 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1938         Manager *m = userdata;
1939
1940         return method_do_shutdown_or_sleep(
1941                         m, message,
1942                         SPECIAL_HIBERNATE_TARGET,
1943                         INHIBIT_SLEEP,
1944                         "org.freedesktop.login1.hibernate",
1945                         "org.freedesktop.login1.hibernate-multiple-sessions",
1946                         "org.freedesktop.login1.hibernate-ignore-inhibit",
1947                         "hibernate",
1948                         error);
1949 }
1950
1951 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1952         Manager *m = userdata;
1953
1954         return method_do_shutdown_or_sleep(
1955                         m, message,
1956                         SPECIAL_HYBRID_SLEEP_TARGET,
1957                         INHIBIT_SLEEP,
1958                         "org.freedesktop.login1.hibernate",
1959                         "org.freedesktop.login1.hibernate-multiple-sessions",
1960                         "org.freedesktop.login1.hibernate-ignore-inhibit",
1961                         "hybrid-sleep",
1962                         error);
1963 }
1964 #endif // 0
1965
1966 static int nologin_timeout_handler(
1967                         sd_event_source *s,
1968                         uint64_t usec,
1969                         void *userdata) {
1970
1971         Manager *m = userdata;
1972         int r;
1973
1974         log_info("Creating /run/nologin, blocking further logins...");
1975
1976         r = write_string_file_atomic_label("/run/nologin", "System is going down.");
1977         if (r < 0)
1978                 log_error_errno(r, "Failed to create /run/nologin: %m");
1979         else
1980                 m->unlink_nologin = true;
1981
1982         return 0;
1983 }
1984
1985 static int update_schedule_file(Manager *m) {
1986         _cleanup_free_ char *temp_path = NULL;
1987         _cleanup_fclose_ FILE *f = NULL;
1988         int r;
1989
1990         assert(m);
1991
1992         r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false);
1993         if (r < 0)
1994                 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1995
1996         r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1997         if (r < 0)
1998                 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1999
2000         (void) fchmod(fileno(f), 0644);
2001
2002         fprintf(f,
2003                 "USEC="USEC_FMT"\n"
2004                 "WARN_WALL=%i\n"
2005                 "MODE=%s\n",
2006                 m->scheduled_shutdown_timeout,
2007                 m->enable_wall_messages,
2008                 m->scheduled_shutdown_type);
2009
2010         if (!isempty(m->wall_message)) {
2011                 _cleanup_free_ char *t;
2012
2013                 t = cescape(m->wall_message);
2014                 if (!t) {
2015                         r = -ENOMEM;
2016                         goto fail;
2017                 }
2018
2019                 fprintf(f, "WALL_MESSAGE=%s\n", t);
2020         }
2021
2022         r = fflush_and_check(f);
2023         if (r < 0)
2024                 goto fail;
2025
2026         if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2027                 r = -errno;
2028                 goto fail;
2029         }
2030
2031         return 0;
2032
2033 fail:
2034         (void) unlink(temp_path);
2035         (void) unlink("/run/systemd/shutdown/scheduled");
2036
2037         return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2038 }
2039
2040 static void reset_scheduled_shutdown(Manager *m) {
2041         assert(m);
2042
2043         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2044         m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2045         m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2046
2047         m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2048         m->scheduled_shutdown_timeout = 0;
2049         m->shutdown_dry_run = false;
2050
2051         if (m->unlink_nologin) {
2052                 (void) unlink("/run/nologin");
2053                 m->unlink_nologin = false;
2054         }
2055
2056         (void) unlink("/run/systemd/shutdown/scheduled");
2057 }
2058
2059 #if 0 /// elogind has its own variant in elogind-dbus.c
2060 static int manager_scheduled_shutdown_handler(
2061                         sd_event_source *s,
2062                         uint64_t usec,
2063                         void *userdata) {
2064
2065         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2066         Manager *m = userdata;
2067         const char *target;
2068         int r;
2069
2070         assert(m);
2071
2072         if (isempty(m->scheduled_shutdown_type))
2073                 return 0;
2074
2075         if (streq(m->scheduled_shutdown_type, "poweroff"))
2076                 target = SPECIAL_POWEROFF_TARGET;
2077         else if (streq(m->scheduled_shutdown_type, "reboot"))
2078                 target = SPECIAL_REBOOT_TARGET;
2079         else if (streq(m->scheduled_shutdown_type, "halt"))
2080                 target = SPECIAL_HALT_TARGET;
2081         else
2082                 assert_not_reached("unexpected shutdown type");
2083
2084         /* Don't allow multiple jobs being executed at the same time */
2085         if (m->action_what) {
2086                 r = -EALREADY;
2087                 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2088                 goto error;
2089         }
2090
2091         if (m->shutdown_dry_run) {
2092                 /* We do not process delay inhibitors here.  Otherwise, we
2093                  * would have to be considered "in progress" (like the check
2094                  * above) for some seconds after our admin has seen the final
2095                  * wall message. */
2096
2097                 bus_manager_log_shutdown(m, target);
2098                 log_info("Running in dry run, suppressing action.");
2099                 reset_scheduled_shutdown(m);
2100
2101                 return 0;
2102         }
2103
2104         r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2105         if (r < 0) {
2106                 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2107                 goto error;
2108         }
2109
2110         return 0;
2111
2112 error:
2113         reset_scheduled_shutdown(m);
2114         return r;
2115 }
2116 #endif // 0
2117
2118 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2119         Manager *m = userdata;
2120         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2121         const char *action_multiple_sessions = NULL;
2122         const char *action_ignore_inhibit = NULL;
2123         const char *action = NULL;
2124         uint64_t elapse;
2125         char *type;
2126         int r;
2127         bool dry_run = false;
2128
2129         assert(m);
2130         assert(message);
2131
2132         log_debug_elogind("%s called", __FUNCTION__);
2133         r = sd_bus_message_read(message, "st", &type, &elapse);
2134         if (r < 0)
2135                 return r;
2136
2137         if (startswith(type, "dry-")) {
2138                 type += 4;
2139                 dry_run = true;
2140         }
2141
2142         if (streq(type, "poweroff")) {
2143                 action = "org.freedesktop.login1.power-off";
2144                 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2145                 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2146         } else if (streq(type, "reboot")) {
2147                 action = "org.freedesktop.login1.reboot";
2148                 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2149                 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2150         } else if (streq(type, "halt")) {
2151                 action = "org.freedesktop.login1.halt";
2152                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2153                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2154         } else
2155                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2156
2157         r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2158                                   action, action_multiple_sessions, action_ignore_inhibit, error);
2159         if (r != 0)
2160                 return r;
2161
2162         if (m->scheduled_shutdown_timeout_source) {
2163                 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2164                 if (r < 0)
2165                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2166
2167                 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2168                 if (r < 0)
2169                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2170         } else {
2171                 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2172                                       CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2173                 if (r < 0)
2174                         return log_error_errno(r, "sd_event_add_time() failed: %m");
2175         }
2176
2177         r = free_and_strdup(&m->scheduled_shutdown_type, type);
2178         if (r < 0) {
2179                 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2180                 return log_oom();
2181         }
2182
2183         m->shutdown_dry_run = dry_run;
2184
2185         if (m->nologin_timeout_source) {
2186                 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2187                 if (r < 0)
2188                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2189
2190                 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2191                 if (r < 0)
2192                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2193         } else {
2194                 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2195                                       CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2196                 if (r < 0)
2197                         return log_error_errno(r, "sd_event_add_time() failed: %m");
2198         }
2199
2200         m->scheduled_shutdown_timeout = elapse;
2201
2202         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2203         if (r >= 0) {
2204                 const char *tty = NULL;
2205
2206                 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2207                 (void) sd_bus_creds_get_tty(creds, &tty);
2208
2209                 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2210                 if (r < 0) {
2211                         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2212                         return log_oom();
2213                 }
2214         }
2215
2216         r = manager_setup_wall_message_timer(m);
2217         if (r < 0)
2218                 return r;
2219
2220         r = update_schedule_file(m);
2221         if (r < 0)
2222                 return r;
2223
2224         return sd_bus_reply_method_return(message, NULL);
2225 }
2226
2227 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2228         Manager *m = userdata;
2229         bool cancelled;
2230 #if 1 /// elogind needs to construct the message to allow extra wall messages
2231         _cleanup_free_ char *l = NULL;
2232 #endif // 1
2233
2234         assert(m);
2235         assert(message);
2236
2237         log_debug_elogind("%s called", __FUNCTION__);
2238         cancelled = m->scheduled_shutdown_type != NULL;
2239         reset_scheduled_shutdown(m);
2240
2241         if (cancelled) {
2242                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2243                 const char *tty = NULL;
2244                 uid_t uid = 0;
2245                 int r;
2246
2247                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2248                 if (r >= 0) {
2249                         (void) sd_bus_creds_get_uid(creds, &uid);
2250                         (void) sd_bus_creds_get_tty(creds, &tty);
2251                 }
2252
2253 #if 0 /// elogind wants to allow extra cancellation messages
2254                 utmp_wall("The system shutdown has been cancelled",
2255                           uid_to_name(uid), tty, logind_wall_tty_filter, m);
2256 #else
2257                 r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
2258                              strempty(m->wall_message),
2259                              isempty(m->wall_message) ? "" : "\n");
2260                 if (r < 0) {
2261                         log_oom();
2262                         return 0;
2263                 }
2264
2265                 utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
2266 #endif // 0
2267         }
2268
2269         return sd_bus_reply_method_return(message, "b", cancelled);
2270 }
2271
2272 static int method_can_shutdown_or_sleep(
2273                 Manager *m,
2274                 sd_bus_message *message,
2275                 InhibitWhat w,
2276                 const char *action,
2277                 const char *action_multiple_sessions,
2278                 const char *action_ignore_inhibit,
2279                 const char *sleep_verb,
2280                 sd_bus_error *error) {
2281
2282         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2283         bool multiple_sessions, challenge, blocked;
2284         const char *result = NULL;
2285         uid_t uid;
2286         int r;
2287
2288         assert(m);
2289         assert(message);
2290         assert(w >= 0);
2291         assert(w <= _INHIBIT_WHAT_MAX);
2292         assert(action);
2293         assert(action_multiple_sessions);
2294         assert(action_ignore_inhibit);
2295
2296         if (sleep_verb) {
2297 #if 0 /// elogind needs to have the manager being passed
2298                 r = can_sleep(sleep_verb);
2299 #else
2300                 r = can_sleep(m, sleep_verb);
2301 #endif // 0
2302                 if (r < 0)
2303                         return r;
2304                 if (r == 0)
2305                         return sd_bus_reply_method_return(message, "s", "na");
2306         }
2307
2308         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2309         if (r < 0)
2310                 return r;
2311
2312         r = sd_bus_creds_get_euid(creds, &uid);
2313         if (r < 0)
2314                 return r;
2315
2316         r = have_multiple_sessions(m, uid);
2317         if (r < 0)
2318                 return r;
2319
2320         multiple_sessions = r > 0;
2321         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2322
2323         if (multiple_sessions) {
2324                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2325                 if (r < 0)
2326                         return r;
2327
2328                 if (r > 0)
2329                         result = "yes";
2330                 else if (challenge)
2331                         result = "challenge";
2332                 else
2333                         result = "no";
2334         }
2335
2336         if (blocked) {
2337                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2338                 if (r < 0)
2339                         return r;
2340
2341                 if (r > 0 && !result)
2342                         result = "yes";
2343                 else if (challenge && (!result || streq(result, "yes")))
2344                         result = "challenge";
2345                 else
2346                         result = "no";
2347         }
2348
2349         if (!multiple_sessions && !blocked) {
2350                 /* If neither inhibit nor multiple sessions
2351                  * apply then just check the normal policy */
2352
2353                 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2354                 if (r < 0)
2355                         return r;
2356
2357                 if (r > 0)
2358                         result = "yes";
2359                 else if (challenge)
2360                         result = "challenge";
2361                 else
2362                         result = "no";
2363         }
2364
2365         return sd_bus_reply_method_return(message, "s", result);
2366 }
2367
2368 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2369         Manager *m = userdata;
2370
2371         return method_can_shutdown_or_sleep(
2372                         m, message,
2373                         INHIBIT_SHUTDOWN,
2374                         "org.freedesktop.login1.power-off",
2375                         "org.freedesktop.login1.power-off-multiple-sessions",
2376                         "org.freedesktop.login1.power-off-ignore-inhibit",
2377                         NULL,
2378                         error);
2379 }
2380
2381 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2382         Manager *m = userdata;
2383
2384         return method_can_shutdown_or_sleep(
2385                         m, message,
2386                         INHIBIT_SHUTDOWN,
2387                         "org.freedesktop.login1.reboot",
2388                         "org.freedesktop.login1.reboot-multiple-sessions",
2389                         "org.freedesktop.login1.reboot-ignore-inhibit",
2390                         NULL,
2391                         error);
2392 }
2393
2394 static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2395         Manager *m = userdata;
2396
2397         return method_can_shutdown_or_sleep(
2398                         m, message,
2399                         INHIBIT_SHUTDOWN,
2400                         "org.freedesktop.login1.halt",
2401                         "org.freedesktop.login1.halt-multiple-sessions",
2402                         "org.freedesktop.login1.halt-ignore-inhibit",
2403                         NULL,
2404                         error);
2405 }
2406
2407 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2408         Manager *m = userdata;
2409
2410         return method_can_shutdown_or_sleep(
2411                         m, message,
2412                         INHIBIT_SLEEP,
2413                         "org.freedesktop.login1.suspend",
2414                         "org.freedesktop.login1.suspend-multiple-sessions",
2415                         "org.freedesktop.login1.suspend-ignore-inhibit",
2416                         "suspend",
2417                         error);
2418 }
2419
2420 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2421         Manager *m = userdata;
2422
2423         return method_can_shutdown_or_sleep(
2424                         m, message,
2425                         INHIBIT_SLEEP,
2426                         "org.freedesktop.login1.hibernate",
2427                         "org.freedesktop.login1.hibernate-multiple-sessions",
2428                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2429                         "hibernate",
2430                         error);
2431 }
2432
2433 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2434         Manager *m = userdata;
2435
2436         return method_can_shutdown_or_sleep(
2437                         m, message,
2438                         INHIBIT_SLEEP,
2439                         "org.freedesktop.login1.hibernate",
2440                         "org.freedesktop.login1.hibernate-multiple-sessions",
2441                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2442                         "hybrid-sleep",
2443                         error);
2444 }
2445
2446 static int property_get_reboot_to_firmware_setup(
2447                 sd_bus *bus,
2448                 const char *path,
2449                 const char *interface,
2450                 const char *property,
2451                 sd_bus_message *reply,
2452                 void *userdata,
2453                 sd_bus_error *error) {
2454 #if 0 /// elogind does not support EFI
2455         int r;
2456
2457         assert(bus);
2458         assert(reply);
2459         assert(userdata);
2460
2461         r = efi_get_reboot_to_firmware();
2462         if (r < 0 && r != -EOPNOTSUPP)
2463                 log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
2464
2465         return sd_bus_message_append(reply, "b", r > 0);
2466 #else
2467         return sd_bus_message_append(reply, "b", false);
2468 #endif // 0
2469 }
2470
2471 static int method_set_reboot_to_firmware_setup(
2472                 sd_bus_message *message,
2473                 void *userdata,
2474                 sd_bus_error *error) {
2475
2476         int b, r;
2477         Manager *m = userdata;
2478
2479         assert(message);
2480         assert(m);
2481
2482         r = sd_bus_message_read(message, "b", &b);
2483         if (r < 0)
2484                 return r;
2485
2486         r = bus_verify_polkit_async(message,
2487                                     CAP_SYS_ADMIN,
2488                                     "org.freedesktop.login1.set-reboot-to-firmware-setup",
2489                                     NULL,
2490                                     false,
2491                                     UID_INVALID,
2492                                     &m->polkit_registry,
2493                                     error);
2494         if (r < 0)
2495                 return r;
2496         if (r == 0)
2497                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2498
2499 #if 0 /// elogind does not support EFI
2500         r = efi_set_reboot_to_firmware(b);
2501         if (r < 0)
2502                 return r;
2503 #endif // 0
2504
2505         return sd_bus_reply_method_return(message, NULL);
2506 }
2507
2508 static int method_can_reboot_to_firmware_setup(
2509                 sd_bus_message *message,
2510                 void *userdata,
2511                 sd_bus_error *error) {
2512
2513 #if 0 /// elogind does not support EFI
2514         int r;
2515         bool challenge;
2516         const char *result;
2517         Manager *m = userdata;
2518
2519         assert(message);
2520         assert(m);
2521
2522         r = efi_reboot_to_firmware_supported();
2523         if (r < 0) {
2524                 if (r != -EOPNOTSUPP)
2525                         log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
2526
2527                 return sd_bus_reply_method_return(message, "s", "na");
2528         }
2529
2530         r = bus_test_polkit(message,
2531                             CAP_SYS_ADMIN,
2532                             "org.freedesktop.login1.set-reboot-to-firmware-setup",
2533                             NULL,
2534                             UID_INVALID,
2535                             &challenge,
2536                             error);
2537         if (r < 0)
2538                 return r;
2539
2540         if (r > 0)
2541                 result = "yes";
2542         else if (challenge)
2543                 result = "challenge";
2544         else
2545                 result = "no";
2546
2547         return sd_bus_reply_method_return(message, "s", result);
2548 #else
2549         return sd_bus_reply_method_return(message, "s", "no");
2550 #endif // 0
2551 }
2552
2553 static int method_set_wall_message(
2554                 sd_bus_message *message,
2555                 void *userdata,
2556                 sd_bus_error *error) {
2557
2558         int r;
2559         Manager *m = userdata;
2560         char *wall_message;
2561         int enable_wall_messages;
2562
2563         assert(message);
2564         assert(m);
2565
2566         r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2567         if (r < 0)
2568                 return r;
2569
2570 #if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
2571         r = bus_verify_polkit_async(message,
2572                                     CAP_SYS_ADMIN,
2573                                     "org.freedesktop.login1.set-wall-message",
2574                                     NULL,
2575                                     false,
2576                                     UID_INVALID,
2577                                     &m->polkit_registry,
2578                                     error);
2579         if (r < 0)
2580                 return r;
2581         if (r == 0)
2582                 return 1; /* Will call us back */
2583 #endif // 0
2584
2585         r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2586         if (r < 0)
2587                 return log_oom();
2588
2589         m->enable_wall_messages = enable_wall_messages;
2590
2591         return sd_bus_reply_method_return(message, NULL);
2592 }
2593
2594 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2595         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2596         const char *who, *why, *what, *mode;
2597         _cleanup_free_ char *id = NULL;
2598         _cleanup_close_ int fifo_fd = -1;
2599         Manager *m = userdata;
2600         Inhibitor *i = NULL;
2601         InhibitMode mm;
2602         InhibitWhat w;
2603         pid_t pid;
2604         uid_t uid;
2605         int r;
2606
2607         assert(message);
2608         assert(m);
2609
2610         r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2611         if (r < 0)
2612                 return r;
2613
2614         w = inhibit_what_from_string(what);
2615         if (w <= 0)
2616                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2617
2618         mm = inhibit_mode_from_string(mode);
2619         if (mm < 0)
2620                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2621
2622         /* Delay is only supported for shutdown/sleep */
2623         if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2624                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2625
2626         /* Don't allow taking delay locks while we are already
2627          * executing the operation. We shouldn't create the impression
2628          * that the lock was successful if the machine is about to go
2629          * down/suspend any moment. */
2630         if (m->action_what & w)
2631                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2632
2633         r = bus_verify_polkit_async(
2634                         message,
2635                         CAP_SYS_BOOT,
2636                         w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2637                         w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
2638                         w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
2639                         w == INHIBIT_HANDLE_POWER_KEY     ? "org.freedesktop.login1.inhibit-handle-power-key" :
2640                         w == INHIBIT_HANDLE_SUSPEND_KEY   ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2641                         w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2642                                                             "org.freedesktop.login1.inhibit-handle-lid-switch",
2643                         NULL,
2644                         false,
2645                         UID_INVALID,
2646                         &m->polkit_registry,
2647                         error);
2648         if (r < 0)
2649                 return r;
2650         if (r == 0)
2651                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2652
2653         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2654         if (r < 0)
2655                 return r;
2656
2657         r = sd_bus_creds_get_euid(creds, &uid);
2658         if (r < 0)
2659                 return r;
2660
2661         r = sd_bus_creds_get_pid(creds, &pid);
2662         if (r < 0)
2663                 return r;
2664
2665         if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2666                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2667
2668         do {
2669                 id = mfree(id);
2670
2671                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2672                         return -ENOMEM;
2673
2674         } while (hashmap_get(m->inhibitors, id));
2675
2676         r = manager_add_inhibitor(m, id, &i);
2677         if (r < 0)
2678                 return r;
2679
2680         i->what = w;
2681         i->mode = mm;
2682         i->pid = pid;
2683         i->uid = uid;
2684         i->why = strdup(why);
2685         i->who = strdup(who);
2686
2687         if (!i->why || !i->who) {
2688                 r = -ENOMEM;
2689                 goto fail;
2690         }
2691
2692         fifo_fd = inhibitor_create_fifo(i);
2693         if (fifo_fd < 0) {
2694                 r = fifo_fd;
2695                 goto fail;
2696         }
2697
2698         inhibitor_start(i);
2699
2700         return sd_bus_reply_method_return(message, "h", fifo_fd);
2701
2702 fail:
2703         if (i)
2704                 inhibitor_free(i);
2705
2706         return r;
2707 }
2708
2709 const sd_bus_vtable manager_vtable[] = {
2710         SD_BUS_VTABLE_START(0),
2711
2712         SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2713         SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2714
2715 #if 0 /// UNNEEDED by elogind
2716         SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2717 #endif // 0
2718         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2719         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2720         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2721         SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2722         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2723         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2724         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2725         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2726         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2727         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2728         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2729         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2730         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2731         SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2732         SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2733         SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2734         SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2735         SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2736         SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2737         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2738         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2739         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2740         SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2741         SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2742         SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2743         SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2744         SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2745         SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2746         SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2747
2748         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2749         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2750         SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2751         SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2752         SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2753         SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2754         SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2755         SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2756         SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2757         SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2758         SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2759         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2760         SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2761         SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2762         SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2763         SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2764         SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2765         SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2766         SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2767         SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2768         SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2769         SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2770         SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2771         SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2772         SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2773         SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2774         SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2775         SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2776         SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2777         SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2778         SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2779         SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2780         SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2781         SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2782         SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2783         SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2784         SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2785         SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2786         SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2787         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2788         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2789         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2790         SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2791
2792         SD_BUS_SIGNAL("SessionNew", "so", 0),
2793         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2794         SD_BUS_SIGNAL("UserNew", "uo", 0),
2795         SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2796         SD_BUS_SIGNAL("SeatNew", "so", 0),
2797         SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2798         SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2799         SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2800
2801         SD_BUS_VTABLE_END
2802 };
2803
2804 #if 0 /// UNNEEDED by elogind
2805 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2806         int r = 0;
2807
2808         assert(s);
2809         assert(unit);
2810
2811         if (!s->started)
2812                 return r;
2813
2814         if (streq(result, "done"))
2815                 r = session_send_create_reply(s, NULL);
2816         else {
2817                 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2818
2819                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2820                 r = session_send_create_reply(s, &e);
2821         }
2822
2823         return r;
2824 }
2825
2826 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2827         const char *path, *result, *unit;
2828         Manager *m = userdata;
2829         Session *session;
2830         uint32_t id;
2831         User *user;
2832         int r;
2833
2834         assert(message);
2835         assert(m);
2836
2837         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2838         if (r < 0) {
2839                 bus_log_parse_error(r);
2840                 return 0;
2841         }
2842
2843         if (m->action_job && streq(m->action_job, path)) {
2844                 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2845
2846                 /* Tell people that they now may take a lock again */
2847                 (void) send_prepare_for(m, m->action_what, false);
2848
2849                 m->action_job = mfree(m->action_job);
2850                 m->action_unit = NULL;
2851                 m->action_what = 0;
2852                 return 0;
2853         }
2854
2855         session = hashmap_get(m->session_units, unit);
2856         if (session && streq_ptr(path, session->scope_job)) {
2857                 session->scope_job = mfree(session->scope_job);
2858                 session_jobs_reply(session, unit, result);
2859
2860                 session_save(session);
2861                 user_save(session->user);
2862                 session_add_to_gc_queue(session);
2863         }
2864
2865         user = hashmap_get(m->user_units, unit);
2866         if (user &&
2867             (streq_ptr(path, user->service_job) ||
2868              streq_ptr(path, user->slice_job))) {
2869
2870                 if (streq_ptr(path, user->service_job))
2871                         user->service_job = mfree(user->service_job);
2872
2873                 if (streq_ptr(path, user->slice_job))
2874                         user->slice_job = mfree(user->slice_job);
2875
2876                 LIST_FOREACH(sessions_by_user, session, user->sessions)
2877                         session_jobs_reply(session, unit, result);
2878
2879                 user_save(user);
2880                 user_add_to_gc_queue(user);
2881         }
2882
2883         return 0;
2884 }
2885
2886 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2887         const char *path, *unit;
2888         Manager *m = userdata;
2889         Session *session;
2890         User *user;
2891         int r;
2892
2893         assert(message);
2894         assert(m);
2895
2896         r = sd_bus_message_read(message, "so", &unit, &path);
2897         if (r < 0) {
2898                 bus_log_parse_error(r);
2899                 return 0;
2900         }
2901
2902         session = hashmap_get(m->session_units, unit);
2903         if (session)
2904                 session_add_to_gc_queue(session);
2905
2906         user = hashmap_get(m->user_units, unit);
2907         if (user)
2908                 user_add_to_gc_queue(user);
2909
2910         return 0;
2911 }
2912
2913 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2914         _cleanup_free_ char *unit = NULL;
2915         Manager *m = userdata;
2916         const char *path;
2917         Session *session;
2918         User *user;
2919         int r;
2920
2921         assert(message);
2922         assert(m);
2923
2924         path = sd_bus_message_get_path(message);
2925         if (!path)
2926                 return 0;
2927
2928         r = unit_name_from_dbus_path(path, &unit);
2929         if (r == -EINVAL) /* not a unit */
2930                 return 0;
2931         if (r < 0) {
2932                 log_oom();
2933                 return 0;
2934         }
2935
2936         session = hashmap_get(m->session_units, unit);
2937         if (session)
2938                 session_add_to_gc_queue(session);
2939
2940         user = hashmap_get(m->user_units, unit);
2941         if (user)
2942                 user_add_to_gc_queue(user);
2943
2944         return 0;
2945 }
2946
2947 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2948         Manager *m = userdata;
2949         Session *session;
2950         Iterator i;
2951         int b, r;
2952
2953         assert(message);
2954         assert(m);
2955
2956         r = sd_bus_message_read(message, "b", &b);
2957         if (r < 0) {
2958                 bus_log_parse_error(r);
2959                 return 0;
2960         }
2961
2962         if (b)
2963                 return 0;
2964
2965         /* systemd finished reloading, let's recheck all our sessions */
2966         log_debug("System manager has been reloaded, rechecking sessions...");
2967
2968         HASHMAP_FOREACH(session, m->sessions, i)
2969                 session_add_to_gc_queue(session);
2970
2971         return 0;
2972 }
2973 #endif // 0
2974
2975 int manager_send_changed(Manager *manager, const char *property, ...) {
2976         char **l;
2977
2978         assert(manager);
2979
2980         l = strv_from_stdarg_alloca(property);
2981
2982         return sd_bus_emit_properties_changed_strv(
2983                         manager->bus,
2984                         "/org/freedesktop/login1",
2985                         "org.freedesktop.login1.Manager",
2986                         l);
2987 }
2988
2989 #if 0 /// UNNEEDED by elogind
2990 static int strdup_job(sd_bus_message *reply, char **job) {
2991         const char *j;
2992         char *copy;
2993         int r;
2994
2995         r = sd_bus_message_read(reply, "o", &j);
2996         if (r < 0)
2997                 return r;
2998
2999         copy = strdup(j);
3000         if (!copy)
3001                 return -ENOMEM;
3002
3003         *job = copy;
3004         return 1;
3005 }
3006
3007 int manager_start_slice(
3008                 Manager *manager,
3009                 const char *slice,
3010                 const char *description,
3011                 const char *after,
3012                 const char *after2,
3013                 uint64_t tasks_max,
3014                 sd_bus_error *error,
3015                 char **job) {
3016
3017         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3018         int r;
3019
3020         assert(manager);
3021         assert(slice);
3022         assert(job);
3023
3024         r = sd_bus_message_new_method_call(
3025                         manager->bus,
3026                         &m,
3027                         "org.freedesktop.systemd1",
3028                         "/org/freedesktop/systemd1",
3029                         "org.freedesktop.systemd1.Manager",
3030                         "StartTransientUnit");
3031         if (r < 0)
3032                 return r;
3033
3034         r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
3035         if (r < 0)
3036                 return r;
3037
3038         r = sd_bus_message_open_container(m, 'a', "(sv)");
3039         if (r < 0)
3040                 return r;
3041
3042         if (!isempty(description)) {
3043                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3044                 if (r < 0)
3045                         return r;
3046         }
3047
3048         if (!isempty(after)) {
3049                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3050                 if (r < 0)
3051                         return r;
3052         }
3053
3054         if (!isempty(after2)) {
3055                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3056                 if (r < 0)
3057                         return r;
3058         }
3059
3060         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3061         if (r < 0)
3062                 return r;
3063
3064         r = sd_bus_message_close_container(m);
3065         if (r < 0)
3066                 return r;
3067
3068         r = sd_bus_message_append(m, "a(sa(sv))", 0);
3069         if (r < 0)
3070                 return r;
3071
3072         r = sd_bus_call(manager->bus, m, 0, error, &reply);
3073         if (r < 0)
3074                 return r;
3075
3076         return strdup_job(reply, job);
3077 }
3078
3079 int manager_start_scope(
3080                 Manager *manager,
3081                 const char *scope,
3082                 pid_t pid,
3083                 const char *slice,
3084                 const char *description,
3085                 const char *after,
3086                 const char *after2,
3087                 uint64_t tasks_max,
3088                 sd_bus_error *error,
3089                 char **job) {
3090
3091         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3092         int r;
3093
3094         assert(manager);
3095         assert(scope);
3096         assert(pid > 1);
3097         assert(job);
3098
3099         r = sd_bus_message_new_method_call(
3100                         manager->bus,
3101                         &m,
3102                         "org.freedesktop.systemd1",
3103                         "/org/freedesktop/systemd1",
3104                         "org.freedesktop.systemd1.Manager",
3105                         "StartTransientUnit");
3106         if (r < 0)
3107                 return r;
3108
3109         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3110         if (r < 0)
3111                 return r;
3112
3113         r = sd_bus_message_open_container(m, 'a', "(sv)");
3114         if (r < 0)
3115                 return r;
3116
3117         if (!isempty(slice)) {
3118                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3119                 if (r < 0)
3120                         return r;
3121         }
3122
3123         if (!isempty(description)) {
3124                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3125                 if (r < 0)
3126                         return r;
3127         }
3128
3129         if (!isempty(after)) {
3130                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3131                 if (r < 0)
3132                         return r;
3133         }
3134
3135         if (!isempty(after2)) {
3136                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3137                 if (r < 0)
3138                         return r;
3139         }
3140
3141         /* cgroup empty notification is not available in containers
3142          * currently. To make this less problematic, let's shorten the
3143          * stop timeout for sessions, so that we don't wait
3144          * forever. */
3145
3146         /* Make sure that the session shells are terminated with
3147          * SIGHUP since bash and friends tend to ignore SIGTERM */
3148         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3149         if (r < 0)
3150                 return r;
3151
3152         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3153         if (r < 0)
3154                 return r;
3155
3156         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3157         if (r < 0)
3158                 return r;
3159
3160         r = sd_bus_message_close_container(m);
3161         if (r < 0)
3162                 return r;
3163
3164         r = sd_bus_message_append(m, "a(sa(sv))", 0);
3165         if (r < 0)
3166                 return r;
3167
3168         r = sd_bus_call(manager->bus, m, 0, error, &reply);
3169         if (r < 0)
3170                 return r;
3171
3172         return strdup_job(reply, job);
3173 }
3174
3175 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3176         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3177         int r;
3178
3179         assert(manager);
3180         assert(unit);
3181         assert(job);
3182
3183         r = sd_bus_call_method(
3184                         manager->bus,
3185                         "org.freedesktop.systemd1",
3186                         "/org/freedesktop/systemd1",
3187                         "org.freedesktop.systemd1.Manager",
3188                         "StartUnit",
3189                         error,
3190                         &reply,
3191                         "ss", unit, "replace");
3192         if (r < 0)
3193                 return r;
3194
3195         return strdup_job(reply, job);
3196 }
3197
3198 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3199         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3200         int r;
3201
3202         assert(manager);
3203         assert(unit);
3204         assert(job);
3205
3206         r = sd_bus_call_method(
3207                         manager->bus,
3208                         "org.freedesktop.systemd1",
3209                         "/org/freedesktop/systemd1",
3210                         "org.freedesktop.systemd1.Manager",
3211                         "StopUnit",
3212                         error,
3213                         &reply,
3214                         "ss", unit, "fail");
3215         if (r < 0) {
3216                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3217                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3218
3219                         *job = NULL;
3220                         sd_bus_error_free(error);
3221                         return 0;
3222                 }
3223
3224                 return r;
3225         }
3226
3227         return strdup_job(reply, job);
3228 }
3229
3230 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3231         _cleanup_free_ char *path = NULL;
3232         int r;
3233
3234         assert(manager);
3235         assert(scope);
3236
3237         path = unit_dbus_path_from_name(scope);
3238         if (!path)
3239                 return -ENOMEM;
3240
3241         r = sd_bus_call_method(
3242                         manager->bus,
3243                         "org.freedesktop.systemd1",
3244                         path,
3245                         "org.freedesktop.systemd1.Scope",
3246                         "Abandon",
3247                         error,
3248                         NULL,
3249                         NULL);
3250         if (r < 0) {
3251                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3252                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3253                     sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3254                         sd_bus_error_free(error);
3255                         return 0;
3256                 }
3257
3258                 return r;
3259         }
3260
3261         return 1;
3262 }
3263
3264 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3265         assert(manager);
3266         assert(unit);
3267
3268         return sd_bus_call_method(
3269                         manager->bus,
3270                         "org.freedesktop.systemd1",
3271                         "/org/freedesktop/systemd1",
3272                         "org.freedesktop.systemd1.Manager",
3273                         "KillUnit",
3274                         error,
3275                         NULL,
3276                         "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3277 }
3278
3279 int manager_unit_is_active(Manager *manager, const char *unit) {
3280         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3281         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3282         _cleanup_free_ char *path = NULL;
3283         const char *state;
3284         int r;
3285
3286         assert(manager);
3287         assert(unit);
3288
3289         path = unit_dbus_path_from_name(unit);
3290         if (!path)
3291                 return -ENOMEM;
3292
3293         r = sd_bus_get_property(
3294                         manager->bus,
3295                         "org.freedesktop.systemd1",
3296                         path,
3297                         "org.freedesktop.systemd1.Unit",
3298                         "ActiveState",
3299                         &error,
3300                         &reply,
3301                         "s");
3302         if (r < 0) {
3303                 /* systemd might have droppped off momentarily, let's
3304                  * not make this an error */
3305                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3306                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3307                         return true;
3308
3309                 /* If the unit is already unloaded then it's not
3310                  * active */
3311                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3312                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3313                         return false;
3314
3315                 return r;
3316         }
3317
3318         r = sd_bus_message_read(reply, "s", &state);
3319         if (r < 0)
3320                 return -EINVAL;
3321
3322         return !streq(state, "inactive") && !streq(state, "failed");
3323 }
3324
3325 int manager_job_is_active(Manager *manager, const char *path) {
3326         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3327         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3328         int r;
3329
3330         assert(manager);
3331         assert(path);
3332
3333         r = sd_bus_get_property(
3334                         manager->bus,
3335                         "org.freedesktop.systemd1",
3336                         path,
3337                         "org.freedesktop.systemd1.Job",
3338                         "State",
3339                         &error,
3340                         &reply,
3341                         "s");
3342         if (r < 0) {
3343                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3344                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3345                         return true;
3346
3347                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3348                         return false;
3349
3350                 return r;
3351         }
3352
3353         /* We don't actually care about the state really. The fact
3354          * that we could read the job state is enough for us */
3355
3356         return true;
3357 }
3358 #endif // 0