diff options
Diffstat (limited to 'core/slock')
| -rw-r--r-- | core/slock/LICENSE | 25 | ||||
| -rw-r--r-- | core/slock/Makefile | 46 | ||||
| -rw-r--r-- | core/slock/README | 24 | ||||
| -rw-r--r-- | core/slock/arg.h | 65 | ||||
| -rw-r--r-- | core/slock/config.def.h | 12 | ||||
| -rw-r--r-- | core/slock/config.mk | 29 | ||||
| -rw-r--r-- | core/slock/explicit_bzero.c | 19 | ||||
| -rw-r--r-- | core/slock/patches/slock-blur_pixelated_screen-1.4.diff | 356 | ||||
| -rw-r--r-- | core/slock/patches/slock-dwmlogo-20210324.diff | 246 | ||||
| -rw-r--r-- | core/slock/patches/slock-dwmlogoandblurscreen-1.0.diff | 336 | ||||
| -rw-r--r-- | core/slock/patches/slock-foreground-image-20211210.diff | 81 | ||||
| -rw-r--r-- | core/slock/slock.1 | 45 | ||||
| -rw-r--r-- | core/slock/slock.c | 576 | ||||
| -rw-r--r-- | core/slock/util.h | 2 |
14 files changed, 1862 insertions, 0 deletions
diff --git a/core/slock/LICENSE b/core/slock/LICENSE new file mode 100644 index 0000000..cb52dba --- /dev/null +++ b/core/slock/LICENSE @@ -0,0 +1,25 @@ +MIT/X Consortium License + +© 2015-2016 Markus Teich <markus.teich@stusta.mhn.de> +© 2014 Dimitris Papastamos <sin@2f30.org> +© 2006-2014 Anselm R Garbe <anselm@garbe.us> +© 2014-2016 Laslo Hunhold <dev@frign.de> +© 2016-2023 Hiltjo Posthuma <hiltjo@codemadness.org> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/core/slock/Makefile b/core/slock/Makefile new file mode 100644 index 0000000..6d74b21 --- /dev/null +++ b/core/slock/Makefile @@ -0,0 +1,46 @@ +# slock - simple screen locker +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = slock.c ${COMPATSRC} +OBJ = ${SRC:.c=.o} + +all: slock + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk arg.h util.h + +config.h: + cp config.def.h $@ + +slock: ${OBJ} + ${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + rm -f slock ${OBJ} slock-${VERSION}.tar.gz + +dist: clean + mkdir -p slock-${VERSION} + cp -R LICENSE Makefile README slock.1 config.mk \ + ${SRC} config.def.h arg.h util.h slock-${VERSION} + tar -cf slock-${VERSION}.tar slock-${VERSION} + gzip slock-${VERSION}.tar + rm -rf slock-${VERSION} + +install: all + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f slock ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/slock + chmod u+s ${DESTDIR}${PREFIX}/bin/slock + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" <slock.1 >${DESTDIR}${MANPREFIX}/man1/slock.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/slock.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/slock + rm -f ${DESTDIR}${MANPREFIX}/man1/slock.1 + +.PHONY: all clean dist install uninstall diff --git a/core/slock/README b/core/slock/README new file mode 100644 index 0000000..dcacd01 --- /dev/null +++ b/core/slock/README @@ -0,0 +1,24 @@ +slock - simple screen locker +============================ +simple screen locker utility for X. + + +Requirements +------------ +In order to build slock you need the Xlib header files. + + +Installation +------------ +Edit config.mk to match your local setup (slock is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install slock +(if necessary as root): + + make clean install + + +Running slock +------------- +Simply invoke the 'slock' command. To get out of it, enter your password. diff --git a/core/slock/arg.h b/core/slock/arg.h new file mode 100644 index 0000000..0b23c53 --- /dev/null +++ b/core/slock/arg.h @@ -0,0 +1,65 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] == '-'\ + && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +/* Handles obsolete -NUM syntax */ +#define ARGNUM case '0':\ + case '1':\ + case '2':\ + case '3':\ + case '4':\ + case '5':\ + case '6':\ + case '7':\ + case '8':\ + case '9' + +#define ARGEND }\ + } + +#define ARGC() argc_ + +#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX)) + +#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ + ((x), abort(), (char *)0) :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ + (char *)0 :\ + (brk_ = 1, (argv[0][1] != '\0')?\ + (&argv[0][1]) :\ + (argc--, argv++, argv[0]))) + +#define LNGARG() &argv[0][0] + +#endif diff --git a/core/slock/config.def.h b/core/slock/config.def.h new file mode 100644 index 0000000..9855e21 --- /dev/null +++ b/core/slock/config.def.h @@ -0,0 +1,12 @@ +/* user and group to drop privileges to */ +static const char *user = "nobody"; +static const char *group = "nogroup"; + +static const char *colorname[NUMCOLS] = { + [INIT] = "black", /* after initialization */ + [INPUT] = "#005577", /* during input */ + [FAILED] = "#CC3333", /* wrong password */ +}; + +/* treat a cleared input like a wrong password (color) */ +static const int failonclear = 1; diff --git a/core/slock/config.mk b/core/slock/config.mk new file mode 100644 index 0000000..5c17d5e --- /dev/null +++ b/core/slock/config.mk @@ -0,0 +1,29 @@ +# slock version +VERSION = 1.6 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +X11INC = /usr/X11R6/include +X11LIB = /usr/X11R6/lib + +# includes and libs +INCS = -I. -I/usr/include -I${X11INC} $(shell pkg-config --cflags xft imlib2) +LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr $(shell pkg-config --libs xft imlib2) + +# 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 + +# On OpenBSD and Darwin remove -lcrypt from LIBS +#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXext -lXrandr +# On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS +# On NetBSD add -D_NETBSD_SOURCE to CPPFLAGS +#CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_NETBSD_SOURCE +# On OpenBSD set COMPATSRC to empty +#COMPATSRC = diff --git a/core/slock/explicit_bzero.c b/core/slock/explicit_bzero.c new file mode 100644 index 0000000..3e33ca8 --- /dev/null +++ b/core/slock/explicit_bzero.c @@ -0,0 +1,19 @@ +/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */ +/* + * Public domain. + * Written by Matthew Dempsky. + */ + +#include <string.h> + +__attribute__((weak)) void +__explicit_bzero_hook(void *buf, size_t len) +{ +} + +void +explicit_bzero(void *buf, size_t len) +{ + memset(buf, 0, len); + __explicit_bzero_hook(buf, len); +} diff --git a/core/slock/patches/slock-blur_pixelated_screen-1.4.diff b/core/slock/patches/slock-blur_pixelated_screen-1.4.diff new file mode 100644 index 0000000..90d9c16 --- /dev/null +++ b/core/slock/patches/slock-blur_pixelated_screen-1.4.diff @@ -0,0 +1,356 @@ +From 36a4863f9a399740aaf8b1e01926485c0a055e1c Mon Sep 17 00:00:00 2001 +From: Lars Niesen <iah71niesen@gso-koeln.de> +Date: Wed, 29 Apr 2020 13:52:42 +0200 +Subject: [PATCH 1/8] Added Bg patch and screenshot capabilities + +--- + config.mk | 2 +- + slock.c | 35 +++++++++++++++++++++++++++++++---- + 2 files changed, 32 insertions(+), 5 deletions(-) + +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..7c63f34 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_image(image); ++ 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); +@@ -354,7 +372,16 @@ main(int argc, char **argv) { + die("slock: setgid: %s\n", strerror(errno)); + if (setuid(duid) < 0) + die("slock: setuid: %s\n", strerror(errno)); +- ++ ++ /*Create screenshot Image*/ ++ Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy)); ++ image = imlib_create_image(scr->width,scr->height); ++ imlib_context_set_image(image); ++ imlib_context_set_display(dpy); ++ imlib_context_set_visual(DefaultVisual(dpy,0)); ++ imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr))); ++ imlib_copy_drawable_to_image(0,0,0,scr->width,scr->height,0,0,1); ++ + /* check for Xrandr support */ + rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); + +-- +2.27.0 + + +From 9d89604ac52b0949d047dae2f9b78cb5085ee1a2 Mon Sep 17 00:00:00 2001 +From: Lars Niesen <iah71niesen@gso-koeln.de> +Date: Wed, 29 Apr 2020 14:15:59 +0200 +Subject: [PATCH 2/8] Added blur function + +--- + config.def.h | 3 +++ + slock.c | 3 ++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index c8e52d6..fcc1b39 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; ++ ++/*Set Blur radius*/ ++static const int blurRadius=5; +\ No newline at end of file +diff --git a/slock.c b/slock.c +index 7c63f34..0f24cd7 100644 +--- a/slock.c ++++ b/slock.c +@@ -372,7 +372,7 @@ main(int argc, char **argv) { + die("slock: setgid: %s\n", strerror(errno)); + if (setuid(duid) < 0) + die("slock: setuid: %s\n", strerror(errno)); +- ++ + /*Create screenshot Image*/ + Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy)); + image = imlib_create_image(scr->width,scr->height); +@@ -381,6 +381,7 @@ main(int argc, char **argv) { + imlib_context_set_visual(DefaultVisual(dpy,0)); + imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr))); + imlib_copy_drawable_to_image(0,0,0,scr->width,scr->height,0,0,1); ++ imlib_image_blur(blurRadius); + + /* check for Xrandr support */ + rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); +-- +2.27.0 + + +From 069aabd7e30244befd4efe74c85d3468ed076c21 Mon Sep 17 00:00:00 2001 +From: Lars Niesen <iah71niesen@gso-koeln.de> +Date: Wed, 29 Apr 2020 17:33:09 +0200 +Subject: [PATCH 4/8] added Pixelation + +--- + config.def.h | 3 ++- + slock.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index fcc1b39..1c1aef3 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,4 +12,5 @@ static const char *colorname[NUMCOLS] = { + static const int failonclear = 1; + + /*Set Blur radius*/ +-static const int blurRadius=5; +\ No newline at end of file ++static const int blurRadius=0; ++static const int pixelSize=5; +diff --git a/slock.c b/slock.c +index 0f24cd7..33ca569 100644 +--- a/slock.c ++++ b/slock.c +@@ -381,7 +381,49 @@ main(int argc, char **argv) { + imlib_context_set_visual(DefaultVisual(dpy,0)); + imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr))); + imlib_copy_drawable_to_image(0,0,0,scr->width,scr->height,0,0,1); ++ ++ /*Blur function*/ + imlib_image_blur(blurRadius); ++ ++ ++ /*Pixelation*/ ++ int width = scr->width; ++ int height = scr->height; ++ ++ for(int y = 0; y < height; y += pixelSize) ++ { ++ for(int x = 0; x < width; x += pixelSize) ++ { ++ int red = 0; ++ int green = 0; ++ int blue = 0; ++ ++ Imlib_Color pixel; ++ Imlib_Color* pp; ++ pp = &pixel; ++ for(int j = 0; j < pixelSize && j < height; j++) ++ { ++ for(int i = 0; i < pixelSize && i < width; i++) ++ { ++ imlib_image_query_pixel(x+i,y+j,pp); ++ red += pixel.red; ++ green += pixel.green; ++ blue += pixel.blue; ++ } ++ } ++ red /= (pixelSize*pixelSize); ++ green /= (pixelSize*pixelSize); ++ blue /= (pixelSize*pixelSize); ++ printf("R/G/B: %i/%i/%i\n",red,green,blue); ++ imlib_context_set_color(red,green,blue,pixel.alpha); ++ imlib_image_fill_rectangle(x,y,pixelSize,pixelSize); ++ red = 0; ++ green = 0; ++ blue = 0; ++ } ++ } ++ ++ + + /* check for Xrandr support */ + rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); +-- +2.27.0 + + +From 109bac015c1c7fbf8440fb42588fe7e0e9cb5e62 Mon Sep 17 00:00:00 2001 +From: Lars Niesen <iah71niesen@gso-koeln.de> +Date: Wed, 29 Apr 2020 17:42:39 +0200 +Subject: [PATCH 6/8] removed debug printf + +--- + slock.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/slock.c b/slock.c +index 33ca569..f54c459 100644 +--- a/slock.c ++++ b/slock.c +@@ -414,7 +414,6 @@ main(int argc, char **argv) { + red /= (pixelSize*pixelSize); + green /= (pixelSize*pixelSize); + blue /= (pixelSize*pixelSize); +- printf("R/G/B: %i/%i/%i\n",red,green,blue); + imlib_context_set_color(red,green,blue,pixel.alpha); + imlib_image_fill_rectangle(x,y,pixelSize,pixelSize); + red = 0; +-- +2.27.0 + + +From a13a0f4ac86f82e4dff145b7ebd93e52d07492c9 Mon Sep 17 00:00:00 2001 +From: Lars Niesen <iah71niesen@gso-koeln.de> +Date: Sun, 3 May 2020 18:03:38 +0200 +Subject: [PATCH 7/8] Changed compilerflag to fast + +--- + config.mk | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config.mk b/config.mk +index 987819e..d0c2f01 100644 +--- a/config.mk ++++ b/config.mk +@@ -16,7 +16,7 @@ LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lImlib2 + + # flags + CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H +-CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} ++CFLAGS = -std=c99 -pedantic -Wall -Ofast ${INCS} ${CPPFLAGS} + LDFLAGS = -s ${LIBS} + COMPATSRC = explicit_bzero.c + +-- +2.27.0 + + +From 31a7001c4954606c066cc3df4318fafd6d216bcd Mon Sep 17 00:00:00 2001 +From: Lars Niesen <iah71niesen@gso-koeln.de> +Date: Mon, 4 May 2020 10:00:40 +0200 +Subject: [PATCH 8/8] Added defines for BLUR/PIXELATION to remove from code by + compilation + +--- + config.def.h | 11 ++++++++--- + slock.c | 9 ++++++--- + 2 files changed, 14 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c1aef3..5407953 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -11,6 +11,11 @@ static const char *colorname[NUMCOLS] = { + /* treat a cleared input like a wrong password (color) */ + static const int failonclear = 1; + +-/*Set Blur radius*/ +-static const int blurRadius=0; +-static const int pixelSize=5; ++/*Enable blur*/ ++#define BLUR ++/*Set blur radius*/ ++static const int blurRadius=5; ++/*Enable Pixelation*/ ++//#define PIXELATION ++/*Set pixelation radius*/ ++static const int pixelSize=0; +diff --git a/slock.c b/slock.c +index f54c459..1a4d6e3 100644 +--- a/slock.c ++++ b/slock.c +@@ -381,11 +381,14 @@ main(int argc, char **argv) { + imlib_context_set_visual(DefaultVisual(dpy,0)); + imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr))); + imlib_copy_drawable_to_image(0,0,0,scr->width,scr->height,0,0,1); +- ++ ++#ifdef BLUR ++ + /*Blur function*/ + imlib_image_blur(blurRadius); ++#endif // BLUR + +- ++#ifdef PIXELATION + /*Pixelation*/ + int width = scr->width; + int height = scr->height; +@@ -423,7 +426,7 @@ main(int argc, char **argv) { + } + + +- ++#endif + /* check for Xrandr support */ + rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); + +-- +2.27.0 + diff --git a/core/slock/patches/slock-dwmlogo-20210324.diff b/core/slock/patches/slock-dwmlogo-20210324.diff new file mode 100644 index 0000000..90625ea --- /dev/null +++ b/core/slock/patches/slock-dwmlogo-20210324.diff @@ -0,0 +1,246 @@ +diff --git a/config.def.h b/config.def.h +index 9855e21..0940fb8 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,10 +3,30 @@ static const char *user = "nobody"; + static const char *group = "nogroup"; + + static const char *colorname[NUMCOLS] = { +- [INIT] = "black", /* after initialization */ ++ [BACKGROUND] = "black", /* after initialization */ ++ [INIT] = "#2d2d2d", /* after initialization */ + [INPUT] = "#005577", /* during input */ + [FAILED] = "#CC3333", /* wrong password */ + }; + + /* treat a cleared input like a wrong password (color) */ + static const int failonclear = 1; ++ ++/* insert grid pattern with scale 1:1, the size can be changed with logosize */ ++static const int logosize = 75; ++static const int logow = 12; /* grid width and height for right center alignment*/ ++static const int logoh = 6; ++ ++static XRectangle rectangles[9] = { ++ /* x y w h */ ++ { 0, 3, 1, 3 }, ++ { 1, 3, 2, 1 }, ++ { 0, 5, 8, 1 }, ++ { 3, 0, 1, 5 }, ++ { 5, 3, 1, 2 }, ++ { 7, 3, 1, 2 }, ++ { 8, 3, 4, 1 }, ++ { 9, 4, 1, 2 }, ++ { 11, 4, 1, 2 }, ++ ++}; +diff --git a/config.mk b/config.mk +index 74429ae..08356e8 100644 +--- a/config.mk ++++ b/config.mk +@@ -10,12 +10,20 @@ MANPREFIX = ${PREFIX}/share/man + X11INC = /usr/X11R6/include + X11LIB = /usr/X11R6/lib + ++# Xinerama, comment if you don't want it ++XINERAMALIBS = -lXinerama ++XINERAMAFLAGS = -DXINERAMA ++ ++# freetype ++FREETYPELIBS = -lXft ++FREETYPEINC = /usr/include/freetype2 ++ + # includes and libs +-INCS = -I. -I/usr/include -I${X11INC} +-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr ++INCS = -I. -I/usr/include -I${X11INC} -I${FREETYPEINC} ++LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXext -lXrandr + + # flags +-CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H ++CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H ${XINERAMAFLAGS} + CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} + LDFLAGS = -s ${LIBS} + COMPATSRC = explicit_bzero.c +diff --git a/slock.c b/slock.c +index 5ae738c..3ea9b7f 100644 +--- a/slock.c ++++ b/slock.c +@@ -1,5 +1,6 @@ + /* See LICENSE file for license details. */ +-#define _XOPEN_SOURCE 500 ++#define _XOPEN_SOURCE 500 ++#define LENGTH(X) (sizeof X / sizeof X[0]) + #if HAVE_SHADOW_H + #include <shadow.h> + #endif +@@ -15,9 +16,13 @@ + #include <unistd.h> + #include <sys/types.h> + #include <X11/extensions/Xrandr.h> ++#ifdef XINERAMA ++#include <X11/extensions/Xinerama.h> ++#endif + #include <X11/keysym.h> + #include <X11/Xlib.h> + #include <X11/Xutil.h> ++#include <X11/Xft/Xft.h> + + #include "arg.h" + #include "util.h" +@@ -25,17 +30,25 @@ + char *argv0; + + enum { ++ BACKGROUND, + INIT, + INPUT, + FAILED, + NUMCOLS + }; + ++#include "config.h" ++ + struct lock { + int screen; + Window root, win; + Pixmap pmap; + unsigned long colors[NUMCOLS]; ++ unsigned int x, y; ++ unsigned int xoff, yoff, mw, mh; ++ Drawable drawable; ++ GC gc; ++ XRectangle rectangles[LENGTH(rectangles)]; + }; + + struct xrandr { +@@ -44,8 +57,6 @@ struct xrandr { + int errbase; + }; + +-#include "config.h" +- + static void + die(const char *errstr, ...) + { +@@ -124,6 +135,32 @@ gethash(void) + return hash; + } + ++static void ++resizerectangles(struct lock *lock) ++{ ++ int i; ++ ++ for (i = 0; i < LENGTH(rectangles); i++){ ++ lock->rectangles[i].x = (rectangles[i].x * logosize) ++ + lock->xoff + ((lock->mw) / 2) - (logow / 2 * logosize); ++ lock->rectangles[i].y = (rectangles[i].y * logosize) ++ + lock->yoff + ((lock->mh) / 2) - (logoh / 2 * logosize); ++ lock->rectangles[i].width = rectangles[i].width * logosize; ++ lock->rectangles[i].height = rectangles[i].height * logosize; ++ } ++} ++ ++static void ++drawlogo(Display *dpy, struct lock *lock, int color) ++{ ++ XSetForeground(dpy, lock->gc, lock->colors[BACKGROUND]); ++ XFillRectangle(dpy, lock->drawable, lock->gc, 0, 0, lock->x, lock->y); ++ XSetForeground(dpy, lock->gc, lock->colors[color]); ++ XFillRectangles(dpy, lock->drawable, lock->gc, lock->rectangles, LENGTH(rectangles)); ++ XCopyArea(dpy, lock->drawable, lock->win, lock->gc, 0, 0, lock->x, lock->y, 0, 0); ++ XSync(dpy, False); ++} ++ + static void + readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, + const char *hash) +@@ -190,10 +227,7 @@ 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]); +- XClearWindow(dpy, locks[screen]->win); ++ drawlogo(dpy, locks[screen], color); + } + oldc = color; + } +@@ -228,6 +262,10 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) + XColor color, dummy; + XSetWindowAttributes wa; + Cursor invisible; ++#ifdef XINERAMA ++ XineramaScreenInfo *info; ++ int n; ++#endif + + if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) + return NULL; +@@ -241,12 +279,31 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) + lock->colors[i] = color.pixel; + } + ++ lock->x = DisplayWidth(dpy, lock->screen); ++ lock->y = DisplayHeight(dpy, lock->screen); ++#ifdef XINERAMA ++ if ((info = XineramaQueryScreens(dpy, &n))) { ++ lock->xoff = info[0].x_org; ++ lock->yoff = info[0].y_org; ++ lock->mw = info[0].width; ++ lock->mh = info[0].height; ++ } else ++#endif ++ { ++ lock->xoff = lock->yoff = 0; ++ lock->mw = lock->x; ++ lock->mh = lock->y; ++ } ++ lock->drawable = XCreatePixmap(dpy, lock->root, ++ lock->x, lock->y, DefaultDepth(dpy, screen)); ++ lock->gc = XCreateGC(dpy, lock->root, 0, NULL); ++ XSetLineAttributes(dpy, lock->gc, 1, LineSolid, CapButt, JoinMiter); ++ + /* init */ + wa.override_redirect = 1; +- wa.background_pixel = lock->colors[INIT]; ++ wa.background_pixel = lock->colors[BACKGROUND]; + lock->win = XCreateWindow(dpy, lock->root, 0, 0, +- DisplayWidth(dpy, lock->screen), +- DisplayHeight(dpy, lock->screen), ++ lock->x, lock->y, + 0, DefaultDepth(dpy, lock->screen), + CopyFromParent, + DefaultVisual(dpy, lock->screen), +@@ -256,6 +313,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) + &color, &color, 0, 0); + XDefineCursor(dpy, lock->win, invisible); + ++ resizerectangles(lock); ++ + /* 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) { +@@ -276,6 +335,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) + XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); + + XSelectInput(dpy, lock->root, SubstructureNotifyMask); ++ drawlogo(dpy, lock, INIT); + return lock; + } + +@@ -391,5 +451,12 @@ main(int argc, char **argv) { + /* everything is now blank. Wait for the correct password */ + readpw(dpy, &rr, locks, nscreens, hash); + ++ for (nlocks = 0, s = 0; s < nscreens; s++) { ++ XFreePixmap(dpy, locks[s]->drawable); ++ XFreeGC(dpy, locks[s]->gc); ++ } ++ ++ XSync(dpy, 0); ++ XCloseDisplay(dpy); + return 0; + } diff --git a/core/slock/patches/slock-dwmlogoandblurscreen-1.0.diff b/core/slock/patches/slock-dwmlogoandblurscreen-1.0.diff new file mode 100644 index 0000000..17ffc72 --- /dev/null +++ b/core/slock/patches/slock-dwmlogoandblurscreen-1.0.diff @@ -0,0 +1,336 @@ +diff -u ../slock-orig/config.def.h ./config.def.h +--- ../slock-orig/config.def.h 2022-04-29 17:07:13.872268452 -0400 ++++ ./config.def.h 2022-04-29 16:44:38.573566776 -0400 +@@ -3,10 +3,36 @@ + static const char *group = "nogroup"; + + static const char *colorname[NUMCOLS] = { +- [INIT] = "black", /* after initialization */ ++ [BACKGROUND] = "white", ++ [INIT] = "2d2d2d", /* after initialization */ + [INPUT] = "#005577", /* during input */ + [FAILED] = "#CC3333", /* wrong password */ + }; + + /* treat a cleared input like a wrong password (color) */ + static const int failonclear = 1; ++ ++static const int logosize = 75; ++static const int logow = 12; /* Grid width and height for right center alignment*/ ++static const int logoh = 6; ++ ++static XRectangle rectangles[9] = { ++ {0, 3, 1, 3}, ++ {1, 3, 2, 1}, ++ {0, 5, 8, 1}, ++ {3, 0, 1, 5}, ++ {5, 3, 1, 2}, ++ {7, 3, 1, 2}, ++ {8, 3, 4, 1}, ++ {9, 4, 1, 2}, ++ {11,4, 1, 2}, ++}; ++ ++/*Enable blur*/ ++#define BLUR ++/*Set blur radius*/ ++static const int blurRadius=5; ++/*Enable Pixelation*/ ++//#define PIXELATION ++/*Set pixelation radius*/ ++static const int pixelSize=0; +diff -u ../slock-orig/config.mk ./config.mk +--- ../slock-orig/config.mk 2022-04-29 17:07:13.872268452 -0400 ++++ ./config.mk 2022-04-29 17:14:49.416921212 -0400 +@@ -10,13 +10,21 @@ + X11INC = /usr/X11R6/include + X11LIB = /usr/X11R6/lib + ++# Xinerama, comment if you don't want it ++XINERAMALIBS = -lXinerama ++XINERAMAFLAGS = -DXINERAMA ++ ++# freetype ++FREETYPELIBS = -lXft ++FREETYPEINC = /usr/include/freetype2 ++ + # includes and libs +-INCS = -I. -I/usr/include -I${X11INC} +-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr ++INCS = -I. -I/usr/include -I${X11INC} -I${FREETYPEINC} ++LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lImlib2 ${XINERAMALIBS} ${FREETYPELIBS} -lXext -lXrandr + + # flags +-CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H +-CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} ++CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H ${XINERAMAFLAGS} ++CFLAGS = -std=c99 -pedantic -Wall -Ofast ${INCS} ${CPPFLAGS} + LDFLAGS = -s ${LIBS} + COMPATSRC = explicit_bzero.c + +diff -u ../slock-orig/slock.c ./slock.c +--- ../slock-orig/slock.c 2022-04-29 17:07:13.872268452 -0400 ++++ ./slock.c 2022-04-29 17:04:53.424073165 -0400 +@@ -1,5 +1,6 @@ + /* See LICENSE file for license details. */ +-#define _XOPEN_SOURCE 500 ++#define _XOPEN_SOURCE 500 ++#define LENGTH(X) (sizeof X / sizeof X[0]) + #if HAVE_SHADOW_H + #include <shadow.h> + #endif +@@ -15,9 +16,13 @@ + #include <unistd.h> + #include <sys/types.h> + #include <X11/extensions/Xrandr.h> ++#ifdef XINERAMA ++#include <X11/extensions/Xinerama.h> ++#endif + #include <X11/keysym.h> + #include <X11/Xlib.h> + #include <X11/Xutil.h> ++#include <Imlib2.h> + + #include "arg.h" + #include "util.h" +@@ -25,17 +30,26 @@ + char *argv0; + + enum { ++ BACKGROUND, + INIT, + INPUT, + FAILED, + NUMCOLS + }; + ++#include "config.h" ++ + struct lock { + int screen; + Window root, win; + Pixmap pmap; ++ Pixmap bgmap; + unsigned long colors[NUMCOLS]; ++ unsigned int x, y; ++ unsigned int xoff, yoff, mw, mh; ++ Drawable drawable; ++ GC gc; ++ XRectangle rectangles[LENGTH(rectangles)]; + }; + + struct xrandr { +@@ -44,7 +58,7 @@ + int errbase; + }; + +-#include "config.h" ++Imlib_Image image; + + static void + die(const char *errstr, ...) +@@ -125,6 +139,29 @@ + } + + static void ++resizerectangles(struct lock *lock) ++{ ++ int i; ++ ++ for (i = 0; i < LENGTH(rectangles); i++){ ++ lock->rectangles[i].x = (rectangles[i].x * logosize) ++ + lock->xoff + ((lock->mw) / 2) - (logow / 2 * logosize); ++ lock->rectangles[i].y = (rectangles[i].y * logosize) ++ + lock->yoff + ((lock->mh) / 2) - (logoh / 2 * logosize); ++ lock->rectangles[i].width = rectangles[i].width * logosize; ++ lock->rectangles[i].height = rectangles[i].height * logosize; ++ } ++} ++ ++static void ++drawlogo(Display *dpy, struct lock *lock, int color) ++{ ++ XSetForeground(dpy, lock->gc, lock->colors[color]); ++ XFillRectangles(dpy, lock->win, lock->gc, lock->rectangles, LENGTH(rectangles)); ++ XSync(dpy, False); ++} ++ ++static void + readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, + const char *hash) + { +@@ -190,10 +227,12 @@ + 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); ++ 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); ++ drawlogo(dpy, locks[screen], color); + } + oldc = color; + } +@@ -228,6 +267,10 @@ + XColor color, dummy; + XSetWindowAttributes wa; + Cursor invisible; ++#ifdef XINERAMA ++ XineramaScreenInfo *info; ++ int n; ++#endif + + if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) + return NULL; +@@ -235,27 +278,61 @@ + 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_image(image); ++ 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); + lock->colors[i] = color.pixel; + } + ++ lock->x = DisplayWidth(dpy, lock->screen); ++ lock->y = DisplayHeight(dpy, lock->screen); ++#ifdef XINERAMA ++ if ((info = XineramaQueryScreens(dpy, &n))) { ++ lock->xoff = info[0].x_org; ++ lock->yoff = info[0].y_org; ++ lock->mw = info[0].width; ++ lock->mh = info[0].height; ++ } else ++#endif ++ { ++ lock->xoff = lock->yoff = 0; ++ lock->mw = lock->x; ++ lock->mh = lock->y; ++ } ++ lock->drawable = XCreatePixmap(dpy, lock->root, ++ lock->x, lock->y, DefaultDepth(dpy, screen)); ++ lock->gc = XCreateGC(dpy, lock->root, 0, NULL); ++ XSetLineAttributes(dpy, lock->gc, 1, LineSolid, CapButt, JoinMiter); ++ + /* init */ + wa.override_redirect = 1; +- wa.background_pixel = lock->colors[INIT]; ++ wa.background_pixel = lock->colors[BACKGROUND]; + lock->win = XCreateWindow(dpy, lock->root, 0, 0, +- DisplayWidth(dpy, lock->screen), +- DisplayHeight(dpy, lock->screen), ++ lock->x, lock->y, + 0, DefaultDepth(dpy, lock->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); + XDefineCursor(dpy, lock->win, invisible); + ++ resizerectangles(lock); ++ + /* 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) { +@@ -276,6 +353,7 @@ + XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); + + XSelectInput(dpy, lock->root, SubstructureNotifyMask); ++ drawlogo(dpy, lock, INIT); + return lock; + } + +@@ -355,6 +433,60 @@ + if (setuid(duid) < 0) + die("slock: setuid: %s\n", strerror(errno)); + ++ /*Create screenshot Image*/ ++ Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy)); ++ image = imlib_create_image(scr->width,scr->height); ++ imlib_context_set_image(image); ++ imlib_context_set_display(dpy); ++ imlib_context_set_visual(DefaultVisual(dpy,0)); ++ imlib_context_set_drawable(RootWindow(dpy,XScreenNumberOfScreen(scr))); ++ imlib_copy_drawable_to_image(0,0,0,scr->width,scr->height,0,0,1); ++ ++#ifdef BLUR ++ ++ /*Blur function*/ ++ imlib_image_blur(blurRadius); ++#endif // BLUR ++ ++#ifdef PIXELATION ++ /*Pixelation*/ ++ int width = scr->width; ++ int height = scr->height; ++ ++ for(int y = 0; y < height; y += pixelSize) ++ { ++ for(int x = 0; x < width; x += pixelSize) ++ { ++ int red = 0; ++ int green = 0; ++ int blue = 0; ++ ++ Imlib_Color pixel; ++ Imlib_Color* pp; ++ pp = &pixel; ++ for(int j = 0; j < pixelSize && j < height; j++) ++ { ++ for(int i = 0; i < pixelSize && i < width; i++) ++ { ++ imlib_image_query_pixel(x+i,y+j,pp); ++ red += pixel.red; ++ green += pixel.green; ++ blue += pixel.blue; ++ } ++ } ++ red /= (pixelSize*pixelSize); ++ green /= (pixelSize*pixelSize); ++ blue /= (pixelSize*pixelSize); ++ imlib_context_set_color(red,green,blue,pixel.alpha); ++ imlib_image_fill_rectangle(x,y,pixelSize,pixelSize); ++ red = 0; ++ green = 0; ++ blue = 0; ++ } ++ } ++ ++ ++#endif + /* check for Xrandr support */ + rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); + +@@ -391,5 +523,12 @@ + /* everything is now blank. Wait for the correct password */ + readpw(dpy, &rr, locks, nscreens, hash); + ++ for (nlocks = 0, s = 0; s < nscreens; s++) { ++ XFreePixmap(dpy, locks[s]->drawable); ++ XFreeGC(dpy, locks[s]->gc); ++ } ++ ++ XSync(dpy, 0); ++ XCloseDisplay(dpy); + return 0; + } diff --git a/core/slock/patches/slock-foreground-image-20211210.diff b/core/slock/patches/slock-foreground-image-20211210.diff new file mode 100644 index 0000000..83d807a --- /dev/null +++ b/core/slock/patches/slock-foreground-image-20211210.diff @@ -0,0 +1,81 @@ +From: Viliam Kováč <viliamkovac1223@gmail.com> +Date: Fri, 10 Dec 2021 17:22:00 +Subject: [PATCH] Add a image foreground +diff --git a/config.def.h b/config.def.h +index 9855e21..dfa61d6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,3 +10,10 @@ static const char *colorname[NUMCOLS] = { + + /* treat a cleared input like a wrong password (color) */ + static const int failonclear = 1; ++ ++static const char *imgpath = "img.xpm"; ++static const int imgwidth = 1920; ++static const int imgheight = 1080; ++static const int imgoffsetx = 0; ++static const int imgoffsety = 0; ++static const int showimgonlyatstart = 1; +diff --git a/config.mk b/config.mk +index 74429ae..6145285 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 -lXpm + + # flags + CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H +diff --git a/slock.c b/slock.c +index 5ae738c..b36c347 100644 +--- a/slock.c ++++ b/slock.c +@@ -18,6 +18,7 @@ + #include <X11/keysym.h> + #include <X11/Xlib.h> + #include <X11/Xutil.h> ++#include <X11/xpm.h> + + #include "arg.h" + #include "util.h" +@@ -124,6 +125,19 @@ gethash(void) + return hash; + } + ++static void ++showimage(Display *dpy, Window win) ++{ ++ XImage *ximage; ++ ++ if (!XpmReadFileToImage (dpy, imgpath, &ximage, NULL, NULL)) { ++ XSelectInput(dpy, win, ButtonPressMask|ExposureMask); ++ XMapWindow(dpy, win); ++ ++ XPutImage(dpy, win, DefaultGC(dpy, 0), ximage, 0, 0, imgoffsetx, imgoffsety, imgwidth, imgheight); ++ } ++} ++ + static void + readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, + const char *hash) +@@ -194,6 +208,8 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, + locks[screen]->win, + locks[screen]->colors[color]); + XClearWindow(dpy, locks[screen]->win); ++ if (showimgonlyatstart != 1) ++ showimage(dpy, locks[screen]->win); + } + oldc = color; + } +@@ -256,6 +272,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) + &color, &color, 0, 0); + XDefineCursor(dpy, lock->win, invisible); + ++ showimage(dpy, lock->win); ++ + /* 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) { diff --git a/core/slock/slock.1 b/core/slock/slock.1 new file mode 100644 index 0000000..40c15e1 --- /dev/null +++ b/core/slock/slock.1 @@ -0,0 +1,45 @@ +.Dd October 6, 2023 +.Dt SLOCK 1 +.Os +.Sh NAME +.Nm slock +.Nd simple X screen locker +.Sh SYNOPSIS +.Nm +.Op Fl v +.Op Ar cmd Op Ar arg ... +.Sh DESCRIPTION +.Nm +is a simple X screen locker. +If provided, +.Ar cmd +is executed after the screen has been locked. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl v +Print version information to stdout and exit. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +$ +.Nm +/usr/sbin/s2ram +.Sh SECURITY CONSIDERATIONS +To make sure a locked screen can not be bypassed by switching VTs +or killing the X server with Ctrl+Alt+Backspace, it is recommended +to disable both in +.Xr xorg.conf 5 +for maximum security: +.Bd -literal +Section "ServerFlags" + Option "DontVTSwitch" "True" + Option "DontZap" "True" +EndSection +.Ed +.Sh CUSTOMIZATION +.Nm +can be customized by creating a custom config.h from config.def.h and +(re)compiling the source code. +This keeps it fast, secure and simple. diff --git a/core/slock/slock.c b/core/slock/slock.c new file mode 100644 index 0000000..962cc1d --- /dev/null +++ b/core/slock/slock.c @@ -0,0 +1,576 @@ +/* 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 <time.h> +#include <poll.h> +#include <X11/extensions/Xrandr.h> +#include <X11/keysym.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xft/Xft.h> +#include <Imlib2.h> +#include "../accent.h" + +#include "arg.h" +#include "util.h" + +char *argv0; + +enum { + INIT, + INPUT, + FAILED, + NUMCOLS +}; + +struct lock { + int screen; + Window root, win; + Pixmap pmap; + Pixmap bgmap; + unsigned long colors[NUMCOLS]; + XftDraw *draw; +}; + +struct xrandr { + int active; + int evbase; + int errbase; +}; + +#include "config.h" + +static ColorShm *accentshm; +static char accentcol[8] = "#005577"; +static XftFont *font; + +static const char *icon[] = { +" ██████████████ ██████████████ ", +" ██████████████ █████████████ ", +" ██████▓▓▓█████ █████▓▓▓██████ ", +" █████▓▓▓▓█████ █████▓▓▓▓█████ ", +" █████▓▓▓▓█████ █████▓▓▓▓█████ ", +" █████▓▓▓▓▓████ ████▓▓▓▓▓█████ ", +" █████▓▓▓▓▓████████ █████████████████████ ████████▓▓▓▓▓█████ ", +" ██████▓▓▓▓▓▓▓█████ █████████████████████ █████▓▓▓▓▓▓▓██████ ", +"▓▓▓▓▓▓▓▓ ██████▓▓▓▓▓▓▓█████ █████████████████████ █████▓▓▓▓▓▓▓██████ ▓▓▓▓▓▓▓▓", +"▓▓▓▓▓▓▓▓▓ █████▓▓▓▓▓████ ████▓▒▒▒▒▓▓▓▒▒▒▒▓████ ████▓▓▓▓▓█████ ▓▓▓▓▓▓▓▓▓", +"▓▓▓▓▓▓▓▓▓ █████▓▓▓▓▓████ ████▓▒▒▒▒▓▓▓▒▒▒▒▓████ ████▓▓▓▓▓█████ ▓▓▓▓▓▓▓▓▓", +"▓▓▓▓▒░░░▒▓▓▓▓ █████▓▓▓▓▓▓▓▓█████▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓█████▓▓▓▓▓▓▓▓█████ ▓▓▓▓▒░░░▒▓▓▓▓", +"▓▓▓▓▒░░░▒▓▓▓▓ █████▓▓▓▓▓▓▓▓█████▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓█████▓▓▓▓▓▓▓▓█████ ▓▓▓▓▒░░░░▓▓▓▓", +"▓▓▓▓▒▒▒▒░░░░▒▓▓▓▓ █████████▓▓▓▓▓▒▒▒▓███▓▓▓▓▓▓▓▓█████▓▓▓▓▓▓▓▓███▓▒▒▒▒▓▓▓▓█████████ ▓▓▓▓▒░░░░▒▒▒▒▓▓▓▓", +" ▒▒▒▒▒░░░░▒▓▓▓▓ ██████████▓▓▓▒▒▒▒▓███▓▓▓▓▓███████████▓▓▓▓▓███▓▒▒▒▒▓▓▓▓█████████ ▓▓▓▓▒░░░░▒▒▒▒▒ ", +" ▓▓▓▓▓░░░░▒▒▒▒▓▓▓▓████████████▓▒▒▒▓███████▓▓▓▓█████▓▓▓▓███████▓▒▒▒▒▓████████████▓▓▓▒▒▒▒░░░░▒▓▓▓▓ ", +" ████▓▒░░░░░░▒▒▓▓▓████████████▓▒▒▒▓████████▓▓▓▓▓▓▓▓▓▓▓████████▓▒▒▒▓████████████▓▓▓▓▒░░░░░░░▓████ ", +" ████▓▒▒▒▒░░░░▒▓▓▓▓███████████▓▒▒▒▓▓▓▓████▓▒▒▒▒▒▒▒▒▒▒▒▓████▓▓▓▓▒▒▒▓████████████▓▓▓▒▒░░░▒▒▒▒▓████ ", +" ▓▓▓▓▓▒░░░▒▒▒▒▓▓▓▓▓███████▓▒▒▒▒▒▒▒▓███▒░░░░░░░░░░░▒▓██▓▒▒▒▒▒▒▒▒▓██████▓▓▓▓▓▒▒▒▒░░░▒▓▓▓▓▓ ", +" ▓▓▓▓▓▒░░░▒▒▒▒▒▓▓▓▓███████▓▒▒▒▒▒▒▒▓███▒░░░░░░░░░░▒▓██▓▒▒▒▒▒▒▒▓▓██████▓▓▓▓▓▒▒▒▒░░░▒▓▓▓▓▓ ", +" ▓▓▓▓▓▒░░░▒▒▒▒▒▒▒▒▓▓▓▓████▓▓▓▒▒░░░▒███▒░░░░░░░░░░░▒▓██▓░░░▒▒▓▓▓████▓▓▓▓▒▒▒▒▒▒▒▒░░░▒▓▓▓▓▓ ", +" ▓▓▓▓▓▒░░░▒▒▒▒▒▒▒▒▓▓▓▓████▓▓▓▒▒░░░▒███▒░░░░░░░░░░░▒▓██▓░░░▒▒▓▓▓████▓▓▓▓▒▒▒▒▒▒▒▒░░░▒▓▓▓▓▓ ", +" ▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▓██████▓▒░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░▒▓██████▓▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓ ", +" ▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▓██████▓▒░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░▒▓██████▓▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓ ", +" ████▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓████ ", +" ████▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓████ ", +" █████▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓█████ ", +" █████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████████████ ", +" █████▓▓▓▓████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████▓▓▓▓█████ ", +" ████▓▓▒▒▒▓███████████▓▓▓▓▓▓▓▓▒░░░░░░░░░░░░░░░░░░░▒▒▓▓▓▓▓▓▓███████████▓▒▒▒▒▓████ ", +" ████▓▓▓▓▒▒▒▒▓▓▓▓████████▓▓▓▓▓▓▓▓▒▒▒▒▒░░░░░░░░░░░░▒▒▒▒▓▓▓▓▓▓▓▓█████████▓▓▓▒▒▒▒▓▓▓▓████ ", +" █████▓▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓████████████▓▓▓▓▒░░░░░░░░░░░▒▓▓▓▓████████████▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓█████ ", +" █████▓▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓████████████▓▓▓▓▒░░░░░░░░░░░▒▓▓▓▓████████████▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓█████ ", +" █████▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓███████████████████████████████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓█████ ", +" █████▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓██████████████████████████████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓█████ ", +" █████▓▓▓▓▓▓▓▓▓▓▓▓█████████████████████▓▓▓██████▓▓█████████████████████▓▓▓▓▓▓▓▓▓▓▓▓█████ ", +" ██████▓▓▓▓▓▓▓▓████████▓▓▓█████████████▓▓▓█████▓▓▓█████████████▓▓▓████████▓▓▓▓▓▓▓▓▓█████ ", +" █████████▓▓▓▓▓████████▓▓▓▓████████████▓▓▓█████▓▓▓▓████████████▓▓▓████████▓▓▓▓▓█████████ ", +" █████▓▓▓▓▓████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████████▓▓▓▓▓█████ ", +" ██████▓▓▓▓▓▓▓████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████████▓▓▓▓▓▓▓▓█████ ", +" ██████▓▓▓▓▓▓▓▓████████▓▓▓█████████▓▓▓▓▓▓▓▓▓▓▓█████████▓▓▓████████▓▓▓▓▓▓▓▓██████ ", +" ██████▓▓▓▓▓▓▓▓████████████████████▓▓▓▓▓▓▓▓▓▓▓████████████████████▓▓▓▓▓▓▓▓██████ ", +" ██████████████████████████████████▓▓▓▓▓▓▓▓▓▓▓██████████████████████████████████ ", +" ██████████████████████████████████▓▓▓▓▓▓▓▓▓▓▓██████████████████████████████████ ", +" ██████▓▓▓▓▓▓██████▓▓▓████▓▓▓▓▓████▓▓▓██████▓▓▓▓▓▓▓█████ ", +" ██████▓▓▓▓▓▓▓█████▓▓▓████▓▓▓▓▓████▓▓▓██████▓▓▓▓▓▓▓█████ ", +" █████▓▓▓▓▓▓▓▓█████████████████████████████▓▓▓▓▓▓▓▓█████ ", +" █████▓▓▓▓▓▓▓▓█████████▓▓▓█████▓▓▓█████████▓▓▓▓▓▓▓▓█████ ", +" ██████▓▓▓▓▓▓▓█████████▓▓▓▓███▓▓▓▓██████████▓▓▓▓▓▓██████ ", +" ██████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████████████ ", +" █████████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓█████████████████████ ", +" ████████████████▓▓▓▓▓▓▓▓▓▓▓██████████████████ ", +" ██████████████████████████████████████████████ ", +" █████████████ ", +" █████████████ ", +NULL}; + +static void +updateaccent(void) +{ + if (!readaccent(&accentshm, accentcol)) + memcpy(accentcol, "#005577", 8); +} + +static void +drawlogo(Display *dpy, struct lock *lock, const char *col) +{ + XftColor xftc; + XGlyphInfo ext; + int i, x, y, w, h, lines = 0, maxw = 0, lineh; + size_t len; + + w = DisplayWidth(dpy, lock->screen); + h = DisplayHeight(dpy, lock->screen); + lineh = font->ascent + font->descent; + + for (i = 0; icon[i]; i++) { + len = strlen(icon[i]); + while (len && icon[i][len - 1] == ' ') + len--; + XftTextExtentsUtf8(dpy, font, (FcChar8 *)icon[i], len, &ext); + if (ext.xOff > maxw) + maxw = ext.xOff; + lines++; + } + x = (w - maxw) / 2; + y = (h - lines * lineh) / 2 + font->ascent; + + if (!XftColorAllocName(dpy, DefaultVisual(dpy, lock->screen), + DefaultColormap(dpy, lock->screen), col, &xftc)) + return; + + XClearWindow(dpy, lock->win); + for (i = 0; icon[i]; i++) { + len = strlen(icon[i]); + while (len && icon[i][len - 1] == ' ') + len--; + XftDrawStringUtf8(lock->draw, &xftc, font, x, y, + (FcChar8 *)icon[i], len); + y += lineh; + } + + XftColorFree(dpy, DefaultVisual(dpy, lock->screen), + DefaultColormap(dpy, lock->screen), &xftc); +} + +static void +blurbackground(Display *dpy, struct lock *lock) +{ + int w = DisplayWidth(dpy, lock->screen); + int h = DisplayHeight(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->root); + + Imlib_Image img = imlib_create_image_from_drawable(0, 0, 0, w, h, 1); + if (!img) + return; + imlib_context_set_image(img); + imlib_image_blur(20); + + lock->bgmap = XCreatePixmap(dpy, lock->root, w, h, + DefaultDepth(dpy, lock->screen)); + imlib_context_set_drawable(lock->bgmap); + imlib_render_image_on_drawable(0, 0); + imlib_free_image(); + + XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap); +} + +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; + unsigned int len; + KeySym ksym; + XEvent ev; + struct pollfd pfd; + time_t last; + const char *col, *oldcol = NULL; + char lastaccent[8]; + + len = 0; + running = 1; + failure = 0; + + updateaccent(); + memcpy(lastaccent, accentcol, 8); + col = accentcol; + last = time(NULL); + for (screen = 0; screen < nscreens; screen++) + drawlogo(dpy, locks[screen], col); + + pfd.fd = ConnectionNumber(dpy); + pfd.events = POLLIN; + + while (running) { + /* poll at ~60Hz so accent gradients appear smooth */ + if (poll(&pfd, 1, 5) > 0) { + while (XPending(dpy)) { + XNextEvent(dpy, &ev); + if (ev.type == KeyPress) { + last = time(NULL); + 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 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; + } + } 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); + drawlogo(dpy, locks[screen], col); + break; + } + } + } else { + for (screen = 0; screen < nscreens; screen++) + XRaiseWindow(dpy, locks[screen]->win); + } + } + } + + updateaccent(); + int idle = time(NULL) - last >= 3; + + if (!idle && len) + col = colorname[INPUT]; + else if (!idle && (failure || failonclear)) + col = colorname[FAILED]; + else + col = accentcol; + + if ((col == accentcol && memcmp(accentcol, lastaccent, 8) != 0) || col != oldcol) { + memcpy(lastaccent, accentcol, 8); + for (screen = 0; screen < nscreens; screen++) + drawlogo(dpy, locks[screen], col); + oldcol = col; + } + } +} + +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); + + blurbackground(dpy, lock); + + if (!font) + font = XftFontOpenName(dpy, lock->screen, "monospace:size=10"); + lock->draw = XftDrawCreate(dpy, lock->win, + DefaultVisual(dpy, lock->screen), + DefaultColormap(dpy, lock->screen)); + + /* 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/core/slock/util.h b/core/slock/util.h new file mode 100644 index 0000000..6f748b8 --- /dev/null +++ b/core/slock/util.h @@ -0,0 +1,2 @@ +#undef explicit_bzero +void explicit_bzero(void *, size_t); |
