File kde-workspace-4.11.0-kdm-logind-multiseat.patch of Package kdebase4-workspace
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a3bdbb3..270b595 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,6 +128,13 @@ if(Q_WS_X11)
endif()
endif(Q_WS_X11)
+macro_optional_find_package(Systemd)
+set_package_properties(Systemd PROPERTIES DESCRIPTION "Init and service manager for Linux"
+ URL "http://www.freedesktop.org/wiki/Software/systemd"
+ TYPE OPTIONAL
+ PURPOSE "Provides automatic multi-seat, session and power management features"
+ )
+
macro_optional_find_package(GLIB2 2.0)
set_package_properties(GLIB2 PROPERTIES DESCRIPTION "Low-level core library for data structure handling, portability wrappers, etc."
URL "http://www.gtk.org"
diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt
index 117b3a5..09d7808 100644
--- a/cmake/modules/CMakeLists.txt
+++ b/cmake/modules/CMakeLists.txt
@@ -8,6 +8,7 @@ set(cmakeFiles FindCkConnector.cmake
FindOpenGLES.cmake
FindPAM.cmake
FindSensors.cmake
+ FindSystemd.cmake
PkgConfigGetVar.cmake
UnixAuth.cmake )
diff --git a/cmake/modules/FindSystemd.cmake b/cmake/modules/FindSystemd.cmake
new file mode 100644
index 0000000..c1141b9
--- /dev/null
+++ b/cmake/modules/FindSystemd.cmake
@@ -0,0 +1,39 @@
+# Finds systemd and its libraries
+# Not a huge module but sufficient for now
+# Uses the same semantics as pkg_check_modules, i.e. ${LIB}{_FOUND,_INCLUDE_DIR,_LIBRARIES}
+# where ${LIB} can be one of the following:
+# LIBSYSTEMD_JOURNAL, SYSTEMD, LIBSYSTEMD_DAEMON, LIBSYSTEMD_LOGIN, LIBSYSTEMD_ID128
+#
+# Copyright: Red Hat, Inc. 2013
+# Author: Martin Briza <mbriza@redhat.com>
+#
+# Distributed under the BSD license. See COPYING-CMAKE-SCRIPTS for details.
+
+#defining any of these disables systemd support
+if (NOT LIBSYSTEMD_JOURNAL_FOUND AND
+ NOT SYSTEMD_FOUND AND
+ NOT LIBSYSTEMD_DAEMON_FOUND AND
+ NOT LIBSYSTEMD_LOGIN_FOUND AND
+ NOT LIBSYSTEMD_ID128_FOUND)
+find_package(PkgConfig)
+if (PKG_CONFIG_FOUND)
+ pkg_check_modules(LIBSYSTEMD_JOURNAL QUIET "libsystemd-journal")
+ pkg_check_modules(SYSTEMD QUIET "systemd")
+ pkg_check_modules(LIBSYSTEMD_DAEMON QUIET "libsystemd-daemon")
+ pkg_check_modules(LIBSYSTEMD_LOGIN QUIET "libsystemd-login")
+ pkg_check_modules(LIBSYSTEMD_ID128 QUIET "libsystemd-id128")
+endif (PKG_CONFIG_FOUND)
+
+if (SYSTEMD_FOUND)
+ message(STATUS "Found systemd")
+endif(SYSTEMD_FOUND)
+
+mark_as_advanced(LIBSYSTEMD_JOURNAL_FOUND SYSTEMD_FOUND LIBSYSTEMD_DAEMON_FOUND LIBSYSTEMD_LOGIN_FOUND LIBSYSTEMD_ID128_FOUND)
+mark_as_advanced(LIBSYSTEMD_JOURNAL_INCLUDE_DIR SYSTEMD_INCLUDE_DIR LIBSYSTEMD_DAEMON_INCLUDE_DIR LIBSYSTEMD_LOGIN_INCLUDE_DIR LIBSYSTEMD_ID128_INCLUDE_DIR)
+mark_as_advanced(LIBSYSTEMD_JOURNAL_LIBRARIES SYSTEMD_LIBRARIES LIBSYSTEMD_DAEMON_LIBRARIES LIBSYSTEMD_LOGIN_LIBRARIES LIBSYSTEMD_ID128_LIBRARIES)
+
+endif (NOT LIBSYSTEMD_JOURNAL_FOUND AND
+ NOT SYSTEMD_FOUND AND
+ NOT LIBSYSTEMD_DAEMON_FOUND AND
+ NOT LIBSYSTEMD_LOGIN_FOUND AND
+ NOT LIBSYSTEMD_ID128_FOUND)
diff --git a/kdm/backend/dm.c b/kdm/backend/dm.c
index e0f1366..84e30fd 100644
--- a/kdm/backend/dm.c
+++ b/kdm/backend/dm.c
@@ -50,6 +50,23 @@ from the copyright holder.
# include <sys/vt.h>
#endif
+#ifdef WITH_SYSTEMD
+# include <systemd/sd-login.h>
+# include <systemd/sd-daemon.h>
+
+#define SYSTEMD_FAILURE_LIMIT 25
+
+ static int systemdMonitorInit(void);
+ static void systemdMonitorDeinit();
+ static int systemdStartDisplay(char *);
+ static void systemdCheckAdded(char **);
+ static void systemdCheckRemoved(char **);
+ static void systemdHandleChange();
+
+ sd_login_monitor *systemdMonitor = NULL;
+ int systemdMonitorFd = -1;
+#endif
+
static void sigHandler(int n);
static int scanConfigs(int force);
static void startDisplay(struct display *d);
@@ -308,7 +325,16 @@ main(int argc, char **argv)
#ifdef XDMCP
updateListenSockets();
#endif
+
+#ifdef WITH_SYSTEMD
+ if (systemdMonitorInit())
+ systemdHandleChange();
+#endif
+
mainLoop();
+#ifdef WITH_SYSTEMD
+ systemdMonitorDeinit();
+#endif
closeCtrl(0);
if (sdRec.how) {
int pid;
@@ -1280,6 +1306,13 @@ mainLoop(void)
}
continue;
}
+#ifdef WITH_SYSTEMD
+ if (systemdMonitorFd >= 0 && FD_ISSET(systemdMonitorFd, &reads)) {
+ systemdHandleChange();
+ sd_login_monitor_flush(systemdMonitor);
+ continue;
+ }
+#endif
#ifdef XDMCP
if (processListenSockets(&reads))
continue;
@@ -1304,6 +1337,151 @@ mainLoop(void)
}
}
+#ifdef WITH_SYSTEMD
+static int
+systemdMonitorInit(void)
+{
+ if (sd_booted() <= 0) {
+ logError("Didn't boot with systemd, automatic multiseat won't be enabled\n");
+ return False;
+ }
+
+ int check = sd_login_monitor_new("seat", &systemdMonitor);
+ if (check < 0) {
+ logError("Can't get systemd monitor: %d, automatic multiseat won't be enabled\n", check);
+ return False;
+ }
+
+ systemdMonitorFd = sd_login_monitor_get_fd(systemdMonitor);
+ if (systemdMonitorFd < 0) {
+ logError("Can't retrieve file descriptor from the systemd monitor: %d, automatic multiseat won't be enabled\n", systemdMonitorFd);
+ sd_login_monitor_unref(systemdMonitor);
+ systemdMonitorFd = -1;
+ return False;
+ }
+
+ registerInput(systemdMonitorFd);
+ return True;
+}
+
+static void
+systemdMonitorDeinit(void)
+{
+ if (systemdMonitor) {
+ sd_login_monitor_unref(systemdMonitor);
+ }
+ systemdMonitorFd = -1;
+}
+
+static int
+systemdStartDisplay(char *seat)
+{
+ struct display *link = NULL;
+ for (link = displays; link; link = link-> next) {
+ if (link->status == reserve)
+ break;
+ }
+ if (!link) {
+ logError("There's not enough reserve displays for all your seats/sessions");
+ return False;
+ }
+ if (!strDup((&link->systemdSeat), seat)) {
+ return False;
+ }
+#ifdef HAVE_VTS
+ link->serverVT = 0;
+#endif
+ link->status = notRunning;
+ link->stillThere = True;
+ link->authorize = True;
+ link->displayType = dLocal | dPermanent;
+ link->reqSrvVT = -1;
+ link->serverPid = -1;
+ return True;
+}
+
+static void
+systemdCheckAdded(char **seat_names)
+{
+ char **iter_name;
+ struct display *link;
+ for (iter_name = seat_names; *iter_name; iter_name++) {
+ if (strcmp(*iter_name, "seat0") == 0)
+ continue; /* ignore the main seat */
+ int can_graphical = sd_seat_can_graphical(*iter_name);
+ for (link = displays; link; link = link->next) {
+ if (!link->systemdSeat)
+ continue;
+ /* see if the can_graphical property didn't change */
+ if (0 == strcmp(*iter_name, link->systemdSeat)) {
+ if (!can_graphical) {
+ free(link->systemdSeat);
+ link->systemdSeat = NULL;
+ rStopDisplay(link, DS_RESERVE);
+ }
+ break;
+ }
+ }
+ /* the display wasn't found */
+ if (!link) {
+ if (can_graphical) {
+ /* if starting the display failed, skip this round until the next change */
+ if (!systemdStartDisplay(*iter_name))
+ break;
+ }
+ }
+ }
+}
+
+static void
+systemdCheckRemoved(char **seat_names)
+{
+ char **iter_name;
+ struct display *link;
+ for (link = displays; link; link = link->next) {
+ for (iter_name = seat_names; *iter_name; iter_name++) {
+ if (strcmp(*iter_name, "seat0") == 0)
+ continue; /* ignore the main seat */
+ if (link->systemdSeat && strcmp(*iter_name, link->systemdSeat) == 0)
+ break;
+ }
+ if (!(*iter_name) && link->systemdSeat) { /* was not found, stop this one */
+ free(link->systemdSeat);
+ link->systemdSeat = NULL;
+ rStopDisplay(link, DS_RESERVE);
+ }
+ }
+}
+
+static void
+systemdHandleChange(void)
+{
+ static int failures = 0;
+ char **seat_names;
+ char **iter_name;
+ int check;
+ if ((check = sd_get_seats(&seat_names)) < 0) {
+ logError("Can't obtain systemd seats, error %d\n", -check);
+ failures++;
+ if (failures >= SYSTEMD_FAILURE_LIMIT) {
+ logError("%u failed calls to sd_get_seats, disabling systemd multi-seat support\n", SYSTEMD_FAILURE_LIMIT);
+ systemdMonitorDeinit();
+ }
+ return;
+ }
+
+ if (!check)
+ return;
+
+ systemdCheckAdded(seat_names);
+ systemdCheckRemoved(seat_names);
+
+ for (iter_name = seat_names; *iter_name; iter_name++)
+ free(*iter_name);
+ free(seat_names);
+}
+#endif
+
static void
checkDisplayStatus(struct display *d)
{
diff --git a/kdm/backend/dm.h b/kdm/backend/dm.h
index 64e106b..48b302e 100644
--- a/kdm/backend/dm.h
+++ b/kdm/backend/dm.h
@@ -306,6 +306,9 @@ struct display {
char *greeterAuthFile; /* file to store authorization for greeter in */
int plymouth_vt; /* Plymouth's VT nr */
+#ifdef WITH_SYSTEMD
+ char *systemdSeat;
+#endif
};
#define d_location 1
diff --git a/kdm/backend/CMakeLists.txt b/kdm/backend/CMakeLists.txt
index 25f383f..26ad237 100644
--- a/kdm/backend/CMakeLists.txt
+++ b/kdm/backend/CMakeLists.txt
@@ -45,6 +45,10 @@ if (SECURE_RPC)
rpcauth.c
)
endif (SECURE_RPC)
+if(LIBSYSTEMD_LOGIN_FOUND AND LIBSYSTEMD_DAEMON_FOUND)
+ add_definitions( -DWITH_SYSTEMD=1 )
+ set(KDM_SYSTEMD_LIBRARIES ${LIBSYSTEMD_DAEMON_LIBRARIES} ${LIBSYSTEMD_LOGIN_LIBRARIES} )
+endif(LIBSYSTEMD_LOGIN_FOUND AND LIBSYSTEMD_DAEMON_FOUND)
macro_add_file_dependencies(dm.h ${confci})
macro_add_file_dependencies(error.c ${CMAKE_CURRENT_SOURCE_DIR}/printf.c)
kde4_add_executable(kdm NOGUI ${kdm_SRCS})
@@ -60,6 +64,7 @@ target_link_libraries( kdm
${NSL_LIBRARIES}
${RESOLV_LIBRARIES}
${SOCKET_LIBRARIES}
+ ${KDM_SYSTEMD_LIBRARIES}
)
if (CKCONNECTOR_FOUND)
include_directories(${CKCONNECTOR_INCLUDE_DIR} ${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR})
diff --git a/kdm/backend/server.c b/kdm/backend/server.c
index d8dd6f3..38c4f3a 100644
--- a/kdm/backend/server.c
+++ b/kdm/backend/server.c
@@ -70,6 +70,25 @@ prepareServerArgv(struct display *d, const char *args)
if (!changeUser(d->serverUID, d->authFile))
exit(47);
+#ifdef WITH_SYSTEMD
+ if (d->systemdSeat) {
+ if (!(argv = parseArgs(argv, "-seat")))
+ exit(47);
+ if (!(argv = parseArgs(argv, d->systemdSeat)))
+ exit(47);
+ if (!(argv = parseArgs(argv, "-layout")))
+ exit(47);
+ if (!(argv = parseArgs(argv, d->systemdSeat)))
+ exit(47);
+ }
+ else {
+ if (!(argv = parseArgs(argv, "-seat")))
+ exit(47);
+ if (!(argv = parseArgs(argv, "seat0")))
+ exit(47);
+ }
+#endif
+
return argv;
}
diff --git a/kdm/backend/client.c b/kdm/backend/client.c
index 26bb0b4..b38bc5a 100644
--- a/kdm/backend/client.c
+++ b/kdm/backend/client.c
@@ -1460,6 +1460,14 @@ startClient(volatile int *pid)
#endif
userEnviron = inheritEnv(env, envvars);
env = systemEnv(0, curuser);
+#ifdef WITH_SYSTEMD
+ if (td->systemdSeat) {
+ char *envbuf;
+ ASPrintf(&envbuf, "XDG_SEAT=%s", td->systemdSeat);
+ pam_putenv(pamh, envbuf);
+ env = setEnv(env, "XDG_SEAT", td->systemdSeat);
+ }
+#endif
systemEnviron = setEnv(env, "HOME", p->pw_dir);
debug("user environment:\n%[|''>'\n's"
"system environment:\n%[|''>'\n's"
diff --git a/kdm/backend/session.c b/kdm/backend/session.c
index 0e7901c..614387d 100644
--- a/kdm/backend/session.c
+++ b/kdm/backend/session.c
@@ -437,6 +437,10 @@ openGreeter()
grttalk.pipe = &grtproc.pipe;
env = systemEnv(dupEnv(), 0);
+#ifdef WITH_SYSTEMD
+ if (td->systemdSeat)
+ env = setEnv(env, "XDG_SEAT", td->systemdSeat);
+#endif
if (gOpen(&grtproc, (char **)0, "_greet", env, name,
greeterUID, td->greeterAuthFile, &td->gpipe))
sessionExit(EX_UNMANAGE_DPY);