64 Commits
0.4 ... 1.3

Author SHA1 Message Date
Markus Teich
6a52a85a1a add slock.1 man page 2016-02-11 16:51:12 +01:00
FRIGN
c28ac1ebf1 Update license year
It actually was 2014 and not 2015.
2016-02-11 16:30:52 +01:00
FRIGN
aa6a385341 Don't forget the E-Mail 2016-02-11 16:29:26 +01:00
FRIGN
6adeb1281e Add myself to License
forgot that a while ago
2016-02-11 16:28:41 +01:00
Markus Teich
f6582b68b0 update copyright year in -v output 2016-02-11 16:26:12 +01:00
Markus Teich
bfafc91da7 prepare 1.3 release 2016-02-11 16:23:48 +01:00
Markus Teich
32149e4043 remove .hgtags 2016-02-11 16:22:34 +01:00
Markus Teich
1766ecdfd4 add hint for suid to oom error message 2016-01-29 22:11:18 +01:00
Markus Teich
9dfe0ce531 error messages on grab failure 2016-01-18 16:49:15 +01:00
Markus Teich
55e827af0f code style fix 2016-01-18 16:47:41 +01:00
Markus Teich
e867c38123 add option to run command after screen is locked 2015-12-26 19:27:01 +01:00
David Phillips
b95ee111c7 Don't change to failure colour on success 2015-08-27 06:16:25 +02:00
David Phillips
0edbd2e016 Slightly safer OOM killer disablement in linux 2015-07-06 11:15:07 +02:00
Markus Teich
754195f8d7 rework setting window color 2015-05-08 18:07:05 +02:00
Markus Teich
10d4e479c5 consistently use () with sizeof 2015-05-08 16:44:18 +02:00
Nick Currier
b1289f30b7 Option to not show failure color on clear 2015-05-08 16:44:06 +02:00
Markus Teich
f5ef1b8eb5 resize lockscreen window after Xrandr resize 2015-04-01 23:25:47 +02:00
David Phillips
f2ea92c3dd Blank the screen with color 0, add third color for failed logins
- Adds another color in config.def.h, COLOR_INIT
- Renames the colours from numerical ones to ones with meaningful names;
  COLOR_INPUT for when there is content in the input buffer and COLOR_EMPTY
  for when the input buffer has been cleared (backspaced or a failed attempt).
- Ensures XFreeColors frees the right number of colours. This is now derived
  from the size of `Lock->colors` rather than being an integer literal.
- Makes slock exhibit the behaviour described by Markus

