update slock

This commit is contained in:
2026-11-05 15:22:19 +01:00
19 changed files with 1343 additions and 54 deletions
+47 -11
View File
@@ -25,17 +25,53 @@ xinput list --name-only | while IFS= read -r device; do
esac esac
done done
# Start desktop services
bluetoothctl power off &
picom &
xbindkeys &
xss-lock -l slock &
feh --bg-scale "$HOME/Obrázky/wallpapers/glados.jpg" &
dwmblocks & dwmblocks &
# ~~Keep this last: it replaces the script with dwm~~ # i really need it :(
exec dwm export GPG_TTY=$(tty)
# Restart audio services before starting the status bar exec dbus-run-session -- sh -c '
systemctl --user restart wireplumber pipewire pipewire-pulse;pkill -RTMIN+2 dwmblocks export GPG_TTY=$(tty)
export PATH=$HOME/.local/bin:$PATH
if ! pgrep -a -u "$(id -u)" -x pipewire >/dev/null 2>&1; then
pipewire &
fi
sleep 1
pkill -RTMIN+2 dwmblocks
# Start desktop services
bluetoothctl power off &
if ! pgrep -a -u "$(id -u)" -x picom >/dev/null 2>&1; then
picom --backend glx &
fi
if ! pgrep -a -u "$(id -u)" -x dunst >/dev/null 2>&1; then
dunst &
fi
if ! pgrep -a -u "$(id -u)" -x mpv >/dev/null 2>&1; then
mpv --shuffle --pause --no-video --loop-playlist -ao=alsa $HOME/Music &
fi
if ! pgrep -a -u "$(id -u)" -x mpv-shuffle-notify >/dev/null 2>&1; then
mpv-shuffle-notify &
fi
if ! pgrep -a -u "$(id -u)" -x sxhkd >/dev/null 2>&1; then
sxhkd &
fi
xbindkeys &
# xss-lock -l slock &
if ! pgrep -a -u "$(id -u)" -x xss-lock >/dev/null 2>&1; then
xss-lock -- \
env XSECURELOCK_AUTHPROTO=authproto_pam \
XSECURELOCK_PAM_SERVICE=login \
XSECURELOCK_NO_PAM_RHOST=1 \
xsecurelock &
fi
feh --bg-scale "$HOME/Pictures/wallpapers/glados.jpg" &
exec dwm
'
+4 -4
View File
@@ -1,12 +1,12 @@
/* keybinds */ /* keybinds */
/** /**
* free keys: * free keys:
* a b c d e f g h i j k l m n o p q r s t u v w x y z space Return grave semicolon colon comma period slash backslash [0-9] minus equals * a b c d e f g h i j k l m n o p q r s t u v w x y z space Return grave semicolon colon comma period slash backslash [0-9] minus equals
* 2x with ShitMask * 2x with ShitMask
* = 38 * 2 = 76 different actions can be bound * = 38 * 2 = 76 different actions can be bound
* (+ however many Fn keys you have) * (+ however many Fn keys you have)
* *
* taken keys: * taken keys:
* space Return m w, h j k l q ShiftMask|f, comma ShiftMask|comma period ShiftMask|period, ShiftMask|Return f p n ShiftMask|m s, [1-9], ShiftMask|e * space Return m w, h j k l q ShiftMask|f, comma ShiftMask|comma period ShiftMask|period, ShiftMask|Return f p n ShiftMask|m s, [1-9], ShiftMask|e
*/ */
@@ -15,7 +15,7 @@ static const Key keys[] = {
// essential apps // essential apps
{ MODKEY, XK_space, spawn, {.v = dmenucmd } }, { MODKEY, XK_space, spawn, {.v = dmenucmd } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_m, spawn, {.v = djcmd } }, // { MODKEY, XK_m, spawn, {.v = djcmd } },
{ MODKEY, XK_w, spawn, {.v = webbrowsercmd } }, { MODKEY, XK_w, spawn, {.v = webbrowsercmd } },
// window management // window management
{ MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_j, focusstack, {.i = +1 } },
+1 -1
View File
@@ -10,7 +10,7 @@ const char *spcmd0[] = {"st", "-n", "spterm", "-g", "120x34", NULL };
const char *spcmd1[] = {"thunar", NULL }; const char *spcmd1[] = {"thunar", NULL };
const char *spcmd2[] = {"keepassxc", NULL }; const char *spcmd2[] = {"keepassxc", NULL };
const char *spcmd3[] = {"st", "-n", "spnmtui", "-g", "140x30", "-e", "nmtui", NULL }; const char *spcmd3[] = {"st", "-n", "spnmtui", "-g", "140x30", "-e", "nmtui", NULL };
const char *spcmd4[] = {"st", "-n", "spmusic", "-g", "140x30", "-e", "ncmpcpp", NULL }; const char *spcmd4[] = {"st", "-n", "spmusic", "-g", "140x30", "-e", "kew", NULL };
const char *spcmd5[] = {"signal-desktop", NULL }; const char *spcmd5[] = {"signal-desktop", NULL };
static Sp scratchpads[] = { static Sp scratchpads[] = {
+13 -3
View File
@@ -3,10 +3,20 @@ static const char *user = "imp";
static const char *group = "imp"; static const char *group = "imp";
static const char *colorname[NUMCOLS] = { static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */ [INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#735e97", /* during input */ [INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#CC3333", /* wrong password */ [FAILED] = "#fb4934", /* Gruvbox bright red */
[PAM] = "#d3869b", /* waiting for PAM */
}; };
/* treat a cleared input like a wrong password (color) */ /* treat a cleared input like a wrong password (color) */
static const int failonclear = 1; static const int failonclear = 1;
/* PAM service that's used for authentication */
static const char* pam_service = "login";
/* Background image path, should be available to the user above */
static const char* background_image = "/usr/share/backgrounds/glados.jpg";
/* time in seconds before the monitor shuts down */
static const int monitortime = 10;
+13
View File
@@ -0,0 +1,13 @@
/* user and group to drop privileges to */
static const char *user = "imp";
static const char *group = "imp";
static const char *colorname[NUMCOLS] = {
[INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#fb4934", /* Gruvbox bright red */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+19
View File
@@ -0,0 +1,19 @@
/* user and group to drop privileges to */
static const char *user = "imp";
static const char *group = "imp";
static const char *colorname[NUMCOLS] = {
[INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#fb4934", /* Gruvbox bright red */
[PAM] = "#d3869b", /* waiting for PAM */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
/* PAM service that's used for authentication */
static const char* pam_service = "login";
/* Background image path, should be available to the user above */
static const char* background_image = "/usr/share/backgrounds/glados.jpg";
+9
View File
@@ -0,0 +1,9 @@
--- config.def.h
+++ config.def.h
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* time in seconds before the monitor shuts down */
+static const int monitortime = 5;
+13 -3
View File
@@ -3,10 +3,20 @@ static const char *user = "imp";
static const char *group = "imp"; static const char *group = "imp";
static const char *colorname[NUMCOLS] = { static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */ [INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#735e97", /* during input */ [INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#CC3333", /* wrong password */ [FAILED] = "#fb4934", /* Gruvbox bright red */
[PAM] = "#d3869b", /* waiting for PAM */
}; };
/* treat a cleared input like a wrong password (color) */ /* treat a cleared input like a wrong password (color) */
static const int failonclear = 1; static const int failonclear = 1;
/* PAM service that's used for authentication */
static const char* pam_service = "login";
/* Background image path, should be available to the user above */
static const char* background_image = "/usr/share/backgrounds/glados.jpg";
/* time in seconds before the monitor shuts down */
static const int monitortime = 10;
+1 -1
View File
@@ -15,7 +15,7 @@ X11LIB = $(shell $(PKG_CONFIG) --libs x11 xft xrandr xinerama fontconfig freetyp
# includes and libs # includes and libs
INCS = ${X11INC} INCS = ${X11INC}
LIBS = -lc -lcrypt ${X11LIB} LIBS = -lc -lcrypt -lpam -lImlib2 -lXext ${X11LIB}
# flags # flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
+26
View File
@@ -0,0 +1,26 @@
# slock version
VERSION = 1.6-odweta
# Customize below to fit your system
# paths
PREFIX = /usr
MANPREFIX = ${PREFIX}/share/man
PKG_CONFIG := pkg-config
# compiler and linker flags
X11INC = $(shell $(PKG_CONFIG) --cflags x11 xft xrandr xinerama fontconfig freetype2)
X11LIB = $(shell $(PKG_CONFIG) --libs x11 xft xrandr xinerama fontconfig freetype2)
# includes and libs
INCS = ${X11INC}
LIBS = -lc -lcrypt -lpam ${X11LIB}
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS}
COMPATSRC = explicit_bzero.c
CC = cc
+11
View File
@@ -0,0 +1,11 @@
--- config.mk
+++ config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lImlib2
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
+88
View File
@@ -0,0 +1,88 @@
diff -up a/slock.c b/slock.c
--- a/slock.c 2026-07-28 03:28:03.120285888 +0530
+++ b/slock.c 2026-08-03 11:20:35.223992495 +0530
@@ -6,7 +6,9 @@
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
#include <grp.h>
+#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -59,7 +61,6 @@ die(const char *errstr, ...)
}
#ifdef __linux__
-#include <fcntl.h>
#include <linux/oom.h>
static void
@@ -301,6 +302,28 @@ lockscreen(Display *dpy, struct xrandr *
return NULL;
}
+static int
+get_xss_sleep_lock_fd(void)
+{
+ char *env_str, *end;
+ long env_val;
+
+ env_str = getenv("XSS_SLEEP_LOCK_FD");
+ if (!env_str || !*env_str)
+ return -1;
+
+ errno = 0;
+ env_val = strtol(env_str, &end, 10);
+ if (errno ||
+ *end ||
+ (env_val < 0 || env_val > INT_MAX)) {
+ fprintf(stderr, "slock: strtol $XSS_SLEEP_LOCK_FD: %s\n",
+ errno ? strerror(errno) : "invalid value");
+ return -1;
+ }
+ return (int)env_val;
+}
+
static void
usage(void)
{
@@ -318,6 +341,7 @@ main(int argc, char **argv) {
const char *hash;
Display *dpy;
int s, nlocks, nscreens;
+ int lockfd;
ARGBEGIN {
case 'v':
@@ -327,6 +351,18 @@ main(int argc, char **argv) {
usage();
} ARGEND
+ lockfd = get_xss_sleep_lock_fd();
+ if (lockfd >= 0) {
+ int flags = fcntl(lockfd, F_GETFD);
+ if (flags < 0) {
+ fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_GETFD: %s\n",
+ strerror(errno));
+ } else if (fcntl(lockfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
+ fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_SETFD: %s\n",
+ strerror(errno));
+ }
+ }
+
/* validate drop-user and -group */
errno = 0;
if (!(pwd = getpwnam(user)))
@@ -378,6 +414,9 @@ main(int argc, char **argv) {
if (nlocks != nscreens)
return 1;
+ if (lockfd >= 0 && close(lockfd) < 0)
+ fprintf(stderr, "slock: close $XSS_SLEEP_LOCK_FD: %s\n", strerror(errno));
+
/* run post-lock command */
if (argc > 0) {
pid_t pid;
@@ -0,0 +1,150 @@
From 1c5a5383a1cf3351fe9c80a21cfbc98c5ec4355d Mon Sep 17 00:00:00 2001
From: Yan Doroshenko <yan1994doroshenko@gmail.com>
Date: Fri, 18 Mar 2022 12:28:13 +0100
Subject: [PATCH] Provide a way to set a background image
---
config.def.h | 5 ++++-
config.mk | 2 +-
slock.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/config.def.h b/config.def.h
index 9855e21..eb88b3d 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,6 +1,6 @@
/* user and group to drop privileges to */
static const char *user = "nobody";
-static const char *group = "nogroup";
+static const char *group = "nobody";
static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* Background image path, should be available to the user above */
+static const char* background_image = "";
diff --git a/config.mk b/config.mk
index 74429ae..987819e 100644
--- a/config.mk
+++ b/config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lImlib2
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
diff --git a/slock.c b/slock.c
index 5ae738c..345a279 100644
--- a/slock.c
+++ b/slock.c
@@ -18,6 +18,7 @@
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <Imlib2.h>
#include "arg.h"
#include "util.h"
@@ -35,6 +36,7 @@ struct lock {
int screen;
Window root, win;
Pixmap pmap;
+ Pixmap bgmap;
unsigned long colors[NUMCOLS];
};
@@ -46,6 +48,8 @@ struct xrandr {
#include "config.h"
+Imlib_Image image;
+
static void
die(const char *errstr, ...)
{
@@ -190,9 +194,10 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) {
- XSetWindowBackground(dpy,
- locks[screen]->win,
- locks[screen]->colors[color]);
+ if (locks[screen]->bgmap)
+ XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
+ else
+ XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win);
}
oldc = color;
@@ -235,6 +240,17 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen);
+ if(image)
+ {
+ lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
+ imlib_context_set_display(dpy);
+ imlib_context_set_visual(DefaultVisual(dpy, lock->screen));
+ imlib_context_set_colormap(DefaultColormap(dpy, lock->screen));
+ imlib_context_set_drawable(lock->bgmap);
+ imlib_render_image_on_drawable(0, 0);
+ imlib_free_image();
+ }
+
for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy);
@@ -251,6 +267,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
CopyFromParent,
DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa);
+ if(lock->bgmap)
+ XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0);
@@ -355,6 +373,32 @@ main(int argc, char **argv) {
if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno));
+ /* Load picture */
+ Imlib_Image buffer = imlib_load_image(background_image);
+ imlib_context_set_image(buffer);
+ int background_image_width = imlib_image_get_width();
+ int background_image_height = imlib_image_get_height();
+
+ /* Create an image to be rendered */
+ Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
+ image = imlib_create_image(scr->width, scr->height);
+ imlib_context_set_image(image);
+
+ /* Fill the image for every X monitor */
+ XRRMonitorInfo *monitors;
+ int number_of_monitors;
+ monitors = XRRGetMonitors(dpy, RootWindow(dpy, XScreenNumberOfScreen(scr)), True, &number_of_monitors);
+
+ int i;
+ for (i = 0; i < number_of_monitors; i++) {
+ imlib_blend_image_onto_image(buffer, 0, 0, 0, background_image_width, background_image_height, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
+ }
+
+ /* Clean up */
+ imlib_context_set_image(buffer);
+ imlib_free_image();
+ imlib_context_set_image(image);
+
/* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
--
2.35.1
+155
View File
@@ -0,0 +1,155 @@
diff --git a/config.def.h b/config.def.h
index 9855e21..19e7f62 100644
--- a/config.def.h
+++ b/config.def.h
@@ -6,7 +6,11 @@ static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */
[INPUT] = "#005577", /* during input */
[FAILED] = "#CC3333", /* wrong password */
+ [PAM] = "#9400D3", /* waiting for PAM */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* PAM service that's used for authentication */
+static const char* pam_service = "login";
diff --git a/config.mk b/config.mk
index 74429ae..6e82074 100644
--- a/config.mk
+++ b/config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lpam
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
diff --git a/slock.c b/slock.c
index 5ae738c..3a8da42 100644
--- a/slock.c
+++ b/slock.c
@@ -18,16 +18,22 @@
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
#include "arg.h"
#include "util.h"
char *argv0;
+static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
+struct pam_conv pamc = {pam_conv, NULL};
+char passwd[256];
enum {
INIT,
INPUT,
FAILED,
+ PAM,
NUMCOLS
};
@@ -57,6 +63,31 @@ die(const char *errstr, ...)
exit(1);
}
+static int
+pam_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int retval = PAM_CONV_ERR;
+ for(int i=0; i<num_msg; i++) {
+ if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
+ strncmp(msg[i]->msg, "Password: ", 10) == 0) {
+ struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
+ if (!resp_msg)
+ die("malloc failed\n");
+ char *password = malloc(strlen(passwd) + 1);
+ if (!password)
+ die("malloc failed\n");
+ memset(password, 0, strlen(passwd) + 1);
+ strcpy(password, passwd);
+ resp_msg->resp_retcode = 0;
+ resp_msg->resp = password;
+ resp[i] = resp_msg;
+ retval = PAM_SUCCESS;
+ }
+ }
+ return retval;
+}
+
#ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h>
@@ -121,6 +152,8 @@ gethash(void)
}
#endif /* HAVE_SHADOW_H */
+ /* pam, store user name */
+ hash = pw->pw_name;
return hash;
}
@@ -129,11 +162,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash)
{
XRRScreenChangeNotifyEvent *rre;
- char buf[32], passwd[256], *inputhash;
- int num, screen, running, failure, oldc;
+ char buf[32];
+ int num, screen, running, failure, oldc, retval;
unsigned int len, color;
KeySym ksym;
XEvent ev;
+ pam_handle_t *pamh;
len = 0;
running = 1;
@@ -160,10 +194,26 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
case XK_Return:
passwd[len] = '\0';
errno = 0;
- if (!(inputhash = crypt(passwd, hash)))
- fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
+ retval = pam_start(pam_service, hash, &pamc, &pamh);
+ color = PAM;
+ for (screen = 0; screen < nscreens; screen++) {
+ XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
+ XClearWindow(dpy, locks[screen]->win);
+ XRaiseWindow(dpy, locks[screen]->win);
+ }
+ XSync(dpy, False);
+
+ if (retval == PAM_SUCCESS)
+ retval = pam_authenticate(pamh, 0);
+ if (retval == PAM_SUCCESS)
+ retval = pam_acct_mgmt(pamh, 0);
+
+ running = 1;
+ if (retval == PAM_SUCCESS)
+ running = 0;
else
- running = !!strcmp(inputhash, hash);
+ fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
+ pam_end(pamh, retval);
if (running) {
XBell(dpy, 100);
failure = 1;
@@ -339,10 +389,9 @@ main(int argc, char **argv) {
dontkillme();
#endif
+ /* the contents of hash are used to transport the current user name */
hash = gethash();
errno = 0;
- if (!crypt("", hash))
- die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
+63
View File
@@ -0,0 +1,63 @@
diff --git a/config.def.h b/config.def.h
index 9855e21..d01bd38 100644
--- a/config.def.h
+++ b/config.def.h
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* time in seconds before the monitor shuts down */
+static const int monitortime = 5;
diff --git a/slock.c b/slock.c
index d2f0886..f65a43b 100644
--- a/slock.c
+++ b/slock.c
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/dpms.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -306,6 +307,7 @@ main(int argc, char **argv) {
const char *hash;
Display *dpy;
int s, nlocks, nscreens;
+ CARD16 standby, suspend, off;
ARGBEGIN {
case 'v':
@@ -366,6 +368,20 @@ main(int argc, char **argv) {
if (nlocks != nscreens)
return 1;
+ /* DPMS magic to disable the monitor */
+ if (!DPMSCapable(dpy))
+ die("slock: DPMSCapable failed\n");
+ if (!DPMSEnable(dpy))
+ die("slock: DPMSEnable failed\n");
+ if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
+ die("slock: DPMSGetTimeouts failed\n");
+ if (!standby || !suspend || !off)
+ die("slock: at least one DPMS variable is zero\n");
+ if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
+ die("slock: DPMSSetTimeouts failed\n");
+
+ XSync(dpy, 0);
+
/* run post-lock command */
if (argc > 0) {
switch (fork()) {
@@ -383,5 +399,9 @@ main(int argc, char **argv) {
/* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash);
+ /* reset DPMS values to inital ones */
+ DPMSSetTimeouts(dpy, standby, suspend, off);
+ XSync(dpy, 0);
+
return 0;
}
+164 -11
View File
@@ -6,7 +6,9 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <grp.h> #include <grp.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@@ -16,20 +18,29 @@
#include <spawn.h> #include <spawn.h>
#include <sys/types.h> #include <sys/types.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/XF86keysym.h> #include <X11/XF86keysym.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <Imlib2.h>
#include "arg.h" #include "arg.h"
#include "util.h" #include "util.h"
char *argv0; char *argv0;
static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
struct pam_conv pamc = {pam_conv, NULL};
char passwd[256];
enum { enum {
INIT, INIT,
INPUT, INPUT,
FAILED, FAILED,
PAM,
NUMCOLS NUMCOLS
}; };
@@ -37,6 +48,7 @@ struct lock {
int screen; int screen;
Window root, win; Window root, win;
Pixmap pmap; Pixmap pmap;
Pixmap bgmap;
unsigned long colors[NUMCOLS]; unsigned long colors[NUMCOLS];
}; };
@@ -48,6 +60,8 @@ struct xrandr {
#include "config.h" #include "config.h"
Imlib_Image image;
static void static void
die(const char *errstr, ...) die(const char *errstr, ...)
{ {
@@ -59,8 +73,32 @@ die(const char *errstr, ...)
exit(1); exit(1);
} }
static int
pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int retval = PAM_CONV_ERR;
for(int i=0; i<num_msg; i++) {
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
strncmp(msg[i]->msg, "Password: ", 10) == 0) {
struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
if (!resp_msg)
die("malloc failed\n");
char *password = malloc(strlen(passwd) + 1);
if (!password)
die("malloc failed\n");
memset(password, 0, strlen(passwd) + 1);
strcpy(password, passwd);
resp_msg->resp_retcode = 0;
resp_msg->resp = password;
resp[i] = resp_msg;
retval = PAM_SUCCESS;
}
}
return retval;
}
#ifdef __linux__ #ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h> #include <linux/oom.h>
static void static void
@@ -123,6 +161,8 @@ gethash(void)
} }
#endif /* HAVE_SHADOW_H */ #endif /* HAVE_SHADOW_H */
/* pam, store user name */
hash = pw->pw_name;
return hash; return hash;
} }
@@ -131,11 +171,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash) const char *hash)
{ {
XRRScreenChangeNotifyEvent *rre; XRRScreenChangeNotifyEvent *rre;
char buf[32], passwd[256], *inputhash; char buf[32];
int num, screen, running, failure, oldc; int num, screen, running, failure, oldc, retval;
unsigned int len, color; unsigned int len, color;
KeySym ksym; KeySym ksym;
XEvent ev; XEvent ev;
pam_handle_t *pamh;
len = 0; len = 0;
running = 1; running = 1;
@@ -170,10 +211,26 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
case XK_Return: case XK_Return:
passwd[len] = '\0'; passwd[len] = '\0';
errno = 0; errno = 0;
if (!(inputhash = crypt(passwd, hash))) retval = pam_start(pam_service, hash, &pamc, &pamh);
fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); // color = PAM;
// for (screen = 0; screen < nscreens; screen++) {
// XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
// XClearWindow(dpy, locks[screen]->win);
// XRaiseWindow(dpy, locks[screen]->win);
// }
// XSync(dpy, False);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0);
running = 1;
if (retval == PAM_SUCCESS)
running = 0;
else else
running = !!strcmp(inputhash, hash); fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
pam_end(pamh, retval);
if (running) { if (running) {
XBell(dpy, 100); XBell(dpy, 100);
failure = 1; failure = 1;
@@ -203,9 +260,10 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) { if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) { for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, if (locks[screen]->bgmap)
locks[screen]->win, XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
locks[screen]->colors[color]); else
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win); XClearWindow(dpy, locks[screen]->win);
} }
oldc = color; oldc = color;
@@ -248,6 +306,17 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
lock->screen = screen; lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen); lock->root = RootWindow(dpy, lock->screen);
if(image)
{
lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy, lock->screen));
imlib_context_set_colormap(DefaultColormap(dpy, lock->screen));
imlib_context_set_drawable(lock->bgmap);
imlib_render_image_on_drawable(0, 0);
imlib_free_image();
}
for (i = 0; i < NUMCOLS; i++) { for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy); colorname[i], &color, &dummy);
@@ -264,6 +333,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
CopyFromParent, CopyFromParent,
DefaultVisual(dpy, lock->screen), DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa); CWOverrideRedirect | CWBackPixel, &wa);
if(lock->bgmap)
XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0); &color, &color, 0, 0);
@@ -310,6 +381,28 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
return NULL; return NULL;
} }
static int
get_xss_sleep_lock_fd(void)
{
char *env_str, *end;
long env_val;
env_str = getenv("XSS_SLEEP_LOCK_FD");
if (!env_str || !*env_str)
return -1;
errno = 0;
env_val = strtol(env_str, &end, 10);
if (errno ||
*end ||
(env_val < 0 || env_val > INT_MAX)) {
fprintf(stderr, "slock: strtol $XSS_SLEEP_LOCK_FD: %s\n",
errno ? strerror(errno) : "invalid value");
return -1;
}
return (int)env_val;
}
static void static void
usage(void) usage(void)
{ {
@@ -327,6 +420,8 @@ main(int argc, char **argv) {
const char *hash; const char *hash;
Display *dpy; Display *dpy;
int s, nlocks, nscreens; int s, nlocks, nscreens;
CARD16 standby, suspend, off;
int lockfd;
ARGBEGIN { ARGBEGIN {
case 'v': case 'v':
@@ -336,6 +431,18 @@ main(int argc, char **argv) {
usage(); usage();
} ARGEND } ARGEND
lockfd = get_xss_sleep_lock_fd();
if (lockfd >= 0) {
int flags = fcntl(lockfd, F_GETFD);
if (flags < 0) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_GETFD: %s\n",
strerror(errno));
} else if (fcntl(lockfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_SETFD: %s\n",
strerror(errno));
}
}
/* validate drop-user and -group */ /* validate drop-user and -group */
errno = 0; errno = 0;
if (!(pwd = getpwnam(user))) if (!(pwd = getpwnam(user)))
@@ -352,10 +459,9 @@ main(int argc, char **argv) {
dontkillme(); dontkillme();
#endif #endif
/* the contents of hash are used to transport the current user name */
hash = gethash(); hash = gethash();
errno = 0; errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n"); die("slock: cannot open display\n");
@@ -368,6 +474,32 @@ main(int argc, char **argv) {
if (setuid(duid) < 0) if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno)); die("slock: setuid: %s\n", strerror(errno));
/* Load picture */
Imlib_Image buffer = imlib_load_image(background_image);
imlib_context_set_image(buffer);
int background_image_width = imlib_image_get_width();
int background_image_height = imlib_image_get_height();
/* Create an image to be rendered */
Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
image = imlib_create_image(scr->width, scr->height);
imlib_context_set_image(image);
/* Fill the image for every X monitor */
XRRMonitorInfo *monitors;
int number_of_monitors;
monitors = XRRGetMonitors(dpy, RootWindow(dpy, XScreenNumberOfScreen(scr)), True, &number_of_monitors);
int i;
for (i = 0; i < number_of_monitors; i++) {
imlib_blend_image_onto_image(buffer, 0, 0, 0, background_image_width, background_image_height, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
}
/* Clean up */
imlib_context_set_image(buffer);
imlib_free_image();
imlib_context_set_image(image);
/* check for Xrandr support */ /* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
@@ -387,6 +519,23 @@ main(int argc, char **argv) {
if (nlocks != nscreens) if (nlocks != nscreens)
return 1; return 1;
if (lockfd >= 0 && close(lockfd) < 0)
fprintf(stderr, "slock: close $XSS_SLEEP_LOCK_FD: %s\n", strerror(errno));
/* DPMS magic to disable the monitor */
if (!DPMSCapable(dpy))
die("slock: DPMSCapable failed\n");
if (!DPMSEnable(dpy))
die("slock: DPMSEnable failed\n");
if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
die("slock: DPMSGetTimeouts failed\n");
if (!standby || !suspend || !off)
die("slock: at least one DPMS variable is zero\n");
if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
die("slock: DPMSSetTimeouts failed\n");
XSync(dpy, 0);
/* run post-lock command */ /* run post-lock command */
if (argc > 0) { if (argc > 0) {
pid_t pid; pid_t pid;
@@ -401,5 +550,9 @@ main(int argc, char **argv) {
/* everything is now blank. Wait for the correct password */ /* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash); readpw(dpy, &rr, locks, nscreens, hash);
/* reset DPMS values to inital ones */
DPMSSetTimeouts(dpy, standby, suspend, off);
XSync(dpy, 0);
return 0; return 0;
} }
+405
View File
@@ -0,0 +1,405 @@
/* See LICENSE file for license details. */
#define _XOPEN_SOURCE 500
#if HAVE_SHADOW_H
#include <shadow.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <spawn.h>
#include <sys/types.h>
#include <X11/extensions/Xrandr.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XF86keysym.h>
#include "arg.h"
#include "util.h"
char *argv0;
enum {
INIT,
INPUT,
FAILED,
NUMCOLS
};
struct lock {
int screen;
Window root, win;
Pixmap pmap;
unsigned long colors[NUMCOLS];
};
struct xrandr {
int active;
int evbase;
int errbase;
};
#include "config.h"
static void
die(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(1);
}
#ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h>
static void
dontkillme(void)
{
FILE *f;
const char oomfile[] = "/proc/self/oom_score_adj";
if (!(f = fopen(oomfile, "w"))) {
if (errno == ENOENT)
return;
die("slock: fopen %s: %s\n", oomfile, strerror(errno));
}
fprintf(f, "%d", OOM_SCORE_ADJ_MIN);
if (fclose(f)) {
if (errno == EACCES)
die("slock: unable to disable OOM killer. "
"Make sure to suid or sgid slock.\n");
else
die("slock: fclose %s: %s\n", oomfile, strerror(errno));
}
}
#endif
static const char *
gethash(void)
{
const char *hash;
struct passwd *pw;
/* Check if the current user has a password entry */
errno = 0;
if (!(pw = getpwuid(getuid()))) {
if (errno)
die("slock: getpwuid: %s\n", strerror(errno));
else
die("slock: cannot retrieve password entry\n");
}
hash = pw->pw_passwd;
#if HAVE_SHADOW_H
if (!strcmp(hash, "x")) {
struct spwd *sp;
if (!(sp = getspnam(pw->pw_name)))
die("slock: getspnam: cannot retrieve shadow entry. "
"Make sure to suid or sgid slock.\n");
hash = sp->sp_pwdp;
}
#else
if (!strcmp(hash, "*")) {
#ifdef __OpenBSD__
if (!(pw = getpwuid_shadow(getuid())))
die("slock: getpwnam_shadow: cannot retrieve shadow entry. "
"Make sure to suid or sgid slock.\n");
hash = pw->pw_passwd;
#else
die("slock: getpwuid: cannot retrieve shadow entry. "
"Make sure to suid or sgid slock.\n");
#endif /* __OpenBSD__ */
}
#endif /* HAVE_SHADOW_H */
return hash;
}
static void
readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash)
{
XRRScreenChangeNotifyEvent *rre;
char buf[32], passwd[256], *inputhash;
int num, screen, running, failure, oldc;
unsigned int len, color;
KeySym ksym;
XEvent ev;
len = 0;
running = 1;
failure = 0;
oldc = INIT;
while (running && !XNextEvent(dpy, &ev)) {
if (ev.type == KeyPress) {
explicit_bzero(&buf, sizeof(buf));
num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0);
if (IsKeypadKey(ksym)) {
if (ksym == XK_KP_Enter)
ksym = XK_Return;
else if (ksym >= XK_KP_0 && ksym <= XK_KP_9)
ksym = (ksym - XK_KP_0) + XK_0;
}
if (IsFunctionKey(ksym) ||
IsKeypadKey(ksym) ||
IsMiscFunctionKey(ksym) ||
IsPFKey(ksym) ||
IsPrivateKeypadKey(ksym))
continue;
switch (ksym) {
case XF86XK_AudioMute:
case XF86XK_AudioRaiseVolume:
case XF86XK_AudioLowerVolume:
case XF86XK_AudioMicMute:
case XF86XK_MonBrightnessUp:
case XF86XK_MonBrightnessDown:
XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break;
case XK_Return:
passwd[len] = '\0';
errno = 0;
if (!(inputhash = crypt(passwd, hash)))
fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
else
running = !!strcmp(inputhash, hash);
if (running) {
XBell(dpy, 100);
failure = 1;
}
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
break;
case XK_Escape:
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
break;
case XK_BackSpace:
if (len)
passwd[--len] = '\0';
break;
default:
if (num && !iscntrl((int)buf[0]) &&
(len + num < sizeof(passwd))) {
memcpy(passwd + len, buf, num);
len += num;
} else if (buf[0] == '\025') { /* ctrl-u clears input */
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
}
break;
}
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy,
locks[screen]->win,
locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win);
}
oldc = color;
}
} else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) {
rre = (XRRScreenChangeNotifyEvent*)&ev;
for (screen = 0; screen < nscreens; screen++) {
if (locks[screen]->win == rre->window) {
if (rre->rotation == RR_Rotate_90 ||
rre->rotation == RR_Rotate_270)
XResizeWindow(dpy, locks[screen]->win,
rre->height, rre->width);
else
XResizeWindow(dpy, locks[screen]->win,
rre->width, rre->height);
XClearWindow(dpy, locks[screen]->win);
break;
}
}
} else {
for (screen = 0; screen < nscreens; screen++)
XRaiseWindow(dpy, locks[screen]->win);
}
}
}
static struct lock *
lockscreen(Display *dpy, struct xrandr *rr, int screen)
{
char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
int i, ptgrab, kbgrab;
struct lock *lock;
XColor color, dummy;
XSetWindowAttributes wa;
Cursor invisible;
if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock))))
return NULL;
lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen);
for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy);
lock->colors[i] = color.pixel;
}
/* init */
wa.override_redirect = 1;
wa.background_pixel = lock->colors[INIT];
lock->win = XCreateWindow(dpy, lock->root, 0, 0,
DisplayWidth(dpy, lock->screen),
DisplayHeight(dpy, lock->screen),
0, DefaultDepth(dpy, lock->screen),
CopyFromParent,
DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0);
XDefineCursor(dpy, lock->win, invisible);
/* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */
for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) {
if (ptgrab != GrabSuccess) {
ptgrab = XGrabPointer(dpy, lock->root, False,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync,
GrabModeAsync, None, invisible, CurrentTime);
}
if (kbgrab != GrabSuccess) {
kbgrab = XGrabKeyboard(dpy, lock->root, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
}
/* input is grabbed: we can lock the screen */
if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
XMapRaised(dpy, lock->win);
if (rr->active)
XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
XSelectInput(dpy, lock->root, SubstructureNotifyMask);
return lock;
}
/* retry on AlreadyGrabbed but fail on other errors */
if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) ||
(kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess))
break;
usleep(100000);
}
/* we couldn't grab all input: fail out */
if (ptgrab != GrabSuccess)
fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n",
screen);
if (kbgrab != GrabSuccess)
fprintf(stderr, "slock: unable to grab keyboard for screen %d\n",
screen);
return NULL;
}
static void
usage(void)
{
die("usage: slock [-v] [cmd [arg ...]]\n");
}
int
main(int argc, char **argv) {
struct xrandr rr;
struct lock **locks;
struct passwd *pwd;
struct group *grp;
uid_t duid;
gid_t dgid;
const char *hash;
Display *dpy;
int s, nlocks, nscreens;
ARGBEGIN {
case 'v':
puts("slock-"VERSION);
return 0;
default:
usage();
} ARGEND
/* validate drop-user and -group */
errno = 0;
if (!(pwd = getpwnam(user)))
die("slock: getpwnam %s: %s\n", user,
errno ? strerror(errno) : "user entry not found");
duid = pwd->pw_uid;
errno = 0;
if (!(grp = getgrnam(group)))
die("slock: getgrnam %s: %s\n", group,
errno ? strerror(errno) : "group entry not found");
dgid = grp->gr_gid;
#ifdef __linux__
dontkillme();
#endif
hash = gethash();
errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
/* drop privileges */
if (setgroups(0, NULL) < 0)
die("slock: setgroups: %s\n", strerror(errno));
if (setgid(dgid) < 0)
die("slock: setgid: %s\n", strerror(errno));
if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno));
/* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
/* get number of screens in display "dpy" and blank them */
nscreens = ScreenCount(dpy);
if (!(locks = calloc(nscreens, sizeof(struct lock *))))
die("slock: out of memory\n");
for (nlocks = 0, s = 0; s < nscreens; s++) {
if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL)
nlocks++;
else
break;
}
XSync(dpy, 0);
/* did we manage to lock everything? */
if (nlocks != nscreens)
return 1;
/* run post-lock command */
if (argc > 0) {
pid_t pid;
extern char **environ;
int err = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ);
if (err) {
die("slock: failed to execute post-lock command: %s: %s\n",
argv[0], strerror(err));
}
}
/* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash);
return 0;
}
+153 -11
View File
@@ -6,7 +6,9 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <grp.h> #include <grp.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@@ -19,16 +21,25 @@
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/XF86keysym.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <Imlib2.h>
#include "arg.h" #include "arg.h"
#include "util.h" #include "util.h"
char *argv0; char *argv0;
static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
struct pam_conv pamc = {pam_conv, NULL};
char passwd[256];
enum { enum {
INIT, INIT,
INPUT, INPUT,
FAILED, FAILED,
PAM,
NUMCOLS NUMCOLS
}; };
@@ -36,6 +47,7 @@ struct lock {
int screen; int screen;
Window root, win; Window root, win;
Pixmap pmap; Pixmap pmap;
Pixmap bgmap;
unsigned long colors[NUMCOLS]; unsigned long colors[NUMCOLS];
}; };
@@ -47,6 +59,8 @@ struct xrandr {
#include "config.h" #include "config.h"
Imlib_Image image;
static void static void
die(const char *errstr, ...) die(const char *errstr, ...)
{ {
@@ -58,8 +72,32 @@ die(const char *errstr, ...)
exit(1); exit(1);
} }
static int
pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int retval = PAM_CONV_ERR;
for(int i=0; i<num_msg; i++) {
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
strncmp(msg[i]->msg, "Password: ", 10) == 0) {
struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
if (!resp_msg)
die("malloc failed\n");
char *password = malloc(strlen(passwd) + 1);
if (!password)
die("malloc failed\n");
memset(password, 0, strlen(passwd) + 1);
strcpy(password, passwd);
resp_msg->resp_retcode = 0;
resp_msg->resp = password;
resp[i] = resp_msg;
retval = PAM_SUCCESS;
}
}
return retval;
}
#ifdef __linux__ #ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h> #include <linux/oom.h>
static void static void
@@ -122,6 +160,8 @@ gethash(void)
} }
#endif /* HAVE_SHADOW_H */ #endif /* HAVE_SHADOW_H */
/* pam, store user name */
hash = pw->pw_name;
return hash; return hash;
} }
@@ -130,11 +170,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash) const char *hash)
{ {
XRRScreenChangeNotifyEvent *rre; XRRScreenChangeNotifyEvent *rre;
char buf[32], passwd[256], *inputhash; char buf[32];
int num, screen, running, failure, oldc; int num, screen, running, failure, oldc, retval;
unsigned int len, color; unsigned int len, color;
KeySym ksym; KeySym ksym;
XEvent ev; XEvent ev;
pam_handle_t *pamh;
len = 0; len = 0;
running = 1; running = 1;
@@ -158,13 +199,37 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
IsPrivateKeypadKey(ksym)) IsPrivateKeypadKey(ksym))
continue; continue;
switch (ksym) { switch (ksym) {
case XF86XK_AudioMute:
case XF86XK_AudioRaiseVolume:
case XF86XK_AudioLowerVolume:
case XF86XK_AudioMicMute:
case XF86XK_MonBrightnessUp:
case XF86XK_MonBrightnessDown:
XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break;
case XK_Return: case XK_Return:
passwd[len] = '\0'; passwd[len] = '\0';
errno = 0; errno = 0;
if (!(inputhash = crypt(passwd, hash))) retval = pam_start(pam_service, hash, &pamc, &pamh);
fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); color = PAM;
for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win);
XRaiseWindow(dpy, locks[screen]->win);
}
XSync(dpy, False);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0);
running = 1;
if (retval == PAM_SUCCESS)
running = 0;
else else
running = !!strcmp(inputhash, hash); fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
pam_end(pamh, retval);
if (running) { if (running) {
XBell(dpy, 100); XBell(dpy, 100);
failure = 1; failure = 1;
@@ -194,9 +259,10 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) { if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) { for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, if (locks[screen]->bgmap)
locks[screen]->win, XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
locks[screen]->colors[color]); else
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win); XClearWindow(dpy, locks[screen]->win);
} }
oldc = color; oldc = color;
@@ -239,6 +305,17 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
lock->screen = screen; lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen); lock->root = RootWindow(dpy, lock->screen);
if(image)
{
lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy, lock->screen));
imlib_context_set_colormap(DefaultColormap(dpy, lock->screen));
imlib_context_set_drawable(lock->bgmap);
imlib_render_image_on_drawable(0, 0);
imlib_free_image();
}
for (i = 0; i < NUMCOLS; i++) { for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy); colorname[i], &color, &dummy);
@@ -255,6 +332,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
CopyFromParent, CopyFromParent,
DefaultVisual(dpy, lock->screen), DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa); CWOverrideRedirect | CWBackPixel, &wa);
if(lock->bgmap)
XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0); &color, &color, 0, 0);
@@ -301,6 +380,28 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
return NULL; return NULL;
} }
static int
get_xss_sleep_lock_fd(void)
{
char *env_str, *end;
long env_val;
env_str = getenv("XSS_SLEEP_LOCK_FD");
if (!env_str || !*env_str)
return -1;
errno = 0;
env_val = strtol(env_str, &end, 10);
if (errno ||
*end ||
(env_val < 0 || env_val > INT_MAX)) {
fprintf(stderr, "slock: strtol $XSS_SLEEP_LOCK_FD: %s\n",
errno ? strerror(errno) : "invalid value");
return -1;
}
return (int)env_val;
}
static void static void
usage(void) usage(void)
{ {
@@ -318,6 +419,7 @@ main(int argc, char **argv) {
const char *hash; const char *hash;
Display *dpy; Display *dpy;
int s, nlocks, nscreens; int s, nlocks, nscreens;
int lockfd;
ARGBEGIN { ARGBEGIN {
case 'v': case 'v':
@@ -327,6 +429,18 @@ main(int argc, char **argv) {
usage(); usage();
} ARGEND } ARGEND
lockfd = get_xss_sleep_lock_fd();
if (lockfd >= 0) {
int flags = fcntl(lockfd, F_GETFD);
if (flags < 0) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_GETFD: %s\n",
strerror(errno));
} else if (fcntl(lockfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_SETFD: %s\n",
strerror(errno));
}
}
/* validate drop-user and -group */ /* validate drop-user and -group */
errno = 0; errno = 0;
if (!(pwd = getpwnam(user))) if (!(pwd = getpwnam(user)))
@@ -343,10 +457,9 @@ main(int argc, char **argv) {
dontkillme(); dontkillme();
#endif #endif
/* the contents of hash are used to transport the current user name */
hash = gethash(); hash = gethash();
errno = 0; errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n"); die("slock: cannot open display\n");
@@ -359,6 +472,32 @@ main(int argc, char **argv) {
if (setuid(duid) < 0) if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno)); die("slock: setuid: %s\n", strerror(errno));
/* Load picture */
Imlib_Image buffer = imlib_load_image(background_image);
imlib_context_set_image(buffer);
int background_image_width = imlib_image_get_width();
int background_image_height = imlib_image_get_height();
/* Create an image to be rendered */
Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
image = imlib_create_image(scr->width, scr->height);
imlib_context_set_image(image);
/* Fill the image for every X monitor */
XRRMonitorInfo *monitors;
int number_of_monitors;
monitors = XRRGetMonitors(dpy, RootWindow(dpy, XScreenNumberOfScreen(scr)), True, &number_of_monitors);
int i;
for (i = 0; i < number_of_monitors; i++) {
imlib_blend_image_onto_image(buffer, 0, 0, 0, background_image_width, background_image_height, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
}
/* Clean up */
imlib_context_set_image(buffer);
imlib_free_image();
imlib_context_set_image(image);
/* check for Xrandr support */ /* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
@@ -378,6 +517,9 @@ main(int argc, char **argv) {
if (nlocks != nscreens) if (nlocks != nscreens)
return 1; return 1;
if (lockfd >= 0 && close(lockfd) < 0)
fprintf(stderr, "slock: close $XSS_SLEEP_LOCK_FD: %s\n", strerror(errno));
/* run post-lock command */ /* run post-lock command */
if (argc > 0) { if (argc > 0) {
pid_t pid; pid_t pid;
+8 -9
View File
@@ -1,11 +1,10 @@
--- slock.c --- slock.c
+++ slock.c +++ slock.c
@@ -186,7 +186,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, @@ -307,6 +308,7 @@ main(int argc, char **argv) {
case XF86XK_AudioStop: const char *hash;
case XF86XK_AudioPrev: Display *dpy;
case XF86XK_AudioNext: int s, nlocks, nscreens;
- XSendEvent(dpy, locks[0]->root, True, KeyPressMask, &ev); + CARD16 standby, suspend, off;
+ XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break; ARGBEGIN {
case XK_Return: case 'v':
passwd[len] = '\0';