]> git.armaanb.net Git - slock.git/blobdiff - slock.c
applied sin's patch and prepared new release
[slock.git] / slock.c
diff --git a/slock.c b/slock.c
index 320ed2b4e3a40272fc37d0ce200d51b11e51ae55..5051f04eb8a70a2fc7756fd29d6950850fb4236d 100644 (file)
--- a/slock.c
+++ b/slock.c
@@ -1,3 +1,4 @@
+
 /* See LICENSE file for license details. */
 #define _XOPEN_SOURCE 500
 #if HAVE_SHADOW_H
@@ -22,6 +23,8 @@
 #include <bsd_auth.h>
 #endif
 
+#include "config.h"
+
 typedef struct {
        int screen;
        Window root, win;
@@ -43,32 +46,51 @@ die(const char *errstr, ...) {
        exit(EXIT_FAILURE);
 }
 
+#ifdef __linux__
+#include <fcntl.h>
+
+static void
+dontkillme(void) {
+       int fd;
+
+       fd = open("/proc/self/oom_score_adj", O_WRONLY);
+       if (fd < 0 && errno == ENOENT)
+               return;
+       if (fd < 0 || write(fd, "-1000\n", 6) != 6 || close(fd) != 0)
+               die("cannot disable the out-of-memory killer for this process\n");
+}
+#endif
+
 #ifndef HAVE_BSD_AUTH
 static const char *
 getpw(void) { /* only run as root */
        const char *rval;
        struct passwd *pw;
 
+       errno = 0;
        pw = getpwuid(getuid());
-       if(!pw)
-               die("slock: cannot retrieve password entry (make sure to suid or sgid slock)");
-       endpwent();
+       if (!pw) {
+               if (errno)
+                       die("slock: getpwuid: %s\n", strerror(errno));
+               else
+                       die("slock: cannot retrieve password entry (make sure to suid or sgid slock)\n");
+       }
        rval =  pw->pw_passwd;
 
 #if HAVE_SHADOW_H
-       if (strlen(rval) >= 1) { /* kludge, assumes pw placeholder entry has len >= 1 */
+       if (rval[0] == 'x' && rval[1] == '\0') {
                struct spwd *sp;
                sp = getspnam(getenv("USER"));
                if(!sp)
                        die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
-               endspent();
                rval = sp->sp_pwdp;
        }
 #endif
 
        /* drop privileges */
-       if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0)
-               die("slock: cannot drop privileges");
+       if (geteuid() == 0
+          && ((getegid() != pw->pw_gid && setgid(pw->pw_gid) < 0) || setuid(pw->pw_uid) < 0))
+               die("slock: cannot drop privileges\n");
        return rval;
 }
 #endif
@@ -113,9 +135,9 @@ readpw(Display *dpy, const char *pws)
 #ifdef HAVE_BSD_AUTH
                                running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd);
 #else
-                               running = strcmp(crypt(passwd, pws), pws);
+                               running = !!strcmp(crypt(passwd, pws), pws);
 #endif
-                               if(running != False)
+                               if(running)
                                        XBell(dpy, 100);
                                len = 0;
                                break;
@@ -127,7 +149,7 @@ readpw(Display *dpy, const char *pws)
                                        --len;
                                break;
                        default:
-                               if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { 
+                               if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) {
                                        memcpy(passwd + len, buf, num);
                                        len += num;
                                }
@@ -211,9 +233,9 @@ lockscreen(Display *dpy, int screen) {
                                break;
                        usleep(1000);
                }
-               running = (len > 0);
        }
 
+       running &= (len > 0);
        if(!running) {
                unlockscreen(dpy, lock);
                lock = NULL;
@@ -243,24 +265,38 @@ main(int argc, char **argv) {
        else if(argc != 1)
                usage();
 
+#ifdef __linux__
+       dontkillme();
+#endif
+
        if(!getpwuid(getuid()))
-               die("slock: no passwd entry for you");
+               die("slock: no passwd entry for you\n");
 
 #ifndef HAVE_BSD_AUTH
        pws = getpw();
 #endif
 
        if(!(dpy = XOpenDisplay(0)))
-               die("slock: cannot open display");
+               die("slock: cannot open display\n");
        /* Get the number of screens in display "dpy" and blank them all. */
        nscreens = ScreenCount(dpy);
        locks = malloc(sizeof(Lock *) * nscreens);
        if(locks == NULL)
-               die("slock: malloc: %s", strerror(errno));
-       for(screen = 0; screen < nscreens; screen++)
-               locks[screen] = lockscreen(dpy, screen);
+               die("slock: malloc: %s\n", strerror(errno));
+       int nlocks = 0;
+       for(screen = 0; screen < nscreens; screen++) {
+               if ( (locks[screen] = lockscreen(dpy, screen)) != NULL)
+                       nlocks++;
+       }
        XSync(dpy, False);
 
+       /* Did we actually manage to lock something? */
+       if (nlocks == 0) { // nothing to protect
+               free(locks);
+               XCloseDisplay(dpy);
+               return 1;
+       }
+
        /* Everything is now blank. Now wait for the correct password. */
 #ifdef HAVE_BSD_AUTH
        readpw(dpy);