Xinqi Bao's Git
1 /* See LICENSE file for license details. */
2 #define _XOPEN_SOURCE 500
15 #include <sys/types.h>
16 #include <X11/keysym.h>
18 #include <X11/Xutil.h>
21 #include <login_cap.h>
31 extern const char *__progname
;
34 die(const char *errstr
, ...) {
37 fprintf(stderr
, "%s: ", __progname
);
39 vfprintf(stderr
, errstr
, ap
);
41 fprintf(stderr
, "\n");
49 getpw(void) { /* only run as root */
53 pw
= getpwuid(getuid());
55 die("cannot retrieve password entry (make sure to suid or sgid slock)");
62 sp
= getspnam(getenv("USER"));
64 die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
71 if(setgid(pw
->pw_gid
) < 0 || setuid(pw
->pw_uid
) < 0)
72 die("cannot drop privileges");
81 readpw(Display
*dpy
, const char *pws
)
84 char buf
[32], passwd
[256];
95 /* As "slock" stands for "Simple X display locker", the DPMS settings
96 * had been removed and you can set it with "xset" or some other
97 * utility. This way the user can easily set a customized DPMS
100 while(running
&& !XNextEvent(dpy
, &ev
)) {
101 if(ev
.type
== KeyPress
) {
103 num
= XLookupString(&ev
.xkey
, buf
, sizeof buf
, &ksym
, 0);
104 if(IsKeypadKey(ksym
)) {
105 if(ksym
== XK_KP_Enter
)
107 else if(ksym
>= XK_KP_0
&& ksym
<= XK_KP_9
)
108 ksym
= (ksym
- XK_KP_0
) + XK_0
;
110 if(IsFunctionKey(ksym
) || IsKeypadKey(ksym
)
111 || IsMiscFunctionKey(ksym
) || IsPFKey(ksym
)
112 || IsPrivateKeypadKey(ksym
))
118 running
= !auth_userokay(getlogin(), NULL
, "auth-xlock", passwd
);
120 running
= strcmp(crypt(passwd
, pws
), pws
);
134 if(num
&& !iscntrl((int) buf
[0]) && (len
+ num
< sizeof passwd
)) {
135 memcpy(passwd
+ len
, buf
, num
);
145 unlockscreen(Display
*dpy
, struct st_lock
*lock
) {
146 if (dpy
== NULL
|| lock
== NULL
)
149 XUngrabPointer(dpy
, CurrentTime
);
150 XFreePixmap(dpy
, lock
->pmap
);
151 XDestroyWindow(dpy
, lock
->w
);
156 static struct st_lock
*
157 lockscreen(Display
*dpy
, int screen
) {
158 char curs
[] = {0, 0, 0, 0, 0, 0, 0, 0};
160 struct st_lock
*lock
;
163 XSetWindowAttributes wa
;
166 if (dpy
== NULL
|| screen
< 0)
169 lock
= malloc(sizeof(struct st_lock
));
173 lock
->screen
= screen
;
175 lock
->root
= RootWindow(dpy
, lock
->screen
);
178 wa
.override_redirect
= 1;
179 wa
.background_pixel
= BlackPixel(dpy
, lock
->screen
);
180 lock
->w
= XCreateWindow(dpy
, lock
->root
, 0, 0, DisplayWidth(dpy
, lock
->screen
), DisplayHeight(dpy
, lock
->screen
),
181 0, DefaultDepth(dpy
, lock
->screen
), CopyFromParent
,
182 DefaultVisual(dpy
, lock
->screen
), CWOverrideRedirect
| CWBackPixel
, &wa
);
183 XAllocNamedColor(dpy
, DefaultColormap(dpy
, lock
->screen
), "black", &black
, &dummy
);
184 lock
->pmap
= XCreateBitmapFromData(dpy
, lock
->w
, curs
, 8, 8);
185 invisible
= XCreatePixmapCursor(dpy
, lock
->pmap
, lock
->pmap
, &black
, &black
, 0, 0);
186 XDefineCursor(dpy
, lock
->w
, invisible
);
187 XMapRaised(dpy
, lock
->w
);
188 for(len
= 1000; len
; len
--) {
189 if(XGrabPointer(dpy
, lock
->root
, False
, ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
190 GrabModeAsync
, GrabModeAsync
, None
, invisible
, CurrentTime
) == GrabSuccess
)
194 if((running
= running
&& (len
> 0))) {
195 for(len
= 1000; len
; len
--) {
196 if(XGrabKeyboard(dpy
, lock
->root
, True
, GrabModeAsync
, GrabModeAsync
, CurrentTime
)
205 unlockscreen(dpy
, lock
);
214 fprintf(stderr
, "usage: %s -v", __progname
);
219 xerrordummy(Display
*dpy
, XErrorEvent
*ee
) {
224 main(int argc
, char **argv
) {
225 #ifndef HAVE_BSD_AUTH
229 int nscreens
, screen
;
231 struct st_lock
**locks
;
233 if((argc
== 2) && !strcmp("-v", argv
[1]))
234 die("slock-%s, © 2006-2012 Anselm R Garbe", VERSION
);
238 if(!getpwuid(getuid()))
239 die("no passwd entry for you");
241 #ifndef HAVE_BSD_AUTH
245 if(!(dpy
= XOpenDisplay(0)))
246 die("cannot open display");
247 /* prevent default error handler to take over */
248 XSetErrorHandler(xerrordummy
);
249 /* Get the number of screens in display "dpy" and blank them all. */
250 nscreens
= ScreenCount(dpy
);
251 locks
= malloc(sizeof(struct st_lock
*) * nscreens
);
253 die("malloc: %s", strerror(errno
));
255 for (screen
= 0; screen
< nscreens
; screen
++)
256 locks
[screen
] = lockscreen(dpy
, screen
);
260 /* Everything is now blank. Now wait for the correct password. */
267 /* Password ok, unlock everything and quit. */
268 for (screen
= 0; screen
< nscreens
; screen
++)
269 unlockscreen(dpy
, locks
[screen
]);