LCOV - code coverage report
Current view: top level - login - logind-dbus.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 1910 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 106 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 1693 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <pwd.h>
       5                 :            : #include <string.h>
       6                 :            : #include <sys/stat.h>
       7                 :            : #include <unistd.h>
       8                 :            : 
       9                 :            : #include "sd-device.h"
      10                 :            : #include "sd-messages.h"
      11                 :            : 
      12                 :            : #include "alloc-util.h"
      13                 :            : #include "audit-util.h"
      14                 :            : #include "bootspec.h"
      15                 :            : #include "bus-common-errors.h"
      16                 :            : #include "bus-error.h"
      17                 :            : #include "bus-unit-util.h"
      18                 :            : #include "bus-util.h"
      19                 :            : #include "cgroup-util.h"
      20                 :            : #include "device-util.h"
      21                 :            : #include "dirent-util.h"
      22                 :            : #include "efivars.h"
      23                 :            : #include "env-util.h"
      24                 :            : #include "escape.h"
      25                 :            : #include "fd-util.h"
      26                 :            : #include "fileio-label.h"
      27                 :            : #include "fileio.h"
      28                 :            : #include "format-util.h"
      29                 :            : #include "fs-util.h"
      30                 :            : #include "logind-dbus.h"
      31                 :            : #include "logind-seat-dbus.h"
      32                 :            : #include "logind-session-dbus.h"
      33                 :            : #include "logind-user-dbus.h"
      34                 :            : #include "logind.h"
      35                 :            : #include "missing_capability.h"
      36                 :            : #include "mkdir.h"
      37                 :            : #include "parse-util.h"
      38                 :            : #include "path-util.h"
      39                 :            : #include "process-util.h"
      40                 :            : #include "reboot-util.h"
      41                 :            : #include "selinux-util.h"
      42                 :            : #include "sleep-config.h"
      43                 :            : #include "special.h"
      44                 :            : #include "stdio-util.h"
      45                 :            : #include "strv.h"
      46                 :            : #include "terminal-util.h"
      47                 :            : #include "tmpfile-util.h"
      48                 :            : #include "unit-name.h"
      49                 :            : #include "user-util.h"
      50                 :            : #include "utmp-wtmp.h"
      51                 :            : #include "virt.h"
      52                 :            : 
      53                 :          0 : static int get_sender_session(
      54                 :            :                 Manager *m,
      55                 :            :                 sd_bus_message *message,
      56                 :            :                 bool consult_display,
      57                 :            :                 sd_bus_error *error,
      58                 :            :                 Session **ret) {
      59                 :            : 
      60                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
      61                 :          0 :         Session *session = NULL;
      62                 :            :         const char *name;
      63                 :            :         int r;
      64                 :            : 
      65                 :            :         /* Acquire the sender's session. This first checks if the sending process is inside a session itself,
      66                 :            :          * and returns that. If not and 'consult_display' is true, this returns the display session of the
      67                 :            :          * owning user of the caller. */
      68                 :            : 
      69         [ #  # ]:          0 :         r = sd_bus_query_sender_creds(message,
      70                 :            :                                       SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT|
      71                 :            :                                       (consult_display ? SD_BUS_CREDS_OWNER_UID : 0), &creds);
      72         [ #  # ]:          0 :         if (r < 0)
      73                 :          0 :                 return r;
      74                 :            : 
      75                 :          0 :         r = sd_bus_creds_get_session(creds, &name);
      76         [ #  # ]:          0 :         if (r < 0) {
      77         [ #  # ]:          0 :                 if (r != -ENXIO)
      78                 :          0 :                         return r;
      79                 :            : 
      80         [ #  # ]:          0 :                 if (consult_display) {
      81                 :            :                         uid_t uid;
      82                 :            : 
      83                 :          0 :                         r = sd_bus_creds_get_owner_uid(creds, &uid);
      84         [ #  # ]:          0 :                         if (r < 0) {
      85         [ #  # ]:          0 :                                 if (r != -ENXIO)
      86                 :          0 :                                         return r;
      87                 :            :                         } else {
      88                 :            :                                 User *user;
      89                 :            : 
      90                 :          0 :                                 user = hashmap_get(m->users, UID_TO_PTR(uid));
      91         [ #  # ]:          0 :                                 if (user)
      92                 :          0 :                                         session = user->display;
      93                 :            :                         }
      94                 :            :                 }
      95                 :            :         } else
      96                 :          0 :                 session = hashmap_get(m->sessions, name);
      97                 :            : 
      98         [ #  # ]:          0 :         if (!session)
      99         [ #  # ]:          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
     100                 :            :                                          consult_display ?
     101                 :            :                                          "Caller does not belong to any known session and doesn't own any suitable session." :
     102                 :            :                                          "Caller does not belong to any known session.");
     103                 :            : 
     104                 :          0 :         *ret = session;
     105                 :          0 :         return 0;
     106                 :            : }
     107                 :            : 
     108                 :          0 : int manager_get_session_from_creds(
     109                 :            :                 Manager *m,
     110                 :            :                 sd_bus_message *message,
     111                 :            :                 const char *name,
     112                 :            :                 sd_bus_error *error,
     113                 :            :                 Session **ret) {
     114                 :            : 
     115                 :            :         Session *session;
     116                 :            : 
     117         [ #  # ]:          0 :         assert(m);
     118         [ #  # ]:          0 :         assert(message);
     119         [ #  # ]:          0 :         assert(ret);
     120                 :            : 
     121         [ #  # ]:          0 :         if (SEAT_IS_SELF(name)) /* the caller's own session */
     122                 :          0 :                 return get_sender_session(m, message, false, error, ret);
     123         [ #  # ]:          0 :         if (SEAT_IS_AUTO(name)) /* The caller's own session if they have one, otherwise their user's display session */
     124                 :          0 :                 return get_sender_session(m, message, true, error, ret);
     125                 :            : 
     126                 :          0 :         session = hashmap_get(m->sessions, name);
     127         [ #  # ]:          0 :         if (!session)
     128                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
     129                 :            : 
     130                 :          0 :         *ret = session;
     131                 :          0 :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :          0 : static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
     135                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     136                 :            :         uid_t uid;
     137                 :            :         User *user;
     138                 :            :         int r;
     139                 :            : 
     140                 :            :         /* Note that we get the owner UID of the session, not the actual client UID here! */
     141                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
     142         [ #  # ]:          0 :         if (r < 0)
     143                 :          0 :                 return r;
     144                 :            : 
     145                 :          0 :         r = sd_bus_creds_get_owner_uid(creds, &uid);
     146         [ #  # ]:          0 :         if (r < 0) {
     147         [ #  # ]:          0 :                 if (r != -ENXIO)
     148                 :          0 :                         return r;
     149                 :            : 
     150                 :          0 :                 user = NULL;
     151                 :            :         } else
     152                 :          0 :                 user = hashmap_get(m->users, UID_TO_PTR(uid));
     153                 :            : 
     154         [ #  # ]:          0 :         if (!user)
     155                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
     156                 :            :                                          "Caller does not belong to any logged in or lingering user");
     157                 :            : 
     158                 :          0 :         *ret = user;
     159                 :          0 :         return 0;
     160                 :            : }
     161                 :            : 
     162                 :          0 : int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
     163                 :            :         User *user;
     164                 :            : 
     165         [ #  # ]:          0 :         assert(m);
     166         [ #  # ]:          0 :         assert(message);
     167         [ #  # ]:          0 :         assert(ret);
     168                 :            : 
     169         [ #  # ]:          0 :         if (!uid_is_valid(uid))
     170                 :          0 :                 return get_sender_user(m, message, error, ret);
     171                 :            : 
     172                 :          0 :         user = hashmap_get(m->users, UID_TO_PTR(uid));
     173         [ #  # ]:          0 :         if (!user)
     174                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER,
     175                 :            :                                          "User ID "UID_FMT" is not logged in or lingering", uid);
     176                 :            : 
     177                 :          0 :         *ret = user;
     178                 :          0 :         return 0;
     179                 :            : }
     180                 :            : 
     181                 :          0 : int manager_get_seat_from_creds(
     182                 :            :                 Manager *m,
     183                 :            :                 sd_bus_message *message,
     184                 :            :                 const char *name,
     185                 :            :                 sd_bus_error *error,
     186                 :            :                 Seat **ret) {
     187                 :            : 
     188                 :            :         Seat *seat;
     189                 :            :         int r;
     190                 :            : 
     191         [ #  # ]:          0 :         assert(m);
     192         [ #  # ]:          0 :         assert(message);
     193         [ #  # ]:          0 :         assert(ret);
     194                 :            : 
     195   [ #  #  #  # ]:          0 :         if (SEAT_IS_SELF(name) || SEAT_IS_AUTO(name)) {
     196                 :            :                 Session *session;
     197                 :            : 
     198                 :            :                 /* Use these special seat names as session names */
     199                 :          0 :                 r = manager_get_session_from_creds(m, message, name, error, &session);
     200         [ #  # ]:          0 :                 if (r < 0)
     201                 :          0 :                         return r;
     202                 :            : 
     203                 :          0 :                 seat = session->seat;
     204         [ #  # ]:          0 :                 if (!seat)
     205                 :          0 :                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session '%s' has no seat.", session->id);
     206                 :            :         } else {
     207                 :          0 :                 seat = hashmap_get(m->seats, name);
     208         [ #  # ]:          0 :                 if (!seat)
     209                 :          0 :                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
     210                 :            :         }
     211                 :            : 
     212                 :          0 :         *ret = seat;
     213                 :          0 :         return 0;
     214                 :            : }
     215                 :            : 
     216                 :          0 : static int return_test_polkit(
     217                 :            :                 sd_bus_message *message,
     218                 :            :                 int capability,
     219                 :            :                 const char *action,
     220                 :            :                 const char **details,
     221                 :            :                 uid_t good_user,
     222                 :            :                 sd_bus_error *e) {
     223                 :            : 
     224                 :            :         const char *result;
     225                 :            :         bool challenge;
     226                 :            :         int r;
     227                 :            : 
     228                 :          0 :         r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
     229         [ #  # ]:          0 :         if (r < 0)
     230                 :          0 :                 return r;
     231                 :            : 
     232         [ #  # ]:          0 :         if (r > 0)
     233                 :          0 :                 result = "yes";
     234         [ #  # ]:          0 :         else if (challenge)
     235                 :          0 :                 result = "challenge";
     236                 :            :         else
     237                 :          0 :                 result = "no";
     238                 :            : 
     239                 :          0 :         return sd_bus_reply_method_return(message, "s", result);
     240                 :            : }
     241                 :            : 
     242                 :          0 : static int property_get_idle_hint(
     243                 :            :                 sd_bus *bus,
     244                 :            :                 const char *path,
     245                 :            :                 const char *interface,
     246                 :            :                 const char *property,
     247                 :            :                 sd_bus_message *reply,
     248                 :            :                 void *userdata,
     249                 :            :                 sd_bus_error *error) {
     250                 :            : 
     251                 :          0 :         Manager *m = userdata;
     252                 :            : 
     253         [ #  # ]:          0 :         assert(bus);
     254         [ #  # ]:          0 :         assert(reply);
     255         [ #  # ]:          0 :         assert(m);
     256                 :            : 
     257                 :          0 :         return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
     258                 :            : }
     259                 :            : 
     260                 :          0 : static int property_get_idle_since_hint(
     261                 :            :                 sd_bus *bus,
     262                 :            :                 const char *path,
     263                 :            :                 const char *interface,
     264                 :            :                 const char *property,
     265                 :            :                 sd_bus_message *reply,
     266                 :            :                 void *userdata,
     267                 :            :                 sd_bus_error *error) {
     268                 :            : 
     269                 :          0 :         Manager *m = userdata;
     270                 :          0 :         dual_timestamp t = DUAL_TIMESTAMP_NULL;
     271                 :            : 
     272         [ #  # ]:          0 :         assert(bus);
     273         [ #  # ]:          0 :         assert(reply);
     274         [ #  # ]:          0 :         assert(m);
     275                 :            : 
     276                 :          0 :         manager_get_idle_hint(m, &t);
     277                 :            : 
     278         [ #  # ]:          0 :         return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
     279                 :            : }
     280                 :            : 
     281                 :          0 : static int property_get_inhibited(
     282                 :            :                 sd_bus *bus,
     283                 :            :                 const char *path,
     284                 :            :                 const char *interface,
     285                 :            :                 const char *property,
     286                 :            :                 sd_bus_message *reply,
     287                 :            :                 void *userdata,
     288                 :            :                 sd_bus_error *error) {
     289                 :            : 
     290                 :          0 :         Manager *m = userdata;
     291                 :            :         InhibitWhat w;
     292                 :            : 
     293         [ #  # ]:          0 :         assert(bus);
     294         [ #  # ]:          0 :         assert(reply);
     295         [ #  # ]:          0 :         assert(m);
     296                 :            : 
     297                 :          0 :         w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
     298                 :            : 
     299                 :          0 :         return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
     300                 :            : }
     301                 :            : 
     302                 :          0 : static int property_get_preparing(
     303                 :            :                 sd_bus *bus,
     304                 :            :                 const char *path,
     305                 :            :                 const char *interface,
     306                 :            :                 const char *property,
     307                 :            :                 sd_bus_message *reply,
     308                 :            :                 void *userdata,
     309                 :            :                 sd_bus_error *error) {
     310                 :            : 
     311                 :          0 :         Manager *m = userdata;
     312                 :            :         bool b;
     313                 :            : 
     314         [ #  # ]:          0 :         assert(bus);
     315         [ #  # ]:          0 :         assert(reply);
     316         [ #  # ]:          0 :         assert(m);
     317                 :            : 
     318         [ #  # ]:          0 :         if (streq(property, "PreparingForShutdown"))
     319                 :          0 :                 b = m->action_what & INHIBIT_SHUTDOWN;
     320                 :            :         else
     321                 :          0 :                 b = m->action_what & INHIBIT_SLEEP;
     322                 :            : 
     323                 :          0 :         return sd_bus_message_append(reply, "b", b);
     324                 :            : }
     325                 :            : 
     326                 :          0 : static int property_get_scheduled_shutdown(
     327                 :            :                 sd_bus *bus,
     328                 :            :                 const char *path,
     329                 :            :                 const char *interface,
     330                 :            :                 const char *property,
     331                 :            :                 sd_bus_message *reply,
     332                 :            :                 void *userdata,
     333                 :            :                 sd_bus_error *error) {
     334                 :            : 
     335                 :          0 :         Manager *m = userdata;
     336                 :            :         int r;
     337                 :            : 
     338         [ #  # ]:          0 :         assert(bus);
     339         [ #  # ]:          0 :         assert(reply);
     340         [ #  # ]:          0 :         assert(m);
     341                 :            : 
     342                 :          0 :         r = sd_bus_message_open_container(reply, 'r', "st");
     343         [ #  # ]:          0 :         if (r < 0)
     344                 :          0 :                 return r;
     345                 :            : 
     346                 :          0 :         r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
     347         [ #  # ]:          0 :         if (r < 0)
     348                 :          0 :                 return r;
     349                 :            : 
     350                 :          0 :         return sd_bus_message_close_container(reply);
     351                 :            : }
     352                 :            : 
     353   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
                   #  # ]
     354   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays);
                   #  # ]
     355   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET(property_get_lid_closed, "b", Manager, manager_is_lid_closed);
                   #  # ]
     356   [ #  #  #  # ]:          0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_on_external_power, "b", manager_is_on_external_power);
     357   [ #  #  #  # ]:          0 : static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX);
     358   [ #  #  #  #  :          0 : static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size);
                   #  # ]
     359                 :            : 
     360                 :          0 : static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     361                 :          0 :         _cleanup_free_ char *p = NULL;
     362                 :          0 :         Manager *m = userdata;
     363                 :            :         const char *name;
     364                 :            :         Session *session;
     365                 :            :         int r;
     366                 :            : 
     367         [ #  # ]:          0 :         assert(message);
     368         [ #  # ]:          0 :         assert(m);
     369                 :            : 
     370                 :          0 :         r = sd_bus_message_read(message, "s", &name);
     371         [ #  # ]:          0 :         if (r < 0)
     372                 :          0 :                 return r;
     373                 :            : 
     374                 :          0 :         r = manager_get_session_from_creds(m, message, name, error, &session);
     375         [ #  # ]:          0 :         if (r < 0)
     376                 :          0 :                 return r;
     377                 :            : 
     378                 :          0 :         p = session_bus_path(session);
     379         [ #  # ]:          0 :         if (!p)
     380                 :          0 :                 return -ENOMEM;
     381                 :            : 
     382                 :          0 :         return sd_bus_reply_method_return(message, "o", p);
     383                 :            : }
     384                 :            : 
     385                 :            : /* Get login session of a process.  This is not what you are looking for these days,
     386                 :            :  * as apps may instead belong to a user service unit.  This includes terminal
     387                 :            :  * emulators and hence command-line apps. */
     388                 :          0 : static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     389                 :          0 :         _cleanup_free_ char *p = NULL;
     390                 :          0 :         Session *session = NULL;
     391                 :          0 :         Manager *m = userdata;
     392                 :            :         pid_t pid;
     393                 :            :         int r;
     394                 :            : 
     395         [ #  # ]:          0 :         assert(message);
     396         [ #  # ]:          0 :         assert(m);
     397                 :            : 
     398                 :            :         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
     399                 :            : 
     400                 :          0 :         r = sd_bus_message_read(message, "u", &pid);
     401         [ #  # ]:          0 :         if (r < 0)
     402                 :          0 :                 return r;
     403         [ #  # ]:          0 :         if (pid < 0)
     404                 :          0 :                 return -EINVAL;
     405                 :            : 
     406         [ #  # ]:          0 :         if (pid == 0) {
     407                 :          0 :                 r = manager_get_session_from_creds(m, message, NULL, error, &session);
     408         [ #  # ]:          0 :                 if (r < 0)
     409                 :          0 :                         return r;
     410                 :            :         } else {
     411                 :          0 :                 r = manager_get_session_by_pid(m, pid, &session);
     412         [ #  # ]:          0 :                 if (r < 0)
     413                 :          0 :                         return r;
     414                 :            : 
     415         [ #  # ]:          0 :                 if (!session)
     416                 :          0 :                         return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
     417                 :            :                                                  "PID "PID_FMT" does not belong to any known session", pid);
     418                 :            :         }
     419                 :            : 
     420                 :          0 :         p = session_bus_path(session);
     421         [ #  # ]:          0 :         if (!p)
     422                 :          0 :                 return -ENOMEM;
     423                 :            : 
     424                 :          0 :         return sd_bus_reply_method_return(message, "o", p);
     425                 :            : }
     426                 :            : 
     427                 :          0 : static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     428                 :          0 :         _cleanup_free_ char *p = NULL;
     429                 :          0 :         Manager *m = userdata;
     430                 :            :         uint32_t uid;
     431                 :            :         User *user;
     432                 :            :         int r;
     433                 :            : 
     434         [ #  # ]:          0 :         assert(message);
     435         [ #  # ]:          0 :         assert(m);
     436                 :            : 
     437                 :          0 :         r = sd_bus_message_read(message, "u", &uid);
     438         [ #  # ]:          0 :         if (r < 0)
     439                 :          0 :                 return r;
     440                 :            : 
     441                 :          0 :         r = manager_get_user_from_creds(m, message, uid, error, &user);
     442         [ #  # ]:          0 :         if (r < 0)
     443                 :          0 :                 return r;
     444                 :            : 
     445                 :          0 :         p = user_bus_path(user);
     446         [ #  # ]:          0 :         if (!p)
     447                 :          0 :                 return -ENOMEM;
     448                 :            : 
     449                 :          0 :         return sd_bus_reply_method_return(message, "o", p);
     450                 :            : }
     451                 :            : 
     452                 :          0 : static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     453                 :          0 :         _cleanup_free_ char *p = NULL;
     454                 :          0 :         Manager *m = userdata;
     455                 :          0 :         User *user = NULL;
     456                 :            :         pid_t pid;
     457                 :            :         int r;
     458                 :            : 
     459         [ #  # ]:          0 :         assert(message);
     460         [ #  # ]:          0 :         assert(m);
     461                 :            : 
     462                 :            :         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
     463                 :            : 
     464                 :          0 :         r = sd_bus_message_read(message, "u", &pid);
     465         [ #  # ]:          0 :         if (r < 0)
     466                 :          0 :                 return r;
     467         [ #  # ]:          0 :         if (pid < 0)
     468                 :          0 :                 return -EINVAL;
     469                 :            : 
     470         [ #  # ]:          0 :         if (pid == 0) {
     471                 :          0 :                 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
     472         [ #  # ]:          0 :                 if (r < 0)
     473                 :          0 :                         return r;
     474                 :            :         } else {
     475                 :          0 :                 r = manager_get_user_by_pid(m, pid, &user);
     476         [ #  # ]:          0 :                 if (r < 0)
     477                 :          0 :                         return r;
     478         [ #  # ]:          0 :                 if (!user)
     479                 :          0 :                         return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
     480                 :            :                                                  "PID "PID_FMT" does not belong to any logged in user or lingering user",
     481                 :            :                                                  pid);
     482                 :            :         }
     483                 :            : 
     484                 :          0 :         p = user_bus_path(user);
     485         [ #  # ]:          0 :         if (!p)
     486                 :          0 :                 return -ENOMEM;
     487                 :            : 
     488                 :          0 :         return sd_bus_reply_method_return(message, "o", p);
     489                 :            : }
     490                 :            : 
     491                 :          0 : static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     492                 :          0 :         _cleanup_free_ char *p = NULL;
     493                 :          0 :         Manager *m = userdata;
     494                 :            :         const char *name;
     495                 :            :         Seat *seat;
     496                 :            :         int r;
     497                 :            : 
     498         [ #  # ]:          0 :         assert(message);
     499         [ #  # ]:          0 :         assert(m);
     500                 :            : 
     501                 :          0 :         r = sd_bus_message_read(message, "s", &name);
     502         [ #  # ]:          0 :         if (r < 0)
     503                 :          0 :                 return r;
     504                 :            : 
     505                 :          0 :         r = manager_get_seat_from_creds(m, message, name, error, &seat);
     506         [ #  # ]:          0 :         if (r < 0)
     507                 :          0 :                 return r;
     508                 :            : 
     509                 :          0 :         p = seat_bus_path(seat);
     510         [ #  # ]:          0 :         if (!p)
     511                 :          0 :                 return -ENOMEM;
     512                 :            : 
     513                 :          0 :         return sd_bus_reply_method_return(message, "o", p);
     514                 :            : }
     515                 :            : 
     516                 :          0 : static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     517                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     518                 :          0 :         Manager *m = userdata;
     519                 :            :         Session *session;
     520                 :            :         Iterator i;
     521                 :            :         int r;
     522                 :            : 
     523         [ #  # ]:          0 :         assert(message);
     524         [ #  # ]:          0 :         assert(m);
     525                 :            : 
     526                 :          0 :         r = sd_bus_message_new_method_return(message, &reply);
     527         [ #  # ]:          0 :         if (r < 0)
     528                 :          0 :                 return r;
     529                 :            : 
     530                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(susso)");
     531         [ #  # ]:          0 :         if (r < 0)
     532                 :          0 :                 return r;
     533                 :            : 
     534         [ #  # ]:          0 :         HASHMAP_FOREACH(session, m->sessions, i) {
     535         [ #  # ]:          0 :                 _cleanup_free_ char *p = NULL;
     536                 :            : 
     537                 :          0 :                 p = session_bus_path(session);
     538         [ #  # ]:          0 :                 if (!p)
     539                 :          0 :                         return -ENOMEM;
     540                 :            : 
     541                 :          0 :                 r = sd_bus_message_append(reply, "(susso)",
     542                 :          0 :                                           session->id,
     543                 :          0 :                                           (uint32_t) session->user->uid,
     544                 :          0 :                                           session->user->name,
     545         [ #  # ]:          0 :                                           session->seat ? session->seat->id : "",
     546                 :            :                                           p);
     547         [ #  # ]:          0 :                 if (r < 0)
     548                 :          0 :                         return r;
     549                 :            :         }
     550                 :            : 
     551                 :          0 :         r = sd_bus_message_close_container(reply);
     552         [ #  # ]:          0 :         if (r < 0)
     553                 :          0 :                 return r;
     554                 :            : 
     555                 :          0 :         return sd_bus_send(NULL, reply, NULL);
     556                 :            : }
     557                 :            : 
     558                 :          0 : static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     559                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     560                 :          0 :         Manager *m = userdata;
     561                 :            :         User *user;
     562                 :            :         Iterator i;
     563                 :            :         int r;
     564                 :            : 
     565         [ #  # ]:          0 :         assert(message);
     566         [ #  # ]:          0 :         assert(m);
     567                 :            : 
     568                 :          0 :         r = sd_bus_message_new_method_return(message, &reply);
     569         [ #  # ]:          0 :         if (r < 0)
     570                 :          0 :                 return r;
     571                 :            : 
     572                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(uso)");
     573         [ #  # ]:          0 :         if (r < 0)
     574                 :          0 :                 return r;
     575                 :            : 
     576         [ #  # ]:          0 :         HASHMAP_FOREACH(user, m->users, i) {
     577         [ #  # ]:          0 :                 _cleanup_free_ char *p = NULL;
     578                 :            : 
     579                 :          0 :                 p = user_bus_path(user);
     580         [ #  # ]:          0 :                 if (!p)
     581                 :          0 :                         return -ENOMEM;
     582                 :            : 
     583                 :          0 :                 r = sd_bus_message_append(reply, "(uso)",
     584                 :          0 :                                           (uint32_t) user->uid,
     585                 :          0 :                                           user->name,
     586                 :            :                                           p);
     587         [ #  # ]:          0 :                 if (r < 0)
     588                 :          0 :                         return r;
     589                 :            :         }
     590                 :            : 
     591                 :          0 :         r = sd_bus_message_close_container(reply);
     592         [ #  # ]:          0 :         if (r < 0)
     593                 :          0 :                 return r;
     594                 :            : 
     595                 :          0 :         return sd_bus_send(NULL, reply, NULL);
     596                 :            : }
     597                 :            : 
     598                 :          0 : static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     599                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     600                 :          0 :         Manager *m = userdata;
     601                 :            :         Seat *seat;
     602                 :            :         Iterator i;
     603                 :            :         int r;
     604                 :            : 
     605         [ #  # ]:          0 :         assert(message);
     606         [ #  # ]:          0 :         assert(m);
     607                 :            : 
     608                 :          0 :         r = sd_bus_message_new_method_return(message, &reply);
     609         [ #  # ]:          0 :         if (r < 0)
     610                 :          0 :                 return r;
     611                 :            : 
     612                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(so)");
     613         [ #  # ]:          0 :         if (r < 0)
     614                 :          0 :                 return r;
     615                 :            : 
     616         [ #  # ]:          0 :         HASHMAP_FOREACH(seat, m->seats, i) {
     617         [ #  # ]:          0 :                 _cleanup_free_ char *p = NULL;
     618                 :            : 
     619                 :          0 :                 p = seat_bus_path(seat);
     620         [ #  # ]:          0 :                 if (!p)
     621                 :          0 :                         return -ENOMEM;
     622                 :            : 
     623                 :          0 :                 r = sd_bus_message_append(reply, "(so)", seat->id, p);
     624         [ #  # ]:          0 :                 if (r < 0)
     625                 :          0 :                         return r;
     626                 :            :         }
     627                 :            : 
     628                 :          0 :         r = sd_bus_message_close_container(reply);
     629         [ #  # ]:          0 :         if (r < 0)
     630                 :          0 :                 return r;
     631                 :            : 
     632                 :          0 :         return sd_bus_send(NULL, reply, NULL);
     633                 :            : }
     634                 :            : 
     635                 :          0 : static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     636                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     637                 :          0 :         Manager *m = userdata;
     638                 :            :         Inhibitor *inhibitor;
     639                 :            :         Iterator i;
     640                 :            :         int r;
     641                 :            : 
     642         [ #  # ]:          0 :         assert(message);
     643         [ #  # ]:          0 :         assert(m);
     644                 :            : 
     645                 :          0 :         r = sd_bus_message_new_method_return(message, &reply);
     646         [ #  # ]:          0 :         if (r < 0)
     647                 :          0 :                 return r;
     648                 :            : 
     649                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
     650         [ #  # ]:          0 :         if (r < 0)
     651                 :          0 :                 return r;
     652                 :            : 
     653         [ #  # ]:          0 :         HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
     654                 :            : 
     655                 :          0 :                 r = sd_bus_message_append(reply, "(ssssuu)",
     656                 :          0 :                                           strempty(inhibit_what_to_string(inhibitor->what)),
     657                 :          0 :                                           strempty(inhibitor->who),
     658                 :          0 :                                           strempty(inhibitor->why),
     659                 :          0 :                                           strempty(inhibit_mode_to_string(inhibitor->mode)),
     660                 :          0 :                                           (uint32_t) inhibitor->uid,
     661                 :          0 :                                           (uint32_t) inhibitor->pid);
     662         [ #  # ]:          0 :                 if (r < 0)
     663                 :          0 :                         return r;
     664                 :            :         }
     665                 :            : 
     666                 :          0 :         r = sd_bus_message_close_container(reply);
     667         [ #  # ]:          0 :         if (r < 0)
     668                 :          0 :                 return r;
     669                 :            : 
     670                 :          0 :         return sd_bus_send(NULL, reply, NULL);
     671                 :            : }
     672                 :            : 
     673                 :          0 : static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     674                 :            :         const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
     675                 :          0 :         _cleanup_free_ char *id = NULL;
     676                 :          0 :         Session *session = NULL;
     677                 :          0 :         uint32_t audit_id = 0;
     678                 :          0 :         Manager *m = userdata;
     679                 :          0 :         User *user = NULL;
     680                 :          0 :         Seat *seat = NULL;
     681                 :            :         pid_t leader;
     682                 :            :         uid_t uid;
     683                 :            :         int remote;
     684                 :          0 :         uint32_t vtnr = 0;
     685                 :            :         SessionType t;
     686                 :            :         SessionClass c;
     687                 :            :         int r;
     688                 :            : 
     689         [ #  # ]:          0 :         assert(message);
     690         [ #  # ]:          0 :         assert(m);
     691                 :            : 
     692                 :            :         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
     693                 :            :         assert_cc(sizeof(uid_t) == sizeof(uint32_t));
     694                 :            : 
     695                 :          0 :         r = sd_bus_message_read(message, "uusssssussbss",
     696                 :            :                                 &uid, &leader, &service, &type, &class, &desktop, &cseat,
     697                 :            :                                 &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
     698         [ #  # ]:          0 :         if (r < 0)
     699                 :          0 :                 return r;
     700                 :            : 
     701         [ #  # ]:          0 :         if (!uid_is_valid(uid))
     702                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
     703   [ #  #  #  #  :          0 :         if (leader < 0 || leader == 1 || leader == getpid_cached())
                   #  # ]
     704                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
     705                 :            : 
     706         [ #  # ]:          0 :         if (isempty(type))
     707                 :          0 :                 t = _SESSION_TYPE_INVALID;
     708                 :            :         else {
     709                 :          0 :                 t = session_type_from_string(type);
     710         [ #  # ]:          0 :                 if (t < 0)
     711                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     712                 :            :                                                  "Invalid session type %s", type);
     713                 :            :         }
     714                 :            : 
     715         [ #  # ]:          0 :         if (isempty(class))
     716                 :          0 :                 c = _SESSION_CLASS_INVALID;
     717                 :            :         else {
     718                 :          0 :                 c = session_class_from_string(class);
     719         [ #  # ]:          0 :                 if (c < 0)
     720                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     721                 :            :                                                  "Invalid session class %s", class);
     722                 :            :         }
     723                 :            : 
     724         [ #  # ]:          0 :         if (isempty(desktop))
     725                 :          0 :                 desktop = NULL;
     726                 :            :         else {
     727         [ #  # ]:          0 :                 if (!string_is_safe(desktop))
     728                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     729                 :            :                                                  "Invalid desktop string %s", desktop);
     730                 :            :         }
     731                 :            : 
     732         [ #  # ]:          0 :         if (isempty(cseat))
     733                 :          0 :                 seat = NULL;
     734                 :            :         else {
     735                 :          0 :                 seat = hashmap_get(m->seats, cseat);
     736         [ #  # ]:          0 :                 if (!seat)
     737                 :          0 :                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT,
     738                 :            :                                                  "No seat '%s' known", cseat);
     739                 :            :         }
     740                 :            : 
     741         [ #  # ]:          0 :         if (tty_is_vc(tty)) {
     742                 :            :                 int v;
     743                 :            : 
     744         [ #  # ]:          0 :                 if (!seat)
     745                 :          0 :                         seat = m->seat0;
     746         [ #  # ]:          0 :                 else if (seat != m->seat0)
     747                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     748                 :            :                                                  "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
     749                 :            : 
     750                 :          0 :                 v = vtnr_from_tty(tty);
     751         [ #  # ]:          0 :                 if (v <= 0)
     752                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     753                 :            :                                                  "Cannot determine VT number from virtual console TTY %s", tty);
     754                 :            : 
     755         [ #  # ]:          0 :                 if (vtnr == 0)
     756                 :          0 :                         vtnr = (uint32_t) v;
     757         [ #  # ]:          0 :                 else if (vtnr != (uint32_t) v)
     758                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     759                 :            :                                                  "Specified TTY and VT number do not match");
     760                 :            : 
     761         [ #  # ]:          0 :         } else if (tty_is_console(tty)) {
     762                 :            : 
     763         [ #  # ]:          0 :                 if (!seat)
     764                 :          0 :                         seat = m->seat0;
     765         [ #  # ]:          0 :                 else if (seat != m->seat0)
     766                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     767                 :            :                                                  "Console TTY specified but seat is not seat0");
     768                 :            : 
     769         [ #  # ]:          0 :                 if (vtnr != 0)
     770                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     771                 :            :                                                  "Console TTY specified but VT number is not 0");
     772                 :            :         }
     773                 :            : 
     774         [ #  # ]:          0 :         if (seat) {
     775         [ #  # ]:          0 :                 if (seat_has_vts(seat)) {
     776   [ #  #  #  # ]:          0 :                         if (vtnr <= 0 || vtnr > 63)
     777                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     778                 :            :                                                          "VT number out of range");
     779                 :            :                 } else {
     780         [ #  # ]:          0 :                         if (vtnr != 0)
     781                 :          0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     782                 :            :                                                          "Seat has no VTs but VT number not 0");
     783                 :            :                 }
     784                 :            :         }
     785                 :            : 
     786         [ #  # ]:          0 :         if (t == _SESSION_TYPE_INVALID) {
     787         [ #  # ]:          0 :                 if (!isempty(display))
     788                 :          0 :                         t = SESSION_X11;
     789         [ #  # ]:          0 :                 else if (!isempty(tty))
     790                 :          0 :                         t = SESSION_TTY;
     791                 :            :                 else
     792                 :          0 :                         t = SESSION_UNSPECIFIED;
     793                 :            :         }
     794                 :            : 
     795         [ #  # ]:          0 :         if (c == _SESSION_CLASS_INVALID) {
     796         [ #  # ]:          0 :                 if (t == SESSION_UNSPECIFIED)
     797                 :          0 :                         c = SESSION_BACKGROUND;
     798                 :            :                 else
     799                 :          0 :                         c = SESSION_USER;
     800                 :            :         }
     801                 :            : 
     802         [ #  # ]:          0 :         if (leader == 0) {
     803         [ #  # ]:          0 :                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
     804                 :            : 
     805                 :          0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
     806         [ #  # ]:          0 :                 if (r < 0)
     807                 :          0 :                         return r;
     808                 :            : 
     809                 :          0 :                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
     810         [ #  # ]:          0 :                 if (r < 0)
     811                 :          0 :                         return r;
     812                 :            :         }
     813                 :            : 
     814                 :            :         /* Check if we are already in a logind session. Or if we are in user@.service
     815                 :            :          * which is a special PAM session that avoids creating a logind session. */
     816                 :          0 :         r = manager_get_user_by_pid(m, leader, NULL);
     817         [ #  # ]:          0 :         if (r < 0)
     818                 :          0 :                 return r;
     819         [ #  # ]:          0 :         if (r > 0)
     820                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY,
     821                 :            :                                          "Already running in a session or user slice");
     822                 :            : 
     823                 :            :         /*
     824                 :            :          * Old gdm and lightdm start the user-session on the same VT as
     825                 :            :          * the greeter session. But they destroy the greeter session
     826                 :            :          * after the user-session and want the user-session to take
     827                 :            :          * over the VT. We need to support this for
     828                 :            :          * backwards-compatibility, so make sure we allow new sessions
     829                 :            :          * on a VT that a greeter is running on. Furthermore, to allow
     830                 :            :          * re-logins, we have to allow a greeter to take over a used VT for
     831                 :            :          * the exact same reasons.
     832                 :            :          */
     833         [ #  # ]:          0 :         if (c != SESSION_GREETER &&
     834         [ #  # ]:          0 :             vtnr > 0 &&
     835         [ #  # ]:          0 :             vtnr < m->seat0->position_count &&
     836         [ #  # ]:          0 :             m->seat0->positions[vtnr] &&
     837         [ #  # ]:          0 :             m->seat0->positions[vtnr]->class != SESSION_GREETER)
     838                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
     839                 :            : 
     840         [ #  # ]:          0 :         if (hashmap_size(m->sessions) >= m->sessions_max)
     841                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
     842                 :            :                                          "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.",
     843                 :            :                                          m->sessions_max);
     844                 :            : 
     845                 :          0 :         (void) audit_session_from_pid(leader, &audit_id);
     846         [ #  # ]:          0 :         if (audit_session_is_valid(audit_id)) {
     847                 :            :                 /* Keep our session IDs and the audit session IDs in sync */
     848                 :            : 
     849         [ #  # ]:          0 :                 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
     850                 :          0 :                         return -ENOMEM;
     851                 :            : 
     852                 :            :                 /* Wut? There's already a session by this name and we didn't find it above? Weird, then let's
     853                 :            :                  * not trust the audit data and let's better register a new ID */
     854         [ #  # ]:          0 :                 if (hashmap_contains(m->sessions, id)) {
     855         [ #  # ]:          0 :                         log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
     856                 :          0 :                         audit_id = AUDIT_SESSION_INVALID;
     857                 :          0 :                         id = mfree(id);
     858                 :            :                 }
     859                 :            :         }
     860                 :            : 
     861         [ #  # ]:          0 :         if (!id) {
     862                 :            :                 do {
     863                 :          0 :                         id = mfree(id);
     864                 :            : 
     865         [ #  # ]:          0 :                         if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
     866                 :          0 :                                 return -ENOMEM;
     867                 :            : 
     868         [ #  # ]:          0 :                 } while (hashmap_contains(m->sessions, id));
     869                 :            :         }
     870                 :            : 
     871                 :            :         /* The generated names should not clash with 'auto' or 'self' */
     872         [ #  # ]:          0 :         assert(!SESSION_IS_SELF(id));
     873         [ #  # ]:          0 :         assert(!SESSION_IS_AUTO(id));
     874                 :            : 
     875                 :            :         /* If we are not watching utmp already, try again */
     876                 :          0 :         manager_reconnect_utmp(m);
     877                 :            : 
     878                 :          0 :         r = manager_add_user_by_uid(m, uid, &user);
     879         [ #  # ]:          0 :         if (r < 0)
     880                 :          0 :                 goto fail;
     881                 :            : 
     882                 :          0 :         r = manager_add_session(m, id, &session);
     883         [ #  # ]:          0 :         if (r < 0)
     884                 :          0 :                 goto fail;
     885                 :            : 
     886                 :          0 :         session_set_user(session, user);
     887                 :          0 :         r = session_set_leader(session, leader);
     888         [ #  # ]:          0 :         if (r < 0)
     889                 :          0 :                 goto fail;
     890                 :            : 
     891                 :          0 :         session->type = t;
     892                 :          0 :         session->class = c;
     893                 :          0 :         session->remote = remote;
     894                 :          0 :         session->vtnr = vtnr;
     895                 :            : 
     896         [ #  # ]:          0 :         if (!isempty(tty)) {
     897                 :          0 :                 session->tty = strdup(tty);
     898         [ #  # ]:          0 :                 if (!session->tty) {
     899                 :          0 :                         r = -ENOMEM;
     900                 :          0 :                         goto fail;
     901                 :            :                 }
     902                 :            : 
     903                 :          0 :                 session->tty_validity = TTY_FROM_PAM;
     904                 :            :         }
     905                 :            : 
     906         [ #  # ]:          0 :         if (!isempty(display)) {
     907                 :          0 :                 session->display = strdup(display);
     908         [ #  # ]:          0 :                 if (!session->display) {
     909                 :          0 :                         r = -ENOMEM;
     910                 :          0 :                         goto fail;
     911                 :            :                 }
     912                 :            :         }
     913                 :            : 
     914         [ #  # ]:          0 :         if (!isempty(remote_user)) {
     915                 :          0 :                 session->remote_user = strdup(remote_user);
     916         [ #  # ]:          0 :                 if (!session->remote_user) {
     917                 :          0 :                         r = -ENOMEM;
     918                 :          0 :                         goto fail;
     919                 :            :                 }
     920                 :            :         }
     921                 :            : 
     922         [ #  # ]:          0 :         if (!isempty(remote_host)) {
     923                 :          0 :                 session->remote_host = strdup(remote_host);
     924         [ #  # ]:          0 :                 if (!session->remote_host) {
     925                 :          0 :                         r = -ENOMEM;
     926                 :          0 :                         goto fail;
     927                 :            :                 }
     928                 :            :         }
     929                 :            : 
     930         [ #  # ]:          0 :         if (!isempty(service)) {
     931                 :          0 :                 session->service = strdup(service);
     932         [ #  # ]:          0 :                 if (!session->service) {
     933                 :          0 :                         r = -ENOMEM;
     934                 :          0 :                         goto fail;
     935                 :            :                 }
     936                 :            :         }
     937                 :            : 
     938         [ #  # ]:          0 :         if (!isempty(desktop)) {
     939                 :          0 :                 session->desktop = strdup(desktop);
     940         [ #  # ]:          0 :                 if (!session->desktop) {
     941                 :          0 :                         r = -ENOMEM;
     942                 :          0 :                         goto fail;
     943                 :            :                 }
     944                 :            :         }
     945                 :            : 
     946         [ #  # ]:          0 :         if (seat) {
     947                 :          0 :                 r = seat_attach_session(seat, session);
     948         [ #  # ]:          0 :                 if (r < 0)
     949                 :          0 :                         goto fail;
     950                 :            :         }
     951                 :            : 
     952                 :          0 :         r = sd_bus_message_enter_container(message, 'a', "(sv)");
     953         [ #  # ]:          0 :         if (r < 0)
     954                 :          0 :                 goto fail;
     955                 :            : 
     956                 :          0 :         r = session_start(session, message, error);
     957         [ #  # ]:          0 :         if (r < 0)
     958                 :          0 :                 goto fail;
     959                 :            : 
     960                 :          0 :         r = sd_bus_message_exit_container(message);
     961         [ #  # ]:          0 :         if (r < 0)
     962                 :          0 :                 goto fail;
     963                 :            : 
     964                 :          0 :         session->create_message = sd_bus_message_ref(message);
     965                 :            : 
     966                 :            :         /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
     967                 :            :          * session_send_create_reply(). */
     968                 :            : 
     969                 :          0 :         return 1;
     970                 :            : 
     971                 :          0 : fail:
     972         [ #  # ]:          0 :         if (session)
     973                 :          0 :                 session_add_to_gc_queue(session);
     974                 :            : 
     975         [ #  # ]:          0 :         if (user)
     976                 :          0 :                 user_add_to_gc_queue(user);
     977                 :            : 
     978                 :          0 :         return r;
     979                 :            : }
     980                 :            : 
     981                 :          0 : static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
     982                 :          0 :         Manager *m = userdata;
     983                 :            :         Session *session;
     984                 :            :         const char *name;
     985                 :            :         int r;
     986                 :            : 
     987         [ #  # ]:          0 :         assert(message);
     988         [ #  # ]:          0 :         assert(m);
     989                 :            : 
     990                 :          0 :         r = sd_bus_message_read(message, "s", &name);
     991         [ #  # ]:          0 :         if (r < 0)
     992                 :          0 :                 return r;
     993                 :            : 
     994                 :          0 :         r = manager_get_session_from_creds(m, message, name, error, &session);
     995         [ #  # ]:          0 :         if (r < 0)
     996                 :          0 :                 return r;
     997                 :            : 
     998                 :          0 :         r = session_release(session);
     999         [ #  # ]:          0 :         if (r < 0)
    1000                 :          0 :                 return r;
    1001                 :            : 
    1002                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1003                 :            : }
    1004                 :            : 
    1005                 :          0 : static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1006                 :          0 :         Manager *m = userdata;
    1007                 :            :         Session *session;
    1008                 :            :         const char *name;
    1009                 :            :         int r;
    1010                 :            : 
    1011         [ #  # ]:          0 :         assert(message);
    1012         [ #  # ]:          0 :         assert(m);
    1013                 :            : 
    1014                 :          0 :         r = sd_bus_message_read(message, "s", &name);
    1015         [ #  # ]:          0 :         if (r < 0)
    1016                 :          0 :                 return r;
    1017                 :            : 
    1018                 :          0 :         r = manager_get_session_from_creds(m, message, name, error, &session);
    1019         [ #  # ]:          0 :         if (r < 0)
    1020                 :          0 :                 return r;
    1021                 :            : 
    1022                 :          0 :         return bus_session_method_activate(message, session, error);
    1023                 :            : }
    1024                 :            : 
    1025                 :          0 : static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1026                 :            :         const char *session_name, *seat_name;
    1027                 :          0 :         Manager *m = userdata;
    1028                 :            :         Session *session;
    1029                 :            :         Seat *seat;
    1030                 :            :         int r;
    1031                 :            : 
    1032         [ #  # ]:          0 :         assert(message);
    1033         [ #  # ]:          0 :         assert(m);
    1034                 :            : 
    1035                 :            :         /* Same as ActivateSession() but refuses to work if the seat doesn't match */
    1036                 :            : 
    1037                 :          0 :         r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
    1038         [ #  # ]:          0 :         if (r < 0)
    1039                 :          0 :                 return r;
    1040                 :            : 
    1041                 :          0 :         r = manager_get_session_from_creds(m, message, session_name, error, &session);
    1042         [ #  # ]:          0 :         if (r < 0)
    1043                 :          0 :                 return r;
    1044                 :            : 
    1045                 :          0 :         r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
    1046         [ #  # ]:          0 :         if (r < 0)
    1047                 :          0 :                 return r;
    1048                 :            : 
    1049         [ #  # ]:          0 :         if (session->seat != seat)
    1050                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT,
    1051                 :            :                                          "Session %s not on seat %s", session_name, seat_name);
    1052                 :            : 
    1053                 :          0 :         r = session_activate(session);
    1054         [ #  # ]:          0 :         if (r < 0)
    1055                 :          0 :                 return r;
    1056                 :            : 
    1057                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1058                 :            : }
    1059                 :            : 
    1060                 :          0 : static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1061                 :          0 :         Manager *m = userdata;
    1062                 :            :         Session *session;
    1063                 :            :         const char *name;
    1064                 :            :         int r;
    1065                 :            : 
    1066         [ #  # ]:          0 :         assert(message);
    1067         [ #  # ]:          0 :         assert(m);
    1068                 :            : 
    1069                 :          0 :         r = sd_bus_message_read(message, "s", &name);
    1070         [ #  # ]:          0 :         if (r < 0)
    1071                 :          0 :                 return r;
    1072                 :            : 
    1073                 :          0 :         r = manager_get_session_from_creds(m, message, name, error, &session);
    1074         [ #  # ]:          0 :         if (r < 0)
    1075                 :          0 :                 return r;
    1076                 :            : 
    1077                 :          0 :         return bus_session_method_lock(message, session, error);
    1078                 :            : }
    1079                 :            : 
    1080                 :          0 : static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1081                 :          0 :         Manager *m = userdata;
    1082                 :            :         int r;
    1083                 :            : 
    1084         [ #  # ]:          0 :         assert(message);
    1085         [ #  # ]:          0 :         assert(m);
    1086                 :            : 
    1087                 :          0 :         r = bus_verify_polkit_async(
    1088                 :            :                         message,
    1089                 :            :                         CAP_SYS_ADMIN,
    1090                 :            :                         "org.freedesktop.login1.lock-sessions",
    1091                 :            :                         NULL,
    1092                 :            :                         false,
    1093                 :            :                         UID_INVALID,
    1094                 :            :                         &m->polkit_registry,
    1095                 :            :                         error);
    1096         [ #  # ]:          0 :         if (r < 0)
    1097                 :          0 :                 return r;
    1098         [ #  # ]:          0 :         if (r == 0)
    1099                 :          0 :                 return 1; /* Will call us back */
    1100                 :            : 
    1101                 :          0 :         r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
    1102         [ #  # ]:          0 :         if (r < 0)
    1103                 :          0 :                 return r;
    1104                 :            : 
    1105                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1106                 :            : }
    1107                 :            : 
    1108                 :          0 : static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1109                 :            :         const char *name;
    1110                 :          0 :         Manager *m = userdata;
    1111                 :            :         Session *session;
    1112                 :            :         int r;
    1113                 :            : 
    1114         [ #  # ]:          0 :         assert(message);
    1115         [ #  # ]:          0 :         assert(m);
    1116                 :            : 
    1117                 :          0 :         r = sd_bus_message_read(message, "s", &name);
    1118         [ #  # ]:          0 :         if (r < 0)
    1119                 :          0 :                 return r;
    1120                 :            : 
    1121                 :          0 :         r = manager_get_session_from_creds(m, message, name, error, &session);
    1122         [ #  # ]:          0 :         if (r < 0)
    1123                 :          0 :                 return r;
    1124                 :            : 
    1125                 :          0 :         return bus_session_method_kill(message, session, error);
    1126                 :            : }
    1127                 :            : 
    1128                 :          0 : static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1129                 :          0 :         Manager *m = userdata;
    1130                 :            :         uint32_t uid;
    1131                 :            :         User *user;
    1132                 :            :         int r;
    1133                 :            : 
    1134         [ #  # ]:          0 :         assert(message);
    1135         [ #  # ]:          0 :         assert(m);
    1136                 :            : 
    1137                 :          0 :         r = sd_bus_message_read(message, "u", &uid);
    1138         [ #  # ]:          0 :         if (r < 0)
    1139                 :          0 :                 return r;
    1140                 :            : 
    1141                 :          0 :         r = manager_get_user_from_creds(m, message, uid, error, &user);
    1142         [ #  # ]:          0 :         if (r < 0)
    1143                 :          0 :                 return r;
    1144                 :            : 
    1145                 :          0 :         return bus_user_method_kill(message, user, error);
    1146                 :            : }
    1147                 :            : 
    1148                 :          0 : static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1149                 :          0 :         Manager *m = userdata;
    1150                 :            :         const char *name;
    1151                 :            :         Session *session;
    1152                 :            :         int r;
    1153                 :            : 
    1154         [ #  # ]:          0 :         assert(message);
    1155         [ #  # ]:          0 :         assert(m);
    1156                 :            : 
    1157                 :          0 :         r = sd_bus_message_read(message, "s", &name);
    1158         [ #  # ]:          0 :         if (r < 0)
    1159                 :          0 :                 return r;
    1160                 :            : 
    1161                 :          0 :         r = manager_get_session_from_creds(m, message, name, error, &session);
    1162         [ #  # ]:          0 :         if (r < 0)
    1163                 :          0 :                 return r;
    1164                 :            : 
    1165                 :          0 :         return bus_session_method_terminate(message, session, error);
    1166                 :            : }
    1167                 :            : 
    1168                 :          0 : static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1169                 :          0 :         Manager *m = userdata;
    1170                 :            :         uint32_t uid;
    1171                 :            :         User *user;
    1172                 :            :         int r;
    1173                 :            : 
    1174         [ #  # ]:          0 :         assert(message);
    1175         [ #  # ]:          0 :         assert(m);
    1176                 :            : 
    1177                 :          0 :         r = sd_bus_message_read(message, "u", &uid);
    1178         [ #  # ]:          0 :         if (r < 0)
    1179                 :          0 :                 return r;
    1180                 :            : 
    1181                 :          0 :         r = manager_get_user_from_creds(m, message, uid, error, &user);
    1182         [ #  # ]:          0 :         if (r < 0)
    1183                 :          0 :                 return r;
    1184                 :            : 
    1185                 :          0 :         return bus_user_method_terminate(message, user, error);
    1186                 :            : }
    1187                 :            : 
    1188                 :          0 : static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1189                 :          0 :         Manager *m = userdata;
    1190                 :            :         const char *name;
    1191                 :            :         Seat *seat;
    1192                 :            :         int r;
    1193                 :            : 
    1194         [ #  # ]:          0 :         assert(message);
    1195         [ #  # ]:          0 :         assert(m);
    1196                 :            : 
    1197                 :          0 :         r = sd_bus_message_read(message, "s", &name);
    1198         [ #  # ]:          0 :         if (r < 0)
    1199                 :          0 :                 return r;
    1200                 :            : 
    1201                 :          0 :         r = manager_get_seat_from_creds(m, message, name, error, &seat);
    1202         [ #  # ]:          0 :         if (r < 0)
    1203                 :          0 :                 return r;
    1204                 :            : 
    1205                 :          0 :         return bus_seat_method_terminate(message, seat, error);
    1206                 :            : }
    1207                 :            : 
    1208                 :          0 : static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1209                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    1210                 :          0 :         _cleanup_free_ char *cc = NULL;
    1211                 :          0 :         Manager *m = userdata;
    1212                 :            :         int r, b, interactive;
    1213                 :            :         struct passwd *pw;
    1214                 :            :         const char *path;
    1215                 :            :         uint32_t uid, auth_uid;
    1216                 :            : 
    1217         [ #  # ]:          0 :         assert(message);
    1218         [ #  # ]:          0 :         assert(m);
    1219                 :            : 
    1220                 :          0 :         r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
    1221         [ #  # ]:          0 :         if (r < 0)
    1222                 :          0 :                 return r;
    1223                 :            : 
    1224                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
    1225                 :            :                                                SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
    1226         [ #  # ]:          0 :         if (r < 0)
    1227                 :          0 :                 return r;
    1228                 :            : 
    1229         [ #  # ]:          0 :         if (!uid_is_valid(uid)) {
    1230                 :            :                 /* Note that we get the owner UID of the session or user unit,
    1231                 :            :                  * not the actual client UID here! */
    1232                 :          0 :                 r = sd_bus_creds_get_owner_uid(creds, &uid);
    1233         [ #  # ]:          0 :                 if (r < 0)
    1234                 :          0 :                         return r;
    1235                 :            :         }
    1236                 :            : 
    1237                 :            :         /* owner_uid is racy, so for authorization we must use euid */
    1238                 :          0 :         r = sd_bus_creds_get_euid(creds, &auth_uid);
    1239         [ #  # ]:          0 :         if (r < 0)
    1240                 :          0 :                 return r;
    1241                 :            : 
    1242                 :          0 :         errno = 0;
    1243                 :          0 :         pw = getpwuid(uid);
    1244         [ #  # ]:          0 :         if (!pw)
    1245                 :          0 :                 return errno_or_else(ENOENT);
    1246                 :            : 
    1247                 :          0 :         r = bus_verify_polkit_async(
    1248                 :            :                         message,
    1249                 :            :                         CAP_SYS_ADMIN,
    1250         [ #  # ]:          0 :                         uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
    1251                 :            :                                           "org.freedesktop.login1.set-user-linger",
    1252                 :            :                         NULL,
    1253                 :            :                         interactive,
    1254                 :            :                         UID_INVALID,
    1255                 :            :                         &m->polkit_registry,
    1256                 :            :                         error);
    1257         [ #  # ]:          0 :         if (r < 0)
    1258                 :          0 :                 return r;
    1259         [ #  # ]:          0 :         if (r == 0)
    1260                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    1261                 :            : 
    1262                 :          0 :         (void) mkdir_p_label("/var/lib/systemd", 0755);
    1263                 :          0 :         r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE);
    1264         [ #  # ]:          0 :         if (r < 0)
    1265                 :          0 :                 return r;
    1266                 :            : 
    1267                 :          0 :         cc = cescape(pw->pw_name);
    1268         [ #  # ]:          0 :         if (!cc)
    1269                 :          0 :                 return -ENOMEM;
    1270                 :            : 
    1271   [ #  #  #  #  :          0 :         path = strjoina("/var/lib/systemd/linger/", cc);
          #  #  #  #  #  
                #  #  # ]
    1272         [ #  # ]:          0 :         if (b) {
    1273                 :            :                 User *u;
    1274                 :            : 
    1275                 :          0 :                 r = touch(path);
    1276         [ #  # ]:          0 :                 if (r < 0)
    1277                 :          0 :                         return r;
    1278                 :            : 
    1279         [ #  # ]:          0 :                 if (manager_add_user_by_uid(m, uid, &u) >= 0)
    1280                 :          0 :                         user_start(u);
    1281                 :            : 
    1282                 :            :         } else {
    1283                 :            :                 User *u;
    1284                 :            : 
    1285                 :          0 :                 r = unlink(path);
    1286   [ #  #  #  # ]:          0 :                 if (r < 0 && errno != ENOENT)
    1287                 :          0 :                         return -errno;
    1288                 :            : 
    1289                 :          0 :                 u = hashmap_get(m->users, UID_TO_PTR(uid));
    1290         [ #  # ]:          0 :                 if (u)
    1291                 :          0 :                         user_add_to_gc_queue(u);
    1292                 :            :         }
    1293                 :            : 
    1294                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1295                 :            : }
    1296                 :            : 
    1297                 :          0 : static int trigger_device(Manager *m, sd_device *d) {
    1298                 :          0 :         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
    1299                 :            :         int r;
    1300                 :            : 
    1301         [ #  # ]:          0 :         assert(m);
    1302                 :            : 
    1303                 :          0 :         r = sd_device_enumerator_new(&e);
    1304         [ #  # ]:          0 :         if (r < 0)
    1305                 :          0 :                 return r;
    1306                 :            : 
    1307                 :          0 :         r = sd_device_enumerator_allow_uninitialized(e);
    1308         [ #  # ]:          0 :         if (r < 0)
    1309                 :          0 :                 return r;
    1310                 :            : 
    1311         [ #  # ]:          0 :         if (d) {
    1312                 :          0 :                 r = sd_device_enumerator_add_match_parent(e, d);
    1313         [ #  # ]:          0 :                 if (r < 0)
    1314                 :          0 :                         return r;
    1315                 :            :         }
    1316                 :            : 
    1317         [ #  # ]:          0 :         FOREACH_DEVICE(e, d) {
    1318         [ #  # ]:          0 :                 _cleanup_free_ char *t = NULL;
    1319                 :            :                 const char *p;
    1320                 :            : 
    1321                 :          0 :                 r = sd_device_get_syspath(d, &p);
    1322         [ #  # ]:          0 :                 if (r < 0)
    1323                 :          0 :                         return r;
    1324                 :            : 
    1325                 :          0 :                 t = path_join(p, "uevent");
    1326         [ #  # ]:          0 :                 if (!t)
    1327                 :          0 :                         return -ENOMEM;
    1328                 :            : 
    1329                 :          0 :                 (void) write_string_file(t, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
    1330                 :            :         }
    1331                 :            : 
    1332                 :          0 :         return 0;
    1333                 :            : }
    1334                 :            : 
    1335                 :          0 : static int attach_device(Manager *m, const char *seat, const char *sysfs) {
    1336                 :          0 :         _cleanup_(sd_device_unrefp) sd_device *d = NULL;
    1337                 :          0 :         _cleanup_free_ char *rule = NULL, *file = NULL;
    1338                 :            :         const char *id_for_seat;
    1339                 :            :         int r;
    1340                 :            : 
    1341         [ #  # ]:          0 :         assert(m);
    1342         [ #  # ]:          0 :         assert(seat);
    1343         [ #  # ]:          0 :         assert(sysfs);
    1344                 :            : 
    1345                 :          0 :         r = sd_device_new_from_syspath(&d, sysfs);
    1346         [ #  # ]:          0 :         if (r < 0)
    1347                 :          0 :                 return r;
    1348                 :            : 
    1349         [ #  # ]:          0 :         if (sd_device_has_tag(d, "seat") <= 0)
    1350                 :          0 :                 return -ENODEV;
    1351                 :            : 
    1352         [ #  # ]:          0 :         if (sd_device_get_property_value(d, "ID_FOR_SEAT", &id_for_seat) < 0)
    1353                 :          0 :                 return -ENODEV;
    1354                 :            : 
    1355         [ #  # ]:          0 :         if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
    1356                 :          0 :                 return -ENOMEM;
    1357                 :            : 
    1358         [ #  # ]:          0 :         if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
    1359                 :          0 :                 return -ENOMEM;
    1360                 :            : 
    1361                 :          0 :         (void) mkdir_p_label("/etc/udev/rules.d", 0755);
    1362                 :          0 :         r = write_string_file_atomic_label(file, rule);
    1363         [ #  # ]:          0 :         if (r < 0)
    1364                 :          0 :                 return r;
    1365                 :            : 
    1366                 :          0 :         return trigger_device(m, d);
    1367                 :            : }
    1368                 :            : 
    1369                 :          0 : static int flush_devices(Manager *m) {
    1370                 :          0 :         _cleanup_closedir_ DIR *d;
    1371                 :            : 
    1372         [ #  # ]:          0 :         assert(m);
    1373                 :            : 
    1374                 :          0 :         d = opendir("/etc/udev/rules.d");
    1375         [ #  # ]:          0 :         if (!d) {
    1376         [ #  # ]:          0 :                 if (errno != ENOENT)
    1377         [ #  # ]:          0 :                         log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
    1378                 :            :         } else {
    1379                 :            :                 struct dirent *de;
    1380                 :            : 
    1381   [ #  #  #  # ]:          0 :                 FOREACH_DIRENT_ALL(de, d, break) {
    1382         [ #  # ]:          0 :                         if (!dirent_is_file(de))
    1383                 :          0 :                                 continue;
    1384                 :            : 
    1385         [ #  # ]:          0 :                         if (!startswith(de->d_name, "72-seat-"))
    1386                 :          0 :                                 continue;
    1387                 :            : 
    1388         [ #  # ]:          0 :                         if (!endswith(de->d_name, ".rules"))
    1389                 :          0 :                                 continue;
    1390                 :            : 
    1391         [ #  # ]:          0 :                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
    1392         [ #  # ]:          0 :                                 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
    1393                 :            :                 }
    1394                 :            :         }
    1395                 :            : 
    1396                 :          0 :         return trigger_device(m, NULL);
    1397                 :            : }
    1398                 :            : 
    1399                 :          0 : static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1400                 :            :         const char *sysfs, *seat;
    1401                 :          0 :         Manager *m = userdata;
    1402                 :            :         int interactive, r;
    1403                 :            : 
    1404         [ #  # ]:          0 :         assert(message);
    1405         [ #  # ]:          0 :         assert(m);
    1406                 :            : 
    1407                 :          0 :         r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
    1408         [ #  # ]:          0 :         if (r < 0)
    1409                 :          0 :                 return r;
    1410                 :            : 
    1411         [ #  # ]:          0 :         if (!path_is_normalized(sysfs))
    1412                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", sysfs);
    1413         [ #  # ]:          0 :         if (!path_startswith(sysfs, "/sys"))
    1414                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
    1415                 :            : 
    1416   [ #  #  #  # ]:          0 :         if (SEAT_IS_SELF(seat) || SEAT_IS_AUTO(seat)) {
    1417                 :            :                 Seat *found;
    1418                 :            : 
    1419                 :          0 :                 r = manager_get_seat_from_creds(m, message, seat, error, &found);
    1420         [ #  # ]:          0 :                 if (r < 0)
    1421                 :          0 :                         return r;
    1422                 :            : 
    1423                 :          0 :                 seat = found->id;
    1424                 :            : 
    1425         [ #  # ]:          0 :         } else if (!seat_name_is_valid(seat)) /* Note that a seat does not have to exist yet for this operation to succeed */
    1426                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat name %s is not valid", seat);
    1427                 :            : 
    1428                 :          0 :         r = bus_verify_polkit_async(
    1429                 :            :                         message,
    1430                 :            :                         CAP_SYS_ADMIN,
    1431                 :            :                         "org.freedesktop.login1.attach-device",
    1432                 :            :                         NULL,
    1433                 :            :                         interactive,
    1434                 :            :                         UID_INVALID,
    1435                 :            :                         &m->polkit_registry,
    1436                 :            :                         error);
    1437         [ #  # ]:          0 :         if (r < 0)
    1438                 :          0 :                 return r;
    1439         [ #  # ]:          0 :         if (r == 0)
    1440                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    1441                 :            : 
    1442                 :          0 :         r = attach_device(m, seat, sysfs);
    1443         [ #  # ]:          0 :         if (r < 0)
    1444                 :          0 :                 return r;
    1445                 :            : 
    1446                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1447                 :            : }
    1448                 :            : 
    1449                 :          0 : static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1450                 :          0 :         Manager *m = userdata;
    1451                 :            :         int interactive, r;
    1452                 :            : 
    1453         [ #  # ]:          0 :         assert(message);
    1454         [ #  # ]:          0 :         assert(m);
    1455                 :            : 
    1456                 :          0 :         r = sd_bus_message_read(message, "b", &interactive);
    1457         [ #  # ]:          0 :         if (r < 0)
    1458                 :          0 :                 return r;
    1459                 :            : 
    1460                 :          0 :         r = bus_verify_polkit_async(
    1461                 :            :                         message,
    1462                 :            :                         CAP_SYS_ADMIN,
    1463                 :            :                         "org.freedesktop.login1.flush-devices",
    1464                 :            :                         NULL,
    1465                 :            :                         interactive,
    1466                 :            :                         UID_INVALID,
    1467                 :            :                         &m->polkit_registry,
    1468                 :            :                         error);
    1469         [ #  # ]:          0 :         if (r < 0)
    1470                 :          0 :                 return r;
    1471         [ #  # ]:          0 :         if (r == 0)
    1472                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    1473                 :            : 
    1474                 :          0 :         r = flush_devices(m);
    1475         [ #  # ]:          0 :         if (r < 0)
    1476                 :          0 :                 return r;
    1477                 :            : 
    1478                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1479                 :            : }
    1480                 :            : 
    1481                 :          0 : static int have_multiple_sessions(
    1482                 :            :                 Manager *m,
    1483                 :            :                 uid_t uid) {
    1484                 :            : 
    1485                 :            :         Session *session;
    1486                 :            :         Iterator i;
    1487                 :            : 
    1488         [ #  # ]:          0 :         assert(m);
    1489                 :            : 
    1490                 :            :         /* Check for other users' sessions. Greeter sessions do not
    1491                 :            :          * count, and non-login sessions do not count either. */
    1492         [ #  # ]:          0 :         HASHMAP_FOREACH(session, m->sessions, i)
    1493         [ #  # ]:          0 :                 if (session->class == SESSION_USER &&
    1494         [ #  # ]:          0 :                     session->user->uid != uid)
    1495                 :          0 :                         return true;
    1496                 :            : 
    1497                 :          0 :         return false;
    1498                 :            : }
    1499                 :            : 
    1500                 :          0 : static int bus_manager_log_shutdown(
    1501                 :            :                 Manager *m,
    1502                 :            :                 const char *unit_name) {
    1503                 :            : 
    1504                 :            :         const char *p, *q;
    1505                 :            : 
    1506         [ #  # ]:          0 :         assert(m);
    1507         [ #  # ]:          0 :         assert(unit_name);
    1508                 :            : 
    1509         [ #  # ]:          0 :         if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
    1510                 :          0 :                 p = "MESSAGE=System is powering down";
    1511                 :          0 :                 q = "SHUTDOWN=power-off";
    1512         [ #  # ]:          0 :         } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
    1513                 :          0 :                 p = "MESSAGE=System is rebooting";
    1514                 :          0 :                 q = "SHUTDOWN=reboot";
    1515         [ #  # ]:          0 :         } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
    1516                 :          0 :                 p = "MESSAGE=System is halting";
    1517                 :          0 :                 q = "SHUTDOWN=halt";
    1518         [ #  # ]:          0 :         } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
    1519                 :          0 :                 p = "MESSAGE=System is rebooting with kexec";
    1520                 :          0 :                 q = "SHUTDOWN=kexec";
    1521                 :            :         } else {
    1522                 :          0 :                 p = "MESSAGE=System is shutting down";
    1523                 :          0 :                 q = NULL;
    1524                 :            :         }
    1525                 :            : 
    1526         [ #  # ]:          0 :         if (isempty(m->wall_message))
    1527   [ #  #  #  #  :          0 :                 p = strjoina(p, ".");
          #  #  #  #  #  
                #  #  # ]
    1528                 :            :         else
    1529   [ #  #  #  #  :          0 :                 p = strjoina(p, " (", m->wall_message, ").");
          #  #  #  #  #  
                #  #  # ]
    1530                 :            : 
    1531                 :          0 :         return log_struct(LOG_NOTICE,
    1532                 :            :                           "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
    1533                 :            :                           p,
    1534                 :            :                           q);
    1535                 :            : }
    1536                 :            : 
    1537                 :          0 : static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
    1538                 :          0 :         Manager *m = userdata;
    1539                 :            : 
    1540         [ #  # ]:          0 :         assert(e);
    1541         [ #  # ]:          0 :         assert(m);
    1542                 :            : 
    1543                 :          0 :         m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
    1544                 :          0 :         return 0;
    1545                 :            : }
    1546                 :            : 
    1547                 :          0 : int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
    1548                 :            :         int r;
    1549                 :            : 
    1550         [ #  # ]:          0 :         assert(m);
    1551                 :            : 
    1552         [ #  # ]:          0 :         if (until <= now(CLOCK_MONOTONIC))
    1553                 :          0 :                 return 0;
    1554                 :            : 
    1555                 :            :         /* We want to ignore the lid switch for a while after each
    1556                 :            :          * suspend, and after boot-up. Hence let's install a timer for
    1557                 :            :          * this. As long as the event source exists we ignore the lid
    1558                 :            :          * switch. */
    1559                 :            : 
    1560         [ #  # ]:          0 :         if (m->lid_switch_ignore_event_source) {
    1561                 :            :                 usec_t u;
    1562                 :            : 
    1563                 :          0 :                 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
    1564         [ #  # ]:          0 :                 if (r < 0)
    1565                 :          0 :                         return r;
    1566                 :            : 
    1567         [ #  # ]:          0 :                 if (until <= u)
    1568                 :          0 :                         return 0;
    1569                 :            : 
    1570                 :          0 :                 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
    1571                 :            :         } else
    1572                 :          0 :                 r = sd_event_add_time(
    1573                 :            :                                 m->event,
    1574                 :            :                                 &m->lid_switch_ignore_event_source,
    1575                 :            :                                 CLOCK_MONOTONIC,
    1576                 :            :                                 until, 0,
    1577                 :            :                                 lid_switch_ignore_handler, m);
    1578                 :            : 
    1579                 :          0 :         return r;
    1580                 :            : }
    1581                 :            : 
    1582                 :          0 : static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
    1583                 :          0 :         int active = _active;
    1584                 :            : 
    1585         [ #  # ]:          0 :         assert(m);
    1586   [ #  #  #  # ]:          0 :         assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP));
    1587                 :            : 
    1588         [ #  # ]:          0 :         return sd_bus_emit_signal(m->bus,
    1589                 :            :                                   "/org/freedesktop/login1",
    1590                 :            :                                   "org.freedesktop.login1.Manager",
    1591                 :            :                                   w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep",
    1592                 :            :                                   "b",
    1593                 :            :                                   active);
    1594                 :            : }
    1595                 :            : 
    1596                 :          0 : static int execute_shutdown_or_sleep(
    1597                 :            :                 Manager *m,
    1598                 :            :                 InhibitWhat w,
    1599                 :            :                 const char *unit_name,
    1600                 :            :                 sd_bus_error *error) {
    1601                 :            : 
    1602                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    1603                 :            :         const char *p;
    1604                 :            :         int r;
    1605                 :            : 
    1606         [ #  # ]:          0 :         assert(m);
    1607         [ #  # ]:          0 :         assert(w > 0);
    1608         [ #  # ]:          0 :         assert(w < _INHIBIT_WHAT_MAX);
    1609         [ #  # ]:          0 :         assert(unit_name);
    1610                 :            : 
    1611         [ #  # ]:          0 :         if (w == INHIBIT_SHUTDOWN)
    1612                 :          0 :                 bus_manager_log_shutdown(m, unit_name);
    1613                 :            : 
    1614                 :          0 :         r = sd_bus_call_method(
    1615                 :            :                         m->bus,
    1616                 :            :                         "org.freedesktop.systemd1",
    1617                 :            :                         "/org/freedesktop/systemd1",
    1618                 :            :                         "org.freedesktop.systemd1.Manager",
    1619                 :            :                         "StartUnit",
    1620                 :            :                         error,
    1621                 :            :                         &reply,
    1622                 :            :                         "ss", unit_name, "replace-irreversibly");
    1623         [ #  # ]:          0 :         if (r < 0)
    1624                 :          0 :                 goto error;
    1625                 :            : 
    1626                 :          0 :         r = sd_bus_message_read(reply, "o", &p);
    1627         [ #  # ]:          0 :         if (r < 0)
    1628                 :          0 :                 goto error;
    1629                 :            : 
    1630                 :          0 :         r = free_and_strdup(&m->action_job, p);
    1631         [ #  # ]:          0 :         if (r < 0)
    1632                 :          0 :                 goto error;
    1633                 :            : 
    1634                 :          0 :         m->action_unit = unit_name;
    1635                 :          0 :         m->action_what = w;
    1636                 :            : 
    1637                 :            :         /* Make sure the lid switch is ignored for a while */
    1638                 :          0 :         manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
    1639                 :            : 
    1640                 :          0 :         return 0;
    1641                 :            : 
    1642                 :          0 : error:
    1643                 :            :         /* Tell people that they now may take a lock again */
    1644                 :          0 :         (void) send_prepare_for(m, w, false);
    1645                 :            : 
    1646                 :          0 :         return r;
    1647                 :            : }
    1648                 :            : 
    1649                 :          0 : int manager_dispatch_delayed(Manager *manager, bool timeout) {
    1650                 :            : 
    1651                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    1652                 :          0 :         Inhibitor *offending = NULL;
    1653                 :            :         int r;
    1654                 :            : 
    1655         [ #  # ]:          0 :         assert(manager);
    1656                 :            : 
    1657   [ #  #  #  # ]:          0 :         if (manager->action_what == 0 || manager->action_job)
    1658                 :          0 :                 return 0;
    1659                 :            : 
    1660         [ #  # ]:          0 :         if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
    1661   [ #  #  #  # ]:          0 :                 _cleanup_free_ char *comm = NULL, *u = NULL;
    1662                 :            : 
    1663         [ #  # ]:          0 :                 if (!timeout)
    1664                 :          0 :                         return 0;
    1665                 :            : 
    1666                 :          0 :                 (void) get_process_comm(offending->pid, &comm);
    1667                 :          0 :                 u = uid_to_name(offending->uid);
    1668                 :            : 
    1669         [ #  # ]:          0 :                 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
    1670                 :            :                            offending->uid, strna(u),
    1671                 :            :                            offending->pid, strna(comm));
    1672                 :            :         }
    1673                 :            : 
    1674                 :            :         /* Actually do the operation */
    1675                 :          0 :         r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
    1676         [ #  # ]:          0 :         if (r < 0) {
    1677         [ #  # ]:          0 :                 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
    1678                 :            :                             bus_error_message(&error, r));
    1679                 :            : 
    1680                 :          0 :                 manager->action_unit = NULL;
    1681                 :          0 :                 manager->action_what = 0;
    1682                 :          0 :                 return r;
    1683                 :            :         }
    1684                 :            : 
    1685                 :          0 :         return 1;
    1686                 :            : }
    1687                 :            : 
    1688                 :          0 : static int manager_inhibit_timeout_handler(
    1689                 :            :                         sd_event_source *s,
    1690                 :            :                         uint64_t usec,
    1691                 :            :                         void *userdata) {
    1692                 :            : 
    1693                 :          0 :         Manager *manager = userdata;
    1694                 :            :         int r;
    1695                 :            : 
    1696         [ #  # ]:          0 :         assert(manager);
    1697         [ #  # ]:          0 :         assert(manager->inhibit_timeout_source == s);
    1698                 :            : 
    1699                 :          0 :         r = manager_dispatch_delayed(manager, true);
    1700                 :          0 :         return (r < 0) ? r : 0;
    1701                 :            : }
    1702                 :            : 
    1703                 :          0 : static int delay_shutdown_or_sleep(
    1704                 :            :                 Manager *m,
    1705                 :            :                 InhibitWhat w,
    1706                 :            :                 const char *unit_name) {
    1707                 :            : 
    1708                 :            :         int r;
    1709                 :            :         usec_t timeout_val;
    1710                 :            : 
    1711         [ #  # ]:          0 :         assert(m);
    1712         [ #  # ]:          0 :         assert(w >= 0);
    1713         [ #  # ]:          0 :         assert(w < _INHIBIT_WHAT_MAX);
    1714         [ #  # ]:          0 :         assert(unit_name);
    1715                 :            : 
    1716                 :          0 :         timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
    1717                 :            : 
    1718         [ #  # ]:          0 :         if (m->inhibit_timeout_source) {
    1719                 :          0 :                 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
    1720         [ #  # ]:          0 :                 if (r < 0)
    1721         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
    1722                 :            : 
    1723                 :          0 :                 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
    1724         [ #  # ]:          0 :                 if (r < 0)
    1725         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
    1726                 :            :         } else {
    1727                 :          0 :                 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
    1728                 :            :                                       timeout_val, 0, manager_inhibit_timeout_handler, m);
    1729         [ #  # ]:          0 :                 if (r < 0)
    1730                 :          0 :                         return r;
    1731                 :            :         }
    1732                 :            : 
    1733                 :          0 :         m->action_unit = unit_name;
    1734                 :          0 :         m->action_what = w;
    1735                 :            : 
    1736                 :          0 :         return 0;
    1737                 :            : }
    1738                 :            : 
    1739                 :          0 : int bus_manager_shutdown_or_sleep_now_or_later(
    1740                 :            :                 Manager *m,
    1741                 :            :                 const char *unit_name,
    1742                 :            :                 InhibitWhat w,
    1743                 :            :                 sd_bus_error *error) {
    1744                 :            : 
    1745                 :          0 :         _cleanup_free_ char *load_state = NULL;
    1746                 :            :         bool delayed;
    1747                 :            :         int r;
    1748                 :            : 
    1749         [ #  # ]:          0 :         assert(m);
    1750         [ #  # ]:          0 :         assert(unit_name);
    1751         [ #  # ]:          0 :         assert(w > 0);
    1752         [ #  # ]:          0 :         assert(w < _INHIBIT_WHAT_MAX);
    1753         [ #  # ]:          0 :         assert(!m->action_job);
    1754                 :            : 
    1755                 :          0 :         r = unit_load_state(m->bus, unit_name, &load_state);
    1756         [ #  # ]:          0 :         if (r < 0)
    1757                 :          0 :                 return r;
    1758                 :            : 
    1759         [ #  # ]:          0 :         if (!streq(load_state, "loaded"))
    1760         [ #  # ]:          0 :                 return log_notice_errno(SYNTHETIC_ERRNO(EACCES),
    1761                 :            :                                         "Unit %s is %s, refusing operation.",
    1762                 :            :                                         unit_name, load_state);
    1763                 :            : 
    1764                 :            :         /* Tell everybody to prepare for shutdown/sleep */
    1765                 :          0 :         (void) send_prepare_for(m, w, true);
    1766                 :            : 
    1767                 :          0 :         delayed =
    1768   [ #  #  #  # ]:          0 :                 m->inhibit_delay_max > 0 &&
    1769                 :          0 :                 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
    1770                 :            : 
    1771         [ #  # ]:          0 :         if (delayed)
    1772                 :            :                 /* Shutdown is delayed, keep in mind what we
    1773                 :            :                  * want to do, and start a timeout */
    1774                 :          0 :                 r = delay_shutdown_or_sleep(m, w, unit_name);
    1775                 :            :         else
    1776                 :            :                 /* Shutdown is not delayed, execute it
    1777                 :            :                  * immediately */
    1778                 :          0 :                 r = execute_shutdown_or_sleep(m, w, unit_name, error);
    1779                 :            : 
    1780                 :          0 :         return r;
    1781                 :            : }
    1782                 :            : 
    1783                 :          0 : static int verify_shutdown_creds(
    1784                 :            :                 Manager *m,
    1785                 :            :                 sd_bus_message *message,
    1786                 :            :                 InhibitWhat w,
    1787                 :            :                 bool interactive,
    1788                 :            :                 const char *action,
    1789                 :            :                 const char *action_multiple_sessions,
    1790                 :            :                 const char *action_ignore_inhibit,
    1791                 :            :                 sd_bus_error *error) {
    1792                 :            : 
    1793                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    1794                 :            :         bool multiple_sessions, blocked;
    1795                 :            :         uid_t uid;
    1796                 :            :         int r;
    1797                 :            : 
    1798         [ #  # ]:          0 :         assert(m);
    1799         [ #  # ]:          0 :         assert(message);
    1800         [ #  # ]:          0 :         assert(w >= 0);
    1801         [ #  # ]:          0 :         assert(w <= _INHIBIT_WHAT_MAX);
    1802                 :            : 
    1803                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
    1804         [ #  # ]:          0 :         if (r < 0)
    1805                 :          0 :                 return r;
    1806                 :            : 
    1807                 :          0 :         r = sd_bus_creds_get_euid(creds, &uid);
    1808         [ #  # ]:          0 :         if (r < 0)
    1809                 :          0 :                 return r;
    1810                 :            : 
    1811                 :          0 :         r = have_multiple_sessions(m, uid);
    1812         [ #  # ]:          0 :         if (r < 0)
    1813                 :          0 :                 return r;
    1814                 :            : 
    1815                 :          0 :         multiple_sessions = r > 0;
    1816                 :          0 :         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
    1817                 :            : 
    1818   [ #  #  #  # ]:          0 :         if (multiple_sessions && action_multiple_sessions) {
    1819                 :          0 :                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
    1820         [ #  # ]:          0 :                 if (r < 0)
    1821                 :          0 :                         return r;
    1822         [ #  # ]:          0 :                 if (r == 0)
    1823                 :          0 :                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    1824                 :            :         }
    1825                 :            : 
    1826   [ #  #  #  # ]:          0 :         if (blocked && action_ignore_inhibit) {
    1827                 :          0 :                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
    1828         [ #  # ]:          0 :                 if (r < 0)
    1829                 :          0 :                         return r;
    1830         [ #  # ]:          0 :                 if (r == 0)
    1831                 :          0 :                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    1832                 :            :         }
    1833                 :            : 
    1834   [ #  #  #  #  :          0 :         if (!multiple_sessions && !blocked && action) {
                   #  # ]
    1835                 :          0 :                 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
    1836         [ #  # ]:          0 :                 if (r < 0)
    1837                 :          0 :                         return r;
    1838         [ #  # ]:          0 :                 if (r == 0)
    1839                 :          0 :                         return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    1840                 :            :         }
    1841                 :            : 
    1842                 :          0 :         return 0;
    1843                 :            : }
    1844                 :            : 
    1845                 :          0 : static int method_do_shutdown_or_sleep(
    1846                 :            :                 Manager *m,
    1847                 :            :                 sd_bus_message *message,
    1848                 :            :                 const char *unit_name,
    1849                 :            :                 InhibitWhat w,
    1850                 :            :                 const char *action,
    1851                 :            :                 const char *action_multiple_sessions,
    1852                 :            :                 const char *action_ignore_inhibit,
    1853                 :            :                 const char *sleep_verb,
    1854                 :            :                 sd_bus_error *error) {
    1855                 :            : 
    1856                 :            :         int interactive, r;
    1857                 :            : 
    1858         [ #  # ]:          0 :         assert(m);
    1859         [ #  # ]:          0 :         assert(message);
    1860         [ #  # ]:          0 :         assert(unit_name);
    1861         [ #  # ]:          0 :         assert(w >= 0);
    1862         [ #  # ]:          0 :         assert(w <= _INHIBIT_WHAT_MAX);
    1863                 :            : 
    1864                 :          0 :         r = sd_bus_message_read(message, "b", &interactive);
    1865         [ #  # ]:          0 :         if (r < 0)
    1866                 :          0 :                 return r;
    1867                 :            : 
    1868                 :            :         /* Don't allow multiple jobs being executed at the same time */
    1869         [ #  # ]:          0 :         if (m->action_what > 0)
    1870                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
    1871                 :            :                                          "There's already a shutdown or sleep operation in progress");
    1872                 :            : 
    1873         [ #  # ]:          0 :         if (sleep_verb) {
    1874                 :          0 :                 r = can_sleep(sleep_verb);
    1875         [ #  # ]:          0 :                 if (r == -ENOSPC)
    1876                 :          0 :                         return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
    1877                 :            :                                                 "Not enough swap space for hibernation");
    1878         [ #  # ]:          0 :                 if (r == 0)
    1879                 :          0 :                         return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
    1880                 :            :                                                  "Sleep verb \"%s\" not supported", sleep_verb);
    1881         [ #  # ]:          0 :                 if (r < 0)
    1882                 :          0 :                         return r;
    1883                 :            :         }
    1884                 :            : 
    1885                 :          0 :         r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
    1886                 :            :                                   action_ignore_inhibit, error);
    1887         [ #  # ]:          0 :         if (r != 0)
    1888                 :          0 :                 return r;
    1889                 :            : 
    1890                 :          0 :         r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
    1891         [ #  # ]:          0 :         if (r < 0)
    1892                 :          0 :                 return r;
    1893                 :            : 
    1894                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    1895                 :            : }
    1896                 :            : 
    1897                 :          0 : static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1898                 :          0 :         Manager *m = userdata;
    1899                 :            : 
    1900                 :          0 :         return method_do_shutdown_or_sleep(
    1901                 :            :                         m, message,
    1902                 :            :                         SPECIAL_POWEROFF_TARGET,
    1903                 :            :                         INHIBIT_SHUTDOWN,
    1904                 :            :                         "org.freedesktop.login1.power-off",
    1905                 :            :                         "org.freedesktop.login1.power-off-multiple-sessions",
    1906                 :            :                         "org.freedesktop.login1.power-off-ignore-inhibit",
    1907                 :            :                         NULL,
    1908                 :            :                         error);
    1909                 :            : }
    1910                 :            : 
    1911                 :          0 : static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1912                 :          0 :         Manager *m = userdata;
    1913                 :            : 
    1914                 :          0 :         return method_do_shutdown_or_sleep(
    1915                 :            :                         m, message,
    1916                 :            :                         SPECIAL_REBOOT_TARGET,
    1917                 :            :                         INHIBIT_SHUTDOWN,
    1918                 :            :                         "org.freedesktop.login1.reboot",
    1919                 :            :                         "org.freedesktop.login1.reboot-multiple-sessions",
    1920                 :            :                         "org.freedesktop.login1.reboot-ignore-inhibit",
    1921                 :            :                         NULL,
    1922                 :            :                         error);
    1923                 :            : }
    1924                 :            : 
    1925                 :          0 : static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1926                 :          0 :         Manager *m = userdata;
    1927                 :            : 
    1928                 :          0 :         return method_do_shutdown_or_sleep(
    1929                 :            :                         m, message,
    1930                 :            :                         SPECIAL_HALT_TARGET,
    1931                 :            :                         INHIBIT_SHUTDOWN,
    1932                 :            :                         "org.freedesktop.login1.halt",
    1933                 :            :                         "org.freedesktop.login1.halt-multiple-sessions",
    1934                 :            :                         "org.freedesktop.login1.halt-ignore-inhibit",
    1935                 :            :                         NULL,
    1936                 :            :                         error);
    1937                 :            : }
    1938                 :            : 
    1939                 :          0 : static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1940                 :          0 :         Manager *m = userdata;
    1941                 :            : 
    1942                 :          0 :         return method_do_shutdown_or_sleep(
    1943                 :            :                         m, message,
    1944                 :            :                         SPECIAL_SUSPEND_TARGET,
    1945                 :            :                         INHIBIT_SLEEP,
    1946                 :            :                         "org.freedesktop.login1.suspend",
    1947                 :            :                         "org.freedesktop.login1.suspend-multiple-sessions",
    1948                 :            :                         "org.freedesktop.login1.suspend-ignore-inhibit",
    1949                 :            :                         "suspend",
    1950                 :            :                         error);
    1951                 :            : }
    1952                 :            : 
    1953                 :          0 : static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1954                 :          0 :         Manager *m = userdata;
    1955                 :            : 
    1956                 :          0 :         return method_do_shutdown_or_sleep(
    1957                 :            :                         m, message,
    1958                 :            :                         SPECIAL_HIBERNATE_TARGET,
    1959                 :            :                         INHIBIT_SLEEP,
    1960                 :            :                         "org.freedesktop.login1.hibernate",
    1961                 :            :                         "org.freedesktop.login1.hibernate-multiple-sessions",
    1962                 :            :                         "org.freedesktop.login1.hibernate-ignore-inhibit",
    1963                 :            :                         "hibernate",
    1964                 :            :                         error);
    1965                 :            : }
    1966                 :            : 
    1967                 :          0 : static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1968                 :          0 :         Manager *m = userdata;
    1969                 :            : 
    1970                 :          0 :         return method_do_shutdown_or_sleep(
    1971                 :            :                         m, message,
    1972                 :            :                         SPECIAL_HYBRID_SLEEP_TARGET,
    1973                 :            :                         INHIBIT_SLEEP,
    1974                 :            :                         "org.freedesktop.login1.hibernate",
    1975                 :            :                         "org.freedesktop.login1.hibernate-multiple-sessions",
    1976                 :            :                         "org.freedesktop.login1.hibernate-ignore-inhibit",
    1977                 :            :                         "hybrid-sleep",
    1978                 :            :                         error);
    1979                 :            : }
    1980                 :            : 
    1981                 :          0 : static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    1982                 :          0 :         Manager *m = userdata;
    1983                 :            : 
    1984                 :          0 :         return method_do_shutdown_or_sleep(
    1985                 :            :                         m, message,
    1986                 :            :                         SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
    1987                 :            :                         INHIBIT_SLEEP,
    1988                 :            :                         "org.freedesktop.login1.hibernate",
    1989                 :            :                         "org.freedesktop.login1.hibernate-multiple-sessions",
    1990                 :            :                         "org.freedesktop.login1.hibernate-ignore-inhibit",
    1991                 :            :                         "hybrid-sleep",
    1992                 :            :                         error);
    1993                 :            : }
    1994                 :            : 
    1995                 :          0 : static int nologin_timeout_handler(
    1996                 :            :                         sd_event_source *s,
    1997                 :            :                         uint64_t usec,
    1998                 :            :                         void *userdata) {
    1999                 :            : 
    2000                 :          0 :         Manager *m = userdata;
    2001                 :            : 
    2002         [ #  # ]:          0 :         log_info("Creating /run/nologin, blocking further logins...");
    2003                 :            : 
    2004                 :          0 :         m->unlink_nologin =
    2005                 :          0 :                 create_shutdown_run_nologin_or_warn() >= 0;
    2006                 :            : 
    2007                 :          0 :         return 0;
    2008                 :            : }
    2009                 :            : 
    2010                 :          0 : static int update_schedule_file(Manager *m) {
    2011                 :          0 :         _cleanup_free_ char *temp_path = NULL;
    2012                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
    2013                 :            :         int r;
    2014                 :            : 
    2015         [ #  # ]:          0 :         assert(m);
    2016                 :            : 
    2017                 :          0 :         r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
    2018         [ #  # ]:          0 :         if (r < 0)
    2019         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
    2020                 :            : 
    2021                 :          0 :         r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
    2022         [ #  # ]:          0 :         if (r < 0)
    2023         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
    2024                 :            : 
    2025                 :          0 :         (void) fchmod(fileno(f), 0644);
    2026                 :            : 
    2027                 :          0 :         fprintf(f,
    2028                 :            :                 "USEC="USEC_FMT"\n"
    2029                 :            :                 "WARN_WALL=%i\n"
    2030                 :            :                 "MODE=%s\n",
    2031                 :            :                 m->scheduled_shutdown_timeout,
    2032                 :            :                 m->enable_wall_messages,
    2033                 :            :                 m->scheduled_shutdown_type);
    2034                 :            : 
    2035         [ #  # ]:          0 :         if (!isempty(m->wall_message)) {
    2036         [ #  # ]:          0 :                 _cleanup_free_ char *t;
    2037                 :            : 
    2038                 :          0 :                 t = cescape(m->wall_message);
    2039         [ #  # ]:          0 :                 if (!t) {
    2040                 :          0 :                         r = -ENOMEM;
    2041                 :          0 :                         goto fail;
    2042                 :            :                 }
    2043                 :            : 
    2044                 :          0 :                 fprintf(f, "WALL_MESSAGE=%s\n", t);
    2045                 :            :         }
    2046                 :            : 
    2047                 :          0 :         r = fflush_and_check(f);
    2048         [ #  # ]:          0 :         if (r < 0)
    2049                 :          0 :                 goto fail;
    2050                 :            : 
    2051         [ #  # ]:          0 :         if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
    2052                 :          0 :                 r = -errno;
    2053                 :          0 :                 goto fail;
    2054                 :            :         }
    2055                 :            : 
    2056                 :          0 :         return 0;
    2057                 :            : 
    2058                 :          0 : fail:
    2059                 :          0 :         (void) unlink(temp_path);
    2060                 :          0 :         (void) unlink("/run/systemd/shutdown/scheduled");
    2061                 :            : 
    2062         [ #  # ]:          0 :         return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
    2063                 :            : }
    2064                 :            : 
    2065                 :          0 : static void reset_scheduled_shutdown(Manager *m) {
    2066         [ #  # ]:          0 :         assert(m);
    2067                 :            : 
    2068                 :          0 :         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
    2069                 :          0 :         m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
    2070                 :          0 :         m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
    2071                 :            : 
    2072                 :          0 :         m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
    2073                 :          0 :         m->scheduled_shutdown_timeout = 0;
    2074                 :          0 :         m->shutdown_dry_run = false;
    2075                 :            : 
    2076         [ #  # ]:          0 :         if (m->unlink_nologin) {
    2077                 :          0 :                 (void) unlink_or_warn("/run/nologin");
    2078                 :          0 :                 m->unlink_nologin = false;
    2079                 :            :         }
    2080                 :            : 
    2081                 :          0 :         (void) unlink("/run/systemd/shutdown/scheduled");
    2082                 :          0 : }
    2083                 :            : 
    2084                 :          0 : static int manager_scheduled_shutdown_handler(
    2085                 :            :                         sd_event_source *s,
    2086                 :            :                         uint64_t usec,
    2087                 :            :                         void *userdata) {
    2088                 :            : 
    2089                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    2090                 :          0 :         Manager *m = userdata;
    2091                 :            :         const char *target;
    2092                 :            :         int r;
    2093                 :            : 
    2094         [ #  # ]:          0 :         assert(m);
    2095                 :            : 
    2096         [ #  # ]:          0 :         if (isempty(m->scheduled_shutdown_type))
    2097                 :          0 :                 return 0;
    2098                 :            : 
    2099         [ #  # ]:          0 :         if (streq(m->scheduled_shutdown_type, "poweroff"))
    2100                 :          0 :                 target = SPECIAL_POWEROFF_TARGET;
    2101         [ #  # ]:          0 :         else if (streq(m->scheduled_shutdown_type, "reboot"))
    2102                 :          0 :                 target = SPECIAL_REBOOT_TARGET;
    2103         [ #  # ]:          0 :         else if (streq(m->scheduled_shutdown_type, "halt"))
    2104                 :          0 :                 target = SPECIAL_HALT_TARGET;
    2105                 :            :         else
    2106                 :          0 :                 assert_not_reached("unexpected shutdown type");
    2107                 :            : 
    2108                 :            :         /* Don't allow multiple jobs being executed at the same time */
    2109         [ #  # ]:          0 :         if (m->action_what > 0) {
    2110                 :          0 :                 r = -EALREADY;
    2111         [ #  # ]:          0 :                 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
    2112                 :          0 :                 goto error;
    2113                 :            :         }
    2114                 :            : 
    2115         [ #  # ]:          0 :         if (m->shutdown_dry_run) {
    2116                 :            :                 /* We do not process delay inhibitors here.  Otherwise, we
    2117                 :            :                  * would have to be considered "in progress" (like the check
    2118                 :            :                  * above) for some seconds after our admin has seen the final
    2119                 :            :                  * wall message. */
    2120                 :            : 
    2121                 :          0 :                 bus_manager_log_shutdown(m, target);
    2122         [ #  # ]:          0 :                 log_info("Running in dry run, suppressing action.");
    2123                 :          0 :                 reset_scheduled_shutdown(m);
    2124                 :            : 
    2125                 :          0 :                 return 0;
    2126                 :            :         }
    2127                 :            : 
    2128                 :          0 :         r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
    2129         [ #  # ]:          0 :         if (r < 0) {
    2130         [ #  # ]:          0 :                 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
    2131                 :          0 :                 goto error;
    2132                 :            :         }
    2133                 :            : 
    2134                 :          0 :         return 0;
    2135                 :            : 
    2136                 :          0 : error:
    2137                 :          0 :         reset_scheduled_shutdown(m);
    2138                 :          0 :         return r;
    2139                 :            : }
    2140                 :            : 
    2141                 :          0 : static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2142                 :          0 :         Manager *m = userdata;
    2143                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    2144                 :          0 :         const char *action_multiple_sessions = NULL;
    2145                 :          0 :         const char *action_ignore_inhibit = NULL;
    2146                 :          0 :         const char *action = NULL;
    2147                 :            :         uint64_t elapse;
    2148                 :            :         char *type;
    2149                 :            :         int r;
    2150                 :          0 :         bool dry_run = false;
    2151                 :            : 
    2152         [ #  # ]:          0 :         assert(m);
    2153         [ #  # ]:          0 :         assert(message);
    2154                 :            : 
    2155                 :          0 :         r = sd_bus_message_read(message, "st", &type, &elapse);
    2156         [ #  # ]:          0 :         if (r < 0)
    2157                 :          0 :                 return r;
    2158                 :            : 
    2159         [ #  # ]:          0 :         if (startswith(type, "dry-")) {
    2160                 :          0 :                 type += 4;
    2161                 :          0 :                 dry_run = true;
    2162                 :            :         }
    2163                 :            : 
    2164         [ #  # ]:          0 :         if (streq(type, "poweroff")) {
    2165                 :          0 :                 action = "org.freedesktop.login1.power-off";
    2166                 :          0 :                 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
    2167                 :          0 :                 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
    2168         [ #  # ]:          0 :         } else if (streq(type, "reboot")) {
    2169                 :          0 :                 action = "org.freedesktop.login1.reboot";
    2170                 :          0 :                 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
    2171                 :          0 :                 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
    2172         [ #  # ]:          0 :         } else if (streq(type, "halt")) {
    2173                 :          0 :                 action = "org.freedesktop.login1.halt";
    2174                 :          0 :                 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
    2175                 :          0 :                 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
    2176                 :            :         } else
    2177                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
    2178                 :            : 
    2179                 :          0 :         r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
    2180                 :            :                                   action, action_multiple_sessions, action_ignore_inhibit, error);
    2181         [ #  # ]:          0 :         if (r != 0)
    2182                 :          0 :                 return r;
    2183                 :            : 
    2184         [ #  # ]:          0 :         if (m->scheduled_shutdown_timeout_source) {
    2185                 :          0 :                 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
    2186         [ #  # ]:          0 :                 if (r < 0)
    2187         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
    2188                 :            : 
    2189                 :          0 :                 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
    2190         [ #  # ]:          0 :                 if (r < 0)
    2191         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
    2192                 :            :         } else {
    2193                 :          0 :                 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
    2194                 :            :                                       CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
    2195         [ #  # ]:          0 :                 if (r < 0)
    2196         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_add_time() failed: %m");
    2197                 :            :         }
    2198                 :            : 
    2199                 :          0 :         r = free_and_strdup(&m->scheduled_shutdown_type, type);
    2200         [ #  # ]:          0 :         if (r < 0) {
    2201                 :          0 :                 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
    2202                 :          0 :                 return log_oom();
    2203                 :            :         }
    2204                 :            : 
    2205                 :          0 :         m->shutdown_dry_run = dry_run;
    2206                 :            : 
    2207         [ #  # ]:          0 :         if (m->nologin_timeout_source) {
    2208                 :          0 :                 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
    2209         [ #  # ]:          0 :                 if (r < 0)
    2210         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_source_set_time() failed: %m");
    2211                 :            : 
    2212                 :          0 :                 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
    2213         [ #  # ]:          0 :                 if (r < 0)
    2214         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
    2215                 :            :         } else {
    2216                 :          0 :                 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
    2217                 :            :                                       CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
    2218         [ #  # ]:          0 :                 if (r < 0)
    2219         [ #  # ]:          0 :                         return log_error_errno(r, "sd_event_add_time() failed: %m");
    2220                 :            :         }
    2221                 :            : 
    2222                 :          0 :         m->scheduled_shutdown_timeout = elapse;
    2223                 :            : 
    2224                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
    2225         [ #  # ]:          0 :         if (r >= 0) {
    2226                 :          0 :                 const char *tty = NULL;
    2227                 :            : 
    2228                 :          0 :                 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
    2229                 :          0 :                 (void) sd_bus_creds_get_tty(creds, &tty);
    2230                 :            : 
    2231                 :          0 :                 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
    2232         [ #  # ]:          0 :                 if (r < 0) {
    2233                 :          0 :                         m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
    2234                 :          0 :                         return log_oom();
    2235                 :            :                 }
    2236                 :            :         }
    2237                 :            : 
    2238                 :          0 :         r = manager_setup_wall_message_timer(m);
    2239         [ #  # ]:          0 :         if (r < 0)
    2240                 :          0 :                 return r;
    2241                 :            : 
    2242                 :          0 :         r = update_schedule_file(m);
    2243         [ #  # ]:          0 :         if (r < 0)
    2244                 :          0 :                 return r;
    2245                 :            : 
    2246                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    2247                 :            : }
    2248                 :            : 
    2249                 :          0 : static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2250                 :          0 :         Manager *m = userdata;
    2251                 :            :         bool cancelled;
    2252                 :            : 
    2253         [ #  # ]:          0 :         assert(m);
    2254         [ #  # ]:          0 :         assert(message);
    2255                 :            : 
    2256                 :          0 :         cancelled = m->scheduled_shutdown_type != NULL;
    2257                 :          0 :         reset_scheduled_shutdown(m);
    2258                 :            : 
    2259   [ #  #  #  # ]:          0 :         if (cancelled && m->enable_wall_messages) {
    2260                 :          0 :                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    2261                 :          0 :                 _cleanup_free_ char *username = NULL;
    2262                 :          0 :                 const char *tty = NULL;
    2263                 :          0 :                 uid_t uid = 0;
    2264                 :            :                 int r;
    2265                 :            : 
    2266                 :          0 :                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
    2267         [ #  # ]:          0 :                 if (r >= 0) {
    2268                 :          0 :                         (void) sd_bus_creds_get_uid(creds, &uid);
    2269                 :          0 :                         (void) sd_bus_creds_get_tty(creds, &tty);
    2270                 :            :                 }
    2271                 :            : 
    2272                 :          0 :                 username = uid_to_name(uid);
    2273                 :          0 :                 utmp_wall("The system shutdown has been cancelled",
    2274                 :            :                           username, tty, logind_wall_tty_filter, m);
    2275                 :            :         }
    2276                 :            : 
    2277                 :          0 :         return sd_bus_reply_method_return(message, "b", cancelled);
    2278                 :            : }
    2279                 :            : 
    2280                 :          0 : static int method_can_shutdown_or_sleep(
    2281                 :            :                 Manager *m,
    2282                 :            :                 sd_bus_message *message,
    2283                 :            :                 InhibitWhat w,
    2284                 :            :                 const char *action,
    2285                 :            :                 const char *action_multiple_sessions,
    2286                 :            :                 const char *action_ignore_inhibit,
    2287                 :            :                 const char *sleep_verb,
    2288                 :            :                 sd_bus_error *error) {
    2289                 :            : 
    2290                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    2291                 :            :         HandleAction handle;
    2292                 :            :         bool multiple_sessions, challenge, blocked;
    2293                 :          0 :         const char *result = NULL;
    2294                 :            :         uid_t uid;
    2295                 :            :         int r;
    2296                 :            : 
    2297         [ #  # ]:          0 :         assert(m);
    2298         [ #  # ]:          0 :         assert(message);
    2299         [ #  # ]:          0 :         assert(w >= 0);
    2300         [ #  # ]:          0 :         assert(w <= _INHIBIT_WHAT_MAX);
    2301         [ #  # ]:          0 :         assert(action);
    2302         [ #  # ]:          0 :         assert(action_multiple_sessions);
    2303         [ #  # ]:          0 :         assert(action_ignore_inhibit);
    2304                 :            : 
    2305         [ #  # ]:          0 :         if (sleep_verb) {
    2306                 :          0 :                 r = can_sleep(sleep_verb);
    2307   [ #  #  #  # ]:          0 :                 if (IN_SET(r,  0, -ENOSPC))
    2308                 :          0 :                         return sd_bus_reply_method_return(message, "s", "na");
    2309         [ #  # ]:          0 :                 if (r < 0)
    2310                 :          0 :                         return r;
    2311                 :            :         }
    2312                 :            : 
    2313                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
    2314         [ #  # ]:          0 :         if (r < 0)
    2315                 :          0 :                 return r;
    2316                 :            : 
    2317                 :          0 :         r = sd_bus_creds_get_euid(creds, &uid);
    2318         [ #  # ]:          0 :         if (r < 0)
    2319                 :          0 :                 return r;
    2320                 :            : 
    2321                 :          0 :         r = have_multiple_sessions(m, uid);
    2322         [ #  # ]:          0 :         if (r < 0)
    2323                 :          0 :                 return r;
    2324                 :            : 
    2325                 :          0 :         multiple_sessions = r > 0;
    2326                 :          0 :         blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
    2327                 :            : 
    2328                 :          0 :         handle = handle_action_from_string(sleep_verb);
    2329         [ #  # ]:          0 :         if (handle >= 0) {
    2330                 :            :                 const char *target;
    2331                 :            : 
    2332                 :          0 :                 target = manager_target_for_action(handle);
    2333         [ #  # ]:          0 :                 if (target) {
    2334      [ #  #  # ]:          0 :                         _cleanup_free_ char *load_state = NULL;
    2335                 :            : 
    2336                 :          0 :                         r = unit_load_state(m->bus, target, &load_state);
    2337         [ #  # ]:          0 :                         if (r < 0)
    2338                 :          0 :                                 return r;
    2339                 :            : 
    2340         [ #  # ]:          0 :                         if (!streq(load_state, "loaded")) {
    2341                 :          0 :                                 result = "no";
    2342                 :          0 :                                 goto finish;
    2343                 :            :                         }
    2344                 :            :                 }
    2345                 :            :         }
    2346                 :            : 
    2347         [ #  # ]:          0 :         if (multiple_sessions) {
    2348                 :          0 :                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
    2349         [ #  # ]:          0 :                 if (r < 0)
    2350                 :          0 :                         return r;
    2351                 :            : 
    2352         [ #  # ]:          0 :                 if (r > 0)
    2353                 :          0 :                         result = "yes";
    2354         [ #  # ]:          0 :                 else if (challenge)
    2355                 :          0 :                         result = "challenge";
    2356                 :            :                 else
    2357                 :          0 :                         result = "no";
    2358                 :            :         }
    2359                 :            : 
    2360         [ #  # ]:          0 :         if (blocked) {
    2361                 :          0 :                 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
    2362         [ #  # ]:          0 :                 if (r < 0)
    2363                 :          0 :                         return r;
    2364                 :            : 
    2365         [ #  # ]:          0 :                 if (r > 0) {
    2366         [ #  # ]:          0 :                         if (!result)
    2367                 :          0 :                                 result = "yes";
    2368         [ #  # ]:          0 :                 } else if (challenge) {
    2369   [ #  #  #  # ]:          0 :                         if (!result || streq(result, "yes"))
    2370                 :          0 :                                 result = "challenge";
    2371                 :            :                 } else
    2372                 :          0 :                         result = "no";
    2373                 :            :         }
    2374                 :            : 
    2375   [ #  #  #  # ]:          0 :         if (!multiple_sessions && !blocked) {
    2376                 :            :                 /* If neither inhibit nor multiple sessions
    2377                 :            :                  * apply then just check the normal policy */
    2378                 :            : 
    2379                 :          0 :                 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
    2380         [ #  # ]:          0 :                 if (r < 0)
    2381                 :          0 :                         return r;
    2382                 :            : 
    2383         [ #  # ]:          0 :                 if (r > 0)
    2384                 :          0 :                         result = "yes";
    2385         [ #  # ]:          0 :                 else if (challenge)
    2386                 :          0 :                         result = "challenge";
    2387                 :            :                 else
    2388                 :          0 :                         result = "no";
    2389                 :            :         }
    2390                 :            : 
    2391                 :          0 :  finish:
    2392                 :          0 :         return sd_bus_reply_method_return(message, "s", result);
    2393                 :            : }
    2394                 :            : 
    2395                 :          0 : static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2396                 :          0 :         Manager *m = userdata;
    2397                 :            : 
    2398                 :          0 :         return method_can_shutdown_or_sleep(
    2399                 :            :                         m, message,
    2400                 :            :                         INHIBIT_SHUTDOWN,
    2401                 :            :                         "org.freedesktop.login1.power-off",
    2402                 :            :                         "org.freedesktop.login1.power-off-multiple-sessions",
    2403                 :            :                         "org.freedesktop.login1.power-off-ignore-inhibit",
    2404                 :            :                         NULL,
    2405                 :            :                         error);
    2406                 :            : }
    2407                 :            : 
    2408                 :          0 : static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2409                 :          0 :         Manager *m = userdata;
    2410                 :            : 
    2411                 :          0 :         return method_can_shutdown_or_sleep(
    2412                 :            :                         m, message,
    2413                 :            :                         INHIBIT_SHUTDOWN,
    2414                 :            :                         "org.freedesktop.login1.reboot",
    2415                 :            :                         "org.freedesktop.login1.reboot-multiple-sessions",
    2416                 :            :                         "org.freedesktop.login1.reboot-ignore-inhibit",
    2417                 :            :                         NULL,
    2418                 :            :                         error);
    2419                 :            : }
    2420                 :            : 
    2421                 :          0 : static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2422                 :          0 :         Manager *m = userdata;
    2423                 :            : 
    2424                 :          0 :         return method_can_shutdown_or_sleep(
    2425                 :            :                         m, message,
    2426                 :            :                         INHIBIT_SHUTDOWN,
    2427                 :            :                         "org.freedesktop.login1.halt",
    2428                 :            :                         "org.freedesktop.login1.halt-multiple-sessions",
    2429                 :            :                         "org.freedesktop.login1.halt-ignore-inhibit",
    2430                 :            :                         NULL,
    2431                 :            :                         error);
    2432                 :            : }
    2433                 :            : 
    2434                 :          0 : static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2435                 :          0 :         Manager *m = userdata;
    2436                 :            : 
    2437                 :          0 :         return method_can_shutdown_or_sleep(
    2438                 :            :                         m, message,
    2439                 :            :                         INHIBIT_SLEEP,
    2440                 :            :                         "org.freedesktop.login1.suspend",
    2441                 :            :                         "org.freedesktop.login1.suspend-multiple-sessions",
    2442                 :            :                         "org.freedesktop.login1.suspend-ignore-inhibit",
    2443                 :            :                         "suspend",
    2444                 :            :                         error);
    2445                 :            : }
    2446                 :            : 
    2447                 :          0 : static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2448                 :          0 :         Manager *m = userdata;
    2449                 :            : 
    2450                 :          0 :         return method_can_shutdown_or_sleep(
    2451                 :            :                         m, message,
    2452                 :            :                         INHIBIT_SLEEP,
    2453                 :            :                         "org.freedesktop.login1.hibernate",
    2454                 :            :                         "org.freedesktop.login1.hibernate-multiple-sessions",
    2455                 :            :                         "org.freedesktop.login1.hibernate-ignore-inhibit",
    2456                 :            :                         "hibernate",
    2457                 :            :                         error);
    2458                 :            : }
    2459                 :            : 
    2460                 :          0 : static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2461                 :          0 :         Manager *m = userdata;
    2462                 :            : 
    2463                 :          0 :         return method_can_shutdown_or_sleep(
    2464                 :            :                         m, message,
    2465                 :            :                         INHIBIT_SLEEP,
    2466                 :            :                         "org.freedesktop.login1.hibernate",
    2467                 :            :                         "org.freedesktop.login1.hibernate-multiple-sessions",
    2468                 :            :                         "org.freedesktop.login1.hibernate-ignore-inhibit",
    2469                 :            :                         "hybrid-sleep",
    2470                 :            :                         error);
    2471                 :            : }
    2472                 :            : 
    2473                 :          0 : static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    2474                 :          0 :         Manager *m = userdata;
    2475                 :            : 
    2476                 :          0 :         return method_can_shutdown_or_sleep(
    2477                 :            :                         m, message,
    2478                 :            :                         INHIBIT_SLEEP,
    2479                 :            :                         "org.freedesktop.login1.hibernate",
    2480                 :            :                         "org.freedesktop.login1.hibernate-multiple-sessions",
    2481                 :            :                         "org.freedesktop.login1.hibernate-ignore-inhibit",
    2482                 :            :                         "suspend-then-hibernate",
    2483                 :            :                         error);
    2484                 :            : }
    2485                 :            : 
    2486                 :          0 : static int property_get_reboot_parameter(
    2487                 :            :                 sd_bus *bus,
    2488                 :            :                 const char *path,
    2489                 :            :                 const char *interface,
    2490                 :            :                 const char *property,
    2491                 :            :                 sd_bus_message *reply,
    2492                 :            :                 void *userdata,
    2493                 :            :                 sd_bus_error *error) {
    2494                 :          0 :         _cleanup_free_ char *parameter = NULL;
    2495                 :            :         int r;
    2496                 :            : 
    2497         [ #  # ]:          0 :         assert(bus);
    2498         [ #  # ]:          0 :         assert(reply);
    2499         [ #  # ]:          0 :         assert(userdata);
    2500                 :            : 
    2501                 :          0 :         r = read_reboot_parameter(&parameter);
    2502         [ #  # ]:          0 :         if (r < 0)
    2503                 :          0 :                 return r;
    2504                 :            : 
    2505                 :          0 :         return sd_bus_message_append(reply, "s", parameter);
    2506                 :            : }
    2507                 :            : 
    2508                 :          0 : static int method_set_reboot_parameter(
    2509                 :            :                 sd_bus_message *message,
    2510                 :            :                 void *userdata,
    2511                 :            :                 sd_bus_error *error) {
    2512                 :            : 
    2513                 :          0 :         Manager *m = userdata;
    2514                 :            :         const char *arg;
    2515                 :            :         int r;
    2516                 :            : 
    2517         [ #  # ]:          0 :         assert(message);
    2518         [ #  # ]:          0 :         assert(m);
    2519                 :            : 
    2520                 :          0 :         r = sd_bus_message_read(message, "s", &arg);
    2521         [ #  # ]:          0 :         if (r < 0)
    2522                 :          0 :                 return r;
    2523                 :            : 
    2524                 :          0 :         r = detect_container();
    2525         [ #  # ]:          0 :         if (r < 0)
    2526                 :          0 :                 return r;
    2527         [ #  # ]:          0 :         if (r > 0)
    2528                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
    2529                 :            :                                          "Reboot parameter not supported in containers, refusing.");
    2530                 :            : 
    2531                 :          0 :         r = bus_verify_polkit_async(message,
    2532                 :            :                                     CAP_SYS_ADMIN,
    2533                 :            :                                     "org.freedesktop.login1.set-reboot-parameter",
    2534                 :            :                                     NULL,
    2535                 :            :                                     false,
    2536                 :            :                                     UID_INVALID,
    2537                 :            :                                     &m->polkit_registry,
    2538                 :            :                                     error);
    2539         [ #  # ]:          0 :         if (r < 0)
    2540                 :          0 :                 return r;
    2541         [ #  # ]:          0 :         if (r == 0)
    2542                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    2543                 :            : 
    2544                 :          0 :         r = update_reboot_parameter_and_warn(arg, false);
    2545         [ #  # ]:          0 :         if (r < 0)
    2546                 :          0 :                 return r;
    2547                 :            : 
    2548                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    2549                 :            : }
    2550                 :            : 
    2551                 :          0 : static int method_can_reboot_parameter(
    2552                 :            :                 sd_bus_message *message,
    2553                 :            :                 void *userdata,
    2554                 :            :                 sd_bus_error *error) {
    2555                 :            : 
    2556                 :          0 :         Manager *m = userdata;
    2557                 :            :         int r;
    2558                 :            : 
    2559         [ #  # ]:          0 :         assert(message);
    2560         [ #  # ]:          0 :         assert(m);
    2561                 :            : 
    2562                 :          0 :         r = detect_container();
    2563         [ #  # ]:          0 :         if (r < 0)
    2564                 :          0 :                 return r;
    2565         [ #  # ]:          0 :         if (r > 0) /* Inside containers, specifying a reboot parameter, doesn't make much sense */
    2566                 :          0 :                 return sd_bus_reply_method_return(message, "s", "na");
    2567                 :            : 
    2568                 :          0 :         return return_test_polkit(
    2569                 :            :                         message,
    2570                 :            :                         CAP_SYS_ADMIN,
    2571                 :            :                         "org.freedesktop.login1.set-reboot-parameter",
    2572                 :            :                         NULL,
    2573                 :            :                         UID_INVALID,
    2574                 :            :                         error);
    2575                 :            : }
    2576                 :            : 
    2577                 :          0 : static int property_get_reboot_to_firmware_setup(
    2578                 :            :                 sd_bus *bus,
    2579                 :            :                 const char *path,
    2580                 :            :                 const char *interface,
    2581                 :            :                 const char *property,
    2582                 :            :                 sd_bus_message *reply,
    2583                 :            :                 void *userdata,
    2584                 :            :                 sd_bus_error *error) {
    2585                 :            :         int r;
    2586                 :            : 
    2587         [ #  # ]:          0 :         assert(bus);
    2588         [ #  # ]:          0 :         assert(reply);
    2589         [ #  # ]:          0 :         assert(userdata);
    2590                 :            : 
    2591                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
    2592         [ #  # ]:          0 :         if (r == -ENXIO) {
    2593                 :            :                 /* EFI case: let's see what is currently configured in the EFI variables */
    2594                 :          0 :                 r = efi_get_reboot_to_firmware();
    2595   [ #  #  #  # ]:          0 :                 if (r < 0 && r != -EOPNOTSUPP)
    2596         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m");
    2597         [ #  # ]:          0 :         } else if (r < 0)
    2598         [ #  # ]:          0 :                 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
    2599         [ #  # ]:          0 :         else if (r > 0) {
    2600                 :            :                 /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */
    2601         [ #  # ]:          0 :                 if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) {
    2602         [ #  # ]:          0 :                         if (errno != ENOENT)
    2603         [ #  # ]:          0 :                                 log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m");
    2604                 :            : 
    2605                 :          0 :                         r = false;
    2606                 :            :                 } else
    2607                 :          0 :                         r = true;
    2608                 :            :         }
    2609                 :            : 
    2610                 :          0 :         return sd_bus_message_append(reply, "b", r > 0);
    2611                 :            : }
    2612                 :            : 
    2613                 :          0 : static int method_set_reboot_to_firmware_setup(
    2614                 :            :                 sd_bus_message *message,
    2615                 :            :                 void *userdata,
    2616                 :            :                 sd_bus_error *error) {
    2617                 :            : 
    2618                 :          0 :         Manager *m = userdata;
    2619                 :            :         bool use_efi;
    2620                 :            :         int b, r;
    2621                 :            : 
    2622         [ #  # ]:          0 :         assert(message);
    2623         [ #  # ]:          0 :         assert(m);
    2624                 :            : 
    2625                 :          0 :         r = sd_bus_message_read(message, "b", &b);
    2626         [ #  # ]:          0 :         if (r < 0)
    2627                 :          0 :                 return r;
    2628                 :            : 
    2629                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
    2630         [ #  # ]:          0 :         if (r == -ENXIO) {
    2631                 :            :                 /* EFI case: let's see what the firmware supports */
    2632                 :            : 
    2633                 :          0 :                 r = efi_reboot_to_firmware_supported();
    2634         [ #  # ]:          0 :                 if (r == -EOPNOTSUPP)
    2635                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
    2636         [ #  # ]:          0 :                 if (r < 0)
    2637                 :          0 :                         return r;
    2638                 :            : 
    2639                 :          0 :                 use_efi = true;
    2640                 :            : 
    2641         [ #  # ]:          0 :         } else if (r <= 0) {
    2642                 :            :                 /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */
    2643                 :            : 
    2644         [ #  # ]:          0 :                 if (r < 0)
    2645         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
    2646                 :            : 
    2647                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
    2648                 :            :         } else
    2649                 :            :                 /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
    2650                 :          0 :                 use_efi = false;
    2651                 :            : 
    2652                 :          0 :         r = bus_verify_polkit_async(message,
    2653                 :            :                                     CAP_SYS_ADMIN,
    2654                 :            :                                     "org.freedesktop.login1.set-reboot-to-firmware-setup",
    2655                 :            :                                     NULL,
    2656                 :            :                                     false,
    2657                 :            :                                     UID_INVALID,
    2658                 :            :                                     &m->polkit_registry,
    2659                 :            :                                     error);
    2660         [ #  # ]:          0 :         if (r < 0)
    2661                 :          0 :                 return r;
    2662         [ #  # ]:          0 :         if (r == 0)
    2663                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    2664                 :            : 
    2665         [ #  # ]:          0 :         if (use_efi) {
    2666                 :          0 :                 r = efi_set_reboot_to_firmware(b);
    2667         [ #  # ]:          0 :                 if (r < 0)
    2668                 :          0 :                         return r;
    2669                 :            :         } else {
    2670         [ #  # ]:          0 :                 if (b) {
    2671                 :          0 :                         r = touch("/run/systemd/reboot-to-firmware-setup");
    2672         [ #  # ]:          0 :                         if (r < 0)
    2673                 :          0 :                                 return r;
    2674                 :            :                 } else {
    2675   [ #  #  #  # ]:          0 :                         if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT)
    2676                 :          0 :                                 return -errno;
    2677                 :            :                 }
    2678                 :            :         }
    2679                 :            : 
    2680                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    2681                 :            : }
    2682                 :            : 
    2683                 :          0 : static int method_can_reboot_to_firmware_setup(
    2684                 :            :                 sd_bus_message *message,
    2685                 :            :                 void *userdata,
    2686                 :            :                 sd_bus_error *error) {
    2687                 :            : 
    2688                 :          0 :         Manager *m = userdata;
    2689                 :            :         int r;
    2690                 :            : 
    2691         [ #  # ]:          0 :         assert(message);
    2692         [ #  # ]:          0 :         assert(m);
    2693                 :            : 
    2694                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
    2695         [ #  # ]:          0 :         if (r == -ENXIO) {
    2696                 :            :                 /* EFI case: let's see what the firmware supports */
    2697                 :            : 
    2698                 :          0 :                 r = efi_reboot_to_firmware_supported();
    2699         [ #  # ]:          0 :                 if (r < 0) {
    2700         [ #  # ]:          0 :                         if (r != -EOPNOTSUPP)
    2701         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
    2702                 :            : 
    2703                 :          0 :                         return sd_bus_reply_method_return(message, "s", "na");
    2704                 :            :                 }
    2705                 :            : 
    2706         [ #  # ]:          0 :         } else if (r <= 0) {
    2707                 :            :                 /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */
    2708                 :            : 
    2709         [ #  # ]:          0 :                 if (r < 0)
    2710         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
    2711                 :            : 
    2712                 :          0 :                 return sd_bus_reply_method_return(message, "s", "na");
    2713                 :            :         }
    2714                 :            : 
    2715                 :          0 :         return return_test_polkit(
    2716                 :            :                         message,
    2717                 :            :                         CAP_SYS_ADMIN,
    2718                 :            :                         "org.freedesktop.login1.set-reboot-to-firmware-setup",
    2719                 :            :                         NULL,
    2720                 :            :                         UID_INVALID,
    2721                 :            :                         error);
    2722                 :            : }
    2723                 :            : 
    2724                 :          0 : static int property_get_reboot_to_boot_loader_menu(
    2725                 :            :                 sd_bus *bus,
    2726                 :            :                 const char *path,
    2727                 :            :                 const char *interface,
    2728                 :            :                 const char *property,
    2729                 :            :                 sd_bus_message *reply,
    2730                 :            :                 void *userdata,
    2731                 :            :                 sd_bus_error *error) {
    2732                 :            : 
    2733                 :          0 :         uint64_t x = UINT64_MAX;
    2734                 :            :         int r;
    2735                 :            : 
    2736         [ #  # ]:          0 :         assert(bus);
    2737         [ #  # ]:          0 :         assert(reply);
    2738         [ #  # ]:          0 :         assert(userdata);
    2739                 :            : 
    2740                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
    2741         [ #  # ]:          0 :         if (r == -ENXIO) {
    2742                 :          0 :                 _cleanup_free_ char *v = NULL;
    2743                 :            : 
    2744                 :            :                 /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
    2745                 :            :                  *
    2746                 :            :                  *     1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
    2747                 :            :                  *     2. Variable set to "0", boot into boot loader menu is enabled with no timeout (we return 0 to the user)
    2748                 :            :                  *     3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
    2749                 :            :                  */
    2750                 :            : 
    2751                 :          0 :                 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
    2752         [ #  # ]:          0 :                 if (r < 0) {
    2753         [ #  # ]:          0 :                         if (r != -ENOENT)
    2754         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
    2755                 :            :                 } else {
    2756                 :            :                         uint64_t sec;
    2757                 :            : 
    2758                 :          0 :                         r = safe_atou64(v, &sec);
    2759         [ #  # ]:          0 :                         if (r < 0)
    2760         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
    2761         [ #  # ]:          0 :                         else if (sec > (USEC_INFINITY / USEC_PER_SEC))
    2762         [ #  # ]:          0 :                                 log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
    2763                 :            :                         else
    2764                 :          0 :                                 x = sec * USEC_PER_SEC; /* return in µs */
    2765                 :            :                 }
    2766                 :            : 
    2767         [ #  # ]:          0 :         } else if (r < 0)
    2768         [ #  # ]:          0 :                 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
    2769         [ #  # ]:          0 :         else if (r > 0) {
    2770                 :          0 :                 _cleanup_free_ char *v = NULL;
    2771                 :            : 
    2772                 :            :                 /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-menu. */
    2773                 :            : 
    2774                 :          0 :                 r = read_one_line_file("/run/systemd/reboot-to-boot-loader-menu", &v);
    2775         [ #  # ]:          0 :                 if (r < 0) {
    2776         [ #  # ]:          0 :                         if (r != -ENOENT)
    2777         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-menu: %m");
    2778                 :            :                 } else {
    2779                 :          0 :                         r = safe_atou64(v, &x);
    2780         [ #  # ]:          0 :                         if (r < 0)
    2781         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to parse /run/systemd/reboot-to-boot-loader-menu: %m");
    2782                 :            :                 }
    2783                 :            :         }
    2784                 :            : 
    2785                 :          0 :         return sd_bus_message_append(reply, "t", x);
    2786                 :            : }
    2787                 :            : 
    2788                 :          0 : static int method_set_reboot_to_boot_loader_menu(
    2789                 :            :                 sd_bus_message *message,
    2790                 :            :                 void *userdata,
    2791                 :            :                 sd_bus_error *error) {
    2792                 :            : 
    2793                 :          0 :         Manager *m = userdata;
    2794                 :            :         bool use_efi;
    2795                 :            :         uint64_t x;
    2796                 :            :         int r;
    2797                 :            : 
    2798         [ #  # ]:          0 :         assert(message);
    2799         [ #  # ]:          0 :         assert(m);
    2800                 :            : 
    2801                 :          0 :         r = sd_bus_message_read(message, "t", &x);
    2802         [ #  # ]:          0 :         if (r < 0)
    2803                 :          0 :                 return r;
    2804                 :            : 
    2805                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
    2806         [ #  # ]:          0 :         if (r == -ENXIO) {
    2807                 :            :                 uint64_t features;
    2808                 :            : 
    2809                 :            :                 /* EFI case: let's see if booting into boot loader menu is supported. */
    2810                 :            : 
    2811                 :          0 :                 r = efi_loader_get_features(&features);
    2812         [ #  # ]:          0 :                 if (r < 0)
    2813         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
    2814   [ #  #  #  # ]:          0 :                 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
    2815                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
    2816                 :            : 
    2817                 :          0 :                 use_efi = true;
    2818                 :            : 
    2819         [ #  # ]:          0 :         } else if (r <= 0) {
    2820                 :            :                 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to off */
    2821                 :            : 
    2822         [ #  # ]:          0 :                 if (r < 0)
    2823         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
    2824                 :            : 
    2825                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
    2826                 :            :         } else
    2827                 :            :                 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */
    2828                 :          0 :                 use_efi = false;
    2829                 :            : 
    2830                 :          0 :         r = bus_verify_polkit_async(message,
    2831                 :            :                                     CAP_SYS_ADMIN,
    2832                 :            :                                     "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
    2833                 :            :                                     NULL,
    2834                 :            :                                     false,
    2835                 :            :                                     UID_INVALID,
    2836                 :            :                                     &m->polkit_registry,
    2837                 :            :                                     error);
    2838         [ #  # ]:          0 :         if (r < 0)
    2839                 :          0 :                 return r;
    2840         [ #  # ]:          0 :         if (r == 0)
    2841                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    2842                 :            : 
    2843         [ #  # ]:          0 :         if (use_efi) {
    2844         [ #  # ]:          0 :                 if (x == UINT64_MAX)
    2845                 :          0 :                         r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0);
    2846                 :            :                 else {
    2847                 :            :                         char buf[DECIMAL_STR_MAX(uint64_t) + 1];
    2848         [ #  # ]:          0 :                         xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */
    2849                 :            : 
    2850                 :          0 :                         r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf);
    2851                 :            :                 }
    2852         [ #  # ]:          0 :                 if (r < 0)
    2853                 :          0 :                         return r;
    2854                 :            :         } else {
    2855         [ #  # ]:          0 :                 if (x == UINT64_MAX) {
    2856   [ #  #  #  # ]:          0 :                         if (unlink("/run/systemd/reboot-to-loader-menu") < 0 && errno != ENOENT)
    2857                 :          0 :                                 return -errno;
    2858                 :            :                 } else {
    2859                 :            :                         char buf[DECIMAL_STR_MAX(uint64_t) + 1];
    2860                 :            : 
    2861         [ #  # ]:          0 :                         xsprintf(buf, "%" PRIu64, x); /* µs granularity */
    2862                 :            : 
    2863                 :          0 :                         r = write_string_file_atomic_label("/run/systemd/reboot-to-loader-menu", buf);
    2864         [ #  # ]:          0 :                         if (r < 0)
    2865                 :          0 :                                 return r;
    2866                 :            :                 }
    2867                 :            :         }
    2868                 :            : 
    2869                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    2870                 :            : }
    2871                 :            : 
    2872                 :          0 : static int method_can_reboot_to_boot_loader_menu(
    2873                 :            :                 sd_bus_message *message,
    2874                 :            :                 void *userdata,
    2875                 :            :                 sd_bus_error *error) {
    2876                 :            : 
    2877                 :          0 :         Manager *m = userdata;
    2878                 :            :         int r;
    2879                 :            : 
    2880         [ #  # ]:          0 :         assert(message);
    2881         [ #  # ]:          0 :         assert(m);
    2882                 :            : 
    2883                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
    2884         [ #  # ]:          0 :         if (r == -ENXIO) {
    2885                 :          0 :                 uint64_t features = 0;
    2886                 :            : 
    2887                 :            :                 /* EFI case, let's see if booting into boot loader menu is supported. */
    2888                 :            : 
    2889                 :          0 :                 r = efi_loader_get_features(&features);
    2890         [ #  # ]:          0 :                 if (r < 0)
    2891         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
    2892   [ #  #  #  # ]:          0 :                 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
    2893                 :          0 :                         return sd_bus_reply_method_return(message, "s", "na");
    2894                 :            : 
    2895         [ #  # ]:          0 :         } else if (r <= 0) {
    2896                 :            :                 /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU */
    2897                 :            : 
    2898         [ #  # ]:          0 :                 if (r < 0)
    2899         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
    2900                 :            : 
    2901                 :          0 :                 return sd_bus_reply_method_return(message, "s", "na");
    2902                 :            :         }
    2903                 :            : 
    2904                 :          0 :         return return_test_polkit(
    2905                 :            :                         message,
    2906                 :            :                         CAP_SYS_ADMIN,
    2907                 :            :                         "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
    2908                 :            :                         NULL,
    2909                 :            :                         UID_INVALID,
    2910                 :            :                         error);
    2911                 :            : }
    2912                 :            : 
    2913                 :          0 : static int property_get_reboot_to_boot_loader_entry(
    2914                 :            :                 sd_bus *bus,
    2915                 :            :                 const char *path,
    2916                 :            :                 const char *interface,
    2917                 :            :                 const char *property,
    2918                 :            :                 sd_bus_message *reply,
    2919                 :            :                 void *userdata,
    2920                 :            :                 sd_bus_error *error) {
    2921                 :            : 
    2922                 :          0 :         _cleanup_free_ char *v = NULL;
    2923                 :            :         int r;
    2924                 :            : 
    2925         [ #  # ]:          0 :         assert(bus);
    2926         [ #  # ]:          0 :         assert(reply);
    2927         [ #  # ]:          0 :         assert(userdata);
    2928                 :            : 
    2929                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
    2930         [ #  # ]:          0 :         if (r == -ENXIO) {
    2931                 :            :                 /* EFI case: let's read the LoaderEntryOneShot variable */
    2932                 :            : 
    2933                 :          0 :                 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
    2934         [ #  # ]:          0 :                 if (r < 0) {
    2935         [ #  # ]:          0 :                         if (r != -ENOENT)
    2936         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m");
    2937         [ #  # ]:          0 :                 } else if (!efi_loader_entry_name_valid(v)) {
    2938         [ #  # ]:          0 :                         log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v);
    2939                 :          0 :                         v = mfree(v);
    2940                 :            :                 }
    2941         [ #  # ]:          0 :         } else if (r < 0)
    2942         [ #  # ]:          0 :                 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
    2943         [ #  # ]:          0 :         else if (r > 0) {
    2944                 :            : 
    2945                 :            :                 /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-entry. */
    2946                 :            : 
    2947                 :          0 :                 r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v);
    2948         [ #  # ]:          0 :                 if (r < 0) {
    2949         [ #  # ]:          0 :                         if (r != -ENOENT)
    2950         [ #  # ]:          0 :                                 log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m");
    2951         [ #  # ]:          0 :                 } else if (!efi_loader_entry_name_valid(v)) {
    2952         [ #  # ]:          0 :                         log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring.");
    2953                 :          0 :                         v = mfree(v);
    2954                 :            :                 }
    2955                 :            :         }
    2956                 :            : 
    2957                 :          0 :         return sd_bus_message_append(reply, "s", v);
    2958                 :            : }
    2959                 :            : 
    2960                 :          0 : static int boot_loader_entry_exists(const char *id) {
    2961                 :          0 :         _cleanup_(boot_config_free) BootConfig config = {};
    2962                 :            :         int r;
    2963                 :            : 
    2964         [ #  # ]:          0 :         assert(id);
    2965                 :            : 
    2966                 :          0 :         r = boot_entries_load_config_auto(NULL, NULL, &config);
    2967   [ #  #  #  # ]:          0 :         if (r < 0 && r != -ENOKEY) /* don't complain if no GPT is found, hence skip ENOKEY */
    2968                 :          0 :                 return r;
    2969                 :            : 
    2970                 :          0 :         (void) boot_entries_augment_from_loader(&config, true);
    2971                 :            : 
    2972                 :          0 :         return boot_config_has_entry(&config, id);
    2973                 :            : }
    2974                 :            : 
    2975                 :          0 : static int method_set_reboot_to_boot_loader_entry(
    2976                 :            :                 sd_bus_message *message,
    2977                 :            :                 void *userdata,
    2978                 :            :                 sd_bus_error *error) {
    2979                 :            : 
    2980                 :          0 :         Manager *m = userdata;
    2981                 :            :         bool use_efi;
    2982                 :            :         const char *v;
    2983                 :            :         int r;
    2984                 :            : 
    2985         [ #  # ]:          0 :         assert(message);
    2986         [ #  # ]:          0 :         assert(m);
    2987                 :            : 
    2988                 :          0 :         r = sd_bus_message_read(message, "s", &v);
    2989         [ #  # ]:          0 :         if (r < 0)
    2990                 :          0 :                 return r;
    2991                 :            : 
    2992         [ #  # ]:          0 :         if (isempty(v))
    2993                 :          0 :                 v = NULL;
    2994         [ #  # ]:          0 :         else if (efi_loader_entry_name_valid(v)) {
    2995                 :          0 :                 r = boot_loader_entry_exists(v);
    2996         [ #  # ]:          0 :                 if (r < 0)
    2997                 :          0 :                         return r;
    2998         [ #  # ]:          0 :                 if (r == 0)
    2999                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader entry '%s' is not known.", v);
    3000                 :            :         } else
    3001                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Boot loader entry name '%s' is not valid, refusing.", v);
    3002                 :            : 
    3003                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
    3004         [ #  # ]:          0 :         if (r == -ENXIO) {
    3005                 :            :                 uint64_t features;
    3006                 :            : 
    3007                 :            :                 /* EFI case: let's see if booting into boot loader entry is supported. */
    3008                 :            : 
    3009                 :          0 :                 r = efi_loader_get_features(&features);
    3010         [ #  # ]:          0 :                 if (r < 0)
    3011         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m");
    3012   [ #  #  #  # ]:          0 :                 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
    3013                 :          0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
    3014                 :            : 
    3015                 :          0 :                 use_efi = true;
    3016                 :            : 
    3017         [ #  # ]:          0 :         } else if (r <= 0) {
    3018                 :            :                 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to off */
    3019                 :            : 
    3020         [ #  # ]:          0 :                 if (r < 0)
    3021         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
    3022                 :            : 
    3023                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
    3024                 :            :         } else
    3025                 :            :                 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */
    3026                 :          0 :                 use_efi = false;
    3027                 :            : 
    3028                 :          0 :         r = bus_verify_polkit_async(message,
    3029                 :            :                                     CAP_SYS_ADMIN,
    3030                 :            :                                     "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
    3031                 :            :                                     NULL,
    3032                 :            :                                     false,
    3033                 :            :                                     UID_INVALID,
    3034                 :            :                                     &m->polkit_registry,
    3035                 :            :                                     error);
    3036         [ #  # ]:          0 :         if (r < 0)
    3037                 :          0 :                 return r;
    3038         [ #  # ]:          0 :         if (r == 0)
    3039                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    3040                 :            : 
    3041         [ #  # ]:          0 :         if (use_efi) {
    3042         [ #  # ]:          0 :                 if (isempty(v))
    3043                 :            :                         /* Delete item */
    3044                 :          0 :                         r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0);
    3045                 :            :                 else
    3046                 :          0 :                         r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v);
    3047         [ #  # ]:          0 :                 if (r < 0)
    3048                 :          0 :                         return r;
    3049                 :            :         } else {
    3050         [ #  # ]:          0 :                 if (isempty(v)) {
    3051   [ #  #  #  # ]:          0 :                         if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT)
    3052                 :          0 :                                 return -errno;
    3053                 :            :                 } else {
    3054                 :          0 :                         r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v);
    3055         [ #  # ]:          0 :                         if (r < 0)
    3056                 :          0 :                                 return r;
    3057                 :            :                 }
    3058                 :            :         }
    3059                 :            : 
    3060                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    3061                 :            : }
    3062                 :            : 
    3063                 :          0 : static int method_can_reboot_to_boot_loader_entry(
    3064                 :            :                 sd_bus_message *message,
    3065                 :            :                 void *userdata,
    3066                 :            :                 sd_bus_error *error) {
    3067                 :            : 
    3068                 :          0 :         Manager *m = userdata;
    3069                 :            :         int r;
    3070                 :            : 
    3071         [ #  # ]:          0 :         assert(message);
    3072         [ #  # ]:          0 :         assert(m);
    3073                 :            : 
    3074                 :          0 :         r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
    3075         [ #  # ]:          0 :         if (r == -ENXIO) {
    3076                 :          0 :                 uint64_t features = 0;
    3077                 :            : 
    3078                 :            :                 /* EFI case, let's see if booting into boot loader entry is supported. */
    3079                 :            : 
    3080                 :          0 :                 r = efi_loader_get_features(&features);
    3081         [ #  # ]:          0 :                 if (r < 0)
    3082         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to determine whether reboot to boot loader entry is supported: %m");
    3083   [ #  #  #  # ]:          0 :                 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
    3084                 :          0 :                         return sd_bus_reply_method_return(message, "s", "na");
    3085                 :            : 
    3086         [ #  # ]:          0 :         } else if (r <= 0) {
    3087                 :            :                 /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY */
    3088                 :            : 
    3089         [ #  # ]:          0 :                 if (r < 0)
    3090         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
    3091                 :            : 
    3092                 :          0 :                 return sd_bus_reply_method_return(message, "s", "na");
    3093                 :            :         }
    3094                 :            : 
    3095                 :          0 :         return return_test_polkit(
    3096                 :            :                         message,
    3097                 :            :                         CAP_SYS_ADMIN,
    3098                 :            :                         "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
    3099                 :            :                         NULL,
    3100                 :            :                         UID_INVALID,
    3101                 :            :                         error);
    3102                 :            : }
    3103                 :            : 
    3104                 :          0 : static int property_get_boot_loader_entries(
    3105                 :            :                 sd_bus *bus,
    3106                 :            :                 const char *path,
    3107                 :            :                 const char *interface,
    3108                 :            :                 const char *property,
    3109                 :            :                 sd_bus_message *reply,
    3110                 :            :                 void *userdata,
    3111                 :            :                 sd_bus_error *error) {
    3112                 :            : 
    3113                 :          0 :         _cleanup_(boot_config_free) BootConfig config = {};
    3114                 :            :         size_t i;
    3115                 :            :         int r;
    3116                 :            : 
    3117         [ #  # ]:          0 :         assert(bus);
    3118         [ #  # ]:          0 :         assert(reply);
    3119         [ #  # ]:          0 :         assert(userdata);
    3120                 :            : 
    3121                 :          0 :         r = boot_entries_load_config_auto(NULL, NULL, &config);
    3122   [ #  #  #  # ]:          0 :         if (r < 0 && r != -ENOKEY) /* don't complain if there's no GPT found */
    3123                 :          0 :                 return r;
    3124                 :            : 
    3125                 :          0 :         (void) boot_entries_augment_from_loader(&config, true);
    3126                 :            : 
    3127                 :          0 :         r = sd_bus_message_open_container(reply, 'a', "s");
    3128         [ #  # ]:          0 :         if (r < 0)
    3129                 :          0 :                 return r;
    3130                 :            : 
    3131         [ #  # ]:          0 :         for (i = 0; i < config.n_entries; i++) {
    3132                 :          0 :                 BootEntry *e = config.entries + i;
    3133                 :            : 
    3134                 :          0 :                 r = sd_bus_message_append(reply, "s", e->id);
    3135         [ #  # ]:          0 :                 if (r < 0)
    3136                 :          0 :                         return r;
    3137                 :            :         }
    3138                 :            : 
    3139                 :          0 :         return sd_bus_message_close_container(reply);
    3140                 :            : }
    3141                 :            : 
    3142                 :          0 : static int method_set_wall_message(
    3143                 :            :                 sd_bus_message *message,
    3144                 :            :                 void *userdata,
    3145                 :            :                 sd_bus_error *error) {
    3146                 :            : 
    3147                 :            :         int r;
    3148                 :          0 :         Manager *m = userdata;
    3149                 :            :         char *wall_message;
    3150                 :            :         unsigned enable_wall_messages;
    3151                 :            : 
    3152         [ #  # ]:          0 :         assert(message);
    3153         [ #  # ]:          0 :         assert(m);
    3154                 :            : 
    3155                 :          0 :         r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
    3156         [ #  # ]:          0 :         if (r < 0)
    3157                 :          0 :                 return r;
    3158                 :            : 
    3159                 :          0 :         r = bus_verify_polkit_async(message,
    3160                 :            :                                     CAP_SYS_ADMIN,
    3161                 :            :                                     "org.freedesktop.login1.set-wall-message",
    3162                 :            :                                     NULL,
    3163                 :            :                                     false,
    3164                 :            :                                     UID_INVALID,
    3165                 :            :                                     &m->polkit_registry,
    3166                 :            :                                     error);
    3167         [ #  # ]:          0 :         if (r < 0)
    3168                 :          0 :                 return r;
    3169         [ #  # ]:          0 :         if (r == 0)
    3170                 :          0 :                 return 1; /* Will call us back */
    3171                 :            : 
    3172                 :          0 :         r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
    3173         [ #  # ]:          0 :         if (r < 0)
    3174                 :          0 :                 return log_oom();
    3175                 :            : 
    3176                 :          0 :         m->enable_wall_messages = enable_wall_messages;
    3177                 :            : 
    3178                 :          0 :         return sd_bus_reply_method_return(message, NULL);
    3179                 :            : }
    3180                 :            : 
    3181                 :          0 : static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    3182                 :          0 :         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
    3183                 :            :         const char *who, *why, *what, *mode;
    3184                 :          0 :         _cleanup_free_ char *id = NULL;
    3185                 :          0 :         _cleanup_close_ int fifo_fd = -1;
    3186                 :          0 :         Manager *m = userdata;
    3187                 :          0 :         Inhibitor *i = NULL;
    3188                 :            :         InhibitMode mm;
    3189                 :            :         InhibitWhat w;
    3190                 :            :         pid_t pid;
    3191                 :            :         uid_t uid;
    3192                 :            :         int r;
    3193                 :            : 
    3194         [ #  # ]:          0 :         assert(message);
    3195         [ #  # ]:          0 :         assert(m);
    3196                 :            : 
    3197                 :          0 :         r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
    3198         [ #  # ]:          0 :         if (r < 0)
    3199                 :          0 :                 return r;
    3200                 :            : 
    3201                 :          0 :         w = inhibit_what_from_string(what);
    3202         [ #  # ]:          0 :         if (w <= 0)
    3203                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
    3204                 :            :                                          "Invalid what specification %s", what);
    3205                 :            : 
    3206                 :          0 :         mm = inhibit_mode_from_string(mode);
    3207         [ #  # ]:          0 :         if (mm < 0)
    3208                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
    3209                 :            :                                          "Invalid mode specification %s", mode);
    3210                 :            : 
    3211                 :            :         /* Delay is only supported for shutdown/sleep */
    3212   [ #  #  #  # ]:          0 :         if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
    3213                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
    3214                 :            :                                          "Delay inhibitors only supported for shutdown and sleep");
    3215                 :            : 
    3216                 :            :         /* Don't allow taking delay locks while we are already
    3217                 :            :          * executing the operation. We shouldn't create the impression
    3218                 :            :          * that the lock was successful if the machine is about to go
    3219                 :            :          * down/suspend any moment. */
    3220         [ #  # ]:          0 :         if (m->action_what & w)
    3221                 :          0 :                 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
    3222                 :            :                                          "The operation inhibition has been requested for is already running");
    3223                 :            : 
    3224         [ #  # ]:          0 :         r = bus_verify_polkit_async(
    3225                 :            :                         message,
    3226                 :            :                         CAP_SYS_BOOT,
    3227         [ #  # ]:          0 :                         w == INHIBIT_SHUTDOWN             ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
    3228   [ #  #  #  # ]:          0 :                         w == INHIBIT_SLEEP                ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep"    : "org.freedesktop.login1.inhibit-delay-sleep") :
    3229         [ #  # ]:          0 :                         w == INHIBIT_IDLE                 ? "org.freedesktop.login1.inhibit-block-idle" :
    3230         [ #  # ]:          0 :                         w == INHIBIT_HANDLE_POWER_KEY     ? "org.freedesktop.login1.inhibit-handle-power-key" :
    3231         [ #  # ]:          0 :                         w == INHIBIT_HANDLE_SUSPEND_KEY   ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
    3232         [ #  # ]:          0 :                         w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
    3233                 :            :                                                             "org.freedesktop.login1.inhibit-handle-lid-switch",
    3234                 :            :                         NULL,
    3235                 :            :                         false,
    3236                 :            :                         UID_INVALID,
    3237                 :            :                         &m->polkit_registry,
    3238                 :            :                         error);
    3239         [ #  # ]:          0 :         if (r < 0)
    3240                 :          0 :                 return r;
    3241         [ #  # ]:          0 :         if (r == 0)
    3242                 :          0 :                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
    3243                 :            : 
    3244                 :          0 :         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
    3245         [ #  # ]:          0 :         if (r < 0)
    3246                 :          0 :                 return r;
    3247                 :            : 
    3248                 :          0 :         r = sd_bus_creds_get_euid(creds, &uid);
    3249         [ #  # ]:          0 :         if (r < 0)
    3250                 :          0 :                 return r;
    3251                 :            : 
    3252                 :          0 :         r = sd_bus_creds_get_pid(creds, &pid);
    3253         [ #  # ]:          0 :         if (r < 0)
    3254                 :          0 :                 return r;
    3255                 :            : 
    3256         [ #  # ]:          0 :         if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
    3257                 :          0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
    3258                 :            :                                          "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.",
    3259                 :            :                                          m->inhibitors_max);
    3260                 :            : 
    3261                 :            :         do {
    3262                 :          0 :                 id = mfree(id);
    3263                 :            : 
    3264         [ #  # ]:          0 :                 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
    3265                 :          0 :                         return -ENOMEM;
    3266                 :            : 
    3267         [ #  # ]:          0 :         } while (hashmap_get(m->inhibitors, id));
    3268                 :            : 
    3269                 :          0 :         r = manager_add_inhibitor(m, id, &i);
    3270         [ #  # ]:          0 :         if (r < 0)
    3271                 :          0 :                 return r;
    3272                 :            : 
    3273                 :          0 :         i->what = w;
    3274                 :          0 :         i->mode = mm;
    3275                 :          0 :         i->pid = pid;
    3276                 :          0 :         i->uid = uid;
    3277                 :          0 :         i->why = strdup(why);
    3278                 :          0 :         i->who = strdup(who);
    3279                 :            : 
    3280   [ #  #  #  # ]:          0 :         if (!i->why || !i->who) {
    3281                 :          0 :                 r = -ENOMEM;
    3282                 :          0 :                 goto fail;
    3283                 :            :         }
    3284                 :            : 
    3285                 :          0 :         fifo_fd = inhibitor_create_fifo(i);
    3286         [ #  # ]:          0 :         if (fifo_fd < 0) {
    3287                 :          0 :                 r = fifo_fd;
    3288                 :          0 :                 goto fail;
    3289                 :            :         }
    3290                 :            : 
    3291                 :          0 :         r = inhibitor_start(i);
    3292         [ #  # ]:          0 :         if (r < 0)
    3293                 :          0 :                 goto fail;
    3294                 :            : 
    3295                 :          0 :         return sd_bus_reply_method_return(message, "h", fifo_fd);
    3296                 :            : 
    3297                 :          0 : fail:
    3298         [ #  # ]:          0 :         if (i)
    3299                 :          0 :                 inhibitor_free(i);
    3300                 :            : 
    3301                 :          0 :         return r;
    3302                 :            : }
    3303                 :            : 
    3304                 :            : const sd_bus_vtable manager_vtable[] = {
    3305                 :            :         SD_BUS_VTABLE_START(0),
    3306                 :            : 
    3307                 :            :         SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
    3308                 :            :         SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
    3309                 :            : 
    3310                 :            :         SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
    3311                 :            :         SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
    3312                 :            :         SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
    3313                 :            :         SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
    3314                 :            :         SD_BUS_PROPERTY("RebootParameter", "s", property_get_reboot_parameter, 0, 0),
    3315                 :            :         SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0),
    3316                 :            :         SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0),
    3317                 :            :         SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0),
    3318                 :            :         SD_BUS_PROPERTY("BootLoaderEntries", "as", property_get_boot_loader_entries, 0, SD_BUS_VTABLE_PROPERTY_CONST),
    3319                 :            :         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
    3320                 :            :         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
    3321                 :            :         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
    3322                 :            :         SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
    3323                 :            :         SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
    3324                 :            :         SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
    3325                 :            :         SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST),
    3326                 :            :         SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
    3327                 :            :         SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
    3328                 :            :         SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
    3329                 :            :         SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
    3330                 :            :         SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
    3331                 :            :         SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
    3332                 :            :         SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
    3333                 :            :         SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
    3334                 :            :         SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
    3335                 :            :         SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
    3336                 :            :         SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
    3337                 :            :         SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
    3338                 :            :         SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
    3339                 :            :         SD_BUS_PROPERTY("LidClosed", "b", property_get_lid_closed, 0, 0),
    3340                 :            :         SD_BUS_PROPERTY("OnExternalPower", "b", property_get_on_external_power, 0, 0),
    3341                 :            :         SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
    3342                 :            :         SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
    3343                 :            :         SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
    3344                 :            :         SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
    3345                 :            :         SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
    3346                 :            :         SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
    3347                 :            :         SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
    3348                 :            : 
    3349                 :            :         SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
    3350                 :            :         SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
    3351                 :            :         SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
    3352                 :            :         SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
    3353                 :            :         SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
    3354                 :            :         SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
    3355                 :            :         SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
    3356                 :            :         SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
    3357                 :            :         SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
    3358                 :            :         SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
    3359                 :            :         SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
    3360                 :            :         SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
    3361                 :            :         SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
    3362                 :            :         SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
    3363                 :            :         SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
    3364                 :            :         SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
    3365                 :            :         SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
    3366                 :            :         SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
    3367                 :            :         SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
    3368                 :            :         SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
    3369                 :            :         SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
    3370                 :            :         SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
    3371                 :            :         SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
    3372                 :            :         SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
    3373                 :            :         SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
    3374                 :            :         SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
    3375                 :            :         SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
    3376                 :            :         SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
    3377                 :            :         SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
    3378                 :            :         SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
    3379                 :            :         SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
    3380                 :            :         SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
    3381                 :            :         SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
    3382                 :            :         SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
    3383                 :            :         SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
    3384                 :            :         SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
    3385                 :            :         SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
    3386                 :            :         SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
    3387                 :            :         SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
    3388                 :            :         SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
    3389                 :            :         SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
    3390                 :            :         SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
    3391                 :            :         SD_BUS_METHOD("CanRebootParameter", NULL, "s", method_can_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
    3392                 :            :         SD_BUS_METHOD("SetRebootParameter", "s", NULL, method_set_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
    3393                 :            :         SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
    3394                 :            :         SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
    3395                 :            :         SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
    3396                 :            :         SD_BUS_METHOD("SetRebootToBootLoaderMenu", "t", NULL, method_set_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
    3397                 :            :         SD_BUS_METHOD("CanRebootToBootLoaderEntry", NULL, "s", method_can_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
    3398                 :            :         SD_BUS_METHOD("SetRebootToBootLoaderEntry", "s", NULL, method_set_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
    3399                 :            :         SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
    3400                 :            : 
    3401                 :            :         SD_BUS_SIGNAL("SessionNew", "so", 0),
    3402                 :            :         SD_BUS_SIGNAL("SessionRemoved", "so", 0),
    3403                 :            :         SD_BUS_SIGNAL("UserNew", "uo", 0),
    3404                 :            :         SD_BUS_SIGNAL("UserRemoved", "uo", 0),
    3405                 :            :         SD_BUS_SIGNAL("SeatNew", "so", 0),
    3406                 :            :         SD_BUS_SIGNAL("SeatRemoved", "so", 0),
    3407                 :            :         SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
    3408                 :            :         SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
    3409                 :            : 
    3410                 :            :         SD_BUS_VTABLE_END
    3411                 :            : };
    3412                 :            : 
    3413                 :          0 : static int session_jobs_reply(Session *s, const char *unit, const char *result) {
    3414         [ #  # ]:          0 :         assert(s);
    3415         [ #  # ]:          0 :         assert(unit);
    3416                 :            : 
    3417         [ #  # ]:          0 :         if (!s->started)
    3418                 :          0 :                 return 0;
    3419                 :            : 
    3420   [ #  #  #  # ]:          0 :         if (result && !streq(result, "done")) {
    3421                 :          0 :                 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
    3422                 :            : 
    3423                 :          0 :                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED,
    3424                 :            :                                   "Start job for unit '%s' failed with '%s'", unit, result);
    3425                 :          0 :                 return session_send_create_reply(s, &e);
    3426                 :            :         }
    3427                 :            : 
    3428                 :          0 :         return session_send_create_reply(s, NULL);
    3429                 :            : }
    3430                 :            : 
    3431                 :          0 : int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    3432                 :            :         const char *path, *result, *unit;
    3433                 :          0 :         Manager *m = userdata;
    3434                 :            :         Session *session;
    3435                 :            :         uint32_t id;
    3436                 :            :         User *user;
    3437                 :            :         int r;
    3438                 :            : 
    3439         [ #  # ]:          0 :         assert(message);
    3440         [ #  # ]:          0 :         assert(m);
    3441                 :            : 
    3442                 :          0 :         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
    3443         [ #  # ]:          0 :         if (r < 0) {
    3444         [ #  # ]:          0 :                 bus_log_parse_error(r);
    3445                 :          0 :                 return 0;
    3446                 :            :         }
    3447                 :            : 
    3448   [ #  #  #  # ]:          0 :         if (m->action_job && streq(m->action_job, path)) {
    3449         [ #  # ]:          0 :                 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
    3450                 :            : 
    3451                 :            :                 /* Tell people that they now may take a lock again */
    3452                 :          0 :                 (void) send_prepare_for(m, m->action_what, false);
    3453                 :            : 
    3454                 :          0 :                 m->action_job = mfree(m->action_job);
    3455                 :          0 :                 m->action_unit = NULL;
    3456                 :          0 :                 m->action_what = 0;
    3457                 :          0 :                 return 0;
    3458                 :            :         }
    3459                 :            : 
    3460                 :          0 :         session = hashmap_get(m->session_units, unit);
    3461         [ #  # ]:          0 :         if (session) {
    3462         [ #  # ]:          0 :                 if (streq_ptr(path, session->scope_job)) {
    3463                 :          0 :                         session->scope_job = mfree(session->scope_job);
    3464                 :          0 :                         (void) session_jobs_reply(session, unit, result);
    3465                 :            : 
    3466                 :          0 :                         session_save(session);
    3467                 :          0 :                         user_save(session->user);
    3468                 :            :                 }
    3469                 :            : 
    3470                 :          0 :                 session_add_to_gc_queue(session);
    3471                 :            :         }
    3472                 :            : 
    3473                 :          0 :         user = hashmap_get(m->user_units, unit);
    3474         [ #  # ]:          0 :         if (user) {
    3475         [ #  # ]:          0 :                 if (streq_ptr(path, user->service_job)) {
    3476                 :          0 :                         user->service_job = mfree(user->service_job);
    3477                 :            : 
    3478         [ #  # ]:          0 :                         LIST_FOREACH(sessions_by_user, session, user->sessions)
    3479                 :          0 :                                 (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */);
    3480                 :            : 
    3481                 :          0 :                         user_save(user);
    3482                 :            :                 }
    3483                 :            : 
    3484                 :          0 :                 user_add_to_gc_queue(user);
    3485                 :            :         }
    3486                 :            : 
    3487                 :          0 :         return 0;
    3488                 :            : }
    3489                 :            : 
    3490                 :          0 : int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    3491                 :            :         const char *path, *unit;
    3492                 :          0 :         Manager *m = userdata;
    3493                 :            :         Session *session;
    3494                 :            :         User *user;
    3495                 :            :         int r;
    3496                 :            : 
    3497         [ #  # ]:          0 :         assert(message);
    3498         [ #  # ]:          0 :         assert(m);
    3499                 :            : 
    3500                 :          0 :         r = sd_bus_message_read(message, "so", &unit, &path);
    3501         [ #  # ]:          0 :         if (r < 0) {
    3502         [ #  # ]:          0 :                 bus_log_parse_error(r);
    3503                 :          0 :                 return 0;
    3504                 :            :         }
    3505                 :            : 
    3506                 :          0 :         session = hashmap_get(m->session_units, unit);
    3507         [ #  # ]:          0 :         if (session)
    3508                 :          0 :                 session_add_to_gc_queue(session);
    3509                 :            : 
    3510                 :          0 :         user = hashmap_get(m->user_units, unit);
    3511         [ #  # ]:          0 :         if (user)
    3512                 :          0 :                 user_add_to_gc_queue(user);
    3513                 :            : 
    3514                 :          0 :         return 0;
    3515                 :            : }
    3516                 :            : 
    3517                 :          0 : int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    3518                 :          0 :         _cleanup_free_ char *unit = NULL;
    3519                 :          0 :         Manager *m = userdata;
    3520                 :            :         const char *path;
    3521                 :            :         Session *session;
    3522                 :            :         User *user;
    3523                 :            :         int r;
    3524                 :            : 
    3525         [ #  # ]:          0 :         assert(message);
    3526         [ #  # ]:          0 :         assert(m);
    3527                 :            : 
    3528                 :          0 :         path = sd_bus_message_get_path(message);
    3529         [ #  # ]:          0 :         if (!path)
    3530                 :          0 :                 return 0;
    3531                 :            : 
    3532                 :          0 :         r = unit_name_from_dbus_path(path, &unit);
    3533         [ #  # ]:          0 :         if (r == -EINVAL) /* not a unit */
    3534                 :          0 :                 return 0;
    3535         [ #  # ]:          0 :         if (r < 0) {
    3536                 :          0 :                 log_oom();
    3537                 :          0 :                 return 0;
    3538                 :            :         }
    3539                 :            : 
    3540                 :          0 :         session = hashmap_get(m->session_units, unit);
    3541         [ #  # ]:          0 :         if (session)
    3542                 :          0 :                 session_add_to_gc_queue(session);
    3543                 :            : 
    3544                 :          0 :         user = hashmap_get(m->user_units, unit);
    3545         [ #  # ]:          0 :         if (user)
    3546                 :          0 :                 user_add_to_gc_queue(user);
    3547                 :            : 
    3548                 :          0 :         return 0;
    3549                 :            : }
    3550                 :            : 
    3551                 :          0 : int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
    3552                 :          0 :         Manager *m = userdata;
    3553                 :            :         Session *session;
    3554                 :            :         Iterator i;
    3555                 :            :         int b, r;
    3556                 :            : 
    3557         [ #  # ]:          0 :         assert(message);
    3558         [ #  # ]:          0 :         assert(m);
    3559                 :            : 
    3560                 :          0 :         r = sd_bus_message_read(message, "b", &b);
    3561         [ #  # ]:          0 :         if (r < 0) {
    3562         [ #  # ]:          0 :                 bus_log_parse_error(r);
    3563                 :          0 :                 return 0;
    3564                 :            :         }
    3565                 :            : 
    3566         [ #  # ]:          0 :         if (b)
    3567                 :          0 :                 return 0;
    3568                 :            : 
    3569                 :            :         /* systemd finished reloading, let's recheck all our sessions */
    3570         [ #  # ]:          0 :         log_debug("System manager has been reloaded, rechecking sessions...");
    3571                 :            : 
    3572         [ #  # ]:          0 :         HASHMAP_FOREACH(session, m->sessions, i)
    3573                 :          0 :                 session_add_to_gc_queue(session);
    3574                 :            : 
    3575                 :          0 :         return 0;
    3576                 :            : }
    3577                 :            : 
    3578                 :          0 : int manager_send_changed(Manager *manager, const char *property, ...) {
    3579                 :            :         char **l;
    3580                 :            : 
    3581         [ #  # ]:          0 :         assert(manager);
    3582                 :            : 
    3583   [ #  #  #  #  :          0 :         l = strv_from_stdarg_alloca(property);
          #  #  #  #  #  
                      # ]
    3584                 :            : 
    3585                 :          0 :         return sd_bus_emit_properties_changed_strv(
    3586                 :            :                         manager->bus,
    3587                 :            :                         "/org/freedesktop/login1",
    3588                 :            :                         "org.freedesktop.login1.Manager",
    3589                 :            :                         l);
    3590                 :            : }
    3591                 :            : 
    3592                 :          0 : static int strdup_job(sd_bus_message *reply, char **job) {
    3593                 :            :         const char *j;
    3594                 :            :         char *copy;
    3595                 :            :         int r;
    3596                 :            : 
    3597                 :          0 :         r = sd_bus_message_read(reply, "o", &j);
    3598         [ #  # ]:          0 :         if (r < 0)
    3599                 :          0 :                 return r;
    3600                 :            : 
    3601                 :          0 :         copy = strdup(j);
    3602         [ #  # ]:          0 :         if (!copy)
    3603                 :          0 :                 return -ENOMEM;
    3604                 :            : 
    3605                 :          0 :         *job = copy;
    3606                 :          0 :         return 1;
    3607                 :            : }
    3608                 :            : 
    3609                 :          0 : int manager_start_scope(
    3610                 :            :                 Manager *manager,
    3611                 :            :                 const char *scope,
    3612                 :            :                 pid_t pid,
    3613                 :            :                 const char *slice,
    3614                 :            :                 const char *description,
    3615                 :            :                 char **wants,
    3616                 :            :                 char **after,
    3617                 :            :                 const char *requires_mounts_for,
    3618                 :            :                 sd_bus_message *more_properties,
    3619                 :            :                 sd_bus_error *error,
    3620                 :            :                 char **job) {
    3621                 :            : 
    3622                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
    3623                 :            :         char **i;
    3624                 :            :         int r;
    3625                 :            : 
    3626         [ #  # ]:          0 :         assert(manager);
    3627         [ #  # ]:          0 :         assert(scope);
    3628         [ #  # ]:          0 :         assert(pid > 1);
    3629         [ #  # ]:          0 :         assert(job);
    3630                 :            : 
    3631                 :          0 :         r = sd_bus_message_new_method_call(
    3632                 :            :                         manager->bus,
    3633                 :            :                         &m,
    3634                 :            :                         "org.freedesktop.systemd1",
    3635                 :            :                         "/org/freedesktop/systemd1",
    3636                 :            :                         "org.freedesktop.systemd1.Manager",
    3637                 :            :                         "StartTransientUnit");
    3638         [ #  # ]:          0 :         if (r < 0)
    3639                 :          0 :                 return r;
    3640                 :            : 
    3641                 :          0 :         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
    3642         [ #  # ]:          0 :         if (r < 0)
    3643                 :          0 :                 return r;
    3644                 :            : 
    3645                 :          0 :         r = sd_bus_message_open_container(m, 'a', "(sv)");
    3646         [ #  # ]:          0 :         if (r < 0)
    3647                 :          0 :                 return r;
    3648                 :            : 
    3649         [ #  # ]:          0 :         if (!isempty(slice)) {
    3650                 :          0 :                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
    3651         [ #  # ]:          0 :                 if (r < 0)
    3652                 :          0 :                         return r;
    3653                 :            :         }
    3654                 :            : 
    3655         [ #  # ]:          0 :         if (!isempty(description)) {
    3656                 :          0 :                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
    3657         [ #  # ]:          0 :                 if (r < 0)
    3658                 :          0 :                         return r;
    3659                 :            :         }
    3660                 :            : 
    3661   [ #  #  #  # ]:          0 :         STRV_FOREACH(i, wants) {
    3662                 :          0 :                 r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i);
    3663         [ #  # ]:          0 :                 if (r < 0)
    3664                 :          0 :                         return r;
    3665                 :            :         }
    3666                 :            : 
    3667   [ #  #  #  # ]:          0 :         STRV_FOREACH(i, after) {
    3668                 :          0 :                 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i);
    3669         [ #  # ]:          0 :                 if (r < 0)
    3670                 :          0 :                         return r;
    3671                 :            :         }
    3672                 :            : 
    3673         [ #  # ]:          0 :         if (!empty_or_root(requires_mounts_for)) {
    3674                 :          0 :                 r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for);
    3675         [ #  # ]:          0 :                 if (r < 0)
    3676                 :          0 :                         return r;
    3677                 :            :         }
    3678                 :            : 
    3679                 :            :         /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
    3680                 :            :          * SIGTERM */
    3681                 :          0 :         r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
    3682         [ #  # ]:          0 :         if (r < 0)
    3683                 :          0 :                 return r;
    3684                 :            : 
    3685                 :          0 :         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
    3686         [ #  # ]:          0 :         if (r < 0)
    3687                 :          0 :                 return r;
    3688                 :            : 
    3689                 :            :         /* disable TasksMax= for the session scope, rely on the slice setting for it */
    3690                 :          0 :         r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1);
    3691         [ #  # ]:          0 :         if (r < 0)
    3692         [ #  # ]:          0 :                 return bus_log_create_error(r);
    3693                 :            : 
    3694         [ #  # ]:          0 :         if (more_properties) {
    3695                 :            :                 /* If TasksMax also appears here, it will overwrite the default value set above */
    3696                 :          0 :                 r = sd_bus_message_copy(m, more_properties, true);
    3697         [ #  # ]:          0 :                 if (r < 0)
    3698                 :          0 :                         return r;
    3699                 :            :         }
    3700                 :            : 
    3701                 :          0 :         r = sd_bus_message_close_container(m);
    3702         [ #  # ]:          0 :         if (r < 0)
    3703                 :          0 :                 return r;
    3704                 :            : 
    3705                 :          0 :         r = sd_bus_message_append(m, "a(sa(sv))", 0);
    3706         [ #  # ]:          0 :         if (r < 0)
    3707                 :          0 :                 return r;
    3708                 :            : 
    3709                 :          0 :         r = sd_bus_call(manager->bus, m, 0, error, &reply);
    3710         [ #  # ]:          0 :         if (r < 0)
    3711                 :          0 :                 return r;
    3712                 :            : 
    3713                 :          0 :         return strdup_job(reply, job);
    3714                 :            : }
    3715                 :            : 
    3716                 :          0 : int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
    3717                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    3718                 :            :         int r;
    3719                 :            : 
    3720         [ #  # ]:          0 :         assert(manager);
    3721         [ #  # ]:          0 :         assert(unit);
    3722         [ #  # ]:          0 :         assert(job);
    3723                 :            : 
    3724                 :          0 :         r = sd_bus_call_method(
    3725                 :            :                         manager->bus,
    3726                 :            :                         "org.freedesktop.systemd1",
    3727                 :            :                         "/org/freedesktop/systemd1",
    3728                 :            :                         "org.freedesktop.systemd1.Manager",
    3729                 :            :                         "StartUnit",
    3730                 :            :                         error,
    3731                 :            :                         &reply,
    3732                 :            :                         "ss", unit, "replace");
    3733         [ #  # ]:          0 :         if (r < 0)
    3734                 :          0 :                 return r;
    3735                 :            : 
    3736                 :          0 :         return strdup_job(reply, job);
    3737                 :            : }
    3738                 :            : 
    3739                 :          0 : int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
    3740                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    3741                 :            :         int r;
    3742                 :            : 
    3743         [ #  # ]:          0 :         assert(manager);
    3744         [ #  # ]:          0 :         assert(unit);
    3745         [ #  # ]:          0 :         assert(job);
    3746                 :            : 
    3747                 :          0 :         r = sd_bus_call_method(
    3748                 :            :                         manager->bus,
    3749                 :            :                         "org.freedesktop.systemd1",
    3750                 :            :                         "/org/freedesktop/systemd1",
    3751                 :            :                         "org.freedesktop.systemd1.Manager",
    3752                 :            :                         "StopUnit",
    3753                 :            :                         error,
    3754                 :            :                         &reply,
    3755                 :            :                         "ss", unit, "fail");
    3756         [ #  # ]:          0 :         if (r < 0) {
    3757   [ #  #  #  # ]:          0 :                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
    3758                 :          0 :                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
    3759                 :            : 
    3760                 :          0 :                         *job = NULL;
    3761                 :          0 :                         sd_bus_error_free(error);
    3762                 :          0 :                         return 0;
    3763                 :            :                 }
    3764                 :            : 
    3765                 :          0 :                 return r;
    3766                 :            :         }
    3767                 :            : 
    3768                 :          0 :         return strdup_job(reply, job);
    3769                 :            : }
    3770                 :            : 
    3771                 :          0 : int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) {
    3772                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    3773                 :          0 :         _cleanup_free_ char *path = NULL;
    3774                 :            :         int r;
    3775                 :            : 
    3776         [ #  # ]:          0 :         assert(manager);
    3777         [ #  # ]:          0 :         assert(scope);
    3778                 :            : 
    3779                 :          0 :         path = unit_dbus_path_from_name(scope);
    3780         [ #  # ]:          0 :         if (!path)
    3781                 :          0 :                 return -ENOMEM;
    3782                 :            : 
    3783                 :          0 :         r = sd_bus_call_method(
    3784                 :            :                         manager->bus,
    3785                 :            :                         "org.freedesktop.systemd1",
    3786                 :            :                         path,
    3787                 :            :                         "org.freedesktop.systemd1.Scope",
    3788                 :            :                         "Abandon",
    3789                 :            :                         &error,
    3790                 :            :                         NULL,
    3791                 :            :                         NULL);
    3792         [ #  # ]:          0 :         if (r < 0) {
    3793   [ #  #  #  # ]:          0 :                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
    3794         [ #  # ]:          0 :                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) ||
    3795                 :          0 :                     sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING))
    3796                 :          0 :                         return 0;
    3797                 :            : 
    3798                 :          0 :                 sd_bus_error_move(ret_error, &error);
    3799                 :          0 :                 return r;
    3800                 :            :         }
    3801                 :            : 
    3802                 :          0 :         return 1;
    3803                 :            : }
    3804                 :            : 
    3805                 :          0 : int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
    3806         [ #  # ]:          0 :         assert(manager);
    3807         [ #  # ]:          0 :         assert(unit);
    3808                 :            : 
    3809         [ #  # ]:          0 :         return sd_bus_call_method(
    3810                 :            :                         manager->bus,
    3811                 :            :                         "org.freedesktop.systemd1",
    3812                 :            :                         "/org/freedesktop/systemd1",
    3813                 :            :                         "org.freedesktop.systemd1.Manager",
    3814                 :            :                         "KillUnit",
    3815                 :            :                         error,
    3816                 :            :                         NULL,
    3817                 :            :                         "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
    3818                 :            : }
    3819                 :            : 
    3820                 :          0 : int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret_error) {
    3821                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    3822                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    3823                 :          0 :         _cleanup_free_ char *path = NULL;
    3824                 :            :         const char *state;
    3825                 :            :         int r;
    3826                 :            : 
    3827         [ #  # ]:          0 :         assert(manager);
    3828         [ #  # ]:          0 :         assert(unit);
    3829                 :            : 
    3830                 :          0 :         path = unit_dbus_path_from_name(unit);
    3831         [ #  # ]:          0 :         if (!path)
    3832                 :          0 :                 return -ENOMEM;
    3833                 :            : 
    3834                 :          0 :         r = sd_bus_get_property(
    3835                 :            :                         manager->bus,
    3836                 :            :                         "org.freedesktop.systemd1",
    3837                 :            :                         path,
    3838                 :            :                         "org.freedesktop.systemd1.Unit",
    3839                 :            :                         "ActiveState",
    3840                 :            :                         &error,
    3841                 :            :                         &reply,
    3842                 :            :                         "s");
    3843         [ #  # ]:          0 :         if (r < 0) {
    3844                 :            :                 /* systemd might have dropped off momentarily, let's
    3845                 :            :                  * not make this an error */
    3846   [ #  #  #  # ]:          0 :                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
    3847                 :          0 :                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
    3848                 :          0 :                         return true;
    3849                 :            : 
    3850                 :            :                 /* If the unit is already unloaded then it's not
    3851                 :            :                  * active */
    3852   [ #  #  #  # ]:          0 :                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
    3853                 :          0 :                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
    3854                 :          0 :                         return false;
    3855                 :            : 
    3856                 :          0 :                 sd_bus_error_move(ret_error, &error);
    3857                 :          0 :                 return r;
    3858                 :            :         }
    3859                 :            : 
    3860                 :          0 :         r = sd_bus_message_read(reply, "s", &state);
    3861         [ #  # ]:          0 :         if (r < 0)
    3862                 :          0 :                 return r;
    3863                 :            : 
    3864                 :          0 :         return !STR_IN_SET(state, "inactive", "failed");
    3865                 :            : }
    3866                 :            : 
    3867                 :          0 : int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_error) {
    3868                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    3869                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    3870                 :            :         int r;
    3871                 :            : 
    3872         [ #  # ]:          0 :         assert(manager);
    3873         [ #  # ]:          0 :         assert(path);
    3874                 :            : 
    3875                 :          0 :         r = sd_bus_get_property(
    3876                 :            :                         manager->bus,
    3877                 :            :                         "org.freedesktop.systemd1",
    3878                 :            :                         path,
    3879                 :            :                         "org.freedesktop.systemd1.Job",
    3880                 :            :                         "State",
    3881                 :            :                         &error,
    3882                 :            :                         &reply,
    3883                 :            :                         "s");
    3884         [ #  # ]:          0 :         if (r < 0) {
    3885   [ #  #  #  # ]:          0 :                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
    3886                 :          0 :                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
    3887                 :          0 :                         return true;
    3888                 :            : 
    3889         [ #  # ]:          0 :                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
    3890                 :          0 :                         return false;
    3891                 :            : 
    3892                 :          0 :                 sd_bus_error_move(ret_error, &error);
    3893                 :          0 :                 return r;
    3894                 :            :         }
    3895                 :            : 
    3896                 :            :         /* We don't actually care about the state really. The fact
    3897                 :            :          * that we could read the job state is enough for us */
    3898                 :            : 
    3899                 :          0 :         return true;
    3900                 :            : }

Generated by: LCOV version 1.14