commit 269b78729601107d10ba648fe2910d9630c0cb6a
Author: Andrew Laack <andrew@laack.co>
Date: Tue, 15 Sep 2026 08:37:45 -0500
fork from dannyfiresnake/xl
Diffstat:
| A | LICENSE | | | 21 | +++++++++++++++++++++ |
| A | Makefile | | | 27 | +++++++++++++++++++++++++++ |
| A | README.md | | | 17 | +++++++++++++++++ |
| A | main.c | | | 90 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 155 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 dannyfiresnake
+
+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/Makefile b/Makefile
@@ -0,0 +1,27 @@
+# uncomment next line if you need shadow passwd support
+#NEEDSHADOW= -DNEED_SHADOW
+
+X11HOME = /usr/X11R6
+
+CC = gcc
+CFLAGS = -O2 -Wall -I${X11HOME}/include ${NEEDSHADOW}
+LIBS = -L${X11HOME}/lib -lX11
+
+# Uncomment for systems with libcrypt
+LIBS += -lcrypt
+
+# uncomment if you are running under solaris
+#LIBS += -lnsl -lsocket
+
+OBJS = main.o
+
+all: xl
+
+xl: $(OBJS)
+ $(CC) $(CFLAGS) -o xl $(OBJS) $(LIBS)
+
+clean:
+ rm -f $(OBJS)
+
+realclean: clean
+ rm -f xl
diff --git a/README.md b/README.md
@@ -0,0 +1,17 @@
+xl: The simple X11 lock
+==
+
+xscreensaver, xlock, xlockmore, all of them, completley useless. They have
+overflows, they have buggy drawning routines, they are very prone to crashing.
+The more complex they get, the more useless they are. If a screen locking
+program decides to crash on me, its not doing a very good job of keeping my
+terminal locked. I've had many people just go to my screen and hit tons of keys
+just to make it crash, or cycling the screen saver to get to a certain one
+known to crash. Absolutly ridiculous!
+
+This is my solution to the problem. Very simple, very small, very few features.
+Doesn't even blank your screen, all this program does is lock your keyboard and
+mouse, and only unlocks it if you type your login password and hit return.
+
+You can also override the password by specifying it as the first argument of
+the command line. A third way is to set the XLPASSWD environment variable.
diff --git a/main.c b/main.c
@@ -0,0 +1,90 @@
+/*
+ * Simple, transparent screen locker in X11
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <crypt.h>
+#include <string.h>
+#include <pwd.h>
+
+#ifdef NEED_SHADOW
+#include <shadow.h>
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ Display *display;
+ Window root;
+ int len = 0, i;
+ XEvent ev;
+ char keybuffer[256], *passwd;
+
+ if (argc > 1) {
+ setenv("XLPASSWD", argv[1], 1);
+ execl("/proc/self/exe", argv[0], NULL);
+ fprintf(stderr, "failed to execute self, use XLPASSWD environment\n");
+ exit(1);
+ }
+ else if ((passwd = getenv("XLPASSWD")))
+ passwd = strdup(crypt(passwd, "ax"));
+ else {
+#ifndef NEED_SHADOW
+ passwd = getpwuid(getuid())->pw_passwd;
+#else
+ {
+ struct spwd *sp = getspnam(getpwuid(getuid())->pw_name);
+ if (sp)
+ passwd = sp->sp_pwdp;
+ else {
+ fprintf(stderr, "could not get shadow entry\n");
+ exit(1);
+ }
+ }
+#endif
+ if (!passwd) {
+ fprintf(stderr, "could not get passwd\n");
+ exit(1);
+ }
+ }
+
+ if (strlen(passwd) < 2) {
+ fprintf(stderr, "passwd too short\n");
+ exit(1);
+ }
+
+ if ((display = XOpenDisplay(NULL)) == NULL) {
+ fprintf(stderr, "could not connect to $DISPLAY\n");
+ exit(1);
+ }
+
+ root = DefaultRootWindow(display);
+ XGrabPointer(display, root, 1, ButtonPress, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ XGrabKeyboard(display, root, 0, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XSelectInput(display, root, KeyPressMask);
+
+ while (XNextEvent(display, &ev), 1) {
+ if (ev.type == KeyPress) {
+ KeySym keysym;
+ XComposeStatus compose;
+ if (len > sizeof(keybuffer)-10)
+ len = 0;
+ i = XLookupString(&ev.xkey, keybuffer+len, 10, &keysym, &compose);
+
+ if (keysym == XK_Return) {
+ keybuffer[len] = 0;
+ if (len && !strcmp(crypt(keybuffer, passwd), passwd)) {
+ XUngrabKeyboard(display, CurrentTime);
+ XUngrabPointer(display, CurrentTime);
+ exit(0);
+ } else
+ len = 0;
+ } else
+ len += i;
+ }
+ }
+}