Browse Source

Add support ConsoleKit.

Applied patch #3209. Thanks to gawen for the patch.

Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/slim/trunk@200 7c53e7cc-98ea-0310-8f1f-a0b24da60408
iwamatsu 12 years ago
parent
commit
d37da78f1c
5 changed files with 274 additions and 0 deletions
  1. 28 0
      CMakeLists.txt
  2. 149 0
      Ck.cpp
  3. 46 0
      Ck.h
  4. 45 0
      app.cpp
  5. 6 0
      app.h

+ 28 - 0
CMakeLists.txt

@@ -56,6 +56,7 @@ set(slim_srcs
 	switchuser.cpp
 	util.cpp
 	PAM.cpp
+	Ck.cpp
 	png.c
 	jpeg.c
 )
@@ -96,6 +97,33 @@ else(USE_PAM)
 	message("\tPAM disabled")
 endif(USE_PAM)
 
+# ConsoleKit
+if(USE_CONSOLEKIT)
+	find_package(CkConnector)
+	message("\tConsoleKit Enabled")
+	if(CKCONNECTOR_FOUND)
+		message("\tConsoleKit Found")
+		# DBus check
+		find_package(DBus REQUIRED)
+		if(DBUS_FOUND)
+			message("\tDBus Found")
+			target_link_libraries(${PROJECT_NAME} ${DBUS_LIBRARIES})
+			include_directories(${DBUS_ARCH_INCLUDE_DIR})
+			include_directories(${DBUS_INCLUDE_DIR})
+			set(SLIM_DEFINITIONS ${SLIM_DEFINITIONS} "-DUSE_CONSOLEKIT")
+			target_link_libraries(${PROJECT_NAME} ${CKCONNECTOR_LIBRARIES})
+			include_directories(${CKCONNECTOR_INCLUDE_DIR})
+		else(DBUS_FOUND)
+			message("\tDBus Not Found")
+		endif(DBUS_FOUND)
+	else(CKCONNECTOR_FOUND)
+		message("\tConsoleKit Not Found")
+		message("\tConsoleKit disabled")
+	endif(CKCONNECTOR_FOUND)
+else(USE_CONSOLEKIT)
+	message("\tConsoleKit disabled")
+endif(USE_CONSOLEKIT)
+
 # system librarys
 find_library(M_LIB m)
 find_library(RT_LIB rt)

+ 149 - 0
Ck.cpp

@@ -0,0 +1,149 @@
+/* SLiM - Simple Login Manager
+   Copyright (C) 2011 David Hauweele
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+*/
+
+#include <cstdio>
+#include <iostream>
+
+#include <ck-connector.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <stdarg.h>
+
+#include "Ck.h"
+
+namespace Ck {
+  Exception::Exception(const std::string &func,
+                       const std::string &errstr):
+    func(func),
+    errstr(errstr)
+  {}
+
+  dbus_bool_t Session::ck_connector_open_graphic_session(const std::string &display,
+                                                         uid_t uid)
+  {
+    dbus_bool_t local        = true;
+    const char *session_type = "x11";
+    const char *x11_display  = display.c_str();
+    const char *x11_device   = get_x11_device(display);
+    const char *remote_host  = "";
+    const char *display_dev  = "";
+
+    return ck_connector_open_session_with_parameters(ckc, &error,
+                                                     "unix-user", &uid,
+                                                     "session-type", &session_type,
+                                                     "x11-display", &x11_display,
+                                                     "x11-display-device", &x11_device,
+                                                     "display-device", &display_dev,
+                                                     "remote-host-name", &remote_host,
+                                                     "is-local", &local,
+                                                     NULL);
+  }
+
+  const char * Session::get_x11_device(const std::string &display)
+  {
+    static char device[32];
+
+    Display *xdisplay = XOpenDisplay(display.c_str());
+
+    if(!xdisplay)
+      throw Exception(__func__, "cannot open display");
+
+    Window root;
+    Atom xfree86_vt_atom;
+    Atom return_type_atom;
+    int return_format;
+    unsigned long return_count;
+    unsigned long bytes_left;
+    unsigned char *return_value;
+    long vt;
+
+    xfree86_vt_atom = XInternAtom(xdisplay, "XFree86_VT", true);
+
+    if(xfree86_vt_atom == None)
+      throw Exception(__func__, "cannot get XFree86_VT");
+
+    root = DefaultRootWindow(xdisplay);
+
+    if(XGetWindowProperty(xdisplay, root, xfree86_vt_atom,
+                          0L, 1L, false, XA_INTEGER,
+                          &return_type_atom, &return_format,
+                          &return_count, &bytes_left,
+                          &return_value) != Success)
+      throw Exception(__func__, "cannot get root window property");
+
+    if(return_type_atom != XA_INTEGER)
+      throw Exception(__func__, "bad atom type");
+
+    if(return_format != 32)
+      throw Exception(__func__, "invalid return format");
+
+    if(return_count != 1)
+      throw Exception(__func__, "invalid count");
+
+    if(bytes_left != 0)
+      throw Exception(__func__, "invalid bytes left");
+
+    vt = *((long *)return_value);
+
+    std::snprintf(device, 32, "/dev/tty%ld", vt);
+
+    if(return_value)
+      XFree(return_value);
+
+    return device;
+  }
+
+  void Session::open_session(const std::string &display, uid_t uid)
+  {
+    ckc = ck_connector_new();
+
+    if(!ckc)
+      throw Exception(__func__, "error setting up connection to ConsoleKit");
+
+    if(!ck_connector_open_graphic_session(display, uid)) {
+      if(dbus_error_is_set(&error))
+        throw Exception(__func__, error.message);
+      else
+        throw Exception(__func__, "cannot open ConsoleKit session: OOM, DBus system bus "
+                        " not available or insufficient privileges");
+    }
+  }
+
+  const char * Session::get_xdg_session_cookie()
+  {
+    return ck_connector_get_cookie(ckc);
+  }
+
+  void Session::close_session()
+  {
+    if(!ck_connector_close_session(ckc, &error)) {
+      if(dbus_error_is_set(&error))
+        throw Exception(__func__, error.message);
+      else
+        throw Exception(__func__, "cannot close ConsoleKit session: OOM, DBus system bus "
+                        " not available or insufficient privileges");
+    }
+  }
+
+  Session::Session()
+  {
+    dbus_error_init(&error);
+  }
+
+  Session::~Session()
+  {
+    dbus_error_free(&error);
+  }
+};
+
+std::ostream& operator<<( std::ostream& os, const Ck::Exception& e)
+{
+  os << e.func << ": " << e.errstr;
+  return os;
+}

