-/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+/* xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski <jwz@netscape.com>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* implied warranty.
*/
+/* #### If anyone ever finishes the Athena locking code, remove this.
+ But until then, locking requires Motif.
+ */
+#if defined(NO_MOTIF) && !defined(NO_LOCKING)
+# define NO_LOCKING
+#endif
+
+
+#ifndef NO_LOCKING
+
#if __STDC__
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#endif
+#ifdef HAVE_SHADOW
+#include <shadow.h>
+#endif
+
#include <pwd.h>
#include <stdio.h>
#include <X11/Intrinsic.h>
+#include "xscreensaver.h"
+
+extern char *screensaver_version;
+extern char *progname;
+extern XtAppContext app;
+extern Bool verbose_p;
+
+#ifdef SCO
+/* SCO has some kind of goofy, nonstandard security crap. This stuff was
+ donated by one of their victims, I mean users, Didier Poirot <dp@chorus.fr>.
+ */
+# include <sys/security.h>
+# include <sys/audit.h>
+# include <prot.h>
+#endif
+
#if !__STDC__
# define _NO_PROTO
#endif
-#include <Xm/Xm.h>
-#include <Xm/List.h>
-#include <Xm/TextF.h>
+#ifdef NO_MOTIF
-#include "xscreensaver.h"
+# include <X11/StringDefs.h>
+# include <X11/Xaw/Text.h>
+# include <X11/Xaw/Label.h>
-#ifndef NO_LOCKING
+#else /* Motif */
-Time passwd_timeout;
+# include <Xm/Xm.h>
+# include <Xm/List.h>
+# include <Xm/TextF.h>
-extern char *screensaver_version;
-extern char *progname;
-extern XtAppContext app;
-extern Bool verbose_p;
+#endif /* Motif */
+
+Time passwd_timeout;
extern Widget passwd_dialog;
extern Widget passwd_form;
extern Widget passwd_done;
extern Widget passwd_cancel;
-extern create_passwd_dialog ();
+extern create_passwd_dialog P((Widget));
+extern void ungrab_keyboard_and_mouse P((void));
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];
+#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
+
+#ifdef SCO
+# define PRPWTYPE struct pr_passwd *
+# define GETPRPW getprpwnam
+#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");
+
+#ifdef SCO
+ PRPWTYPE prpwd = GETPRPW ("root");
+ if (prpwd && *prpwd->ufld.fd_encrypt)
+ strcpy (root_passwd, prpwd->ufld.fd_encrypt);
+#else /* !SCO */
+ if (p && p->PWSLOT && p->PWSLOT[0] != '*')
+ strcpy (root_passwd, p->PWSLOT);
+#endif /* !SCO */
else
{
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);
+ {
+#ifdef SCO
+ prpwd = GETPRPW (u);
+#endif /* SCO */
+ p = GETPW (u);
+ }
else
{
/* getlogin() fails if not attached to a terminal;
in that case, use getpwuid(). */
- p = getpwuid (getuid ());
- u = p->pw_name;
+ struct passwd *p2 = getpwuid (getuid ());
+ u = p2->pw_name;
+#ifdef HAVE_SHADOW
+ p = GETPW (u);
+#else
+ p = p2;
+#endif
}
- if (p && p->pw_passwd && p->pw_passwd[0] != '*')
- strcpy (user_passwd, p->pw_passwd);
+#ifdef SCO
+ if (prpwd && *prpwd->ufld.fd_encrypt)
+ strcpy (user_passwd, prpwd->ufld.fd_encrypt);
+#else /* !SCO */
+ if (p && p->PWSLOT &&
+ /* p->PWSLOT[0] != '*' */ /* sensible */
+ (strlen (p->PWSLOT) > 4) /* solaris */
+ )
+ strcpy (user_passwd, p->PWSLOT);
+#endif /* !SCO */
else
{
fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u);
return ok;
}
+
+\f
+#if defined(NO_MOTIF) || (XmVersion >= 1002)
+ /* The `destroy' bug apears to be fixed as of Motif 1.2.1, but
+ the `verify-callback' bug is still present. */
+# define DESTROY_WORKS
+#endif
+
static void
passwd_cancel_cb (button, client_data, call_data)
Widget button;
passwd_state = pw_fail;
}
-#ifdef VERIFY_CALLBACK_WORKS
+#if !defined(NO_MOTIF) && defined(VERIFY_CALLBACK_WORKS)
/* #### 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 char translations[] = "<Key>:keypress()";
#endif
+static void
+text_field_set_string (widget, text, position)
+ Widget widget;
+ char *text;
+ int position;
+{
+#ifdef NO_MOTIF
+ XawTextBlock block;
+ block.firstPos = 0;
+ block.length = strlen (text);
+ block.ptr = text;
+ block.format = 0;
+ XawTextReplace (widget, 0, -1, &block);
+ XawTextSetInsertionPoint (widget, position);
+#else /* !NO_MOTIF */
+ XmTextFieldSetString (widget, text);
+ XmTextFieldSetInsertionPosition (widget, position);
+#endif /* !NO_MOTIF */
+}
+
+
static void
keypress (w, event, argv, argc)
Widget w;
s [++i] = 0;
while (i--)
s [i] = '*';
- XmTextFieldSetString (passwd_text, s);
- XmTextFieldSetInsertionPosition (passwd_text, j + 1);
+
+ text_field_set_string (passwd_text, s, j + 1);
}
static void
s [i] = 0;
while (i--)
s [i] = '*';
- XmTextFieldSetString (passwd_text, s);
- XmTextFieldSetInsertionPosition (passwd_text, j + 1);
+
+ text_field_set_string (passwd_text, s, j + 1);
}
static void
Cardinal *argc;
{
memset (typed_passwd, 0, sizeof (typed_passwd));
- XmTextFieldSetString (passwd_text, "");
+ text_field_set_string (passwd_text, "", 0);
}
static void
passwd_done_cb (w, 0, 0);
}
-#endif /* !VERIFY_CALLBACK_WORKS */
+#endif /* !VERIFY_CALLBACK_WORKS || NO_MOTIF */
static void
format_into_label (widget, string)
{
char *label;
char buf [255];
- XmString xm_label = 0;
- XmString new_xm_label;
Arg av[10];
int ac = 0;
+
+#ifdef NO_MOTIF
+ XtSetArg (av [ac], XtNlabel, &label); ac++;
+ XtGetValues (widget, av, ac);
+#else /* Motif */
+ XmString xm_label = 0;
+ XmString new_xm_label;
XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
XtGetValues (widget, av, ac);
XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
- if (!strcmp (label, XtName (widget)))
+#endif /* Motif */
+
+ if (!label || !strcmp (label, XtName (widget)))
strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
else
sprintf (buf, label, string);
- new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
+
ac = 0;
+
+#ifdef NO_MOTIF
+ XtSetArg (av [ac], XtNlabel, buf); ac++;
+#else /* Motif */
+ new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
+#endif /* Motif */
+
XtSetValues (widget, av, ac);
+#ifndef NO_MOTIF
XmStringFree (new_xm_label);
+#endif
XtFree (label);
}
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], XtNforeground, &fg); ac++;
+ XtSetArg (av [ac], XtNbackground, &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))
XFreeGC (dpy, erase_gc);
}
+#ifdef NO_MOTIF
+
+static void
+make_passwd_dialog (parent)
+ Widget parent;
+{
+ abort (); /* #### */
+}
+
+#else /* Motif */
+
static void
make_passwd_dialog (parent)
Widget parent;
XtOverrideTranslations (passwd_text, XtParseTranslationTable (translations));
#endif
+#if !defined(NO_MOTIF) && (XmVersion >= 1002)
+ /* The focus stuff changed around; this didn't exist in 1.1.5. */
+ XtVaSetValues (passwd_form, XmNinitialFocus, passwd_text, 0);
+#endif
+
+ /* Another random thing necessary in 1.2.1 but not 1.1.5... */
+ XtVaSetValues (roger_label, XmNborderWidth, 2, 0);
+
pw = getpwuid (getuid ());
format_into_label (passwd_label3, (pw->pw_name ? pw->pw_name : "???"));
format_into_label (passwd_label1, screensaver_version);
}
+#endif /* Motif */
extern void idle_timer ();
XtPointer junk2;
{
Display *dpy = XtDisplay (passwd_form);
- Window window = XtWindow (passwd_form);
+ Window window = XtWindow (XtParent(passwd_done));
static Dimension x, y, d, s, ss;
static GC gc = 0;
int max = passwd_timeout / 1000;
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;
+ unsigned long fg, bg, ts, bs;
+ Dimension w = 0, h = 0;
+ XtVaGetValues(XtParent(passwd_done),
+ XmNwidth, &w,
+ 0);
+ XtVaGetValues(passwd_done,
+ XmNheight, &h,
+ XmNy, &y,
+ XtNforeground, &fg,
+ XtNbackground, &bg,
+ XmNtopShadowColor, &ts,
+ XmNbottomShadowColor, &bs,
+ 0);
+
+ if (ts != bg && ts != fg)
+ fg = ts;
+ if (bs != bg && bs != fg)
+ fg = bs;
+
+ d = h / 2;
+ if (d & 1) d++;
+
+ x = (w / 2);
+
+ x -= d/2;
+ y += d/2;
+
gcv.foreground = fg;
if (gc) XFreeGC (dpy, gc);
gc = XCreateGC (dpy, window, GCForeground, &gcv);
if (--passwd_idle_timer_tick)
{
- id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0);
+ id = XtAppAddTimeOut (app, 1000,
+ (XtTimerCallbackProc) passwd_idle_timer, 0);
XFillArc (dpy, window, gc, x, y, d, d, ss, s);
ss += s;
}
int revert_to;
typed_passwd [0] = 0;
passwd_state = pw_read;
- XmTextFieldSetString (passwd_text, "");
+ text_field_set_string (passwd_text, "", 0);
XGetInputFocus (dpy, &focus, &revert_to);
#ifndef DESTROY_WORKS
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);
+ pop_up_dialog_box (passwd_dialog, passwd_form, 2);
XtManageChild (passwd_form);
- XSetInputFocus (dpy, XtWindow (passwd_dialog), revert_to, CurrentTime);
- XmProcessTraversal (passwd_text, 0);
+
+#if !defined(NO_MOTIF) && (XmVersion < 1002)
+ /* The focus stuff changed around; this causes problems in 1.2.1
+ but is necessary in 1.1.5. */
+ XmProcessTraversal (passwd_text, XmTRAVERSE_CURRENT);
+#endif
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! */
+ /* this call to ungrab used to be in main_loop() - see comment in
+ xscreensaver.c around line 696. */
+ ungrab_keyboard_and_mouse ();
+
while (passwd_state == pw_read)
{
XEvent event;
case pw_cancel: lose = 0; break;
default: abort ();
}
+#ifndef NO_MOTIF
XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */
+#endif
if (lose)
{
- XmTextFieldSetString (passwd_text, lose);
- XmTextFieldSetInsertionPosition (passwd_text, strlen (lose) + 1);
+ text_field_set_string (passwd_text, lose, strlen (lose) + 1);
passwd_idle_timer_tick = 1;
- id = XtAppAddTimeOut (app, 3000, passwd_idle_timer, 0);
+ id = XtAppAddTimeOut (app, 3000,
+ (XtTimerCallbackProc) passwd_idle_timer, 0);
while (1)
{
XEvent event;
}
}
memset (typed_passwd, 0, sizeof (typed_passwd));
- XmTextFieldSetString (passwd_text, "");
+ text_field_set_string (passwd_text, "", 0);
XtSetKeyboardFocus (parent, None);
-#ifndef DESTROY_WORKS
+#ifdef DESTROY_WORKS
XtDestroyWidget (passwd_dialog);
passwd_dialog = 0;
#else