Remove cleanup and deglobalize and rework data structures - slock - simple X display locker utility
 (HTM) git clone git://git.suckless.org/slock
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit b00f444a4ea0d9ffa5cd7dcda71c97cdf05d322e
 (DIR) parent cd3c546c37d91e24b8c55bab88bfcb920d8ea895
 (HTM) Author: FRIGN <dev@frign.de>
       Date:   Sun, 11 Sep 2016 23:08:19 +0200
       
       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.
       
       Diffstat:
         M slock.c                             |      78 +++++++++----------------------
       
       1 file changed, 23 insertions(+), 55 deletions(-)
       ---
 (DIR) diff --git a/slock.c b/slock.c
       @@ -33,18 +33,18 @@ enum {
        
        #include "config.h"
        
       -typedef struct {
       +struct lock {
                int screen;
                Window root, win;
                Pixmap pmap;
                unsigned long colors[NUMCOLS];
       -} Lock;
       +};
        
       -static Lock **locks;
       -static int nscreens;
       -static Bool rr;
       -static int rrevbase;
       -static int rrerrbase;
       +struct xrandr {
       +        int active;
       +        int evbase;
       +        int errbase;
       +};
        
        static void
        die(const char *errstr, ...)
       @@ -123,7 +123,8 @@ getpw(void)
        }
        
        static void
       -readpw(Display *dpy, const char *pws)
       +readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
       +       const char *pws)
        {
                char buf[32], passwd[256], *encrypted;
                int num, screen, running, failure;
       @@ -194,7 +195,7 @@ readpw(Display *dpy, const char *pws)
                                        }
                                        oldc = color;
                                }
       -                } else if (rr && ev.type == rrevbase + RRScreenChangeNotify) {
       +                } else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) {
                                XRRScreenChangeNotifyEvent *rre = (XRRScreenChangeNotifyEvent*)&ev;
                                for (screen = 0; screen < nscreens; screen++) {
                                        if (locks[screen]->win == rre->window) {
       @@ -207,44 +208,17 @@ readpw(Display *dpy, const char *pws)
                }
        }
        
       -static void
       -unlockscreen(Display *dpy, Lock *lock)
       -{
       -        if(dpy == NULL || lock == NULL)
       -                return;
       -
       -        XUngrabPointer(dpy, CurrentTime);
       -        XUngrabKeyboard(dpy, CurrentTime);
       -        XFreeColors(dpy, DefaultColormap(dpy, lock->screen), lock->colors, NUMCOLS, 0);
       -        XFreePixmap(dpy, lock->pmap);
       -        XDestroyWindow(dpy, lock->win);
       -
       -        free(lock);
       -}
       -
       -static void
       -cleanup(Display *dpy)
       -{
       -        int s;
       -
       -        for (s = 0; s < nscreens; ++s)
       -                unlockscreen(dpy, locks[s]);
       -
       -        free(locks);
       -        XCloseDisplay(dpy);
       -}
       -
       -static Lock *
       -lockscreen(Display *dpy, int screen)
       +static struct lock *
       +lockscreen(Display *dpy, struct xrandr *rr, int screen)
        {
                char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
                int i, ptgrab, kbgrab;
       -        Lock *lock;
       +        struct lock *lock;
                XColor color, dummy;
                XSetWindowAttributes wa;
                Cursor invisible;
        
       -        if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(Lock))))
       +        if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock))))
                        return NULL;
        
                lock->screen = screen;
       @@ -281,7 +255,7 @@ lockscreen(Display *dpy, int screen)
                        /* input is grabbed: we can lock the screen */
                        if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
                                XMapRaised(dpy, lock->win);
       -                        if (rr)
       +                        if (rr->active)
                                        XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
        
                                XSelectInput(dpy, lock->root, SubstructureNotifyMask);
       @@ -312,13 +286,15 @@ usage(void)
        
        int
        main(int argc, char **argv) {
       +        struct xrandr rr;
       +        struct lock **locks;
                struct passwd *pwd;
                struct group *grp;
                uid_t duid;
                gid_t dgid;
                const char *pws;
                Display *dpy;
       -        int s, nlocks;
       +        int s, nlocks, nscreens;
        
                ARGBEGIN {
                case 'v':
       @@ -360,16 +336,14 @@ main(int argc, char **argv) {
                        die("slock: setuid: %s\n", strerror(errno));
        
                /* check for Xrandr support */
       -        rr = XRRQueryExtension(dpy, &rrevbase, &rrerrbase);
       +        rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
        
                /* get number of screens in display "dpy" and blank them */
                nscreens = ScreenCount(dpy);
       -        if (!(locks = calloc(nscreens, sizeof(Lock *)))) {
       -                XCloseDisplay(dpy);
       +        if (!(locks = calloc(nscreens, sizeof(struct lock *))))
                        die("slock: out of memory\n");
       -        }
                for (nlocks = 0, s = 0; s < nscreens; s++) {
       -                if ((locks[s] = lockscreen(dpy, s)) != NULL)
       +                if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL)
                                nlocks++;
                        else
                                break;
       @@ -377,16 +351,13 @@ main(int argc, char **argv) {
                XSync(dpy, 0);
        
                /* did we manage to lock everything? */
       -        if (nlocks != nscreens) {
       -                cleanup(dpy);
       +        if (nlocks != nscreens)
                        return 1;
       -        }
        
                /* run post-lock command */
                if (argc > 0) {
                        switch (fork()) {
                        case -1:
       -                        cleanup(dpy);
                                die("slock: fork failed: %s\n", strerror(errno));
                        case 0:
                                if (close(ConnectionNumber(dpy)) < 0)
       @@ -399,10 +370,7 @@ main(int argc, char **argv) {
                }
        
                /* everything is now blank. Wait for the correct password */
       -        readpw(dpy, pws);
       -
       -        /* password ok, unlock everything and quit */
       -        cleanup(dpy);
       +        readpw(dpy, &rr, locks, nscreens, pws);
        
                return 0;
        }