Xinqi Bao's Git
df5c3fea36f2e0f1b7ccdb1e035588bd0f0a5d00
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>
38 unsigned long colors
[NUMCOLS
];
43 static Bool running
= True
;
46 die(const char *errstr
, ...)
51 vfprintf(stderr
, errstr
, ap
);
64 fd
= open("/proc/self/oom_score_adj", O_WRONLY
);
65 if (fd
< 0 && errno
== ENOENT
)
67 if (fd
< 0 || write(fd
, "-1000\n", 6) != 6 || close(fd
) != 0)
68 die("cannot disable the out-of-memory killer for this process\n");
73 /* only run as root */
81 pw
= getpwuid(getuid());
84 die("slock: getpwuid: %s\n", strerror(errno
));
86 die("slock: cannot retrieve password entry\n");
91 if (rval
[0] == 'x' && rval
[1] == '\0') {
93 sp
= getspnam(getenv("USER"));
95 die("slock: cannot retrieve shadow entry (make sure to suid or sgid slock)\n");
100 /* drop privileges */
101 if (geteuid() == 0 &&
102 ((getegid() != pw
->pw_gid
&& setgid(pw
->pw_gid
) < 0) || setuid(pw
->pw_uid
) < 0))
103 die("slock: cannot drop privileges\n");
112 readpw(Display
*dpy
, const char *pws
)
115 char buf
[32], passwd
[256];
117 unsigned int len
, llen
;
124 /* As "slock" stands for "Simple X display locker", the DPMS settings
125 * had been removed and you can set it with "xset" or some other
126 * utility. This way the user can easily set a customized DPMS
128 while (running
&& !XNextEvent(dpy
, &ev
)) {
129 if (ev
.type
== KeyPress
) {
131 num
= XLookupString(&ev
.xkey
, buf
, sizeof buf
, &ksym
, 0);
132 if (IsKeypadKey(ksym
)) {
133 if (ksym
== XK_KP_Enter
)
135 else if (ksym
>= XK_KP_0
&& ksym
<= XK_KP_9
)
136 ksym
= (ksym
- XK_KP_0
) + XK_0
;
138 if (IsFunctionKey(ksym
) ||
140 IsMiscFunctionKey(ksym
) ||
142 IsPrivateKeypadKey(ksym
))
148 running
= !auth_userokay(getlogin(), NULL
, "auth-xlock", passwd
);
150 running
= !!strcmp(crypt(passwd
, pws
), pws
);
164 if (num
&& !iscntrl((int) buf
[0]) && (len
+ num
< sizeof passwd
)) {
165 memcpy(passwd
+ len
, buf
, num
);
170 if (llen
== 0 && len
!= 0) {
171 for (screen
= 0; screen
< nscreens
; screen
++) {
172 XSetWindowBackground(dpy
, locks
[screen
]->win
, locks
[screen
]->colors
[INPUT
]);
173 XClearWindow(dpy
, locks
[screen
]->win
);
175 } else if (llen
!= 0 && len
== 0) {
176 for (screen
= 0; screen
< nscreens
; screen
++) {
177 XSetWindowBackground(dpy
, locks
[screen
]->win
, locks
[screen
]->colors
[EMPTY
]);
178 XClearWindow(dpy
, locks
[screen
]->win
);
183 else for (screen
= 0; screen
< nscreens
; screen
++)
184 XRaiseWindow(dpy
, locks
[screen
]->win
);
189 unlockscreen(Display
*dpy
, Lock
*lock
)
191 if(dpy
== NULL
|| lock
== NULL
)
194 XUngrabPointer(dpy
, CurrentTime
);
195 XFreeColors(dpy
, DefaultColormap(dpy
, lock
->screen
), lock
->colors
, NUMCOLS
, 0);
196 XFreePixmap(dpy
, lock
->pmap
);
197 XDestroyWindow(dpy
, lock
->win
);
203 lockscreen(Display
*dpy
, int screen
)
205 char curs
[] = {0, 0, 0, 0, 0, 0, 0, 0};
210 XSetWindowAttributes wa
;
213 if (dpy
== NULL
|| screen
< 0)
216 lock
= malloc(sizeof(Lock
));
220 lock
->screen
= screen
;
222 lock
->root
= RootWindow(dpy
, lock
->screen
);
224 for (i
= 0; i
< NUMCOLS
; i
++) {
225 XAllocNamedColor(dpy
, DefaultColormap(dpy
, lock
->screen
), colorname
[i
], &color
, &dummy
);
226 lock
->colors
[i
] = color
.pixel
;
230 wa
.override_redirect
= 1;
231 wa
.background_pixel
= lock
->colors
[INIT
];
232 lock
->win
= XCreateWindow(dpy
, lock
->root
, 0, 0, DisplayWidth(dpy
, lock
->screen
), DisplayHeight(dpy
, lock
->screen
),
233 0, DefaultDepth(dpy
, lock
->screen
), CopyFromParent
,
234 DefaultVisual(dpy
, lock
->screen
), CWOverrideRedirect
| CWBackPixel
, &wa
);
235 lock
->pmap
= XCreateBitmapFromData(dpy
, lock
->win
, curs
, 8, 8);
236 invisible
= XCreatePixmapCursor(dpy
, lock
->pmap
, lock
->pmap
, &color
, &color
, 0, 0);
237 XDefineCursor(dpy
, lock
->win
, invisible
);
238 XMapRaised(dpy
, lock
->win
);
239 for (len
= 1000; len
; len
--) {
240 if (XGrabPointer(dpy
, lock
->root
, False
, ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
241 GrabModeAsync
, GrabModeAsync
, None
, invisible
, CurrentTime
) == GrabSuccess
)
245 if (running
&& (len
> 0)) {
246 for (len
= 1000; len
; len
--) {
247 if (XGrabKeyboard(dpy
, lock
->root
, True
, GrabModeAsync
, GrabModeAsync
, CurrentTime
) == GrabSuccess
)
253 running
&= (len
> 0);
255 unlockscreen(dpy
, lock
);
259 XSelectInput(dpy
, lock
->root
, SubstructureNotifyMask
);
268 fprintf(stderr
, "usage: slock [-v]\n");
273 main(int argc
, char **argv
) {
274 #ifndef HAVE_BSD_AUTH
280 if ((argc
== 2) && !strcmp("-v", argv
[1]))
281 die("slock-%s, © 2006-2015 slock engineers\n", VERSION
);
289 if (!getpwuid(getuid()))
290 die("slock: no passwd entry for you\n");
292 #ifndef HAVE_BSD_AUTH
296 if (!(dpy
= XOpenDisplay(0)))
297 die("slock: cannot open display\n");
298 /* Get the number of screens in display "dpy" and blank them all. */
299 nscreens
= ScreenCount(dpy
);
300 locks
= malloc(sizeof(Lock
*) * nscreens
);
302 die("slock: malloc: %s\n", strerror(errno
));
304 for (screen
= 0; screen
< nscreens
; screen
++) {
305 if ( (locks
[screen
] = lockscreen(dpy
, screen
)) != NULL
)
310 /* Did we actually manage to lock something? */
311 if (nlocks
== 0) { /* nothing to protect */
317 /* Everything is now blank. Now wait for the correct password. */
324 /* Password ok, unlock everything and quit. */
325 for (screen
= 0; screen
< nscreens
; screen
++)
326 unlockscreen(dpy
, locks
[screen
]);