The default colours are the same as the ones slock currently uses, with the
exception of the new color, which I have set to red, as it indicates someone
has either failed an attempt to unlock, or that they have entered input and
erased it all.
2015-04-01 23:13:11 +02:00
Anselm R Garbe
a31b919111 applied Dimitris' style patch from Dec'14, with some minor modifications 2015-01-27 22:16:52 +01:00
Anselm R Garbe
66e31556db fixed usage string 2014-12-22 11:17:45 +01:00
Anselm R Garbe
44ce161c13 applied sin's patch and prepared new release 2014-12-22 11:16:26 +01:00
sin
4339b507af end{pw,sp}ent() can only be called after get{pw,sp}ent()
Calling them unconditionally can result in memory corruption.
2014-11-09 13:10:02 +00:00
sin
8745098fa4 Only check errno if getpwuid() fails
Checking errno otherwise is unspecified.
2014-07-09 14:41:32 +01:00
FRIGN
9db14b10dd Add /etc/passwd support
Fix slock to work with /etc/passwd without /etc/shadow.
while we're at it, remove an occurence of trailing whitespace.
2014-06-09 19:14:31 +01:00
sin
6a55128354 Set errno to 0 before getpwuid() and check it afterwards 2014-01-29 14:19:35 +00:00
Anselm R Garbe
ba3acfc0dc applied Robert Schneider's Linux suggestions, also bumped version and updated LICENSE file's copyright notice 2013-08-02 22:11:18 +02:00
anselm@garbe.us
3092d3b314 prepared 1.1 2012-10-25 20:59:50 +02:00
garbeam@gmail.com
d276b9b0e0 applied andres' multi-slock fix, thanks for spotting this issue 2012-08-02 21:54:18 +02:00
anselm@garbe.us
4b4fcca1bc added Ben's password placeholder entry kludge 2012-04-15 11:58:16 +02:00
anselm@garbe.us
c1507cd225 applied Eckehard Bern's dualcolor patch to slock 2012-03-17 18:03:25 +01:00
anselm@garbe.us
88d9684966 Added tag 1.0 for changeset 05b949016e85 2012-02-11 10:51:31 +01:00
anselm@garbe.us
34f5edb29e preparing 1.0 2012-02-11 10:51:26 +01:00
anselm@garbe.us
0b13628462 select for SubstructureRedirectMask as well 2012-02-09 20:56:34 +01:00
anselm@garbe.us
7a217cb7c4 fixed missing new lines 2012-02-09 20:18:49 +01:00
anselm@garbe.us
5d433c7cf5 typo fix 2012-02-05 16:41:31 +01:00
anselm@garbe.us
d6e9e7d9e3 added XRaiseWindow workaround when new clients are launched 2012-02-05 16:38:58 +01:00
garbeam@gmail.com
f013cb264e applied Michaels patch 2012-01-24 22:10:02 +01:00
anselm@garbe.us
5a5c581285 added dummy error handler to prevent X from terminating slock just in case 2012-01-22 18:58:10 +01:00
Anselm R Garbe
ede2935e10 applied Markus' patch to die in case /etc/passwd is unavailable 2011-04-21 08:22:47 +00:00
Anselm R Garbe
732d2b3bf5 applied Fernando Silveira's multiscreen patch for old style multihead setups 2009-11-26 12:53:26 +00:00
a@null
0cb05bdb75 applied Ali Gholami Rudi's patch regarding DPMS timeout customization and persistence 2008-12-12 19:34:43 +00:00
Anselm R Garbe
cadc8a7472 Added tag 0.9 for changeset 1e8a77601cb9 2008-07-29 19:23:21 +01:00
Anselm R Garbe
a6a3471dd9 fix 2008-07-29 19:17:24 +01:00
Anselm R Garbe
75dd779245 prepared release 2008-07-29 19:14:53 +01:00
Anselm R Garbe
1460b14f45 removed useless chars, prepared release 2008-07-29 19:08:18 +01:00
Anselm R Garbe
c0fdcb8afc s/d// 2008-04-09 23:42:50 +01:00
Anselm R Garbe
cc36050e44 yet another DPMS fix, still trying to prevent the error handler 2008-04-09 23:42:19 +01:00
Anselm R Garbe
049ccf9a90 fixed DPMS crashing issue 2008-04-08 09:55:46 +01:00
Anselm R Garbe
4ed35d22dc Added tag 0.8 for changeset c0eb8221ba49 2008-03-13 16:59:24 +00:00
Anselm R Garbe
98e2fef63d applied two patches, BSD_AUTH patch and Gottox' DPMS support patch 2008-02-22 10:13:12 +00:00
Anselm R. Garbe
a430a647e4 removed Sander from -v by request 2007-11-25 12:17:33 +01:00
Anselm R. Garbe
18b2f4f34f next version will be 0.8 2007-11-24 21:27:44 +01:00
Anselm R. Garbe
925381bfd0 Added tag 0.7 for changeset c4635bb35a45 2007-11-24 21:18:06 +01:00
Anselm R. Garbe
6fdf8be204 final fixes and cleanups 2007-11-24 21:17:32 +01:00
arg@suckless.org
1fd4e7b23e applied Ryan Sorensen bugfix which allows slock to acquire the keyboard grab asynchroneously 2007-11-13 18:16:18 +01:00
Anselm R. Garbe
20e294a66f updating copyright stuff in slock as well 2007-04-13 11:48:17 +02:00
Anselm R. Garbe
1726ff0816 Added tag 0.6 for changeset dd226a81c09a 2007-03-07 13:31:49 +01:00
Anselm R. Garbe
48a7ab2225 grab on the root window, it is correct, all lockers do that 2007-03-07 10:57:23 +01:00
Anselm R. Garbe
d8ea936899 Added tag 0.5 for changeset bd24ea7fcca2 2007-03-05 11:28:53 +01:00
Anselm R. Garbe
8322f22871 grab on the slock window instead on the root window 2007-03-02 21:50:05 +01:00
Anselm R. Garbe
d83a9a1d01 made slock more readable, added root variable because we intend to call RootWindow(...) quite a lot 2007-02-21 22:16:23 +01:00
Anselm R. Garbe
ae8cce24d3 made slock more aggressive, DenisG please recheck 2007-02-21 21:25:53 +01:00
Anselm R. Garbe
663fdb326a foobar 2007-02-01 13:52:36 +01:00
Anselm R. Garbe
48f386ce9d Added tag 0.4 for changeset 4c2cf4d6a2d0 2007-01-13 14:10:56 +01:00
8 changed files with 376 additions and 108 deletions

