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