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