diff --git a/config.mk b/config.mk index 97e9a8f..8b2b613 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ -# slock version -VERSION = 0.9 +# i3lock version +VERSION = 1.0 # Customize below to fit your system @@ -13,16 +13,13 @@ MANDIR = $(DESTDIR)$(PREFIX)/share/man # includes and libs INCS = -I. -I/usr/include -I${X11INC} -LIBS = -L/usr/lib -L${X11LIB} -lX11 -lpam +LIBS = -L${X11LIB} -lX11 -lpam -lXext # flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H +CPPFLAGS = -DVERSION=\"${VERSION}\" CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} LDFLAGS = -s ${LIBS} -# 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 INSTALL=install diff --git a/i3lock.1 b/i3lock.1 index facc39f..922c153 100644 --- a/i3lock.1 +++ b/i3lock.1 @@ -8,13 +8,17 @@ .fi .. -.TH i3lock 1 "MARCH 2009" Linux "User Manuals" +.TH i3lock 1 "MAY 2009" Linux "User Manuals" .SH NAME i3lock \- slightly improved version of slock .SH SYNOPSIS -i3lock takes no arguments +.B i3lock +.RB [\|\-v\|] +.RB [\|\-n\|] +.RB [\|\-b\|] +.RB [\|\-d\|] .SH DESCRIPTION .B i3lock @@ -37,8 +41,28 @@ does not call XBell(). This is important because .B i3lock/slock think you've entered a password when resuming from suspend, at least sometimes. +Since version 1.0, i3lock supports PAM. + +.SH OPTIONS +.TP +.B \-v, \-\-version +Display the version of your .B i3lock -was forked from slock-0.9 + +.TP +.B \-n, \-\-nofork +Don't fork after starting. + +.TP +.B \-b, \-\-beep +Enable beeping. Be sure to not do this when you are about to annoy other people, +like when opening your laptop in a boring lecture. + +.TP +.B \-d, \-\-dpms +Enable turning off your screen using DPMS. Note that, when you do not specify this +option, DPMS will turn off your screen after 15 minutes of inactivity anyways (if +you did not disable this in your X server). .SH AUTHOR Michael Stapelberg diff --git a/i3lock.c b/i3lock.c index 05110f4..2c95929 100644 --- a/i3lock.c +++ b/i3lock.c @@ -26,7 +26,9 @@ #include #include #include +#include #include +#include #include @@ -75,10 +77,16 @@ static int conv_callback(int num_msg, const struct pam_message **msg, int main(int argc, char *argv[]) { char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; char buf[32]; + char *username; int num, screen; unsigned int len; bool running = true; + + /* By default, fork, don’t beep and don’t turn off monitor */ + bool dont_fork = false; + bool beep = false; + bool dpms = false; Cursor invisible; Display *dpy; KeySym ksym; @@ -88,30 +96,54 @@ int main(int argc, char *argv[]) { XEvent ev; XSetWindowAttributes wa; - /* TODO: use getopt */ - if((argc == 2) && !strcmp("-v", argv[1])) - die("i3lock-"VERSION", © 2009 Michael Stapelberg\n" - "based on slock, which is © 2006-2008 Anselm R Garbe\n"); - else if(argc != 1) - die("usage: i3lock [-v]\n"); - pam_handle_t *handle; + struct pam_conv conv = {conv_callback, NULL}; - struct pam_conv conv; - conv.conv = conv_callback; + char opt; + int optind = 0; + static struct option long_options[] = { + {"version", no_argument, NULL, 'v'}, + {"nofork", no_argument, NULL, 'n'}, + {"beep", no_argument, NULL, 'b'}, + {"dpms", no_argument, NULL, 'd'}, + {NULL, no_argument, NULL, 0} + }; - int ret = pam_start("i3lock", getenv("USER"), &conv, &handle); - printf("pam_start = %d\n", ret); + while ((opt = getopt_long(argc, argv, "vnbd", long_options, &optind)) != -1) { + switch (opt) { + case 'v': + die("i3lock-"VERSION", © 2009 Michael Stapelberg\n" + "based on slock, which is © 2006-2008 Anselm R Garbe\n"); + case 'n': + dont_fork = true; + break; + case 'b': + beep = true; + break; + case 'd': + dpms = true; + break; + default: + die("i3lock: Unknown option. Syntax: i3lock [-v] [-n] [-b] [-d]\n"); + } + } + + if ((username = getenv("USER")) == NULL) + die("USER environment variable not set, please set it.\n"); + + int ret = pam_start("i3lock", username, &conv, &handle); if (ret != PAM_SUCCESS) - die("error = %s\n", pam_strerror(handle, ret)); + die("PAM: %s\n", pam_strerror(handle, ret)); if(!(dpy = XOpenDisplay(0))) - die("slock: cannot open display\n"); + die("i3lock: cannot open display\n"); screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); - if (fork() != 0) - return 0; + if (!dont_fork) { + if (fork() != 0) + return 0; + } /* init */ wa.override_redirect = 1; @@ -144,41 +176,53 @@ int main(int argc, char *argv[]) { /* main event loop */ while(running && !XNextEvent(dpy, &ev)) { - if(ev.type == KeyPress) { - buf[0] = 0; - 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 (len == 0 && dpms && DPMSCapable(dpy)) { + DPMSEnable(dpy); + DPMSForceLevel(dpy, DPMSModeOff); + } + + if(ev.type != KeyPress) + continue; + + buf[0] = 0; + 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) { + case XK_Return: + passwd[len] = 0; + if ((ret = pam_authenticate(handle, 0)) == PAM_SUCCESS) + running = false; + else { + fprintf(stderr, "PAM: %s\n", pam_strerror(handle, ret)); + if (beep) + XBell(dpy, 100); } - if(IsFunctionKey(ksym) || IsKeypadKey(ksym) - || IsMiscFunctionKey(ksym) || IsPFKey(ksym) - || IsPrivateKeypadKey(ksym)) - continue; - switch(ksym) { - case XK_Return: - passwd[len] = 0; - if ((ret = pam_authenticate(handle, 0)) == PAM_SUCCESS) - running = false; - else fprintf(stderr, "PAM: %s\n", pam_strerror(handle, ret)); - len = 0; - break; - case XK_Escape: - len = 0; - break; - case XK_BackSpace: - if (len > 0) - len--; - break; - default: - if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { - memcpy(passwd + len, buf, num); - len += num; - } - break; + len = 0; + break; + case XK_Escape: + len = 0; + break; + case XK_BackSpace: + if (len > 0) + len--; + break; + default: + if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { + memcpy(passwd + len, buf, num); + len += num; } + break; } } XUngrabPointer(dpy, CurrentTime);