diff --git a/README b/README index dcacd01..4d28b23 100644 --- a/README +++ b/README @@ -1,6 +1,8 @@ slock - simple screen locker ============================ -simple screen locker utility for X. +simple screen locker utility for X. + +Includes patch for using image file as the background. Requirements @@ -13,6 +15,10 @@ Installation Edit config.mk to match your local setup (slock is installed into the /usr/local namespace by default). +Apply the background image patch: + + patch -N < slock-image.patch + Afterwards enter the following command to build and install slock (if necessary as root): diff --git a/config.def.h b/config.def.h index 9855e21..27cc2d0 100644 --- a/config.def.h +++ b/config.def.h @@ -1,6 +1,6 @@ /* user and group to drop privileges to */ static const char *user = "nobody"; -static const char *group = "nogroup"; +static const char *group = "nobody"; static const char *colorname[NUMCOLS] = { [INIT] = "black", /* after initialization */ diff --git a/config.h b/config.h new file mode 100644 index 0000000..27cc2d0 --- /dev/null +++ b/config.h @@ -0,0 +1,12 @@ +/* user and group to drop privileges to */ +static const char *user = "nobody"; +static const char *group = "nobody"; + +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/config.mk b/config.mk index 74429ae..0d9d6be 100644 --- a/config.mk +++ b/config.mk @@ -12,19 +12,19 @@ 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 -CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -LDFLAGS = -s ${LIBS} +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 +#CPPFLAGS += -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_NETBSD_SOURCE # On OpenBSD set COMPATSRC to empty #COMPATSRC = diff --git a/slock.1 b/slock.1 index 82cdcd6..253452c 100644 --- a/slock.1 +++ b/slock.1 @@ -5,7 +5,7 @@ .Nd simple X screen locker .Sh SYNOPSIS .Nm -.Op Fl v +.Op Fl v i .Op Ar cmd Op Ar arg ... .Sh DESCRIPTION .Nm @@ -16,6 +16,8 @@ is executed after the screen has been locked. .Bl -tag -width Ds .It Fl v Print version information to stdout and exit. +.It Fl i +Load image as background. .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..3241c0c 100644 --- a/slock.c +++ b/slock.c @@ -18,8 +18,9 @@ #include #include #include +#include +#include -#include "arg.h" #include "util.h" char *argv0; @@ -35,6 +36,7 @@ struct lock { int screen; Window root, win; Pixmap pmap; + Pixmap bgmap; unsigned long colors[NUMCOLS]; }; @@ -177,7 +179,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, break; case XK_BackSpace: if (len) - passwd[--len] = '\0'; + passwd[len--] = '\0'; break; default: if (num && !iscntrl((int)buf[0]) && @@ -190,10 +192,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]); - 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]); } oldc = color; } @@ -201,26 +203,18 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, 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); + XResizeWindow(dpy, locks[screen]->win, + rre->width, rre->height); XClearWindow(dpy, locks[screen]->win); - break; } } - } else { - for (screen = 0; screen < nscreens; screen++) - XRaiseWindow(dpy, locks[screen]->win); - } + } else for (screen = 0; screen < nscreens; screen++) + XRaiseWindow(dpy, locks[screen]->win); } } static struct lock * -lockscreen(Display *dpy, struct xrandr *rr, int screen) +lockscreen(Display *dpy, struct xrandr *rr, int screen,Imlib_Image *image, int use_bg_image) { char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; int i, ptgrab, kbgrab; @@ -241,6 +235,16 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) lock->colors[i] = color.pixel; } + if(image && use_bg_image == 1) { + 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(); + } /* init */ wa.override_redirect = 1; wa.background_pixel = lock->colors[INIT]; @@ -256,6 +260,10 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) &color, &color, 0, 0); XDefineCursor(dpy, lock->win, invisible); + if(lock->bgmap) + XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap); + + /* 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) { @@ -300,7 +308,7 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen) static void usage(void) { - die("usage: slock [-v] [cmd [arg ...]]\n"); + die("\nusage: slock [options]\noptions:\n\t-v\tPrint version and exit.\n\t-i\t\n"); } int @@ -314,14 +322,25 @@ main(int argc, char **argv) { const char *hash; Display *dpy; int s, nlocks, nscreens; + Imlib_Image image; + int use_bg_image = 0; + int option = 0; - ARGBEGIN { - case 'v': - fprintf(stderr, "slock-"VERSION"\n"); - return 0; - default: - usage(); - } ARGEND + while ((option = getopt(argc, argv,"vi:")) != -1) { + switch (option) { + case 'v' : + die("slock-"VERSION" mod-bgimage\n"); + break; + case 'i' : + use_bg_image = 1; + image = imlib_load_image(optarg); + if(!image) { + die("slock: unable to load image.\n"); + } + break; + default: usage(); + } + } /* validate drop-user and -group */ errno = 0; @@ -363,7 +382,7 @@ 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, image, use_bg_image)) != NULL) nlocks++; else break;