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