aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnselm R Garbe <garbeam@gmail.com>2009-11-26 12:53:26 +0000
committerAnselm R Garbe <garbeam@gmail.com>2009-11-26 12:53:26 +0000
commit732d2b3bf5da3a1883b3246062aa556a59b8517c (patch)
tree85dcc7c6506f933d327bc801972e3791e0140948
parent0cb05bdb75ac13f010d51e267007ca1c869763ec (diff)
applied Fernando Silveira's multiscreen patch for old style multihead setups
-rw-r--r--slock.c220
1 files changed, 151 insertions, 69 deletions
diff --git a/slock.c b/slock.c
index 8490dae..eece4e3 100644
--- a/slock.c
+++ b/slock.c
@@ -5,6 +5,7 @@
5#endif 5#endif
6 6
7#include <ctype.h> 7#include <ctype.h>
8#include <errno.h>
8#include <pwd.h> 9#include <pwd.h>
9#include <stdarg.h> 10#include <stdarg.h>
10#include <stdlib.h> 11#include <stdlib.h>
@@ -15,31 +16,42 @@
15#include <X11/keysym.h> 16#include <X11/keysym.h>
16#include <X11/Xlib.h> 17#include <X11/Xlib.h>
17#include <X11/Xutil.h> 18#include <X11/Xutil.h>
18#include <X11/extensions/dpms.h>
19 19
20#if HAVE_BSD_AUTH 20#if HAVE_BSD_AUTH
21#include <login_cap.h> 21#include <login_cap.h>
22#include <bsd_auth.h> 22#include <bsd_auth.h>
23#endif 23#endif
24 24
25struct st_lock {
26 int screen;
27 Window root, w;
28 Pixmap pmap;
29};
30
31extern const char *__progname;
32
25static void 33static void
26die(const char *errstr, ...) { 34die(const char *errstr, ...) {
27 va_list ap; 35 va_list ap;
28 36
37 fprintf(stderr, "%s: ", __progname);
29 va_start(ap, errstr); 38 va_start(ap, errstr);
30 vfprintf(stderr, errstr, ap); 39 vfprintf(stderr, errstr, ap);
31 va_end(ap); 40 va_end(ap);
41 fprintf(stderr, "\n");
42 fflush(stderr);
43
32 exit(EXIT_FAILURE); 44 exit(EXIT_FAILURE);
33} 45}
34 46
35#ifndef HAVE_BSD_AUTH 47#ifndef HAVE_BSD_AUTH
36static const char * 48static const char *
37get_password() { /* only run as root */ 49get_password(void) { /* only run as root */
38 const char *rval; 50 const char *rval;
39 struct passwd *pw; 51 struct passwd *pw;
40 52
41 if(geteuid() != 0) 53 if(geteuid() != 0)
42 die("slock: cannot retrieve password entry (make sure to suid slock)\n"); 54 die("cannot retrieve password entry (make sure to suid slock)");
43 pw = getpwuid(getuid()); 55 pw = getpwuid(getuid());
44 endpwent(); 56 endpwent();
45 rval = pw->pw_passwd; 57 rval = pw->pw_passwd;
@@ -55,81 +67,34 @@ get_password() { /* only run as root */
55 67
56 /* drop privileges */ 68 /* drop privileges */
57 if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) 69 if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0)
58 die("slock: cannot drop privileges\n"); 70 die("cannot drop privileges");
59 return rval; 71 return rval;
60} 72}
61#endif 73#endif
62 74
63int 75static void
64main(int argc, char **argv) { 76#ifdef HAVE_BSD_AUTH
65 char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; 77read_password(Display *dpy)
78#else
79read_password(Display *dpy, const char *pws)
80#endif
81{
66 char buf[32], passwd[256]; 82 char buf[32], passwd[256];
67 int num, screen; 83 int num;
68 84
69#ifndef HAVE_BSD_AUTH
70 const char *pws;
71#endif
72 unsigned int len; 85 unsigned int len;
73 Bool running = True; 86 Bool running = True;
74 Cursor invisible;
75 Display *dpy;
76 KeySym ksym; 87 KeySym ksym;
77 Pixmap pmap;
78 Window root, w;
79 XColor black, dummy;
80 XEvent ev; 88 XEvent ev;
81 XSetWindowAttributes wa;
82 CARD16 standby, suspend, off;
83
84 if((argc == 2) && !strcmp("-v", argv[1]))
85 die("slock-"VERSION", © 2006-2008 Anselm R Garbe\n");
86 else if(argc != 1)
87 die("usage: slock [-v]\n");
88
89#ifndef HAVE_BSD_AUTH
90 pws = get_password();
91#endif
92
93 if(!(dpy = XOpenDisplay(0)))
94 die("slock: cannot open display\n");
95 screen = DefaultScreen(dpy);
96 root = RootWindow(dpy, screen);
97 89
98 /* init */
99 wa.override_redirect = 1;
100 wa.background_pixel = BlackPixel(dpy, screen);
101 w = XCreateWindow(dpy, root, 0, 0, DisplayWidth(dpy, screen), DisplayHeight(dpy, screen),
102 0, DefaultDepth(dpy, screen), CopyFromParent,
103 DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixel, &wa);
104 XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "black", &black, &dummy);
105 pmap = XCreateBitmapFromData(dpy, w, curs, 8, 8);
106 invisible = XCreatePixmapCursor(dpy, pmap, pmap, &black, &black, 0, 0);
107 XDefineCursor(dpy, w, invisible);
108 XMapRaised(dpy, w);
109 for(len = 1000; len; len--) {
110 if(XGrabPointer(dpy, root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
111 GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess)
112 break;
113 usleep(1000);
114 }
115 if((running = running && (len > 0))) {
116 for(len = 1000; len; len--) {
117 if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
118 == GrabSuccess)
119 break;
120 usleep(1000);
121 }
122 running = (len > 0);
123 }
124 len = 0; 90 len = 0;
125 XSync(dpy, False); 91 running = True;
126 92
127 if(DPMSCapable(dpy)) { /* save and customize DPMS settings */ 93 /* As "slock" stands for "Simple X display locker", the DPMS settings
128 DPMSGetTimeouts(dpy, &standby, &suspend, &off); 94 * had been removed and you can set it with "xset" or some other
129 DPMSSetTimeouts(dpy, 10, 30, 90); 95 * utility. This way the user can easily set a customized DPMS
130 } 96 * timeout. */
131 97
132 /* main event loop */
133 while(running && !XNextEvent(dpy, &ev)) { 98 while(running && !XNextEvent(dpy, &ev)) {
134 if(ev.type == KeyPress) { 99 if(ev.type == KeyPress) {
135 buf[0] = 0; 100 buf[0] = 0;
@@ -172,12 +137,129 @@ main(int argc, char **argv) {
172 } 137 }
173 } 138 }
174 } 139 }
175 if(DPMSCapable(dpy)) { /* restore DPMS settings */ 140}
176 DPMSSetTimeouts(dpy, standby, suspend, off); 141
177 } 142static void
143unlockscreen(Display *dpy, struct st_lock *lock) {
144 if (dpy == NULL || lock == NULL)
145 return;
146
178 XUngrabPointer(dpy, CurrentTime); 147 XUngrabPointer(dpy, CurrentTime);
179 XFreePixmap(dpy, pmap); 148 XFreePixmap(dpy, lock->pmap);
180 XDestroyWindow(dpy, w); 149 XDestroyWindow(dpy, lock->w);
150
151 free(lock);
152}
153
154static struct st_lock *
155lockscreen(Display *dpy, int screen) {
156 char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
157 unsigned int len;
158 struct st_lock *lock;
159 Bool running = True;
160 XColor black, dummy;
161 XSetWindowAttributes wa;
162 Cursor invisible;
163
164 if (dpy == NULL || screen < 0)
165 return NULL;
166
167 lock = malloc(sizeof(struct st_lock));
168 if (lock == NULL)
169 return NULL;
170
171 lock->screen = screen;
172
173 lock->root = RootWindow(dpy, lock->screen);
174
175 /* init */
176 wa.override_redirect = 1;
177 wa.background_pixel = BlackPixel(dpy, lock->screen);
178 lock->w = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen),
179 0, DefaultDepth(dpy, lock->screen), CopyFromParent,
180 DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa);
181 XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), "black", &black, &dummy);
182 lock->pmap = XCreateBitmapFromData(dpy, lock->w, curs, 8, 8);
183 invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &black, &black, 0, 0);
184 XDefineCursor(dpy, lock->w, invisible);
185 XMapRaised(dpy, lock->w);
186 for(len = 1000; len; len--) {
187 if(XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
188 GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess)
189 break;
190 usleep(1000);
191 }
192 if((running = running && (len > 0))) {
193 for(len = 1000; len; len--) {
194 if(XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
195 == GrabSuccess)
196 break;
197 usleep(1000);
198 }
199 running = (len > 0);
200 }
201
202 if (!running) {
203 unlockscreen(dpy, lock);
204 lock = NULL;
205 }
206
207 return lock;
208}
209
210static void
211usage(void) {
212 fprintf(stderr, "usage: %s -v", __progname);
213 exit(EXIT_FAILURE);
214}
215
216int
217main(int argc, char **argv) {
218#ifndef HAVE_BSD_AUTH
219 const char *pws;
220#endif
221 Display *dpy;
222 int nscreens, screen;
223
224 struct st_lock **locks;
225
226 if((argc == 2) && !strcmp("-v", argv[1]))
227 die("slock-%s, © 2006-2008 Anselm R Garbe", VERSION);
228 else if(argc != 1)
229 usage();
230
231#ifndef HAVE_BSD_AUTH
232 pws = get_password();
233#endif
234
235 if(!(dpy = XOpenDisplay(0)))
236 die("cannot open display");
237
238 /* Get the number of screens in display "dpy" and blank them all. */
239 nscreens = ScreenCount(dpy);
240 locks = malloc(sizeof(struct st_lock *) * nscreens);
241 if (locks == NULL)
242 die("malloc: %s", strerror(errno));
243
244 for (screen = 0; screen < nscreens; screen++)
245 locks[screen] = lockscreen(dpy, screen);
246
247 XSync(dpy, False);
248
249 /* Everything is now blank. Now wait for the correct password. */
250#ifdef HAVE_BSD_AUTH
251 read_password(dpy);
252#else
253 read_password(dpy, pws);
254#endif
255
256 /* Password ok, unlock everything and quit. */
257 for (screen = 0; screen < nscreens; screen++)
258 unlockscreen(dpy, locks[screen]);
259
260 free(locks);
261
181 XCloseDisplay(dpy); 262 XCloseDisplay(dpy);
263
182 return 0; 264 return 0;
183} 265}