xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

systemd-logind.c (20385B)


      1 /*
      2  * Copyright © 2013 Red Hat Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  *
     23  * Author: Hans de Goede <hdegoede@redhat.com>
     24  */
     25 
     26 #ifdef HAVE_XORG_CONFIG_H
     27 #include <xorg-config.h>
     28 #endif
     29 
     30 #include <dbus/dbus.h>
     31 #include <string.h>
     32 #include <sys/types.h>
     33 #include <unistd.h>
     34 
     35 #include "os.h"
     36 #include "dbus-core.h"
     37 #include "linux.h"
     38 #include "xf86.h"
     39 #include "xf86platformBus.h"
     40 #include "xf86Xinput.h"
     41 #include "xf86Priv.h"
     42 #include "globals.h"
     43 
     44 #include "systemd-logind.h"
     45 
     46 struct systemd_logind_info {
     47     DBusConnection *conn;
     48     char *session;
     49     Bool active;
     50     Bool vt_active;
     51 };
     52 
     53 static struct systemd_logind_info logind_info;
     54 
     55 static InputInfoPtr
     56 systemd_logind_find_info_ptr_by_devnum(InputInfoPtr start,
     57                                        int major, int minor)
     58 {
     59     InputInfoPtr pInfo;
     60 
     61     for (pInfo = start; pInfo; pInfo = pInfo->next)
     62         if (pInfo->major == major && pInfo->minor == minor &&
     63                 (pInfo->flags & XI86_SERVER_FD))
     64             return pInfo;
     65 
     66     return NULL;
     67 }
     68 
     69 static void
     70 systemd_logind_set_input_fd_for_all_devs(int major, int minor, int fd,
     71                                          Bool enable)
     72 {
     73     InputInfoPtr pInfo;
     74 
     75     pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
     76     while (pInfo) {
     77         pInfo->fd = fd;
     78         pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
     79         if (enable)
     80             xf86EnableInputDeviceForVTSwitch(pInfo);
     81 
     82         pInfo = systemd_logind_find_info_ptr_by_devnum(pInfo->next, major, minor);
     83     }
     84 }
     85 
     86 int
     87 systemd_logind_take_fd(int _major, int _minor, const char *path,
     88                        Bool *paused_ret)
     89 {
     90     struct systemd_logind_info *info = &logind_info;
     91     InputInfoPtr pInfo;
     92     DBusError error;
     93     DBusMessage *msg = NULL;
     94     DBusMessage *reply = NULL;
     95     dbus_int32_t major = _major;
     96     dbus_int32_t minor = _minor;
     97     dbus_bool_t paused;
     98     int fd = -1;
     99 
    100     if (!info->session || major == 0)
    101         return -1;
    102 
    103     /* logind does not support mouse devs (with evdev we don't need them) */
    104     if (strstr(path, "mouse"))
    105         return -1;
    106 
    107     /* Check if we already have an InputInfo entry with this major, minor
    108      * (shared device-nodes happen ie with Wacom tablets). */
    109     pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
    110     if (pInfo) {
    111         LogMessage(X_INFO, "systemd-logind: returning pre-existing fd for %s %u:%u\n",
    112                path, major, minor);
    113         *paused_ret = FALSE;
    114         return pInfo->fd;
    115     }
    116 
    117     dbus_error_init(&error);
    118 
    119     msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
    120             "org.freedesktop.login1.Session", "TakeDevice");
    121     if (!msg) {
    122         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    123         goto cleanup;
    124     }
    125 
    126     if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
    127                                        DBUS_TYPE_UINT32, &minor,
    128                                        DBUS_TYPE_INVALID)) {
    129         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    130         goto cleanup;
    131     }
    132 
    133     reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
    134                                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
    135     if (!reply) {
    136         LogMessage(X_ERROR, "systemd-logind: failed to take device %s: %s\n",
    137                    path, error.message);
    138         goto cleanup;
    139     }
    140 
    141     if (!dbus_message_get_args(reply, &error,
    142                                DBUS_TYPE_UNIX_FD, &fd,
    143                                DBUS_TYPE_BOOLEAN, &paused,
    144                                DBUS_TYPE_INVALID)) {
    145         LogMessage(X_ERROR, "systemd-logind: TakeDevice %s: %s\n",
    146                    path, error.message);
    147         goto cleanup;
    148     }
    149 
    150     *paused_ret = paused;
    151 
    152     LogMessage(X_INFO, "systemd-logind: got fd for %s %u:%u fd %d paused %d\n",
    153                path, major, minor, fd, paused);
    154 
    155 cleanup:
    156     if (msg)
    157         dbus_message_unref(msg);
    158     if (reply)
    159         dbus_message_unref(reply);
    160     dbus_error_free(&error);
    161 
    162     return fd;
    163 }
    164 
    165 void
    166 systemd_logind_release_fd(int _major, int _minor, int fd)
    167 {
    168     struct systemd_logind_info *info = &logind_info;
    169     InputInfoPtr pInfo;
    170     DBusError error;
    171     DBusMessage *msg = NULL;
    172     DBusMessage *reply = NULL;
    173     dbus_int32_t major = _major;
    174     dbus_int32_t minor = _minor;
    175     int matches = 0;
    176 
    177     if (!info->session || major == 0)
    178         goto close;
    179 
    180     /* Only release the fd if there is only 1 InputInfo left for this major
    181      * and minor, otherwise other InputInfo's are still referencing the fd. */
    182     pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
    183     while (pInfo) {
    184         matches++;
    185         pInfo = systemd_logind_find_info_ptr_by_devnum(pInfo->next, major, minor);
    186     }
    187     if (matches > 1) {
    188         LogMessage(X_INFO, "systemd-logind: not releasing fd for %u:%u, still in use\n", major, minor);
    189         return;
    190     }
    191 
    192     LogMessage(X_INFO, "systemd-logind: releasing fd for %u:%u\n", major, minor);
    193 
    194     dbus_error_init(&error);
    195 
    196     msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
    197             "org.freedesktop.login1.Session", "ReleaseDevice");
    198     if (!msg) {
    199         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    200         goto cleanup;
    201     }
    202 
    203     if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
    204                                        DBUS_TYPE_UINT32, &minor,
    205                                        DBUS_TYPE_INVALID)) {
    206         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    207         goto cleanup;
    208     }
    209 
    210     reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
    211                                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
    212     if (!reply)
    213         LogMessage(X_ERROR, "systemd-logind: failed to release device: %s\n",
    214                    error.message);
    215 
    216 cleanup:
    217     if (msg)
    218         dbus_message_unref(msg);
    219     if (reply)
    220         dbus_message_unref(reply);
    221     dbus_error_free(&error);
    222 close:
    223     if (fd != -1)
    224         close(fd);
    225 }
    226 
    227 int
    228 systemd_logind_controls_session(void)
    229 {
    230     return logind_info.session ? 1 : 0;
    231 }
    232 
    233 void
    234 systemd_logind_vtenter(void)
    235 {
    236     struct systemd_logind_info *info = &logind_info;
    237     InputInfoPtr pInfo;
    238     int i;
    239 
    240     if (!info->session)
    241         return; /* Not using systemd-logind */
    242 
    243     if (!info->active)
    244         return; /* Session not active */
    245 
    246     if (info->vt_active)
    247         return; /* Already did vtenter */
    248 
    249     for (i = 0; i < xf86_num_platform_devices; i++) {
    250         if (xf86_platform_devices[i].flags & XF86_PDEV_PAUSED)
    251             break;
    252     }
    253     if (i != xf86_num_platform_devices)
    254         return; /* Some drm nodes are still paused wait for resume */
    255 
    256     xf86VTEnter();
    257     info->vt_active = TRUE;
    258 
    259     /* Activate any input devices which were resumed before the drm nodes */
    260     for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
    261         if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
    262             xf86EnableInputDeviceForVTSwitch(pInfo);
    263 
    264     /* Do delayed input probing, this must be done after the above enabling */
    265     xf86InputEnableVTProbe();
    266 }
    267 
    268 static void
    269 systemd_logind_ack_pause(struct systemd_logind_info *info,
    270                          dbus_int32_t minor, dbus_int32_t major)
    271 {
    272     DBusError error;
    273     DBusMessage *msg = NULL;
    274     DBusMessage *reply = NULL;
    275 
    276     dbus_error_init(&error);
    277 
    278     msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
    279             "org.freedesktop.login1.Session", "PauseDeviceComplete");
    280     if (!msg) {
    281         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    282         goto cleanup;
    283     }
    284 
    285     if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
    286                                        DBUS_TYPE_UINT32, &minor,
    287                                        DBUS_TYPE_INVALID)) {
    288         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    289         goto cleanup;
    290     }
    291 
    292     reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
    293                                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
    294     if (!reply)
    295         LogMessage(X_ERROR, "systemd-logind: failed to ack pause: %s\n",
    296                    error.message);
    297 
    298 cleanup:
    299     if (msg)
    300         dbus_message_unref(msg);
    301     if (reply)
    302         dbus_message_unref(reply);
    303     dbus_error_free(&error);
    304 }
    305 
    306 /*
    307  * Send a message to logind, to pause the drm device
    308  * and ensure the drm_drop_master is done before
    309  * VT_RELDISP when switching VT
    310  */
    311 void systemd_logind_drop_master(void)
    312 {
    313     int i;
    314     for (i = 0; i < xf86_num_platform_devices; i++) {
    315         if (xf86_platform_devices[i].flags & XF86_PDEV_SERVER_FD) {
    316             dbus_int32_t major, minor;
    317             struct systemd_logind_info *info = &logind_info;
    318 
    319             xf86_platform_devices[i].flags |= XF86_PDEV_PAUSED;
    320             major = xf86_platform_odev_attributes(i)->major;
    321             minor = xf86_platform_odev_attributes(i)->minor;
    322             systemd_logind_ack_pause(info, minor, major);
    323         }
    324     }
    325 }
    326 
    327 static Bool are_platform_devices_resumed(void) {
    328     int i;
    329     for (i = 0; i < xf86_num_platform_devices; i++) {
    330         if (xf86_platform_devices[i].flags & XF86_PDEV_PAUSED) {
    331             return FALSE;
    332         }
    333     }
    334     return TRUE;
    335 }
    336 
    337 static DBusHandlerResult
    338 message_filter(DBusConnection * connection, DBusMessage * message, void *data)
    339 {
    340     struct systemd_logind_info *info = data;
    341     struct xf86_platform_device *pdev = NULL;
    342     InputInfoPtr pInfo = NULL;
    343     int ack = 0, pause = 0, fd = -1;
    344     DBusError error;
    345     dbus_int32_t major, minor;
    346     char *pause_str;
    347 
    348     if (strcmp(dbus_message_get_path(message), info->session) != 0)
    349         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    350 
    351     dbus_error_init(&error);
    352 
    353     if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
    354                                "PauseDevice")) {
    355         if (!dbus_message_get_args(message, &error,
    356                                DBUS_TYPE_UINT32, &major,
    357                                DBUS_TYPE_UINT32, &minor,
    358                                DBUS_TYPE_STRING, &pause_str,
    359                                DBUS_TYPE_INVALID)) {
    360             LogMessage(X_ERROR, "systemd-logind: PauseDevice: %s\n",
    361                        error.message);
    362             dbus_error_free(&error);
    363             return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    364         }
    365 
    366         if (strcmp(pause_str, "pause") == 0) {
    367             pause = 1;
    368             ack = 1;
    369         }
    370         else if (strcmp(pause_str, "force") == 0) {
    371             pause = 1;
    372         }
    373         else if (strcmp(pause_str, "gone") == 0) {
    374             /* Device removal is handled through udev */
    375             return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    376         }
    377         else {
    378             LogMessage(X_WARNING, "systemd-logind: unknown pause type: %s\n",
    379                        pause_str);
    380             return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    381         }
    382     }
    383     else if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
    384                                     "ResumeDevice")) {
    385         if (!dbus_message_get_args(message, &error,
    386                                    DBUS_TYPE_UINT32, &major,
    387                                    DBUS_TYPE_UINT32, &minor,
    388                                    DBUS_TYPE_UNIX_FD, &fd,
    389                                    DBUS_TYPE_INVALID)) {
    390             LogMessage(X_ERROR, "systemd-logind: ResumeDevice: %s\n",
    391                        error.message);
    392             dbus_error_free(&error);
    393             return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    394         }
    395     } else
    396         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    397 
    398     LogMessage(X_INFO, "systemd-logind: got %s for %u:%u\n",
    399                pause ? "pause" : "resume", major, minor);
    400 
    401     pdev = xf86_find_platform_device_by_devnum(major, minor);
    402     if (!pdev)
    403         pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs,
    404                                                        major, minor);
    405     if (!pdev && !pInfo) {
    406         LogMessage(X_WARNING, "systemd-logind: could not find dev %u:%u\n",
    407                    major, minor);
    408         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    409     }
    410 
    411     if (pause) {
    412         /* Our VT_PROCESS usage guarantees we've already given up the vt */
    413         info->active = info->vt_active = FALSE;
    414         /* Note the actual vtleave has already been handled by xf86Events.c */
    415         if (pdev)
    416             pdev->flags |= XF86_PDEV_PAUSED;
    417         else {
    418             close(pInfo->fd);
    419             systemd_logind_set_input_fd_for_all_devs(major, minor, -1, FALSE);
    420         }
    421         if (ack)
    422             systemd_logind_ack_pause(info, major, minor);
    423     }
    424     else {
    425         /* info->vt_active gets set by systemd_logind_vtenter() */
    426         info->active = TRUE;
    427 
    428         if (pdev) {
    429             pdev->flags &= ~XF86_PDEV_PAUSED;
    430         } else
    431             systemd_logind_set_input_fd_for_all_devs(major, minor, fd,
    432                                                      info->vt_active);
    433         /* Call vtenter if all platform devices are resumed, or if there are no platform device */
    434         if (are_platform_devices_resumed())
    435             systemd_logind_vtenter();
    436     }
    437     return DBUS_HANDLER_RESULT_HANDLED;
    438 }
    439 
    440 static void
    441 connect_hook(DBusConnection *connection, void *data)
    442 {
    443     struct systemd_logind_info *info = data;
    444     DBusError error;
    445     DBusMessage *msg = NULL;
    446     DBusMessage *reply = NULL;
    447     dbus_int32_t arg;
    448     char *session = NULL;
    449 
    450     dbus_error_init(&error);
    451 
    452     msg = dbus_message_new_method_call("org.freedesktop.login1",
    453             "/org/freedesktop/login1", "org.freedesktop.login1.Manager",
    454             "GetSessionByPID");
    455     if (!msg) {
    456         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    457         goto cleanup;
    458     }
    459 
    460     arg = getpid();
    461     if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &arg,
    462                                   DBUS_TYPE_INVALID)) {
    463         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    464         goto cleanup;
    465     }
    466 
    467     reply = dbus_connection_send_with_reply_and_block(connection, msg,
    468                                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
    469     if (!reply) {
    470         LogMessage(X_ERROR, "systemd-logind: failed to get session: %s\n",
    471                    error.message);
    472         goto cleanup;
    473     }
    474     dbus_message_unref(msg);
    475 
    476     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &session,
    477                                DBUS_TYPE_INVALID)) {
    478         LogMessage(X_ERROR, "systemd-logind: GetSessionByPID: %s\n",
    479                    error.message);
    480         goto cleanup;
    481     }
    482     session = XNFstrdup(session);
    483 
    484     dbus_message_unref(reply);
    485     reply = NULL;
    486 
    487 
    488     msg = dbus_message_new_method_call("org.freedesktop.login1",
    489             session, "org.freedesktop.login1.Session", "TakeControl");
    490     if (!msg) {
    491         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    492         goto cleanup;
    493     }
    494 
    495     arg = FALSE; /* Don't forcibly take over over the session */
    496     if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg,
    497                                   DBUS_TYPE_INVALID)) {
    498         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    499         goto cleanup;
    500     }
    501 
    502     reply = dbus_connection_send_with_reply_and_block(connection, msg,
    503                                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
    504     if (!reply) {
    505         LogMessage(X_ERROR, "systemd-logind: TakeControl failed: %s\n",
    506                    error.message);
    507         goto cleanup;
    508     }
    509 
    510     dbus_bus_add_match(connection,
    511         "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='PauseDevice'",
    512         &error);
    513     if (dbus_error_is_set(&error)) {
    514         LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
    515                    error.message);
    516         goto cleanup;
    517     }
    518 
    519     dbus_bus_add_match(connection,
    520         "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='ResumeDevice'",
    521         &error);
    522     if (dbus_error_is_set(&error)) {
    523         LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
    524                    error.message);
    525         goto cleanup;
    526     }
    527 
    528     /*
    529      * HdG: This is not useful with systemd <= 208 since the signal only
    530      * contains invalidated property names there, rather than property, val
    531      * pairs as it should.  Instead we just use the first resume / pause now.
    532      */
    533 #if 0
    534     snprintf(match, sizeof(match),
    535         "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='%s'",
    536         session);
    537     dbus_bus_add_match(connection, match, &error);
    538     if (dbus_error_is_set(&error)) {
    539         LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
    540                    error.message);
    541         goto cleanup;
    542     }
    543 #endif
    544 
    545     if (!dbus_connection_add_filter(connection, message_filter, info, NULL)) {
    546         LogMessage(X_ERROR, "systemd-logind: could not add filter: %s\n",
    547                    error.message);
    548         goto cleanup;
    549     }
    550 
    551     LogMessage(X_INFO, "systemd-logind: took control of session %s\n",
    552                session);
    553     info->conn = connection;
    554     info->session = session;
    555     info->vt_active = info->active = TRUE; /* The server owns the vt during init */
    556     session = NULL;
    557 
    558 cleanup:
    559     free(session);
    560     if (msg)
    561         dbus_message_unref(msg);
    562     if (reply)
    563         dbus_message_unref(reply);
    564     dbus_error_free(&error);
    565 }
    566 
    567 static void
    568 systemd_logind_release_control(struct systemd_logind_info *info)
    569 {
    570     DBusError error;
    571     DBusMessage *msg = NULL;
    572     DBusMessage *reply = NULL;
    573 
    574     dbus_error_init(&error);
    575 
    576     msg = dbus_message_new_method_call("org.freedesktop.login1",
    577             info->session, "org.freedesktop.login1.Session", "ReleaseControl");
    578     if (!msg) {
    579         LogMessage(X_ERROR, "systemd-logind: out of memory\n");
    580         goto cleanup;
    581     }
    582 
    583     reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
    584                                                       DBUS_TIMEOUT_USE_DEFAULT, &error);
    585     if (!reply) {
    586         LogMessage(X_ERROR, "systemd-logind: ReleaseControl failed: %s\n",
    587                    error.message);
    588         goto cleanup;
    589     }
    590 
    591 cleanup:
    592     if (msg)
    593         dbus_message_unref(msg);
    594     if (reply)
    595         dbus_message_unref(reply);
    596     dbus_error_free(&error);
    597 }
    598 
    599 static void
    600 disconnect_hook(void *data)
    601 {
    602     struct systemd_logind_info *info = data;
    603 
    604     free(info->session);
    605     info->session = NULL;
    606     info->conn = NULL;
    607 }
    608 
    609 static struct dbus_core_hook core_hook = {
    610     .connect = connect_hook,
    611     .disconnect = disconnect_hook,
    612     .data = &logind_info,
    613 };
    614 
    615 int
    616 systemd_logind_init(void)
    617 {
    618     if (!ServerIsNotSeat0() && xf86HasTTYs() && linux_parse_vt_settings(TRUE) && !linux_get_keeptty()) {
    619         LogMessage(X_INFO,
    620             "systemd-logind: logind integration requires -keeptty and "
    621             "-keeptty was not provided, disabling logind integration\n");
    622         return 1;
    623     }
    624 
    625     return dbus_core_add_hook(&core_hook);
    626 }
    627 
    628 void
    629 systemd_logind_fini(void)
    630 {
    631     if (logind_info.session)
    632         systemd_logind_release_control(&logind_info);
    633 
    634     dbus_core_remove_hook(&core_hook);
    635 }