summaryrefslogtreecommitdiff
path: root/xtrlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'xtrlock.c')
-rw-r--r--xtrlock.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/xtrlock.c b/xtrlock.c
new file mode 100644
index 0000000..6117c6f
--- /dev/null
+++ b/xtrlock.c
@@ -0,0 +1,274 @@
+/*
+ * xtrlock.c
+ *
+ * X Transparent Lock
+ *
+ * Copyright (C)1993,1994 Ian Jackson
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xos.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <limits.h>
+#include <string.h>
+#include <crypt.h>
+#include <unistd.h>
+#include <math.h>
+#include <ctype.h>
+#include <values.h>
+
+#ifdef SHADOW_PWD
+#include <shadow.h>
+#endif
+
+#include "lock.bitmap"
+#include "mask.bitmap"
+#include "patchlevel.h"
+
+Display *display;
+Window window, root;
+
+#define TIMEOUTPERATTEMPT 30000
+#define MAXGOODWILL (TIMEOUTPERATTEMPT*5)
+#define INITIALGOODWILL MAXGOODWILL
+#define GOODWILLPORTION 0.3
+
+struct passwd *pw;
+int passwordok(const char *s) {
+#if 0
+ char key[3];
+ char *encr;
+
+ key[0] = *(pw->pw_passwd);
+ key[1] = (pw->pw_passwd)[1];
+ key[2] = 0;
+ encr = crypt(s, key);
+ return !strcmp(encr, pw->pw_passwd);
+#else
+ /* simpler, and should work with crypt() algorithms using longer
+ salt strings (like the md5-based one on freebsd). --marekm */
+ return !strcmp(crypt(s, pw->pw_passwd), pw->pw_passwd);
+#endif
+}
+
+int main(int argc, char **argv){
+ XEvent ev;
+ KeySym ks;
+ char cbuf[10], rbuf[128]; /* shadow appears to suggest 127 a good value here */
+ int clen, rlen=0;
+ long goodwill= INITIALGOODWILL, timeout= 0;
+ XSetWindowAttributes attrib;
+ Cursor cursor;
+ Pixmap csr_source,csr_mask;
+ XColor csr_fg, csr_bg, dummy, black;
+ int ret, screen, blank = 0, fork_after = 0;
+#ifdef SHADOW_PWD
+ struct spwd *sp;
+#endif
+ struct timeval tv;
+ int tvt, gs;
+
+ while (argc > 1) {
+ if ((strcmp(argv[1], "-b") == 0)) {
+ blank = 1;
+ argc--;
+ argv++;
+ } else if ((strcmp(argv[1], "-f") == 0)) {
+ fork_after = 1;
+ argc--;
+ argv++;
+ } else {
+ fprintf(stderr,"xtrlock (version %s); usage: xtrlock [-b] [-f]\n",
+ program_version);
+ exit(1);
+ }
+ }
+
+ errno=0; pw= getpwuid(getuid());
+ if (!pw) { perror("password entry for uid not found"); exit(1); }
+#ifdef SHADOW_PWD
+ sp = getspnam(pw->pw_name);
+ if (sp)
+ pw->pw_passwd = sp->sp_pwdp;
+ endspent();
+#endif
+
+ /* logically, if we need to do the following then the same
+ applies to being installed setgid shadow.
+ we do this first, because of a bug in linux. --jdamery */
+ if (setgid(getgid())) { perror("setgid"); exit(1); }
+ /* we can be installed setuid root to support shadow passwords,
+ and we don't need root privileges any longer. --marekm */
+ if (setuid(getuid())) { perror("setuid"); exit(1); }
+
+ if (strlen(pw->pw_passwd) < 13) {
+ fputs("password entry has no pwd\n",stderr); exit(1);
+ }
+
+ display= XOpenDisplay(0);
+
+ if (display==NULL) {
+ fprintf(stderr,"xtrlock (version %s): cannot open display\n",
+ program_version);
+ exit(1);
+ }
+
+ attrib.override_redirect= True;
+
+ if (blank) {
+ screen = DefaultScreen(display);
+ attrib.background_pixel = BlackPixel(display, screen);
+ window= XCreateWindow(display,DefaultRootWindow(display),
+ 0,0,DisplayWidth(display, screen),DisplayHeight(display, screen),
+ 0,DefaultDepth(display, screen), CopyFromParent, DefaultVisual(display, screen),
+ CWOverrideRedirect|CWBackPixel,&attrib);
+ XAllocNamedColor(display, DefaultColormap(display, screen), "black", &black, &dummy);
+ } else {
+ window= XCreateWindow(display,DefaultRootWindow(display),
+ 0,0,1,1,0,CopyFromParent,InputOnly,CopyFromParent,
+ CWOverrideRedirect,&attrib);
+ }
+
+ XSelectInput(display,window,KeyPressMask|KeyReleaseMask);
+
+ csr_source= XCreateBitmapFromData(display,window,lock_bits,lock_width,lock_height);
+ csr_mask= XCreateBitmapFromData(display,window,mask_bits,mask_width,mask_height);
+
+ ret = XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "steelblue3",
+ &dummy, &csr_bg);
+ if (ret==0)
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "black",
+ &dummy, &csr_bg);
+
+ ret = XAllocNamedColor(display,
+ DefaultColormap(display,DefaultScreen(display)),
+ "grey25",
+ &dummy, &csr_fg);
+ if (ret==0)
+ XAllocNamedColor(display,
+ DefaultColormap(display, DefaultScreen(display)),
+ "white",
+ &dummy, &csr_bg);
+
+
+
+ cursor= XCreatePixmapCursor(display,csr_source,csr_mask,&csr_fg,&csr_bg,
+ lock_x_hot,lock_y_hot);
+
+ XMapWindow(display,window);
+
+ /*Sometimes the WM doesn't ungrab the keyboard quickly enough if
+ *launching xtrlock from a keystroke shortcut, meaning xtrlock fails
+ *to start We deal with this by waiting (up to 100 times) for 10,000
+ *microsecs and trying to grab each time. If we still fail
+ *(i.e. after 1s in total), then give up, and emit an error
+ */
+
+ gs=0; /*gs==grab successful*/
+ for (tvt=0 ; tvt<100; tvt++) {
+ ret = XGrabKeyboard(display,window,False,GrabModeAsync,GrabModeAsync,
+ CurrentTime);
+ if (ret == GrabSuccess) {
+ gs=1;
+ break;
+ }
+ /*grab failed; wait .01s*/
+ tv.tv_sec=0;
+ tv.tv_usec=10000;
+ select(1,NULL,NULL,NULL,&tv);
+ }
+ if (gs==0){
+ fprintf(stderr,"xtrlock (version %s): cannot grab keyboard\n",
+ program_version);
+ exit(1);
+ }
+
+ if (XGrabPointer(display,window,False,(KeyPressMask|KeyReleaseMask)&0,
+ GrabModeAsync,GrabModeAsync,None,
+ cursor,CurrentTime)!=GrabSuccess) {
+ XUngrabKeyboard(display,CurrentTime);
+ fprintf(stderr,"xtrlock (version %s): cannot grab pointer\n",
+ program_version);
+ exit(1);
+ }
+
+ if (fork_after) {
+ pid_t pid = fork();
+ if (pid < 0) {
+ fprintf(stderr,"xtrlock (version %s): cannot fork: %s\n",
+ program_version, strerror(errno));
+ exit(1);
+ } else if (pid > 0) {
+ exit(0);
+ }
+ }
+
+ for (;;) {
+ XNextEvent(display,&ev);
+ switch (ev.type) {
+ case KeyPress:
+ if (ev.xkey.time < timeout) { XBell(display,0); break; }
+ clen= XLookupString(&ev.xkey,cbuf,9,&ks,0);
+ switch (ks) {
+ case XK_Escape: case XK_Clear:
+ rlen=0; break;
+ case XK_Delete: case XK_BackSpace:
+ if (rlen>0) rlen--;
+ break;
+ case XK_Linefeed: case XK_Return:
+ if (rlen==0) break;
+ rbuf[rlen]=0;
+ if (passwordok(rbuf)) goto loop_x;
+ XBell(display,0);
+ rlen= 0;
+ if (timeout) {
+ goodwill+= ev.xkey.time - timeout;
+ if (goodwill > MAXGOODWILL) {
+ goodwill= MAXGOODWILL;
+ }
+ }
+ timeout= -goodwill*GOODWILLPORTION;
+ goodwill+= timeout;
+ timeout+= ev.xkey.time + TIMEOUTPERATTEMPT;
+ break;
+ default:
+ if (clen != 1) break;
+ /* allow space for the trailing \0 */
+ if (rlen < (sizeof(rbuf) - 1)){
+ rbuf[rlen]=cbuf[0];
+ rlen++;
+ }
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ loop_x:
+ exit(0);
+}