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