chiark / gitweb /
bf00b137a31f4cdd278aed227c982e6498369d3b
[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         /* Here upstream systemd starts cgroups and the user systemd,
821            and arranges to reply asynchronously.  We reply
822            directly.  */
823
824         r = session_send_create_reply(session, NULL);
825         if (r < 0)
826                 goto fail;
827
828         session_save(session);
829
830         return 1;
831
832 fail:
833         if (session)
834                 session_add_to_gc_queue(session);
835
836         if (user)
837                 user_add_to_gc_queue(user);
838
839         return r;
840 }
841
842 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
843         Manager *m = userdata;
844         Session *session;
845         const char *name;
846         int r;
847
848         assert(message);
849         assert(m);
850
851         r = sd_bus_message_read(message, "s", &name);
852         if (r < 0)
853                 return r;
854
855         r = manager_get_session_from_creds(m, message, name, error, &session);
856         if (r < 0)
857                 return r;
858
859         r = session_release(session);
860         if (r < 0)
861                 return r;
862
863         session_add_to_gc_queue(session);
864
865         return sd_bus_reply_method_return(message, NULL);
866 }
867
868 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
869         Manager *m = userdata;
870         Session *session;
871         const char *name;
872         int r;
873
874         assert(message);
875         assert(m);
876
877         r = sd_bus_message_read(message, "s", &name);
878         if (r < 0)
879                 return r;
880
881         r = manager_get_session_from_creds(m, message, name, error, &session);
882         if (r < 0)
883                 return r;
884
885         return bus_session_method_activate(message, session, error);
886 }
887
888 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
889         const char *session_name, *seat_name;
890         Manager *m = userdata;
891         Session *session;
892         Seat *seat;
893         int r;
894
895         assert(message);
896         assert(m);
897
898         /* Same as ActivateSession() but refuses to work if
899          * the seat doesn't match */
900
901         r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
902         if (r < 0)
903                 return r;
904
905         r = manager_get_session_from_creds(m, message, session_name, error, &session);
906         if (r < 0)
907                 return r;
908
909         r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
910         if (r < 0)
911                 return r;
912
913         if (session->seat != seat)
914                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
915
916         r = session_activate(session);
917         if (r < 0)
918                 return r;
919
920         return sd_bus_reply_method_return(message, NULL);
921 }
922
923 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
924         Manager *m = userdata;
925         Session *session;
926         const char *name;
927         int r;
928
929         assert(message);
930         assert(m);
931
932         r = sd_bus_message_read(message, "s", &name);
933         if (r < 0)
934                 return r;
935
936         r = manager_get_session_from_creds(m, message, name, error, &session);
937         if (r < 0)
938                 return r;
939
940         return bus_session_method_lock(message, session, error);
941 }
942
943 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
944         Manager *m = userdata;
945         int r;
946
947         assert(message);
948         assert(m);
949
950         r = bus_verify_polkit_async(
951                         message,
952                         CAP_SYS_ADMIN,
953                         "org.freedesktop.login1.lock-sessions",
954                         NULL,
955                         false,
956                         UID_INVALID,
957                         &m->polkit_registry,
958                         error);
959         if (r < 0)
960                 return r;
961         if (r == 0)
962                 return 1; /* Will call us back */
963
964         r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
965         if (r < 0)
966                 return r;
967
968         return sd_bus_reply_method_return(message, NULL);
969 }
970
971 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
972         const char *name;
973         Manager *m = userdata;
974         Session *session;
975         int r;
976
977         assert(message);
978         assert(m);
979
980         r = sd_bus_message_read(message, "s", &name);
981         if (r < 0)
982                 return r;
983
984         r = manager_get_session_from_creds(m, message, name, error, &session);
985         if (r < 0)
986                 return r;
987
988         return bus_session_method_kill(message, session, error);
989 }
990
991 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
992         Manager *m = userdata;
993         uint32_t uid;
994         User *user;
995         int r;
996
997         assert(message);
998         assert(m);
999
1000         r = sd_bus_message_read(message, "u", &uid);
1001         if (r < 0)
1002                 return r;
1003
1004         r = manager_get_user_from_creds(m, message, uid, error, &user);
1005         if (r < 0)
1006                 return r;
1007
1008         return bus_user_method_kill(message, user, error);
1009 }
1010
1011 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1012         Manager *m = userdata;
1013         const char *name;
1014         Session *session;
1015         int r;
1016
1017         assert(message);
1018         assert(m);
1019
1020         r = sd_bus_message_read(message, "s", &name);
1021         if (r < 0)
1022                 return r;
1023
1024         r = manager_get_session_from_creds(m, message, name, error, &session);
1025         if (r < 0)
1026                 return r;
1027
1028         return bus_session_method_terminate(message, session, error);
1029 }
1030
1031 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1032         Manager *m = userdata;
1033         uint32_t uid;
1034         User *user;
1035         int r;
1036
1037         assert(message);
1038         assert(m);
1039
1040         r = sd_bus_message_read(message, "u", &uid);
1041         if (r < 0)
1042                 return r;
1043
1044         r = manager_get_user_from_creds(m, message, uid, error, &user);
1045         if (r < 0)
1046                 return r;
1047
1048         return bus_user_method_terminate(message, user, error);
1049 }
1050
1051 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1052         Manager *m = userdata;
1053         const char *name;
1054         Seat *seat;
1055         int r;
1056
1057         assert(message);
1058         assert(m);
1059
1060         r = sd_bus_message_read(message, "s", &name);
1061         if (r < 0)
1062                 return r;
1063
1064         r = manager_get_seat_from_creds(m, message, name, error, &seat);
1065         if (r < 0)
1066                 return r;
1067
1068         return bus_seat_method_terminate(message, seat, error);
1069 }
1070
1071 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1072         _cleanup_free_ char *cc = NULL;
1073         Manager *m = userdata;
1074         int b, r;
1075         struct passwd *pw;
1076         const char *path;
1077         uint32_t uid;
1078         int interactive;
1079
1080         assert(message);
1081         assert(m);
1082
1083         r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1084         if (r < 0)
1085                 return r;
1086
1087         if (uid == UID_INVALID) {
1088                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1089
1090                 /* Note that we get the owner UID of the session, not the actual client UID here! */
1091                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1092                 if (r < 0)
1093                         return r;
1094
1095                 r = sd_bus_creds_get_owner_uid(creds, &uid);
1096                 if (r < 0)
1097                         return r;
1098         }
1099
1100         errno = 0;
1101         pw = getpwuid(uid);
1102         if (!pw)
1103                 return errno ? -errno : -ENOENT;
1104
1105         r = bus_verify_polkit_async(
1106                         message,
1107                         CAP_SYS_ADMIN,
1108                         "org.freedesktop.login1.set-user-linger",
1109                         NULL,
1110                         interactive,
1111                         UID_INVALID,
1112                         &m->polkit_registry,
1113                         error);
1114         if (r < 0)
1115                 return r;
1116         if (r == 0)
1117                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1118
1119         mkdir_p_label("/var/lib/systemd", 0755);
1120
1121         r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1122         if (r < 0)
1123                 return r;
1124
1125         cc = cescape(pw->pw_name);
1126         if (!cc)
1127                 return -ENOMEM;
1128
1129         path = strjoina("/var/lib/systemd/linger/", cc);
1130         if (b) {
1131                 User *u;
1132
1133                 r = touch(path);
1134                 if (r < 0)
1135                         return r;
1136
1137                 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1138                         user_start(u);
1139
1140         } else {
1141                 User *u;
1142
1143                 r = unlink(path);
1144                 if (r < 0 && errno != ENOENT)
1145                         return -errno;
1146
1147                 u = hashmap_get(m->users, UID_TO_PTR(uid));
1148                 if (u)
1149                         user_add_to_gc_queue(u);
1150         }
1151
1152         return sd_bus_reply_method_return(message, NULL);
1153 }
1154
1155 static int trigger_device(Manager *m, struct udev_device *d) {
1156         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1157         struct udev_list_entry *first, *item;
1158         int r;
1159
1160         assert(m);
1161
1162         e = udev_enumerate_new(m->udev);
1163         if (!e)
1164                 return -ENOMEM;
1165
1166         if (d) {
1167                 r = udev_enumerate_add_match_parent(e, d);
1168                 if (r < 0)
1169                         return r;
1170         }
1171
1172         r = udev_enumerate_scan_devices(e);
1173         if (r < 0)
1174                 return r;
1175
1176         first = udev_enumerate_get_list_entry(e);
1177         udev_list_entry_foreach(item, first) {
1178                 _cleanup_free_ char *t = NULL;
1179                 const char *p;
1180
1181                 p = udev_list_entry_get_name(item);
1182
1183                 t = strappend(p, "/uevent");
1184                 if (!t)
1185                         return -ENOMEM;
1186
1187                 write_string_file(t, "change");
1188         }
1189
1190         return 0;
1191 }
1192
1193 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1194         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1195         _cleanup_free_ char *rule = NULL, *file = NULL;
1196         const char *id_for_seat;
1197         int r;
1198
1199         assert(m);
1200         assert(seat);
1201         assert(sysfs);
1202
1203         d = udev_device_new_from_syspath(m->udev, sysfs);
1204         if (!d)
1205                 return -ENODEV;
1206
1207         if (!udev_device_has_tag(d, "seat"))
1208                 return -ENODEV;
1209
1210         id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1211         if (!id_for_seat)
1212                 return -ENODEV;
1213
1214         if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1215                 return -ENOMEM;
1216
1217         if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1218                 return -ENOMEM;
1219
1220         mkdir_p_label("/etc/udev/rules.d", 0755);
1221         mac_selinux_init("/etc");
1222         r = write_string_file_atomic_label(file, rule);
1223         if (r < 0)
1224                 return r;
1225
1226         return trigger_device(m, d);
1227 }
1228
1229 static int flush_devices(Manager *m) {
1230         _cleanup_closedir_ DIR *d;
1231
1232         assert(m);
1233
1234         d = opendir("/etc/udev/rules.d");
1235         if (!d) {
1236                 if (errno != ENOENT)
1237                         log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1238         } else {
1239                 struct dirent *de;
1240
1241                 while ((de = readdir(d))) {
1242
1243                         if (!dirent_is_file(de))
1244                                 continue;
1245
1246                         if (!startswith(de->d_name, "72-seat-"))
1247                                 continue;
1248
1249                         if (!endswith(de->d_name, ".rules"))
1250                                 continue;
1251
1252                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1253                                 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1254                 }
1255         }
1256
1257         return trigger_device(m, NULL);
1258 }
1259
1260 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1261         const char *sysfs, *seat;
1262         Manager *m = userdata;
1263         int interactive, r;
1264
1265         assert(message);
1266         assert(m);
1267
1268         r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1269         if (r < 0)
1270                 return r;
1271
1272         if (!path_startswith(sysfs, "/sys"))
1273                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1274
1275         if (!seat_name_is_valid(seat))
1276                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1277
1278         r = bus_verify_polkit_async(
1279                         message,
1280                         CAP_SYS_ADMIN,
1281                         "org.freedesktop.login1.attach-device",
1282                         NULL,
1283                         interactive,
1284                         UID_INVALID,
1285                         &m->polkit_registry,
1286                         error);
1287         if (r < 0)
1288                 return r;
1289         if (r == 0)
1290                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1291
1292         r = attach_device(m, seat, sysfs);
1293         if (r < 0)
1294                 return r;
1295
1296         return sd_bus_reply_method_return(message, NULL);
1297 }
1298
1299 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1300         Manager *m = userdata;
1301         int interactive, r;
1302
1303         assert(message);
1304         assert(m);
1305
1306         r = sd_bus_message_read(message, "b", &interactive);
1307         if (r < 0)
1308                 return r;
1309
1310         r = bus_verify_polkit_async(
1311                         message,
1312                         CAP_SYS_ADMIN,
1313                         "org.freedesktop.login1.flush-devices",
1314                         NULL,
1315                         interactive,
1316                         UID_INVALID,
1317                         &m->polkit_registry,
1318                         error);
1319         if (r < 0)
1320                 return r;
1321         if (r == 0)
1322                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1323
1324         r = flush_devices(m);
1325         if (r < 0)
1326                 return r;
1327
1328         return sd_bus_reply_method_return(message, NULL);
1329 }
1330
1331 static int have_multiple_sessions(
1332                 Manager *m,
1333                 uid_t uid) {
1334
1335         Session *session;
1336         Iterator i;
1337
1338         assert(m);
1339
1340         /* Check for other users' sessions. Greeter sessions do not
1341          * count, and non-login sessions do not count either. */
1342         HASHMAP_FOREACH(session, m->sessions, i)
1343                 if (session->class == SESSION_USER &&
1344                     session->user->uid != uid)
1345                         return true;
1346
1347         return false;
1348 }
1349
1350 static int bus_manager_log_shutdown(
1351                 Manager *m,
1352                 InhibitWhat w,
1353                 HandleAction action) {
1354
1355         const char *p, *q;
1356
1357         assert(m);
1358
1359         if (w != INHIBIT_SHUTDOWN)
1360                 return 0;
1361
1362         switch (action) {
1363         case HANDLE_POWEROFF:
1364                 p = "MESSAGE=System is powering down.";
1365                 q = "SHUTDOWN=power-off";
1366                 break;
1367         case HANDLE_HALT:
1368                 p = "MESSAGE=System is halting.";
1369                 q = "SHUTDOWN=halt";
1370                 break;
1371         case HANDLE_REBOOT:
1372                 p = "MESSAGE=System is rebooting.";
1373                 q = "SHUTDOWN=reboot";
1374                 break;
1375         case HANDLE_KEXEC:
1376                 p = "MESSAGE=System is rebooting with kexec.";
1377                 q = "SHUTDOWN=kexec";
1378                 break;
1379         default:
1380                 p = "MESSAGE=System is shutting down.";
1381                 q = NULL;
1382         }
1383
1384         if (!isempty(m->wall_message))
1385                 p = strjoina(p, " (", m->wall_message, ")");
1386
1387         return log_struct(LOG_NOTICE,
1388                           LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1389                           p,
1390                           q,
1391                           NULL);
1392 }
1393
1394 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1395         Manager *m = userdata;
1396
1397         assert(e);
1398         assert(m);
1399
1400         m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1401         return 0;
1402 }
1403
1404 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1405         int r;
1406
1407         assert(m);
1408
1409         if (until <= now(CLOCK_MONOTONIC))
1410                 return 0;
1411
1412         /* We want to ignore the lid switch for a while after each
1413          * suspend, and after boot-up. Hence let's install a timer for
1414          * this. As long as the event source exists we ignore the lid
1415          * switch. */
1416
1417         if (m->lid_switch_ignore_event_source) {
1418                 usec_t u;
1419
1420                 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1421                 if (r < 0)
1422                         return r;
1423
1424                 if (until <= u)
1425                         return 0;
1426
1427                 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1428         } else
1429                 r = sd_event_add_time(
1430                                 m->event,
1431                                 &m->lid_switch_ignore_event_source,
1432                                 CLOCK_MONOTONIC,
1433                                 until, 0,
1434                                 lid_switch_ignore_handler, m);
1435
1436         return r;
1437 }
1438
1439 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1440
1441         static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1442                 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1443                 [INHIBIT_SLEEP] = "PrepareForSleep"
1444         };
1445
1446         int active = _active;
1447
1448         assert(m);
1449         assert(w >= 0);
1450         assert(w < _INHIBIT_WHAT_MAX);
1451         assert(signal_name[w]);
1452
1453         return sd_bus_emit_signal(m->bus,
1454                                   "/org/freedesktop/login1",
1455                                   "org.freedesktop.login1.Manager",
1456                                   signal_name[w],
1457                                   "b",
1458                                   active);
1459 }
1460
1461 static int execute_shutdown_or_sleep(
1462                 Manager *m,
1463                 InhibitWhat w,
1464                 HandleAction action,
1465                 sd_bus_error *error) {
1466
1467 /// elogind does not need these, we do it ourselves
1468 #if 0
1469         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1470         const char *p;
1471         char *c;
1472 #endif // 0
1473         int r;
1474
1475         assert(m);
1476         assert(w >= 0);
1477         assert(w < _INHIBIT_WHAT_MAX);
1478
1479         bus_manager_log_shutdown(m, w, action);
1480
1481 /// elogind does it directly without depending on systemd running the system
1482 #if 0
1483         r = sd_bus_call_method(
1484                         m->bus,
1485                         "org.freedesktop.systemd1",
1486                         "/org/freedesktop/systemd1",
1487                         "org.freedesktop.systemd1.Manager",
1488                         "StartUnit",
1489                         error,
1490                         &reply,
1491                         "ss", NULL, "replace-irreversibly");
1492 #else
1493         r = shutdown_or_sleep(m, action);
1494 #endif // 0
1495         if (r < 0)
1496                 return r;
1497
1498 /// elogind neither needs a dbus reply, nor supports systemd action jobs
1499 #if 0
1500         r = sd_bus_message_read(reply, "o", &p);
1501         if (r < 0)
1502                 return r;
1503
1504         c = strdup(p);
1505         if (!c)
1506                 return -ENOMEM;
1507
1508         m->action_unit = unit_name;
1509         free(m->action_job);
1510         m->action_job = c;
1511         m->action_what = w;
1512 #endif // 0
1513
1514         if (w == INHIBIT_SLEEP)
1515                 /* And we're back. */
1516                 send_prepare_for(m, w, false);
1517
1518         m->action_what = 0;
1519
1520         /* Make sure the lid switch is ignored for a while */
1521         manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1522
1523         return 0;
1524 }
1525
1526 static int manager_inhibit_timeout_handler(
1527                         sd_event_source *s,
1528                         uint64_t usec,
1529                         void *userdata) {
1530
1531         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1532         Inhibitor *offending = NULL;
1533         Manager *manager = userdata;
1534         int r;
1535
1536         assert(manager);
1537         assert(manager->inhibit_timeout_source == s);
1538
1539         if (manager->action_what == 0)
1540                 return 0;
1541
1542         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1543                 _cleanup_free_ char *comm = NULL, *u = NULL;
1544
1545                 (void) get_process_comm(offending->pid, &comm);
1546                 u = uid_to_name(offending->uid);
1547
1548                 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1549                            offending->uid, strna(u),
1550                            offending->pid, strna(comm));
1551         }
1552
1553         /* Actually do the operation */
1554         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1555         if (r < 0) {
1556                 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1557
1558                 manager->pending_action = HANDLE_IGNORE;
1559                 manager->action_what    = 0;
1560         }
1561
1562         return 0;
1563 }
1564
1565 static int delay_shutdown_or_sleep(
1566                 Manager *m,
1567                 InhibitWhat w,
1568                 HandleAction action) {
1569
1570         int r;
1571         usec_t timeout_val;
1572
1573         assert(m);
1574         assert(w >= 0);
1575         assert(w < _INHIBIT_WHAT_MAX);
1576
1577         timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1578
1579         if (m->inhibit_timeout_source) {
1580                 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1581                 if (r < 0)
1582                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1583
1584                 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1585                 if (r < 0)
1586                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1587         } else {
1588                 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1589                                       timeout_val, 0, manager_inhibit_timeout_handler, m);
1590                 if (r < 0)
1591                         return r;
1592         }
1593
1594         m->pending_action = action;
1595         m->action_what = w;
1596
1597         return 0;
1598 }
1599
1600 int bus_manager_shutdown_or_sleep_now_or_later(
1601                 Manager *m,
1602                 HandleAction action,
1603                 InhibitWhat w,
1604                 sd_bus_error *error) {
1605
1606         bool delayed;
1607         int r;
1608
1609         assert(m);
1610         assert(w >= 0);
1611         assert(w <= _INHIBIT_WHAT_MAX);
1612
1613         /* Tell everybody to prepare for shutdown/sleep */
1614         send_prepare_for(m, w, true);
1615
1616         delayed =
1617                 m->inhibit_delay_max > 0 &&
1618                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1619
1620         if (delayed)
1621                 /* Shutdown is delayed, keep in mind what we
1622                  * want to do, and start a timeout */
1623                 r = delay_shutdown_or_sleep(m, w, action);
1624         else
1625                 /* Shutdown is not delayed, execute it
1626                  * immediately */
1627                 r = execute_shutdown_or_sleep(m, w, action, error);
1628
1629         return r;
1630 }
1631
1632 static int verify_shutdown_creds(
1633                 Manager *m,
1634                 sd_bus_message *message,
1635                 InhibitWhat w,
1636                 bool interactive,
1637                 const char *action,
1638                 const char *action_multiple_sessions,
1639                 const char *action_ignore_inhibit,
1640                 sd_bus_error *error) {
1641
1642         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1643         bool multiple_sessions, blocked;
1644         uid_t uid;
1645         int r;
1646
1647         assert(m);
1648         assert(message);
1649         assert(w >= 0);
1650         assert(w <= _INHIBIT_WHAT_MAX);
1651
1652         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1653         if (r < 0)
1654                 return r;
1655
1656         r = sd_bus_creds_get_euid(creds, &uid);
1657         if (r < 0)
1658                 return r;
1659
1660         r = have_multiple_sessions(m, uid);
1661         if (r < 0)
1662                 return r;
1663
1664         multiple_sessions = r > 0;
1665         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1666
1667         if (multiple_sessions && action_multiple_sessions) {
1668                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1669                 if (r < 0)
1670                         return r;
1671                 if (r == 0)
1672                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1673         }
1674
1675         if (blocked && action_ignore_inhibit) {
1676                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1677                 if (r < 0)
1678                         return r;
1679                 if (r == 0)
1680                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1681         }
1682
1683         if (!multiple_sessions && !blocked && action) {
1684                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1685                 if (r < 0)
1686                         return r;
1687                 if (r == 0)
1688                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1689         }
1690
1691         return 0;
1692 }
1693
1694 static int method_do_shutdown_or_sleep(
1695                 Manager *m,
1696                 sd_bus_message *message,
1697                 HandleAction sleep_action,
1698                 InhibitWhat w,
1699                 const char *action,
1700                 const char *action_multiple_sessions,
1701                 const char *action_ignore_inhibit,
1702                 const char *sleep_verb,
1703                 sd_bus_error *error) {
1704
1705         int interactive, r;
1706
1707         assert(m);
1708         assert(message);
1709         assert(w >= 0);
1710         assert(w <= _INHIBIT_WHAT_MAX);
1711
1712         r = sd_bus_message_read(message, "b", &interactive);
1713         if (r < 0)
1714                 return r;
1715
1716         /* Don't allow multiple jobs being executed at the same time */
1717         if (m->action_what)
1718                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1719
1720         if (sleep_verb) {
1721                 r = can_sleep(sleep_verb);
1722                 if (r < 0)
1723                         return r;
1724
1725                 if (r == 0)
1726                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1727         }
1728
1729         r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1730                                   action_ignore_inhibit, error);
1731         if (r != 0)
1732                 return r;
1733
1734         r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
1735         if (r < 0)
1736                 return r;
1737
1738         return sd_bus_reply_method_return(message, NULL);
1739 }
1740
1741 static int method_poweroff(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                         HANDLE_POWEROFF,
1747                         INHIBIT_SHUTDOWN,
1748                         "org.freedesktop.login1.power-off",
1749                         "org.freedesktop.login1.power-off-multiple-sessions",
1750                         "org.freedesktop.login1.power-off-ignore-inhibit",
1751                         NULL,
1752                         error);
1753 }
1754
1755 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1756         Manager *m = userdata;
1757
1758         return method_do_shutdown_or_sleep(
1759                         m, message,
1760                         HANDLE_REBOOT,
1761                         INHIBIT_SHUTDOWN,
1762                         "org.freedesktop.login1.reboot",
1763                         "org.freedesktop.login1.reboot-multiple-sessions",
1764                         "org.freedesktop.login1.reboot-ignore-inhibit",
1765                         NULL,
1766                         error);
1767 }
1768
1769 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1770         Manager *m = userdata;
1771
1772         return method_do_shutdown_or_sleep(
1773                         m, message,
1774                         HANDLE_SUSPEND,
1775                         INHIBIT_SLEEP,
1776                         "org.freedesktop.login1.suspend",
1777                         "org.freedesktop.login1.suspend-multiple-sessions",
1778                         "org.freedesktop.login1.suspend-ignore-inhibit",
1779                         "suspend",
1780                         error);
1781 }
1782
1783 static int nologin_timeout_handler(
1784                         sd_event_source *s,
1785                         uint64_t usec,
1786                         void *userdata) {
1787
1788         Manager *m = userdata;
1789         int r;
1790
1791         log_info("Creating /run/nologin, blocking further logins...");
1792
1793         r = write_string_file_atomic("/run/nologin", "System is going down.");
1794         if (r < 0)
1795                 log_error_errno(r, "Failed to create /run/nologin: %m");
1796         else
1797                 m->unlink_nologin = true;
1798
1799         return 0;
1800 }
1801
1802 static int update_schedule_file(Manager *m) {
1803         _cleanup_free_ char *temp_path = NULL;
1804         _cleanup_fclose_ FILE *f = NULL;
1805         int r;
1806
1807         assert(m);
1808
1809         r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1810         if (r < 0)
1811                 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1812
1813         r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1814         if (r < 0)
1815                 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1816
1817         (void) fchmod(fileno(f), 0644);
1818
1819         fprintf(f,
1820                 "USEC="USEC_FMT"\n"
1821                 "WARN_WALL=%i\n"
1822                 "MODE=%s\n",
1823                 m->scheduled_shutdown_timeout,
1824                 m->enable_wall_messages,
1825                 m->scheduled_shutdown_type);
1826
1827         if (!isempty(m->wall_message)) {
1828                 _cleanup_free_ char *t;
1829
1830                 t = cescape(m->wall_message);
1831                 if (!t) {
1832                         r = -ENOMEM;
1833                         goto fail;
1834                 }
1835
1836                 fprintf(f, "WALL_MESSAGE=%s\n", t);
1837         }
1838
1839         r = fflush_and_check(f);
1840         if (r < 0)
1841                 goto fail;
1842
1843         if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1844                 r = -errno;
1845                 goto fail;
1846         }
1847
1848         return 0;
1849
1850 fail:
1851                 (void) unlink(temp_path);
1852                 (void) unlink("/run/systemd/shutdown/scheduled");
1853
1854         return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
1855 }
1856
1857 static int manager_scheduled_shutdown_handler(
1858                         sd_event_source *s,
1859                         uint64_t usec,
1860                         void *userdata) {
1861
1862         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1863         Manager *m = userdata;
1864         HandleAction action;
1865         int r;
1866
1867         assert(m);
1868
1869         if (isempty(m->scheduled_shutdown_type))
1870                 return 0;
1871
1872         if (streq(m->scheduled_shutdown_type, "halt"))
1873                 action = HANDLE_HALT;
1874         else if (streq(m->scheduled_shutdown_type, "poweroff"))
1875                 action = HANDLE_POWEROFF;
1876         else
1877                 action = HANDLE_REBOOT;
1878
1879         r = execute_shutdown_or_sleep(m, 0, action, &error);
1880         if (r < 0)
1881                 return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
1882
1883         return 0;
1884 }
1885
1886 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1887         Manager *m = userdata;
1888         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1889         const char *action_multiple_sessions = NULL;
1890         const char *action_ignore_inhibit = NULL;
1891         const char *action = NULL;
1892         uint64_t elapse;
1893         char *type;
1894         int r;
1895
1896         assert(m);
1897         assert(message);
1898
1899         r = sd_bus_message_read(message, "st", &type, &elapse);
1900         if (r < 0)
1901                 return r;
1902
1903         if (streq(type, "reboot")) {
1904                 action = "org.freedesktop.login1.reboot";
1905                 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1906                 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1907         } else if (streq(type, "halt")) {
1908                 action = "org.freedesktop.login1.halt";
1909                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1910                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1911         } else if (streq(type, "poweroff")) {
1912                 action = "org.freedesktop.login1.poweroff";
1913                 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1914                 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1915         } else
1916                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1917
1918         r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1919                                   action, action_multiple_sessions, action_ignore_inhibit, error);
1920         if (r != 0)
1921                 return r;
1922
1923         if (m->scheduled_shutdown_timeout_source) {
1924                 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1925                 if (r < 0)
1926                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1927
1928                 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1929                 if (r < 0)
1930                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1931         } else {
1932                 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1933                                       CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1934                 if (r < 0)
1935                         return log_error_errno(r, "sd_event_add_time() failed: %m");
1936         }
1937
1938         r = free_and_strdup(&m->scheduled_shutdown_type, type);
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         if (m->nologin_timeout_source) {
1945                 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
1946                 if (r < 0)
1947                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1948
1949                 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
1950                 if (r < 0)
1951                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1952         } else {
1953                 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
1954                                       CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
1955                 if (r < 0)
1956                         return log_error_errno(r, "sd_event_add_time() failed: %m");
1957         }
1958
1959         m->scheduled_shutdown_timeout = elapse;
1960
1961         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1962         if (r >= 0) {
1963                 const char *tty;
1964
1965                 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
1966                 (void) sd_bus_creds_get_tty(creds, &tty);
1967
1968                 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
1969                 if (r < 0) {
1970                         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1971                         return log_oom();
1972                 }
1973         }
1974
1975         r = manager_setup_wall_message_timer(m);
1976         if (r < 0)
1977                 return r;
1978
1979         if (!isempty(type)) {
1980                 r = update_schedule_file(m);
1981                 if (r < 0)
1982                         return r;
1983         } else
1984                 (void) unlink("/run/systemd/shutdown/scheduled");
1985
1986         return sd_bus_reply_method_return(message, NULL);
1987 }
1988
1989 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1990         Manager *m = userdata;
1991         bool cancelled;
1992
1993         assert(m);
1994         assert(message);
1995
1996         cancelled = m->scheduled_shutdown_type != NULL;
1997
1998         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1999         m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2000         m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2001         free(m->scheduled_shutdown_type);
2002         m->scheduled_shutdown_type = NULL;
2003         m->scheduled_shutdown_timeout = 0;
2004
2005         if (cancelled) {
2006                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2007                 const char *tty = NULL;
2008                 uid_t uid = 0;
2009                 int r;
2010
2011                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2012                 if (r >= 0) {
2013                         (void) sd_bus_creds_get_uid(creds, &uid);
2014                         (void) sd_bus_creds_get_tty(creds, &tty);
2015                 }
2016
2017                 utmp_wall("The system shutdown has been cancelled",
2018                           lookup_uid(uid), tty, logind_wall_tty_filter, m);
2019         }
2020
2021         return sd_bus_reply_method_return(message, "b", cancelled);
2022 }
2023
2024 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2025         Manager *m = userdata;
2026
2027         return method_do_shutdown_or_sleep(
2028                         m, message,
2029                         HANDLE_HIBERNATE,
2030                         INHIBIT_SLEEP,
2031                         "org.freedesktop.login1.hibernate",
2032                         "org.freedesktop.login1.hibernate-multiple-sessions",
2033                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2034                         "hibernate",
2035                         error);
2036 }
2037
2038 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2039         Manager *m = userdata;
2040
2041         return method_do_shutdown_or_sleep(
2042                         m, message,
2043                         HANDLE_HYBRID_SLEEP,
2044                         INHIBIT_SLEEP,
2045                         "org.freedesktop.login1.hibernate",
2046                         "org.freedesktop.login1.hibernate-multiple-sessions",
2047                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2048                         "hybrid-sleep",
2049                         error);
2050 }
2051
2052 static int method_can_shutdown_or_sleep(
2053                 Manager *m,
2054                 sd_bus_message *message,
2055                 InhibitWhat w,
2056                 const char *action,
2057                 const char *action_multiple_sessions,
2058                 const char *action_ignore_inhibit,
2059                 const char *sleep_verb,
2060                 sd_bus_error *error) {
2061
2062         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2063         bool multiple_sessions, challenge, blocked;
2064         const char *result = NULL;
2065         uid_t uid;
2066         int r;
2067
2068         assert(m);
2069         assert(message);
2070         assert(w >= 0);
2071         assert(w <= _INHIBIT_WHAT_MAX);
2072         assert(action);
2073         assert(action_multiple_sessions);
2074         assert(action_ignore_inhibit);
2075
2076         if (sleep_verb) {
2077                 r = can_sleep(sleep_verb);
2078                 if (r < 0)
2079                         return r;
2080                 if (r == 0)
2081                         return sd_bus_reply_method_return(message, "s", "na");
2082         }
2083
2084         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2085         if (r < 0)
2086                 return r;
2087
2088         r = sd_bus_creds_get_euid(creds, &uid);
2089         if (r < 0)
2090                 return r;
2091
2092         r = have_multiple_sessions(m, uid);
2093         if (r < 0)
2094                 return r;
2095
2096         multiple_sessions = r > 0;
2097         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2098
2099         if (multiple_sessions) {
2100                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2101                 if (r < 0)
2102                         return r;
2103
2104                 if (r > 0)
2105                         result = "yes";
2106                 else if (challenge)
2107                         result = "challenge";
2108                 else
2109                         result = "no";
2110         }
2111
2112         if (blocked) {
2113                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2114                 if (r < 0)
2115                         return r;
2116
2117                 if (r > 0 && !result)
2118                         result = "yes";
2119                 else if (challenge && (!result || streq(result, "yes")))
2120                         result = "challenge";
2121                 else
2122                         result = "no";
2123         }
2124
2125         if (!multiple_sessions && !blocked) {
2126                 /* If neither inhibit nor multiple sessions
2127                  * apply then just check the normal policy */
2128
2129                 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2130                 if (r < 0)
2131                         return r;
2132
2133                 if (r > 0)
2134                         result = "yes";
2135                 else if (challenge)
2136                         result = "challenge";
2137                 else
2138                         result = "no";
2139         }
2140
2141         return sd_bus_reply_method_return(message, "s", result);
2142 }
2143
2144 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2145         Manager *m = userdata;
2146
2147         return method_can_shutdown_or_sleep(
2148                         m, message,
2149                         INHIBIT_SHUTDOWN,
2150                         "org.freedesktop.login1.power-off",
2151                         "org.freedesktop.login1.power-off-multiple-sessions",
2152                         "org.freedesktop.login1.power-off-ignore-inhibit",
2153                         NULL,
2154                         error);
2155 }
2156
2157 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2158         Manager *m = userdata;
2159
2160         return method_can_shutdown_or_sleep(
2161                         m, message,
2162                         INHIBIT_SHUTDOWN,
2163                         "org.freedesktop.login1.reboot",
2164                         "org.freedesktop.login1.reboot-multiple-sessions",
2165                         "org.freedesktop.login1.reboot-ignore-inhibit",
2166                         NULL,
2167                         error);
2168 }
2169
2170 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2171         Manager *m = userdata;
2172
2173         return method_can_shutdown_or_sleep(
2174                         m, message,
2175                         INHIBIT_SLEEP,
2176                         "org.freedesktop.login1.suspend",
2177                         "org.freedesktop.login1.suspend-multiple-sessions",
2178                         "org.freedesktop.login1.suspend-ignore-inhibit",
2179                         "suspend",
2180                         error);
2181 }
2182
2183 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2184         Manager *m = userdata;
2185
2186         return method_can_shutdown_or_sleep(
2187                         m, message,
2188                         INHIBIT_SLEEP,
2189                         "org.freedesktop.login1.hibernate",
2190                         "org.freedesktop.login1.hibernate-multiple-sessions",
2191                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2192                         "hibernate",
2193                         error);
2194 }
2195
2196 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2197         Manager *m = userdata;
2198
2199         return method_can_shutdown_or_sleep(
2200                         m, message,
2201                         INHIBIT_SLEEP,
2202                         "org.freedesktop.login1.hibernate",
2203                         "org.freedesktop.login1.hibernate-multiple-sessions",
2204                         "org.freedesktop.login1.hibernate-ignore-inhibit",
2205                         "hybrid-sleep",
2206                         error);
2207 }
2208
2209 static int property_get_reboot_to_firmware_setup(
2210                 sd_bus *bus,
2211                 const char *path,
2212                 const char *interface,
2213                 const char *property,
2214                 sd_bus_message *reply,
2215                 void *userdata,
2216                 sd_bus_error *error) {
2217         int r;
2218
2219         assert(bus);
2220         assert(reply);
2221         assert(userdata);
2222
2223         r = efi_get_reboot_to_firmware();
2224         if (r < 0 && r != -EOPNOTSUPP)
2225                 return r;
2226
2227         return sd_bus_message_append(reply, "b", r > 0);
2228 }
2229
2230 static int method_set_reboot_to_firmware_setup(
2231                 sd_bus_message *message,
2232                 void *userdata,
2233                 sd_bus_error *error) {
2234
2235         int b, r;
2236         Manager *m = userdata;
2237
2238         assert(message);
2239         assert(m);
2240
2241         r = sd_bus_message_read(message, "b", &b);
2242         if (r < 0)
2243                 return r;
2244
2245         r = bus_verify_polkit_async(message,
2246                                     CAP_SYS_ADMIN,
2247                                     "org.freedesktop.login1.set-reboot-to-firmware-setup",
2248                                     NULL,
2249                                     false,
2250                                     UID_INVALID,
2251                                     &m->polkit_registry,
2252                                     error);
2253         if (r < 0)
2254                 return r;
2255         if (r == 0)
2256                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2257
2258         r = efi_set_reboot_to_firmware(b);
2259         if (r < 0)
2260                 return r;
2261
2262         return sd_bus_reply_method_return(message, NULL);
2263 }
2264
2265 static int method_can_reboot_to_firmware_setup(
2266                 sd_bus_message *message,
2267                 void *userdata,
2268                 sd_bus_error *error) {
2269
2270         int r;
2271         bool challenge;
2272         const char *result;
2273         Manager *m = userdata;
2274
2275         assert(message);
2276         assert(m);
2277
2278         r = efi_reboot_to_firmware_supported();
2279         if (r == -EOPNOTSUPP)
2280                 return sd_bus_reply_method_return(message, "s", "na");
2281         else if (r < 0)
2282                 return r;
2283
2284         r = bus_test_polkit(message,
2285                             CAP_SYS_ADMIN,
2286                             "org.freedesktop.login1.set-reboot-to-firmware-setup",
2287                             NULL,
2288                             UID_INVALID,
2289                             &challenge,
2290                             error);
2291         if (r < 0)
2292                 return r;
2293
2294         if (r > 0)
2295                 result = "yes";
2296         else if (challenge)
2297                 result = "challenge";
2298         else
2299                 result = "no";
2300
2301         return sd_bus_reply_method_return(message, "s", result);
2302 }
2303
2304 static int method_set_wall_message(
2305                 sd_bus_message *message,
2306                 void *userdata,
2307                 sd_bus_error *error) {
2308
2309         int r;
2310         Manager *m = userdata;
2311         char *wall_message;
2312         int enable_wall_messages;
2313
2314         assert(message);
2315         assert(m);
2316
2317         r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2318         if (r < 0)
2319                 return r;
2320
2321         r = bus_verify_polkit_async(message,
2322                                     CAP_SYS_ADMIN,
2323                                     "org.freedesktop.login1.set-wall-message",
2324                                     NULL,
2325                                     false,
2326                                     UID_INVALID,
2327                                     &m->polkit_registry,
2328                                     error);
2329         if (r < 0)
2330                 return r;
2331         if (r == 0)
2332                 return 1; /* Will call us back */
2333
2334         if (isempty(wall_message))
2335                 m->wall_message = mfree(m->wall_message);
2336         else {
2337                 r = free_and_strdup(&m->wall_message, wall_message);
2338                 if (r < 0)
2339                         return log_oom();
2340         }
2341
2342         m->enable_wall_messages = enable_wall_messages;
2343
2344         return sd_bus_reply_method_return(message, NULL);
2345 }
2346
2347 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2348         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2349         const char *who, *why, *what, *mode;
2350         _cleanup_free_ char *id = NULL;
2351         _cleanup_close_ int fifo_fd = -1;
2352         Manager *m = userdata;
2353         Inhibitor *i = NULL;
2354         InhibitMode mm;
2355         InhibitWhat w;
2356         pid_t pid;
2357         uid_t uid;
2358         int r;
2359
2360         assert(message);
2361         assert(m);
2362
2363         r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2364         if (r < 0)
2365                 return r;
2366
2367         w = inhibit_what_from_string(what);
2368         if (w <= 0)
2369                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2370
2371         mm = inhibit_mode_from_string(mode);
2372         if (mm < 0)
2373                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2374
2375         /* Delay is only supported for shutdown/sleep */
2376         if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2377                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2378
2379         /* Don't allow taking delay locks while we are already
2380          * executing the operation. We shouldn't create the impression
2381          * that the lock was successful if the machine is about to go
2382          * down/suspend any moment. */
2383         if (m->action_what & w)
2384                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2385
2386         r = bus_verify_polkit_async(
2387                         message,
2388                         CAP_SYS_BOOT,
2389                         w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2390                         w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
2391                         w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
2392                         w == INHIBIT_HANDLE_POWER_KEY     ? "org.freedesktop.login1.inhibit-handle-power-key" :
2393                         w == INHIBIT_HANDLE_SUSPEND_KEY   ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2394                         w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2395                                                             "org.freedesktop.login1.inhibit-handle-lid-switch",
2396                         NULL,
2397                         false,
2398                         UID_INVALID,
2399                         &m->polkit_registry,
2400                         error);
2401         if (r < 0)
2402                 return r;
2403         if (r == 0)
2404                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2405
2406         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2407         if (r < 0)
2408                 return r;
2409
2410         r = sd_bus_creds_get_euid(creds, &uid);
2411         if (r < 0)
2412                 return r;
2413
2414         r = sd_bus_creds_get_pid(creds, &pid);
2415         if (r < 0)
2416                 return r;
2417
2418         do {
2419                 id = mfree(id);
2420
2421                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2422                         return -ENOMEM;
2423
2424         } while (hashmap_get(m->inhibitors, id));
2425
2426         r = manager_add_inhibitor(m, id, &i);
2427         if (r < 0)
2428                 return r;
2429
2430         i->what = w;
2431         i->mode = mm;
2432         i->pid = pid;
2433         i->uid = uid;
2434         i->why = strdup(why);
2435         i->who = strdup(who);
2436
2437         if (!i->why || !i->who) {
2438                 r = -ENOMEM;
2439                 goto fail;
2440         }
2441
2442         fifo_fd = inhibitor_create_fifo(i);
2443         if (fifo_fd < 0) {
2444                 r = fifo_fd;
2445                 goto fail;
2446         }
2447
2448         inhibitor_start(i);
2449
2450         return sd_bus_reply_method_return(message, "h", fifo_fd);
2451
2452 fail:
2453         if (i)
2454                 inhibitor_free(i);
2455
2456         return r;
2457 }
2458
2459 const sd_bus_vtable manager_vtable[] = {
2460         SD_BUS_VTABLE_START(0),
2461
2462         SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2463         SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2464
2465 //        SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2466         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2467         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2468         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2469         SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2470         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2471         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2472         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2473         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2474         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2475         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2476         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2477         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2478         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2479         SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2480         SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2481         SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2482         SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2483         SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2484         SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2485         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2486         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2487
2488         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2489         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2490         SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2491         SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2492         SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2493         SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2494         SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2495         SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2496         SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2497         SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2498         SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2499         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2500         SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2501         SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2502         SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2503         SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2504         SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2505         SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2506         SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2507         SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2508         SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2509         SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2510         SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2511         SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2512         SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2513         SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2514         SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2515         SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2516         SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2517         SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2518         SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2519         SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2520         SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2521         SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2522         SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2523         SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2524         SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2525         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2526         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2527         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2528         SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2529
2530         SD_BUS_SIGNAL("SessionNew", "so", 0),
2531         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2532         SD_BUS_SIGNAL("UserNew", "uo", 0),
2533         SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2534         SD_BUS_SIGNAL("SeatNew", "so", 0),
2535         SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2536         SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2537         SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2538
2539         SD_BUS_VTABLE_END
2540 };
2541
2542 /// UNNEEDED by elogind
2543 #if 0
2544 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2545         int r = 0;
2546
2547         assert(s);
2548         assert(unit);
2549
2550         if (!s->started)
2551                 return r;
2552
2553         if (streq(result, "done"))
2554                 r = session_send_create_reply(s, NULL);
2555         else {
2556                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2557
2558                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2559                 r = session_send_create_reply(s, &e);
2560         }
2561
2562         return r;
2563 }
2564
2565 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2566         const char *path, *result, *unit;
2567         Manager *m = userdata;
2568         Session *session;
2569         uint32_t id;
2570         User *user;
2571         int r;
2572
2573         assert(message);
2574         assert(m);
2575
2576         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2577         if (r < 0) {
2578                 bus_log_parse_error(r);
2579                 return 0;
2580         }
2581
2582         if (m->action_job && streq(m->action_job, path)) {
2583                 log_info("Operation finished.");
2584
2585                 /* Tell people that they now may take a lock again */
2586                 send_prepare_for(m, m->action_what, false);
2587
2588                 m->action_job = mfree(m->action_job);
2589                 m->action_unit = NULL;
2590                 m->action_what = 0;
2591                 return 0;
2592         }
2593
2594         session = hashmap_get(m->session_units, unit);
2595         if (session) {
2596
2597                 if (streq_ptr(path, session->scope_job))
2598                         session->scope_job = mfree(session->scope_job);
2599
2600                 session_jobs_reply(session, unit, result);
2601
2602                 session_save(session);
2603                 session_add_to_gc_queue(session);
2604         }
2605
2606         user = hashmap_get(m->user_units, unit);
2607         if (user) {
2608
2609                 if (streq_ptr(path, user->service_job))
2610                         user->service_job = mfree(user->service_job);
2611
2612                 if (streq_ptr(path, user->slice_job))
2613                         user->slice_job = mfree(user->slice_job);
2614
2615                 LIST_FOREACH(sessions_by_user, session, user->sessions)
2616                         session_jobs_reply(session, unit, result);
2617
2618                 user_save(user);
2619                 user_add_to_gc_queue(user);
2620         }
2621
2622         return 0;
2623 }
2624 #endif // 0
2625
2626 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2627         const char *path, *unit;
2628         Manager *m = userdata;
2629         Session *session;
2630         User *user;
2631         int r;
2632
2633         assert(message);
2634         assert(m);
2635
2636         r = sd_bus_message_read(message, "so", &unit, &path);
2637         if (r < 0) {
2638                 bus_log_parse_error(r);
2639                 return 0;
2640         }
2641
2642         session = hashmap_get(m->session_units, unit);
2643         if (session)
2644                 session_add_to_gc_queue(session);
2645
2646         user = hashmap_get(m->user_units, unit);
2647         if (user)
2648                 user_add_to_gc_queue(user);
2649
2650         return 0;
2651 }
2652
2653 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2654         _cleanup_free_ char *unit = NULL;
2655         Manager *m = userdata;
2656         const char *path;
2657         Session *session;
2658         User *user;
2659         int r;
2660
2661         assert(message);
2662         assert(m);
2663
2664         path = sd_bus_message_get_path(message);
2665         if (!path)
2666                 return 0;
2667
2668         r = unit_name_from_dbus_path(path, &unit);
2669         if (r == -EINVAL) /* not a unit */
2670                 return 0;
2671         if (r < 0) {
2672                 log_oom();
2673                 return 0;
2674         }
2675
2676         session = hashmap_get(m->session_units, unit);
2677         if (session)
2678                 session_add_to_gc_queue(session);
2679
2680         user = hashmap_get(m->user_units, unit);
2681         if (user)
2682                 user_add_to_gc_queue(user);
2683
2684         return 0;
2685 }
2686
2687 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2688         Manager *m = userdata;
2689         Session *session;
2690         Iterator i;
2691         int b, r;
2692
2693         assert(message);
2694         assert(m);
2695
2696         r = sd_bus_message_read(message, "b", &b);
2697         if (r < 0) {
2698                 bus_log_parse_error(r);
2699                 return 0;
2700         }
2701
2702         if (b)
2703                 return 0;
2704
2705         /* systemd finished reloading, let's recheck all our sessions */
2706         log_debug("System manager has been reloaded, rechecking sessions...");
2707
2708         HASHMAP_FOREACH(session, m->sessions, i)
2709                 session_add_to_gc_queue(session);
2710
2711         return 0;
2712 }
2713
2714 int manager_send_changed(Manager *manager, const char *property, ...) {
2715         char **l;
2716
2717         assert(manager);
2718
2719         l = strv_from_stdarg_alloca(property);
2720
2721         return sd_bus_emit_properties_changed_strv(
2722                         manager->bus,
2723                         "/org/freedesktop/login1",
2724                         "org.freedesktop.login1.Manager",
2725                         l);
2726 }
2727
2728 /// UNNEEDED by elogind
2729 #if 0
2730 int manager_start_scope(
2731                 Manager *manager,
2732                 const char *scope,
2733                 pid_t pid,
2734                 const char *slice,
2735                 const char *description,
2736                 const char *after, const char *after2,
2737                 sd_bus_error *error,
2738                 char **job) {
2739
2740         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2741         int r;
2742
2743         assert(manager);
2744         assert(scope);
2745         assert(pid > 1);
2746
2747         r = sd_bus_message_new_method_call(
2748                         manager->bus,
2749                         &m,
2750                         "org.freedesktop.systemd1",
2751                         "/org/freedesktop/systemd1",
2752                         "org.freedesktop.systemd1.Manager",
2753                         "StartTransientUnit");
2754         if (r < 0)
2755                 return r;
2756
2757         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2758         if (r < 0)
2759                 return r;
2760
2761         r = sd_bus_message_open_container(m, 'a', "(sv)");
2762         if (r < 0)
2763                 return r;
2764
2765         if (!isempty(slice)) {
2766                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2767                 if (r < 0)
2768                         return r;
2769         }
2770
2771         if (!isempty(description)) {
2772                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2773                 if (r < 0)
2774                         return r;
2775         }
2776
2777         if (!isempty(after)) {
2778                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2779                 if (r < 0)
2780                         return r;
2781         }
2782
2783         if (!isempty(after2)) {
2784                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2785                 if (r < 0)
2786                         return r;
2787         }
2788
2789         /* cgroup empty notification is not available in containers
2790          * currently. To make this less problematic, let's shorten the
2791          * stop timeout for sessions, so that we don't wait
2792          * forever. */
2793
2794         /* Make sure that the session shells are terminated with
2795          * SIGHUP since bash and friends tend to ignore SIGTERM */
2796         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2797         if (r < 0)
2798                 return r;
2799
2800         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2801         if (r < 0)
2802                 return r;
2803
2804         r = sd_bus_message_close_container(m);
2805         if (r < 0)
2806                 return r;
2807
2808         r = sd_bus_message_append(m, "a(sa(sv))", 0);
2809         if (r < 0)
2810                 return r;
2811
2812         r = sd_bus_call(manager->bus, m, 0, error, &reply);
2813         if (r < 0)
2814                 return r;
2815
2816         if (job) {
2817                 const char *j;
2818                 char *copy;
2819
2820                 r = sd_bus_message_read(reply, "o", &j);
2821                 if (r < 0)
2822                         return r;
2823
2824                 copy = strdup(j);
2825                 if (!copy)
2826                         return -ENOMEM;
2827
2828                 *job = copy;
2829         }
2830
2831         return 1;
2832 }
2833
2834 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2835         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2836         int r;
2837
2838         assert(manager);
2839         assert(unit);
2840
2841         r = sd_bus_call_method(
2842                         manager->bus,
2843                         "org.freedesktop.systemd1",
2844                         "/org/freedesktop/systemd1",
2845                         "org.freedesktop.systemd1.Manager",
2846                         "StartUnit",
2847                         error,
2848                         &reply,
2849                         "ss", unit, "fail");
2850         if (r < 0)
2851                 return r;
2852
2853         if (job) {
2854                 const char *j;
2855                 char *copy;
2856
2857                 r = sd_bus_message_read(reply, "o", &j);
2858                 if (r < 0)
2859                         return r;
2860
2861                 copy = strdup(j);
2862                 if (!copy)
2863                         return -ENOMEM;
2864
2865                 *job = copy;
2866         }
2867
2868         return 1;
2869 }
2870
2871 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2872         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2873         int r;
2874
2875         assert(manager);
2876         assert(unit);
2877
2878         r = sd_bus_call_method(
2879                         manager->bus,
2880                         "org.freedesktop.systemd1",
2881                         "/org/freedesktop/systemd1",
2882                         "org.freedesktop.systemd1.Manager",
2883                         "StopUnit",
2884                         error,
2885                         &reply,
2886                         "ss", unit, "fail");
2887         if (r < 0) {
2888                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2889                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2890
2891                         if (job)
2892                                 *job = NULL;
2893
2894                         sd_bus_error_free(error);
2895                         return 0;
2896                 }
2897
2898                 return r;
2899         }
2900
2901         if (job) {
2902                 const char *j;
2903                 char *copy;
2904
2905                 r = sd_bus_message_read(reply, "o", &j);
2906                 if (r < 0)
2907                         return r;
2908
2909                 copy = strdup(j);
2910                 if (!copy)
2911                         return -ENOMEM;
2912
2913                 *job = copy;
2914         }
2915
2916         return 1;
2917 }
2918
2919 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2920         _cleanup_free_ char *path = NULL;
2921         int r;
2922
2923         assert(manager);
2924         assert(scope);
2925
2926         path = unit_dbus_path_from_name(scope);
2927         if (!path)
2928                 return -ENOMEM;
2929
2930         r = sd_bus_call_method(
2931                         manager->bus,
2932                         "org.freedesktop.systemd1",
2933                         path,
2934                         "org.freedesktop.systemd1.Scope",
2935                         "Abandon",
2936                         error,
2937                         NULL,
2938                         NULL);
2939         if (r < 0) {
2940                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2941                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2942                     sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2943                         sd_bus_error_free(error);
2944                         return 0;
2945                 }
2946
2947                 return r;
2948         }
2949
2950         return 1;
2951 }
2952
2953 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2954         assert(manager);
2955         assert(unit);
2956
2957         return sd_bus_call_method(
2958                         manager->bus,
2959                         "org.freedesktop.systemd1",
2960                         "/org/freedesktop/systemd1",
2961                         "org.freedesktop.systemd1.Manager",
2962                         "KillUnit",
2963                         error,
2964                         NULL,
2965                         "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2966 }
2967
2968 int manager_unit_is_active(Manager *manager, const char *unit) {
2969         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2970         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2971         _cleanup_free_ char *path = NULL;
2972         const char *state;
2973         int r;
2974
2975         assert(manager);
2976         assert(unit);
2977
2978         path = unit_dbus_path_from_name(unit);
2979         if (!path)
2980                 return -ENOMEM;
2981
2982         r = sd_bus_get_property(
2983                         manager->bus,
2984                         "org.freedesktop.systemd1",
2985                         path,
2986                         "org.freedesktop.systemd1.Unit",
2987                         "ActiveState",
2988                         &error,
2989                         &reply,
2990                         "s");
2991         if (r < 0) {
2992                 /* systemd might have droppped off momentarily, let's
2993                  * not make this an error */
2994                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2995                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2996                         return true;
2997
2998                 /* If the unit is already unloaded then it's not
2999                  * active */
3000                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3001                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3002                         return false;
3003
3004                 return r;
3005         }
3006
3007         r = sd_bus_message_read(reply, "s", &state);
3008         if (r < 0)
3009                 return -EINVAL;
3010
3011         return !streq(state, "inactive") && !streq(state, "failed");
3012 }
3013
3014 int manager_job_is_active(Manager *manager, const char *path) {
3015         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3016         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3017         int r;
3018
3019         assert(manager);
3020         assert(path);
3021
3022         r = sd_bus_get_property(
3023                         manager->bus,
3024                         "org.freedesktop.systemd1",
3025                         path,
3026                         "org.freedesktop.systemd1.Job",
3027                         "State",
3028                         &error,
3029                         &reply,
3030                         "s");
3031         if (r < 0) {
3032                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3033                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3034                         return true;
3035
3036                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3037                         return false;
3038
3039                 return r;
3040         }
3041
3042         /* We don't actually care about the state really. The fact
3043          * that we could read the job state is enough for us */
3044
3045         return true;
3046 }
3047 #endif //