|
@@ -42,7 +42,7 @@ void setBackground(const string& themedir);
|
|
|
void HideCursor();
|
|
|
bool AuthenticateUser();
|
|
|
static int ConvCallback(int num_msgs, const struct pam_message **msg,
|
|
|
- struct pam_response **resp, void *appdata_ptr);
|
|
|
+ struct pam_response **resp, void *appdata_ptr);
|
|
|
string findValidRandomTheme(const string& set);
|
|
|
void HandleSignal(int sig);
|
|
|
void *RaiseWindow(void *data);
|
|
@@ -64,246 +64,244 @@ int term;
|
|
|
|
|
|
static void
|
|
|
die(const char *errstr, ...) {
|
|
|
- va_list ap;
|
|
|
+ va_list ap;
|
|
|
|
|
|
- va_start(ap, errstr);
|
|
|
- vfprintf(stderr, errstr, ap);
|
|
|
- va_end(ap);
|
|
|
- exit(EXIT_FAILURE);
|
|
|
+ va_start(ap, errstr);
|
|
|
+ vfprintf(stderr, errstr, ap);
|
|
|
+ va_end(ap);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
- if((argc == 2) && !strcmp("-v", argv[1]))
|
|
|
- die(APPNAME"-"VERSION", © 2010-2012 Joel Burget\n");
|
|
|
- else if(argc != 1)
|
|
|
- die("usage: "APPNAME" [-v]\n");
|
|
|
-
|
|
|
- void (*prev_fn)(int);
|
|
|
-
|
|
|
- // restore DPMS settings should slimlock be killed in the line of duty
|
|
|
- prev_fn = signal(SIGTERM, HandleSignal);
|
|
|
- if (prev_fn == SIG_IGN) signal(SIGTERM, SIG_IGN);
|
|
|
-
|
|
|
- // create a lock file to solve mutliple instances problem
|
|
|
- // /var/lock used to be the place to put this, now it's /run/lock
|
|
|
- // ...i think
|
|
|
- struct stat statbuf;
|
|
|
- int lock_file;
|
|
|
-
|
|
|
- // try /run/lock first, since i believe it's preferred
|
|
|
- if (!stat("/run/lock", &statbuf))
|
|
|
- lock_file = open("/run/lock/"APPNAME".lock", O_CREAT | O_RDWR, 0666);
|
|
|
- else
|
|
|
- lock_file = open("/var/lock/"APPNAME".lock", O_CREAT | O_RDWR, 0666);
|
|
|
-
|
|
|
- int rc = flock(lock_file, LOCK_EX | LOCK_NB);
|
|
|
-
|
|
|
- if(rc) {
|
|
|
- if(EWOULDBLOCK == errno)
|
|
|
- die(APPNAME" already running\n");
|
|
|
- }
|
|
|
-
|
|
|
- unsigned int cfg_passwd_timeout;
|
|
|
- // Read user's current theme
|
|
|
- cfg = new Cfg;
|
|
|
- cfg->readConf(CFGFILE);
|
|
|
- cfg->readConf(SLIMLOCKCFG);
|
|
|
- string themebase = "";
|
|
|
- string themefile = "";
|
|
|
- string themedir = "";
|
|
|
- themeName = "";
|
|
|
- themebase = string(THEMESDIR) + "/";
|
|
|
- themeName = cfg->getOption("current_theme");
|
|
|
- string::size_type pos;
|
|
|
- if ((pos = themeName.find(",")) != string::npos) {
|
|
|
- themeName = findValidRandomTheme(themeName);
|
|
|
- }
|
|
|
-
|
|
|
- bool loaded = false;
|
|
|
- while (!loaded) {
|
|
|
- themedir = themebase + themeName;
|
|
|
- themefile = themedir + THEMESFILE;
|
|
|
- if (!cfg->readConf(themefile)) {
|
|
|
- if (themeName == "default") {
|
|
|
- cerr << APPNAME << ": Failed to open default theme file "
|
|
|
- << themefile << endl;
|
|
|
- exit(ERR_EXIT);
|
|
|
- } else {
|
|
|
- cerr << APPNAME << ": Invalid theme in config: "
|
|
|
- << themeName << endl;
|
|
|
- themeName = "default";
|
|
|
- }
|
|
|
- } else {
|
|
|
- loaded = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const char *display = getenv("DISPLAY");
|
|
|
- if (!display)
|
|
|
- display = DISPLAY;
|
|
|
-
|
|
|
- if(!(dpy = XOpenDisplay(display)))
|
|
|
- die(APPNAME": cannot open display\n");
|
|
|
- scr = DefaultScreen(dpy);
|
|
|
-
|
|
|
- XSetWindowAttributes wa;
|
|
|
- wa.override_redirect = 1;
|
|
|
- wa.background_pixel = BlackPixel(dpy, scr);
|
|
|
-
|
|
|
- // Create a full screen window
|
|
|
- Window root = RootWindow(dpy, scr);
|
|
|
- win = XCreateWindow(dpy,
|
|
|
- root,
|
|
|
- 0,
|
|
|
- 0,
|
|
|
- DisplayWidth(dpy, scr),
|
|
|
- DisplayHeight(dpy, scr),
|
|
|
- 0,
|
|
|
- DefaultDepth(dpy, scr),
|
|
|
- CopyFromParent,
|
|
|
- DefaultVisual(dpy, scr),
|
|
|
- CWOverrideRedirect | CWBackPixel,
|
|
|
- &wa);
|
|
|
- XMapWindow(dpy, win);
|
|
|
-
|
|
|
- XFlush(dpy);
|
|
|
- for (int len = 1000; len; len--) {
|
|
|
- if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
|
|
|
- == GrabSuccess)
|
|
|
- break;
|
|
|
- usleep(1000);
|
|
|
- }
|
|
|
- XSelectInput(dpy, win, ExposureMask | KeyPressMask);
|
|
|
-
|
|
|
- // This hides the cursor if the user has that option enabled in their
|
|
|
- // configuration
|
|
|
- HideCursor();
|
|
|
-
|
|
|
- loginPanel = new Panel(dpy, scr, win, cfg, themedir, Panel::Mode_Lock);
|
|
|
-
|
|
|
- int ret = pam_start(APPNAME, loginPanel->GetName().c_str(), &conv, &pam_handle);
|
|
|
- // If we can't start PAM, just exit because slimlock won't work right
|
|
|
- if (ret != PAM_SUCCESS)
|
|
|
- die("PAM: %s\n", pam_strerror(pam_handle, ret));
|
|
|
-
|
|
|
- // disable tty switching
|
|
|
- if(cfg->getOption("tty_lock") == "1") {
|
|
|
- if ((term = open("/dev/console", O_RDWR)) == -1)
|
|
|
- perror("error opening console");
|
|
|
-
|
|
|
- if ((ioctl(term, VT_LOCKSWITCH)) == -1)
|
|
|
- perror("error locking console");
|
|
|
- }
|
|
|
-
|
|
|
- // Set up DPMS
|
|
|
- unsigned int cfg_dpms_standby, cfg_dpms_off;
|
|
|
- cfg_dpms_standby = Cfg::string2int(cfg->getOption("dpms_standby_timeout").c_str());
|
|
|
- cfg_dpms_off = Cfg::string2int(cfg->getOption("dpms_off_timeout").c_str());
|
|
|
- using_dpms = DPMSCapable(dpy) && (cfg_dpms_standby > 0);
|
|
|
- if (using_dpms) {
|
|
|
- DPMSGetTimeouts(dpy, &dpms_standby, &dpms_suspend, &dpms_off);
|
|
|
-
|
|
|
- DPMSSetTimeouts(dpy, cfg_dpms_standby,
|
|
|
- cfg_dpms_standby, cfg_dpms_off);
|
|
|
-
|
|
|
- DPMSInfo(dpy, &dpms_level, &dpms_state);
|
|
|
- if (!dpms_state)
|
|
|
- DPMSEnable(dpy);
|
|
|
- }
|
|
|
-
|
|
|
- // Get password timeout
|
|
|
- cfg_passwd_timeout = Cfg::string2int(cfg->getOption("wrong_passwd_timeout").c_str());
|
|
|
- // Let's just make sure it has a sane value
|
|
|
- cfg_passwd_timeout = cfg_passwd_timeout > 60 ? 60 : cfg_passwd_timeout;
|
|
|
-
|
|
|
- pthread_t raise_thread;
|
|
|
- pthread_create(&raise_thread, NULL, RaiseWindow, NULL);
|
|
|
-
|
|
|
- // Main loop
|
|
|
- while (true)
|
|
|
- {
|
|
|
- loginPanel->ResetPasswd();
|
|
|
-
|
|
|
- // AuthenticateUser returns true if authenticated
|
|
|
- if (AuthenticateUser())
|
|
|
- break;
|
|
|
-
|
|
|
- cerr << APPNAME << ": HOGE14b: " << endl;
|
|
|
- loginPanel->WrongPassword(cfg_passwd_timeout);
|
|
|
- cerr << APPNAME << ": HOGE14c: " << endl;
|
|
|
- }
|
|
|
-
|
|
|
- // kill thread before destroying the window that it's supposed to be raising
|
|
|
- pthread_cancel(raise_thread);
|
|
|
-
|
|
|
- loginPanel->ClosePanel();
|
|
|
- delete loginPanel;
|
|
|
-
|
|
|
- // Get DPMS stuff back to normal
|
|
|
- if (using_dpms) {
|
|
|
- DPMSSetTimeouts(dpy, dpms_standby, dpms_suspend, dpms_off);
|
|
|
- // turn off DPMS if it was off when we entered
|
|
|
- if (!dpms_state)
|
|
|
- DPMSDisable(dpy);
|
|
|
- }
|
|
|
-
|
|
|
- XCloseDisplay(dpy);
|
|
|
-
|
|
|
- close(lock_file);
|
|
|
-
|
|
|
- if(cfg->getOption("tty_lock") == "1") {
|
|
|
- if ((ioctl(term, VT_UNLOCKSWITCH)) == -1) {
|
|
|
- perror("error unlocking console");
|
|
|
- }
|
|
|
- }
|
|
|
- close(term);
|
|
|
-
|
|
|
- return 0;
|
|
|
+ if((argc == 2) && !strcmp("-v", argv[1]))
|
|
|
+ die(APPNAME"-"VERSION", © 2010-2012 Joel Burget\n");
|
|
|
+ else if(argc != 1)
|
|
|
+ die("usage: "APPNAME" [-v]\n");
|
|
|
+
|
|
|
+ void (*prev_fn)(int);
|
|
|
+
|
|
|
+ // restore DPMS settings should slimlock be killed in the line of duty
|
|
|
+ prev_fn = signal(SIGTERM, HandleSignal);
|
|
|
+ if (prev_fn == SIG_IGN) signal(SIGTERM, SIG_IGN);
|
|
|
+
|
|
|
+ // create a lock file to solve mutliple instances problem
|
|
|
+ // /var/lock used to be the place to put this, now it's /run/lock
|
|
|
+ // ...i think
|
|
|
+ struct stat statbuf;
|
|
|
+ int lock_file;
|
|
|
+
|
|
|
+ // try /run/lock first, since i believe it's preferred
|
|
|
+ if (!stat("/run/lock", &statbuf))
|
|
|
+ lock_file = open("/run/lock/"APPNAME".lock", O_CREAT | O_RDWR, 0666);
|
|
|
+ else
|
|
|
+ lock_file = open("/var/lock/"APPNAME".lock", O_CREAT | O_RDWR, 0666);
|
|
|
+
|
|
|
+ int rc = flock(lock_file, LOCK_EX | LOCK_NB);
|
|
|
+
|
|
|
+ if(rc) {
|
|
|
+ if(EWOULDBLOCK == errno)
|
|
|
+ die(APPNAME" already running\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ unsigned int cfg_passwd_timeout;
|
|
|
+ // Read user's current theme
|
|
|
+ cfg = new Cfg;
|
|
|
+ cfg->readConf(CFGFILE);
|
|
|
+ cfg->readConf(SLIMLOCKCFG);
|
|
|
+ string themebase = "";
|
|
|
+ string themefile = "";
|
|
|
+ string themedir = "";
|
|
|
+ themeName = "";
|
|
|
+ themebase = string(THEMESDIR) + "/";
|
|
|
+ themeName = cfg->getOption("current_theme");
|
|
|
+ string::size_type pos;
|
|
|
+ if ((pos = themeName.find(",")) != string::npos) {
|
|
|
+ themeName = findValidRandomTheme(themeName);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool loaded = false;
|
|
|
+ while (!loaded) {
|
|
|
+ themedir = themebase + themeName;
|
|
|
+ themefile = themedir + THEMESFILE;
|
|
|
+ if (!cfg->readConf(themefile)) {
|
|
|
+ if (themeName == "default") {
|
|
|
+ cerr << APPNAME << ": Failed to open default theme file "
|
|
|
+ << themefile << endl;
|
|
|
+ exit(ERR_EXIT);
|
|
|
+ } else {
|
|
|
+ cerr << APPNAME << ": Invalid theme in config: "
|
|
|
+ << themeName << endl;
|
|
|
+ themeName = "default";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ loaded = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const char *display = getenv("DISPLAY");
|
|
|
+ if (!display)
|
|
|
+ display = DISPLAY;
|
|
|
+
|
|
|
+ if(!(dpy = XOpenDisplay(display)))
|
|
|
+ die(APPNAME": cannot open display\n");
|
|
|
+ scr = DefaultScreen(dpy);
|
|
|
+
|
|
|
+ XSetWindowAttributes wa;
|
|
|
+ wa.override_redirect = 1;
|
|
|
+ wa.background_pixel = BlackPixel(dpy, scr);
|
|
|
+
|
|
|
+ // Create a full screen window
|
|
|
+ Window root = RootWindow(dpy, scr);
|
|
|
+ win = XCreateWindow(dpy,
|
|
|
+ root,
|
|
|
+ 0,
|
|
|
+ 0,
|
|
|
+ DisplayWidth(dpy, scr),
|
|
|
+ DisplayHeight(dpy, scr),
|
|
|
+ 0,
|
|
|
+ DefaultDepth(dpy, scr),
|
|
|
+ CopyFromParent,
|
|
|
+ DefaultVisual(dpy, scr),
|
|
|
+ CWOverrideRedirect | CWBackPixel,
|
|
|
+ &wa);
|
|
|
+ XMapWindow(dpy, win);
|
|
|
+
|
|
|
+ XFlush(dpy);
|
|
|
+ for (int len = 1000; len; len--) {
|
|
|
+ if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
|
|
|
+ == GrabSuccess)
|
|
|
+ break;
|
|
|
+ usleep(1000);
|
|
|
+ }
|
|
|
+ XSelectInput(dpy, win, ExposureMask | KeyPressMask);
|
|
|
+
|
|
|
+ // This hides the cursor if the user has that option enabled in their
|
|
|
+ // configuration
|
|
|
+ HideCursor();
|
|
|
+
|
|
|
+ loginPanel = new Panel(dpy, scr, win, cfg, themedir, Panel::Mode_Lock);
|
|
|
+
|
|
|
+ int ret = pam_start(APPNAME, loginPanel->GetName().c_str(), &conv, &pam_handle);
|
|
|
+ // If we can't start PAM, just exit because slimlock won't work right
|
|
|
+ if (ret != PAM_SUCCESS)
|
|
|
+ die("PAM: %s\n", pam_strerror(pam_handle, ret));
|
|
|
+
|
|
|
+ // disable tty switching
|
|
|
+ if(cfg->getOption("tty_lock") == "1") {
|
|
|
+ if ((term = open("/dev/console", O_RDWR)) == -1)
|
|
|
+ perror("error opening console");
|
|
|
+
|
|
|
+ if ((ioctl(term, VT_LOCKSWITCH)) == -1)
|
|
|
+ perror("error locking console");
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set up DPMS
|
|
|
+ unsigned int cfg_dpms_standby, cfg_dpms_off;
|
|
|
+ cfg_dpms_standby = Cfg::string2int(cfg->getOption("dpms_standby_timeout").c_str());
|
|
|
+ cfg_dpms_off = Cfg::string2int(cfg->getOption("dpms_off_timeout").c_str());
|
|
|
+ using_dpms = DPMSCapable(dpy) && (cfg_dpms_standby > 0);
|
|
|
+ if (using_dpms) {
|
|
|
+ DPMSGetTimeouts(dpy, &dpms_standby, &dpms_suspend, &dpms_off);
|
|
|
+
|
|
|
+ DPMSSetTimeouts(dpy, cfg_dpms_standby,
|
|
|
+ cfg_dpms_standby, cfg_dpms_off);
|
|
|
+
|
|
|
+ DPMSInfo(dpy, &dpms_level, &dpms_state);
|
|
|
+ if (!dpms_state)
|
|
|
+ DPMSEnable(dpy);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get password timeout
|
|
|
+ cfg_passwd_timeout = Cfg::string2int(cfg->getOption("wrong_passwd_timeout").c_str());
|
|
|
+ // Let's just make sure it has a sane value
|
|
|
+ cfg_passwd_timeout = cfg_passwd_timeout > 60 ? 60 : cfg_passwd_timeout;
|
|
|
+
|
|
|
+ pthread_t raise_thread;
|
|
|
+ pthread_create(&raise_thread, NULL, RaiseWindow, NULL);
|
|
|
+
|
|
|
+ // Main loop
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ loginPanel->ResetPasswd();
|
|
|
+
|
|
|
+ // AuthenticateUser returns true if authenticated
|
|
|
+ if (AuthenticateUser())
|
|
|
+ break;
|
|
|
+
|
|
|
+ loginPanel->WrongPassword(cfg_passwd_timeout);
|
|
|
+ }
|
|
|
+
|
|
|
+ // kill thread before destroying the window that it's supposed to be raising
|
|
|
+ pthread_cancel(raise_thread);
|
|
|
+
|
|
|
+ loginPanel->ClosePanel();
|
|
|
+ delete loginPanel;
|
|
|
+
|
|
|
+ // Get DPMS stuff back to normal
|
|
|
+ if (using_dpms) {
|
|
|
+ DPMSSetTimeouts(dpy, dpms_standby, dpms_suspend, dpms_off);
|
|
|
+ // turn off DPMS if it was off when we entered
|
|
|
+ if (!dpms_state)
|
|
|
+ DPMSDisable(dpy);
|
|
|
+ }
|
|
|
+
|
|
|
+ XCloseDisplay(dpy);
|
|
|
+
|
|
|
+ close(lock_file);
|
|
|
+
|
|
|
+ if(cfg->getOption("tty_lock") == "1") {
|
|
|
+ if ((ioctl(term, VT_UNLOCKSWITCH)) == -1) {
|
|
|
+ perror("error unlocking console");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ close(term);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
void HideCursor()
|
|
|
{
|
|
|
- if (cfg->getOption("hidecursor") == "true") {
|
|
|
- XColor black;
|
|
|
- char cursordata[1];
|
|
|
- Pixmap cursorpixmap;
|
|
|
- Cursor cursor;
|
|
|
- cursordata[0] = 0;
|
|
|
- cursorpixmap = XCreateBitmapFromData(dpy, win, cursordata, 1, 1);
|
|
|
- black.red = 0;
|
|
|
- black.green = 0;
|
|
|
- black.blue = 0;
|
|
|
- cursor = XCreatePixmapCursor(dpy, cursorpixmap, cursorpixmap,
|
|
|
- &black, &black, 0, 0);
|
|
|
- XFreePixmap(dpy, cursorpixmap);
|
|
|
- XDefineCursor(dpy, win, cursor);
|
|
|
- }
|
|
|
+ if (cfg->getOption("hidecursor") == "true") {
|
|
|
+ XColor black;
|
|
|
+ char cursordata[1];
|
|
|
+ Pixmap cursorpixmap;
|
|
|
+ Cursor cursor;
|
|
|
+ cursordata[0] = 0;
|
|
|
+ cursorpixmap = XCreateBitmapFromData(dpy, win, cursordata, 1, 1);
|
|
|
+ black.red = 0;
|
|
|
+ black.green = 0;
|
|
|
+ black.blue = 0;
|
|
|
+ cursor = XCreatePixmapCursor(dpy, cursorpixmap, cursorpixmap,
|
|
|
+ &black, &black, 0, 0);
|
|
|
+ XFreePixmap(dpy, cursorpixmap);
|
|
|
+ XDefineCursor(dpy, win, cursor);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static int ConvCallback(int num_msgs, const struct pam_message **msg,
|
|
|
- struct pam_response **resp, void *appdata_ptr)
|
|
|
+ struct pam_response **resp, void *appdata_ptr)
|
|
|
{
|
|
|
- loginPanel->EventHandler(Panel::Get_Passwd);
|
|
|
-
|
|
|
- // PAM expects an array of responses, one for each message
|
|
|
- if (num_msgs == 0 ||
|
|
|
- (*resp = (pam_response*) calloc(num_msgs, sizeof(struct pam_message))) == NULL)
|
|
|
- return PAM_BUF_ERR;
|
|
|
-
|
|
|
- for (int i = 0; i < num_msgs; i++) {
|
|
|
- if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF &&
|
|
|
- msg[i]->msg_style != PAM_PROMPT_ECHO_ON)
|
|
|
- continue;
|
|
|
-
|
|
|
- // return code is currently not used but should be set to zero
|
|
|
- resp[i]->resp_retcode = 0;
|
|
|
- if ((resp[i]->resp = strdup(loginPanel->GetPasswd().c_str())) == NULL) {
|
|
|
- free(*resp);
|
|
|
- return PAM_BUF_ERR;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return PAM_SUCCESS;
|
|
|
+ loginPanel->EventHandler(Panel::Get_Passwd);
|
|
|
+
|
|
|
+ // PAM expects an array of responses, one for each message
|
|
|
+ if (num_msgs == 0 ||
|
|
|
+ (*resp = (pam_response*) calloc(num_msgs, sizeof(struct pam_message))) == NULL)
|
|
|
+ return PAM_BUF_ERR;
|
|
|
+
|
|
|
+ for (int i = 0; i < num_msgs; i++) {
|
|
|
+ if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF &&
|
|
|
+ msg[i]->msg_style != PAM_PROMPT_ECHO_ON)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ // return code is currently not used but should be set to zero
|
|
|
+ resp[i]->resp_retcode = 0;
|
|
|
+ if ((resp[i]->resp = strdup(loginPanel->GetPasswd().c_str())) == NULL) {
|
|
|
+ free(*resp);
|
|
|
+ return PAM_BUF_ERR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return PAM_SUCCESS;
|
|
|
}
|
|
|
|
|
|
bool AuthenticateUser()
|
|
@@ -313,60 +311,60 @@ bool AuthenticateUser()
|
|
|
|
|
|
string findValidRandomTheme(const string& set)
|
|
|
{
|
|
|
- // extract random theme from theme set; return empty string on error
|
|
|
- string name = set;
|
|
|
- struct stat buf;
|
|
|
-
|
|
|
- if (name[name.length() - 1] == ',') {
|
|
|
- name.erase(name.length() - 1);
|
|
|
- }
|
|
|
-
|
|
|
- Util::srandom(Util::makeseed());
|
|
|
-
|
|
|
- vector<string> themes;
|
|
|
- string themefile;
|
|
|
- Cfg::split(themes, name, ',');
|
|
|
- do {
|
|
|
- int sel = Util::random() % themes.size();
|
|
|
-
|
|
|
- name = Cfg::Trim(themes[sel]);
|
|
|
- themefile = string(THEMESDIR) +"/" + name + THEMESFILE;
|
|
|
- if (stat(themefile.c_str(), &buf) != 0) {
|
|
|
- themes.erase(find(themes.begin(), themes.end(), name));
|
|
|
- cerr << APPNAME << ": Invalid theme in config: "
|
|
|
- << name << endl;
|
|
|
- name = "";
|
|
|
- }
|
|
|
- } while (name == "" && themes.size());
|
|
|
- return name;
|
|
|
+ // extract random theme from theme set; return empty string on error
|
|
|
+ string name = set;
|
|
|
+ struct stat buf;
|
|
|
+
|
|
|
+ if (name[name.length() - 1] == ',') {
|
|
|
+ name.erase(name.length() - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ Util::srandom(Util::makeseed());
|
|
|
+
|
|
|
+ vector<string> themes;
|
|
|
+ string themefile;
|
|
|
+ Cfg::split(themes, name, ',');
|
|
|
+ do {
|
|
|
+ int sel = Util::random() % themes.size();
|
|
|
+
|
|
|
+ name = Cfg::Trim(themes[sel]);
|
|
|
+ themefile = string(THEMESDIR) +"/" + name + THEMESFILE;
|
|
|
+ if (stat(themefile.c_str(), &buf) != 0) {
|
|
|
+ themes.erase(find(themes.begin(), themes.end(), name));
|
|
|
+ cerr << APPNAME << ": Invalid theme in config: "
|
|
|
+ << name << endl;
|
|
|
+ name = "";
|
|
|
+ }
|
|
|
+ } while (name == "" && themes.size());
|
|
|
+ return name;
|
|
|
}
|
|
|
|
|
|
void HandleSignal(int sig)
|
|
|
{
|
|
|
- // Get DPMS stuff back to normal
|
|
|
- if (using_dpms) {
|
|
|
- DPMSSetTimeouts(dpy, dpms_standby, dpms_suspend, dpms_off);
|
|
|
- // turn off DPMS if it was off when we entered
|
|
|
- if (!dpms_state)
|
|
|
- DPMSDisable(dpy);
|
|
|
- }
|
|
|
-
|
|
|
- if ((ioctl(term, VT_UNLOCKSWITCH)) == -1) {
|
|
|
- perror("error unlocking console");
|
|
|
- }
|
|
|
- close(term);
|
|
|
-
|
|
|
- loginPanel->ClosePanel();
|
|
|
- delete loginPanel;
|
|
|
-
|
|
|
- die(APPNAME": Caught signal; dying\n");
|
|
|
+ // Get DPMS stuff back to normal
|
|
|
+ if (using_dpms) {
|
|
|
+ DPMSSetTimeouts(dpy, dpms_standby, dpms_suspend, dpms_off);
|
|
|
+ // turn off DPMS if it was off when we entered
|
|
|
+ if (!dpms_state)
|
|
|
+ DPMSDisable(dpy);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((ioctl(term, VT_UNLOCKSWITCH)) == -1) {
|
|
|
+ perror("error unlocking console");
|
|
|
+ }
|
|
|
+ close(term);
|
|
|
+
|
|
|
+ loginPanel->ClosePanel();
|
|
|
+ delete loginPanel;
|
|
|
+
|
|
|
+ die(APPNAME": Caught signal; dying\n");
|
|
|
}
|
|
|
|
|
|
void* RaiseWindow(void *data) {
|
|
|
- while(1) {
|
|
|
- XRaiseWindow(dpy, win);
|
|
|
- sleep(1);
|
|
|
- }
|
|
|
+ while(1) {
|
|
|
+ XRaiseWindow(dpy, win);
|
|
|
+ sleep(1);
|
|
|
+ }
|
|
|
|
|
|
return (void *)0;
|
|
|
}
|