Added capscolor, control clear, dpms, mediakeys, message, pam auth, quickcancel patches

This commit is contained in:
bakkeby 2019-10-17 19:06:39 +02:00
parent 35633d4567
commit 2cf80900da
12 changed files with 518 additions and 6 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
dwm
config.h

54
README.md Normal file
View File

@ -0,0 +1,54 @@
Similar to [dwm-flexipatch](https://github.com/bakkeby/dwm-flexipatch) this slock 1.4 project has a different take on patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more.
For example to include the `capscolor` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/slock-flexipatch/blob/master/patches.h):
```c
#define CAPSCOLOR_PATCH 1
```
Once you have found out what works for you and what doesn't then you should be in a better position to choose patches should you want to start patching from scratch.
Alternatively if you have found the patches you want, but don't want the rest of the flexipatch entanglement on your plate then you may want to have a look at [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer); a custom pre-processor tool that removes all the unused flexipatch code leaving you with a build that contains the patches you selected.
Refer to [https://tools.suckless.org/slock/](https://tools.suckless.org/slock/) for details on the slock tool, how to install it and how it works.
---
### Changelog:
2019-10-17 - Added capscolor, control clear, dpms, mediakeys, message, pam auth, quickcancel patches
2019-10-16 - Introduced [flexipatch-finalizer](https://github.com/bakkeby/flexipatch-finalizer)
### Patches included:
- [capscolor](https://tools.suckless.org/slock/patches/capscolor/)
- adds an additional color to indicate the state of Caps Lock
- [control-clear](https://tools.suckless.org/slock/patches/control-clear/)
- with this patch slock will no longer change to the failure color if a control key is pressed while the buffer is empty
- this may be useful if, for example, you wake your monitor up by pressing a control key and don't want to spoil the detection of failed unlocking attempts
- [dpms](https://tools.suckless.org/slock/patches/dpms/)
- interacts with the Display Power Signaling and automatically shuts down the monitor after a configurable amount of seconds
- the monitor will automatically be activated by pressing a key or moving the mouse and the password can be entered then
- [mediakeys](https://tools.suckless.org/slock/patches/mediakeys/)
- allows media keys to be used while the screen is locked, e.g. adjust volume or skip to the next song without having to unlock the screen first
- [message](https://tools.suckless.org/slock/patches/message/)
- this patch lets you add a custom message to your lock screen
- [pam-auth](https://tools.suckless.org/slock/patches/pam_auth/)
- replaces shadow support with PAM authentication support
- [quickcancel](https://tools.suckless.org/slock/patches/quickcancel/)
- cancel slock by moving the mouse within a certain time-period after slock started
- the time-period can be defined in seconds with the setting timetocancel in the config.h
- this can be useful if you forgot to disable xautolock during an activity that requires no input (e.g. reading text, watching video, etc.)
- [terminalkeys](https://tools.suckless.org/slock/patches/terminalkeys/)
- adds key commands that are commonly used in terminal applications (in particular the login prompt)
- [unlockscreen](https://tools.suckless.org/slock/patches/unlock_screen/)
- this patch keeps the screen unlocked, but keeps the input locked
- that is, the screen is not affected by slock, but users will not be able to interact with the X session unless they enter the correct password

View File

@ -6,7 +6,44 @@ static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */ [INIT] = "black", /* after initialization */
[INPUT] = "#005577", /* during input */ [INPUT] = "#005577", /* during input */
[FAILED] = "#CC3333", /* wrong password */ [FAILED] = "#CC3333", /* wrong password */
#if CAPSCOLOR_PATCH
[CAPS] = "red", /* CapsLock on */
#endif // CAPSCOLOR_PATCH
#if PAMAUTH_PATCH
[PAM] = "#9400D3", /* waiting for PAM */
#endif // CAPSCOLOR_PATCH
}; };
/* treat a cleared input like a wrong password (color) */ /* treat a cleared input like a wrong password (color) */
static const int failonclear = 1; static const int failonclear = 1;
#if CONTROLCLEAR_PATCH
/* allow control key to trigger fail on clear */
static const int controlkeyclear = 0;
#endif // CONTROLCLEAR_PATCH
#if DPMS_PATCH
/* time in seconds before the monitor shuts down */
static const int monitortime = 5;
#endif // DPMS_PATCH
#if MESSAGE_PATCH
/* default message */
static const char * message = "Suckless: Software that sucks less.";
/* text color */
static const char * text_color = "#ffffff";
/* text size (must be a valid size) */
static const char * font_name = "6x10";
#endif // MESSAGE_PATCH
#if PAMAUTH_PATCH
/* PAM service that's used for authentication */
static const char* pam_service = "login";
#endif // PAMAUTH_PATCH
#if QUICKCANCEL_PATCH
/* time in seconds to cancel lock with mouse movement */
static const int timetocancel = 4;
#endif // QUICKCANCEL_PATCH

View File

@ -10,9 +10,15 @@ MANPREFIX = ${PREFIX}/share/man
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
# Uncomment for message patch / MESSAGE_PATCH
#XINERAMA=-lXinerama
# Uncomment for pam auth patch / PAMAUTH_PATCH
#PAM=-lpam
# includes and libs # includes and libs
INCS = -I. -I/usr/include -I${X11INC} 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 ${XINERAMA} ${PAM}
# flags # flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H

9
patch/dpms.c Normal file
View File

@ -0,0 +1,9 @@
#include <X11/extensions/dpms.h>
static void
monitorreset(Display* dpy, CARD16 standby, CARD16 suspend, CARD16 off)
{
DPMSSetTimeouts(dpy, standby, suspend, off);
DPMSForceLevel(dpy, DPMSModeOn);
XFlush(dpy);
}

12
patch/include.c Normal file
View File

@ -0,0 +1,12 @@
/* Patches */
#if DPMS_PATCH
#include "dpms.c"
#endif
#if MESSAGE_PATCH
#include "message.c"
#endif
#if PAMAUTH_PATCH
#include "pamauth.c"
#endif

4
patch/include.h Normal file
View File

@ -0,0 +1,4 @@
/* Patches */
#if PAMAUTH_PATCH
#include "pamauth.h"
#endif

94
patch/message.c Normal file
View File

@ -0,0 +1,94 @@
#include <X11/extensions/Xinerama.h>
/* global count to prevent repeated error messages */
int count_error = 0;
static void
writemessage(Display *dpy, Window win, int screen)
{
int len, line_len, width, height, s_width, s_height, i, j, k, tab_replace, tab_size;
XGCValues gr_values;
XFontStruct *fontinfo;
XColor color, dummy;
XineramaScreenInfo *xsi;
GC gc;
fontinfo = XLoadQueryFont(dpy, font_name);
if (fontinfo == NULL) {
if (count_error == 0) {
fprintf(stderr, "slock: Unable to load font \"%s\"\n", font_name);
fprintf(stderr, "slock: Try listing fonts with 'slock -f'\n");
count_error++;
}
return;
}
tab_size = 8 * XTextWidth(fontinfo, " ", 1);
XAllocNamedColor(dpy, DefaultColormap(dpy, screen),
text_color, &color, &dummy);
gr_values.font = fontinfo->fid;
gr_values.foreground = color.pixel;
gc=XCreateGC(dpy,win,GCFont+GCForeground, &gr_values);
/* To prevent "Uninitialized" warnings. */
xsi = NULL;
/*
* Start formatting and drawing text
*/
len = strlen(message);
/* Max max line length (cut at '\n') */
line_len = 0;
k = 0;
for (i = j = 0; i < len; i++) {
if (message[i] == '\n') {
if (i - j > line_len)
line_len = i - j;
k++;
i++;
j = i;
}
}
/* If there is only one line */
if (line_len == 0)
line_len = len;
if (XineramaIsActive(dpy)) {
xsi = XineramaQueryScreens(dpy, &i);
s_width = xsi[0].width;
s_height = xsi[0].height;
} else {
s_width = DisplayWidth(dpy, screen);
s_height = DisplayHeight(dpy, screen);
}
height = s_height*3/7 - (k*20)/3;
width = (s_width - XTextWidth(fontinfo, message, line_len))/2;
/* Look for '\n' and print the text between them. */
for (i = j = k = 0; i <= len; i++) {
/* i == len is the special case for the last line */
if (i == len || message[i] == '\n') {
tab_replace = 0;
while (message[j] == '\t' && j < i) {
tab_replace++;
j++;
}
XDrawString(dpy, win, gc, width + tab_size*tab_replace, height + 20*k, message + j, i - j);
while (i < len && message[i] == '\n') {
i++;
j = i;
k++;
}
}
}
/* xsi should not be NULL anyway if Xinerama is active, but to be safe */
if (XineramaIsActive(dpy) && xsi != NULL)
XFree(xsi);
}

27
patch/pamauth.c Normal file
View File

@ -0,0 +1,27 @@
char passwd[256];
static int
pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int retval = PAM_CONV_ERR;
for (int i=0; i<num_msg; i++) {
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
strncmp(msg[i]->msg, "Password: ", 10) == 0) {
struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
if (!resp_msg)
die("malloc failed\n");
char *password = malloc(strlen(passwd) + 1);
if (!password)
die("malloc failed\n");
memset(password, 0, strlen(passwd) + 1);
strcpy(password, passwd);
resp_msg->resp_retcode = 0;
resp_msg->resp = password;
resp[i] = resp_msg;
retval = PAM_SUCCESS;
}
}
return retval;
}

5
patch/pamauth.h Normal file
View File

@ -0,0 +1,5 @@
#include <security/pam_appl.h>
#include <security/pam_misc.h>
static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
struct pam_conv pamc = {pam_conv, NULL};

75
patches.h Normal file
View File

@ -0,0 +1,75 @@
/*
* This file contains patch control flags.
*
* In principle you should be able to mix and match any patches
* you may want. In cases where patches are logically incompatible
* one patch may take precedence over the other as noted in the
* relevant descriptions.
*/
/* Patches */
/* This patch introduces an additional color to indicate the state of Caps Lock.
* https://tools.suckless.org/slock/patches/capscolor/
*/
#define CAPSCOLOR_PATCH 0
/* Adds an additional configuration parameter, controlkeyclear. When set to 1, slock will no
* longer change to the failure color if a control key is pressed while the buffer is empty.
* This may be useful if, for example, you wake your monitor up by pressing a control key
* and don't want to spoil the detection of failed unlocking attempts.
* https://tools.suckless.org/slock/patches/control-clear/
*/
#define CONTROLCLEAR_PATCH 0
/* This patch interacts with the Display Power Signaling and automatically shuts down
* the monitor after a configurable amount of seconds.
* The monitor will automatically be activated by pressing a key or moving the mouse
* and the password can be entered then.
* https://tools.suckless.org/slock/patches/dpms/
*/
#define DPMS_PATCH 0
/* This patch allows media keys to be used while the screen is locked. Allows for volume
* to be adjusted or to skip to the next song without having to unlock the screen first.
* https://tools.suckless.org/slock/patches/mediakeys/
*/
#define MEDIAKEYS_PATCH 0
/* This patch lets you add a message to your lock screen. You can place a default message
* in config.h and you can also pass a message with the -m command line option.
* If you enable this then you also need to add the -lXinerama library to the LIBS
* configuration in config.mk. Look for and uncomment the XINERAMA placeholder.
* https://tools.suckless.org/slock/patches/message/
*/
#define MESSAGE_PATCH 0
/* Replaces shadow support with PAM authentication support.
* Change variable pam_service in config.def.h to the corresponding PAM service.
* The default configuration is for ArchLinux's login service.
* If you enable this then you also need to add the -lpam library to the LIBS configuration
* in config.mk. Look for and uncomment the PAM placeholder.
* https://tools.suckless.org/slock/patches/pam_auth/
*/
#define PAMAUTH_PATCH 0
/* Cancel slock by moving the mouse within a certain time-period after slock started.
* The time-period can be defined in seconds with the setting timetocancel in the config.h.
* This can be useful if you forgot to disable xautolock during an activity that requires
* no input (e.g. reading text, watching video, etc.).
* https://tools.suckless.org/slock/patches/quickcancel/
*/
#define QUICKCANCEL_PATCH 0
/* Adds key commands that are commonly used in terminal applications (in particular the
* login prompt) to slock.
* https://tools.suckless.org/slock/patches/terminalkeys/
*/
#define TERMINALKEYS_PATCH 0
/* This patch keeps the screen unlocked but keeps the input locked. That is, the screen
* is not affected by slock, but users will not be able to interact with the X session
* unless they enter the correct password.
* https://tools.suckless.org/slock/patches/unlock_screen/
*/
#define UNLOCKSCREEN_PATCH 0

196
slock.c
View File

@ -19,15 +19,36 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include "patches.h"
#if CAPSCOLOR_PATCH
#include <X11/XKBlib.h>
#endif // CAPSCOLOR_PATCH
#if MEDIAKEYS_PATCH
#include <X11/XF86keysym.h>
#endif // MEDIAKEYS_PATCH
#if QUICKCANCEL_PATCH
#include <time.h>
#endif // QUICKCANCEL_PATCH
#include "arg.h" #include "arg.h"
#include "util.h" #include "util.h"
char *argv0; char *argv0;
#if QUICKCANCEL_PATCH
static time_t locktime;
#endif // QUICKCANCEL_PATCH
enum { enum {
INIT, INIT,
INPUT, INPUT,
FAILED, FAILED,
#if CAPSCOLOR_PATCH
CAPS,
#endif // CAPSCOLOR_PATCH
#if PAMAUTH_PATCH
PAM,
#endif // PAMAUTH_PATCH
NUMCOLS NUMCOLS
}; };
@ -44,6 +65,7 @@ struct xrandr {
int errbase; int errbase;
}; };
#include "patch/include.h"
#include "config.h" #include "config.h"
static void static void
@ -57,6 +79,8 @@ die(const char *errstr, ...)
exit(1); exit(1);
} }
#include "patch/include.c"
#ifdef __linux__ #ifdef __linux__
#include <fcntl.h> #include <fcntl.h>
#include <linux/oom.h> #include <linux/oom.h>
@ -121,6 +145,10 @@ gethash(void)
} }
#endif /* HAVE_SHADOW_H */ #endif /* HAVE_SHADOW_H */
#if PAMAUTH_PATCH
/* pam, store user name */
hash = pw->pw_name;
#endif // PAMAUTH_PATCH
return hash; return hash;
} }
@ -129,18 +157,39 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash) const char *hash)
{ {
XRRScreenChangeNotifyEvent *rre; XRRScreenChangeNotifyEvent *rre;
#if PAMAUTH_PATCH
char buf[32];
int retval;
pam_handle_t *pamh;
#else
char buf[32], passwd[256], *inputhash; char buf[32], passwd[256], *inputhash;
#endif // PAMAUTH_PATCH
int num, screen, running, failure, oldc; int num, screen, running, failure, oldc;
unsigned int len, color; unsigned int len, color;
#if CAPSCOLOR_PATCH
int caps;
unsigned int indicators;
#endif // CAPSCOLOR_PATCH
KeySym ksym; KeySym ksym;
XEvent ev; XEvent ev;
len = 0; len = 0;
#if CAPSCOLOR_PATCH
caps = 0;
#endif // CAPSCOLOR_PATCH
running = 1; running = 1;
failure = 0; failure = 0;
oldc = INIT; oldc = INIT;
#if CAPSCOLOR_PATCH
if (!XkbGetIndicatorState(dpy, XkbUseCoreKbd, &indicators))
caps = indicators & 1;
#endif // CAPSCOLOR_PATCH
while (running && !XNextEvent(dpy, &ev)) { while (running && !XNextEvent(dpy, &ev)) {
#if QUICKCANCEL_PATCH
running = !((time(NULL) - locktime < timetocancel) && (ev.type == MotionNotify));
#endif // QUICKCANCEL_PATCH
if (ev.type == KeyPress) { if (ev.type == KeyPress) {
explicit_bzero(&buf, sizeof(buf)); explicit_bzero(&buf, sizeof(buf));
num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0);
@ -156,14 +205,55 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
IsPFKey(ksym) || IsPFKey(ksym) ||
IsPrivateKeypadKey(ksym)) IsPrivateKeypadKey(ksym))
continue; continue;
#if TERMINALKEYS_PATCH
if (ev.xkey.state & ControlMask) {
switch (ksym) {
case XK_u:
ksym = XK_Escape;
break;
case XK_m:
ksym = XK_Return;
break;
case XK_j:
ksym = XK_Return;
break;
case XK_h:
ksym = XK_BackSpace;
break;
}
}
#endif // TERMINALKEYS_PATCH
switch (ksym) { switch (ksym) {
case XK_Return: case XK_Return:
passwd[len] = '\0'; passwd[len] = '\0';
errno = 0; errno = 0;
#if PAMAUTH_PATCH
retval = pam_start(pam_service, hash, &pamc, &pamh);
color = PAM;
for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win);
XRaiseWindow(dpy, locks[screen]->win);
}
XSync(dpy, False);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0);
running = 1;
if (retval == PAM_SUCCESS)
running = 0;
else
fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
pam_end(pamh, retval);
#else
if (!(inputhash = crypt(passwd, hash))) if (!(inputhash = crypt(passwd, hash)))
fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
else else
running = !!strcmp(inputhash, hash); running = !!strcmp(inputhash, hash);
#endif // PAMAUTH_PATCH
if (running) { if (running) {
XBell(dpy, 100); XBell(dpy, 100);
failure = 1; failure = 1;
@ -179,21 +269,51 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
if (len) if (len)
passwd[--len] = '\0'; passwd[--len] = '\0';
break; break;
#if CAPSCOLOR_PATCH
case XK_Caps_Lock:
caps = !caps;
break;
#endif // CAPSCOLOR_PATCH
#if MEDIAKEYS_PATCH
case XF86XK_AudioLowerVolume:
case XF86XK_AudioMute:
case XF86XK_AudioRaiseVolume:
case XF86XK_AudioPlay:
case XF86XK_AudioStop:
case XF86XK_AudioPrev:
case XF86XK_AudioNext:
XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break;
#endif // MEDIAKEYS_PATCH
default: default:
#if CONTROLCLEAR_PATCH
if (controlkeyclear && iscntrl((int)buf[0]))
continue;
if (num && (len + num < sizeof(passwd)))
#else
if (num && !iscntrl((int)buf[0]) && if (num && !iscntrl((int)buf[0]) &&
(len + num < sizeof(passwd))) { (len + num < sizeof(passwd)))
#endif // CONTROLCLEAR_PATCH
{
memcpy(passwd + len, buf, num); memcpy(passwd + len, buf, num);
len += num; len += num;
} }
break; break;
} }
#if CAPSCOLOR_PATCH
color = len ? (caps ? CAPS : INPUT) : (failure || failonclear ? FAILED : INIT);
#else
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
#endif // CAPSCOLOR_PATCH
if (running && oldc != color) { if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) { for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, XSetWindowBackground(dpy,
locks[screen]->win, locks[screen]->win,
locks[screen]->colors[color]); locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win); XClearWindow(dpy, locks[screen]->win);
#if MESSAGE_PATCH
writemessage(dpy, locks[screen]->win, screen);
#endif // MESSAGE_PATCH
} }
oldc = color; oldc = color;
} }
@ -262,7 +382,13 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
ptgrab = XGrabPointer(dpy, lock->root, False, ptgrab = XGrabPointer(dpy, lock->root, False,
ButtonPressMask | ButtonReleaseMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync, PointerMotionMask, GrabModeAsync,
GrabModeAsync, None, invisible, CurrentTime); GrabModeAsync, None,
#if UNLOCKSCREEN_PATCH
None,
#else
invisible,
#endif // UNLOCKSCREEN_PATCH
CurrentTime);
} }
if (kbgrab != GrabSuccess) { if (kbgrab != GrabSuccess) {
kbgrab = XGrabKeyboard(dpy, lock->root, True, kbgrab = XGrabKeyboard(dpy, lock->root, True,
@ -271,11 +397,16 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
/* input is grabbed: we can lock the screen */ /* input is grabbed: we can lock the screen */
if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
#if !UNLOCKSCREEN_PATCH
XMapRaised(dpy, lock->win); XMapRaised(dpy, lock->win);
#endif // UNLOCKSCREEN_PATCH
if (rr->active) if (rr->active)
XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
XSelectInput(dpy, lock->root, SubstructureNotifyMask); XSelectInput(dpy, lock->root, SubstructureNotifyMask);
#if QUICKCANCEL_PATCH
locktime = time(NULL);
#endif // QUICKCANCEL_PATCH
return lock; return lock;
} }
@ -300,7 +431,11 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
static void static void
usage(void) usage(void)
{ {
#if MESSAGE_PATCH
die("usage: slock [-v] [-f] [-m message] [cmd [arg ...]]\n");
#else
die("usage: slock [-v] [cmd [arg ...]]\n"); die("usage: slock [-v] [cmd [arg ...]]\n");
#endif // MESSAGE_PATCH
} }
int int
@ -314,11 +449,30 @@ main(int argc, char **argv) {
const char *hash; const char *hash;
Display *dpy; Display *dpy;
int s, nlocks, nscreens; int s, nlocks, nscreens;
#if DPMS_PATCH
CARD16 standby, suspend, off;
#endif // DPMS_PATCH
#if MESSAGE_PATCH
int i, count_fonts;
char **font_names;
#endif // MESSAGE_PATCH
ARGBEGIN { ARGBEGIN {
case 'v': case 'v':
fprintf(stderr, "slock-"VERSION"\n"); fprintf(stderr, "slock-"VERSION"\n");
return 0; return 0;
#if MESSAGE_PATCH
case 'm':
message = EARGF(usage());
break;
case 'f':
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
font_names = XListFonts(dpy, "*", 10000 /* list 10000 fonts*/, &count_fonts);
for (i=0; i<count_fonts; i++) {
fprintf(stderr, "%s\n", *(font_names+i));
}
return 0;
#endif // MESSAGE_PATCH
default: default:
usage(); usage();
} ARGEND } ARGEND
@ -339,10 +493,15 @@ main(int argc, char **argv) {
dontkillme(); dontkillme();
#endif #endif
#if PAMAUTH_PATCH
/* the contents of hash are used to transport the current user name */
#endif // PAMAUTH_PATCH
hash = gethash(); hash = gethash();
errno = 0; errno = 0;
#if !PAMAUTH_PATCH
if (!crypt("", hash)) if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno)); die("slock: crypt: %s\n", strerror(errno));
#endif // PAMAUTH_PATCH
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n"); die("slock: cannot open display\n");
@ -363,10 +522,14 @@ main(int argc, char **argv) {
if (!(locks = calloc(nscreens, sizeof(struct lock *)))) if (!(locks = calloc(nscreens, sizeof(struct lock *))))
die("slock: out of memory\n"); die("slock: out of memory\n");
for (nlocks = 0, s = 0; s < nscreens; s++) { for (nlocks = 0, s = 0; s < nscreens; s++) {
if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) {
#if MESSAGE_PATCH
writemessage(dpy, locks[s]->win, s);
#endif // MESSAGE_PATCH
nlocks++; nlocks++;
else } else {
break; break;
}
} }
XSync(dpy, 0); XSync(dpy, 0);
@ -374,12 +537,31 @@ main(int argc, char **argv) {
if (nlocks != nscreens) if (nlocks != nscreens)
return 1; return 1;
#if DPMS_PATCH
/* DPMS-magic to disable the monitor */
if (!DPMSCapable(dpy))
die("slock: DPMSCapable failed\n");
if (!DPMSEnable(dpy))
die("slock: DPMSEnable failed\n");
if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
die("slock: DPMSGetTimeouts failed\n");
if (!standby || !suspend || !off)
/* set values if there arent some */
standby = suspend = off = 300;
DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime);
XFlush(dpy);
#endif // DPMS_PATCH
/* run post-lock command */ /* run post-lock command */
if (argc > 0) { if (argc > 0) {
switch (fork()) { switch (fork()) {
case -1: case -1:
die("slock: fork failed: %s\n", strerror(errno)); die("slock: fork failed: %s\n", strerror(errno));
case 0: case 0:
#if DPMS_PATCH
monitorreset(dpy, standby, suspend, off);
#endif // DPMS_PATCH
if (close(ConnectionNumber(dpy)) < 0) if (close(ConnectionNumber(dpy)) < 0)
die("slock: close: %s\n", strerror(errno)); die("slock: close: %s\n", strerror(errno));
execvp(argv[0], argv); execvp(argv[0], argv);
@ -390,6 +572,10 @@ main(int argc, char **argv) {
/* 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);
#if DPMS_PATCH
/* reset DPMS values to inital ones */
monitorreset(dpy, standby, suspend, off);
#endif // DPMS_PATCH
return 0; return 0;
} }