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