diff options
| -rw-r--r-- | slock.c | 78 |
1 files changed, 23 insertions, 55 deletions
| @@ -33,18 +33,18 @@ enum { | |||
| 33 | 33 | ||
| 34 | #include "config.h" | 34 | #include "config.h" |
| 35 | 35 | ||
| 36 | typedef struct { | 36 | struct lock { |
| 37 | int screen; | 37 | int screen; |
| 38 | Window root, win; | 38 | Window root, win; |
| 39 | Pixmap pmap; | 39 | Pixmap pmap; |
| 40 | unsigned long colors[NUMCOLS]; | 40 | unsigned long colors[NUMCOLS]; |
| 41 | } Lock; | 41 | }; |
| 42 | 42 | ||
| 43 | static Lock **locks; | 43 | struct xrandr { |
| 44 | static int nscreens; | 44 | int active; |
| 45 | static Bool rr; | 45 | int evbase; |
| 46 | static int rrevbase; | 46 | int errbase; |
| 47 | static int rrerrbase; | 47 | }; |
| 48 | 48 | ||
| 49 | static void | 49 | static void |
| 50 | die(const char *errstr, ...) | 50 | die(const char *errstr, ...) |
| @@ -123,7 +123,8 @@ getpw(void) | |||
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static void | 125 | static void |
| 126 | readpw(Display *dpy, const char *pws) | 126 | readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, |
| 127 | const char *pws) | ||
| 127 | { | 128 | { |
| 128 | char buf[32], passwd[256], *encrypted; | 129 | char buf[32], passwd[256], *encrypted; |
| 129 | int num, screen, running, failure; | 130 | int num, screen, running, failure; |
| @@ -194,7 +195,7 @@ readpw(Display *dpy, const char *pws) | |||
| 194 | } | 195 | } |
| 195 | oldc = color; | 196 | oldc = color; |
| 196 | } | 197 | } |
| 197 | } else if (rr && ev.type == rrevbase + RRScreenChangeNotify) { | 198 | } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) { |
| 198 | XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev; | 199 | XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev; |
| 199 | for (screen = 0; screen < nscreens; screen++) { | 200 | for (screen = 0; screen < nscreens; screen++) { |
| 200 | if (locks[screen]->win == rre->window) { | 201 | if (locks[screen]->win == rre->window) { |
| @@ -207,44 +208,17 @@ readpw(Display *dpy, const char *pws) | |||
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| 209 | 210 | ||
| 210 | static void | 211 | static struct lock * |
| 211 | unlockscreen(Display *dpy, Lock *lock) | 212 | lockscreen(Display *dpy, struct xrandr *rr, int screen) |
| 212 | { | ||
| 213 | if(dpy == NULL || lock == NULL) | ||
| 214 | return; | ||
| 215 | |||
| 216 | XUngrabPointer(dpy, CurrentTime); | ||
| 217 | XUngrabKeyboard(dpy, CurrentTime); | ||
| 218 | XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0); | ||
| 219 | XFreePixmap(dpy, lock->pmap); | ||
| 220 | XDestroyWindow(dpy, lock->win); | ||
| 221 | |||
| 222 | free(lock); | ||
| 223 | } | ||
| 224 | |||
| 225 | static void | ||
| 226 | cleanup(Display *dpy) | ||
| 227 | { | ||
| 228 | int s; | ||
| 229 | |||
| 230 | for (s = 0; s < nscreens; ++s) | ||
| 231 | unlockscreen(dpy, locks[s]); | ||
| 232 | |||
| 233 | free(locks); | ||
| 234 | XCloseDisplay(dpy); | ||
| 235 | } | ||
| 236 | |||
| 237 | static Lock * | ||
| 238 | lockscreen(Display *dpy, int screen) | ||
| 239 | { | 213 | { |
| 240 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; | 214 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; |
| 241 | int i, ptgrab, kbgrab; | 215 | int i, ptgrab, kbgrab; |
| 242 | Lock *lock; | 216 | struct lock *lock; |
| 243 | XColor color, dummy; | 217 | XColor color, dummy; |
| 244 | XSetWindowAttributes wa; | 218 | XSetWindowAttributes wa; |
| 245 | Cursor invisible; | 219 | Cursor invisible; |
| 246 | 220 | ||
| 247 | if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock)))) | 221 | if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock)))) |
| 248 | return NULL; | 222 | return NULL; |
| 249 | 223 | ||
| 250 | lock->screen = screen; | 224 | lock->screen = screen; |
| @@ -281,7 +255,7 @@ lockscreen(Display *dpy, int screen) | |||
| 281 | /* input is grabbed: we can lock the screen */ | 255 | /* input is grabbed: we can lock the screen */ |
| 282 | if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { | 256 | if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) { |
| 283 | XMapRaised(dpy, lock->win); | 257 | XMapRaised(dpy, lock->win); |
| 284 | if (rr) | 258 | if (rr->active) |
| 285 | XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); | 259 | XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask); |
| 286 | 260 | ||
| 287 | XSelectInput(dpy, lock->root, SubstructureNotifyMask); | 261 | XSelectInput(dpy, lock->root, SubstructureNotifyMask); |
| @@ -312,13 +286,15 @@ usage(void) | |||
| 312 | 286 | ||
| 313 | int | 287 | int |
| 314 | main(int argc, char **argv) { | 288 | main(int argc, char **argv) { |
| 289 | struct xrandr rr; | ||
| 290 | struct lock **locks; | ||
| 315 | struct passwd *pwd; | 291 | struct passwd *pwd; |
| 316 | struct group *grp; | 292 | struct group *grp; |
| 317 | uid_t duid; | 293 | uid_t duid; |
| 318 | gid_t dgid; | 294 | gid_t dgid; |
| 319 | const char *pws; | 295 | const char *pws; |
| 320 | Display *dpy; | 296 | Display *dpy; |
| 321 | int s, nlocks; | 297 | int s, nlocks, nscreens; |
| 322 | 298 | ||
| 323 | ARGBEGIN { | 299 | ARGBEGIN { |
| 324 | case 'v': | 300 | case 'v': |
| @@ -360,16 +336,14 @@ main(int argc, char **argv) { | |||
| 360 | die("slock: setuid: %s\n", strerror(errno)); | 336 | die("slock: setuid: %s\n", strerror(errno)); |
| 361 | 337 | ||
| 362 | /* check for Xrandr support */ | 338 | /* check for Xrandr support */ |
| 363 | rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase); | 339 | rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); |
| 364 | 340 | ||
| 365 | /* get number of screens in display "dpy" and blank them */ | 341 | /* get number of screens in display "dpy" and blank them */ |
| 366 | nscreens = ScreenCount(dpy); | 342 | nscreens = ScreenCount(dpy); |
| 367 | if (!(locks = calloc(nscreens, sizeof(Lock *)))) { | 343 | if (!(locks = calloc(nscreens, sizeof(struct lock *)))) |
| 368 | XCloseDisplay(dpy); | ||
| 369 | die("slock: out of memory\n"); | 344 | die("slock: out of memory\n"); |
| 370 | } | ||
| 371 | for (nlocks = 0, s = 0; s < nscreens; s++) { | 345 | for (nlocks = 0, s = 0; s < nscreens; s++) { |
| 372 | if ((locks[s] = lockscreen(dpy, s)) != NULL) | 346 | if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL) |
| 373 | nlocks++; | 347 | nlocks++; |
| 374 | else | 348 | else |
| 375 | break; | 349 | break; |
| @@ -377,16 +351,13 @@ main(int argc, char **argv) { | |||
| 377 | XSync(dpy, 0); | 351 | XSync(dpy, 0); |
| 378 | 352 | ||
| 379 | /* did we manage to lock everything? */ | 353 | /* did we manage to lock everything? */ |
| 380 | if (nlocks != nscreens) { | 354 | if (nlocks != nscreens) |
| 381 | cleanup(dpy); | ||
| 382 | return 1; | 355 | return 1; |
| 383 | } | ||
| 384 | 356 | ||
| 385 | /* run post-lock command */ | 357 | /* run post-lock command */ |
| 386 | if (argc > 0) { | 358 | if (argc > 0) { |
| 387 | switch (fork()) { | 359 | switch (fork()) { |
| 388 | case -1: | 360 | case -1: |
| 389 | cleanup(dpy); | ||
| 390 | die("slock: fork failed: %s\n", strerror(errno)); | 361 | die("slock: fork failed: %s\n", strerror(errno)); |
| 391 | case 0: | 362 | case 0: |
| 392 | if (close(ConnectionNumber(dpy)) < 0) | 363 | if (close(ConnectionNumber(dpy)) < 0) |
| @@ -399,10 +370,7 @@ main(int argc, char **argv) { | |||
| 399 | } | 370 | } |
| 400 | 371 | ||
| 401 | /* everything is now blank. Wait for the correct password */ | 372 | /* everything is now blank. Wait for the correct password */ |
| 402 | readpw(dpy, pws); | 373 | readpw(dpy, &rr, locks, nscreens, pws); |
| 403 | |||
| 404 | /* password ok, unlock everything and quit */ | ||
| 405 | cleanup(dpy); | ||
| 406 | 374 | ||
| 407 | return 0; | 375 | return 0; |
| 408 | } | 376 | } |
