diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | PKGBUILD | 43 | ||||
| -rw-r--r-- | config.def.h | 12 | ||||
| -rw-r--r-- | config.h | 25 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | patches/slock-dpms-1.4.diff | 62 | ||||
| -rw-r--r-- | patches/slock-message-20191002-b46028b.diff | 250 | ||||
| -rw-r--r-- | slock.1 | 7 | ||||
| -rw-r--r-- | slock.c | 140 |
9 files changed, 537 insertions, 6 deletions
@@ -30,7 +30,7 @@ slock: ${OBJ} clean: @echo cleaning - @rm -f slock ${OBJ} slock-${VERSION}.tar.gz + @rm -rf slock ${OBJ} slock-${VERSION}.tar.gz *.zst pkg src dist: clean @echo creating dist tarball diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..4f818f6 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,43 @@ +pkgname=slock-custom-git +_pkgname=slock +pkgver=1.4 +pkgrel=1 +pkgdesc='Simple X display locker' +url='http://git.vasthecat.ru/slock.git' +arch=('i686' 'x86_64' 'armv7h') +license=('MIT') +makedepends=('git') +depends=('libxrandr') +source=( + 'config.h' + 'slock.c' + 'slock.1' + 'Makefile' + 'arg.h' + 'config.mk' + 'explicit_bzero.c' + 'LICENSE' + 'util.h' +) +md5sums=( + 'SKIP' + '31bcab9d9fc728d06ce0e7901ac76ea1' + '9b6e3255f77ba8d96dde17058580761c' + 'b55b4021060bc816ff9ac68ef5269144' + '088564fdbdbbae55b777dce80abc602f' + 'f0fad6e2be404189b869a7598cf98626' + '4885a6c0db3b9f2fd6c07100fea0fe6e' + '41b71f339fba66b45a89418a350ef914' + 'f26ca62b855e6d8e134f2ecdf9f0ca92' +) +provides=("${_pkgname}") +conflicts=("${_pkgname}") + +build() { + make X11INC=/usr/include/X11 X11LIB=/usr/lib/X11 +} + +package() { + make PREFIX=/usr DESTDIR="${pkgdir}" install + install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" +} diff --git a/config.def.h b/config.def.h index 9855e21..ef9bb60 100644 --- a/config.def.h +++ b/config.def.h @@ -10,3 +10,15 @@ 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; + +/* default message */ +static const char * message = "Suckless: Software that sucks less."; + +/* text color */ +static const char * text_color = "#ffffff"; + +/* text size (must be a valid size) */ +static const char * font_name = "6x10"; diff --git a/config.h b/config.h new file mode 100644 index 0000000..805b0ea --- /dev/null +++ b/config.h @@ -0,0 +1,25 @@ +/* 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; + +/* time in seconds before the monitor shuts down */ +static const int monitortime = 5; + +/* default message */ +static const char * message = "Suckless: Software that sucks less."; + +/* text color */ +static const char * text_color = "#ffffff"; + +/* text size (must be a valid size) */ +// static const char * font_name = "-misc-dejavu sans mono-medium-o-normal--0-0-0-0-m-0-iso8859-1"; +static const char * font_name = "-misc-dejavu sans mono-medium-r-normal--0-0-0-0-m-0-iso8859-1"; @@ -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 -lXinerama # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H diff --git a/patches/slock-dpms-1.4.diff b/patches/slock-dpms-1.4.diff new file mode 100644 index 0000000..027bbf7 --- /dev/null +++ b/patches/slock-dpms-1.4.diff @@ -0,0 +1,62 @@ +diff --git a/config.def.h b/config.def.h +index 9855e21..d01bd38 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = { + + /* treat a cleared input like a wrong password (color) */ + static const int failonclear = 1; ++ ++/* time in seconds before the monitor shuts down */ ++static const int monitortime = 5; +diff --git a/slock.c b/slock.c +index d2f0886..f65a43b 100644 +--- a/slock.c ++++ b/slock.c +@@ -15,6 +15,7 @@ + #include <unistd.h> + #include <sys/types.h> + #include <X11/extensions/Xrandr.h> ++#include <X11/extensions/dpms.h> + #include <X11/keysym.h> + #include <X11/Xlib.h> + #include <X11/Xutil.h> +@@ -306,6 +307,7 @@ main(int argc, char **argv) { + const char *hash; + Display *dpy; + int s, nlocks, nscreens; ++ CARD16 standby, suspend, off; + + ARGBEGIN { + case 'v': +@@ -366,6 +368,20 @@ main(int argc, char **argv) { + if (nlocks != nscreens) + return 1; + ++ /* DPMS magic to disable the monitor */ ++ if (!DPMSCapable(dpy)) ++ die("slock: DPMSCapable failed\n"); ++ if (!DPMSEnable(dpy)) ++ die("slock: DPMSEnable failed\n"); ++ if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off)) ++ die("slock: DPMSGetTimeouts failed\n"); ++ if (!standby || !suspend || !off) ++ die("slock: at least one DPMS variable is zero\n"); ++ if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime)) ++ die("slock: DPMSSetTimeouts failed\n"); ++ ++ XSync(dpy, 0); ++ + /* run post-lock command */ + if (argc > 0) { + switch (fork()) { +@@ -383,5 +399,9 @@ main(int argc, char **argv) { + /* everything is now blank. Wait for the correct password */ + readpw(dpy, &rr, locks, nscreens, hash); + ++ /* reset DPMS values to inital ones */ ++ DPMSSetTimeouts(dpy, standby, suspend, off); ++ XSync(dpy, 0); ++ + return 0; + } diff --git a/patches/slock-message-20191002-b46028b.diff b/patches/slock-message-20191002-b46028b.diff new file mode 100644 index 0000000..54b17e6 --- /dev/null +++ b/patches/slock-message-20191002-b46028b.diff @@ -0,0 +1,250 @@ +From b46028b2797b886154258dcafe71c349cdc68b43 Mon Sep 17 00:00:00 2001 +From: Blair Drummond <blair.robert.drummond@gmail.com> +Date: Wed, 2 Oct 2019 14:59:00 -0400 +Subject: [PATCH] Add a message command. Fixes old version's bugs. + +--- + config.def.h | 9 ++++ + config.mk | 2 +- + slock.1 | 7 +++ + slock.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++-- + 4 files changed, 133 insertions(+), 5 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9855e21..c2a0ab2 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -10,3 +10,12 @@ static const char *colorname[NUMCOLS] = { + + /* treat a cleared input like a wrong password (color) */ + static const int failonclear = 1; ++ ++/* default message */ ++static const char * message = "Suckless: Software that sucks less."; ++ ++/* text color */ ++static const char * text_color = "#ffffff"; ++ ++/* text size (must be a valid size) */ ++static const char * font_name = "6x10"; +diff --git a/config.mk b/config.mk +index 74429ae..c4ccf66 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 -lXinerama + + # flags + CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H +diff --git a/slock.1 b/slock.1 +index 82cdcd6..946165f 100644 +--- a/slock.1 ++++ b/slock.1 +@@ -6,6 +6,8 @@ + .Sh SYNOPSIS + .Nm + .Op Fl v ++.Op Fl f ++.Op Fl m Ar message + .Op Ar cmd Op Ar arg ... + .Sh DESCRIPTION + .Nm +@@ -16,6 +18,11 @@ is executed after the screen has been locked. + .Bl -tag -width Ds + .It Fl v + Print version information to stdout and exit. ++.It Fl f ++List all valid X fonts and exit. ++.It Fl m Ar message ++Overrides default slock lock message. ++.TP + .El + .Sh SECURITY CONSIDERATIONS + To make sure a locked screen can not be bypassed by switching VTs +diff --git a/slock.c b/slock.c +index 5ae738c..610929b 100644 +--- a/slock.c ++++ b/slock.c +@@ -15,6 +15,7 @@ + #include <unistd.h> + #include <sys/types.h> + #include <X11/extensions/Xrandr.h> ++#include <X11/extensions/Xinerama.h> + #include <X11/keysym.h> + #include <X11/Xlib.h> + #include <X11/Xutil.h> +@@ -24,6 +25,9 @@ + + char *argv0; + ++/* global count to prevent repeated error messages */ ++int count_error = 0; ++ + enum { + INIT, + INPUT, +@@ -83,6 +87,98 @@ dontkillme(void) + } + #endif + ++static void ++writemessage(Display *dpy, Window win, int screen) ++{ ++ int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size; ++ XGCValues gr_values; ++ XFontStruct *fontinfo; ++ XColor color, dummy; ++ XineramaScreenInfo *xsi; ++ GC gc; ++ fontinfo = XLoadQueryFont(dpy, font_name); ++ ++ if (fontinfo == NULL) { ++ if (count_error == 0) { ++ fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name); ++ fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n"); ++ count_error++; ++ } ++ return; ++ } ++ ++ tab_size = 8 * XTextWidth(fontinfo, " ", 1); ++ ++ XAllocNamedColor(dpy, DefaultColormap(dpy, screen), ++ text_color, &color, &dummy); ++ ++ gr_values.font = fontinfo->fid; ++ gr_values.foreground = color.pixel; ++ gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values); ++ ++ /* To prevent "Uninitialized" warnings. */ ++ xsi = NULL; ++ ++ /* ++ * Start formatting and drawing text ++ */ ++ ++ len = strlen(message); ++ ++ /* Max max line length (cut at '\n') */ ++ line_len = 0; ++ k = 0; ++ for (i = j = 0; i < len; i++) { ++ if (message[i] == '\n') { ++ if (i - j > line_len) ++ line_len = i - j; ++ k++; ++ i++; ++ j = i; ++ } ++ } ++ /* If there is only one line */ ++ if (line_len == 0) ++ line_len = len; ++ ++ if (XineramaIsActive(dpy)) { ++ xsi = XineramaQueryScreens(dpy, &i); ++ s_width = xsi[0].width; ++ s_height = xsi[0].height; ++ } else { ++ s_width = DisplayWidth(dpy, screen); ++ s_height = DisplayHeight(dpy, screen); ++ } ++ ++ height = s_height*3/7 - (k*20)/3; ++ width = (s_width - XTextWidth(fontinfo, message, line_len))/2; ++ ++ /* Look for '\n' and print the text between them. */ ++ for (i = j = k = 0; i <= len; i++) { ++ /* i == len is the special case for the last line */ ++ if (i == len || message[i] == '\n') { ++ tab_replace = 0; ++ while (message[j] == '\t' && j < i) { ++ tab_replace++; ++ j++; ++ } ++ ++ XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j); ++ while (i < len && message[i] == '\n') { ++ i++; ++ j = i; ++ k++; ++ } ++ } ++ } ++ ++ /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ ++ if (XineramaIsActive(dpy) && xsi != NULL) ++ XFree(xsi); ++} ++ ++ ++ + static const char * + gethash(void) + { +@@ -194,6 +290,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, + locks[screen]->win, + locks[screen]->colors[color]); + XClearWindow(dpy, locks[screen]->win); ++ writemessage(dpy, locks[screen]->win, screen); + } + oldc = color; + } +@@ -300,7 +397,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) + static void + usage(void) + { +- die("usage: slock [-v] [cmd [arg ...]]\n"); ++ die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n"); + } + + int +@@ -313,12 +410,25 @@ main(int argc, char **argv) { + gid_t dgid; + const char *hash; + Display *dpy; +- int s, nlocks, nscreens; ++ int i, s, nlocks, nscreens; ++ int count_fonts; ++ char **font_names; + + ARGBEGIN { + case 'v': + fprintf(stderr, "slock-"VERSION"\n"); + return 0; ++ case 'm': ++ message = EARGF(usage()); ++ break; ++ case 'f': ++ if (!(dpy = XOpenDisplay(NULL))) ++ die("slock: cannot open display\n"); ++ font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts); ++ for (i=0; i<count_fonts; i++) { ++ fprintf(stderr, "%s\n", *(font_names+i)); ++ } ++ return 0; + default: + usage(); + } ARGEND +@@ -363,10 +473,12 @@ main(int argc, char **argv) { + 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) ++ if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { ++ writemessage(dpy, locks[s]->win, s); + nlocks++; +- else ++ } else { + break; ++ } + } + XSync(dpy, 0); + +-- +2.20.1 + @@ -6,6 +6,8 @@ .Sh SYNOPSIS .Nm .Op Fl v +.Op Fl f +.Op Fl m Ar message .Op Ar cmd Op Ar arg ... .Sh DESCRIPTION .Nm @@ -16,6 +18,11 @@ is executed after the screen has been locked. .Bl -tag -width Ds .It Fl v Print version information to stdout and exit. +.It Fl f +List all valid X fonts and exit. +.It Fl m Ar message +Overrides default slock lock message. +.TP .El .Sh SECURITY CONSIDERATIONS To make sure a locked screen can not be bypassed by switching VTs @@ -15,6 +15,8 @@ #include <unistd.h> #include <sys/types.h> #include <X11/extensions/Xrandr.h> +#include <X11/extensions/dpms.h> +#include <X11/extensions/Xinerama.h> #include <X11/keysym.h> #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -24,6 +26,9 @@ char *argv0; +/* global count to prevent repeated error messages */ +int count_error = 0; + enum { INIT, INPUT, @@ -83,6 +88,98 @@ dontkillme(void) } #endif +static void +writemessage(Display *dpy, Window win, int screen) +{ + int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size; + XGCValues gr_values; + XFontStruct *fontinfo; + XColor color, dummy; + XineramaScreenInfo *xsi; + GC gc; + fontinfo = XLoadQueryFont(dpy, font_name); + + if (fontinfo == NULL) { + if (count_error == 0) { + fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name); + fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n"); + count_error++; + } + return; + } + + tab_size = 8 * XTextWidth(fontinfo, " ", 1); + + XAllocNamedColor(dpy, DefaultColormap(dpy, screen), + text_color, &color, &dummy); + + gr_values.font = fontinfo->fid; + gr_values.foreground = color.pixel; + gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values); + + /* To prevent "Uninitialized" warnings. */ + xsi = NULL; + + /* + * Start formatting and drawing text + */ + + len = strlen(message); + + /* Max max line length (cut at '\n') */ + line_len = 0; + k = 0; + for (i = j = 0; i < len; i++) { + if (message[i] == '\n') { + if (i - j > line_len) + line_len = i - j; + k++; + i++; + j = i; + } + } + /* If there is only one line */ + if (line_len == 0) + line_len = len; + + if (XineramaIsActive(dpy)) { + xsi = XineramaQueryScreens(dpy, &i); + s_width = xsi[0].width; + s_height = xsi[0].height; + } else { + s_width = DisplayWidth(dpy, screen); + s_height = DisplayHeight(dpy, screen); + } + + height = s_height*3/7 - (k*20)/3; + width = (s_width - XTextWidth(fontinfo, message, line_len))/2; + + /* Look for '\n' and print the text between them. */ + for (i = j = k = 0; i <= len; i++) { + /* i == len is the special case for the last line */ + if (i == len || message[i] == '\n') { + tab_replace = 0; + while (message[j] == '\t' && j < i) { + tab_replace++; + j++; + } + + XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j); + while (i < len && message[i] == '\n') { + i++; + j = i; + k++; + } + } + } + + /* xsi should not be NULL anyway if Xinerama is active, but to be safe */ + if (XineramaIsActive(dpy) && xsi != NULL) + XFree(xsi); +} + + + static const char * gethash(void) { @@ -194,6 +291,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, locks[screen]->win, locks[screen]->colors[color]); XClearWindow(dpy, locks[screen]->win); + writemessage(dpy, locks[screen]->win, screen); } oldc = color; } @@ -292,7 +390,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) static void usage(void) { - die("usage: slock [-v] [cmd [arg ...]]\n"); + die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n"); } int @@ -305,12 +403,26 @@ main(int argc, char **argv) { gid_t dgid; const char *hash; Display *dpy; - int s, nlocks, nscreens; + int i, s, nlocks, nscreens; + CARD16 standby, suspend, off; + int count_fonts; + char **font_names; ARGBEGIN { case 'v': fprintf(stderr, "slock-"VERSION"\n"); return 0; + case 'm': + message = EARGF(usage()); + break; + case 'f': + if (!(dpy = XOpenDisplay(NULL))) + die("slock: cannot open display\n"); + font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts); + for (i=0; i<count_fonts; i++) { + fprintf(stderr, "%s\n", *(font_names+i)); + } + return 0; default: usage(); } ARGEND @@ -355,10 +467,12 @@ main(int argc, char **argv) { 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) + if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) { + writemessage(dpy, locks[s]->win, s); nlocks++; - else + } else { break; + } } XSync(dpy, 0); @@ -366,6 +480,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 +511,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; } |