+ 46 - 0
Ck.h

@@ -0,0 +1,46 @@
+/* SLiM - Simple Login Manager
+   Copyright (C) 2007 Martin Parm
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+*/
+
+#ifndef _CK_H_
+#define _CK_H_
+
+#include <string>
+
+#include <ck-connector.h>
+#include <dbus/dbus.h>
+
+namespace Ck {
+  class Exception {
+  public:
+    std::string func;
+    std::string errstr;
+    Exception(const std::string &func, const std::string &errstr);
+  };
+
+  class Session {
+  private:
+    CkConnector *ckc;
+    DBusError error;
+
+    const char * get_x11_device(const std::string &display);
+    dbus_bool_t ck_connector_open_graphic_session(const std::string &display,
+                                                  uid_t uid);
+  public:
+    const char * get_xdg_session_cookie();
+    void open_session(const std::string &display, uid_t uid);
+    void close_session();
+
+    Session();
+    ~Session();
+  };
+};
+
+std::ostream& operator<<( std::ostream& os, const Ck::Exception& e);
+
+#endif /* _CK_H_ */

+ 45 - 0
app.cpp

@@ -556,6 +556,17 @@ void App::Login() {
     }
 #endif
 
+#ifdef USE_CONSOLEKIT
+    // Setup the ConsoleKit session
+    try {
+        ck.open_session(DisplayName, pw->pw_uid);
+    }
+    catch(Ck::Exception &e) {
+        cerr << APPNAME << ": " << e << endl;
+        exit(ERR_EXIT);
+    }
+#endif
+
     // Create new process
     pid = fork();
     if(pid == 0) {
@@ -563,9 +574,30 @@ void App::Login() {
         // Get a copy of the environment and close the child's copy
         // of the PAM-handle.
         char** child_env = pam.getenvlist();
+
+# ifdef USE_CONSOLEKIT
+        char** old_env = child_env;
+
+        // Grow the copy of the environment for the session cookie
+        int n;
+        for(n = 0; child_env[n] != NULL ; n++);
+
+        n++;
+
+        child_env = static_cast<char**>(malloc(sizeof(char*)*n));
+        memcpy(child_env, old_env, sizeof(char*)*n);
+        child_env[n - 1] = StrConcat("XDG_SESSION_COOKIE=", ck.get_xdg_session_cookie());
+        child_env[n] = NULL;
+# endif /* USE_CONSOLEKIT */
+
         pam.end();
 #else
+
+# ifdef USE_CONSOLEKIT
+        const int Num_Of_Variables = 12; // Number of env. variables + 1
+# else
         const int Num_Of_Variables = 11; // Number of env. variables + 1
+# endif /* USE_CONSOLEKIT */
         char** child_env = static_cast<char**>(malloc(sizeof(char*)*Num_Of_Variables));
         int n = 0;
         if(term) child_env[n++]=StrConcat("TERM=", term);
@@ -578,7 +610,11 @@ void App::Login() {
         child_env[n++]=StrConcat("DISPLAY=", DisplayName);
         child_env[n++]=StrConcat("MAIL=", maildir.c_str());
         child_env[n++]=StrConcat("XAUTHORITY=", xauthority.c_str());
+# ifdef USE_CONSOLEKIT
+        child_env[n++]=StrConcat("XDG_SESSION_COOKIE=", ck.get_xdg_session_cookie());
+# endif /* USE_CONSOLEKIT */
         child_env[n++]=0;
+
 #endif
 
         // Login process starts here
@@ -619,6 +655,15 @@ void App::Login() {
         }
     }
 
+#ifdef USE_CONSOLEKIT
+    try {
+        ck.close_session();
+    }
+    catch(Ck::Exception &e) {
+        cerr << APPNAME << ": " << e << endl;
+    };
+#endif
+
 #ifdef USE_PAM
     try{
         pam.close_session();

+ 6 - 0
app.h

@@ -27,6 +27,9 @@
 #ifdef USE_PAM
 #include "PAM.h"
 #endif
+#ifdef USE_CONSOLEKIT
+#include "Ck.h"
+#endif
 
 class App {
 public:
@@ -81,6 +84,9 @@ private:
 #ifdef USE_PAM
 	PAM::Authenticator pam;
 #endif
+#ifdef USE_CONSOLEKIT
+    Ck::Session ck;
+#endif
 
     // Options
     char* DispName;