diff options
Diffstat (limited to 'slock.c')
-rw-r--r-- | slock.c | 220 |
1 files changed, 151 insertions, 69 deletions
@@ -5,6 +5,7 @@ | |||
5 | #endif | 5 | #endif |
6 | 6 | ||
7 | #include <ctype.h> | 7 | #include <ctype.h> |
8 | #include <errno.h> | ||
8 | #include <pwd.h> | 9 | #include <pwd.h> |
9 | #include <stdarg.h> | 10 | #include <stdarg.h> |
10 | #include <stdlib.h> | 11 | #include <stdlib.h> |
@@ -15,31 +16,42 @@ | |||
15 | #include <X11/keysym.h> | 16 | #include <X11/keysym.h> |
16 | #include <X11/Xlib.h> | 17 | #include <X11/Xlib.h> |
17 | #include <X11/Xutil.h> | 18 | #include <X11/Xutil.h> |
18 | #include <X11/extensions/dpms.h> | ||
19 | 19 | ||
20 | #if HAVE_BSD_AUTH | 20 | #if HAVE_BSD_AUTH |
21 | #include <login_cap.h> | 21 | #include <login_cap.h> |
22 | #include <bsd_auth.h> | 22 | #include <bsd_auth.h> |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | struct st_lock { | ||
26 | int screen; | ||
27 | Window root, w; | ||
28 | Pixmap pmap; | ||
29 | }; | ||
30 | |||
31 | extern const char *__progname; | ||
32 | |||
25 | static void | 33 | static void |
26 | die(const char *errstr, ...) { | 34 | die(const char *errstr, ...) { |
27 | va_list ap; | 35 | va_list ap; |
28 | 36 | ||
37 | fprintf(stderr, "%s: ", __progname); | ||
29 | va_start(ap, errstr); | 38 | va_start(ap, errstr); |
30 | vfprintf(stderr, errstr, ap); | 39 | vfprintf(stderr, errstr, ap); |
31 | va_end(ap); | 40 | va_end(ap); |
41 | fprintf(stderr, "\n"); | ||
42 | fflush(stderr); | ||
43 | |||
32 | exit(EXIT_FAILURE); | 44 | exit(EXIT_FAILURE); |
33 | } | 45 | } |
34 | 46 | ||
35 | #ifndef HAVE_BSD_AUTH | 47 | #ifndef HAVE_BSD_AUTH |
36 | static const char * | 48 | static const char * |
37 | get_password() { /* only run as root */ | 49 | get_password(void) { /* only run as root */ |
38 | const char *rval; | 50 | const char *rval; |
39 | struct passwd *pw; | 51 | struct passwd *pw; |
40 | 52 | ||
41 | if(geteuid() != 0) | 53 | if(geteuid() != 0) |
42 | die("slock: cannot retrieve password entry (make sure to suid slock)\n"); | 54 | die("cannot retrieve password entry (make sure to suid slock)"); |
43 | pw = getpwuid(getuid()); | 55 | pw = getpwuid(getuid()); |
44 | endpwent(); | 56 | endpwent(); |
45 | rval = pw->pw_passwd; | 57 | rval = pw->pw_passwd; |
@@ -55,81 +67,34 @@ get_password() { /* only run as root */ | |||
55 | 67 | ||
56 | /* drop privileges */ | 68 | /* drop privileges */ |
57 | if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) | 69 | if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) |
58 | die("slock: cannot drop privileges\n"); | 70 | die("cannot drop privileges"); |
59 | return rval; | 71 | return rval; |
60 | } | 72 | } |
61 | #endif | 73 | #endif |
62 | 74 | ||
63 | int | 75 | static void |
64 | main(int argc, char **argv) { | 76 | #ifdef HAVE_BSD_AUTH |
65 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; | 77 | read_password(Display *dpy) |
78 | #else | ||
79 | read_password(Display *dpy, const char *pws) | ||
80 | #endif | ||
81 | { | ||
66 | char buf[32], passwd[256]; | 82 | char buf[32], passwd[256]; |
67 | int num, screen; | 83 | int num; |
68 | 84 | ||
69 | #ifndef HAVE_BSD_AUTH | ||
70 | const char *pws; | ||
71 | #endif | ||
72 | unsigned int len; | 85 | unsigned int len; |
73 | Bool running = True; | 86 | Bool running = True; |
74 | Cursor invisible; | ||
75 | Display *dpy; | ||
76 | KeySym ksym; | 87 | KeySym ksym; |
77 | Pixmap pmap; | ||
78 | Window root, w; | ||
79 | XColor black, dummy; | ||
80 | XEvent ev; | 88 | XEvent ev; |
81 | XSetWindowAttributes wa; | ||
82 | CARD16 standby, suspend, off; | ||
83 | |||
84 | if((argc == 2) && !strcmp("-v", argv[1])) | ||
85 | die("slock-"VERSION", © 2006-2008 Anselm R Garbe\n"); | ||
86 | else if(argc != 1) | ||
87 | die("usage: slock [-v]\n"); | ||
88 | |||
89 | #ifndef HAVE_BSD_AUTH | ||
90 | pws = get_password(); | ||
91 | #endif | ||
92 | |||
93 | if(!(dpy = XOpenDisplay(0))) | ||
94 | die("slock: cannot open display\n"); | ||
95 | screen = DefaultScreen(dpy); | ||
96 | root = RootWindow(dpy, screen); | ||
97 | 89 | ||
98 | /* init */ | ||
99 | wa.override_redirect = 1; | ||
100 | wa.background_pixel = BlackPixel(dpy, screen); | ||
101 | w = XCreateWindow(dpy, root, 0, 0, DisplayWidth(dpy, screen), DisplayHeight(dpy, screen), | ||
102 | 0, DefaultDepth(dpy, screen), CopyFromParent, | ||
103 | DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixel, &wa); | ||
104 | XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "black", &black, &dummy); | ||
105 | pmap = XCreateBitmapFromData(dpy, w, curs, 8, 8); | ||
106 | invisible = XCreatePixmapCursor(dpy, pmap, pmap, &black, &black, 0, 0); | ||
107 | XDefineCursor(dpy, w, invisible); | ||
108 | XMapRaised(dpy, w); | ||
109 | for(len = 1000; len; len--) { | ||
110 | if(XGrabPointer(dpy, root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, | ||
111 | GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) | ||
112 | break; | ||
113 | usleep(1000); | ||
114 | } | ||
115 | if((running = running && (len > 0))) { | ||
116 | for(len = 1000; len; len--) { | ||
117 | if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) | ||
118 | == GrabSuccess) | ||
119 | break; | ||
120 | usleep(1000); | ||
121 | } | ||
122 | running = (len > 0); | ||
123 | } | ||
124 | len = 0; | 90 | len = 0; |
125 | XSync(dpy, False); | 91 | running = True; |
126 | 92 | ||
127 | if(DPMSCapable(dpy)) { /* save and customize DPMS settings */ | 93 | /* As "slock" stands for "Simple X display locker", the DPMS settings |
128 | DPMSGetTimeouts(dpy, &standby, &suspend, &off); | 94 | * had been removed and you can set it with "xset" or some other |
129 | DPMSSetTimeouts(dpy, 10, 30, 90); | 95 | * utility. This way the user can easily set a customized DPMS |
130 | } | 96 | * timeout. */ |
131 | 97 | ||
132 | /* main event loop */ | ||
133 | while(running && !XNextEvent(dpy, &ev)) { | 98 | while(running && !XNextEvent(dpy, &ev)) { |
134 | if(ev.type == KeyPress) { | 99 | if(ev.type == KeyPress) { |
135 | buf[0] = 0; | 100 | buf[0] = 0; |
@@ -172,12 +137,129 @@ main(int argc, char **argv) { | |||
172 | } | 137 | } |
173 | } | 138 | } |
174 | } | 139 | } |
175 | if(DPMSCapable(dpy)) { /* restore DPMS settings */ | 140 | } |
176 | DPMSSetTimeouts(dpy, standby, suspend, off); | 141 | |
177 | } | 142 | static void |
143 | unlockscreen(Display *dpy, struct st_lock *lock) { | ||
144 | if (dpy == NULL || lock == NULL) | ||
145 | return; | ||
146 | |||
178 | XUngrabPointer(dpy, CurrentTime); | 147 | XUngrabPointer(dpy, CurrentTime); |
179 | XFreePixmap(dpy, pmap); | 148 | XFreePixmap(dpy, lock->pmap); |
180 | XDestroyWindow(dpy, w); | 149 | XDestroyWindow(dpy, lock->w); |
150 | |||
151 | free(lock); | ||
152 | } | ||
153 | |||
154 | static struct st_lock * | ||
155 | lockscreen(Display *dpy, int screen) { | ||
156 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
157 | unsigned int len; | ||
158 | struct st_lock *lock; | ||
159 | Bool running = True; | ||
160 | XColor black, dummy; | ||
161 | XSetWindowAttributes wa; | ||
162 | Cursor invisible; | ||
163 | |||
164 | if (dpy == NULL || screen < 0) | ||
165 | return NULL; | ||
166 | |||
167 | lock = malloc(sizeof(struct st_lock)); | ||
168 | if (lock == NULL) | ||
169 | return NULL; | ||
170 | |||
171 | lock->screen = screen; | ||
172 | |||
173 | lock->root = RootWindow(dpy, lock->screen); | ||
174 | |||
175 | /* init */ | ||
176 | wa.override_redirect = 1; | ||
177 | wa.background_pixel = BlackPixel(dpy, lock->screen); | ||
178 | lock->w = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), | ||
179 | 0, DefaultDepth(dpy, lock->screen), CopyFromParent, | ||
180 | DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); | ||
181 | XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), "black", &black, &dummy); | ||
182 | lock->pmap = XCreateBitmapFromData(dpy, lock->w, curs, 8, 8); | ||
183 | invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &black, &black, 0, 0); | ||
184 | XDefineCursor(dpy, lock->w, invisible); | ||
185 | XMapRaised(dpy, lock->w); | ||
186 | for(len = 1000; len; len--) { | ||
187 | if(XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, | ||
188 | GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) | ||
189 | break; | ||
190 | usleep(1000); | ||
191 | } | ||
192 | if((running = running && (len > 0))) { | ||
193 | for(len = 1000; len; len--) { | ||
194 | if(XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) | ||
195 | == GrabSuccess) | ||
196 | break; | ||
197 | usleep(1000); | ||
198 | } | ||
199 | running = (len > 0); | ||
200 | } | ||
201 | |||
202 | if (!running) { | ||
203 | unlockscreen(dpy, lock); | ||
204 | lock = NULL; | ||
205 | } | ||
206 | |||
207 | return lock; | ||
208 | } | ||
209 | |||
210 | static void | ||
211 | usage(void) { | ||
212 | fprintf(stderr, "usage: %s -v", __progname); | ||
213 | exit(EXIT_FAILURE); | ||
214 | } | ||
215 | |||
216 | int | ||
217 | main(int argc, char **argv) { | ||
218 | #ifndef HAVE_BSD_AUTH | ||
219 | const char *pws; | ||
220 | #endif | ||
221 | Display *dpy; | ||
222 | int nscreens, screen; | ||
223 | |||
224 | struct st_lock **locks; | ||
225 | |||
226 | if((argc == 2) && !strcmp("-v", argv[1])) | ||
227 | die("slock-%s, © 2006-2008 Anselm R Garbe", VERSION); | ||
228 | else if(argc != 1) | ||
229 | usage(); | ||
230 | |||
231 | #ifndef HAVE_BSD_AUTH | ||
232 | pws = get_password(); | ||
233 | #endif | ||
234 | |||
235 | if(!(dpy = XOpenDisplay(0))) | ||
236 | die("cannot open display"); | ||
237 | |||
238 | /* Get the number of screens in display "dpy" and blank them all. */ | ||
239 | nscreens = ScreenCount(dpy); | ||
240 | locks = malloc(sizeof(struct st_lock *) * nscreens); | ||
241 | if (locks == NULL) | ||
242 | die("malloc: %s", strerror(errno)); | ||
243 | |||
244 | for (screen = 0; screen < nscreens; screen++) | ||
245 | locks[screen] = lockscreen(dpy, screen); | ||
246 | |||
247 | XSync(dpy, False); | ||
248 | |||
249 | /* Everything is now blank. Now wait for the correct password. */ | ||
250 | #ifdef HAVE_BSD_AUTH | ||
251 | read_password(dpy); | ||
252 | #else | ||
253 | read_password(dpy, pws); | ||
254 | #endif | ||
255 | |||
256 | /* Password ok, unlock everything and quit. */ | ||
257 | for (screen = 0; screen < nscreens; screen++) | ||
258 | unlockscreen(dpy, locks[screen]); | ||
259 | |||
260 | free(locks); | ||
261 | |||
181 | XCloseDisplay(dpy); | 262 | XCloseDisplay(dpy); |
263 | |||
182 | return 0; | 264 | return 0; |
183 | } | 265 | } |