@@ -18,12 +18,13 @@ INCLUDE(CheckTypeSize) | |||
# Version | |||
set(SLIM_VERSION_MAJOR "1") | |||
set(SLIM_VERSION_MINOR "3") | |||
set(SLIM_VERSION_PATCH "4") | |||
set(SLIM_VERSION_PATCH "6") | |||
set(SLIM_VERSION "${SLIM_VERSION_MAJOR}.${SLIM_VERSION_MINOR}.${SLIM_VERSION_PATCH}") | |||
set(CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation Directory") | |||
set(PKGDATADIR "${CMAKE_INSTALL_PREFIX}/share/slim") | |||
set(SYSCONFDIR "/etc") | |||
set(LIBDIR "/lib") | |||
set(MANDIR "${CMAKE_INSTALL_PREFIX}/share/man") | |||
set(SLIM_DEFINITIONS) | |||
@@ -42,32 +43,56 @@ set(SLIM_DEFINITIONS ${SLIM_DEFINITIONS} "-DPKGDATADIR=\"${PKGDATADIR}\"") | |||
set(SLIM_DEFINITIONS ${SLIM_DEFINITIONS} "-DSYSCONFDIR=\"${SYSCONFDIR}\"") | |||
# Flags | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -g -O2" ) | |||
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -g -O2" ) | |||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -g -O2") | |||
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -g -O2") | |||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -g -O2") | |||
# source | |||
set(slim_srcs | |||
main.cpp | |||
app.cpp | |||
cfg.cpp | |||
image.cpp | |||
numlock.cpp | |||
panel.cpp | |||
switchuser.cpp | |||
util.cpp | |||
log.cpp | |||
png.c | |||
jpeg.c | |||
) | |||
set(slimlock_srcs | |||
slimlock.cpp | |||
) | |||
set(common_srcs | |||
cfg.cpp | |||
image.cpp | |||
log.cpp | |||
panel.cpp | |||
util.cpp | |||
) | |||
if(USE_PAM) | |||
set(slim_srcs ${slim_srcs} PAM.cpp) | |||
set(common_srcs ${common_srcs} PAM.cpp) | |||
# for now, only build slimlock if we are using PAM. | |||
set(BUILD_SLIMLOCK 1) | |||
endif(USE_PAM) | |||
# Build common library | |||
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries") | |||
if (BUILD_SHARED_LIBS) | |||
message(STATUS "Enable shared library building") | |||
add_library(libslim ${common_srcs}) | |||
else(BUILD_SHARED_LIBS) | |||
message(STATUS "Disable shared library building") | |||
add_library(libslim STATIC ${common_srcs}) | |||
endif(BUILD_SHARED_LIBS) | |||
if(USE_CONSOLEKIT) | |||
set(slim_srcs ${slim_srcs} Ck.cpp) | |||
endif(USE_CONSOLEKIT) | |||
add_executable(${PROJECT_NAME} ${slim_srcs}) | |||
if(BUILD_SLIMLOCK) | |||
add_executable(slimlock ${slimlock_srcs}) | |||
endif(BUILD_SLIMLOCK) | |||
#Set the custom CMake module directory where our include/lib finders are | |||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") | |||
@@ -95,6 +120,7 @@ if(USE_PAM) | |||
message("\tPAM Found") | |||
set(SLIM_DEFINITIONS ${SLIM_DEFINITIONS} "-DUSE_PAM") | |||
target_link_libraries(${PROJECT_NAME} ${PAM_LIBRARY}) | |||
target_link_libraries(slimlock ${PAM_LIBRARY}) | |||
include_directories(${PAM_INCLUDE_DIR}) | |||
else(PAM_FOUND) | |||
message("\tPAM Not Found") | |||
@@ -134,6 +160,7 @@ endif(USE_CONSOLEKIT) | |||
find_library(M_LIB m) | |||
find_library(RT_LIB rt) | |||
find_library(CRYPTO_LIB crypt) | |||
find_package(Threads) | |||
add_definitions(${SLIM_DEFINITIONS}) | |||
@@ -142,6 +169,7 @@ include_directories( | |||
${X11_INCLUDE_DIR} | |||
${X11_Xft_INCLUDE_PATH} | |||
${X11_Xrender_INCLUDE_PATH} | |||
${X11_Xrandr_INCLUDE_PATH} | |||
${FREETYPE_INCLUDE_DIR_freetype2} | |||
${X11_Xmu_INCLUDE_PATH} | |||
${ZLIB_INCLUDE_DIR} | |||
@@ -149,7 +177,12 @@ include_directories( | |||
${PNG_INCLUDE_DIR} | |||
) | |||
#Set up library with all found packages | |||
target_link_libraries(libslim | |||
${JPEG_LIBRARIES} | |||
${PNG_LIBRARIES} | |||
) | |||
#Set up library with all found packages for slim | |||
target_link_libraries(${PROJECT_NAME} | |||
${M_LIB} | |||
${RT_LIB} | |||
@@ -157,18 +190,58 @@ target_link_libraries(${PROJECT_NAME} | |||
${X11_X11_LIB} | |||
${X11_Xft_LIB} | |||
${X11_Xrender_LIB} | |||
${X11_Xrandr_LIB} | |||
${X11_Xmu_LIB} | |||
${FREETYPE_LIBRARY} | |||
${JPEG_LIBRARIES} | |||
${PNG_LIBRARIES} | |||
) | |||
libslim | |||
) | |||
if(BUILD_SLIMLOCK) | |||
#Set up library with all found packages for slimlock | |||
target_link_libraries(slimlock | |||
${M_LIB} | |||
${RT_LIB} | |||
${CRYPTO_LIB} | |||
${X11_X11_LIB} | |||
${X11_Xft_LIB} | |||
${X11_Xrender_LIB} | |||
${X11_Xrandr_LIB} | |||
${X11_Xmu_LIB} | |||
${X11_Xext_LIB} | |||
${FREETYPE_LIBRARY} | |||
${JPEG_LIBRARIES} | |||
${PNG_LIBRARIES} | |||
${CMAKE_THREAD_LIBS_INIT} | |||
libslim | |||
) | |||
endif(BUILD_SLIMLOCK) | |||
####### install | |||
# slim | |||
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin ) | |||
install(TARGETS slim RUNTIME DESTINATION bin) | |||
install(TARGETS slimlock RUNTIME DESTINATION bin) | |||
if (BUILD_SHARED_LIBS) | |||
set_target_properties(libslim PROPERTIES | |||
OUTPUT_NAME slim | |||
SOVERSION ${SLIM_VERSION}) | |||
install(TARGETS libslim | |||
LIBRARY DESTINATION lib | |||
ARCHIVE DESTINATION lib | |||
) | |||
endif (BUILD_SHARED_LIBS) | |||
# man file | |||
install(FILES slim.1 DESTINATION ${MANDIR}/man1/) | |||
install(FILES slimlock.1 DESTINATION ${MANDIR}/man1/) | |||
# configure | |||
install(FILES slim.conf DESTINATION ${SYSCONFDIR}) | |||
# systemd service file | |||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
install(FILES slim.service DESTINATION ${LIBDIR}/systemd/system) | |||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") | |||
# themes directory | |||
subdirs(themes) |
@@ -1,3 +1,13 @@ | |||
1.3.6 - 2013.10.01 | |||
* Merge slimlock. | |||
* Add support ^H (like backspace). | |||
* And fix some bugs. | |||
1.3.5 - 2012.12.31 | |||
* Support UTF8 string. | |||
* Add systemd service. | |||
* And fix some bugs. | |||
1.3.4 - 2012.06.26 | |||
* Replaced stderr writes function. | |||
* Fix numlock control. | |||
@@ -19,128 +19,128 @@ | |||
namespace Ck { | |||
Exception::Exception(const std::string &func, | |||
const std::string &errstr): | |||
func(func), | |||
errstr(errstr) | |||
const std::string &errstr): | |||
func(func), | |||
errstr(errstr) | |||
{} | |||
dbus_bool_t Session::ck_connector_open_graphic_session(const std::string &display, | |||
uid_t uid) | |||
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); | |||
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]; | |||
static char device[32]; | |||
Display *xdisplay = XOpenDisplay(display.c_str()); | |||
Display *xdisplay = XOpenDisplay(display.c_str()); | |||
if(!xdisplay) | |||
throw Exception(__func__, "cannot open display"); | |||
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; | |||
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); | |||
xfree86_vt_atom = XInternAtom(xdisplay, "XFree86_VT", true); | |||
if(xfree86_vt_atom == None) | |||
throw Exception(__func__, "cannot get XFree86_VT"); | |||
if(xfree86_vt_atom == None) | |||
throw Exception(__func__, "cannot get XFree86_VT"); | |||
root = DefaultRootWindow(xdisplay); | |||
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(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_type_atom != XA_INTEGER) | |||
throw Exception(__func__, "bad atom type"); | |||
if(return_format != 32) | |||
throw Exception(__func__, "invalid return format"); | |||
if(return_format != 32) | |||
throw Exception(__func__, "invalid return format"); | |||
if(return_count != 1) | |||
throw Exception(__func__, "invalid count"); | |||
if(return_count != 1) | |||
throw Exception(__func__, "invalid count"); | |||
if(bytes_left != 0) | |||
throw Exception(__func__, "invalid bytes left"); | |||
if(bytes_left != 0) | |||
throw Exception(__func__, "invalid bytes left"); | |||
vt = *((long *)return_value); | |||
vt = *((long *)return_value); | |||
std::snprintf(device, 32, "/dev/tty%ld", vt); | |||
std::snprintf(device, 32, "/dev/tty%ld", vt); | |||
if(return_value) | |||
XFree(return_value); | |||
if(return_value) | |||
XFree(return_value); | |||
return device; | |||
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"); | |||
} | |||
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); | |||
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"); | |||
} | |||
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); | |||
dbus_error_init(&error); | |||
} | |||
Session::~Session() | |||
{ | |||
dbus_error_free(&error); | |||
dbus_error_free(&error); | |||
} | |||
}; | |||
} | |||
std::ostream& operator<<( std::ostream& os, const Ck::Exception& e) | |||
{ | |||
@@ -16,31 +16,31 @@ | |||
#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); | |||
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_ */ |
@@ -11,265 +11,263 @@ | |||
#include "PAM.h" | |||
namespace PAM { | |||
Exception::Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum): | |||
errnum(_errnum), | |||
errstr(pam_strerror(_pam_handle, _errnum)), | |||
func_name(_func_name) | |||
{} | |||
Exception::~Exception(void){} | |||
Auth_Exception::Auth_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum): | |||
Exception(_pam_handle, _func_name, _errnum){} | |||
Cred_Exception::Cred_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum): | |||
Exception(_pam_handle, _func_name, _errnum){} | |||
int Authenticator::_end(void){ | |||
int result=pam_end(pam_handle, last_result); | |||
pam_handle=0; | |||
return result; | |||
} | |||
Authenticator::Authenticator(conversation* conv, void* data): | |||
pam_handle(0), | |||
last_result(PAM_SUCCESS) | |||
{ | |||
pam_conversation.conv=conv; | |||
pam_conversation.appdata_ptr=data; | |||
} | |||
Authenticator::~Authenticator(void){ | |||
if (pam_handle) _end(); | |||
} | |||
void Authenticator::start(const std::string& service){ | |||
switch((last_result=pam_start(service.c_str(), NULL, &pam_conversation, &pam_handle))){ | |||
default: | |||
throw Exception(pam_handle, "pam_start()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::end(void){ | |||
switch((last_result=_end())){ | |||
default: | |||
throw Exception(pam_handle, "pam_end()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::set_item(const Authenticator::ItemType item, const void* value){ | |||
switch((last_result=pam_set_item(pam_handle, item, value))){ | |||
default: | |||
_end(); | |||
throw Exception(pam_handle, "pam_set_item()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
const void* Authenticator::get_item(const Authenticator::ItemType item){ | |||
const void* data; | |||
switch ((last_result=pam_get_item(pam_handle, item, &data))){ | |||
default: | |||
case PAM_SYSTEM_ERR: | |||
Exception::Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum): | |||
errnum(_errnum), | |||
errstr(pam_strerror(_pam_handle, _errnum)), | |||
func_name(_func_name) | |||
{} | |||
Exception::~Exception(void){} | |||
Auth_Exception::Auth_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum): | |||
Exception(_pam_handle, _func_name, _errnum){} | |||
Cred_Exception::Cred_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum): | |||
Exception(_pam_handle, _func_name, _errnum){} | |||
int Authenticator::_end(void){ | |||
int result=pam_end(pam_handle, last_result); | |||
pam_handle=0; | |||
return result; | |||
} | |||
Authenticator::Authenticator(conversation* conv, void* data): | |||
pam_handle(0), | |||
last_result(PAM_SUCCESS) | |||
{ | |||
pam_conversation.conv=conv; | |||
pam_conversation.appdata_ptr=data; | |||
} | |||
Authenticator::~Authenticator(void){ | |||
if (pam_handle) _end(); | |||
} | |||
void Authenticator::start(const std::string& service){ | |||
switch((last_result=pam_start(service.c_str(), NULL, &pam_conversation, &pam_handle))){ | |||
default: | |||
throw Exception(pam_handle, "pam_start()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::end(void){ | |||
switch((last_result=_end())){ | |||
default: | |||
throw Exception(pam_handle, "pam_end()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::set_item(const Authenticator::ItemType item, const void* value){ | |||
switch((last_result=pam_set_item(pam_handle, item, value))){ | |||
default: | |||
_end(); | |||
throw Exception(pam_handle, "pam_set_item()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
const void* Authenticator::get_item(const Authenticator::ItemType item){ | |||
const void* data; | |||
switch ((last_result=pam_get_item(pam_handle, item, &data))){ | |||
default: | |||
case PAM_SYSTEM_ERR: | |||
#ifdef __LIBPAM_VERSION | |||
case PAM_BAD_ITEM: | |||
case PAM_BAD_ITEM: | |||
#endif | |||
_end(); | |||
throw Exception(pam_handle, "pam_get_item()", last_result); | |||
_end(); | |||
throw Exception(pam_handle, "pam_get_item()", last_result); | |||
case PAM_PERM_DENIED: // The value of item was NULL | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return data; | |||
} | |||
case PAM_PERM_DENIED: /* The value of item was NULL */ | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return data; | |||
} | |||
#ifdef __LIBPAM_VERSION | |||
void Authenticator::fail_delay(const unsigned int micro_sec){ | |||
switch((last_result=pam_fail_delay(pam_handle, micro_sec))){ | |||
default: | |||
_end(); | |||
throw Exception(pam_handle, "fail_delay()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::fail_delay(const unsigned int micro_sec){ | |||
switch((last_result=pam_fail_delay(pam_handle, micro_sec))){ | |||
default: | |||
_end(); | |||
throw Exception(pam_handle, "fail_delay()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
#endif | |||
void Authenticator::authenticate(void){ | |||
switch((last_result=pam_authenticate(pam_handle, 0))){ | |||
default: | |||
case PAM_ABORT: | |||
case PAM_AUTHINFO_UNAVAIL: | |||
_end(); | |||
throw Exception(pam_handle, "pam_authenticate()", last_result); | |||
case PAM_USER_UNKNOWN: | |||
case PAM_MAXTRIES: | |||
case PAM_CRED_INSUFFICIENT: | |||
case PAM_AUTH_ERR: | |||
throw Auth_Exception(pam_handle, "pam_authentication()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
switch((last_result=pam_acct_mgmt(pam_handle, PAM_SILENT))){ | |||
// The documentation and implementation of Linux PAM differs: | |||
// PAM_NEW_AUTHTOKEN_REQD is described in the documentation but | |||
// don't exists in the actual implementation. This issue needs | |||
// to be fixes at some point. | |||
default: | |||
//case PAM_NEW_AUTHTOKEN_REQD: | |||
case PAM_ACCT_EXPIRED: | |||
case PAM_USER_UNKNOWN: | |||
_end(); | |||
throw Exception(pam_handle, "pam_acct_mgmt()", last_result); | |||
case PAM_AUTH_ERR: | |||
case PAM_PERM_DENIED: | |||
throw Auth_Exception(pam_handle, "pam_acct_mgmt()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
void Authenticator::open_session(void){ | |||
switch((last_result=pam_setcred(pam_handle, PAM_ESTABLISH_CRED))){ | |||
default: | |||
case PAM_CRED_ERR: | |||
case PAM_CRED_UNAVAIL: | |||
_end(); | |||
throw Exception(pam_handle, "pam_setcred()", last_result); | |||
case PAM_CRED_EXPIRED: | |||
case PAM_USER_UNKNOWN: | |||
throw Cred_Exception(pam_handle, "pam_setcred()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
switch((last_result=pam_open_session(pam_handle, 0))){ | |||
// The documentation and implementation of Linux PAM differs: | |||
// PAM_SESSION_ERROR is described in the documentation but | |||
// don't exists in the actual implementation. This issue needs | |||
// to be fixes at some point. | |||
default: | |||
//case PAM_SESSION_ERROR: | |||
pam_setcred(pam_handle, PAM_DELETE_CRED); | |||
_end(); | |||
throw Exception(pam_handle, "pam_open_session()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
void Authenticator::close_session(void){ | |||
switch((last_result=pam_close_session(pam_handle, 0))){ | |||
// The documentation and implementation of Linux PAM differs: | |||
// PAM_SESSION_ERROR is described in the documentation but | |||
// don't exists in the actual implementation. This issue needs | |||
// to be fixes at some point. | |||
default: | |||
//case PAM_SESSION_ERROR: | |||
pam_setcred(pam_handle, PAM_DELETE_CRED); | |||
_end(); | |||
throw Exception(pam_handle, "pam_close_session", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
switch((last_result=pam_setcred(pam_handle, PAM_DELETE_CRED))){ | |||
default: | |||
case PAM_CRED_ERR: | |||
case PAM_CRED_UNAVAIL: | |||
case PAM_CRED_EXPIRED: | |||
case PAM_USER_UNKNOWN: | |||
_end(); | |||
throw Exception(pam_handle, "pam_setcred()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::setenv(const std::string& key, const std::string& value){ | |||
std::string name_value = key+"="+value; | |||
switch((last_result=pam_putenv(pam_handle, name_value.c_str()))){ | |||
default: | |||
case PAM_PERM_DENIED: | |||
case PAM_ABORT: | |||
case PAM_BUF_ERR: | |||
void Authenticator::authenticate(void){ | |||
switch((last_result=pam_authenticate(pam_handle, 0))){ | |||
default: | |||
case PAM_ABORT: | |||
case PAM_AUTHINFO_UNAVAIL: | |||
_end(); | |||
throw Exception(pam_handle, "pam_authenticate()", last_result); | |||
case PAM_USER_UNKNOWN: | |||
case PAM_MAXTRIES: | |||
case PAM_CRED_INSUFFICIENT: | |||
case PAM_AUTH_ERR: | |||
throw Auth_Exception(pam_handle, "pam_authentication()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
switch((last_result=pam_acct_mgmt(pam_handle, PAM_SILENT))){ | |||
/* The documentation and implementation of Linux PAM differs: | |||
PAM_NEW_AUTHTOKEN_REQD is described in the documentation but | |||
don't exists in the actual implementation. This issue needs | |||
to be fixes at some point. */ | |||
default: | |||
/* case PAM_NEW_AUTHTOKEN_REQD: */ | |||
case PAM_ACCT_EXPIRED: | |||
case PAM_USER_UNKNOWN: | |||
_end(); | |||
throw Exception(pam_handle, "pam_acct_mgmt()", last_result); | |||
case PAM_AUTH_ERR: | |||
case PAM_PERM_DENIED: | |||
throw Auth_Exception(pam_handle, "pam_acct_mgmt()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
void Authenticator::open_session(void){ | |||
switch((last_result=pam_setcred(pam_handle, PAM_ESTABLISH_CRED))){ | |||
default: | |||
case PAM_CRED_ERR: | |||
case PAM_CRED_UNAVAIL: | |||
_end(); | |||
throw Exception(pam_handle, "pam_setcred()", last_result); | |||
case PAM_CRED_EXPIRED: | |||
case PAM_USER_UNKNOWN: | |||
throw Cred_Exception(pam_handle, "pam_setcred()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
switch((last_result=pam_open_session(pam_handle, 0))){ | |||
/* The documentation and implementation of Linux PAM differs: | |||
PAM_SESSION_ERROR is described in the documentation but | |||
don't exists in the actual implementation. This issue needs | |||
to be fixes at some point. */ | |||
default: | |||
/* case PAM_SESSION_ERROR: */ | |||
pam_setcred(pam_handle, PAM_DELETE_CRED); | |||
_end(); | |||
throw Exception(pam_handle, "pam_open_session()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
void Authenticator::close_session(void){ | |||
switch((last_result=pam_close_session(pam_handle, 0))){ | |||
/* The documentation and implementation of Linux PAM differs: | |||
PAM_SESSION_ERROR is described in the documentation but | |||
don't exists in the actual implementation. This issue needs | |||
to be fixes at some point. */ | |||
default: | |||
/* case PAM_SESSION_ERROR: */ | |||
pam_setcred(pam_handle, PAM_DELETE_CRED); | |||
_end(); | |||
throw Exception(pam_handle, "pam_close_session", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
switch((last_result=pam_setcred(pam_handle, PAM_DELETE_CRED))){ | |||
default: | |||
case PAM_CRED_ERR: | |||
case PAM_CRED_UNAVAIL: | |||
case PAM_CRED_EXPIRED: | |||
case PAM_USER_UNKNOWN: | |||
_end(); | |||
throw Exception(pam_handle, "pam_setcred()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
} | |||
return; | |||
} | |||
void Authenticator::setenv(const std::string& key, const std::string& value){ | |||
std::string name_value = key+"="+value; | |||
switch((last_result=pam_putenv(pam_handle, name_value.c_str()))){ | |||
default: | |||
case PAM_PERM_DENIED: | |||
case PAM_ABORT: | |||
case PAM_BUF_ERR: | |||
#ifdef __LIBPAM_VERSION | |||
case PAM_BAD_ITEM: | |||
case PAM_BAD_ITEM: | |||
#endif | |||
_end(); | |||
throw Exception(pam_handle, "pam_putenv()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
void Authenticator::delenv(const std::string& key){ | |||
switch((last_result=pam_putenv(pam_handle, key.c_str()))){ | |||
default: | |||
case PAM_PERM_DENIED: | |||
case PAM_ABORT: | |||
case PAM_BUF_ERR: | |||
_end(); | |||
throw Exception(pam_handle, "pam_putenv()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
void Authenticator::delenv(const std::string& key){ | |||
switch((last_result=pam_putenv(pam_handle, key.c_str()))){ | |||
default: | |||
case PAM_PERM_DENIED: | |||
case PAM_ABORT: | |||
case PAM_BUF_ERR: | |||
#ifdef __LIBPAM_VERSION | |||
case PAM_BAD_ITEM: | |||
case PAM_BAD_ITEM: | |||
#endif | |||
_end(); | |||
throw Exception(pam_handle, "pam_putenv()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
const char* Authenticator::getenv(const std::string& key){ | |||
return pam_getenv(pam_handle, key.c_str()); | |||
} | |||
char** Authenticator::getenvlist(void){ | |||
return pam_getenvlist(pam_handle); | |||
} | |||
}; | |||
_end(); | |||
throw Exception(pam_handle, "pam_putenv()", last_result); | |||
case PAM_SUCCESS: | |||
break; | |||
}; | |||
return; | |||
} | |||
const char* Authenticator::getenv(const std::string& key){ | |||
return pam_getenv(pam_handle, key.c_str()); | |||
} | |||
char** Authenticator::getenvlist(void){ | |||
return pam_getenvlist(pam_handle); | |||
} | |||
} | |||
std::ostream& operator<<( std::ostream& os, const PAM::Exception& e){ | |||
os << e.func_name << ": " << e.errstr; | |||
return os; | |||
os << e.func_name << ": " << e.errstr; | |||
return os; | |||
} |
@@ -17,83 +17,83 @@ | |||
#endif | |||
namespace PAM { | |||
class Exception{ | |||
public: | |||
int errnum; | |||
std::string errstr; | |||
std::string func_name; | |||
Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum); | |||
virtual ~Exception(void); | |||
}; | |||
class Exception{ | |||
public: | |||
int errnum; | |||
std::string errstr; | |||
std::string func_name; | |||
Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum); | |||
virtual ~Exception(void); | |||
}; | |||
class Auth_Exception: public Exception{ | |||
public: | |||
Auth_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum); | |||
}; | |||
class Auth_Exception: public Exception{ | |||
public: | |||
Auth_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum); | |||
}; | |||
class Cred_Exception: public Exception{ | |||
public: | |||
Cred_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum); | |||
}; | |||
class Cred_Exception: public Exception{ | |||
public: | |||
Cred_Exception(pam_handle_t* _pam_handle, | |||
const std::string& _func_name, | |||
int _errnum); | |||
}; | |||
class Authenticator{ | |||
private: | |||
struct pam_conv pam_conversation; | |||
pam_handle_t* pam_handle; | |||
int last_result; | |||
class Authenticator{ | |||
private: | |||
struct pam_conv pam_conversation; | |||
pam_handle_t* pam_handle; | |||
int last_result; | |||
int _end(void); | |||
public: | |||
typedef int (conversation)(int num_msg, | |||
const struct pam_message **msg, | |||
struct pam_response **resp, | |||
void *appdata_ptr); | |||
int _end(void); | |||
public: | |||
typedef int (conversation)(int num_msg, | |||
const struct pam_message **msg, | |||
struct pam_response **resp, | |||
void *appdata_ptr); | |||
enum ItemType { | |||
Service = PAM_SERVICE, | |||
User = PAM_USER, | |||
User_Prompt = PAM_USER_PROMPT, | |||
TTY = PAM_TTY, | |||
Requestor = PAM_RUSER, | |||
Host = PAM_RHOST, | |||
Conv = PAM_CONV, | |||
enum ItemType { | |||
Service = PAM_SERVICE, | |||
User = PAM_USER, | |||
User_Prompt = PAM_USER_PROMPT, | |||
TTY = PAM_TTY, | |||
Requestor = PAM_RUSER, | |||
Host = PAM_RHOST, | |||
Conv = PAM_CONV, | |||
#ifdef __LIBPAM_VERSION | |||
//Fail_Delay = PAM_FAIL_DELAY | |||
/* Fail_Delay = PAM_FAIL_DELAY */ | |||
#endif | |||
}; | |||
}; | |||
public: | |||
Authenticator(conversation* conv, void* data=0); | |||
~Authenticator(void); | |||
void start(const std::string& service); | |||
void end(void); | |||
void set_item(const ItemType item, const void* value); | |||
const void* get_item(const ItemType item); | |||
public: | |||
Authenticator(conversation* conv, void* data=0); | |||
~Authenticator(void); | |||
void start(const std::string& service); | |||
void end(void); | |||
void set_item(const ItemType item, const void* value); | |||
const void* get_item(const ItemType item); | |||
#ifdef __LIBPAM_VERSION | |||
void fail_delay(const unsigned int micro_sec); | |||
void fail_delay(const unsigned int micro_sec); | |||
#endif | |||
void authenticate(void); | |||
void open_session(void); | |||
void close_session(void); | |||
void setenv(const std::string& key, const std::string& value); | |||
void delenv(const std::string& key); | |||
const char* getenv(const std::string& key); | |||
char** getenvlist(void); | |||
void authenticate(void); | |||
void open_session(void); | |||
void close_session(void); | |||
void setenv(const std::string& key, const std::string& value); | |||
void delenv(const std::string& key); | |||
const char* getenv(const std::string& key); | |||
char** getenvlist(void); | |||
private: | |||
// Explicitly disable copy constructor and copy assignment | |||
Authenticator(const PAM::Authenticator&); | |||
Authenticator& operator=(const PAM::Authenticator&); | |||
}; | |||
}; | |||
private: | |||
/* Explicitly disable copy constructor and copy assignment */ | |||
Authenticator(const PAM::Authenticator&); | |||
Authenticator& operator=(const PAM::Authenticator&); | |||
}; | |||
} | |||
std::ostream& operator<<( std::ostream& os, const PAM::Exception& e); | |||
#endif | |||
#endif /* _PAM_H_ */ |
@@ -13,6 +13,7 @@ | |||
#define _APP_H_ | |||
#include <X11/Xlib.h> | |||
#include <X11/Xatom.h> | |||
#include <signal.h> | |||
#include <unistd.h> | |||
#include <sys/wait.h> | |||
@@ -33,87 +34,86 @@ | |||
class App { | |||
public: | |||
App(int argc, char** argv); | |||
~App(); | |||
void Run(); | |||
int GetServerPID(); | |||
void RestartServer(); | |||
void StopServer(); | |||
App(int argc, char **argv); | |||
~App(); | |||
void Run(); | |||
int GetServerPID(); | |||
void RestartServer(); | |||
void StopServer(); | |||
// Lock functions | |||
void GetLock(); | |||
void RemoveLock(); | |||
/* Lock functions */ | |||
void GetLock(); | |||
void RemoveLock(); | |||
bool isServerStarted(); | |||
bool isServerStarted(); | |||
private: | |||
void Login(); | |||
void Reboot(); | |||
void Halt(); | |||
void Suspend(); | |||
void Console(); | |||
void Exit(); | |||
void KillAllClients(Bool top); | |||
void ReadConfig(); | |||
void OpenLog(); | |||
void CloseLog(); | |||
void HideCursor(); | |||
void CreateServerAuth(); | |||
char* StrConcat(const char* str1, const char* str2); | |||
void UpdatePid(); | |||
bool AuthenticateUser(bool focuspass); | |||
static std::string findValidRandomTheme(const std::string& set); | |||
static void replaceVariables(std::string& input, | |||
const std::string& var, | |||
const std::string& value); | |||
// Server functions | |||
int StartServer(); | |||
int ServerTimeout(int timeout, char *string); | |||
int WaitForServer(); | |||
// Private data | |||
Window Root; | |||
Display* Dpy; | |||
int Scr; | |||
Panel* LoginPanel; | |||
int ServerPID; | |||
const char* DisplayName; | |||
bool serverStarted; | |||
void Login(); | |||
void Reboot(); | |||
void Halt(); | |||
void Suspend(); | |||
void Console(); | |||
void Exit(); | |||
void KillAllClients(Bool top); | |||
void ReadConfig(); | |||
void OpenLog(); | |||
void CloseLog(); | |||
void HideCursor(); | |||
void CreateServerAuth(); | |||
char *StrConcat(const char *str1, const char *str2); | |||
void UpdatePid(); | |||
bool AuthenticateUser(bool focuspass); | |||
static std::string findValidRandomTheme(const std::string &set); | |||
static void replaceVariables(std::string &input, | |||
const std::string &var, | |||
const std::string &value); | |||
/* Server functions */ | |||
int StartServer(); | |||
int ServerTimeout(int timeout, char *string); | |||
int WaitForServer(); | |||
/* Private data */ | |||
Window Root; | |||
Display *Dpy; | |||
int Scr; | |||
Panel *LoginPanel; | |||
int ServerPID; | |||
const char *DisplayName; | |||
bool serverStarted; | |||
#ifdef USE_PAM | |||
PAM::Authenticator pam; | |||
#endif | |||
#ifdef USE_CONSOLEKIT | |||
Ck::Session ck; | |||
Ck::Session ck; | |||
#endif | |||
// Options | |||
char* DispName; | |||
/* Options */ | |||
char *DispName; | |||
Cfg *cfg; | |||
Cfg *cfg; | |||
Pixmap BackgroundPixmap; | |||
Pixmap BackgroundPixmap; | |||
void blankScreen(); | |||
Image* image; | |||
void setBackground(const std::string& themedir); | |||
void blankScreen(); | |||
Image *image; | |||
Atom BackgroundPixmapId; | |||
void setBackground(const std::string &themedir); | |||
bool firstlogin; | |||
bool daemonmode; | |||
bool force_nodaemon; | |||
// For testing themes | |||
char* testtheme; | |||
bool testing; | |||
std::string themeName; | |||
std::string mcookie; | |||
const int mcookiesize; | |||
}; | |||
bool firstlogin; | |||
bool daemonmode; | |||
bool force_nodaemon; | |||
/* For testing themes */ | |||
char *testtheme; | |||
bool testing; | |||
std::string themeName; | |||
std::string mcookie; | |||
#endif | |||
const int mcookiesize; | |||
}; | |||
#endif /* _APP_H_ */ |
@@ -1,6 +1,7 @@ | |||
/* SLiM - Simple Login Manager | |||
Copyright (C) 2004-06 Simone Rota <sip@varlock.com> | |||
Copyright (C) 2004-06 Johannes Winkelmann <jw@tks6.net> | |||
Copyright (C) 2012-13 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> | |||
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 | |||
@@ -24,288 +25,325 @@ using namespace std; | |||
typedef pair<string,string> option; | |||
Cfg::Cfg() | |||
: currentSession(-1) | |||
Cfg::Cfg() | |||
: currentSession(-1) | |||
{ | |||
// Configuration options | |||
options.insert(option("default_path","/bin:/usr/bin:/usr/local/bin")); | |||
options.insert(option("default_xserver","/usr/bin/X")); | |||
options.insert(option("xserver_arguments","")); | |||
options.insert(option("numlock","")); | |||
options.insert(option("daemon","")); | |||
options.insert(option("xauth_path","/usr/bin/xauth")); | |||
options.insert(option("login_cmd","exec /bin/bash -login ~/.xinitrc %session")); | |||
options.insert(option("halt_cmd","/sbin/shutdown -h now")); | |||
options.insert(option("reboot_cmd","/sbin/shutdown -r now")); | |||
options.insert(option("suspend_cmd","")); | |||
options.insert(option("sessionstart_cmd","")); | |||
options.insert(option("sessionstop_cmd","")); | |||
options.insert(option("console_cmd","/usr/bin/xterm -C -fg white -bg black +sb -g %dx%d+%d+%d -fn %dx%d -T ""Console login"" -e /bin/sh -c ""/bin/cat /etc/issue; exec /bin/login""")); | |||
options.insert(option("screenshot_cmd","import -window root /slim.png")); | |||
options.insert(option("welcome_msg","Welcome to %host")); | |||
options.insert(option("session_msg","Session:")); | |||
options.insert(option("default_user","")); | |||
options.insert(option("focus_password","no")); | |||
options.insert(option("auto_login","no")); | |||
options.insert(option("current_theme","default")); | |||
options.insert(option("lockfile","/var/run/slim.lock")); | |||
options.insert(option("logfile","/var/log/slim.log")); | |||
options.insert(option("authfile","/var/run/slim.auth")); | |||
options.insert(option("shutdown_msg","The system is halting...")); | |||
options.insert(option("reboot_msg","The system is rebooting...")); | |||
options.insert(option("sessions","wmaker,blackbox,icewm")); | |||
options.insert(option("sessiondir","")); | |||
options.insert(option("hidecursor","false")); | |||
// Theme stuff | |||
options.insert(option("input_panel_x","50%")); | |||
options.insert(option("input_panel_y","40%")); | |||
options.insert(option("input_name_x","200")); | |||
options.insert(option("input_name_y","154")); | |||
options.insert(option("input_pass_x","-1")); // default is single inputbox | |||
options.insert(option("input_pass_y","-1")); | |||
options.insert(option("input_font","Verdana:size=11")); | |||
options.insert(option("input_color", "#000000")); | |||
options.insert(option("input_cursor_height","20")); | |||
options.insert(option("input_maxlength_name","20")); | |||
options.insert(option("input_maxlength_passwd","20")); | |||
options.insert(option("input_shadow_xoffset", "0")); | |||
options.insert(option("input_shadow_yoffset", "0")); | |||
options.insert(option("input_shadow_color","#FFFFFF")); | |||
options.insert(option("welcome_font","Verdana:size=14")); | |||
options.insert(option("welcome_color","#FFFFFF")); | |||
options.insert(option("welcome_x","-1")); | |||
options.insert(option("welcome_y","-1")); | |||
options.insert(option("welcome_shadow_xoffset", "0")); | |||
options.insert(option("welcome_shadow_yoffset", "0")); | |||
options.insert(option("welcome_shadow_color","#FFFFFF")); | |||
options.insert(option("intro_msg","")); | |||
options.insert(option("intro_font","Verdana:size=14")); | |||
options.insert(option("intro_color","#FFFFFF")); | |||
options.insert(option("intro_x","-1")); | |||
options.insert(option("intro_y","-1")); | |||
options.insert(option("background_style","stretch")); | |||
options.insert(option("background_color","#CCCCCC")); | |||
options.insert(option("username_font","Verdana:size=12")); | |||
options.insert(option("username_color","#FFFFFF")); | |||
options.insert(option("username_x","-1")); | |||
options.insert(option("username_y","-1")); | |||
options.insert(option("username_msg","Please enter your username")); | |||
options.insert(option("username_shadow_xoffset", "0")); | |||
options.insert(option("username_shadow_yoffset", "0")); | |||
options.insert(option("username_shadow_color","#FFFFFF")); | |||
options.insert(option("password_x","-1")); | |||
options.insert(option("password_y","-1")); | |||
options.insert(option("password_msg","Please enter your password")); | |||
options.insert(option("msg_color","#FFFFFF")); | |||
options.insert(option("msg_font","Verdana:size=16:bold")); | |||
options.insert(option("msg_x","40")); | |||
options.insert(option("msg_y","40")); | |||
options.insert(option("msg_shadow_xoffset", "0")); | |||
options.insert(option("msg_shadow_yoffset", "0")); | |||
options.insert(option("msg_shadow_color","#FFFFFF")); | |||
options.insert(option("session_color","#FFFFFF")); | |||
options.insert(option("session_font","Verdana:size=16:bold")); | |||
options.insert(option("session_x","50%")); | |||
options.insert(option("session_y","90%")); | |||
options.insert(option("session_shadow_xoffset", "0")); | |||
options.insert(option("session_shadow_yoffset", "0")); | |||
options.insert(option("session_shadow_color","#FFFFFF")); | |||
error = ""; | |||
/* Configuration options */ | |||
options.insert(option("default_path","/bin:/usr/bin:/usr/local/bin")); | |||
options.insert(option("default_xserver","/usr/bin/X")); | |||
options.insert(option("xserver_arguments","")); | |||
options.insert(option("numlock","")); | |||
options.insert(option("daemon","")); | |||
options.insert(option("xauth_path","/usr/bin/xauth")); | |||
options.insert(option("login_cmd","exec /bin/bash -login ~/.xinitrc %session")); | |||
options.insert(option("halt_cmd","/sbin/shutdown -h now")); | |||
options.insert(option("reboot_cmd","/sbin/shutdown -r now")); | |||
options.insert(option("suspend_cmd","")); | |||
options.insert(option("sessionstart_cmd","")); | |||
options.insert(option("sessionstop_cmd","")); | |||
options.insert(option("console_cmd","/usr/bin/xterm -C -fg white -bg black +sb -g %dx%d+%d+%d -fn %dx%d -T ""Console login"" -e /bin/sh -c ""/bin/cat /etc/issue; exec /bin/login""")); | |||
options.insert(option("screenshot_cmd","import -window root /slim.png")); | |||
options.insert(option("welcome_msg","Welcome to %host")); | |||
options.insert(option("session_msg","Session:")); | |||
options.insert(option("default_user","")); | |||
options.insert(option("focus_password","no")); | |||
options.insert(option("auto_login","no")); | |||
options.insert(option("current_theme","default")); | |||
options.insert(option("lockfile","/var/run/slim.lock")); | |||
options.insert(option("logfile","/var/log/slim.log")); | |||
options.insert(option("authfile","/var/run/slim.auth")); | |||
options.insert(option("shutdown_msg","The system is halting...")); | |||
options.insert(option("reboot_msg","The system is rebooting...")); | |||
options.insert(option("sessiondir","")); | |||
options.insert(option("hidecursor","false")); | |||
/* Theme stuff */ | |||
options.insert(option("input_panel_x","50%")); | |||
options.insert(option("input_panel_y","40%")); | |||
options.insert(option("input_name_x","200")); | |||
options.insert(option("input_name_y","154")); | |||
options.insert(option("input_pass_x","-1")); /* default is single inputbox */ | |||
options.insert(option("input_pass_y","-1")); | |||
options.insert(option("input_font","Verdana:size=11")); | |||
options.insert(option("input_color", "#000000")); | |||
options.insert(option("input_cursor_height","20")); | |||
options.insert(option("input_maxlength_name","20")); | |||
options.insert(option("input_maxlength_passwd","20")); | |||
options.insert(option("input_shadow_xoffset", "0")); | |||
options.insert(option("input_shadow_yoffset", "0")); | |||
options.insert(option("input_shadow_color","#FFFFFF")); | |||
options.insert(option("welcome_font","Verdana:size=14")); | |||
options.insert(option("welcome_color","#FFFFFF")); | |||
options.insert(option("welcome_x","-1")); | |||
options.insert(option("welcome_y","-1")); | |||
options.insert(option("welcome_shadow_xoffset", "0")); | |||
options.insert(option("welcome_shadow_yoffset", "0")); | |||
options.insert(option("welcome_shadow_color","#FFFFFF")); | |||
options.insert(option("intro_msg","")); | |||
options.insert(option("intro_font","Verdana:size=14")); | |||
options.insert(option("intro_color","#FFFFFF")); | |||
options.insert(option("intro_x","-1")); | |||
options.insert(option("intro_y","-1")); | |||
options.insert(option("background_style","stretch")); | |||
options.insert(option("background_color","#CCCCCC")); | |||
options.insert(option("username_font","Verdana:size=12")); | |||
options.insert(option("username_color","#FFFFFF")); | |||
options.insert(option("username_x","-1")); | |||
options.insert(option("username_y","-1")); | |||
options.insert(option("username_msg","Please enter your username")); | |||
options.insert(option("username_shadow_xoffset", "0")); | |||
options.insert(option("username_shadow_yoffset", "0")); | |||
options.insert(option("username_shadow_color","#FFFFFF")); | |||
options.insert(option("password_x","-1")); | |||
options.insert(option("password_y","-1")); | |||
options.insert(option("password_msg","Please enter your password")); | |||
options.insert(option("msg_color","#FFFFFF")); | |||
options.insert(option("msg_font","Verdana:size=16:bold")); | |||
options.insert(option("msg_x","40")); | |||
options.insert(option("msg_y","40")); | |||
options.insert(option("msg_shadow_xoffset", "0")); | |||
options.insert(option("msg_shadow_yoffset", "0")); | |||
options.insert(option("msg_shadow_color","#FFFFFF")); | |||
options.insert(option("session_color","#FFFFFF")); | |||
options.insert(option("session_font","Verdana:size=16:bold")); | |||
options.insert(option("session_x","50%")); | |||
options.insert(option("session_y","90%")); | |||
options.insert(option("session_shadow_xoffset", "0")); | |||
options.insert(option("session_shadow_yoffset", "0")); | |||
options.insert(option("session_shadow_color","#FFFFFF")); | |||
// slimlock-specific options | |||
options.insert(option("dpms_standby_timeout", "60")); | |||
options.insert(option("dpms_off_timeout", "600")); | |||
options.insert(option("wrong_passwd_timeout", "2")); | |||
options.insert(option("passwd_feedback_x", "50%")); | |||
options.insert(option("passwd_feedback_y", "10%")); | |||
options.insert(option("passwd_feedback_msg", "Authentication failed")); | |||
options.insert(option("passwd_feedback_capslock", "Authentication failed (CapsLock is on)")); | |||
options.insert(option("show_username", "1")); | |||
options.insert(option("show_welcome_msg", "0")); | |||
options.insert(option("tty_lock", "1")); | |||
options.insert(option("bell", "1")); | |||
error = ""; | |||
} | |||
Cfg::~Cfg() { | |||
options.clear(); | |||
options.clear(); | |||
} | |||
/* | |||
* Creates the Cfg object and parses | |||
* known options from the given configfile / themefile | |||
*/ | |||
bool Cfg::readConf(string configfile) { | |||
int n = -1; | |||
string line, fn(configfile); | |||
map<string,string>::iterator it; | |||
string op; | |||
ifstream cfgfile( fn.c_str() ); | |||
if (cfgfile) { | |||
while (getline( cfgfile, line )) { | |||
it = options.begin(); | |||
while (it != options.end()) { | |||
op = it->first; | |||
n = line.find(op); | |||
if (n == 0) | |||
options[op] = parseOption(line, op); | |||
it++; | |||
} | |||
} | |||
cfgfile.close(); | |||
fillSessionList(); | |||
return true; | |||
} else { | |||
error = "Cannot read configuration file: " + configfile; | |||
return false; | |||
} | |||
int n = -1; | |||
size_t pos = 0; | |||
string line, next, op, fn(configfile); | |||
map<string,string>::iterator it; | |||
ifstream cfgfile(fn.c_str()); | |||
if (!cfgfile) { | |||
error = "Cannot read configuration file: " + configfile; | |||
return false; | |||
} | |||
while (getline(cfgfile, line)) { | |||
if ((pos = line.find('\\')) != string::npos) { | |||
if (line.length() == pos + 1) { | |||
line.replace(pos, 1, " "); | |||
next = next + line; | |||
continue; | |||
} else | |||
line.replace(pos, line.length() - pos, " "); | |||
} | |||
if (!next.empty()) { | |||
line = next + line; | |||
next = ""; | |||
} | |||
it = options.begin(); | |||
while (it != options.end()) { | |||
op = it->first; | |||
n = line.find(op); | |||
if (n == 0) | |||
options[op] = parseOption(line, op); | |||
++it; | |||
} | |||
} | |||
cfgfile.close(); | |||
fillSessionList(); | |||
return true; | |||
} | |||
/* Returns the option value, trimmed */ | |||
string Cfg::parseOption(string line, string option ) { | |||
return Trim( line.substr(option.size(), line.size() - option.size())); | |||
return Trim( line.substr(option.size(), line.size() - option.size())); | |||
} | |||
const string& Cfg::getError() const { | |||
return error; | |||
return error; | |||
} | |||
string& Cfg::getOption(string option) { | |||
return options[option]; | |||
return options[option]; | |||
} | |||
/* return a trimmed string */ | |||
string Cfg::Trim( const string& s ) { | |||
if ( s.empty() ) { | |||
return s; | |||
} | |||
int pos = 0; | |||
string line = s; | |||
int len = line.length(); | |||
while ( pos < len && isspace( line[pos] ) ) { | |||
++pos; | |||
} | |||
line.erase( 0, pos ); | |||
pos = line.length()-1; | |||
while ( pos > -1 && isspace( line[pos] ) ) { | |||
--pos; | |||
} | |||
if ( pos != -1 ) { | |||
line.erase( pos+1 ); | |||
} | |||
return line; | |||
if ( s.empty() ) { | |||
return s; | |||
} | |||
int pos = 0; | |||
string line = s; | |||
int len = line.length(); | |||
while ( pos < len && isspace( line[pos] ) ) { | |||
++pos; | |||
} | |||
line.erase( 0, pos ); | |||
pos = line.length()-1; | |||
while ( pos > -1 && isspace( line[pos] ) ) { | |||
--pos; | |||
} | |||
if ( pos != -1 ) { | |||
line.erase( pos+1 ); | |||
} | |||
return line; | |||
} | |||
/* Return the welcome message with replaced vars */ | |||
string Cfg::getWelcomeMessage(){ | |||
string s = getOption("welcome_msg"); | |||
int n = -1; | |||
n = s.find("%host"); | |||
if (n >= 0) { | |||
string tmp = s.substr(0, n); | |||
char host[40]; | |||
gethostname(host,40); | |||
tmp = tmp + host; | |||
tmp = tmp + s.substr(n+5, s.size() - n); | |||
s = tmp; | |||
} | |||
n = s.find("%domain"); | |||
if (n >= 0) { | |||
string tmp = s.substr(0, n);; | |||
char domain[40]; | |||
getdomainname(domain,40); | |||
tmp = tmp + domain; | |||
tmp = tmp + s.substr(n+7, s.size() - n); | |||
s = tmp; | |||
} | |||
return s; | |||
string s = getOption("welcome_msg"); | |||
int n = s.find("%host"); | |||
if (n >= 0) { | |||
string tmp = s.substr(0, n); | |||
char host[40]; | |||
gethostname(host,40); | |||
tmp = tmp + host; | |||
tmp = tmp + s.substr(n+5, s.size() - n); | |||
s = tmp; | |||
} | |||
n = s.find("%domain"); | |||
if (n >= 0) { | |||
string tmp = s.substr(0, n);; | |||
char domain[40]; | |||
getdomainname(domain,40); | |||
tmp = tmp + domain; | |||
tmp = tmp + s.substr(n+7, s.size() - n); | |||
s = tmp; | |||
} | |||
return s; | |||
} | |||
int Cfg::string2int(const char* string, bool* ok) { | |||
char* err = 0; | |||
int l = (int)strtol(string, &err, 10); | |||
if (ok) { | |||
*ok = (*err == 0); | |||
} | |||
return (*err == 0) ? l : 0; | |||
char* err = 0; | |||
int l = (int)strtol(string, &err, 10); | |||
if (ok) { | |||
*ok = (*err == 0); | |||
} | |||
return (*err == 0) ? l : 0; | |||
} | |||
int Cfg::getIntOption(std::string option) { | |||
return string2int(options[option].c_str()); | |||
return string2int(options[option].c_str()); | |||
} | |||
// Get absolute position | |||
/* Get absolute position */ | |||
int Cfg::absolutepos(const string& position, int max, int width) { | |||
int n = -1; | |||
n = position.find("%"); | |||
if (n>0) { // X Position expressed in percentage | |||
int result = (max*string2int(position.substr(0, n).c_str())/100) - (width / 2); | |||
return result < 0 ? 0 : result ; | |||
} else { // Absolute X position | |||
return string2int(position.c_str()); | |||
} | |||
int n = position.find("%"); | |||
if (n>0) { /* X Position expressed in percentage */ | |||
int result = (max*string2int(position.substr(0, n).c_str())/100) - (width / 2); | |||
return result < 0 ? 0 : result ; | |||
} else { /* Absolute X position */ | |||
return string2int(position.c_str()); | |||
} | |||
} | |||
// split a comma separated string into a vector of strings | |||
/* split a comma separated string into a vector of strings */ | |||
void Cfg::split(vector<string>& v, const string& str, char c, bool useEmpty) { | |||
v.clear(); | |||
string::const_iterator s = str.begin(); | |||
string tmp; | |||
while (true) { | |||
string::const_iterator begin = s; | |||
while (*s != c && s != str.end()) { ++s; } | |||
tmp = string(begin, s); | |||
if (useEmpty || tmp.size() > 0) | |||
v.push_back(tmp); | |||
if (s == str.end()) { | |||
break; | |||
} | |||
if (++s == str.end()) { | |||
if (useEmpty) | |||
v.push_back(""); | |||
break; | |||
} | |||
} | |||
v.clear(); | |||
string::const_iterator s = str.begin(); | |||
string tmp; | |||
while (true) { | |||
string::const_iterator begin = s; | |||
while (*s != c && s != str.end()) { ++s; } | |||
tmp = string(begin, s); | |||
if (useEmpty || tmp.size() > 0) | |||
v.push_back(tmp); | |||
if (s == str.end()) { | |||
break; | |||
} | |||
if (++s == str.end()) { | |||
if (useEmpty) | |||
v.push_back(""); | |||
break; | |||
} | |||
} | |||
} | |||
void Cfg::fillSessionList(){ | |||
string strSessionList = getOption("sessions"); | |||
string strSessionDir = getOption("sessiondir"); | |||
sessions.clear(); | |||
if( !strSessionDir.empty() ) { | |||
DIR *pDir = opendir(strSessionDir.c_str()); | |||
if (pDir != NULL) { | |||
struct dirent *pDirent = NULL; | |||
while ((pDirent = readdir(pDir)) != NULL) { | |||
string strFile(strSessionDir); | |||
strFile += "/"; | |||
strFile += pDirent->d_name; | |||
struct stat oFileStat; | |||
if (stat(strFile.c_str( ), &oFileStat) == 0){ | |||
if (S_ISREG(oFileStat.st_mode) && | |||
access(strFile.c_str(), R_OK | X_OK) == 0){ | |||
sessions.push_back(string(pDirent->d_name)); | |||
} | |||
} | |||
} | |||
closedir(pDir); | |||
} | |||
} | |||
if (sessions.empty()){ | |||
split(sessions, strSessionList, ',', false); | |||
} | |||
string strSessionDir = getOption("sessiondir"); | |||
sessions.clear(); | |||
if( !strSessionDir.empty() ) { | |||
DIR *pDir = opendir(strSessionDir.c_str()); | |||
if (pDir != NULL) { | |||
struct dirent *pDirent = NULL; | |||
while ((pDirent = readdir(pDir)) != NULL) { | |||
string strFile(strSessionDir); | |||
strFile += "/"; | |||
strFile += pDirent->d_name; | |||
struct stat oFileStat; | |||
if (stat(strFile.c_str(), &oFileStat) == 0) { | |||
if (S_ISREG(oFileStat.st_mode) && | |||
access(strFile.c_str(), R_OK) == 0){ | |||
ifstream desktop_file( strFile.c_str() ); | |||
if (desktop_file){ | |||
string line, session_name = "", session_exec = ""; | |||
while (getline( desktop_file, line )) { | |||
if (line.substr(0, 5) == "Name=") { | |||
session_name = line.substr(5); | |||
if (!session_exec.empty()) | |||
break; | |||
} else | |||
if (line.substr(0, 5) == "Exec=") { | |||
session_exec = line.substr(5); | |||
if (!session_name.empty()) | |||
break; | |||
} | |||
} | |||
desktop_file.close(); | |||
pair<string,string> session(session_name,session_exec); | |||
sessions.push_back(session); | |||
cout << session_exec << " - " << session_name << endl; | |||
} | |||
} | |||
} | |||
} | |||
closedir(pDir); | |||
} | |||
} | |||
if (sessions.empty()){ | |||
pair<string,string> session("",""); | |||
sessions.push_back(session); | |||
} | |||
} | |||
string Cfg::nextSession(string current) { | |||
if (sessions.size() < 1) | |||
return current; | |||
currentSession = (currentSession + 1) % sessions.size(); | |||
return sessions[currentSession]; | |||
pair<string,string> Cfg::nextSession() { | |||
currentSession = (currentSession + 1) % sessions.size(); | |||
return sessions[currentSession]; | |||
} |
@@ -15,7 +15,7 @@ | |||
#include <map> | |||
#include <vector> | |||
#define INPUT_MAXLENGTH_NAME 30 | |||
#define INPUT_MAXLENGTH_NAME 30 | |||
#define INPUT_MAXLENGTH_PASSWD 50 | |||
#define CFGFILE SYSCONFDIR"/slim.conf" | |||
@@ -25,32 +25,32 @@ | |||
class Cfg { | |||
public: | |||
Cfg(); | |||
~Cfg(); | |||
bool readConf(std::string configfile); | |||
std::string parseOption(std::string line, std::string option); | |||
const std::string& getError() const; | |||
std::string& getOption(std::string option); | |||
int getIntOption(std::string option); | |||
std::string getWelcomeMessage(); | |||
static int absolutepos(const std::string& position, int max, int width); | |||
static int string2int(const char* string, bool* ok = 0); | |||
static void split(std::vector<std::string>& v, const std::string& str, | |||
char c, bool useEmpty=true); | |||
static std::string Trim(const std::string& s); | |||
std::string nextSession(std::string current); | |||
Cfg(); | |||
~Cfg(); | |||
private: | |||
void fillSessionList(); | |||
bool readConf(std::string configfile); | |||
std::string parseOption(std::string line, std::string option); | |||
const std::string& getError() const; | |||
std::string& getOption(std::string option); | |||
int getIntOption(std::string option); | |||
std::string getWelcomeMessage(); | |||
static int absolutepos(const std::string &position, int max, int width); | |||
static int string2int(const char *string, bool *ok = 0); | |||
static void split(std::vector<std::string> &v, const std::string &str, | |||
char c, bool useEmpty=true); | |||
static std::string Trim(const std::string &s); | |||
std::pair<std::string,std::string> nextSession(); | |||
private: | |||
std::map<std::string,std::string> options; | |||
std::vector<std::string> sessions; | |||
int currentSession; | |||
std::string error; | |||
void fillSessionList(); | |||
private: | |||
std::map<std::string,std::string> options; | |||
std::vector<std::pair<std::string,std::string> > sessions; | |||
int currentSession; | |||
std::string error; | |||
}; | |||
#endif | |||
#endif /* _CFG_H_ */ |
@@ -12,39 +12,37 @@ | |||
#ifndef _CONST_H_ | |||
#define _CONST_H_ | |||
#define APPNAME "slim" | |||
#define DISPLAY ":0.0" | |||
#define APPNAME "slim" | |||
#define CONSOLE_STR "console" | |||
#define HALT_STR "halt" | |||
#define REBOOT_STR "reboot" | |||
#define EXIT_STR "exit" | |||
#define SUSPEND_STR "suspend" | |||
#define DISPLAY ":0.0" | |||
#define HIDE 0 | |||
#define SHOW 1 | |||
#define CONSOLE_STR "console" | |||
#define HALT_STR "halt" | |||
#define REBOOT_STR "reboot" | |||
#define EXIT_STR "exit" | |||
#define SUSPEND_STR "suspend" | |||
#define HIDE 0 | |||
#define SHOW 1 | |||
#define GET_NAME 0 | |||
#define GET_NAME 0 | |||
#define GET_PASSWD 1 | |||
#define OK_EXIT 0 | |||
#define ERR_EXIT 1 | |||
#define OK_EXIT 0 | |||
#define ERR_EXIT 1 | |||
/* duration for showing error messages, | |||
* as "login command failed", in seconds | |||
*/ | |||
#define ERROR_DURATION 5 | |||
// variables replaced in login_cmd | |||
#define SESSION_VAR "%session" | |||
#define THEME_VAR "%theme" | |||
/* variables replaced in login_cmd */ | |||
#define SESSION_VAR "%session" | |||
#define THEME_VAR "%theme" | |||
/* variables replaced in pre-session_cmd and post-session_cmd */ | |||
#define USER_VAR "%user" | |||
#define USER_VAR "%user" | |||
/* max height/width for images */ | |||
#define MAX_DIMENSION 10000 | |||
#endif | |||
#endif /* _CONST_H_ */ |
@@ -1,15 +1,15 @@ | |||
/* SLiM - Simple Login Manager | |||
Copyright (C) 2004-06 Simone Rota <sip@varlock.com> | |||
Copyright (C) 2004-06 Johannes Winkelmann <jw@tks6.net> | |||
Copyright (C) 2012 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> | |||
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. | |||
The following code has been adapted and extended from | |||
xplanet 1.0.1, Copyright (C) 2002-04 Hari Nair <hari@alumni.caltech.edu> | |||
Copyright (C) 2004-06 Simone Rota <sip@varlock.com> | |||
Copyright (C) 2004-06 Johannes Winkelmann <jw@tks6.net> | |||
Copyright (C) 2012 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> | |||
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. | |||
The following code has been adapted and extended from | |||
xplanet 1.0.1, Copyright (C) 2002-04 Hari Nair <hari@alumni.caltech.edu> | |||
*/ | |||
#ifndef _IMAGE_H_ | |||
@@ -21,59 +21,60 @@ | |||
class Image { | |||
public: | |||
Image(); | |||
Image(const int w, const int h, const unsigned char *rgb, | |||
const unsigned char *alpha); | |||
~Image(); | |||
const unsigned char * getPNGAlpha() const { | |||
return(png_alpha); | |||
}; | |||
const unsigned char * getRGBData() const { | |||
return(rgb_data); | |||
}; | |||
void getPixel(double px, double py, unsigned char *pixel); | |||
void getPixel(double px, double py, unsigned char *pixel, | |||
unsigned char *alpha); | |||