lock

Fork of xl, the simplest screen locker
git clone git://git.laack.co/lock.git
Log | Files | Refs | README | LICENSE

main.c (2547B)


      1 /*
      2  *  Simple, transparent screen locker in X11
      3  */
      4 #include <X11/Xlib.h>
      5 #include <X11/Xutil.h>
      6 #include <X11/keysym.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <unistd.h>
     10 #include <crypt.h>
     11 #include <string.h>
     12 #include <pwd.h>
     13 
     14 #ifdef NEED_SHADOW
     15 #include <shadow.h>
     16 #endif
     17 
     18 int
     19 main(int argc, char *argv[])
     20 {
     21     Display *display;
     22     Window root;
     23     int len = 0, i;
     24     XEvent ev;
     25     char keybuffer[256], *passwd;
     26 
     27     if (argc > 1) {
     28 	setenv("XLPASSWD", argv[1], 1);
     29 	execl("/proc/self/exe", argv[0], NULL);
     30 	fprintf(stderr, "failed to execute self, use XLPASSWD environment\n");
     31 	exit(1);
     32     }
     33     else if ((passwd = getenv("XLPASSWD")))
     34 	passwd = strdup(crypt(passwd, "ax"));
     35     else {
     36 #ifndef NEED_SHADOW
     37 	passwd = getpwuid(getuid())->pw_passwd;
     38 #else
     39 	{
     40 	    struct spwd *sp = getspnam(getpwuid(getuid())->pw_name);
     41 	    if (sp)
     42 		passwd = sp->sp_pwdp;
     43 	    else {
     44 		fprintf(stderr, "could not get shadow entry\n");
     45 		exit(1);
     46 	    }
     47 	}
     48 #endif
     49 	if (!passwd) {
     50 	    fprintf(stderr, "could not get passwd\n");
     51 	    exit(1);
     52 	}
     53     }
     54 
     55     if (strlen(passwd) < 2) {
     56 	fprintf(stderr, "passwd too short\n");
     57 	exit(1);
     58     }
     59 
     60     if ((display = XOpenDisplay(NULL)) == NULL) {
     61 	fprintf(stderr, "could not connect to $DISPLAY\n");
     62 	exit(1);
     63     }
     64 
     65     root = DefaultRootWindow(display);
     66 
     67     for (i = 0; i < 1000; i++) {
     68         if (XGrabPointer(display, root, 1, ButtonPress, GrabModeAsync,
     69                          GrabModeAsync, None, None, CurrentTime) == GrabSuccess)
     70             break;
     71         usleep(1000);
     72     }
     73 
     74 
     75     if (i == 1000) {
     76         fprintf(stderr, "could not grab pointer\n");
     77         exit(1);
     78     }
     79 
     80     for (i = 0; i < 1000; i++) {
     81         if (XGrabKeyboard(display, root, 0, GrabModeAsync,
     82                           GrabModeAsync, CurrentTime) == GrabSuccess)
     83             break;
     84         usleep(1000);
     85     }
     86     if (i == 1000) {
     87         XUngrabPointer(display, CurrentTime);
     88         fprintf(stderr, "could not grab keyboard\n");
     89         exit(1);
     90     }
     91     XSelectInput(display, root, KeyPressMask);
     92 
     93     while (XNextEvent(display, &ev), 1) {
     94 	if (ev.type == KeyPress) {
     95 	    KeySym keysym;
     96 	    XComposeStatus compose;
     97 	    if (len > sizeof(keybuffer)-10)
     98 		len = 0;
     99 	    i = XLookupString(&ev.xkey, keybuffer+len, 10, &keysym, &compose);
    100 
    101 	    if (keysym == XK_Return) {
    102 		keybuffer[len] = 0;
    103 		if (len && !strcmp(crypt(keybuffer, passwd), passwd)) {
    104 		    XUngrabKeyboard(display, CurrentTime);
    105 		    XUngrabPointer(display, CurrentTime);
    106 		    exit(0);
    107 		} else
    108 		    len = 0;
    109 	    } else
    110 		len += i;
    111 	}
    112     }
    113 }