Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
accountsservice
accountsservice
Commits
d45610fe
Commit
d45610fe
authored
Mar 23, 2012
by
Ray Strode
Browse files
wip: start adding systemd support
Only started, still more to do, just sketching at this point.
parent
1f0356a6
Changes
2
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
d45610fe
...
...
@@ -161,10 +161,22 @@ AC_PATH_PROG([XSLTPROC], [xsltproc])
# systemd
PKG_CHECK_MODULES(SYSTEMD, [libsystemd-login libsystemd-daemon],
[have_systemd=yes], [have_systemd=no])
AC_SUBST(SYSTEMD_CFLAGS)
AC_SUBST(SYSTEMD_LIBS)
LIBACCOUNTSSERVICE_LIBS="$LIBACCOUNTSSERVICE_LIBS $SYSTEMD_LIBS"
LIBACCOUNTSSERVICE_CFLAGS="$LIBACCOUNTSSERVICE_CFLAGS $SYSTEMD_CFLAGS"
if test "x$have_systemd" != "no" ; then
AC_DEFINE(WITH_SYSTEMD, 1, [Define to enable systemd support])
fi
AC_ARG_WITH([systemdsystemunitdir],
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
[],
[with_systemdsystemunitdir=
yes
])
[with_systemdsystemunitdir=
$have_systemd
])
if test "x$with_systemdsystemunitdir" = "xyes"; then
with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
fi
...
...
src/libaccountsservice/act-user-manager.c
View file @
d45610fe
...
...
@@ -39,6 +39,12 @@
#include
<glib/gstdio.h>
#include
<glib-object.h>
#include
<gio/gio.h>
#include
<gio/gunixinputstream.h>
#ifdef WITH_SYSTEMD
#include
<systemd/sd-daemon.h>
#include
<systemd/sd-login.h>
#endif
#include
"act-user-manager.h"
#include
"act-user-private.h"
...
...
@@ -76,6 +82,10 @@ typedef struct
char
*
session_id
;
ConsoleKitSeat
*
seat_proxy
;
ConsoleKitSession
*
session_proxy
;
#ifdef WITH_SYSTEMD
sd_login_monitor
*
session_monitor
;
GInputStream
*
session_monitor_stream
;
#endif
}
ActUserManagerSeat
;
typedef
enum
{
...
...
@@ -195,33 +205,14 @@ act_user_manager_error_quark (void)
}
static
gboolean
start_new_login_session
(
ActUserManager
*
manager
)
{
GError
*
error
;
gboolean
res
;
res
=
g_spawn_command_line_async
(
"gdmflexiserver -s"
,
&
error
);
if
(
!
res
)
{
if
(
error
!=
NULL
)
{
g_warning
(
"Unable to start new login: %s"
,
error
->
message
);
g_error_free
(
error
);
}
else
{
g_warning
(
"Unable to start new login"
);
}
}
return
res
;
}
static
gboolean
activate_session_id
(
ActUserManager
*
manager
,
const
char
*
seat_id
,
const
char
*
session_id
)
activate_console_kit_session_id
(
ActUserManager
*
manager
,
const
char
*
seat_id
,
const
char
*
session_id
)
{
ConsoleKitSeat
*
proxy
;
GError
*
error
=
NULL
;
gboolean
res
=
FALSE
;
proxy
=
console_kit_seat_proxy_new_sync
(
manager
->
priv
->
connection
,
G_DBUS_PROXY_FLAGS_NONE
,
CK_NAME
,
...
...
@@ -243,9 +234,57 @@ activate_session_id (ActUserManager *manager,
return
TRUE
;
}
#ifdef WITH_SYSTEMD
static
gboolean
session_is_login_window
(
ActUserManager
*
manager
,
const
char
*
session_id
)
activate_systemd_session_id
(
ActUserManager
*
manager
,
const
char
*
seat_id
,
const
char
*
session_id
)
{
GDBusConnection
*
connection
;
GVariant
*
reply
;
GError
*
error
;
error
=
NULL
;
connection
=
g_bus_get_sync
(
G_BUS_TYPE_SYSTEM
,
NULL
,
&
error
);
if
(
connection
==
NULL
)
{
goto
failed
;
}
reply
=
g_dbus_connection_call_sync
(
connection
,
"org.freedesktop.login1"
,
"/org/freedesktop/login1"
,
"org.freedesktop.login1.Manager"
,
"ActivateSessionOnSeat"
,
g_variant_new
(
"(ss)"
,
seat_id
,
session_id
),
NULL
,
G_DBUS_CALL_FLAGS_NONE
,
-
1
,
NULL
,
&
error
);
g_object_unref
(
connection
);
if
(
reply
==
NULL
)
{
goto
failed
;
}
g_object_unref
(
reply
);
return
TRUE
;
failed:
g_warning
(
"Unable to activate session: %s"
,
error
->
message
);
g_error_free
(
error
);
return
FALSE
;
}
#endif
static
gboolean
_ck_session_is_login_window
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
ConsoleKitSession
*
proxy
;
GError
*
error
=
NULL
;
...
...
@@ -280,99 +319,94 @@ session_is_login_window (ActUserManager *manager,
return
ret
;
}
static
char
*
_get_login_window_session_id
(
ActUserManager
*
manager
)
#ifdef WITH_SYSTEMD
static
gboolean
_systemd_session_is_login_window
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
gboolean
can_activate_sessions
;
GError
*
error
=
NULL
;
gchar
**
sessions
,
**
i
;
char
*
primary_ssid
;
if
(
manager
->
priv
->
seat
.
id
==
NULL
||
manager
->
priv
->
seat
.
id
[
0
]
==
'\0'
)
{
g_debug
(
"ActUserManager: display seat ID is not set; can't switch sessions"
);
return
NULL
;
}
int
res
;
int
ret
;
char
*
session_class
;
can_activate_sessions
=
act_user_manager_can_switch
(
manager
);
ret
=
FALSE
;
res
=
sd_session_get_class
(
session_id
,
&
session_class
);
if
(
!
can_activate_sessions
)
{
g_debug
(
"ActUserManager: seat is unable to activate sessions"
);
return
NULL
;
if
(
res
<
0
)
{
g_debug
(
"failed to determine class of session %s: %s"
,
session_id
,
strerror
(
-
res
));
goto
out
;
}
if
(
!
console_kit_seat_call_get_sessions_sync
(
manager
->
priv
->
seat
.
seat_proxy
,
&
sessions
,
NULL
,
&
error
))
{
if
(
error
!=
NULL
)
{
g_warning
(
"unable to determine sessions for user: %s"
,
error
->
message
);
g_error_free
(
error
);
}
else
{
g_warning
(
"unable to determine sessions for user"
);
}
return
NULL
;
if
(
g_strcmp0
(
session_class
,
"greeter"
)
==
0
)
{
ret
=
TRUE
;
}
primary_ssid
=
NULL
;
for
(
i
=
sessions
;
i
;
i
++
)
{
if
(
session_is_login_window
(
manager
,
*
i
))
{
primary_ssid
=
g_strdup
(
*
i
);
break
;
}
free
(
session_class
);
out:
return
ret
;
}
#endif
static
gboolean
session_is_login_window
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
return
_systemd_session_is_login_window
(
manager
,
session_id
);
}
g_strfreev
(
sessions
);
#endif
return
primary_ssid
;
return
_ck_session_is_login_window
(
manager
,
session_id
)
;
}
gboolean
act_user_manager_goto_login_session
(
ActUserManager
*
manager
)
{
gboolean
ret
;
gboolean
res
;
char
*
ssid
;
GError
*
error
;
g_return_val_if_fail
(
ACT_IS_USER_MANAGER
(
manager
),
FALSE
);
g_return_val_if_fail
(
manager
->
priv
->
is_loaded
,
FALSE
);
ret
=
FALSE
;
/* First look for any existing LoginWindow sessions on the seat.
If none are found, create a new one. */
ssid
=
_get_login_window_session_id
(
manager
);
if
(
ssid
!=
NULL
)
{
res
=
activate_session_id
(
manager
,
manager
->
priv
->
seat
.
id
,
ssid
);
if
(
res
)
{
ret
=
TRUE
;
res
=
g_spawn_command_line_async
(
"gdmflexiserver"
,
&
error
);
if
(
!
res
)
{
if
(
error
!=
NULL
)
{
g_warning
(
"Unable to start new login: %s"
,
error
->
message
);
g_error_free
(
error
);
}
else
{
g_warning
(
"Unable to start new login"
);
}
}
if
(
!
ret
)
{
res
=
start_new_login_session
(
manager
);
if
(
res
)
{
ret
=
TRUE
;
}
}
return
res
;
return
ret
;
}
#ifdef WITH_SYSTEMD
gboolean
act_user_manager_can_switch
(
ActUserManager
*
manager
)
_can_activate_systemd_sessions
(
ActUserManager
*
manager
)
{
gboolean
can_activate_sessions
;
GError
*
error
=
NULL
;
int
res
;
if
(
!
manager
->
priv
->
is_loaded
)
{
g_debug
(
"ActUserManager: Unable to switch sessions until fully loaded"
);
res
=
sd_seat_can_multi_session
(
manager
->
priv
->
seat
.
id
);
if
(
res
<
0
)
{
g_warning
(
"unable to determine if seat can activate sessions: %s"
,
strerror
(
-
res
));
return
FALSE
;
}
if
(
manager
->
priv
->
seat
.
id
==
NULL
||
manager
->
priv
->
seat
.
id
[
0
]
==
'\0'
)
{
g_debug
(
"ActUserManager: display seat ID is not set; can't switch sessions"
);
return
FALSE
;
}
return
res
>
0
;
}
#endif
g_debug
(
"ActUserManager: checking if seat can activate sessions"
);
gboolean
_can_activate_console_kit_sessions
(
ActUserManager
*
manager
)
{
GError
*
error
=
NULL
;
gboolean
can_activate_sessions
=
FALSE
;
if
(
!
console_kit_seat_call_can_activate_sessions_sync
(
manager
->
priv
->
seat
.
seat_proxy
,
&
can_activate_sessions
,
NULL
,
&
error
))
{
if
(
error
!=
NULL
)
{
...
...
@@ -388,6 +422,31 @@ act_user_manager_can_switch (ActUserManager *manager)
return
can_activate_sessions
;
}
gboolean
act_user_manager_can_switch
(
ActUserManager
*
manager
)
{
if
(
!
manager
->
priv
->
is_loaded
)
{
g_debug
(
"ActUserManager: Unable to switch sessions until fully loaded"
);
return
FALSE
;
}
if
(
manager
->
priv
->
seat
.
id
==
NULL
||
manager
->
priv
->
seat
.
id
[
0
]
==
'\0'
)
{
g_debug
(
"ActUserManager: display seat ID is not set; can't switch sessions"
);
return
FALSE
;
}
g_debug
(
"ActUserManager: checking if seat can activate sessions"
);
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
return
_can_activate_systemd_sessions
(
manager
);
}
#endif
return
_can_activate_console_kit_sessions
(
manager
);
}
gboolean
act_user_manager_activate_user_session
(
ActUserManager
*
manager
,
ActUser
*
user
)
...
...
@@ -415,7 +474,13 @@ act_user_manager_activate_user_session (ActUserManager *manager,
goto
out
;
}
res
=
activate_session_id
(
manager
,
manager
->
priv
->
seat
.
id
,
ssid
);
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
return
activate_systemd_session_id
(
manager
,
manager
->
priv
->
seat
.
id
,
ssid
);
}
#endif
res
=
activate_console_kit_session_id
(
manager
,
manager
->
priv
->
seat
.
id
,
ssid
);
if
(
!
res
)
{
g_debug
(
"ActUserManager: unable to activate session: %s"
,
ssid
);
goto
out
;
...
...
@@ -499,9 +564,42 @@ on_get_seat_id_finished (GObject *object,
g_object_unref
(
manager
);
}
#ifdef WITH_SYSTEMD
static
void
_get_systemd_seat_id
(
ActUserManager
*
manager
)
{
int
res
;
char
*
seat_id
;
res
=
sd_session_get_seat
(
manager
->
priv
->
seat
.
session_id
,
&
seat_id
);
if
(
res
<
0
)
{
g_warning
(
"Could not get seat of session '%s': %s"
,
manager
->
priv
->
seat
.
session_id
,
strerror
(
-
res
));
unload_seat
(
manager
);
return
;
}
manager
->
priv
->
seat
.
id
=
g_strdup
(
seat_id
);
free
(
seat_id
);
manager
->
priv
->
seat
.
state
++
;
load_seat_incrementally
(
manager
);
}
#endif
static
void
get_seat_id_for_current_session
(
ActUserManager
*
manager
)
{
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
_get_systemd_seat_id
(
manager
);
return
;
}
#endif
console_kit_session_call_get_seat_id
(
manager
->
priv
->
seat
.
session_proxy
,
NULL
,
on_get_seat_id_finished
,
...
...
@@ -808,9 +906,41 @@ on_get_current_session_finished (GObject *object,
g_object_unref
(
manager
);
}
#ifdef WITH_SYSTEMD
static
void
_get_current_systemd_session_id
(
ActUserManager
*
manager
)
{
char
*
session_id
;
int
res
;
res
=
sd_seat_get_active
(
"seat0"
,
&
session_id
,
NULL
);
if
(
res
<
0
)
{
g_debug
(
"Failed to identify the current session: %s"
,
strerror
(
-
res
));
unload_seat
(
manager
);
return
;
}
manager
->
priv
->
seat
.
session_id
=
g_strdup
(
session_id
);
free
(
session_id
);
manager
->
priv
->
seat
.
state
++
;
load_seat_incrementally
(
manager
);
}
#endif
static
void
get_current_session_id
(
ActUserManager
*
manager
)
{
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
_get_current_systemd_session_id
(
manager
);
return
;
}
#endif
console_kit_manager_call_get_current_session
(
manager
->
priv
->
ck_manager_proxy
,
NULL
,
on_get_current_session_finished
,
g_object_ref
(
manager
));
...
...
@@ -841,6 +971,13 @@ static void
get_proxy_for_new_session
(
ActUserManagerNewSession
*
new_session
)
{
GError
*
error
=
NULL
;
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
new_session
->
state
++
;
load_new_session_incrementally
(
new_session
);
return
;
}
#endif
new_session
->
proxy
=
console_kit_session_proxy_new_sync
(
new_session
->
manager
->
priv
->
connection
,
G_DBUS_PROXY_FLAGS_NONE
,
...
...
@@ -893,9 +1030,40 @@ on_get_unix_user_finished (GObject *object,
load_new_session_incrementally
(
new_session
);
}
#ifdef WITH_SYSTEMD
static
void
_get_uid_for_new_systemd_session
(
ActUserManagerNewSession
*
new_session
)
{
uid_t
uid
;
int
res
;
res
=
sd_session_get_uid
(
new_session
->
id
,
&
uid
);
if
(
res
<
0
)
{
g_debug
(
"Failed to get uid of session '%s': %s"
,
new_session
->
id
,
strerror
(
-
res
));
unload_new_session
(
new_session
);
return
;
}
new_session
->
uid
=
uid
;
new_session
->
state
++
;
load_new_session_incrementally
(
new_session
);
}
#endif
static
void
get_uid_for_new_session
(
ActUserManagerNewSession
*
new_session
)
{
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
_get_uid_for_new_systemd_session
(
new_session
);
return
;
}
#endif
g_assert
(
new_session
->
proxy
!=
NULL
);
console_kit_session_call_get_unix_user
(
new_session
->
proxy
,
...
...
@@ -1061,9 +1229,45 @@ on_get_x11_display_finished (GObject *object,
load_new_session_incrementally
(
new_session
);
}
#ifdef WITH_SYSTEMD
static
void
_get_x11_display_for_new_systemd_session
(
ActUserManagerNewSession
*
new_session
)
{
char
*
x11_display
;
int
res
;
res
=
sd_session_get_display
(
new_session
->
id
,
&
x11_display
);
if
(
res
<
0
)
{
g_debug
(
"ActUserManager: Failed to get the x11 display of session '%s': %s"
,
new_session
->
id
,
strerror
(
-
res
));
unload_new_session
(
new_session
);
return
;
}
g_debug
(
"ActUserManager: Found x11 display of session '%s': %s"
,
new_session
->
id
,
x11_display
);
new_session
->
x11_display
=
g_strdup
(
x11_display
);
free
(
x11_display
);
new_session
->
state
++
;
load_new_session_incrementally
(
new_session
);
}
#endif
static
void
get_x11_display_for_new_session
(
ActUserManagerNewSession
*
new_session
)
{
#ifdef WITH_SYSTEMD
if
(
sd_booted
()
>
0
)
{
_get_x11_display_for_new_systemd_session
(
new_session
);
return
;
}
#endif
g_assert
(
new_session
->
proxy
!=
NULL
);
console_kit_session_call_get_x11_display
(
new_session
->
proxy
,
...
...
@@ -1186,9 +1390,8 @@ match_new_session_cmpfunc (gconstpointer a,
}
static
void
seat_session_removed
(
GDBusProxy
*
seat_proxy
,
const
char
*
session_id
,
ActUserManager
*
manager
)
_remove_session
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
ActUser
*
user
;
GSList
*
found
;
...
...
@@ -1239,11 +1442,209 @@ seat_session_removed (GDBusProxy *seat_proxy,
_act_user_remove_session
(
user
,
session_id
);
}
static
void
seat_session_removed
(
GDBusProxy
*
seat_proxy
,
const
char
*
session_id
,
ActUserManager
*
manager
)
{
_remove_session
(
manager
,
session_id
);
}
#ifdef WITH_SYSTEMD
static
gboolean
_session_recognized
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
GSList
*
node
;
if
(
g_hash_table_contains
(
manager
->
priv
->
sessions
,
session_id
))
{
return
TRUE
;
}
node
=
manager
->
priv
->
new_sessions
;
while
(
node
!=
NULL
)
{
ActUserManagerNewSession
*
new_session
=
node
->
data
;
if
(
g_strcmp0
(
new_session
->
id
,
session_id
)
==
0
)
{
return
TRUE
;
}
node
=
node
->
next
;
}
return
FALSE
;
}
static
void
_add_systemd_session
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
load_new_session
(
manager
,
session_id
);
}
static
void
_add_new_systemd_sessions
(
ActUserManager
*
manager
,
GHashTable
*
systemd_sessions
)
{
GHashTableIter
iter
;
gpointer
key
,
value
;
g_hash_table_iter_init
(
&
iter
,
systemd_sessions
);
while
(
g_hash_table_iter_next
(
&
iter
,
&
key
,
&
value
))
{
char
*
session_id
=
key
;
if
(
!
_session_recognized
(
manager
,
session_id
))
{
_add_systemd_session
(
manager
,
session_id
);
}
}
}
static
void
_remove_systemd_session
(
ActUserManager
*
manager
,
const
char
*
session_id
)
{
_remove_session
(
manager
,
session_id
);
}
static
void
_remove_stale_systemd_sessions
(
ActUserManager
*
manager
,
GHashTable
*
systemd_sessions
)
{
GHashTableIter
iter
;
gpointer
key
,
value
;
GSList
*
node