View File

@@ -1,3 +0,0 @@
0a95c73c7374fbc2342b6040d9f35ddf597729e1 0.1
da5cb1f0a685258d5315ea109860bacbc2871a57 0.2
f9157b1864388ad8f1920e5fde7c5849e73d8327 0.3

23
LICENSE
View File

@@ -1,21 +1,24 @@
MIT/X Consortium License
(C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
© 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>
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
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 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
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.

View File

@@ -1,5 +1,5 @@
# slock - simple screen locker
# (C)opyright MMVI-MMVII Anselm R. Garbe
# See LICENSE file for copyright and license details.
include config.mk
@@ -13,18 +13,20 @@ options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: config.mk
${OBJ}: config.h config.mk
config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
slock: ${OBJ}
@echo LD $@
@${LD} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@@ -33,7 +35,8 @@ clean:
dist: clean
@echo creating dist tarball
@mkdir -p slock-${VERSION}
@cp -R LICENSE Makefile README config.mk ${SRC} slock-${VERSION}
@cp -R LICENSE Makefile README config.def.h config.mk ${SRC} slock.1 \
slock-${VERSION}
@tar -cf slock-${VERSION}.tar slock-${VERSION}
@gzip slock-${VERSION}.tar
@rm -rf slock-${VERSION}
@@ -44,9 +47,15 @@ install: all
@cp -f slock ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/slock
@chmod u+s ${DESTDIR}${PREFIX}/bin/slock
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@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:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/slock
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/slock.1
.PHONY: all options clean dist install uninstall

6
README
View File

@@ -13,12 +13,12 @@ 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):
Afterwards enter the following command to build and install slock
(if necessary as root):
make clean install
Running slock
-------------
Simply invoke the 'slock' command.
Simply invoke the 'slock' command. To get out of it, enter your password.

6
config.def.h Normal file
View File

@@ -0,0 +1,6 @@
static const char *colorname[NUMCOLS] = {
"black", /* after initialization */
"#005577", /* during input */
"#CC3333", /* failed/cleared the input */
};
static const Bool failonclear = True;

View File

@@ -1,5 +1,5 @@
# slock version
VERSION = 0.4
VERSION = 1.3
# Customize below to fit your system
@@ -12,17 +12,20 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11
LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
# flags
CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H
LDFLAGS = ${LIBS}
#CFLAGS = -g -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H
#LDFLAGS = -g ${LIBS}
CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS}
# On *BSD remove -DHAVE_SHADOW_H from CFLAGS
# On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS and add -DHAVE_BSD_AUTH
# On OpenBSD and Darwin remove -lcrypt from LIBS
# compiler and linker
CC = cc
LD = ${CC}
# Install mode. On BSD systems MODE=2755 and GROUP=auth
# On others MODE=4755 and GROUP=root
#MODE=2755
#GROUP=auth

29
slock.1 Normal file
View File

@@ -0,0 +1,29 @@
.TH SLOCK 1 slock\-VERSION
.SH NAME
slock \- simple X display locker
.SH SYNOPSIS
.B slock
.RB [ \-v
|
.IR post_lock_command ]
.SH DESCRIPTION
.B slock
is a screen locker for X. If provided, the
.IR post_lock_command
will be executed when the screen is locked.
.SH OPTIONS
.TP
.B \-v
prints version information to stdout, then exits.
.SH EXAMPLES
$ slock /usr/sbin/s2ram
.SH CUSTOMIZATION
.B slock
can be customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH AUTHORS
See the LICENSE file for the authors.
.SH LICENSE
See the LICENSE file for the terms of redistribution.
.SH BUGS
Please report them.

375
slock.c
View File

