VirtualBox

Ignore:
Timestamp:
Nov 1, 2012 1:25:57 PM (12 years ago)
Author:
vboxsync
Message:

VBoxService/vminfo: Added support for ConsoleKit session detection via D-Bus.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp

    r43363 r43791  
    3939# include <sys/socket.h>
    4040# include <net/if.h>
     41# include <pwd.h> /* getpwuid */
    4142# include <unistd.h>
    4243# if !defined(RT_OS_OS2) && !defined(RT_OS_FREEBSD) && !defined(RT_OS_HAIKU)
     
    5152#  include <net/if_dl.h> /* LLADDR */
    5253#  include <netdb.h> /* getnameinfo */
     54# endif
     55# ifdef VBOX_WITH_DBUS
     56#  include <VBox/dbus.h>
    5357# endif
    5458#endif
     
    8589
    8690
     91/*******************************************************************************
     92*   Defines                                                                    *
     93*******************************************************************************/
     94#ifdef VBOX_WITH_DBUS
     95/** ConsoleKit defines (taken from 0.4.5). */
     96#define CK_NAME      "org.freedesktop.ConsoleKit"
     97#define CK_PATH      "/org/freedesktop/ConsoleKit"
     98#define CK_INTERFACE "org.freedesktop.ConsoleKit"
     99
     100#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
     101#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
     102#define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
     103#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
     104#endif
     105
     106
    87107
    88108/**
     
    241261}
    242262
     263# if defined(VBOX_WITH_DBUS) && defined(RT_OS_LINUX) /* Not yet for Solaris/FreeBSB. */
     264/*
     265 * Simple wrapper to work around compiler-specific va_list madness.
     266 */
     267static dbus_bool_t vboxService_dbus_message_get_args(DBusMessage *message,
     268                                                     DBusError   *error,
     269                                                     int              first_arg_type,
     270                                                     ...)
     271{
     272    va_list va;
     273    va_start(va, first_arg_type);
     274    dbus_bool_t ret = dbus_message_get_args_valist(message, error,
     275                                                   first_arg_type, va);
     276    va_end(va);
     277    return ret;
     278}
     279#endif
    243280
    244281/**
     
    282319        rc = VERR_NO_MEMORY;
    283320
    284     /* Process all entries in the utmp file. */
     321    /* Process all entries in the utmp file.
     322     * Note: This only handles */
    285323    while (   (ut_user = getutxent())
    286324           && RT_SUCCESS(rc))
    287325    {
    288         VBoxServiceVerbose(4, "Found logged in user \"%s\" (type: %d)\n",
    289                            ut_user->ut_user, ut_user->ut_type);
     326        VBoxServiceVerbose(4, "Found entry \"%s\" (type: %d, PID: %RU32, session: %RU32)\n",
     327                           ut_user->ut_user, ut_user->ut_type, ut_user->ut_pid, ut_user->ut_session);
    290328        if (cUsersInList > cListSize)
    291329        {
     
    297335
    298336        /* Make sure we don't add user names which are not
    299          * part of type USER_PROCESS. */
    300         if (ut_user->ut_type == USER_PROCESS)
     337         * part of type USER_PROCES. */
     338        if (ut_user->ut_type == USER_PROCESS) /* Regular user process. */
    301339        {
    302340            bool fFound = false;
     
    317355    }
    318356
     357#ifdef VBOX_WITH_DBUS
     358# if defined(RT_OS_LINUX) /* Not yet for Solaris/FreeBSB. */
     359    /* Handle desktop sessions using ConsoleKit. */
     360    VBoxServiceVerbose(4, "Checking ConsoleKit sessions ...\n");
     361
     362    DBusError dbErr;
     363    dbus_error_init(&dbErr);
     364
     365    DBusConnection *pConnection = dbus_bus_get(DBUS_BUS_SYSTEM, &dbErr);
     366    if (   pConnection
     367        && !dbus_error_is_set(&dbErr))
     368    {
     369        /* Get all available sessions. */
     370        DBusMessage *pMsgSessions = dbus_message_new_method_call("org.freedesktop.ConsoleKit",
     371                                                                 "/org/freedesktop/ConsoleKit/Manager",
     372                                                                 "org.freedesktop.ConsoleKit.Manager",
     373                                                                 "GetSessions");
     374        if (   pMsgSessions
     375            && (dbus_message_get_type(pMsgSessions) == DBUS_MESSAGE_TYPE_METHOD_CALL))
     376        {
     377            DBusMessage *pReplySessions = dbus_connection_send_with_reply_and_block(pConnection,
     378                                                                                    pMsgSessions, 30 * 1000 /* 30s timeout */,
     379                                                                                    &dbErr);
     380            if (   pReplySessions
     381                && !dbus_error_is_set(&dbErr))
     382            {
     383                char **ppszSessions; int cSessions;
     384                if (   (dbus_message_get_type(pMsgSessions) == DBUS_MESSAGE_TYPE_METHOD_CALL)
     385                    && vboxService_dbus_message_get_args(pReplySessions, &dbErr, DBUS_TYPE_ARRAY,
     386                                                         DBUS_TYPE_OBJECT_PATH, &ppszSessions, &cSessions,
     387                                                         DBUS_TYPE_INVALID /* Termination */))
     388                {
     389                    VBoxServiceVerbose(4, "ConsoleKit: retrieved %RU16 session(s)\n", cSessions);
     390                    AssertPtr(*ppszSessions);
     391
     392                    char **ppszCurSession = ppszSessions;
     393                    for (ppszCurSession; *ppszCurSession; ppszCurSession++)
     394                    {
     395                        VBoxServiceVerbose(4, "ConsoleKit: processing session '%s' ...\n", *ppszCurSession);
     396
     397                        /* *ppszCurSession now contains the object path
     398                         * (e.g. "/org/freedesktop/ConsoleKit/Session1"). */
     399                        DBusMessage *pMsgUnixUser = dbus_message_new_method_call("org.freedesktop.ConsoleKit",
     400                                                                                 *ppszCurSession,
     401                                                                                 "org.freedesktop.ConsoleKit.Session",
     402                                                                                 "GetUnixUser");
     403                        if (   pMsgUnixUser
     404                            && dbus_message_get_type(pMsgUnixUser) == DBUS_MESSAGE_TYPE_METHOD_CALL)
     405                        {
     406                            DBusMessage *pReplyUnixUser = dbus_connection_send_with_reply_and_block(pConnection,
     407                                                                                                    pMsgUnixUser, 30 * 1000 /* 30s timeout */,
     408                                                                                                    &dbErr);
     409                            if (   pReplyUnixUser
     410                                && !dbus_error_is_set(&dbErr))
     411                            {
     412                                DBusMessageIter itMsg;
     413                                if (   dbus_message_iter_init(pReplyUnixUser, &itMsg)
     414                                    && dbus_message_iter_get_arg_type(&itMsg) == DBUS_TYPE_UINT32)
     415                                {
     416                                    /* Get uid from message. */
     417                                    uint32_t uid;
     418                                    dbus_message_iter_get_basic(&itMsg, &uid);
     419
     420                                    /* Look up user name (realname) from uid. */
     421                                    setpwent();
     422                                    struct passwd *ppwEntry = getpwuid(uid);
     423                                    if (   ppwEntry
     424                                        && ppwEntry->pw_name)
     425                                    {
     426                                        VBoxServiceVerbose(4, "ConsoleKit: session '%s' -> %s (uid: %RU32)\n",
     427                                                           *ppszCurSession, ppwEntry->pw_name, uid);
     428
     429                                        bool fFound = false;
     430                                        for (uint32_t i = 0; i < cUsersInList && !fFound; i++)
     431                                            fFound = strcmp(papszUsers[i], ppwEntry->pw_name) == 0;
     432
     433                                        if (!fFound)
     434                                        {
     435                                            VBoxServiceVerbose(4, "ConsoleKit: adding user \"%s\" to list\n",
     436                                                               ppwEntry->pw_name);
     437
     438                                            rc = RTStrDupEx(&papszUsers[cUsersInList], (const char *)ppwEntry->pw_name);
     439                                            if (RT_FAILURE(rc))
     440                                                break;
     441                                            cUsersInList++;
     442                                        }
     443                                    }
     444                                    else
     445                                        VBoxServiceError("ConsoleKit: unable to lookup user name for uid=%RU32\n", uid);
     446                                }
     447                                else
     448                                    AssertMsgFailed(("ConsoleKit: GetUnixUser returned a wrong argument type\n"));
     449                            }
     450
     451                            if (pReplyUnixUser)
     452                                dbus_message_unref(pReplyUnixUser);
     453                        }
     454                        else
     455                            VBoxServiceError("ConsoleKit: unable to retrieve user for session '%s' (msg type=%d): %s",
     456                                             *ppszCurSession, dbus_message_get_type(pMsgUnixUser),
     457                                             dbus_error_is_set(&dbErr) ? dbErr.message : "No error information available\n");
     458
     459                        if (pMsgUnixUser)
     460                            dbus_message_unref(pMsgUnixUser);
     461                    }
     462
     463                    dbus_free_string_array(ppszSessions);
     464                }
     465                else
     466                {
     467                    VBoxServiceError("ConsoleKit: unable to retrieve session parameters (msg type=%d): %s",
     468                                     dbus_message_get_type(pMsgSessions),
     469                                     dbus_error_is_set(&dbErr) ? dbErr.message : "No error information available\n");
     470                }
     471                dbus_message_unref(pReplySessions);
     472            }
     473
     474            if (pMsgSessions)
     475            {
     476                dbus_message_unref(pMsgSessions);
     477                pMsgSessions = NULL;
     478            }
     479        }
     480        else
     481        {
     482            static int s_iBitchedAboutConsoleKit = 0;
     483            if (s_iBitchedAboutConsoleKit++ < 3)
     484                VBoxServiceError("Unable to invoke ConsoleKit (%d/3) -- maybe not installed / used? Error: %s\n",
     485                                 s_iBitchedAboutConsoleKit,
     486                                 dbus_error_is_set(&dbErr) ? dbErr.message : "No error information available\n");
     487        }
     488
     489        if (pMsgSessions)
     490            dbus_message_unref(pMsgSessions);
     491    }
     492    else
     493    {
     494        static int s_iBitchedAboutDBus = 0;
     495        if (s_iBitchedAboutDBus++ < 3)
     496            VBoxServiceError("Unable to connect to system D-Bus (%d/3)\n", s_iBitchedAboutDBus);
     497    }
     498
     499    if (dbus_error_is_set(&dbErr))
     500        dbus_error_free(&dbErr);
     501# endif /* RT_OS_LINUX */
     502#endif /* VBOX_WITH_DBUS */
     503
     504    /** @todo Fedora/others: Handle systemd-loginctl. */
     505
    319506    /* Calc the string length. */
    320507    size_t cchUserList = 0;
    321     for (uint32_t i = 0; i < cUsersInList; i++)
    322         cchUserList += (i != 0) + strlen(papszUsers[i]);
     508    if (RT_SUCCESS(rc))
     509    {
     510        for (uint32_t i = 0; i < cUsersInList; i++)
     511            cchUserList += (i != 0) + strlen(papszUsers[i]);
     512    }
    323513
    324514    /* Build the user list. */
    325     rc = RTStrAllocEx(&pszUserList, cchUserList + 1);
     515    if (RT_SUCCESS(rc))
     516        rc = RTStrAllocEx(&pszUserList, cchUserList + 1);
    326517    if (RT_SUCCESS(rc))
    327518    {
     
    368559                       cUsersInList, pszUserList ? pszUserList : "<NULL>", rc);
    369560
     561#if 0
    370562    if (pszUserList && cUsersInList > 0)
    371563        VBoxServicePropCacheUpdate(&g_VMInfoPropCache, "/VirtualBox/GuestInfo/OS/LoggedInUsersList", "%s", pszUserList);
     
    379571        g_cVMInfoLoggedInUsers = cUsersInList;
    380572    }
     573#endif
    381574    if (RT_SUCCESS(rc) && pszUserList)
    382575        RTStrFree(pszUserList);
     
    795988#endif /* RT_OS_WINDOWS */
    796989
     990    int rc2;
     991#ifdef VBOX_WITH_DBUS
     992    rc2 = RTDBusLoadLib();
     993    if (RT_FAILURE(rc2))
     994        VBoxServiceVerbose(0, "VMInfo: D-Bus seems not to be installed; no ConsoleKit session handling available\n");
     995#endif /* VBOX_WITH_DBUS */
     996
    797997    /*
    798998     * Write the fixed properties first.
     
    8341034        if (*pfShutdown)
    8351035            break;
    836         int rc2 = RTSemEventMultiWait(g_hVMInfoEvent, g_cMsVMInfoInterval);
     1036        rc2 = RTSemEventMultiWait(g_hVMInfoEvent, g_cMsVMInfoInterval);
    8371037        if (*pfShutdown)
    8381038            break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette