diff options
| author | Anselm R Garbe <garbeam@gmail.com> | 2009-11-26 12:53:26 +0000 |
|---|---|---|
| committer | Anselm R Garbe <garbeam@gmail.com> | 2009-11-26 12:53:26 +0000 |
| commit | 732d2b3bf5da3a1883b3246062aa556a59b8517c (patch) | |
| tree | 85dcc7c6506f933d327bc801972e3791e0140948 | |
| parent | 0cb05bdb75ac13f010d51e267007ca1c869763ec (diff) | |
applied Fernando Silveira's multiscreen patch for old style multihead setups
| -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 | } |
