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