]> git.sur5r.net Git - i3/i3lock/blob - i3lock.c
Forgot one instance of slock in Makefile
[i3/i3lock] / i3lock.c
1 /* See LICENSE file for license details. */
2 #define _XOPEN_SOURCE 500
3 #if HAVE_SHADOW_H
4 #include <shadow.h>
5 #endif
6
7 #include <ctype.h>
8 #include <pwd.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <X11/keysym.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18
19 #if HAVE_BSD_AUTH
20 #include <login_cap.h>
21 #include <bsd_auth.h>
22 #endif
23
24 static void
25 die(const char *errstr, ...) {
26         va_list ap;
27
28         va_start(ap, errstr);
29         vfprintf(stderr, errstr, ap);
30         va_end(ap);
31         exit(EXIT_FAILURE);
32 }
33
34 #ifndef HAVE_BSD_AUTH
35 static const char *
36 get_password() { /* only run as root */
37         const char *rval;
38         struct passwd *pw;
39
40         if(geteuid() != 0)
41                 die("slock: cannot retrieve password entry (make sure to suid slock)\n");
42         pw = getpwuid(getuid());
43         endpwent();
44         rval =  pw->pw_passwd;
45
46 #if HAVE_SHADOW_H
47         {
48                 struct spwd *sp;
49                 sp = getspnam(getenv("USER"));
50                 endspent();
51                 rval = sp->sp_pwdp;
52         }
53 #endif
54
55         /* drop privileges */
56         if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0)
57                 die("slock: cannot drop privileges\n");
58         return rval;
59 }
60 #endif
61
62 int
63 main(int argc, char **argv) {
64         char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
65         char buf[32], passwd[256];
66         int num, screen;
67
68 #ifndef HAVE_BSD_AUTH
69         const char *pws;
70 #endif
71         unsigned int len;
72         Bool running = True;
73         Cursor invisible;
74         Display *dpy;
75         KeySym ksym;
76         Pixmap pmap;
77         Window root, w;
78         XColor black, dummy;
79         XEvent ev;
80         XSetWindowAttributes wa;
81
82         if((argc == 2) && !strcmp("-v", argv[1]))
83                 die("i3lock-"VERSION", © 2009 Michael Stapelberg\n"
84                     "based on slock, which is © 2006-2008 Anselm R Garbe\n");
85         else if(argc != 1)
86                 die("usage: slock [-v]\n");
87
88 #ifndef HAVE_BSD_AUTH
89         pws = get_password();
90 #endif
91
92         if(!(dpy = XOpenDisplay(0)))
93                 die("slock: cannot open display\n");
94         screen = DefaultScreen(dpy);
95         root = RootWindow(dpy, screen);
96
97         if (fork() != 0)
98                 return 0;
99
100         /* init */
101         wa.override_redirect = 1;
102         wa.background_pixel = WhitePixel(dpy, screen);
103         w = XCreateWindow(dpy, root, 0, 0, DisplayWidth(dpy, screen), DisplayHeight(dpy, screen),
104                         0, DefaultDepth(dpy, screen), CopyFromParent,
105                         DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixel, &wa);
106         XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "black", &black, &dummy);
107         pmap = XCreateBitmapFromData(dpy, w, curs, 8, 8);
108         invisible = XCreatePixmapCursor(dpy, pmap, pmap, &black, &black, 0, 0);
109         XDefineCursor(dpy, w, invisible);
110         XMapRaised(dpy, w);
111         for(len = 1000; len; len--) {
112                 if(XGrabPointer(dpy, root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
113                         GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess)
114                         break;
115                 usleep(1000);
116         }
117         if((running = running && (len > 0))) {
118                 for(len = 1000; len; len--) {
119                         if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
120                                 == GrabSuccess)
121                                 break;
122                         usleep(1000);
123                 }
124                 running = (len > 0);
125         }
126         len = 0;
127         XSync(dpy, False);
128
129         /* main event loop */
130         while(running && !XNextEvent(dpy, &ev)) {
131                 if(ev.type == KeyPress) {
132                         buf[0] = 0;
133                         num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0);
134                         if(IsKeypadKey(ksym)) {
135                                 if(ksym == XK_KP_Enter)
136                                         ksym = XK_Return;
137                                 else if(ksym >= XK_KP_0 && ksym <= XK_KP_9)
138                                         ksym = (ksym - XK_KP_0) + XK_0;
139                         }
140                         if(IsFunctionKey(ksym) || IsKeypadKey(ksym)
141                                         || IsMiscFunctionKey(ksym) || IsPFKey(ksym)
142                                         || IsPrivateKeypadKey(ksym))
143                                 continue;
144                         switch(ksym) {
145                         case XK_Return:
146                                 passwd[len] = 0;
147 #ifdef HAVE_BSD_AUTH
148                                 running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd);
149 #else
150                                 running = strcmp(crypt(passwd, pws), pws);
151 #endif
152                                 len = 0;
153                                 break;
154                         case XK_Escape:
155                                 len = 0;
156                                 break;
157                         case XK_BackSpace:
158                                 if(len)
159                                         --len;
160                                 break;
161                         default:
162                                 if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { 
163                                         memcpy(passwd + len, buf, num);
164                                         len += num;
165                                 }
166                                 break;
167                         }
168                 }
169         }
170         XUngrabPointer(dpy, CurrentTime);
171         XFreePixmap(dpy, pmap);
172         XDestroyWindow(dpy, w);
173         XCloseDisplay(dpy);
174         return 0;
175 }