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