Xinqi Bao's Git
506231e16ee779633e5cc4d0e838372f26d42175
2 /* See LICENSE file for license details. */
3 #define _XOPEN_SOURCE 500
16 #include <sys/types.h>
17 #include <X11/keysym.h>
19 #include <X11/Xutil.h>
22 #include <login_cap.h>
30 unsigned long colors
[2];
35 static Bool running
= True
;
38 die(const char *errstr
, ...) {
42 vfprintf(stderr
, errstr
, ap
);
54 fd
= open("/proc/self/oom_score_adj", O_WRONLY
);
55 if (fd
< 0 && errno
== ENOENT
)
57 if (fd
< 0 || write(fd
, "-1000\n", 6) != 6 || close(fd
) != 0)
58 die("cannot disable the out-of-memory killer for this process\n");
64 getpw(void) { /* only run as root */
69 pw
= getpwuid(getuid());
71 die("slock: getpwuid: %s\n", strerror(errno
));
73 die("slock: cannot retrieve password entry (make sure to suid or sgid slock)\n");
78 if (strlen(rval
) >= 1) { /* kludge, assumes pw placeholder entry has len >= 1 */
80 sp
= getspnam(getenv("USER"));
82 die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
90 && ((getegid() != pw
->pw_gid
&& setgid(pw
->pw_gid
) < 0) || setuid(pw
->pw_uid
) < 0))
91 die("slock: cannot drop privileges\n");
100 readpw(Display
*dpy
, const char *pws
)
103 char buf
[32], passwd
[256];
105 unsigned int len
, llen
;
112 /* As "slock" stands for "Simple X display locker", the DPMS settings
113 * had been removed and you can set it with "xset" or some other
114 * utility. This way the user can easily set a customized DPMS
116 while(running
&& !XNextEvent(dpy
, &ev
)) {
117 if(ev
.type
== KeyPress
) {
119 num
= XLookupString(&ev
.xkey
, buf
, sizeof buf
, &ksym
, 0);
120 if(IsKeypadKey(ksym
)) {
121 if(ksym
== XK_KP_Enter
)
123 else if(ksym
>= XK_KP_0
&& ksym
<= XK_KP_9
)
124 ksym
= (ksym
- XK_KP_0
) + XK_0
;
126 if(IsFunctionKey(ksym
) || IsKeypadKey(ksym
)
127 || IsMiscFunctionKey(ksym
) || IsPFKey(ksym
)
128 || IsPrivateKeypadKey(ksym
))
134 running
= !auth_userokay(getlogin(), NULL
, "auth-xlock", passwd
);
136 running
= !!strcmp(crypt(passwd
, pws
), pws
);
150 if(num
&& !iscntrl((int) buf
[0]) && (len
+ num
< sizeof passwd
)) {
151 memcpy(passwd
+ len
, buf
, num
);
156 if(llen
== 0 && len
!= 0) {
157 for(screen
= 0; screen
< nscreens
; screen
++) {
158 XSetWindowBackground(dpy
, locks
[screen
]->win
, locks
[screen
]->colors
[1]);
159 XClearWindow(dpy
, locks
[screen
]->win
);
161 } else if(llen
!= 0 && len
== 0) {
162 for(screen
= 0; screen
< nscreens
; screen
++) {
163 XSetWindowBackground(dpy
, locks
[screen
]->win
, locks
[screen
]->colors
[0]);
164 XClearWindow(dpy
, locks
[screen
]->win
);
169 else for(screen
= 0; screen
< nscreens
; screen
++)
170 XRaiseWindow(dpy
, locks
[screen
]->win
);
175 unlockscreen(Display
*dpy
, Lock
*lock
) {
176 if(dpy
== NULL
|| lock
== NULL
)
179 XUngrabPointer(dpy
, CurrentTime
);
180 XFreeColors(dpy
, DefaultColormap(dpy
, lock
->screen
), lock
->colors
, 2, 0);
181 XFreePixmap(dpy
, lock
->pmap
);
182 XDestroyWindow(dpy
, lock
->win
);
188 lockscreen(Display
*dpy
, int screen
) {
189 char curs
[] = {0, 0, 0, 0, 0, 0, 0, 0};
193 XSetWindowAttributes wa
;
196 if(dpy
== NULL
|| screen
< 0)
199 lock
= malloc(sizeof(Lock
));
203 lock
->screen
= screen
;
205 lock
->root
= RootWindow(dpy
, lock
->screen
);
208 wa
.override_redirect
= 1;
209 wa
.background_pixel
= BlackPixel(dpy
, lock
->screen
);
210 lock
->win
= XCreateWindow(dpy
, lock
->root
, 0, 0, DisplayWidth(dpy
, lock
->screen
), DisplayHeight(dpy
, lock
->screen
),
211 0, DefaultDepth(dpy
, lock
->screen
), CopyFromParent
,
212 DefaultVisual(dpy
, lock
->screen
), CWOverrideRedirect
| CWBackPixel
, &wa
);
213 XAllocNamedColor(dpy
, DefaultColormap(dpy
, lock
->screen
), COLOR2
, &color
, &dummy
);
214 lock
->colors
[1] = color
.pixel
;
215 XAllocNamedColor(dpy
, DefaultColormap(dpy
, lock
->screen
), COLOR1
, &color
, &dummy
);
216 lock
->colors
[0] = color
.pixel
;
217 lock
->pmap
= XCreateBitmapFromData(dpy
, lock
->win
, curs
, 8, 8);
218 invisible
= XCreatePixmapCursor(dpy
, lock
->pmap
, lock
->pmap
, &color
, &color
, 0, 0);
219 XDefineCursor(dpy
, lock
->win
, invisible
);
220 XMapRaised(dpy
, lock
->win
);
221 for(len
= 1000; len
; len
--) {
222 if(XGrabPointer(dpy
, lock
->root
, False
, ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
223 GrabModeAsync
, GrabModeAsync
, None
, invisible
, CurrentTime
) == GrabSuccess
)
227 if(running
&& (len
> 0)) {
228 for(len
= 1000; len
; len
--) {
229 if(XGrabKeyboard(dpy
, lock
->root
, True
, GrabModeAsync
, GrabModeAsync
, CurrentTime
)
236 running
&= (len
> 0);
238 unlockscreen(dpy
, lock
);
242 XSelectInput(dpy
, lock
->root
, SubstructureNotifyMask
);
249 fprintf(stderr
, "usage: slock [-v]\n");
254 main(int argc
, char **argv
) {
255 #ifndef HAVE_BSD_AUTH
261 if((argc
== 2) && !strcmp("-v", argv
[1]))
262 die("slock-%s, © 2006-2012 Anselm R Garbe\n", VERSION
);
270 if(!getpwuid(getuid()))
271 die("slock: no passwd entry for you\n");
273 #ifndef HAVE_BSD_AUTH
277 if(!(dpy
= XOpenDisplay(0)))
278 die("slock: cannot open display\n");
279 /* Get the number of screens in display "dpy" and blank them all. */
280 nscreens
= ScreenCount(dpy
);
281 locks
= malloc(sizeof(Lock
*) * nscreens
);
283 die("slock: malloc: %s\n", strerror(errno
));
285 for(screen
= 0; screen
< nscreens
; screen
++) {
286 if ( (locks
[screen
] = lockscreen(dpy
, screen
)) != NULL
)
291 /* Did we actually manage to lock something? */
292 if (nlocks
== 0) { // nothing to protect
298 /* Everything is now blank. Now wait for the correct password. */
305 /* Password ok, unlock everything and quit. */
306 for(screen
= 0; screen
< nscreens
; screen
++)
307 unlockscreen(dpy
, locks
[screen
]);