chiark / gitweb /
basic/mkdir: convert bool flag to enum
[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, 0);
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 #endif // 0
1639
1640 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1641
1642         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1643         Inhibitor *offending = NULL;
1644         int r;
1645
1646         assert(manager);
1647
1648 #if 0 /// elogind has no action_job, but a pending_action
1649         if (manager->action_what == 0 || manager->action_job)
1650 #else
1651         if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
1652 #endif // 0
1653                 return 0;
1654
1655         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1656                 _cleanup_free_ char *comm = NULL, *u = NULL;
1657
1658                 if (!timeout)
1659                         return 0;
1660
1661                 (void) get_process_comm(offending->pid, &comm);
1662                 u = uid_to_name(offending->uid);
1663
1664                 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1665                            offending->uid, strna(u),
1666                            offending->pid, strna(comm));
1667         }
1668
1669         /* Actually do the operation */
1670 #if 0 /// elogind has no action_unit but a pending_action
1671         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1672 #else
1673         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1674 #endif // 0
1675         if (r < 0) {
1676                 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1677                             bus_error_message(&error, r));
1678
1679
1680 #if 0 /// elogind has no action_unit but a pending_action
1681                 manager->action_unit = NULL;
1682                 manager->action_what = 0;
1683                 return r;
1684 #else
1685                 manager->pending_action = HANDLE_IGNORE;
1686                 manager->action_what    = 0;
1687                 /* It is not a critical error for elogind if suspending fails */
1688 #endif // 0
1689         }
1690
1691         return 1;
1692 }
1693
1694 static int manager_inhibit_timeout_handler(
1695                         sd_event_source *s,
1696                         uint64_t usec,
1697                         void *userdata) {
1698
1699         Manager *manager = userdata;
1700         int r;
1701
1702         assert(manager);
1703         assert(manager->inhibit_timeout_source == s);
1704
1705         r = manager_dispatch_delayed(manager, true);
1706         return (r < 0) ? r : 0;
1707 }
1708
1709 #if 0 /// elogind does not have unit_name but action
1710 static int delay_shutdown_or_sleep(
1711                 Manager *m,
1712                 InhibitWhat w,
1713                 const char *unit_name) {
1714
1715 #else
1716 int delay_shutdown_or_sleep(
1717                 Manager *m,
1718                 InhibitWhat w,
1719                 HandleAction action) {
1720 #endif // 0
1721         int r;
1722         usec_t timeout_val;
1723
1724         assert(m);
1725         assert(w >= 0);
1726         assert(w < _INHIBIT_WHAT_MAX);
1727 #if 0 /// UNNEEDED by elogind
1728         assert(unit_name);
1729 #endif // 0
1730
1731         timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1732
1733         if (m->inhibit_timeout_source) {
1734                 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1735                 if (r < 0)
1736                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1737
1738                 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1739                 if (r < 0)
1740                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1741         } else {
1742                 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1743                                       timeout_val, 0, manager_inhibit_timeout_handler, m);
1744                 if (r < 0)
1745                         return r;
1746         }
1747
1748 #if 0 /// elogind does not have unit_name but pendig_action
1749         m->action_unit = unit_name;
1750 #else
1751         m->pending_action = action;
1752 #endif // 0
1753         m->action_what = w;
1754
1755         return 0;
1756 }
1757
1758 int bus_manager_shutdown_or_sleep_now_or_later(
1759                 Manager *m,
1760 #if 0 /// elogind has HandleAction instead of const char* unit_name
1761                 const char *unit_name,
1762
1763 #else
1764                 HandleAction unit_name,
1765 #endif // 0
1766                 InhibitWhat w,
1767                 sd_bus_error *error) {
1768         bool delayed;
1769         int r;
1770
1771         assert(m);
1772 #if 0 /// for elogind only w has to be checked.
1773         assert(unit_name);
1774         assert(w > 0);
1775         assert(w <= _INHIBIT_WHAT_MAX);
1776         assert(!m->action_job);
1777 #else
1778         assert(w > 0);
1779         assert(w <= _INHIBIT_WHAT_MAX);
1780 #endif // 0
1781
1782         /* Tell everybody to prepare for shutdown/sleep */
1783         (void) send_prepare_for(m, w, true);
1784
1785         delayed =
1786                 m->inhibit_delay_max > 0 &&
1787                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1788
1789         log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
1790                           handle_action_to_string(unit_name),
1791                           delayed ? "" : "NOT ");
1792         if (delayed)
1793                 /* Shutdown is delayed, keep in mind what we
1794                  * want to do, and start a timeout */
1795                 r = delay_shutdown_or_sleep(m, w, unit_name);
1796         else
1797                 /* Shutdown is not delayed, execute it
1798                  * immediately */
1799                 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1800
1801         return r;
1802 }
1803
1804 static int verify_shutdown_creds(
1805                 Manager *m,
1806                 sd_bus_message *message,
1807                 InhibitWhat w,
1808                 bool interactive,
1809                 const char *action,
1810                 const char *action_multiple_sessions,
1811                 const char *action_ignore_inhibit,
1812                 sd_bus_error *error) {
1813
1814         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1815         bool multiple_sessions, blocked;
1816         uid_t uid;
1817         int r;
1818
1819         assert(m);
1820         assert(message);
1821         assert(w >= 0);
1822         assert(w <= _INHIBIT_WHAT_MAX);
1823
1824         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1825         if (r < 0)
1826                 return r;
1827
1828         r = sd_bus_creds_get_euid(creds, &uid);
1829         if (r < 0)
1830                 return r;
1831
1832         r = have_multiple_sessions(m, uid);
1833         if (r < 0)
1834                 return r;
1835
1836         multiple_sessions = r > 0;
1837         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1838
1839         if (multiple_sessions && action_multiple_sessions) {
1840                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1841                 if (r < 0)
1842                         return r;
1843                 if (r == 0)
1844                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1845         }
1846
1847         if (blocked && action_ignore_inhibit) {
1848                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1849                 if (r < 0)
1850                         return r;
1851                 if (r == 0)
1852                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1853         }
1854
1855         if (!multiple_sessions && !blocked && action) {
1856                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1857                 if (r < 0)
1858                         return r;
1859                 if (r == 0)
1860                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1861         }
1862
1863         return 0;
1864 }
1865
1866 static int method_do_shutdown_or_sleep(
1867                 Manager *m,
1868                 sd_bus_message *message,
1869 #if 0 /// elogind has HandleAction instead of const char* unit_name
1870                 const char *unit_name,
1871 #else
1872                 HandleAction unit_name,
1873 #endif // 0
1874                 InhibitWhat w,
1875                 const char *action,
1876                 const char *action_multiple_sessions,
1877                 const char *action_ignore_inhibit,
1878                 const char *sleep_verb,
1879                 sd_bus_error *error) {
1880
1881         int interactive, r;
1882
1883         assert(m);
1884         assert(message);
1885 #if 0 /// elogind does not need this to be checked
1886         assert(unit_name);
1887 #endif // 0
1888         assert(w >= 0);
1889         assert(w <= _INHIBIT_WHAT_MAX);
1890
1891         r = sd_bus_message_read(message, "b", &interactive);
1892         if (r < 0)
1893                 return r;
1894
1895         log_debug_elogind("%s called with action '%s', sleep '%s' (%sinteractive)",
1896                           __FUNCTION__, action, sleep_verb,
1897                           interactive ? "" : "NOT ");
1898         /* Don't allow multiple jobs being executed at the same time */
1899         if (m->action_what)
1900                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1901
1902         if (sleep_verb) {
1903 #if 0 /// Within elogind the manager m must be provided, too
1904                 r = can_sleep(sleep_verb);
1905 #else
1906                 r = can_sleep(m, sleep_verb);
1907 #endif // 0
1908                 if (r < 0)
1909                         return r;
1910
1911                 if (r == 0)
1912                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1913         }
1914
1915 #if 0 /// Within elogind it does not make sense to verify shutdown creds when suspending
1916         r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1917                                   action_ignore_inhibit, error);
1918         if (r != 0)
1919                 return r;
1920 #else
1921         if (IN_SET(unit_name, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
1922                 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1923                                           action_ignore_inhibit, error);
1924                 log_debug_elogind("verify_shutdown_creds() returned %d", r);
1925                 if (r != 0)
1926                         return r;
1927         }
1928 #endif // 0
1929
1930         r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1931         if (r < 0)
1932                 return r;
1933
1934         return sd_bus_reply_method_return(message, NULL);
1935 }
1936
1937 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1938         Manager *m = userdata;
1939
1940         log_debug_elogind("%s called", __FUNCTION__);
1941         return method_do_shutdown_or_sleep(
1942                         m, message,
1943 #if 0 /// elogind uses HandleAction instead of const char* unti names
1944                         SPECIAL_POWEROFF_TARGET,
1945 #else
1946                         HANDLE_POWEROFF,
1947 #endif // 0
1948                         INHIBIT_SHUTDOWN,
1949                         "org.freedesktop.login1.power-off",
1950                         "org.freedesktop.login1.power-off-multiple-sessions",
1951                         "org.freedesktop.login1.power-off-ignore-inhibit",
1952                         NULL,
1953                         error);
1954 }
1955
1956 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1957         Manager *m = userdata;
1958
1959         log_debug_elogind("%s called", __FUNCTION__);
1960         return method_do_shutdown_or_sleep(
1961                         m, message,
1962 #if 0 /// elogind uses HandleAction instead of const char* unti names
1963                         SPECIAL_REBOOT_TARGET,
1964 #else
1965                         HANDLE_REBOOT,
1966 #endif // 0
1967                         INHIBIT_SHUTDOWN,
1968                         "org.freedesktop.login1.reboot",
1969                         "org.freedesktop.login1.reboot-multiple-sessions",
1970                         "org.freedesktop.login1.reboot-ignore-inhibit",
1971                         NULL,
1972                         error);
1973 }
1974
1975 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1976         Manager *m = userdata;
1977
1978         log_debug_elogind("%s called", __FUNCTION__);
1979         return method_do_shutdown_or_sleep(
1980                         m, message,
1981 #if 0 /// elogind uses HandleAction instead of const char* unti names
1982                         SPECIAL_HALT_TARGET,
1983 #else
1984                         HANDLE_HALT,
1985 #endif // 0
1986                         INHIBIT_SHUTDOWN,
1987                         "org.freedesktop.login1.halt",
1988                         "org.freedesktop.login1.halt-multiple-sessions",
1989                         "org.freedesktop.login1.halt-ignore-inhibit",
1990                         NULL,
1991                         error);
1992 }
1993
1994 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1995         Manager *m = userdata;
1996
1997         log_debug_elogind("%s called", __FUNCTION__);
1998         return method_do_shutdown_or_sleep(
1999                         m, message,
2000 #if 0 /// elogind uses HandleAction instead of const char* unti names
2001                         SPECIAL_SUSPEND_TARGET,
2002 #else
2003                         HANDLE_SUSPEND,
2004 #endif // 0
2005                         INHIBIT_SLEEP,
2006                         "org.freedesktop.login1.suspend",
2007                         "org.freedesktop.login1.suspend-multiple-sessions",
2008                         "org.freedesktop.login1.suspend-ignore-inhibit",
2009                         "suspend",
2010                         error);
2011 }
2012
2013 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2014         Manager *m = userdata;
2015
2016         log_debug_elogind("%s called", __FUNCTION__);
2017         return method_do_shutdown_or_sleep(
2018                         m, message,
2019 #if 0 /// elogind uses HandleAction instead of const char* unti names
2020                         SPECIAL_HIBERNATE_TARGET,
2021 #else
2022                         HANDLE_HIBERNATE,
2023 #endif // 0
2024                         INHIBIT_SLEEP,
2025                         "org.freedesktop.login1.hibernate",
2026                         "org.freedesktop.login1.hibernate-multiple-sessions",
2027                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2028                         "hibernate",
2029                         error);
2030 }
2031
2032 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2033         Manager *m = userdata;
2034
2035         log_debug_elogind("%s called", __FUNCTION__);
2036         return method_do_shutdown_or_sleep(
2037                         m, message,
2038 #if 0 /// elogind uses HandleAction instead of const char* unti names
2039                         SPECIAL_HYBRID_SLEEP_TARGET,
2040                         INHIBIT_SLEEP,
2041                         "org.freedesktop.login1.hibernate",
2042                         "org.freedesktop.login1.hibernate-multiple-sessions",
2043                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2044                         "hybrid-sleep",
2045                         error);
2046 }
2047
2048 static int method_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2049         Manager *m = userdata;
2050
2051         return method_do_shutdown_or_sleep(
2052                         m, message,
2053                         SPECIAL_SUSPEND_TO_HIBERNATE_TARGET,
2054 #else
2055                         HANDLE_HYBRID_SLEEP,
2056 #endif // 0
2057                         INHIBIT_SLEEP,
2058                         "org.freedesktop.login1.hibernate",
2059                         "org.freedesktop.login1.hibernate-multiple-sessions",
2060                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2061                         "hybrid-sleep",
2062                         error);
2063 }
2064
2065 static int nologin_timeout_handler(
2066                         sd_event_source *s,
2067                         uint64_t usec,
2068                         void *userdata) {
2069
2070         Manager *m = userdata;
2071
2072         log_info("Creating /run/nologin, blocking further logins...");
2073
2074         m->unlink_nologin =
2075                 create_shutdown_run_nologin_or_warn() >= 0;
2076
2077         return 0;
2078 }
2079
2080 static int update_schedule_file(Manager *m) {
2081         _cleanup_free_ char *temp_path = NULL;
2082         _cleanup_fclose_ FILE *f = NULL;
2083         int r;
2084
2085         assert(m);
2086
2087         r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, 0);
2088         if (r < 0)
2089                 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
2090
2091         r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
2092         if (r < 0)
2093                 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
2094
2095         (void) fchmod(fileno(f), 0644);
2096
2097         fprintf(f,
2098                 "USEC="USEC_FMT"\n"
2099                 "WARN_WALL=%i\n"
2100                 "MODE=%s\n",
2101                 m->scheduled_shutdown_timeout,
2102                 m->enable_wall_messages,
2103                 m->scheduled_shutdown_type);
2104
2105         if (!isempty(m->wall_message)) {
2106                 _cleanup_free_ char *t;
2107
2108                 t = cescape(m->wall_message);
2109                 if (!t) {
2110                         r = -ENOMEM;
2111                         goto fail;
2112                 }
2113
2114                 fprintf(f, "WALL_MESSAGE=%s\n", t);
2115         }
2116
2117         r = fflush_and_check(f);
2118         if (r < 0)
2119                 goto fail;
2120
2121         if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2122                 r = -errno;
2123                 goto fail;
2124         }
2125
2126         return 0;
2127
2128 fail:
2129         (void) unlink(temp_path);
2130         (void) unlink("/run/systemd/shutdown/scheduled");
2131
2132         return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2133 }
2134
2135 #if 0 /// elogind must access this from elogind-dbus.c
2136 static void reset_scheduled_shutdown(Manager *m) {
2137 #else
2138 void reset_scheduled_shutdown(Manager *m) {
2139 #endif // 0
2140         assert(m);
2141
2142         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2143         m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2144         m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2145
2146         m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2147         m->scheduled_shutdown_timeout = 0;
2148         m->shutdown_dry_run = false;
2149
2150         if (m->unlink_nologin) {
2151                 (void) unlink_or_warn("/run/nologin");
2152                 m->unlink_nologin = false;
2153         }
2154
2155         (void) unlink("/run/systemd/shutdown/scheduled");
2156 }
2157
2158 #if 0 /// elogind has its own variant in elogind-dbus.c
2159 static int manager_scheduled_shutdown_handler(
2160                         sd_event_source *s,
2161                         uint64_t usec,
2162                         void *userdata) {
2163
2164         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2165         Manager *m = userdata;
2166         const char *target;
2167         int r;
2168
2169         assert(m);
2170
2171         if (isempty(m->scheduled_shutdown_type))
2172                 return 0;
2173
2174         if (streq(m->scheduled_shutdown_type, "poweroff"))
2175                 target = SPECIAL_POWEROFF_TARGET;
2176         else if (streq(m->scheduled_shutdown_type, "reboot"))
2177                 target = SPECIAL_REBOOT_TARGET;
2178         else if (streq(m->scheduled_shutdown_type, "halt"))
2179                 target = SPECIAL_HALT_TARGET;
2180         else
2181                 assert_not_reached("unexpected shutdown type");
2182
2183         /* Don't allow multiple jobs being executed at the same time */
2184         if (m->action_what) {
2185                 r = -EALREADY;
2186                 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2187                 goto error;
2188         }
2189
2190         if (m->shutdown_dry_run) {
2191                 /* We do not process delay inhibitors here.  Otherwise, we
2192                  * would have to be considered "in progress" (like the check
2193                  * above) for some seconds after our admin has seen the final
2194                  * wall message. */
2195
2196                 bus_manager_log_shutdown(m, target);
2197                 log_info("Running in dry run, suppressing action.");
2198                 reset_scheduled_shutdown(m);
2199
2200                 return 0;
2201         }
2202
2203         r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2204         if (r < 0) {
2205                 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2206                 goto error;
2207         }
2208
2209         return 0;
2210
2211 error:
2212         reset_scheduled_shutdown(m);
2213         return r;
2214 }
2215 #endif // 0
2216
2217 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2218         Manager *m = userdata;
2219         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2220         const char *action_multiple_sessions = NULL;
2221         const char *action_ignore_inhibit = NULL;
2222         const char *action = NULL;
2223         uint64_t elapse;
2224         char *type;
2225         int r;
2226         bool dry_run = false;
2227
2228         assert(m);
2229         assert(message);
2230
2231         log_debug_elogind("%s called", __FUNCTION__);
2232         r = sd_bus_message_read(message, "st", &type, &elapse);
2233         if (r < 0)
2234                 return r;
2235
2236         if (startswith(type, "dry-")) {
2237                 type += 4;
2238                 dry_run = true;
2239         }
2240
2241         if (streq(type, "poweroff")) {
2242                 action = "org.freedesktop.login1.power-off";
2243                 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2244                 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2245         } else if (streq(type, "reboot")) {
2246                 action = "org.freedesktop.login1.reboot";
2247                 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2248                 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2249         } else if (streq(type, "halt")) {
2250                 action = "org.freedesktop.login1.halt";
2251                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2252                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2253         } else
2254                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2255
2256         r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2257                                   action, action_multiple_sessions, action_ignore_inhibit, error);
2258         if (r != 0)
2259                 return r;
2260
2261         if (m->scheduled_shutdown_timeout_source) {
2262                 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2263                 if (r < 0)
2264                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2265
2266                 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2267                 if (r < 0)
2268                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2269         } else {
2270                 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2271                                       CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2272                 if (r < 0)
2273                         return log_error_errno(r, "sd_event_add_time() failed: %m");
2274         }
2275
2276         r = free_and_strdup(&m->scheduled_shutdown_type, type);
2277         if (r < 0) {
2278                 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2279                 return log_oom();
2280         }
2281
2282         m->shutdown_dry_run = dry_run;
2283
2284         if (m->nologin_timeout_source) {
2285                 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2286                 if (r < 0)
2287                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2288
2289                 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2290                 if (r < 0)
2291                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2292         } else {
2293                 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2294                                       CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2295                 if (r < 0)
2296                         return log_error_errno(r, "sd_event_add_time() failed: %m");
2297         }
2298
2299         m->scheduled_shutdown_timeout = elapse;
2300
2301         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2302         if (r >= 0) {
2303                 const char *tty = NULL;
2304
2305                 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2306                 (void) sd_bus_creds_get_tty(creds, &tty);
2307
2308                 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2309                 if (r < 0) {
2310                         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2311                         return log_oom();
2312                 }
2313         }
2314
2315         r = manager_setup_wall_message_timer(m);
2316         if (r < 0)
2317                 return r;
2318
2319         r = update_schedule_file(m);
2320         if (r < 0)
2321                 return r;
2322
2323         return sd_bus_reply_method_return(message, NULL);
2324 }
2325
2326 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2327         Manager *m = userdata;
2328         bool cancelled;
2329 #if 1 /// elogind needs to construct the message to allow extra wall messages
2330         _cleanup_free_ char *l = NULL;
2331 #endif // 1
2332
2333         assert(m);
2334         assert(message);
2335
2336         log_debug_elogind("%s called", __FUNCTION__);
2337         cancelled = m->scheduled_shutdown_type != NULL;
2338         reset_scheduled_shutdown(m);
2339
2340         if (cancelled) {
2341                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2342                 const char *tty = NULL;
2343                 uid_t uid = 0;
2344                 int r;
2345
2346                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2347                 if (r >= 0) {
2348                         (void) sd_bus_creds_get_uid(creds, &uid);
2349                         (void) sd_bus_creds_get_tty(creds, &tty);
2350                 }
2351
2352 #if 0 /// elogind wants to allow extra cancellation messages
2353                 utmp_wall("The system shutdown has been cancelled",
2354                           uid_to_name(uid), tty, logind_wall_tty_filter, m);
2355 #else
2356                 r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
2357                              strempty(m->wall_message),
2358                              isempty(m->wall_message) ? "" : "\n");
2359                 if (r < 0) {
2360                         log_oom();
2361                         return 0;
2362                 }
2363
2364                 utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
2365 #endif // 0
2366         }
2367
2368         return sd_bus_reply_method_return(message, "b", cancelled);
2369 }
2370
2371 static int method_can_shutdown_or_sleep(
2372                 Manager *m,
2373                 sd_bus_message *message,
2374                 InhibitWhat w,
2375                 const char *action,
2376                 const char *action_multiple_sessions,
2377                 const char *action_ignore_inhibit,
2378                 const char *sleep_verb,
2379                 sd_bus_error *error) {
2380
2381         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2382         bool multiple_sessions, challenge, blocked;
2383         const char *result = NULL;
2384         uid_t uid;
2385         int r;
2386
2387         assert(m);
2388         assert(message);
2389         assert(w >= 0);
2390         assert(w <= _INHIBIT_WHAT_MAX);
2391         assert(action);
2392         assert(action_multiple_sessions);
2393         assert(action_ignore_inhibit);
2394
2395         if (sleep_verb) {
2396 #if 0 /// elogind needs to have the manager being passed
2397                 r = can_sleep(sleep_verb);
2398 #else
2399                 r = can_sleep(m, sleep_verb);
2400 #endif // 0
2401                 if (r < 0)
2402                         return r;
2403                 if (r == 0)
2404                         return sd_bus_reply_method_return(message, "s", "na");
2405         }
2406
2407         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2408         if (r < 0)
2409                 return r;
2410
2411         r = sd_bus_creds_get_euid(creds, &uid);
2412         if (r < 0)
2413                 return r;
2414
2415         r = have_multiple_sessions(m, uid);
2416         if (r < 0)
2417                 return r;
2418
2419         multiple_sessions = r > 0;
2420         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2421
2422         if (multiple_sessions) {
2423                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2424                 if (r < 0)
2425                         return r;
2426
2427                 if (r > 0)
2428                         result = "yes";
2429                 else if (challenge)
2430                         result = "challenge";
2431                 else
2432                         result = "no";
2433         }
2434
2435         if (blocked) {
2436                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2437                 if (r < 0)
2438                         return r;
2439
2440                 if (r > 0 && !result)
2441                         result = "yes";
2442                 else if (challenge && (!result || streq(result, "yes")))
2443                         result = "challenge";
2444                 else
2445                         result = "no";
2446         }
2447
2448         if (!multiple_sessions && !blocked) {
2449                 /* If neither inhibit nor multiple sessions
2450                  * apply then just check the normal policy */
2451
2452                 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2453                 if (r < 0)
2454                         return r;
2455
2456                 if (r > 0)
2457                         result = "yes";
2458                 else if (challenge)
2459                         result = "challenge";
2460                 else
2461                         result = "no";
2462         }
2463
2464         return sd_bus_reply_method_return(message, "s", result);
2465 }
2466
2467 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2468         Manager *m = userdata;
2469
2470         return method_can_shutdown_or_sleep(
2471                         m, message,
2472                         INHIBIT_SHUTDOWN,
2473                         "org.freedesktop.login1.power-off",
2474                         "org.freedesktop.login1.power-off-multiple-sessions",
2475                         "org.freedesktop.login1.power-off-ignore-inhibit",
2476                         NULL,
2477                         error);
2478 }
2479
2480 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2481         Manager *m = userdata;
2482
2483         return method_can_shutdown_or_sleep(
2484                         m, message,
2485                         INHIBIT_SHUTDOWN,
2486                         "org.freedesktop.login1.reboot",
2487                         "org.freedesktop.login1.reboot-multiple-sessions",
2488                         "org.freedesktop.login1.reboot-ignore-inhibit",
2489                         NULL,
2490                         error);
2491 }
2492
2493 static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2494         Manager *m = userdata;
2495
2496         return method_can_shutdown_or_sleep(
2497                         m, message,
2498                         INHIBIT_SHUTDOWN,
2499                         "org.freedesktop.login1.halt",
2500                         "org.freedesktop.login1.halt-multiple-sessions",
2501                         "org.freedesktop.login1.halt-ignore-inhibit",
2502                         NULL,
2503                         error);
2504 }
2505
2506 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2507         Manager *m = userdata;
2508
2509         return method_can_shutdown_or_sleep(
2510                         m, message,
2511                         INHIBIT_SLEEP,
2512                         "org.freedesktop.login1.suspend",
2513                         "org.freedesktop.login1.suspend-multiple-sessions",
2514                         "org.freedesktop.login1.suspend-ignore-inhibit",
2515                         "suspend",
2516                         error);
2517 }
2518
2519 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2520         Manager *m = userdata;
2521
2522         return method_can_shutdown_or_sleep(
2523                         m, message,
2524                         INHIBIT_SLEEP,
2525                         "org.freedesktop.login1.hibernate",
2526                         "org.freedesktop.login1.hibernate-multiple-sessions",
2527                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2528                         "hibernate",
2529                         error);
2530 }
2531
2532 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2533         Manager *m = userdata;
2534
2535         return method_can_shutdown_or_sleep(
2536                         m, message,
2537                         INHIBIT_SLEEP,
2538                         "org.freedesktop.login1.hibernate",
2539                         "org.freedesktop.login1.hibernate-multiple-sessions",
2540                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2541                         "hybrid-sleep",
2542                         error);
2543 }
2544
2545 static int method_can_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2546         Manager *m = userdata;
2547
2548         return method_can_shutdown_or_sleep(
2549                         m, message,
2550                         INHIBIT_SLEEP,
2551                         "org.freedesktop.login1.hibernate",
2552                         "org.freedesktop.login1.hibernate-multiple-sessions",
2553                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2554                         "suspend-to-hibernate",
2555                         error);
2556 }
2557
2558 static int property_get_reboot_to_firmware_setup(
2559                 sd_bus *bus,
2560                 const char *path,
2561                 const char *interface,
2562                 const char *property,
2563                 sd_bus_message *reply,
2564                 void *userdata,
2565                 sd_bus_error *error) {
2566 #if 0 /// elogind does not support EFI
2567         int r;
2568
2569         assert(bus);
2570         assert(reply);
2571         assert(userdata);
2572
2573         r = efi_get_reboot_to_firmware();
2574         if (r < 0 && r != -EOPNOTSUPP)
2575                 log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
2576
2577         return sd_bus_message_append(reply, "b", r > 0);
2578 #else
2579         return sd_bus_message_append(reply, "b", false);
2580 #endif // 0
2581 }
2582
2583 static int method_set_reboot_to_firmware_setup(
2584                 sd_bus_message *message,
2585                 void *userdata,
2586                 sd_bus_error *error) {
2587
2588         int b, r;
2589         Manager *m = userdata;
2590
2591         assert(message);
2592         assert(m);
2593
2594         r = sd_bus_message_read(message, "b", &b);
2595         if (r < 0)
2596                 return r;
2597
2598         r = bus_verify_polkit_async(message,
2599                                     CAP_SYS_ADMIN,
2600                                     "org.freedesktop.login1.set-reboot-to-firmware-setup",
2601                                     NULL,
2602                                     false,
2603                                     UID_INVALID,
2604                                     &m->polkit_registry,
2605                                     error);
2606         if (r < 0)
2607                 return r;
2608         if (r == 0)
2609                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2610
2611 #if 0 /// elogind does not support EFI
2612         r = efi_set_reboot_to_firmware(b);
2613         if (r < 0)
2614                 return r;
2615 #endif // 0
2616
2617         return sd_bus_reply_method_return(message, NULL);
2618 }
2619
2620 static int method_can_reboot_to_firmware_setup(
2621                 sd_bus_message *message,
2622                 void *userdata,
2623                 sd_bus_error *error) {
2624
2625 #if 0 /// elogind does not support EFI
2626         int r;
2627         bool challenge;
2628         const char *result;
2629         Manager *m = userdata;
2630
2631         assert(message);
2632         assert(m);
2633
2634         r = efi_reboot_to_firmware_supported();
2635         if (r < 0) {
2636                 if (r != -EOPNOTSUPP)
2637                         log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
2638
2639                 return sd_bus_reply_method_return(message, "s", "na");
2640         }
2641
2642         r = bus_test_polkit(message,
2643                             CAP_SYS_ADMIN,
2644                             "org.freedesktop.login1.set-reboot-to-firmware-setup",
2645                             NULL,
2646                             UID_INVALID,
2647                             &challenge,
2648                             error);
2649         if (r < 0)
2650                 return r;
2651
2652         if (r > 0)
2653                 result = "yes";
2654         else if (challenge)
2655                 result = "challenge";
2656         else
2657                 result = "no";
2658
2659         return sd_bus_reply_method_return(message, "s", result);
2660 #else
2661         return sd_bus_reply_method_return(message, "s", "no");
2662 #endif // 0
2663 }
2664
2665 static int method_set_wall_message(
2666                 sd_bus_message *message,
2667                 void *userdata,
2668                 sd_bus_error *error) {
2669
2670         int r;
2671         Manager *m = userdata;
2672         char *wall_message;
2673         int enable_wall_messages;
2674
2675         assert(message);
2676         assert(m);
2677
2678         r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2679         if (r < 0)
2680                 return r;
2681
2682 #if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
2683         r = bus_verify_polkit_async(message,
2684                                     CAP_SYS_ADMIN,
2685                                     "org.freedesktop.login1.set-wall-message",
2686                                     NULL,
2687                                     false,
2688                                     UID_INVALID,
2689                                     &m->polkit_registry,
2690                                     error);
2691         if (r < 0)
2692                 return r;
2693         if (r == 0)
2694                 return 1; /* Will call us back */
2695 #endif // 0
2696
2697         r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2698         if (r < 0)
2699                 return log_oom();
2700
2701         m->enable_wall_messages = enable_wall_messages;
2702
2703         return sd_bus_reply_method_return(message, NULL);
2704 }
2705
2706 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2707         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2708         const char *who, *why, *what, *mode;
2709         _cleanup_free_ char *id = NULL;
2710         _cleanup_close_ int fifo_fd = -1;
2711         Manager *m = userdata;
2712         Inhibitor *i = NULL;
2713         InhibitMode mm;
2714         InhibitWhat w;
2715         pid_t pid;
2716         uid_t uid;
2717         int r;
2718
2719         assert(message);
2720         assert(m);
2721
2722         r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2723         if (r < 0)
2724                 return r;
2725
2726         w = inhibit_what_from_string(what);
2727         if (w <= 0)
2728                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2729
2730         mm = inhibit_mode_from_string(mode);
2731         if (mm < 0)
2732                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2733
2734         /* Delay is only supported for shutdown/sleep */
2735         if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2736                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2737
2738         /* Don't allow taking delay locks while we are already
2739          * executing the operation. We shouldn't create the impression
2740          * that the lock was successful if the machine is about to go
2741          * down/suspend any moment. */
2742         if (m->action_what & w)
2743                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2744
2745         r = bus_verify_polkit_async(
2746                         message,
2747                         CAP_SYS_BOOT,
2748                         w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2749                         w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
2750                         w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
2751                         w == INHIBIT_HANDLE_POWER_KEY     ? "org.freedesktop.login1.inhibit-handle-power-key" :
2752                         w == INHIBIT_HANDLE_SUSPEND_KEY   ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2753                         w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2754                                                             "org.freedesktop.login1.inhibit-handle-lid-switch",
2755                         NULL,
2756                         false,
2757                         UID_INVALID,
2758                         &m->polkit_registry,
2759                         error);
2760         if (r < 0)
2761                 return r;
2762         if (r == 0)
2763                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2764
2765         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2766         if (r < 0)
2767                 return r;
2768
2769         r = sd_bus_creds_get_euid(creds, &uid);
2770         if (r < 0)
2771                 return r;
2772
2773         r = sd_bus_creds_get_pid(creds, &pid);
2774         if (r < 0)
2775                 return r;
2776
2777         if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2778                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2779
2780         do {
2781                 id = mfree(id);
2782
2783                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2784                         return -ENOMEM;
2785
2786         } while (hashmap_get(m->inhibitors, id));
2787
2788         r = manager_add_inhibitor(m, id, &i);
2789         if (r < 0)
2790                 return r;
2791
2792         i->what = w;
2793         i->mode = mm;
2794         i->pid = pid;
2795         i->uid = uid;
2796         i->why = strdup(why);
2797         i->who = strdup(who);
2798
2799         if (!i->why || !i->who) {
2800                 r = -ENOMEM;
2801                 goto fail;
2802         }
2803
2804         fifo_fd = inhibitor_create_fifo(i);
2805         if (fifo_fd < 0) {
2806                 r = fifo_fd;
2807                 goto fail;
2808         }
2809
2810         inhibitor_start(i);
2811
2812         return sd_bus_reply_method_return(message, "h", fifo_fd);
2813
2814 fail:
2815         if (i)
2816                 inhibitor_free(i);
2817
2818         return r;
2819 }
2820
2821 const sd_bus_vtable manager_vtable[] = {
2822         SD_BUS_VTABLE_START(0),
2823
2824         SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2825         SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2826
2827 #if 0 /// UNNEEDED by elogind
2828         SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2829 #endif // 0
2830         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2831         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2832         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2833         SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2834         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2835         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2836         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2837         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2838         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2839         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2840         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2841         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2842         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2843         SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2844         SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
2845         SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2846         SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2847         SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2848         SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2849         SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2850         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2851         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2852         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2853         SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2854         SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2855         SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2856         SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2857         SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2858         SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2859         SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2860
2861         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2862         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2863         SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2864         SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2865         SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2866         SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2867         SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2868         SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2869         SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2870         SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2871         SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2872         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2873         SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2874         SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2875         SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2876         SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2877         SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2878         SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2879         SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2880         SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2881         SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2882         SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2883         SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2884         SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2885         SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2886         SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2887         SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2888         SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2889         SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2890         SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2891         SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2892         SD_BUS_METHOD("SuspendToHibernate", "b", NULL, method_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2893         SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2894         SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2895         SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2896         SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2897         SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2898         SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2899         SD_BUS_METHOD("CanSuspendToHibernate", NULL, "s", method_can_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2900         SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2901         SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2902         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2903         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2904         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2905         SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2906
2907         SD_BUS_SIGNAL("SessionNew", "so", 0),
2908         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2909         SD_BUS_SIGNAL("UserNew", "uo", 0),
2910         SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2911         SD_BUS_SIGNAL("SeatNew", "so", 0),
2912         SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2913         SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2914         SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2915
2916         SD_BUS_VTABLE_END
2917 };
2918
2919 #if 0 /// UNNEEDED by elogind
2920 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2921         int r = 0;
2922
2923         assert(s);
2924         assert(unit);
2925
2926         if (!s->started)
2927                 return r;
2928
2929         if (streq(result, "done"))
2930                 r = session_send_create_reply(s, NULL);
2931         else {
2932                 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2933
2934                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2935                 r = session_send_create_reply(s, &e);
2936         }
2937
2938         return r;
2939 }
2940
2941 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2942         const char *path, *result, *unit;
2943         Manager *m = userdata;
2944         Session *session;
2945         uint32_t id;
2946         User *user;
2947         int r;
2948
2949         assert(message);
2950         assert(m);
2951
2952         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2953         if (r < 0) {
2954                 bus_log_parse_error(r);
2955                 return 0;
2956         }
2957
2958         if (m->action_job && streq(m->action_job, path)) {
2959                 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2960
2961                 /* Tell people that they now may take a lock again */
2962                 (void) send_prepare_for(m, m->action_what, false);
2963
2964                 m->action_job = mfree(m->action_job);
2965                 m->action_unit = NULL;
2966                 m->action_what = 0;
2967                 return 0;
2968         }
2969
2970         session = hashmap_get(m->session_units, unit);
2971         if (session && streq_ptr(path, session->scope_job)) {
2972                 session->scope_job = mfree(session->scope_job);
2973                 session_jobs_reply(session, unit, result);
2974
2975                 session_save(session);
2976                 user_save(session->user);
2977                 session_add_to_gc_queue(session);
2978         }
2979
2980         user = hashmap_get(m->user_units, unit);
2981         if (user &&
2982             (streq_ptr(path, user->service_job) ||
2983              streq_ptr(path, user->slice_job))) {
2984
2985                 if (streq_ptr(path, user->service_job))
2986                         user->service_job = mfree(user->service_job);
2987
2988                 if (streq_ptr(path, user->slice_job))
2989                         user->slice_job = mfree(user->slice_job);
2990
2991                 LIST_FOREACH(sessions_by_user, session, user->sessions)
2992                         session_jobs_reply(session, unit, result);
2993
2994                 user_save(user);
2995                 user_add_to_gc_queue(user);
2996         }
2997
2998         return 0;
2999 }
3000
3001 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3002         const char *path, *unit;
3003         Manager *m = userdata;
3004         Session *session;
3005         User *user;
3006         int r;
3007
3008         assert(message);
3009         assert(m);
3010
3011         r = sd_bus_message_read(message, "so", &unit, &path);
3012         if (r < 0) {
3013                 bus_log_parse_error(r);
3014                 return 0;
3015         }
3016
3017         session = hashmap_get(m->session_units, unit);
3018         if (session)
3019                 session_add_to_gc_queue(session);
3020
3021         user = hashmap_get(m->user_units, unit);
3022         if (user)
3023                 user_add_to_gc_queue(user);
3024
3025         return 0;
3026 }
3027
3028 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3029         _cleanup_free_ char *unit = NULL;
3030         Manager *m = userdata;
3031         const char *path;
3032         Session *session;
3033         User *user;
3034         int r;
3035
3036         assert(message);
3037         assert(m);
3038
3039         path = sd_bus_message_get_path(message);
3040         if (!path)
3041                 return 0;
3042
3043         r = unit_name_from_dbus_path(path, &unit);
3044         if (r == -EINVAL) /* not a unit */
3045                 return 0;
3046         if (r < 0) {
3047                 log_oom();
3048                 return 0;
3049         }
3050
3051         session = hashmap_get(m->session_units, unit);
3052         if (session)
3053                 session_add_to_gc_queue(session);
3054
3055         user = hashmap_get(m->user_units, unit);
3056         if (user)
3057                 user_add_to_gc_queue(user);
3058
3059         return 0;
3060 }
3061
3062 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3063         Manager *m = userdata;
3064         Session *session;
3065         Iterator i;
3066         int b, r;
3067
3068         assert(message);
3069         assert(m);
3070
3071         r = sd_bus_message_read(message, "b", &b);
3072         if (r < 0) {
3073                 bus_log_parse_error(r);
3074                 return 0;
3075         }
3076
3077         if (b)
3078                 return 0;
3079
3080         /* systemd finished reloading, let's recheck all our sessions */
3081         log_debug("System manager has been reloaded, rechecking sessions...");
3082
3083         HASHMAP_FOREACH(session, m->sessions, i)
3084                 session_add_to_gc_queue(session);
3085
3086         return 0;
3087 }
3088 #endif // 0
3089
3090 int manager_send_changed(Manager *manager, const char *property, ...) {
3091         char **l;
3092
3093         assert(manager);
3094
3095         l = strv_from_stdarg_alloca(property);
3096
3097         return sd_bus_emit_properties_changed_strv(
3098                         manager->bus,
3099                         "/org/freedesktop/login1",
3100                         "org.freedesktop.login1.Manager",
3101                         l);
3102 }
3103
3104 #if 0 /// UNNEEDED by elogind
3105 static int strdup_job(sd_bus_message *reply, char **job) {
3106         const char *j;
3107         char *copy;
3108         int r;
3109
3110         r = sd_bus_message_read(reply, "o", &j);
3111         if (r < 0)
3112                 return r;
3113
3114         copy = strdup(j);
3115         if (!copy)
3116                 return -ENOMEM;
3117
3118         *job = copy;
3119         return 1;
3120 }
3121
3122 int manager_start_slice(
3123                 Manager *manager,
3124                 const char *slice,
3125                 const char *description,
3126                 const char *after,
3127                 const char *after2,
3128                 uint64_t tasks_max,
3129                 sd_bus_error *error,
3130                 char **job) {
3131
3132         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3133         int r;
3134
3135         assert(manager);
3136         assert(slice);
3137         assert(job);
3138
3139         r = sd_bus_message_new_method_call(
3140                         manager->bus,
3141                         &m,
3142                         "org.freedesktop.systemd1",
3143                         "/org/freedesktop/systemd1",
3144                         "org.freedesktop.systemd1.Manager",
3145                         "StartTransientUnit");
3146         if (r < 0)
3147                 return r;
3148
3149         r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
3150         if (r < 0)
3151                 return r;
3152
3153         r = sd_bus_message_open_container(m, 'a', "(sv)");
3154         if (r < 0)
3155                 return r;
3156
3157         if (!isempty(description)) {
3158                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3159                 if (r < 0)
3160                         return r;
3161         }
3162
3163         if (!isempty(after)) {
3164                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3165                 if (r < 0)
3166                         return r;
3167         }
3168
3169         if (!isempty(after2)) {
3170                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3171                 if (r < 0)
3172                         return r;
3173         }
3174
3175         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3176         if (r < 0)
3177                 return r;
3178
3179         r = sd_bus_message_close_container(m);
3180         if (r < 0)
3181                 return r;
3182
3183         r = sd_bus_message_append(m, "a(sa(sv))", 0);
3184         if (r < 0)
3185                 return r;
3186
3187         r = sd_bus_call(manager->bus, m, 0, error, &reply);
3188         if (r < 0)
3189                 return r;
3190
3191         return strdup_job(reply, job);
3192 }
3193
3194 int manager_start_scope(
3195                 Manager *manager,
3196                 const char *scope,
3197                 pid_t pid,
3198                 const char *slice,
3199                 const char *description,
3200                 const char *after,
3201                 const char *after2,
3202                 uint64_t tasks_max,
3203                 sd_bus_error *error,
3204                 char **job) {
3205
3206         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3207         int r;
3208
3209         assert(manager);
3210         assert(scope);
3211         assert(pid > 1);
3212         assert(job);
3213
3214         r = sd_bus_message_new_method_call(
3215                         manager->bus,
3216                         &m,
3217                         "org.freedesktop.systemd1",
3218                         "/org/freedesktop/systemd1",
3219                         "org.freedesktop.systemd1.Manager",
3220                         "StartTransientUnit");
3221         if (r < 0)
3222                 return r;
3223
3224         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3225         if (r < 0)
3226                 return r;
3227
3228         r = sd_bus_message_open_container(m, 'a', "(sv)");
3229         if (r < 0)
3230                 return r;
3231
3232         if (!isempty(slice)) {
3233                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3234                 if (r < 0)
3235                         return r;
3236         }
3237
3238         if (!isempty(description)) {
3239                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3240                 if (r < 0)
3241                         return r;
3242         }
3243
3244         if (!isempty(after)) {
3245                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3246                 if (r < 0)
3247                         return r;
3248         }
3249
3250         if (!isempty(after2)) {
3251                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3252                 if (r < 0)
3253                         return r;
3254         }
3255
3256         /* cgroup empty notification is not available in containers
3257          * currently. To make this less problematic, let's shorten the
3258          * stop timeout for sessions, so that we don't wait
3259          * forever. */
3260
3261         /* Make sure that the session shells are terminated with
3262          * SIGHUP since bash and friends tend to ignore SIGTERM */
3263         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3264         if (r < 0)
3265                 return r;
3266
3267         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3268         if (r < 0)
3269                 return r;
3270
3271         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3272         if (r < 0)
3273                 return r;
3274
3275         r = sd_bus_message_close_container(m);
3276         if (r < 0)
3277                 return r;
3278
3279         r = sd_bus_message_append(m, "a(sa(sv))", 0);
3280         if (r < 0)
3281                 return r;
3282
3283         r = sd_bus_call(manager->bus, m, 0, error, &reply);
3284         if (r < 0)
3285                 return r;
3286
3287         return strdup_job(reply, job);
3288 }
3289
3290 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3291         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3292         int r;
3293
3294         assert(manager);
3295         assert(unit);
3296         assert(job);
3297
3298         r = sd_bus_call_method(
3299                         manager->bus,
3300                         "org.freedesktop.systemd1",
3301                         "/org/freedesktop/systemd1",
3302                         "org.freedesktop.systemd1.Manager",
3303                         "StartUnit",
3304                         error,
3305                         &reply,
3306                         "ss", unit, "replace");
3307         if (r < 0)
3308                 return r;
3309
3310         return strdup_job(reply, job);
3311 }
3312
3313 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3314         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3315         int r;
3316
3317         assert(manager);
3318         assert(unit);
3319         assert(job);
3320
3321         r = sd_bus_call_method(
3322                         manager->bus,
3323                         "org.freedesktop.systemd1",
3324                         "/org/freedesktop/systemd1",
3325                         "org.freedesktop.systemd1.Manager",
3326                         "StopUnit",
3327                         error,
3328                         &reply,
3329                         "ss", unit, "fail");
3330         if (r < 0) {
3331                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3332                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3333
3334                         *job = NULL;
3335                         sd_bus_error_free(error);
3336                         return 0;
3337                 }
3338
3339                 return r;
3340         }
3341
3342         return strdup_job(reply, job);
3343 }
3344
3345 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3346         _cleanup_free_ char *path = NULL;
3347         int r;
3348
3349         assert(manager);
3350         assert(scope);
3351
3352         path = unit_dbus_path_from_name(scope);
3353         if (!path)
3354                 return -ENOMEM;
3355
3356         r = sd_bus_call_method(
3357                         manager->bus,
3358                         "org.freedesktop.systemd1",
3359                         path,
3360                         "org.freedesktop.systemd1.Scope",
3361                         "Abandon",
3362                         error,
3363                         NULL,
3364                         NULL);
3365         if (r < 0) {
3366                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3367                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3368                     sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3369                         sd_bus_error_free(error);
3370                         return 0;
3371                 }
3372
3373                 return r;
3374         }
3375
3376         return 1;
3377 }
3378
3379 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3380         assert(manager);
3381         assert(unit);
3382
3383         return sd_bus_call_method(
3384                         manager->bus,
3385                         "org.freedesktop.systemd1",
3386                         "/org/freedesktop/systemd1",
3387                         "org.freedesktop.systemd1.Manager",
3388                         "KillUnit",
3389                         error,
3390                         NULL,
3391                         "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3392 }
3393
3394 int manager_unit_is_active(Manager *manager, const char *unit) {
3395         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3396         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3397         _cleanup_free_ char *path = NULL;
3398         const char *state;
3399         int r;
3400
3401         assert(manager);
3402         assert(unit);
3403
3404         path = unit_dbus_path_from_name(unit);
3405         if (!path)
3406                 return -ENOMEM;
3407
3408         r = sd_bus_get_property(
3409                         manager->bus,
3410                         "org.freedesktop.systemd1",
3411                         path,
3412                         "org.freedesktop.systemd1.Unit",
3413                         "ActiveState",
3414                         &error,
3415                         &reply,
3416                         "s");
3417         if (r < 0) {
3418                 /* systemd might have droppped off momentarily, let's
3419                  * not make this an error */
3420                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3421                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3422                         return true;
3423
3424                 /* If the unit is already unloaded then it's not
3425                  * active */
3426                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3427                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3428                         return false;
3429
3430                 return r;
3431         }
3432
3433         r = sd_bus_message_read(reply, "s", &state);
3434         if (r < 0)
3435                 return -EINVAL;
3436
3437         return !streq(state, "inactive") && !streq(state, "failed");
3438 }
3439
3440 int manager_job_is_active(Manager *manager, const char *path) {
3441         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3442         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3443         int r;
3444
3445         assert(manager);
3446         assert(path);
3447
3448         r = sd_bus_get_property(
3449                         manager->bus,
3450                         "org.freedesktop.systemd1",
3451                         path,
3452                         "org.freedesktop.systemd1.Job",
3453                         "State",
3454                         &error,
3455                         &reply,
3456                         "s");
3457         if (r < 0) {
3458                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3459                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3460                         return true;
3461
3462                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3463                         return false;
3464
3465                 return r;
3466         }
3467
3468         /* We don't actually care about the state really. The fact
3469          * that we could read the job state is enough for us */
3470
3471         return true;
3472 }
3473 #endif // 0