21 Commits
Author SHA1 Message Date
Hiltjo Posthuma 65cb721c9e remove support for running post lock command
This command was used for example to suspend-to-ram (man page example).

On Linux running this command inherits OOM killer immunity. This could be
abused by an other local user on the same machine (abusing resources).

To keep the use-case for suspend-to-ram an user could write a wrapper script
for it, outside the scope of slock.

Simplify argument handling, because the post-lock command parameter is removed.

Reported by: Acts1631 <acts1631kjv@proton.me>
2026-09-05 12:57:54 +02:00
Hiltjo Posthuma 890eaf6343 bump LICENSE year
... and sort by maintainer
2026-09-05 12:53:39 +02:00
Hiltjo Posthuma b04f4d0810 bump version to 1.7 2026-07-27 23:55:46 +02:00
Leonardo Taccari 55d985a354 Avoid ctype(3) abuses
Valid argument of ctype(3) functions must be either EOF or non-negative
value within the range representable as unsigned char. Invalid values
leads to undefined behavior.

Cast all such uses to avoid that.

At least in NetBSD 11 ctype(3) abuses will always crash and permit
to break slock screen locking.
2026-07-27 23:53:20 +02:00
Hiltjo Posthuma 3791a996e2 add a comment for the ctrl-u clear field combo 2025-08-16 11:11:27 +02:00
Drew Marino bf0a5577ac Support ^U for clearing password
^U is a fairly common key combo for clearing fields, this patch adds
support for it.
2025-08-16 11:05:32 +02:00
Hiltjo Posthuma e3fb34364e bump version to 1.6 2025-08-09 14:34:37 +02:00
NRK a70d5d2429 simplify post-lock cmd and die if it fails
this patch does two things:

0. simplify the code by using posix_spawn()
1. unify the behavior of what happens if the post-lock cmd fails.

currently, if `fork()` fails, slock will die without locking the screen.
HOWEVER if `execvp()` fails it prints a message to stderr (which the
user cannot see since the screen has been locked already) and only exits
the child while the parent locks the screen.

to reproduce:

	# slock some_bin_that_doesnt_exist

this behavior is inconsistent, if the idea is that post-lock cmd is
_not_ important then we shouldn't `die()` on `fork()` failure either.
and if we assume that the post-lock cmd _is_ important, then we should
die on exec failure as well.

this patch assumes the latter and calls `die()` if `posix_spawn()`
fails.
2025-03-09 10:02:34 +01:00
Hiltjo Posthuma a34d8fb432 slock.1: use standard wording for options
Remove the OPTIONS section and add an EXIT STATUS section.
2023-10-06 11:57:31 +02:00
Hiltjo Posthuma e8bca65d62 write version to stdout like the man page says 2023-10-06 11:50:11 +02:00
Hiltjo Posthuma ca6f30f621 slock.1: improve man page
* Fix all lint warnings.
* Remove "Op Ar arg..." in the description. It looks ugly.
* No need to set -offset left for .Bd literal.
2023-10-06 11:48:40 +02:00
Hiltjo Posthuma 2fec14c567 config.mk: no need to set CC 2023-10-06 11:41:19 +02:00
Hiltjo Posthuma 5678764412 Makefile: be verbose and remove options
Some things to improve at some point:

* Respect system/packaging CFLAGS/LDFLAGS (don't hardcode -Os -Wall -pedantic,
  -s, etc).
2023-10-06 11:39:40 +02:00
Hiltjo Posthuma aecfb3f680 update LICENSE 2023-10-06 11:39:31 +02:00
Hiltjo Posthuma 4f045545a2 bump version to 1.5 2022-10-04 19:45:14 +02:00
Hiltjo Posthuma 265704d736 Makefile: explicit_bzero.c was copied twice (GNU make gives a warning) 2022-10-04 19:44:47 +02:00
Tobias Stoeckmann 35633d4567 Properly clear the last entered character
When enter is pressed, passwd[len] will be set to '\0'. Pressing
backspace is supposed to remove the last entered character.

But currently, the clearing has an off-by-one, as in setting
passwd[len] to '\0' just like enter would do.

You can also verify it by imagining len=1 and that it's impossible to
clear passwd[0] by pressing backspace with the current code.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
2017-03-25 21:51:29 +01:00
Markus Teich 2d2a21a90a rm trailing whitespace in README 2016-11-23 00:29:18 +01:00
Markus Teich 325581b935 syntax fix 2016-11-23 00:28:43 +01:00
Markus Teich 0ff0d9f7a7 there can only be one window in the event 2016-11-23 00:28:25 +01:00
Bob Uhl 7a604ec1fa Fix resize with multiple monitors and portrait mode
When connecting/disconnecting a portrait monitor, the
XRRScreenChangeNotifyEvent height & width are reversed due to the XRandR
rotation; detect this and DTRT.
2016-11-23 00:26:51 +01:00
6 changed files with 52 additions and 142 deletions