@@ -1,137 +1,358 @@
/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
* See LICENSE file for license details.
*/
/* 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 <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <X11/extensions/Xrandr.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
const char *
get_password() { /* only run as root */
#if HAVE_BSD_AUTH
#include <login_cap.h>
#include <bsd_auth.h>
#endif
enum {
INIT,
INPUT,
FAILED,
NUMCOLS
};
#include "config.h"
typedef struct {
int screen;
Window root, win;
Pixmap pmap;
unsigned long colors[NUMCOLS];
} Lock;
static Lock **locks;
static int nscreens;
static Bool running = True;
static Bool failure = False;
static Bool rr;
static int rrevbase;
static int rrerrbase;
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)
{
int fd;
int length;
char value[64];
fd = open("/proc/self/oom_score_adj", O_WRONLY);
if (fd < 0 && errno == ENOENT)
return;
/* convert OOM_SCORE_ADJ_MIN to string for writing */
length = snprintf(value, sizeof(value), "%d\n", OOM_SCORE_ADJ_MIN);
/* bail on truncation */
if (length >= sizeof(value))
die("buffer too small\n");
if (fd < 0 || write(fd, value, length) != length || close(fd) != 0)
die("cannot disable the out-of-memory killer for this process (make sure to suid or sgid slock)\n");
}
#endif
#ifndef HAVE_BSD_AUTH
/* only run as root */
static const char *
getpw(void)
{
const char *rval;
struct passwd *pw;
if(geteuid() != 0) {
fputs("slock: cannot retrieve password entry (make sure to suid slock)\n", stderr);
exit(EXIT_FAILURE);
errno = 0;
if (!(pw = getpwuid(getuid()))) {
if (errno)
die("slock: getpwuid: %s\n", strerror(errno));
else
die("slock: cannot retrieve password entry\n");
}
pw = getpwuid(getuid());
endpwent();
rval = pw->pw_passwd;
rval = pw->pw_passwd;
#if HAVE_SHADOW_H
{
if (rval[0] == 'x' && rval[1] == '\0') {
struct spwd *sp;
sp = getspnam(getenv("USER"));
endspent();
if (!(sp = getspnam(getenv("USER"))))
die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
rval = sp->sp_pwdp;
}
#endif
/* drop privileges */
if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
fputs("slock: cannot drop privileges\n",stdout);
exit(EXIT_FAILURE);
}
if (geteuid() == 0 &&
((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) || setuid(pw->pw_uid) < 0))
die("slock: cannot drop privileges\n");
return rval;
}
#endif
int
main(int argc, char **argv) {
char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
static void
#ifdef HAVE_BSD_AUTH
readpw(Display *dpy)
#else
readpw(Display *dpy, const char *pws)
#endif
{
char buf[32], passwd[256];
int num, screen;
const char *pws;
unsigned int len;
Bool running = True;
Cursor invisible;
Display *dpy;
unsigned int len, color;
KeySym ksym;
Pixmap pmap;
Window w;
XColor black, dummy;
XEvent ev;
XSetWindowAttributes wa;
static int oldc = INIT;
if((argc > 1) && !strncmp(argv[1], "-v", 3)) {
fputs("slock-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
exit(EXIT_SUCCESS);
}
pws = get_password();
if(!(dpy = XOpenDisplay(0))) {
fputs("slock: cannot open display\n", stderr);
exit(EXIT_FAILURE);
}
screen = DefaultScreen(dpy);
/* init */
wa.override_redirect = 1;
wa.background_pixel = BlackPixel(dpy, screen);
w = XCreateWindow(dpy, RootWindow(dpy, screen), 0, 0,
DisplayWidth(dpy, screen), DisplayHeight(dpy, screen),
0, DefaultDepth(dpy, screen), CopyFromParent,
DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixel, &wa);
XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "black", &black, &dummy);
pmap = XCreateBitmapFromData(dpy, w, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, pmap, pmap, &black, &black, 0, 0);
XDefineCursor(dpy, w, invisible);
running = XGrabPointer(dpy, RootWindow(dpy, screen), False,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeSync, None, invisible, CurrentTime) == GrabSuccess;
len = 10;
for(len = 10; len && (XGrabKeyboard(dpy, RootWindow(dpy, screen), True, GrabModeAsync,
GrabModeAsync, CurrentTime) != GrabSuccess); len--)
usleep(1000);
running = running && (len > 0);
len = 0;
XMapRaised(dpy, w);
XSync(dpy, False);
running = True;
/* main event loop */
while(running && !XNextEvent(dpy, &ev))
if(ev.type == KeyPress) {
/* As "slock" stands for "Simple X display locker", the DPMS settings
* had been removed and you can set it with "xset" or some other
* utility. This way the user can easily set a customized DPMS
* timeout. */
while (running && !XNextEvent(dpy, &ev)) {
if (ev.type == KeyPress) {
buf[0] = 0;
num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0);
if(IsFunctionKey(ksym) || IsKeypadKey(ksym)
|| IsMiscFunctionKey(ksym) || IsPFKey(ksym)
|| IsPrivateKeypadKey(ksym))
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) {
switch (ksym) {
case XK_Return:
passwd[len] = 0;
if((running = strcmp(crypt(passwd, pws), pws)) != 0)
#ifdef HAVE_BSD_AUTH
running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd);
#else
running = !!strcmp(crypt(passwd, pws), pws);
#endif
if (running) {
XBell(dpy, 100);
failure = True;
}
len = 0;
break;
case XK_Escape:
len = 0;
break;
case XK_BackSpace:
if(len)
if (len)
--len;
break;
default:
if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) {
if (num && !iscntrl((int)buf[0]) && (len + num < sizeof(passwd))) {
memcpy(passwd + len, buf, num);
len += num;
}
break;
}
}
color = len ? INPUT : (failure || failonclear ? FAILED : INIT);
if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win);
}
oldc = color;
}
} else if (rr && ev.type == rrevbase + RRScreenChangeNotify) {
XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev;
for (screen = 0; screen < nscreens; screen++) {
if (locks[screen]->win == rre->window) {
XResizeWindow(dpy, locks[screen]->win, rre->width, rre->height);
XClearWindow(dpy, locks[screen]->win);
}
}
} else for (screen = 0; screen < nscreens; screen++)
XRaiseWindow(dpy, locks[screen]->win);
}
}
static void
unlockscreen(Display *dpy, Lock *lock)
{
if(dpy == NULL || lock == NULL)
return;
XUngrabPointer(dpy, CurrentTime);
XFreePixmap(dpy, pmap);
XDestroyWindow(dpy, w);
XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0);
XFreePixmap(dpy, lock->pmap);
XDestroyWindow(dpy, lock->win);
free(lock);
}
static Lock *
lockscreen(Display *dpy, int screen)
{
char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned int len;
int i;
Lock *lock;
XColor color, dummy;
XSetWindowAttributes wa;
Cursor invisible;
if (!running || dpy == NULL || screen < 0 || !(lock = malloc(sizeof(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);
XMapRaised(dpy, lock->win);
if (rr)
XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
/* Try to grab mouse pointer *and* keyboard, else fail the lock */
for (len = 1000; len; len--) {
if (XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess)
break;
usleep(1000);
}
if (!len) {
fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n", screen);
} else {
for (len = 1000; len; len--) {
if (XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) {
/* everything fine, we grabbed both inputs */
XSelectInput(dpy, lock->root, SubstructureNotifyMask);
return lock;
}
usleep(1000);
}
fprintf(stderr, "slock: unable to grab keyboard for screen %d\n", screen);
}
/* grabbing one of the inputs failed */
running = 0;
unlockscreen(dpy, lock);
return NULL;
}
static void
usage(void)
{
fprintf(stderr, "usage: slock [-v|POST_LOCK_CMD]\n");
exit(1);
}
int
main(int argc, char **argv) {
#ifndef HAVE_BSD_AUTH
const char *pws;
#endif
Display *dpy;
int screen;
if ((argc == 2) && !strcmp("-v", argv[1]))
die("slock-%s, © 2006-2016 slock engineers\n", VERSION);
if ((argc == 2) && !strcmp("-h", argv[1]))
usage();
#ifdef __linux__
dontkillme();
#endif
if (!getpwuid(getuid()))
die("slock: no passwd entry for you\n");
#ifndef HAVE_BSD_AUTH
pws = getpw();
#endif
if (!(dpy = XOpenDisplay(0)))
die("slock: cannot open display\n");
rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase);
/* Get the number of screens in display "dpy" and blank them all. */
nscreens = ScreenCount(dpy);
if (!(locks = malloc(sizeof(Lock*) * nscreens)))
die("slock: malloc: %s\n", strerror(errno));
int nlocks = 0;
for (screen = 0; screen < nscreens; screen++) {
if ((locks[screen] = lockscreen(dpy, screen)) != NULL)
nlocks++;
}
XSync(dpy, False);
/* Did we actually manage to lock something? */
if (nlocks == 0) { /* nothing to protect */
free(locks);
XCloseDisplay(dpy);
return 1;
}
if (argc >= 2 && fork() == 0) {
if (dpy)
close(ConnectionNumber(dpy));
execvp(argv[1], argv+1);
die("slock: execvp %s failed: %s\n", argv[1], strerror(errno));
}
/* Everything is now blank. Now wait for the correct password. */
#ifdef HAVE_BSD_AUTH
readpw(dpy);
#else
readpw(dpy, pws);
#endif
/* Password ok, unlock everything and quit. */
for (screen = 0; screen < nscreens; screen++)
unlockscreen(dpy, locks[screen]);
free(locks);
XCloseDisplay(dpy);
return 0;
}