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