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); |
