X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=slock.c;h=6541b7046cc5c7a50a5c6bda7ef7581e616eec38;hb=27d8d248275ca3eb63882202dcc21ecf2f81e72a;hp=824baa29f360730a9c7d156cec8ebb738eef1c7c;hpb=763e52878dba100e79c6f4a837a92e1df0d41ae0;p=slock.git diff --git a/slock.c b/slock.c index 824baa2..6541b70 100644 --- a/slock.c +++ b/slock.c @@ -1,92 +1,138 @@ /* (C)opyright MMIV-MMV Anselm R. Garbe * See LICENSE file for license details. */ -#define _XOPEN_SOURCE -#include +#define _XOPEN_SOURCE 500 + +#include +#include #include #include #include #include +#if HAVE_SHADOW_H +#include +#endif #include #include #include #include +const char * +get_password() { /* only run as root */ + const char *rval; + struct passwd *pw; + + if(geteuid() != 0) { + fputs("slock: cannot retrieve password entry (make sure to suid slock)\n", stderr); + exit(EXIT_FAILURE); + } + pw = getpwuid(getuid()); + endpwent(); + rval = pw->pw_passwd; + +#if HAVE_SHADOW_H + { + struct spwd *sp; + sp = getspnam(getenv("USER")); + endspent(); + rval = sp->sp_pwdp; + } +#endif + /* drop privileges */ + if(setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) { + fputs("slock: cannot drop privileges\n",stdout); + exit(EXIT_FAILURE); + } + return rval; +} + int main(int argc, char **argv) { + char curs[] = {0, 0, 0, 0, 0, 0, 0, 0}; char buf[32], passwd[256]; - int num, prev_nitem; - struct spwd *sp; - unsigned int i, len; + int num, screen; + const char *pws; + unsigned int len; Bool running = True; - KeySym ksym; + Cursor invisible; Display *dpy; + KeySym ksym; + Pixmap pmap; + Window w; + XColor black, dummy; XEvent ev; + XSetWindowAttributes wa; if((argc > 1) && !strncmp(argv[1], "-v", 3)) { fputs("slock-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout); exit(EXIT_SUCCESS); } - if(!(sp = getspnam(getenv("USER")))) { - fputs("slock: cannot retrieve password entry (make sure to suid slock)\n", stderr); - exit(EXIT_FAILURE); - } - endspent(); + pws = get_password(); if(!(dpy = XOpenDisplay(0))) { fputs("slock: cannot open display\n", stderr); exit(EXIT_FAILURE); } + screen = DefaultScreen(dpy); /* init */ - passwd[0] = 0; - while(XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, - GrabModeAsync, CurrentTime) != GrabSuccess) + len = 0; + + wa.override_redirect = 1; + wa.background_pixel = BlackPixel(dpy, screen); + w = XCreateWindow(dpy, RootWindow(dpy, screen), 0, 0, + DisplayWidth(dpy, screen), DisplayHeight(dpy, screen), + 0, DefaultDepth(dpy, screen), CopyFromParent, + DefaultVisual(dpy, screen), CWOverrideRedirect | CWBackPixel, &wa); + + XAllocNamedColor(dpy, DefaultColormap(dpy, screen), "black", &black, &dummy); + pmap = XCreateBitmapFromData(dpy, w, curs, 8, 8); + invisible = XCreatePixmapCursor(dpy, pmap, pmap, &black, &black, 0, 0); + XDefineCursor(dpy, w, invisible); + running = XGrabPointer(dpy, RootWindow(dpy, screen), False, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + GrabModeAsync, GrabModeSync, None, invisible, CurrentTime) == GrabSuccess; + len = 10; + for(len = 10; len && (XGrabKeyboard(dpy, RootWindow(dpy, screen), True, GrabModeAsync, + GrabModeAsync, CurrentTime) != GrabSuccess); len--) usleep(1000); + running = running && (len > 0); + XMapRaised(dpy, w); + XSync(dpy, False); /* main event loop */ while(running && !XNextEvent(dpy, &ev)) if(ev.type == KeyPress) { - len = strlen(passwd); buf[0] = 0; num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0); if(IsFunctionKey(ksym) || IsKeypadKey(ksym) || IsMiscFunctionKey(ksym) || IsPFKey(ksym) || IsPrivateKeypadKey(ksym)) continue; - /* first check if a control mask is omitted */ - if(ev.xkey.state & ControlMask) { - switch (ksym) { - case XK_h: - case XK_H: ksym = XK_BackSpace; - break; - case XK_u: - case XK_U: passwd[0] = 0; - continue; - } - } switch(ksym) { case XK_Return: - running = strncmp(crypt(passwd, sp->sp_pwdp), sp->sp_pwdp, sizeof(passwd)); - passwd[0] = 0; + passwd[len] = 0; + if((running = strcmp(crypt(passwd, pws), pws)) != 0) + XBell(dpy, 100); + len = 0; break; case XK_Escape: - passwd[0] = 0; + len = 0; break; case XK_BackSpace: if(len) - passwd[--len] = 0; + --len; break; default: if(num && !iscntrl((int) buf[0])) { - buf[num] = 0; - if(len) - strncat(passwd, buf, sizeof(passwd)); - else - strncpy(passwd, buf, sizeof(passwd)); + memcpy(passwd + len,buf,num); + len += num; } break; } } + XUngrabPointer(dpy, CurrentTime); + XFreePixmap(dpy, pmap); + XDestroyWindow(dpy, w); XCloseDisplay(dpy); return 0; }