|
@@ -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;
|
|
|
+}
|