/* 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 #include #include #include #include #include #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; }