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