X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Flock.c;h=92137aa821a70ec9077d19dbf29cdb3d5dfb5fee;hb=258170f6204e23da06f272ffda1f4504b6ae2eaf;hp=48b2f5260480544723bc54933e49195223138ac8;hpb=0a1527cc01e9894017614b7c36b838b2b6914ba9;p=xscreensaver diff --git a/driver/lock.c b/driver/lock.c index 48b2f526..92137aa8 100644 --- a/driver/lock.c +++ b/driver/lock.c @@ -1,11 +1,11 @@ -/* xscreensaver, Copyright (c) 1993 Jamie Zawinski +/* xscreensaver, Copyright (c) 1993 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or + * software for any purpose. It is provided "as is" without express or * implied warranty. */ @@ -15,6 +15,10 @@ #include #endif +#ifdef HAVE_SHADOW +#include +#endif + #include #include @@ -30,9 +34,9 @@ #include "xscreensaver.h" +Time passwd_timeout; #ifndef NO_LOCKING -Time passwd_timeout; extern char *screensaver_version; extern char *progname; @@ -50,48 +54,69 @@ extern Widget passwd_cancel; extern create_passwd_dialog (); -static enum { pw_read, pw_ok, pw_fail, pw_cancel, pw_time } passwd_state; -static char typed_passwd [1024]; +static enum +{ + pw_read, pw_ok, pw_fail, pw_cancel, pw_time +} passwd_state; +static char typed_passwd[1024]; -static char root_passwd [255]; -static char user_passwd [255]; +static char root_passwd[255]; +static char user_passwd[255]; + +#ifdef HAVE_SHADOW +# define PWTYPE struct spwd * +# define PWSLOT sp_pwdp +# define GETPW getspnam +#else +# define PWTYPE struct passwd * +# define PWSLOT pw_passwd +# define GETPW getpwnam +#endif Bool lock_init () { Bool ok = True; - struct passwd *p; char *u; - p = getpwnam ("root"); - if (p && p->pw_passwd && p->pw_passwd[0] != '*') - strcpy (root_passwd, p->pw_passwd); + PWTYPE p = GETPW ("root"); + + if (p && p->PWSLOT && p->PWSLOT[0] != '*') + strcpy (root_passwd, p->PWSLOT); else - { - fprintf (stderr, "%s: couldn't get root's password\n", progname); - strcpy (root_passwd, "*"); - } + { + fprintf (stderr, "%s: couldn't get root's password\n", progname); + strcpy (root_passwd, "*"); + } - u = getlogin (); + /* It has been reported that getlogin() returns the wrong user id on some + very old SGI systems... */ + u = (char *) getlogin (); if (u) - p = getpwnam (u); + p = GETPW (u); else - { - /* getlogin() fails if not attached to a terminal; + { + /* getlogin() fails if not attached to a terminal; in that case, use getpwuid(). */ - p = getpwuid (getuid ()); - u = p->pw_name; - } + p = getpwuid (getuid ()); + u = p->pw_name; + } - if (p && p->pw_passwd && p->pw_passwd[0] != '*') - strcpy (user_passwd, p->pw_passwd); + if (p && p->PWSLOT && p->PWSLOT[0] != '*') + strcpy (user_passwd, p->PWSLOT); else - { - fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u); - strcpy (user_passwd, "*"); - ok = False; - } + { + fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u); + strcpy (user_passwd, "*"); + ok = False; + } return ok; } + +#ifdef XmVersion +# if (XmVersion >= 1002) /* The `destroy' bug apears to be fixed as */ +# define DESTROY_WORKS /* of Motif 1.2.1, but the `verify-callback' */ +# endif /* bug is still present. */ +#endif static void passwd_cancel_cb (button, client_data, call_data) @@ -106,11 +131,13 @@ passwd_done_cb (button, client_data, call_data) Widget button; XtPointer client_data, call_data; { - if (passwd_state != pw_read) return; /* already done */ + if (passwd_state != pw_read) + return; /* already done */ + if (!strcmp ((char *) crypt (typed_passwd, user_passwd), user_passwd)) passwd_state = pw_ok; /* do not allow root to have empty passwd */ - else if (typed_passwd [0] && + else if (typed_passwd[0] && !strcmp ((char *) crypt (typed_passwd, root_passwd), root_passwd)) passwd_state = pw_ok; else @@ -119,13 +146,17 @@ passwd_done_cb (button, client_data, call_data) #ifdef VERIFY_CALLBACK_WORKS - /* #### It looks to me like adding any modifyVerify callback causes +/* #### It looks to me like adding any modifyVerify callback causes #### Motif 1.1.4 to free the the TextF_Value() twice. I can't see #### the bug in the Motif source, but Purify complains, even if #### check_passwd_cb() is a no-op. + + #### Update: Motif 1.2.1 also loses, but in a different way: it + #### writes beyond the end of a malloc'ed block in ModifyVerify(). + #### Probably this block is the text field's text. */ -static void +static void check_passwd_cb (button, client_data, call_data) Widget button; XtPointer client_data, call_data; @@ -135,37 +166,40 @@ check_passwd_cb (button, client_data, call_data) if (passwd_state != pw_read) return; else if (vcb->reason == XmCR_ACTIVATE) - { - passwd_done_cb (0, 0, 0); - } + { + passwd_done_cb (0, 0, 0); + } else if (vcb->text->length > 1) /* don't allow "paste" operations */ - { - vcb->doit = False; - } + { + vcb->doit = False; + } else if (vcb->text->ptr != 0) - { - int i; - strncat (typed_passwd, vcb->text->ptr, vcb->text->length); - typed_passwd [vcb->endPos + vcb->text->length] = 0; - for (i = 0; i < vcb->text->length; i++) - vcb->text->ptr [i] = '*'; - } + { + int i; + + strncat (typed_passwd, vcb->text->ptr, vcb->text->length); + typed_passwd[vcb->endPos + vcb->text->length] = 0; + for (i = 0; i < vcb->text->length; i++) + vcb->text->ptr[i] = '*'; + } } #else /* !VERIFY_CALLBACK_WORKS */ -static void keypress(); -static void backspace(); -static void kill_line(); -static void done(); +static void keypress (); +static void backspace (); +static void kill_line (); +static void done (); -static XtActionsRec actions[] = {{"keypress", keypress}, - {"backspace", backspace}, - {"kill_line", kill_line}, - {"done", done} - }; +static XtActionsRec actions[] = +{ + {"keypress", keypress}, + {"backspace", backspace}, + {"kill_line", kill_line}, + {"done", done} +}; -#if 0 /* oh fuck, why doesn't this work? */ +#if 0 /* oh fuck, why doesn't this work? */ static char translations[] = "\ BackSpace: backspace()\n\ Delete: backspace()\n\ @@ -176,8 +210,10 @@ CtrlJ: done()\n\ CtrlM: done()\n\ : keypress()\n\ "; + #else static char translations[] = ":keypress()"; + #endif static void @@ -188,23 +224,49 @@ keypress (w, event, argv, argc) Cardinal *argc; { int i, j; - char s [sizeof (typed_passwd)]; + char s[sizeof (typed_passwd)]; int size = XLookupString ((XKeyEvent *) event, s, sizeof (s), 0, 0); - if (size != 1) return; + + if (size != 1) + return; /* hack because I can't get translations to dance to my tune... */ - if (*s == '\010') { backspace (w, event, argv, argc); return; } - if (*s == '\177') { backspace (w, event, argv, argc); return; } - if (*s == '\025') { kill_line (w, event, argv, argc); return; } - if (*s == '\030') { kill_line (w, event, argv, argc); return; } - if (*s == '\012') { done (w, event, argv, argc); return; } - if (*s == '\015') { done (w, event, argv, argc); return; } + if (*s == '\010') + { + backspace (w, event, argv, argc); + return; + } + if (*s == '\177') + { + backspace (w, event, argv, argc); + return; + } + if (*s == '\025') + { + kill_line (w, event, argv, argc); + return; + } + if (*s == '\030') + { + kill_line (w, event, argv, argc); + return; + } + if (*s == '\012') + { + done (w, event, argv, argc); + return; + } + if (*s == '\015') + { + done (w, event, argv, argc); + return; + } i = j = strlen (typed_passwd); - typed_passwd [i] = *s; - s [++i] = 0; + typed_passwd[i] = *s; + s[++i] = 0; while (i--) - s [i] = '*'; + s[i] = '*'; XmTextFieldSetString (passwd_text, s); XmTextFieldSetInsertionPosition (passwd_text, j + 1); } @@ -216,15 +278,16 @@ backspace (w, event, argv, argc) String *argv; Cardinal *argc; { - char s [sizeof (typed_passwd)]; + char s[sizeof (typed_passwd)]; int i = strlen (typed_passwd); int j = i; + if (i == 0) return; - typed_passwd [--i] = 0; - s [i] = 0; + typed_passwd[--i] = 0; + s[i] = 0; while (i--) - s [i] = '*'; + s[i] = '*'; XmTextFieldSetString (passwd_text, s); XmTextFieldSetInsertionPosition (passwd_text, j + 1); } @@ -258,12 +321,14 @@ format_into_label (widget, string) char *string; { char *label; - char buf [255]; + char buf[255]; XmString xm_label = 0; XmString new_xm_label; Arg av[10]; int ac = 0; - XtSetArg (av [ac], XmNlabelString, &xm_label); ac++; + + XtSetArg (av[ac], XmNlabelString, &xm_label); + ac++; XtGetValues (widget, av, ac); XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); if (!strcmp (label, XtName (widget))) @@ -272,7 +337,8 @@ format_into_label (widget, string) sprintf (buf, label, string); new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET); ac = 0; - XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++; + XtSetArg (av[ac], XmNlabelString, new_xm_label); + ac++; XtSetValues (widget, av, ac); XmStringFree (new_xm_label); XtFree (label); @@ -280,6 +346,7 @@ format_into_label (widget, string) #if __STDC__ extern void skull (Display *, Window, GC, GC, int, int, int, int); + #endif static void @@ -290,7 +357,7 @@ roger (button, client_data, call_data) Display *dpy = XtDisplay (button); Screen *screen = XtScreen (button); Window window = XtWindow (button); - Arg av [10]; + Arg av[10]; int ac = 0; XGCValues gcv; Colormap cmap; @@ -298,15 +365,21 @@ roger (button, client_data, call_data) unsigned int fg, bg; int x, y, size; XWindowAttributes xgwa; + XGetWindowAttributes (dpy, window, &xgwa); cmap = xgwa.colormap; - if (xgwa.width > xgwa.height) size = xgwa.height; - else size = xgwa.width; - if (size > 40) size -= 30; + if (xgwa.width > xgwa.height) + size = xgwa.height; + else + size = xgwa.width; + if (size > 40) + size -= 30; x = (xgwa.width - size) / 2; y = (xgwa.height - size) / 2; - XtSetArg (av [ac], XmNforeground, &fg); ac++; - XtSetArg (av [ac], XmNbackground, &bg); ac++; + XtSetArg (av[ac], XmNforeground, &fg); + ac++; + XtSetArg (av[ac], XmNbackground, &bg); + ac++; XtGetValues (button, av, ac); /* if it's black on white, swap it cause it looks better (hack hack) */ if (fg == BlackPixelOfScreen (screen) && bg == WhitePixelOfScreen (screen)) @@ -326,6 +399,7 @@ make_passwd_dialog (parent) Widget parent; { struct passwd *pw; + create_passwd_dialog (parent); XtAddCallback (passwd_done, XmNactivateCallback, passwd_done_cb, 0); @@ -345,7 +419,6 @@ make_passwd_dialog (parent) format_into_label (passwd_label1, screensaver_version); } - extern void idle_timer (); static int passwd_idle_timer_tick; @@ -364,41 +437,48 @@ passwd_idle_timer (junk1, junk2) idle_timer (junk1, junk2); - if (passwd_idle_timer_tick == max) /* first time */ - { - Arg av [10]; - int ac = 0; - XGCValues gcv; - unsigned long fg, bg; - XtSetArg (av [ac], XmNheight, &d); ac++; - XtGetValues (passwd_done, av, ac); - ac = 0; - XtSetArg (av [ac], XmNwidth, &x); ac++; - XtSetArg (av [ac], XmNheight, &y); ac++; - XtSetArg (av [ac], XmNforeground, &fg); ac++; - XtSetArg (av [ac], XmNbackground, &bg); ac++; - XtGetValues (passwd_form, av, ac); - x -= d; - y -= d; - d -= 4; - gcv.foreground = fg; - if (gc) XFreeGC (dpy, gc); - gc = XCreateGC (dpy, window, GCForeground, &gcv); - s = 360*64 / (passwd_idle_timer_tick - 1); - ss = 90*64; - XFillArc (dpy, window, gc, x, y, d, d, 0, 360*64); - XSetForeground (dpy, gc, bg); - x += 1; - y += 1; - d -= 2; - } + if (passwd_idle_timer_tick == max) /* first time */ + { + Arg av[10]; + int ac = 0; + XGCValues gcv; + unsigned long fg, bg; + + XtSetArg (av[ac], XmNheight, &d); + ac++; + XtGetValues (passwd_done, av, ac); + ac = 0; + XtSetArg (av[ac], XmNwidth, &x); + ac++; + XtSetArg (av[ac], XmNheight, &y); + ac++; + XtSetArg (av[ac], XmNforeground, &fg); + ac++; + XtSetArg (av[ac], XmNbackground, &bg); + ac++; + XtGetValues (passwd_form, av, ac); + x -= d; + y -= d; + d -= 4; + gcv.foreground = fg; + if (gc) + XFreeGC (dpy, gc); + gc = XCreateGC (dpy, window, GCForeground, &gcv); + s = 360 * 64 / (passwd_idle_timer_tick - 1); + ss = 90 * 64; + XFillArc (dpy, window, gc, x, y, d, d, 0, 360 * 64); + XSetForeground (dpy, gc, bg); + x += 1; + y += 1; + d -= 2; + } if (--passwd_idle_timer_tick) - { - id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0); - XFillArc (dpy, window, gc, x, y, d, d, ss, s); - ss += s; - } + { + id = XtAppAddTimeOut (app, 1000, (XtTimerCallbackProc) passwd_idle_timer, 0); + XFillArc (dpy, window, gc, x, y, d, d, ss, s); + ss += s; + } } extern void pop_up_dialog_box (); @@ -411,7 +491,8 @@ pop_passwd_dialog (parent) Display *dpy = XtDisplay (passwd_dialog); Window focus; int revert_to; - typed_passwd [0] = 0; + + typed_passwd[0] = 0; passwd_state = pw_read; XmTextFieldSetString (passwd_text, ""); @@ -423,68 +504,79 @@ pop_passwd_dialog (parent) doesn't work right either, so we hack the window directly. FMH. */ if (XtWindow (passwd_form)) - XMapWindow (dpy, XtWindow (passwd_dialog)); + XMapRaised (dpy, XtWindow (passwd_dialog)); #endif pop_up_dialog_box (passwd_dialog, passwd_form, 2); XtManageChild (passwd_form); XSetInputFocus (dpy, XtWindow (passwd_dialog), revert_to, CurrentTime); + + /* #### This doesn't work in 1.2.1... Check return code... */ XmProcessTraversal (passwd_text, 0); passwd_idle_timer_tick = passwd_timeout / 1000; - id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0); + id = XtAppAddTimeOut (app, 1000, (XtTimerCallbackProc) passwd_idle_timer, 0); - - XGrabServer (dpy); /* ############ DANGER! */ + XGrabServer (dpy); /* ############ DANGER! */ while (passwd_state == pw_read) - { - XEvent event; - XtAppNextEvent (app, &event); - /* wait for timer event */ - if (event.xany.type == 0 && passwd_idle_timer_tick == 0) - passwd_state = pw_time; - XtDispatchEvent (&event); - } + { + XEvent event; + + XtAppNextEvent (app, &event); + /* wait for timer event */ + if (event.xany.type == 0 && passwd_idle_timer_tick == 0) + passwd_state = pw_time; + XtDispatchEvent (&event); + } XUngrabServer (dpy); - XSync (dpy, False); /* ###### (danger over) */ + XSync (dpy, False); /* ###### (danger over) */ if (passwd_state != pw_time) XtRemoveTimeOut (id); if (passwd_state != pw_ok) + { + char *lose; + + switch (passwd_state) + { + case pw_time: + lose = "Timed out!"; + break; + case pw_fail: + lose = "Sorry!"; + break; + case pw_cancel: + lose = 0; + break; + default: + abort (); + } + XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */ + if (lose) { - char *lose; - switch (passwd_state) - { - case pw_time: lose = "Timed out!"; break; - case pw_fail: lose = "Sorry!"; break; - case pw_cancel: lose = 0; break; - default: abort (); - } - XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */ - if (lose) - { - XmTextFieldSetString (passwd_text, lose); - XmTextFieldSetInsertionPosition (passwd_text, strlen (lose) + 1); - passwd_idle_timer_tick = 1; - id = XtAppAddTimeOut (app, 3000, passwd_idle_timer, 0); - while (1) - { - XEvent event; - XtAppNextEvent (app, &event); - if (event.xany.type == 0 && /* wait for timer event */ - passwd_idle_timer_tick == 0) - break; - XtDispatchEvent (&event); - } - } + XmTextFieldSetString (passwd_text, lose); + XmTextFieldSetInsertionPosition (passwd_text, strlen (lose) + 1); + passwd_idle_timer_tick = 1; + id = XtAppAddTimeOut (app, 3000, (XtTimerCallbackProc) passwd_idle_timer, 0); + while (1) + { + XEvent event; + + XtAppNextEvent (app, &event); + if (event.xany.type == 0 && /* wait for timer event */ + passwd_idle_timer_tick == 0) + break; + XtDispatchEvent (&event); + } } + } memset (typed_passwd, 0, sizeof (typed_passwd)); XmTextFieldSetString (passwd_text, ""); XtSetKeyboardFocus (parent, None); -#ifndef DESTROY_WORKS +#ifdef DESTROY_WORKS XtDestroyWidget (passwd_dialog); passwd_dialog = 0; #else @@ -492,6 +584,7 @@ pop_passwd_dialog (parent) #endif { int (*old_handler) (); + old_handler = XSetErrorHandler (BadWindow_ehandler); /* I don't understand why this doesn't refocus on the old selected window when MWM is running in click-to-type mode. The value of @@ -509,15 +602,16 @@ unlock_p (parent) Widget parent; { static Bool initted = False; - if (! initted) - { + + if (!initted) + { #ifndef VERIFY_CALLBACK_WORKS - XtAppAddActions (app, actions, XtNumber (actions)); + XtAppAddActions (app, actions, XtNumber (actions)); #endif - passwd_dialog = 0; - initted = True; - } - if (! passwd_dialog) + passwd_dialog = 0; + initted = True; + } + if (!passwd_dialog) make_passwd_dialog (parent); return pop_passwd_dialog (parent); }