chiark / gitweb /
b549552aebfcf15bca25952fc77fdef6a143deca
[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 ? -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         mac_selinux_init("/etc");
1239         r = write_string_file_atomic_label(file, rule);
1240         if (r < 0)
1241                 return r;
1242
1243         return trigger_device(m, d);
1244 }
1245
1246 static int flush_devices(Manager *m) {
1247         _cleanup_closedir_ DIR *d;
1248
1249         assert(m);
1250
1251         d = opendir("/etc/udev/rules.d");
1252         if (!d) {
1253                 if (errno != ENOENT)
1254                         log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1255         } else {
1256                 struct dirent *de;
1257
1258                 while ((de = readdir(d))) {
1259
1260                         if (!dirent_is_file(de))
1261                                 continue;
1262
1263                         if (!startswith(de->d_name, "72-seat-"))
1264                                 continue;
1265
1266                         if (!endswith(de->d_name, ".rules"))
1267                                 continue;
1268
1269                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1270                                 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1271                 }
1272         }
1273
1274         return trigger_device(m, NULL);
1275 }
1276
1277 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1278         const char *sysfs, *seat;
1279         Manager *m = userdata;
1280         int interactive, r;
1281
1282         assert(message);
1283         assert(m);
1284
1285         r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1286         if (r < 0)
1287                 return r;
1288
1289         if (!path_startswith(sysfs, "/sys"))
1290                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1291
1292         if (!seat_name_is_valid(seat))
1293                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1294
1295         r = bus_verify_polkit_async(
1296                         message,
1297                         CAP_SYS_ADMIN,
1298                         "org.freedesktop.login1.attach-device",
1299                         NULL,
1300                         interactive,
1301                         UID_INVALID,
1302                         &m->polkit_registry,
1303                         error);
1304         if (r < 0)
1305                 return r;
1306         if (r == 0)
1307                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1308
1309         r = attach_device(m, seat, sysfs);
1310         if (r < 0)
1311                 return r;
1312
1313         return sd_bus_reply_method_return(message, NULL);
1314 }
1315
1316 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1317         Manager *m = userdata;
1318         int interactive, r;
1319
1320         assert(message);
1321         assert(m);
1322
1323         r = sd_bus_message_read(message, "b", &interactive);
1324         if (r < 0)
1325                 return r;
1326
1327         r = bus_verify_polkit_async(
1328                         message,
1329                         CAP_SYS_ADMIN,
1330                         "org.freedesktop.login1.flush-devices",
1331                         NULL,
1332                         interactive,
1333                         UID_INVALID,
1334                         &m->polkit_registry,
1335                         error);
1336         if (r < 0)
1337                 return r;
1338         if (r == 0)
1339                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1340
1341         r = flush_devices(m);
1342         if (r < 0)
1343                 return r;
1344
1345         return sd_bus_reply_method_return(message, NULL);
1346 }
1347
1348 static int have_multiple_sessions(
1349                 Manager *m,
1350                 uid_t uid) {
1351
1352         Session *session;
1353         Iterator i;
1354
1355         assert(m);
1356
1357         /* Check for other users' sessions. Greeter sessions do not
1358          * count, and non-login sessions do not count either. */
1359         HASHMAP_FOREACH(session, m->sessions, i)
1360                 if (session->class == SESSION_USER &&
1361                     session->user->uid != uid)
1362                         return true;
1363
1364         return false;
1365 }
1366
1367 static int bus_manager_log_shutdown(
1368                 Manager *m,
1369                 InhibitWhat w,
1370 #if 0 /// elogind does not support systemd units
1371                 const char *unit_name) {
1372
1373         const char *p, *q;
1374
1375         assert(m);
1376         assert(unit_name);
1377
1378         if (w != INHIBIT_SHUTDOWN)
1379                 return 0;
1380
1381         if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1382                 p = "MESSAGE=System is powering down";
1383                 q = "SHUTDOWN=power-off";
1384         } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1385                 p = "MESSAGE=System is halting";
1386                 q = "SHUTDOWN=halt";
1387         } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1388                 p = "MESSAGE=System is rebooting";
1389                 q = "SHUTDOWN=reboot";
1390         } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1391                 p = "MESSAGE=System is rebooting with kexec";
1392                 q = "SHUTDOWN=kexec";
1393         } else {
1394                 p = "MESSAGE=System is shutting down";
1395                 q = NULL;
1396         }
1397 #else
1398                  HandleAction action) {
1399
1400          const char *p, *q;
1401
1402          assert(m);
1403
1404          if (w != INHIBIT_SHUTDOWN)
1405                  return 0;
1406
1407          switch (action) {
1408          case HANDLE_POWEROFF:
1409                  p = "MESSAGE=System is powering down.";
1410                  q = "SHUTDOWN=power-off";
1411                  break;
1412          case HANDLE_HALT:
1413                  p = "MESSAGE=System is halting.";
1414                  q = "SHUTDOWN=halt";
1415                  break;
1416          case HANDLE_REBOOT:
1417                  p = "MESSAGE=System is rebooting.";
1418                  q = "SHUTDOWN=reboot";
1419                  break;
1420          case HANDLE_KEXEC:
1421                  p = "MESSAGE=System is rebooting with kexec.";
1422                  q = "SHUTDOWN=kexec";
1423                  break;
1424          default:
1425                  p = "MESSAGE=System is shutting down.";
1426                  q = NULL;
1427          }
1428 #endif // 0
1429         if (isempty(m->wall_message))
1430                 p = strjoina(p, ".");
1431         else
1432                 p = strjoina(p, " (", m->wall_message, ").");
1433
1434         return log_struct(LOG_NOTICE,
1435                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1436                           p,
1437                           q,
1438                           NULL);
1439 }
1440
1441 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1442         Manager *m = userdata;
1443
1444         assert(e);
1445         assert(m);
1446
1447         m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1448         return 0;
1449 }
1450
1451 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1452         int r;
1453
1454         assert(m);
1455
1456         if (until <= now(CLOCK_MONOTONIC))
1457                 return 0;
1458
1459         /* We want to ignore the lid switch for a while after each
1460          * suspend, and after boot-up. Hence let's install a timer for
1461          * this. As long as the event source exists we ignore the lid
1462          * switch. */
1463
1464         if (m->lid_switch_ignore_event_source) {
1465                 usec_t u;
1466
1467                 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1468                 if (r < 0)
1469                         return r;
1470
1471                 if (until <= u)
1472                         return 0;
1473
1474                 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1475         } else
1476                 r = sd_event_add_time(
1477                                 m->event,
1478                                 &m->lid_switch_ignore_event_source,
1479                                 CLOCK_MONOTONIC,
1480                                 until, 0,
1481                                 lid_switch_ignore_handler, m);
1482
1483         return r;
1484 }
1485
1486 static void reset_scheduled_shutdown(Manager *m) {
1487         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1488         m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
1489         m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
1490         m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
1491         m->scheduled_shutdown_timeout = 0;
1492         m->shutdown_dry_run = false;
1493
1494         if (m->unlink_nologin) {
1495                 (void) unlink("/run/nologin");
1496                 m->unlink_nologin = false;
1497         }
1498 }
1499
1500 static int execute_shutdown_or_sleep(
1501                 Manager *m,
1502                 InhibitWhat w,
1503                 HandleAction action,
1504                 sd_bus_error *error) {
1505
1506 #if 0 /// elogind does not need these, we do it ourselves
1507         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1508         char *c = NULL;
1509         const char *p;
1510 #endif // 0
1511         int r;
1512
1513         assert(m);
1514         assert(w >= 0);
1515         assert(w < _INHIBIT_WHAT_MAX);
1516
1517         bus_manager_log_shutdown(m, w, action);
1518
1519 #if 0 /// elogind does it directly without depending on systemd running the system
1520         if (m->shutdown_dry_run) {
1521                 log_info("Running in dry run, suppressing action.");
1522                 reset_scheduled_shutdown(m);
1523         } else {
1524         r = sd_bus_call_method(
1525                         m->bus,
1526                         "org.freedesktop.systemd1",
1527                         "/org/freedesktop/systemd1",
1528                         "org.freedesktop.systemd1.Manager",
1529                         "StartUnit",
1530                         error,
1531                         &reply,
1532                         "ss", NULL, "replace-irreversibly");
1533 #else
1534         r = shutdown_or_sleep(m, action);
1535 #endif // 0
1536         if (r < 0)
1537                 return r;
1538
1539 #if 0 /// elogind neither needs a dbus reply, nor supports systemd action jobs
1540         r = sd_bus_message_read(reply, "o", &p);
1541         if (r < 0)
1542                 return r;
1543
1544         c = strdup(p);
1545         if (!c)
1546                 return -ENOMEM;
1547         }
1548
1549         m->action_unit = unit_name;
1550         free(m->action_job);
1551         m->action_job = c;
1552         m->action_what = w;
1553 #endif // 0
1554
1555         /* Make sure the lid switch is ignored for a while */
1556         manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1557
1558         return 0;
1559 }
1560
1561 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1562
1563         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1564         Inhibitor *offending = NULL;
1565         int r;
1566
1567         assert(manager);
1568
1569         if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
1570                 return 0;
1571
1572         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1573                 _cleanup_free_ char *comm = NULL, *u = NULL;
1574
1575                 if (!timeout)
1576                         return 0;
1577
1578                 (void) get_process_comm(offending->pid, &comm);
1579                 u = uid_to_name(offending->uid);
1580
1581                 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1582                            offending->uid, strna(u),
1583                            offending->pid, strna(comm));
1584         }
1585
1586         /* Actually do the operation */
1587         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1588         if (r < 0) {
1589                 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1590
1591                 manager->pending_action = HANDLE_IGNORE;
1592                 manager->action_what    = 0;
1593                 return r;
1594         }
1595
1596         return 1;
1597 }
1598
1599 static int manager_inhibit_timeout_handler(
1600                         sd_event_source *s,
1601                         uint64_t usec,
1602                         void *userdata) {
1603
1604         Manager *manager = userdata;
1605         int r;
1606
1607         assert(manager);
1608         assert(manager->inhibit_timeout_source == s);
1609
1610         r = manager_dispatch_delayed(manager, true);
1611         return (r < 0) ? r : 0;
1612 }
1613
1614 static int delay_shutdown_or_sleep(
1615                 Manager *m,
1616                 InhibitWhat w,
1617                 HandleAction action) {
1618
1619         int r;
1620         usec_t timeout_val;
1621
1622         assert(m);
1623         assert(w >= 0);
1624         assert(w < _INHIBIT_WHAT_MAX);
1625
1626         timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1627
1628         if (m->inhibit_timeout_source) {
1629                 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1630                 if (r < 0)
1631                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1632
1633                 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1634                 if (r < 0)
1635                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1636         } else {
1637                 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1638                                       timeout_val, 0, manager_inhibit_timeout_handler, m);
1639                 if (r < 0)
1640                         return r;
1641         }
1642
1643         m->pending_action = action;
1644         m->action_what = w;
1645
1646         return 0;
1647 }
1648
1649 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1650
1651         static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1652                 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1653                 [INHIBIT_SLEEP] = "PrepareForSleep"
1654         };
1655
1656         int active = _active;
1657
1658         assert(m);
1659         assert(w >= 0);
1660         assert(w < _INHIBIT_WHAT_MAX);
1661         assert(signal_name[w]);
1662
1663         return sd_bus_emit_signal(m->bus,
1664                                   "/org/freedesktop/login1",
1665                                   "org.freedesktop.login1.Manager",
1666                                   signal_name[w],
1667                                   "b",
1668                                   active);
1669 }
1670
1671 int bus_manager_shutdown_or_sleep_now_or_later(
1672                 Manager *m,
1673                 HandleAction action,
1674                 InhibitWhat w,
1675                 sd_bus_error *error) {
1676
1677         bool delayed;
1678         int r;
1679
1680         assert(m);
1681         assert(w >= 0);
1682         assert(w <= _INHIBIT_WHAT_MAX);
1683
1684         /* Tell everybody to prepare for shutdown/sleep */
1685         send_prepare_for(m, w, true);
1686
1687         delayed =
1688                 m->inhibit_delay_max > 0 &&
1689                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1690
1691         if (delayed)
1692                 /* Shutdown is delayed, keep in mind what we
1693                  * want to do, and start a timeout */
1694                 r = delay_shutdown_or_sleep(m, w, action);
1695         else
1696                 /* Shutdown is not delayed, execute it
1697                  * immediately */
1698                 r = execute_shutdown_or_sleep(m, w, action, error);
1699
1700         return r;
1701 }
1702
1703 static int verify_shutdown_creds(
1704                 Manager *m,
1705                 sd_bus_message *message,
1706                 InhibitWhat w,
1707                 bool interactive,
1708                 const char *action,
1709                 const char *action_multiple_sessions,
1710                 const char *action_ignore_inhibit,
1711                 sd_bus_error *error) {
1712
1713         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1714         bool multiple_sessions, blocked;
1715         uid_t uid;
1716         int r;
1717
1718         assert(m);
1719         assert(message);
1720         assert(w >= 0);
1721         assert(w <= _INHIBIT_WHAT_MAX);
1722
1723         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1724         if (r < 0)
1725                 return r;
1726
1727         r = sd_bus_creds_get_euid(creds, &uid);
1728         if (r < 0)
1729                 return r;
1730
1731         r = have_multiple_sessions(m, uid);
1732         if (r < 0)
1733                 return r;
1734
1735         multiple_sessions = r > 0;
1736         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1737
1738         if (multiple_sessions && action_multiple_sessions) {
1739                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1740                 if (r < 0)
1741                         return r;
1742                 if (r == 0)
1743                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1744         }
1745
1746         if (blocked && action_ignore_inhibit) {
1747                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1748                 if (r < 0)
1749                         return r;
1750                 if (r == 0)
1751                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1752         }
1753
1754         if (!multiple_sessions && !blocked && action) {
1755                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1756                 if (r < 0)
1757                         return r;
1758                 if (r == 0)
1759                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1760         }
1761
1762         return 0;
1763 }
1764
1765 static int method_do_shutdown_or_sleep(
1766                 Manager *m,
1767                 sd_bus_message *message,
1768                 HandleAction sleep_action,
1769                 InhibitWhat w,
1770                 const char *action,
1771                 const char *action_multiple_sessions,
1772                 const char *action_ignore_inhibit,
1773                 const char *sleep_verb,
1774                 sd_bus_error *error) {
1775
1776         int interactive, r;
1777
1778         assert(m);
1779         assert(message);
1780         assert(w >= 0);
1781         assert(w <= _INHIBIT_WHAT_MAX);
1782
1783         r = sd_bus_message_read(message, "b", &interactive);
1784         if (r < 0)
1785                 return r;
1786
1787         /* Don't allow multiple jobs being executed at the same time */
1788         if (m->action_what)
1789                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1790
1791         if (sleep_verb) {
1792                 r = can_sleep(sleep_verb);
1793                 if (r < 0)
1794                         return r;
1795
1796                 if (r == 0)
1797                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1798         }
1799
1800         r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1801                                   action_ignore_inhibit, error);
1802         if (r != 0)
1803                 return r;
1804
1805         r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
1806         if (r < 0)
1807                 return r;
1808
1809         return sd_bus_reply_method_return(message, NULL);
1810 }
1811
1812 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1813         Manager *m = userdata;
1814
1815         return method_do_shutdown_or_sleep(
1816                         m, message,
1817                         HANDLE_POWEROFF,
1818                         INHIBIT_SHUTDOWN,
1819                         "org.freedesktop.login1.power-off",
1820                         "org.freedesktop.login1.power-off-multiple-sessions",
1821                         "org.freedesktop.login1.power-off-ignore-inhibit",
1822                         NULL,
1823                         error);
1824 }
1825
1826 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1827         Manager *m = userdata;
1828
1829         return method_do_shutdown_or_sleep(
1830                         m, message,
1831                         HANDLE_REBOOT,
1832                         INHIBIT_SHUTDOWN,
1833                         "org.freedesktop.login1.reboot",
1834                         "org.freedesktop.login1.reboot-multiple-sessions",
1835                         "org.freedesktop.login1.reboot-ignore-inhibit",
1836                         NULL,
1837                         error);
1838 }
1839
1840 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1841         Manager *m = userdata;
1842
1843         return method_do_shutdown_or_sleep(
1844                         m, message,
1845                         HANDLE_SUSPEND,
1846                         INHIBIT_SLEEP,
1847                         "org.freedesktop.login1.suspend",
1848                         "org.freedesktop.login1.suspend-multiple-sessions",
1849                         "org.freedesktop.login1.suspend-ignore-inhibit",
1850                         "suspend",
1851                         error);
1852 }
1853
1854 static int nologin_timeout_handler(
1855                         sd_event_source *s,
1856                         uint64_t usec,
1857                         void *userdata) {
1858
1859         Manager *m = userdata;
1860         int r;
1861
1862         log_info("Creating /run/nologin, blocking further logins...");
1863
1864         r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
1865         if (r < 0)
1866                 log_error_errno(r, "Failed to create /run/nologin: %m");
1867         else
1868                 m->unlink_nologin = true;
1869
1870         return 0;
1871 }
1872
1873 static int update_schedule_file(Manager *m) {
1874         _cleanup_free_ char *temp_path = NULL;
1875         _cleanup_fclose_ FILE *f = NULL;
1876         int r;
1877
1878         assert(m);
1879
1880         r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1881         if (r < 0)
1882                 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1883
1884         r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1885         if (r < 0)
1886                 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1887
1888         (void) fchmod(fileno(f), 0644);
1889
1890         fprintf(f,
1891                 "USEC="USEC_FMT"\n"
1892                 "WARN_WALL=%i\n"
1893                 "MODE=%s\n",
1894                 m->scheduled_shutdown_timeout,
1895                 m->enable_wall_messages,
1896                 m->scheduled_shutdown_type);
1897
1898         if (!isempty(m->wall_message)) {
1899                 _cleanup_free_ char *t;
1900
1901                 t = cescape(m->wall_message);
1902                 if (!t) {
1903                         r = -ENOMEM;
1904                         goto fail;
1905                 }
1906
1907                 fprintf(f, "WALL_MESSAGE=%s\n", t);
1908         }
1909
1910         r = fflush_and_check(f);
1911         if (r < 0)
1912                 goto fail;
1913
1914         if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1915                 r = -errno;
1916                 goto fail;
1917         }
1918
1919         return 0;
1920
1921 fail:
1922                 (void) unlink(temp_path);
1923                 (void) unlink("/run/systemd/shutdown/scheduled");
1924
1925         return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
1926 }
1927
1928 static int manager_scheduled_shutdown_handler(
1929                         sd_event_source *s,
1930                         uint64_t usec,
1931                         void *userdata) {
1932
1933         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1934         Manager *m = userdata;
1935         HandleAction action;
1936         int r;
1937
1938         assert(m);
1939
1940         if (isempty(m->scheduled_shutdown_type))
1941                 return 0;
1942
1943         if (streq(m->scheduled_shutdown_type, "halt"))
1944                 action = HANDLE_HALT;
1945         else if (streq(m->scheduled_shutdown_type, "poweroff"))
1946                 action = HANDLE_POWEROFF;
1947         else
1948                 action = HANDLE_REBOOT;
1949
1950         r = execute_shutdown_or_sleep(m, 0, action, &error);
1951         if (r < 0)
1952                 return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
1953
1954         return 0;
1955 }
1956
1957 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1958         Manager *m = userdata;
1959         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1960         const char *action_multiple_sessions = NULL;
1961         const char *action_ignore_inhibit = NULL;
1962         const char *action = NULL;
1963         uint64_t elapse;
1964         char *type;
1965         int r;
1966
1967         assert(m);
1968         assert(message);
1969
1970         r = sd_bus_message_read(message, "st", &type, &elapse);
1971         if (r < 0)
1972                 return r;
1973
1974         if (startswith(type, "dry-")) {
1975                 type += 4;
1976                 m->shutdown_dry_run = true;
1977         }
1978
1979         if (streq(type, "reboot")) {
1980                 action = "org.freedesktop.login1.reboot";
1981                 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1982                 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1983         } else if (streq(type, "halt")) {
1984                 action = "org.freedesktop.login1.halt";
1985                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1986                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1987         } else if (streq(type, "poweroff")) {
1988                 action = "org.freedesktop.login1.poweroff";
1989                 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1990                 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1991         } else
1992                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1993
1994         r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1995                                   action, action_multiple_sessions, action_ignore_inhibit, error);
1996         if (r != 0)
1997                 return r;
1998
1999         if (m->scheduled_shutdown_timeout_source) {
2000                 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2001                 if (r < 0)
2002                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2003
2004                 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2005                 if (r < 0)
2006                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2007         } else {
2008                 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2009                                       CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2010                 if (r < 0)
2011                         return log_error_errno(r, "sd_event_add_time() failed: %m");
2012         }
2013
2014         r = free_and_strdup(&m->scheduled_shutdown_type, type);
2015         if (r < 0) {
2016                 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2017                 return log_oom();
2018         }
2019
2020         if (m->nologin_timeout_source) {
2021                 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2022                 if (r < 0)
2023                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2024
2025                 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2026                 if (r < 0)
2027                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2028         } else {
2029                 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2030                                       CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2031                 if (r < 0)
2032                         return log_error_errno(r, "sd_event_add_time() failed: %m");
2033         }
2034
2035         m->scheduled_shutdown_timeout = elapse;
2036
2037         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2038         if (r >= 0) {
2039                 const char *tty;
2040
2041                 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2042                 (void) sd_bus_creds_get_tty(creds, &tty);
2043
2044                 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2045                 if (r < 0) {
2046                         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2047                         return log_oom();
2048                 }
2049         }
2050
2051 #if 0 /// elogind does not support utmp-wtmp
2052         r = manager_setup_wall_message_timer(m);
2053         if (r < 0)
2054                 return r;
2055 #endif // 0
2056
2057         if (!isempty(type)) {
2058                 r = update_schedule_file(m);
2059                 if (r < 0)
2060                         return r;
2061         } else
2062                 (void) unlink("/run/systemd/shutdown/scheduled");
2063
2064         return sd_bus_reply_method_return(message, NULL);
2065 }
2066
2067 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2068         Manager *m = userdata;
2069         bool cancelled;
2070
2071         assert(m);
2072         assert(message);
2073
2074         cancelled = m->scheduled_shutdown_type != NULL;
2075         reset_scheduled_shutdown(m);
2076
2077 #if 0 /// elogind does not support utmp-wtmp
2078         if (cancelled) {
2079                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2080                 const char *tty = NULL;
2081                 uid_t uid = 0;
2082                 int r;
2083
2084                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2085                 if (r >= 0) {
2086                         (void) sd_bus_creds_get_uid(creds, &uid);
2087                         (void) sd_bus_creds_get_tty(creds, &tty);
2088                 }
2089
2090                 utmp_wall("The system shutdown has been cancelled",
2091                           uid_to_name(uid), tty, logind_wall_tty_filter, m);
2092         }
2093 #endif // 0
2094
2095         return sd_bus_reply_method_return(message, "b", cancelled);
2096 }
2097
2098 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2099         Manager *m = userdata;
2100
2101         return method_do_shutdown_or_sleep(
2102                         m, message,
2103                         HANDLE_HIBERNATE,
2104                         INHIBIT_SLEEP,
2105                         "org.freedesktop.login1.hibernate",
2106                         "org.freedesktop.login1.hibernate-multiple-sessions",
2107                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2108                         "hibernate",
2109                         error);
2110 }
2111
2112 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2113         Manager *m = userdata;
2114
2115         return method_do_shutdown_or_sleep(
2116                         m, message,
2117                         HANDLE_HYBRID_SLEEP,
2118                         INHIBIT_SLEEP,
2119                         "org.freedesktop.login1.hibernate",
2120                         "org.freedesktop.login1.hibernate-multiple-sessions",
2121                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2122                         "hybrid-sleep",
2123                         error);
2124 }
2125
2126 static int method_can_shutdown_or_sleep(
2127                 Manager *m,
2128                 sd_bus_message *message,
2129                 InhibitWhat w,
2130                 const char *action,
2131                 const char *action_multiple_sessions,
2132                 const char *action_ignore_inhibit,
2133                 const char *sleep_verb,
2134                 sd_bus_error *error) {
2135
2136         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2137         bool multiple_sessions, challenge, blocked;
2138         const char *result = NULL;
2139         uid_t uid;
2140         int r;
2141
2142         assert(m);
2143         assert(message);
2144         assert(w >= 0);
2145         assert(w <= _INHIBIT_WHAT_MAX);
2146         assert(action);
2147         assert(action_multiple_sessions);
2148         assert(action_ignore_inhibit);
2149
2150         if (sleep_verb) {
2151                 r = can_sleep(sleep_verb);
2152                 if (r < 0)
2153                         return r;
2154                 if (r == 0)
2155                         return sd_bus_reply_method_return(message, "s", "na");
2156         }
2157
2158         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2159         if (r < 0)
2160                 return r;
2161
2162         r = sd_bus_creds_get_euid(creds, &uid);
2163         if (r < 0)
2164                 return r;
2165
2166         r = have_multiple_sessions(m, uid);
2167         if (r < 0)
2168                 return r;
2169
2170         multiple_sessions = r > 0;
2171         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2172
2173         if (multiple_sessions) {
2174                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2175                 if (r < 0)
2176                         return r;
2177
2178                 if (r > 0)
2179                         result = "yes";
2180                 else if (challenge)
2181                         result = "challenge";
2182                 else
2183                         result = "no";
2184         }
2185
2186         if (blocked) {
2187                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2188                 if (r < 0)
2189                         return r;
2190
2191                 if (r > 0 && !result)
2192                         result = "yes";
2193                 else if (challenge && (!result || streq(result, "yes")))
2194                         result = "challenge";
2195                 else
2196                         result = "no";
2197         }
2198
2199         if (!multiple_sessions && !blocked) {
2200                 /* If neither inhibit nor multiple sessions
2201                  * apply then just check the normal policy */
2202
2203                 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2204                 if (r < 0)
2205                         return r;
2206
2207                 if (r > 0)
2208                         result = "yes";
2209                 else if (challenge)
2210                         result = "challenge";
2211                 else
2212                         result = "no";
2213         }
2214
2215         return sd_bus_reply_method_return(message, "s", result);
2216 }
2217
2218 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2219         Manager *m = userdata;
2220
2221         return method_can_shutdown_or_sleep(
2222                         m, message,
2223                         INHIBIT_SHUTDOWN,
2224                         "org.freedesktop.login1.power-off",
2225                         "org.freedesktop.login1.power-off-multiple-sessions",
2226                         "org.freedesktop.login1.power-off-ignore-inhibit",
2227                         NULL,
2228                         error);
2229 }
2230
2231 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2232         Manager *m = userdata;
2233
2234         return method_can_shutdown_or_sleep(
2235                         m, message,
2236                         INHIBIT_SHUTDOWN,
2237                         "org.freedesktop.login1.reboot",
2238                         "org.freedesktop.login1.reboot-multiple-sessions",
2239                         "org.freedesktop.login1.reboot-ignore-inhibit",
2240                         NULL,
2241                         error);
2242 }
2243
2244 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2245         Manager *m = userdata;
2246
2247         return method_can_shutdown_or_sleep(
2248                         m, message,
2249                         INHIBIT_SLEEP,
2250                         "org.freedesktop.login1.suspend",
2251                         "org.freedesktop.login1.suspend-multiple-sessions",
2252                         "org.freedesktop.login1.suspend-ignore-inhibit",
2253                         "suspend",
2254                         error);
2255 }
2256
2257 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2258         Manager *m = userdata;
2259
2260         return method_can_shutdown_or_sleep(
2261                         m, message,
2262                         INHIBIT_SLEEP,
2263                         "org.freedesktop.login1.hibernate",
2264                         "org.freedesktop.login1.hibernate-multiple-sessions",
2265                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2266                         "hibernate",
2267                         error);
2268 }
2269
2270 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2271         Manager *m = userdata;
2272
2273         return method_can_shutdown_or_sleep(
2274                         m, message,
2275                         INHIBIT_SLEEP,
2276                         "org.freedesktop.login1.hibernate",
2277                         "org.freedesktop.login1.hibernate-multiple-sessions",
2278                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2279                         "hybrid-sleep",
2280                         error);
2281 }
2282
2283 static int property_get_reboot_to_firmware_setup(
2284                 sd_bus *bus,
2285                 const char *path,
2286                 const char *interface,
2287                 const char *property,
2288                 sd_bus_message *reply,
2289                 void *userdata,
2290                 sd_bus_error *error) {
2291 #if 0 /// elogind does not support EFI
2292         int r;
2293
2294         assert(bus);
2295         assert(reply);
2296         assert(userdata);
2297
2298         r = efi_get_reboot_to_firmware();
2299         if (r < 0 && r != -EOPNOTSUPP)
2300                 return r;
2301
2302         return sd_bus_message_append(reply, "b", r > 0);
2303 #else
2304         return sd_bus_message_append(reply, "b", -EOPNOTSUPP);
2305 #endif // 0
2306 }
2307
2308 static int method_set_reboot_to_firmware_setup(
2309                 sd_bus_message *message,
2310                 void *userdata,
2311                 sd_bus_error *error) {
2312
2313         int b, r;
2314         Manager *m = userdata;
2315
2316         assert(message);
2317         assert(m);
2318
2319         r = sd_bus_message_read(message, "b", &b);
2320         if (r < 0)
2321                 return r;
2322
2323         r = bus_verify_polkit_async(message,
2324                                     CAP_SYS_ADMIN,
2325                                     "org.freedesktop.login1.set-reboot-to-firmware-setup",
2326                                     NULL,
2327                                     false,
2328                                     UID_INVALID,
2329                                     &m->polkit_registry,
2330                                     error);
2331         if (r < 0)
2332                 return r;
2333         if (r == 0)
2334                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2335
2336 #if 0 /// elogind does not support EFI
2337         r = efi_set_reboot_to_firmware(b);
2338         if (r < 0)
2339                 return r;
2340 #endif // 0
2341
2342         return sd_bus_reply_method_return(message, NULL);
2343 }
2344
2345 static int method_can_reboot_to_firmware_setup(
2346                 sd_bus_message *message,
2347                 void *userdata,
2348                 sd_bus_error *error) {
2349
2350 #if 0 /// elogind does not support EFI
2351         int r;
2352         bool challenge;
2353         const char *result;
2354         Manager *m = userdata;
2355
2356         assert(message);
2357         assert(m);
2358
2359         r = efi_reboot_to_firmware_supported();
2360         if (r == -EOPNOTSUPP)
2361                 return sd_bus_reply_method_return(message, "s", "na");
2362         else if (r < 0)
2363                 return r;
2364
2365         r = bus_test_polkit(message,
2366                             CAP_SYS_ADMIN,
2367                             "org.freedesktop.login1.set-reboot-to-firmware-setup",
2368                             NULL,
2369                             UID_INVALID,
2370                             &challenge,
2371                             error);
2372         if (r < 0)
2373                 return r;
2374
2375         if (r > 0)
2376                 result = "yes";
2377         else if (challenge)
2378                 result = "challenge";
2379         else
2380                 result = "no";
2381
2382         return sd_bus_reply_method_return(message, "s", result);
2383 #else
2384         return sd_bus_reply_method_return(message, "s", "na");
2385 #endif // 0
2386 }
2387
2388 static int method_set_wall_message(
2389                 sd_bus_message *message,
2390                 void *userdata,
2391                 sd_bus_error *error) {
2392
2393         int r;
2394         Manager *m = userdata;
2395         char *wall_message;
2396         int enable_wall_messages;
2397
2398         assert(message);
2399         assert(m);
2400
2401         r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2402         if (r < 0)
2403                 return r;
2404
2405         r = bus_verify_polkit_async(message,
2406                                     CAP_SYS_ADMIN,
2407                                     "org.freedesktop.login1.set-wall-message",
2408                                     NULL,
2409                                     false,
2410                                     UID_INVALID,
2411                                     &m->polkit_registry,
2412                                     error);
2413         if (r < 0)
2414                 return r;
2415         if (r == 0)
2416                 return 1; /* Will call us back */
2417
2418         if (isempty(wall_message))
2419                 m->wall_message = mfree(m->wall_message);
2420         else {
2421                 r = free_and_strdup(&m->wall_message, wall_message);
2422                 if (r < 0)
2423                         return log_oom();
2424         }
2425
2426         m->enable_wall_messages = enable_wall_messages;
2427
2428         return sd_bus_reply_method_return(message, NULL);
2429 }
2430
2431 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2432         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2433         const char *who, *why, *what, *mode;
2434         _cleanup_free_ char *id = NULL;
2435         _cleanup_close_ int fifo_fd = -1;
2436         Manager *m = userdata;
2437         Inhibitor *i = NULL;
2438         InhibitMode mm;
2439         InhibitWhat w;
2440         pid_t pid;
2441         uid_t uid;
2442         int r;
2443
2444         assert(message);
2445         assert(m);
2446
2447         r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2448         if (r < 0)
2449                 return r;
2450
2451         w = inhibit_what_from_string(what);
2452         if (w <= 0)
2453                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2454
2455         mm = inhibit_mode_from_string(mode);
2456         if (mm < 0)
2457                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2458
2459         /* Delay is only supported for shutdown/sleep */
2460         if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2461                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2462
2463         /* Don't allow taking delay locks while we are already
2464          * executing the operation. We shouldn't create the impression
2465          * that the lock was successful if the machine is about to go
2466          * down/suspend any moment. */
2467         if (m->action_what & w)
2468                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2469
2470         r = bus_verify_polkit_async(
2471                         message,
2472                         CAP_SYS_BOOT,
2473                         w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2474                         w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
2475                         w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
2476                         w == INHIBIT_HANDLE_POWER_KEY     ? "org.freedesktop.login1.inhibit-handle-power-key" :
2477                         w == INHIBIT_HANDLE_SUSPEND_KEY   ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2478                         w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2479                                                             "org.freedesktop.login1.inhibit-handle-lid-switch",
2480                         NULL,
2481                         false,
2482                         UID_INVALID,
2483                         &m->polkit_registry,
2484                         error);
2485         if (r < 0)
2486                 return r;
2487         if (r == 0)
2488                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2489
2490         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2491         if (r < 0)
2492                 return r;
2493
2494         r = sd_bus_creds_get_euid(creds, &uid);
2495         if (r < 0)
2496                 return r;
2497
2498         r = sd_bus_creds_get_pid(creds, &pid);
2499         if (r < 0)
2500                 return r;
2501
2502         do {
2503                 id = mfree(id);
2504
2505                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2506                         return -ENOMEM;
2507
2508         } while (hashmap_get(m->inhibitors, id));
2509
2510         r = manager_add_inhibitor(m, id, &i);
2511         if (r < 0)
2512                 return r;
2513
2514         i->what = w;
2515         i->mode = mm;
2516         i->pid = pid;
2517         i->uid = uid;
2518         i->why = strdup(why);
2519         i->who = strdup(who);
2520
2521         if (!i->why || !i->who) {
2522                 r = -ENOMEM;
2523                 goto fail;
2524         }
2525
2526         fifo_fd = inhibitor_create_fifo(i);
2527         if (fifo_fd < 0) {
2528                 r = fifo_fd;
2529                 goto fail;
2530         }
2531
2532         inhibitor_start(i);
2533
2534         return sd_bus_reply_method_return(message, "h", fifo_fd);
2535
2536 fail:
2537         if (i)
2538                 inhibitor_free(i);
2539
2540         return r;
2541 }
2542
2543 const sd_bus_vtable manager_vtable[] = {
2544         SD_BUS_VTABLE_START(0),
2545
2546         SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2547         SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2548
2549 //        SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2550         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2551         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2552         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2553         SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2554         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2555         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2556         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2557         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2558         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2559         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2560         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2561         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2562         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2563         SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2564         SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2565         SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2566         SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2567         SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2568         SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2569         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2570         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2571         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2572
2573         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2574         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2575         SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2576         SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2577         SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2578         SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2579         SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2580         SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2581         SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2582         SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2583         SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2584         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2585         SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2586         SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2587         SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2588         SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2589         SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2590         SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2591         SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2592         SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2593         SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2594         SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2595         SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2596         SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2597         SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2598         SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2599         SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2600         SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2601         SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2602         SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2603         SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2604         SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2605         SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2606         SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2607         SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2608         SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2609         SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2610         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2611         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2612         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2613         SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2614
2615         SD_BUS_SIGNAL("SessionNew", "so", 0),
2616         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2617         SD_BUS_SIGNAL("UserNew", "uo", 0),
2618         SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2619         SD_BUS_SIGNAL("SeatNew", "so", 0),
2620         SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2621         SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2622         SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2623
2624         SD_BUS_VTABLE_END
2625 };
2626
2627 #if 0 /// UNNEEDED by elogind
2628 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2629         int r = 0;
2630
2631         assert(s);
2632         assert(unit);
2633
2634         if (!s->started)
2635                 return r;
2636
2637         if (streq(result, "done"))
2638                 r = session_send_create_reply(s, NULL);
2639         else {
2640                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2641
2642                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2643                 r = session_send_create_reply(s, &e);
2644         }
2645
2646         return r;
2647 }
2648
2649 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2650         const char *path, *result, *unit;
2651         Manager *m = userdata;
2652         Session *session;
2653         uint32_t id;
2654         User *user;
2655         int r;
2656
2657         assert(message);
2658         assert(m);
2659
2660         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2661         if (r < 0) {
2662                 bus_log_parse_error(r);
2663                 return 0;
2664         }
2665
2666         if (m->action_job && streq(m->action_job, path)) {
2667                 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2668
2669                 /* Tell people that they now may take a lock again */
2670                 send_prepare_for(m, m->action_what, false);
2671
2672                 m->action_job = mfree(m->action_job);
2673                 m->action_unit = NULL;
2674                 m->action_what = 0;
2675                 return 0;
2676         }
2677
2678         session = hashmap_get(m->session_units, unit);
2679         if (session && streq_ptr(path, session->scope_job)) {
2680                 session->scope_job = mfree(session->scope_job);
2681                 session_jobs_reply(session, unit, result);
2682
2683                 session_save(session);
2684                 user_save(session->user);
2685                 session_add_to_gc_queue(session);
2686         }
2687
2688         user = hashmap_get(m->user_units, unit);
2689         if (user &&
2690             (streq_ptr(path, user->service_job) ||
2691              streq_ptr(path, user->slice_job))) {
2692
2693                 if (streq_ptr(path, user->service_job))
2694                         user->service_job = mfree(user->service_job);
2695
2696                 if (streq_ptr(path, user->slice_job))
2697                         user->slice_job = mfree(user->slice_job);
2698
2699                 LIST_FOREACH(sessions_by_user, session, user->sessions)
2700                         session_jobs_reply(session, unit, result);
2701
2702                 user_save(user);
2703                 user_add_to_gc_queue(user);
2704         }
2705
2706         return 0;
2707 }
2708
2709 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2710         const char *path, *unit;
2711         Manager *m = userdata;
2712         Session *session;
2713         User *user;
2714         int r;
2715
2716         assert(message);
2717         assert(m);
2718
2719         r = sd_bus_message_read(message, "so", &unit, &path);
2720         if (r < 0) {
2721                 bus_log_parse_error(r);
2722                 return 0;
2723         }
2724
2725         session = hashmap_get(m->session_units, unit);
2726         if (session)
2727                 session_add_to_gc_queue(session);
2728
2729         user = hashmap_get(m->user_units, unit);
2730         if (user)
2731                 user_add_to_gc_queue(user);
2732
2733         return 0;
2734 }
2735
2736 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2737         _cleanup_free_ char *unit = NULL;
2738         Manager *m = userdata;
2739         const char *path;
2740         Session *session;
2741         User *user;
2742         int r;
2743
2744         assert(message);
2745         assert(m);
2746
2747         path = sd_bus_message_get_path(message);
2748         if (!path)
2749                 return 0;
2750
2751         r = unit_name_from_dbus_path(path, &unit);
2752         if (r == -EINVAL) /* not a unit */
2753                 return 0;
2754         if (r < 0) {
2755                 log_oom();
2756                 return 0;
2757         }
2758
2759         session = hashmap_get(m->session_units, unit);
2760         if (session)
2761                 session_add_to_gc_queue(session);
2762
2763         user = hashmap_get(m->user_units, unit);
2764         if (user)
2765                 user_add_to_gc_queue(user);
2766
2767         return 0;
2768 }
2769
2770 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2771         Manager *m = userdata;
2772         Session *session;
2773         Iterator i;
2774         int b, r;
2775
2776         assert(message);
2777         assert(m);
2778
2779         r = sd_bus_message_read(message, "b", &b);
2780         if (r < 0) {
2781                 bus_log_parse_error(r);
2782                 return 0;
2783         }
2784
2785         if (b)
2786                 return 0;
2787
2788         /* systemd finished reloading, let's recheck all our sessions */
2789         log_debug("System manager has been reloaded, rechecking sessions...");
2790
2791         HASHMAP_FOREACH(session, m->sessions, i)
2792                 session_add_to_gc_queue(session);
2793
2794         return 0;
2795 }
2796 #endif // 0
2797
2798 int manager_send_changed(Manager *manager, const char *property, ...) {
2799         char **l;
2800
2801         assert(manager);
2802
2803         l = strv_from_stdarg_alloca(property);
2804
2805         return sd_bus_emit_properties_changed_strv(
2806                         manager->bus,
2807                         "/org/freedesktop/login1",
2808                         "org.freedesktop.login1.Manager",
2809                         l);
2810 }
2811
2812 #if 0 /// UNNEEDED by elogind
2813 int manager_start_slice(
2814                 Manager *manager,
2815                 const char *slice,
2816                 const char *description,
2817                 const char *after,
2818                 const char *after2,
2819                 uint64_t tasks_max,
2820                 sd_bus_error *error,
2821                 char **job) {
2822
2823         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2824         int r;
2825
2826         assert(manager);
2827         assert(slice);
2828
2829         r = sd_bus_message_new_method_call(
2830                         manager->bus,
2831                         &m,
2832                         "org.freedesktop.systemd1",
2833                         "/org/freedesktop/systemd1",
2834                         "org.freedesktop.systemd1.Manager",
2835                         "StartTransientUnit");
2836         if (r < 0)
2837                 return r;
2838
2839         r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
2840         if (r < 0)
2841                 return r;
2842
2843         r = sd_bus_message_open_container(m, 'a', "(sv)");
2844         if (r < 0)
2845                 return r;
2846
2847         if (!isempty(description)) {
2848                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2849                 if (r < 0)
2850                         return r;
2851         }
2852
2853         if (!isempty(after)) {
2854                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2855                 if (r < 0)
2856                         return r;
2857         }
2858
2859         if (!isempty(after2)) {
2860                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2861                 if (r < 0)
2862                         return r;
2863         }
2864
2865         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
2866         if (r < 0)
2867                 return r;
2868
2869         r = sd_bus_message_close_container(m);
2870         if (r < 0)
2871                 return r;
2872
2873         r = sd_bus_message_append(m, "a(sa(sv))", 0);
2874         if (r < 0)
2875                 return r;
2876
2877         r = sd_bus_call(manager->bus, m, 0, error, &reply);
2878         if (r < 0)
2879                 return r;
2880
2881         if (job) {
2882                 const char *j;
2883                 char *copy;
2884
2885                 r = sd_bus_message_read(reply, "o", &j);
2886                 if (r < 0)
2887                         return r;
2888
2889                 copy = strdup(j);
2890                 if (!copy)
2891                         return -ENOMEM;
2892
2893                 *job = copy;
2894         }
2895
2896         return 1;
2897 }
2898
2899 int manager_start_scope(
2900                 Manager *manager,
2901                 const char *scope,
2902                 pid_t pid,
2903                 const char *slice,
2904                 const char *description,
2905                 const char *after,
2906                 const char *after2,
2907                 uint64_t tasks_max,
2908                 sd_bus_error *error,
2909                 char **job) {
2910
2911         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2912         int r;
2913
2914         assert(manager);
2915         assert(scope);
2916         assert(pid > 1);
2917
2918         r = sd_bus_message_new_method_call(
2919                         manager->bus,
2920                         &m,
2921                         "org.freedesktop.systemd1",
2922                         "/org/freedesktop/systemd1",
2923                         "org.freedesktop.systemd1.Manager",
2924                         "StartTransientUnit");
2925         if (r < 0)
2926                 return r;
2927
2928         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2929         if (r < 0)
2930                 return r;
2931
2932         r = sd_bus_message_open_container(m, 'a', "(sv)");
2933         if (r < 0)
2934                 return r;
2935
2936         if (!isempty(slice)) {
2937                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2938                 if (r < 0)
2939                         return r;
2940         }
2941
2942         if (!isempty(description)) {
2943                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2944                 if (r < 0)
2945                         return r;
2946         }
2947
2948         if (!isempty(after)) {
2949                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2950                 if (r < 0)
2951                         return r;
2952         }
2953
2954         if (!isempty(after2)) {
2955                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2956                 if (r < 0)
2957                         return r;
2958         }
2959
2960         /* cgroup empty notification is not available in containers
2961          * currently. To make this less problematic, let's shorten the
2962          * stop timeout for sessions, so that we don't wait
2963          * forever. */
2964
2965         /* Make sure that the session shells are terminated with
2966          * SIGHUP since bash and friends tend to ignore SIGTERM */
2967         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2968         if (r < 0)
2969                 return r;
2970
2971         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2972         if (r < 0)
2973                 return r;
2974
2975         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
2976         if (r < 0)
2977                 return r;
2978
2979         r = sd_bus_message_close_container(m);
2980         if (r < 0)
2981                 return r;
2982
2983         r = sd_bus_message_append(m, "a(sa(sv))", 0);
2984         if (r < 0)
2985                 return r;
2986
2987         r = sd_bus_call(manager->bus, m, 0, error, &reply);
2988         if (r < 0)
2989                 return r;
2990
2991         if (job) {
2992                 const char *j;
2993                 char *copy;
2994
2995                 r = sd_bus_message_read(reply, "o", &j);
2996                 if (r < 0)
2997                         return r;
2998
2999                 copy = strdup(j);
3000                 if (!copy)
3001                         return -ENOMEM;
3002
3003                 *job = copy;
3004         }
3005
3006         return 1;
3007 }
3008
3009 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3010         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3011         int r;
3012
3013         assert(manager);
3014         assert(unit);
3015
3016         r = sd_bus_call_method(
3017                         manager->bus,
3018                         "org.freedesktop.systemd1",
3019                         "/org/freedesktop/systemd1",
3020                         "org.freedesktop.systemd1.Manager",
3021                         "StartUnit",
3022                         error,
3023                         &reply,
3024                         "ss", unit, "replace");
3025         if (r < 0)
3026                 return r;
3027
3028         if (job) {
3029                 const char *j;
3030                 char *copy;
3031
3032                 r = sd_bus_message_read(reply, "o", &j);
3033                 if (r < 0)
3034                         return r;
3035
3036                 copy = strdup(j);
3037                 if (!copy)
3038                         return -ENOMEM;
3039
3040                 *job = copy;
3041         }
3042
3043         return 1;
3044 }
3045
3046 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3047         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3048         int r;
3049
3050         assert(manager);
3051         assert(unit);
3052
3053         r = sd_bus_call_method(
3054                         manager->bus,
3055                         "org.freedesktop.systemd1",
3056                         "/org/freedesktop/systemd1",
3057                         "org.freedesktop.systemd1.Manager",
3058                         "StopUnit",
3059                         error,
3060                         &reply,
3061                         "ss", unit, "fail");
3062         if (r < 0) {
3063                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3064                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3065
3066                         if (job)
3067                                 *job = NULL;
3068
3069                         sd_bus_error_free(error);
3070                         return 0;
3071                 }
3072
3073                 return r;
3074         }
3075
3076         if (job) {
3077                 const char *j;
3078                 char *copy;
3079
3080                 r = sd_bus_message_read(reply, "o", &j);
3081                 if (r < 0)
3082                         return r;
3083
3084                 copy = strdup(j);
3085                 if (!copy)
3086                         return -ENOMEM;
3087
3088                 *job = copy;
3089         }
3090
3091         return 1;
3092 }
3093
3094 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3095         _cleanup_free_ char *path = NULL;
3096         int r;
3097
3098         assert(manager);
3099         assert(scope);
3100
3101         path = unit_dbus_path_from_name(scope);
3102         if (!path)
3103                 return -ENOMEM;
3104
3105         r = sd_bus_call_method(
3106                         manager->bus,
3107                         "org.freedesktop.systemd1",
3108                         path,
3109                         "org.freedesktop.systemd1.Scope",
3110                         "Abandon",
3111                         error,
3112                         NULL,
3113                         NULL);
3114         if (r < 0) {
3115                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3116                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3117                     sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3118                         sd_bus_error_free(error);
3119                         return 0;
3120                 }
3121
3122                 return r;
3123         }
3124
3125         return 1;
3126 }
3127
3128 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3129         assert(manager);
3130         assert(unit);
3131
3132         return sd_bus_call_method(
3133                         manager->bus,
3134                         "org.freedesktop.systemd1",
3135                         "/org/freedesktop/systemd1",
3136                         "org.freedesktop.systemd1.Manager",
3137                         "KillUnit",
3138                         error,
3139                         NULL,
3140                         "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3141 }
3142
3143 int manager_unit_is_active(Manager *manager, const char *unit) {
3144         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3145         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3146         _cleanup_free_ char *path = NULL;
3147         const char *state;
3148         int r;
3149
3150         assert(manager);
3151         assert(unit);
3152
3153         path = unit_dbus_path_from_name(unit);
3154         if (!path)
3155                 return -ENOMEM;
3156
3157         r = sd_bus_get_property(
3158                         manager->bus,
3159                         "org.freedesktop.systemd1",
3160                         path,
3161                         "org.freedesktop.systemd1.Unit",
3162                         "ActiveState",
3163                         &error,
3164                         &reply,
3165                         "s");
3166         if (r < 0) {
3167                 /* systemd might have droppped off momentarily, let's
3168                  * not make this an error */
3169                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3170                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3171                         return true;
3172
3173                 /* If the unit is already unloaded then it's not
3174                  * active */
3175                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3176                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3177                         return false;
3178
3179                 return r;
3180         }
3181
3182         r = sd_bus_message_read(reply, "s", &state);
3183         if (r < 0)
3184                 return -EINVAL;
3185
3186         return !streq(state, "inactive") && !streq(state, "failed");
3187 }
3188
3189 int manager_job_is_active(Manager *manager, const char *path) {
3190         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3191         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3192         int r;
3193
3194         assert(manager);
3195         assert(path);
3196
3197         r = sd_bus_get_property(
3198                         manager->bus,
3199                         "org.freedesktop.systemd1",
3200                         path,
3201                         "org.freedesktop.systemd1.Job",
3202                         "State",
3203                         &error,
3204                         &reply,
3205                         "s");
3206         if (r < 0) {
3207                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3208                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3209                         return true;
3210
3211                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3212                         return false;
3213
3214                 return r;
3215         }
3216
3217         /* We don't actually care about the state really. The fact
3218          * that we could read the job state is enough for us */
3219
3220         return true;
3221 }
3222 #endif //