From e9e8ad1b67df4676cce3e15715544f3aa8abaaa1 Mon Sep 17 00:00:00 2001 From: odweta Date: Sun, 25 Oct 2026 04:40:51 +0100 Subject: [PATCH] update suckless --- .xinitrc | 52 ++- dwm/config/keybinds.h | 8 +- dwm/config/scratchpads.h | 2 +- slock/config.def.h | 16 +- slock/config.def.h.BEFORE | 13 + slock/config.def.h.orig | 19 + slock/config.def.h.rej | 9 + slock/config.h | 16 +- slock/config.mk | 2 +- slock/config.mk.orig | 26 ++ slock/config.mk.rej | 11 + slock/patches/slock-02-xss-lock.diff | 88 ++++ slock/patches/slock-03-background_image.diff | 150 +++++++ slock/patches/slock-03-pam_auth.diff | 155 +++++++ slock/patches/slock-04-dpms.diff | 63 +++ slock/slock.c | 175 +++++++- slock/slock.c.BEFORE | 405 +++++++++++++++++++ slock/slock.c.orig | 164 +++++++- slock/slock.c.rej | 17 +- 19 files changed, 1339 insertions(+), 52 deletions(-) create mode 100644 slock/config.def.h.BEFORE create mode 100644 slock/config.def.h.orig create mode 100644 slock/config.def.h.rej create mode 100644 slock/config.mk.orig create mode 100644 slock/config.mk.rej create mode 100644 slock/patches/slock-02-xss-lock.diff create mode 100644 slock/patches/slock-03-background_image.diff create mode 100644 slock/patches/slock-03-pam_auth.diff create mode 100644 slock/patches/slock-04-dpms.diff create mode 100644 slock/slock.c.BEFORE diff --git a/.xinitrc b/.xinitrc index e0d8311..01d3c8a 100755 --- a/.xinitrc +++ b/.xinitrc @@ -20,19 +20,53 @@ xinput list --name-only | while IFS= read -r device; do esac done -# Start desktop services -bluetoothctl power off & -picom & -xbindkeys & -xss-lock -l slock & -feh --bg-scale "$HOME/Obrázky/wallpapers/glados.jpg" & - dwmblocks & +# i really need it :( +export GPG_TTY=$(tty) + exec dbus-run-session -- sh -c ' - GPG_TTY=$(tty) - pipewire & + 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 ' diff --git a/dwm/config/keybinds.h b/dwm/config/keybinds.h index 464ff58..31b2476 100644 --- a/dwm/config/keybinds.h +++ b/dwm/config/keybinds.h @@ -1,12 +1,12 @@ /* keybinds */ -/** +/** * 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 * 2x with ShitMask * = 38 * 2 = 76 different actions can be bound - * (+ however many Fn keys you have) - * + * (+ however many Fn keys you have) + * * 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 */ @@ -15,7 +15,7 @@ static const Key keys[] = { // essential apps { MODKEY, XK_space, spawn, {.v = dmenucmd } }, { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_m, spawn, {.v = djcmd } }, +// { MODKEY, XK_m, spawn, {.v = djcmd } }, { MODKEY, XK_w, spawn, {.v = webbrowsercmd } }, // window management { MODKEY, XK_j, focusstack, {.i = +1 } }, diff --git a/dwm/config/scratchpads.h b/dwm/config/scratchpads.h index f600080..8cbbe89 100644 --- a/dwm/config/scratchpads.h +++ b/dwm/config/scratchpads.h @@ -10,7 +10,7 @@ const char *spcmd0[] = {"st", "-n", "spterm", "-g", "120x34", NULL }; const char *spcmd1[] = {"thunar", NULL }; const char *spcmd2[] = {"keepassxc", 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 }; static Sp scratchpads[] = { diff --git a/slock/config.def.h b/slock/config.def.h index b051a85..fe3d752 100644 --- a/slock/config.def.h +++ b/slock/config.def.h @@ -3,10 +3,20 @@ static const char *user = "imp"; static const char *group = "imp"; static const char *colorname[NUMCOLS] = { - [INIT] = "black", /* after initialization */ - [INPUT] = "#735e97", /* during input */ - [FAILED] = "#CC3333", /* wrong password */ + [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"; + +/* time in seconds before the monitor shuts down */ +static const int monitortime = 10; diff --git a/slock/config.def.h.BEFORE b/slock/config.def.h.BEFORE new file mode 100644 index 0000000..8b206ab --- /dev/null +++ b/slock/config.def.h.BEFORE @@ -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; + diff --git a/slock/config.def.h.orig b/slock/config.def.h.orig new file mode 100644 index 0000000..bd9ac46 --- /dev/null +++ b/slock/config.def.h.orig @@ -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"; diff --git a/slock/config.def.h.rej b/slock/config.def.h.rej new file mode 100644 index 0000000..89bee35 --- /dev/null +++ b/slock/config.def.h.rej @@ -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; diff --git a/slock/config.h b/slock/config.h index b051a85..fe3d752 100644 --- a/slock/config.h +++ b/slock/config.h @@ -3,10 +3,20 @@ static const char *user = "imp"; static const char *group = "imp"; static const char *colorname[NUMCOLS] = { - [INIT] = "black", /* after initialization */ - [INPUT] = "#735e97", /* during input */ - [FAILED] = "#CC3333", /* wrong password */ + [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"; + +/* time in seconds before the monitor shuts down */ +static const int monitortime = 10; diff --git a/slock/config.mk b/slock/config.mk index 4e4abd0..8d856ec 100644 --- a/slock/config.mk +++ b/slock/config.mk @@ -15,7 +15,7 @@ X11LIB = $(shell $(PKG_CONFIG) --libs x11 xft xrandr xinerama fontconfig freetyp # includes and libs INCS = ${X11INC} -LIBS = -lc -lcrypt ${X11LIB} +LIBS = -lc -lcrypt -lpam -lImlib2 -lXext ${X11LIB} # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/slock/config.mk.orig b/slock/config.mk.orig new file mode 100644 index 0000000..d09a53b --- /dev/null +++ b/slock/config.mk.orig @@ -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 diff --git a/slock/config.mk.rej b/slock/config.mk.rej new file mode 100644 index 0000000..c085e25 --- /dev/null +++ b/slock/config.mk.rej @@ -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 diff --git a/slock/patches/slock-02-xss-lock.diff b/slock/patches/slock-02-xss-lock.diff new file mode 100644 index 0000000..fbf3c55 --- /dev/null +++ b/slock/patches/slock-02-xss-lock.diff @@ -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 + #include ++#include + #include ++#include + #include + #include + #include +@@ -59,7 +61,6 @@ die(const char *errstr, ...) + } + + #ifdef __linux__ +-#include + #include + + 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; + diff --git a/slock/patches/slock-03-background_image.diff b/slock/patches/slock-03-background_image.diff new file mode 100644 index 0000000..5202fd9 --- /dev/null +++ b/slock/patches/slock-03-background_image.diff @@ -0,0 +1,150 @@ +From 1c5a5383a1cf3351fe9c80a21cfbc98c5ec4355d Mon Sep 17 00:00:00 2001 +From: Yan Doroshenko +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 + #include + #include ++#include + + #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 + + diff --git a/slock/patches/slock-03-pam_auth.diff b/slock/patches/slock-03-pam_auth.diff new file mode 100644 index 0000000..d1ba9e6 --- /dev/null +++ b/slock/patches/slock-03-pam_auth.diff @@ -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 + #include + #include ++#include ++#include + + #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; imsg_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 + #include +@@ -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"); + diff --git a/slock/patches/slock-04-dpms.diff b/slock/patches/slock-04-dpms.diff new file mode 100644 index 0000000..4c35b09 --- /dev/null +++ b/slock/patches/slock-04-dpms.diff @@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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; + } + diff --git a/slock/slock.c b/slock/slock.c index f556d34..bee808b 100644 --- a/slock/slock.c +++ b/slock/slock.c @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -16,20 +18,29 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #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 }; @@ -37,6 +48,7 @@ struct lock { int screen; Window root, win; Pixmap pmap; + Pixmap bgmap; unsigned long colors[NUMCOLS]; }; @@ -48,6 +60,8 @@ struct xrandr { #include "config.h" +Imlib_Image image; + static void die(const char *errstr, ...) { @@ -59,8 +73,32 @@ 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; imsg_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 #include static void @@ -123,6 +161,8 @@ gethash(void) } #endif /* HAVE_SHADOW_H */ + /* pam, store user name */ + hash = pw->pw_name; return hash; } @@ -131,11 +171,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; @@ -170,10 +211,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; @@ -203,9 +260,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; @@ -248,6 +306,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); @@ -264,6 +333,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); @@ -310,6 +381,28 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) 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) { @@ -327,6 +420,8 @@ main(int argc, char **argv) { const char *hash; Display *dpy; int s, nlocks, nscreens; + CARD16 standby, suspend, off; + int lockfd; ARGBEGIN { case 'v': @@ -336,6 +431,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))) @@ -352,10 +459,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"); @@ -368,6 +474,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); @@ -387,6 +519,23 @@ 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)); + + /* 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) { pid_t pid; @@ -401,5 +550,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; } diff --git a/slock/slock.c.BEFORE b/slock/slock.c.BEFORE new file mode 100644 index 0000000..f556d34 --- /dev/null +++ b/slock/slock.c.BEFORE @@ -0,0 +1,405 @@ +/* See LICENSE file for license details. */ +#define _XOPEN_SOURCE 500 +#if HAVE_SHADOW_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + +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; +} diff --git a/slock/slock.c.orig b/slock/slock.c.orig index f16781f..369cb7d 100644 --- a/slock/slock.c.orig +++ b/slock/slock.c.orig @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -19,16 +21,25 @@ #include #include #include +#include +#include +#include +#include #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 }; @@ -36,6 +47,7 @@ struct lock { int screen; Window root, win; Pixmap pmap; + Pixmap bgmap; unsigned long colors[NUMCOLS]; }; @@ -47,6 +59,8 @@ struct xrandr { #include "config.h" +Imlib_Image image; + static void die(const char *errstr, ...) { @@ -58,8 +72,32 @@ 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; imsg_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 #include static void @@ -122,6 +160,8 @@ gethash(void) } #endif /* HAVE_SHADOW_H */ + /* pam, store user name */ + hash = pw->pw_name; return hash; } @@ -130,11 +170,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; @@ -158,13 +199,37 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, 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)); + 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; @@ -194,9 +259,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; @@ -239,6 +305,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); @@ -255,6 +332,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); @@ -301,6 +380,28 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) 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 +419,7 @@ main(int argc, char **argv) { const char *hash; Display *dpy; int s, nlocks, nscreens; + int lockfd; ARGBEGIN { case 'v': @@ -327,6 +429,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))) @@ -343,10 +457,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"); @@ -359,6 +472,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); @@ -378,6 +517,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; diff --git a/slock/slock.c.rej b/slock/slock.c.rej index 891986a..c3eab29 100644 --- a/slock/slock.c.rej +++ b/slock/slock.c.rej @@ -1,11 +1,10 @@ --- slock.c +++ slock.c -@@ -186,7 +186,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, - case XF86XK_AudioStop: - case XF86XK_AudioPrev: - case XF86XK_AudioNext: -- XSendEvent(dpy, locks[0]->root, True, KeyPressMask, &ev); -+ XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev); - break; - case XK_Return: - passwd[len] = '\0'; +@@ -307,6 +308,7 @@ main(int argc, char **argv) { + const char *hash; + Display *dpy; + int s, nlocks, nscreens; ++ CARD16 standby, suspend, off; + + ARGBEGIN { + case 'v':