No files matched your search

+1
View File
@@ -1,5 +1,6 @@
MIT/X Consortium License MIT/X Consortium License
© 2016-2026 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2015-2016 Markus Teich <markus.teich@stusta.mhn.de> © 2015-2016 Markus Teich <markus.teich@stusta.mhn.de>
© 2014 Dimitris Papastamos <sin@2f30.org> © 2014 Dimitris Papastamos <sin@2f30.org>
© 2006-2014 Anselm R Garbe <anselm@garbe.us> © 2006-2014 Anselm R Garbe <anselm@garbe.us>
+22 -37
View File
@@ -6,56 +6,41 @@ include config.mk
SRC = slock.c ${COMPATSRC} SRC = slock.c ${COMPATSRC}
OBJ = ${SRC:.c=.o} OBJ = ${SRC:.c=.o}
all: options slock all: slock
options:
@echo slock build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o: .c.o:
@echo CC $< ${CC} -c ${CFLAGS} $<
@${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk arg.h util.h ${OBJ}: config.h config.mk util.h
config.h: config.h:
@echo creating $@ from config.def.h cp config.def.h $@
@cp config.def.h $@
slock: ${OBJ} slock: ${OBJ}
@echo CC -o $@ ${CC} -o $@ ${OBJ} ${LDFLAGS}
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean: clean:
@echo cleaning rm -f slock ${OBJ} slock-${VERSION}.tar.gz
@rm -f slock ${OBJ} slock-${VERSION}.tar.gz
dist: clean dist: clean
@echo creating dist tarball mkdir -p slock-${VERSION}
@mkdir -p slock-${VERSION} cp -R LICENSE Makefile README slock.1 config.mk \
@cp -R LICENSE Makefile README slock.1 config.mk \ ${SRC} config.def.h util.h slock-${VERSION}
${SRC} explicit_bzero.c config.def.h arg.h util.h slock-${VERSION} tar -cf slock-${VERSION}.tar slock-${VERSION}
@tar -cf slock-${VERSION}.tar slock-${VERSION} gzip slock-${VERSION}.tar
@gzip slock-${VERSION}.tar rm -rf slock-${VERSION}
@rm -rf slock-${VERSION}
install: all install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin mkdir -p ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin cp -f slock ${DESTDIR}${PREFIX}/bin
@cp -f slock ${DESTDIR}${PREFIX}/bin chmod 755 ${DESTDIR}${PREFIX}/bin/slock
@chmod 755 ${DESTDIR}${PREFIX}/bin/slock chmod u+s ${DESTDIR}${PREFIX}/bin/slock
@chmod u+s ${DESTDIR}${PREFIX}/bin/slock mkdir -p ${DESTDIR}${MANPREFIX}/man1
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/${VERSION}/g" <slock.1 >${DESTDIR}${MANPREFIX}/man1/slock.1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1 chmod 644 ${DESTDIR}${MANPREFIX}/man1/slock.1
@sed "s/VERSION/${VERSION}/g" <slock.1 >${DESTDIR}${MANPREFIX}/man1/slock.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/slock.1
uninstall: uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin rm -f ${DESTDIR}${PREFIX}/bin/slock
@rm -f ${DESTDIR}${PREFIX}/bin/slock rm -f ${DESTDIR}${MANPREFIX}/man1/slock.1
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/slock.1
.PHONY: all options clean dist install uninstall .PHONY: all clean dist install uninstall
-65
View File
@@ -1,65 +0,0 @@
/*
* 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
+1 -4
View File
@@ -1,5 +1,5 @@
# slock version # slock version
VERSION = 1.4 VERSION = 1.7
# Customize below to fit your system # Customize below to fit your system
@@ -27,6 +27,3 @@ COMPATSRC = explicit_bzero.c
#CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_NETBSD_SOURCE #CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_NETBSD_SOURCE
# On OpenBSD set COMPATSRC to empty # On OpenBSD set COMPATSRC to empty
#COMPATSRC = #COMPATSRC =
# compiler and linker
CC = cc
+9 -12
View File
@@ -1,39 +1,36 @@
.Dd 2016-08-23 .Dd September 5, 2026
.Dt SLOCK 1 .Dt SLOCK 1
.Os
.Sh NAME .Sh NAME
.Nm slock .Nm slock
.Nd simple X screen locker .Nd simple X screen locker
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl v .Op Fl v
.Op Ar cmd Op Ar arg ...
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
is a simple X screen locker. If provided, is a simple X screen locker.
.Ar cmd Op Ar arg ... The options are as follows:
is executed after the screen has been locked.
.Sh OPTIONS
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl v .It Fl v
Print version information to stdout and exit. Print version information to stdout and exit.
.El .El
.Sh EXIT STATUS
.Ex -std
.Sh SECURITY CONSIDERATIONS .Sh SECURITY CONSIDERATIONS
To make sure a locked screen can not be bypassed by switching VTs 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 or killing the X server with Ctrl+Alt+Backspace, it is recommended
to disable both in to disable both in
.Xr xorg.conf 5 .Xr xorg.conf 5
for maximum security: for maximum security:
.Bd -literal -offset left .Bd -literal
Section "ServerFlags" Section "ServerFlags"
Option "DontVTSwitch" "True" Option "DontVTSwitch" "True"
Option "DontZap" "True" Option "DontZap" "True"
EndSection EndSection
.Ed .Ed
.Sh EXAMPLES
$
.Nm
/usr/sbin/s2ram
.Sh CUSTOMIZATION .Sh CUSTOMIZATION
.Nm .Nm
can be customized by creating a custom config.h from config.def.h and 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. (re)compiling the source code.
This keeps it fast, secure and simple.
+19 -24
View File
@@ -19,7 +19,6 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include "arg.h"
#include "util.h" #include "util.h"
char *argv0; char *argv0;
@@ -177,13 +176,16 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
break; break;
case XK_BackSpace: case XK_BackSpace:
if (len) if (len)
passwd[len--] = '\0'; passwd[--len] = '\0';
break; break;
default: default:
if (num && !iscntrl((int)buf[0]) && if (num && !iscntrl((unsigned char)buf[0]) &&
(len + num < sizeof(passwd))) { (len + num < sizeof(passwd))) {
memcpy(passwd + len, buf, num); memcpy(passwd + len, buf, num);
len += num; len += num;
} else if (buf[0] == '\025') { /* ctrl-u clears input */
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
} }
break; break;
} }
@@ -201,15 +203,23 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
rre = (XRRScreenChangeNotifyEvent*)&ev; rre = (XRRScreenChangeNotifyEvent*)&ev;
for (screen = 0; screen < nscreens; screen++) { for (screen = 0; screen < nscreens; screen++) {
if (locks[screen]->win == rre->window) { 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, XResizeWindow(dpy, locks[screen]->win,
rre->width, rre->height); rre->width, rre->height);
XClearWindow(dpy, locks[screen]->win); XClearWindow(dpy, locks[screen]->win);
break;
} }
} }
} else for (screen = 0; screen < nscreens; screen++) } else {
for (screen = 0; screen < nscreens; screen++)
XRaiseWindow(dpy, locks[screen]->win); XRaiseWindow(dpy, locks[screen]->win);
} }
} }
}
static struct lock * static struct lock *
lockscreen(Display *dpy, struct xrandr *rr, int screen) lockscreen(Display *dpy, struct xrandr *rr, int screen)
@@ -292,7 +302,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
static void static void
usage(void) usage(void)
{ {
die("usage: slock [-v] [cmd [arg ...]]\n"); die("usage: slock [-v]\n");
} }
int int
@@ -307,13 +317,12 @@ main(int argc, char **argv) {
Display *dpy; Display *dpy;
int s, nlocks, nscreens; int s, nlocks, nscreens;
ARGBEGIN { if (argc > 1 && !strcmp(argv[1], "-v")) {
case 'v': puts("slock-"VERSION);
fprintf(stderr, "slock-"VERSION"\n");
return 0; return 0;
default: } else if (argc > 1) {
usage(); usage();
} ARGEND }
/* validate drop-user and -group */ /* validate drop-user and -group */
errno = 0; errno = 0;
@@ -366,20 +375,6 @@ main(int argc, char **argv) {
if (nlocks != nscreens) if (nlocks != nscreens)
return 1; return 1;
/* run post-lock command */
if (argc > 0) {
switch (fork()) {
case -1:
die("slock: fork failed: %s\n", strerror(errno));
case 0:
if (close(ConnectionNumber(dpy)) < 0)
die("slock: close: %s\n", strerror(errno));
execvp(argv[0], argv);
fprintf(stderr, "slock: execvp %s: %s\n", argv[0], strerror(errno));
_exit(1);
}
}
/* everything is now blank. Wait for the correct password */ /* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash); readpw(dpy, &rr, locks, nscreens, hash);