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