slock with DPMS and other tweaks

Remove cleanup and deglobalize and rework data structures

The cleanup removal is a joint-venture with Markus. We assume the X server does
the cleanup, so we don't need it. The idea is that the fds are closed at exit
and thus already indicate to the X server that the client has quit. Analogously
the same applies to freeing memory sections previously allocated for the X
server.

We love XXXXXL burgers and therefore removed
XUngrabPointer
XUngrabKeyboard
XFreeColors
XFreePixmap
XDestroyWindow
Lines of Code.

For a project like slock there is no need to carry around global state. By
moving the three structures to main() it is now clear which functions modify
which state, greatly improving the readability of the code, especially given
slock is a suid program.

authored by

FRIGN and committed by
Markus Teich
b00f444a cd3c546c

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