diff options
-rw-r--r-- | slock.c | 112 |
1 files changed, 60 insertions, 52 deletions
@@ -1,4 +1,3 @@ | |||
1 | |||
2 | /* See LICENSE file for license details. */ | 1 | /* See LICENSE file for license details. */ |
3 | #define _XOPEN_SOURCE 500 | 2 | #define _XOPEN_SOURCE 500 |
4 | #if HAVE_SHADOW_H | 3 | #if HAVE_SHADOW_H |
@@ -37,20 +36,22 @@ static int nscreens; | |||
37 | static Bool running = True; | 36 | static Bool running = True; |
38 | 37 | ||
39 | static void | 38 | static void |
40 | die(const char *errstr, ...) { | 39 | die(const char *errstr, ...) |
40 | { | ||
41 | va_list ap; | 41 | va_list ap; |
42 | 42 | ||
43 | va_start(ap, errstr); | 43 | va_start(ap, errstr); |
44 | vfprintf(stderr, errstr, ap); | 44 | vfprintf(stderr, errstr, ap); |
45 | va_end(ap); | 45 | va_end(ap); |
46 | exit(EXIT_FAILURE); | 46 | exit(1); |
47 | } | 47 | } |
48 | 48 | ||
49 | #ifdef __linux__ | 49 | #ifdef __linux__ |
50 | #include <fcntl.h> | 50 | #include <fcntl.h> |
51 | 51 | ||
52 | static void | 52 | static void |
53 | dontkillme(void) { | 53 | dontkillme(void) |
54 | { | ||
54 | int fd; | 55 | int fd; |
55 | 56 | ||
56 | fd = open("/proc/self/oom_score_adj", O_WRONLY); | 57 | fd = open("/proc/self/oom_score_adj", O_WRONLY); |
@@ -62,8 +63,10 @@ dontkillme(void) { | |||
62 | #endif | 63 | #endif |
63 | 64 | ||
64 | #ifndef HAVE_BSD_AUTH | 65 | #ifndef HAVE_BSD_AUTH |
66 | /* only run as root */ | ||
65 | static const char * | 67 | static const char * |
66 | getpw(void) { /* only run as root */ | 68 | getpw(void) |
69 | { | ||
67 | const char *rval; | 70 | const char *rval; |
68 | struct passwd *pw; | 71 | struct passwd *pw; |
69 | 72 | ||
@@ -73,7 +76,7 @@ getpw(void) { /* only run as root */ | |||
73 | if (errno) | 76 | if (errno) |
74 | die("slock: getpwuid: %s\n", strerror(errno)); | 77 | die("slock: getpwuid: %s\n", strerror(errno)); |
75 | else | 78 | else |
76 | die("slock: cannot retrieve password entry (make sure to suid or sgid slock)\n"); | 79 | die("slock: cannot retrieve password entry\n"); |
77 | } | 80 | } |
78 | rval = pw->pw_passwd; | 81 | rval = pw->pw_passwd; |
79 | 82 | ||
@@ -81,15 +84,15 @@ getpw(void) { /* only run as root */ | |||
81 | if (rval[0] == 'x' && rval[1] == '\0') { | 84 | if (rval[0] == 'x' && rval[1] == '\0') { |
82 | struct spwd *sp; | 85 | struct spwd *sp; |
83 | sp = getspnam(getenv("USER")); | 86 | sp = getspnam(getenv("USER")); |
84 | if(!sp) | 87 | if (!sp) |
85 | die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); | 88 | die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n"); |
86 | rval = sp->sp_pwdp; | 89 | rval = sp->sp_pwdp; |
87 | } | 90 | } |
88 | #endif | 91 | #endif |
89 | 92 | ||
90 | /* drop privileges */ | 93 | /* drop privileges */ |
91 | if (geteuid() == 0 | 94 | if (geteuid() == 0 && |
92 | && ((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) || setuid(pw->pw_uid) < 0)) | 95 | ((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) || setuid(pw->pw_uid) < 0)) |
93 | die("slock: cannot drop privileges\n"); | 96 | die("slock: cannot drop privileges\n"); |
94 | return rval; | 97 | return rval; |
95 | } | 98 | } |
@@ -115,21 +118,23 @@ readpw(Display *dpy, const char *pws) | |||
115 | * had been removed and you can set it with "xset" or some other | 118 | * had been removed and you can set it with "xset" or some other |
116 | * utility. This way the user can easily set a customized DPMS | 119 | * utility. This way the user can easily set a customized DPMS |
117 | * timeout. */ | 120 | * timeout. */ |
118 | while(running && !XNextEvent(dpy, &ev)) { | 121 | while (running && !XNextEvent(dpy, &ev)) { |
119 | if(ev.type == KeyPress) { | 122 | if (ev.type == KeyPress) { |
120 | buf[0] = 0; | 123 | buf[0] = 0; |
121 | num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0); | 124 | num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0); |
122 | if(IsKeypadKey(ksym)) { | 125 | if (IsKeypadKey(ksym)) { |
123 | if(ksym == XK_KP_Enter) | 126 | if (ksym == XK_KP_Enter) |
124 | ksym = XK_Return; | 127 | ksym = XK_Return; |
125 | else if(ksym >= XK_KP_0 && ksym <= XK_KP_9) | 128 | else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) |
126 | ksym = (ksym - XK_KP_0) + XK_0; | 129 | ksym = (ksym - XK_KP_0) + XK_0; |
127 | } | 130 | } |
128 | if(IsFunctionKey(ksym) || IsKeypadKey(ksym) | 131 | if (IsFunctionKey(ksym) || |
129 | || IsMiscFunctionKey(ksym) || IsPFKey(ksym) | 132 | IsKeypadKey(ksym) || |
130 | || IsPrivateKeypadKey(ksym)) | 133 | IsMiscFunctionKey(ksym) || |
134 | IsPFKey(ksym) || | ||
135 | IsPrivateKeypadKey(ksym)) | ||
131 | continue; | 136 | continue; |
132 | switch(ksym) { | 137 | switch (ksym) { |
133 | case XK_Return: | 138 | case XK_Return: |
134 | passwd[len] = 0; | 139 | passwd[len] = 0; |
135 | #ifdef HAVE_BSD_AUTH | 140 | #ifdef HAVE_BSD_AUTH |
@@ -137,7 +142,7 @@ readpw(Display *dpy, const char *pws) | |||
137 | #else | 142 | #else |
138 | running = !!strcmp(crypt(passwd, pws), pws); | 143 | running = !!strcmp(crypt(passwd, pws), pws); |
139 | #endif | 144 | #endif |
140 | if(running) | 145 | if (running) |
141 | XBell(dpy, 100); | 146 | XBell(dpy, 100); |
142 | len = 0; | 147 | len = 0; |
143 | break; | 148 | break; |
@@ -145,36 +150,37 @@ readpw(Display *dpy, const char *pws) | |||
145 | len = 0; | 150 | len = 0; |
146 | break; | 151 | break; |
147 | case XK_BackSpace: | 152 | case XK_BackSpace: |
148 | if(len) | 153 | if (len) |
149 | --len; | 154 | --len; |
150 | break; | 155 | break; |
151 | default: | 156 | default: |
152 | if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { | 157 | if (num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { |
153 | memcpy(passwd + len, buf, num); | 158 | memcpy(passwd + len, buf, num); |
154 | len += num; | 159 | len += num; |
155 | } | 160 | } |
156 | break; | 161 | break; |
157 | } | 162 | } |
158 | if(llen == 0 && len != 0) { | 163 | if (llen == 0 && len != 0) { |
159 | for(screen = 0; screen < nscreens; screen++) { | 164 | for (screen = 0; screen < nscreens; screen++) { |
160 | XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[1]); | 165 | XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[1]); |
161 | XClearWindow(dpy, locks[screen]->win); | 166 | XClearWindow(dpy, locks[screen]->win); |
162 | } | 167 | } |
163 | } else if(llen != 0 && len == 0) { | 168 | } else if (llen != 0 && len == 0) { |
164 | for(screen = 0; screen < nscreens; screen++) { | 169 | for (screen = 0; screen < nscreens; screen++) { |
165 | XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]); | 170 | XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]); |
166 | XClearWindow(dpy, locks[screen]->win); | 171 | XClearWindow(dpy, locks[screen]->win); |
167 | } | 172 | } |
168 | } | 173 | } |
169 | llen = len; | 174 | llen = len; |
170 | } | 175 | } |
171 | else for(screen = 0; screen < nscreens; screen++) | 176 | else for (screen = 0; screen < nscreens; screen++) |
172 | XRaiseWindow(dpy, locks[screen]->win); | 177 | XRaiseWindow(dpy, locks[screen]->win); |
173 | } | 178 | } |
174 | } | 179 | } |
175 | 180 | ||
176 | static void | 181 | static void |
177 | unlockscreen(Display *dpy, Lock *lock) { | 182 | unlockscreen(Display *dpy, Lock *lock) |
183 | { | ||
178 | if(dpy == NULL || lock == NULL) | 184 | if(dpy == NULL || lock == NULL) |
179 | return; | 185 | return; |
180 | 186 | ||
@@ -187,7 +193,8 @@ unlockscreen(Display *dpy, Lock *lock) { | |||
187 | } | 193 | } |
188 | 194 | ||
189 | static Lock * | 195 | static Lock * |
190 | lockscreen(Display *dpy, int screen) { | 196 | lockscreen(Display *dpy, int screen) |
197 | { | ||
191 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; | 198 | char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; |
192 | unsigned int len; | 199 | unsigned int len; |
193 | Lock *lock; | 200 | Lock *lock; |
@@ -195,11 +202,11 @@ lockscreen(Display *dpy, int screen) { | |||
195 | XSetWindowAttributes wa; | 202 | XSetWindowAttributes wa; |
196 | Cursor invisible; | 203 | Cursor invisible; |
197 | 204 | ||
198 | if(dpy == NULL || screen < 0) | 205 | if (dpy == NULL || screen < 0) |
199 | return NULL; | 206 | return NULL; |
200 | 207 | ||
201 | lock = malloc(sizeof(Lock)); | 208 | lock = malloc(sizeof(Lock)); |
202 | if(lock == NULL) | 209 | if (lock == NULL) |
203 | return NULL; | 210 | return NULL; |
204 | 211 | ||
205 | lock->screen = screen; | 212 | lock->screen = screen; |
@@ -210,8 +217,8 @@ lockscreen(Display *dpy, int screen) { | |||
210 | wa.override_redirect = 1; | 217 | wa.override_redirect = 1; |
211 | wa.background_pixel = BlackPixel(dpy, lock->screen); | 218 | wa.background_pixel = BlackPixel(dpy, lock->screen); |
212 | lock->win = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), | 219 | lock->win = XCreateWindow(dpy, lock->root, 0, 0, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), |
213 | 0, DefaultDepth(dpy, lock->screen), CopyFromParent, | 220 | 0, DefaultDepth(dpy, lock->screen), CopyFromParent, |
214 | DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); | 221 | DefaultVisual(dpy, lock->screen), CWOverrideRedirect | CWBackPixel, &wa); |
215 | XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR2, &color, &dummy); | 222 | XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR2, &color, &dummy); |
216 | lock->colors[1] = color.pixel; | 223 | lock->colors[1] = color.pixel; |
217 | XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR1, &color, &dummy); | 224 | XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), COLOR1, &color, &dummy); |
@@ -220,36 +227,37 @@ lockscreen(Display *dpy, int screen) { | |||
220 | invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); | 227 | invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, &color, &color, 0, 0); |
221 | XDefineCursor(dpy, lock->win, invisible); | 228 | XDefineCursor(dpy, lock->win, invisible); |
222 | XMapRaised(dpy, lock->win); | 229 | XMapRaised(dpy, lock->win); |
223 | for(len = 1000; len; len--) { | 230 | for (len = 1000; len; len--) { |
224 | if(XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, | 231 | if (XGrabPointer(dpy, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, |
225 | GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) | 232 | GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) |
226 | break; | 233 | break; |
227 | usleep(1000); | 234 | usleep(1000); |
228 | } | 235 | } |
229 | if(running && (len > 0)) { | 236 | if (running && (len > 0)) { |
230 | for(len = 1000; len; len--) { | 237 | for (len = 1000; len; len--) { |
231 | if(XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) | 238 | if (XGrabKeyboard(dpy, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) |
232 | == GrabSuccess) | ||
233 | break; | 239 | break; |
234 | usleep(1000); | 240 | usleep(1000); |
235 | } | 241 | } |
236 | } | 242 | } |
237 | 243 | ||
238 | running &= (len > 0); | 244 | running &= (len > 0); |
239 | if(!running) { | 245 | if (!running) { |
240 | unlockscreen(dpy, lock); | 246 | unlockscreen(dpy, lock); |
241 | lock = NULL; | 247 | lock = NULL; |
242 | } | 248 | } |
243 | else | 249 | else { |
244 | XSelectInput(dpy, lock->root, SubstructureNotifyMask); | 250 | XSelectInput(dpy, lock->root, SubstructureNotifyMask); |
251 | } | ||
245 | 252 | ||
246 | return lock; | 253 | return lock; |
247 | } | 254 | } |
248 | 255 | ||
249 | static void | 256 | static void |
250 | usage(void) { | 257 | usage(void) |
258 | { | ||
251 | fprintf(stderr, "usage: slock [-v]\n"); | 259 | fprintf(stderr, "usage: slock [-v]\n"); |
252 | exit(EXIT_FAILURE); | 260 | exit(1); |
253 | } | 261 | } |
254 | 262 | ||
255 | int | 263 | int |
@@ -260,38 +268,38 @@ main(int argc, char **argv) { | |||
260 | Display *dpy; | 268 | Display *dpy; |
261 | int screen; | 269 | int screen; |
262 | 270 | ||
263 | if((argc == 2) && !strcmp("-v", argv[1])) | 271 | if ((argc == 2) && !strcmp("-v", argv[1])) |
264 | die("slock-%s, © 2006-2014 slock engineers\n", VERSION); | 272 | die("slock-%s, © 2006-2015 slock engineers\n", VERSION); |
265 | else if(argc != 1) | 273 | else if (argc != 1) |
266 | usage(); | 274 | usage(); |
267 | 275 | ||
268 | #ifdef __linux__ | 276 | #ifdef __linux__ |
269 | dontkillme(); | 277 | dontkillme(); |
270 | #endif | 278 | #endif |
271 | 279 | ||
272 | if(!getpwuid(getuid())) | 280 | if (!getpwuid(getuid())) |
273 | die("slock: no passwd entry for you\n"); | 281 | die("slock: no passwd entry for you\n"); |
274 | 282 | ||
275 | #ifndef HAVE_BSD_AUTH | 283 | #ifndef HAVE_BSD_AUTH |
276 | pws = getpw(); | 284 | pws = getpw(); |
277 | #endif | 285 | #endif |
278 | 286 | ||
279 | if(!(dpy = XOpenDisplay(0))) | 287 | if (!(dpy = XOpenDisplay(0))) |
280 | die("slock: cannot open display\n"); | 288 | die("slock: cannot open display\n"); |
281 | /* Get the number of screens in display "dpy" and blank them all. */ | 289 | /* Get the number of screens in display "dpy" and blank them all. */ |
282 | nscreens = ScreenCount(dpy); | 290 | nscreens = ScreenCount(dpy); |
283 | locks = malloc(sizeof(Lock *) * nscreens); | 291 | locks = malloc(sizeof(Lock *) * nscreens); |
284 | if(locks == NULL) | 292 | if (locks == NULL) |
285 | die("slock: malloc: %s\n", strerror(errno)); | 293 | die("slock: malloc: %s\n", strerror(errno)); |
286 | int nlocks = 0; | 294 | int nlocks = 0; |
287 | for(screen = 0; screen < nscreens; screen++) { | 295 | for (screen = 0; screen < nscreens; screen++) { |
288 | if ( (locks[screen] = lockscreen(dpy, screen)) != NULL) | 296 | if ( (locks[screen] = lockscreen(dpy, screen)) != NULL) |
289 | nlocks++; | 297 | nlocks++; |
290 | } | 298 | } |
291 | XSync(dpy, False); | 299 | XSync(dpy, False); |
292 | 300 | ||
293 | /* Did we actually manage to lock something? */ | 301 | /* Did we actually manage to lock something? */ |
294 | if (nlocks == 0) { // nothing to protect | 302 | if (nlocks == 0) { /* nothing to protect */ |
295 | free(locks); | 303 | free(locks); |
296 | XCloseDisplay(dpy); | 304 | XCloseDisplay(dpy); |
297 | return 1; | 305 | return 1; |
@@ -305,7 +313,7 @@ main(int argc, char **argv) { | |||
305 | #endif | 313 | #endif |
306 | 314 | ||
307 | /* Password ok, unlock everything and quit. */ | 315 | /* Password ok, unlock everything and quit. */ |
308 | for(screen = 0; screen < nscreens; screen++) | 316 | for (screen = 0; screen < nscreens; screen++) |
309 | unlockscreen(dpy, locks[screen]); | 317 | unlockscreen(dpy, locks[screen]); |
310 | 318 | ||
311 | free(locks); | 319 | free(locks); |