+#ifdef HAVE_UNAME
+# include <sys/utsname.h> /* for hostname info */
+#endif /* HAVE_UNAME */
+#include <ctype.h>
+
+#ifndef VMS
+# include <pwd.h>
+#else /* VMS */
+
+extern char *getenv(const char *name);
+extern int validate_user(char *name, char *password);
+
+static Bool
+vms_passwd_valid_p(char *pw, Bool verbose_p)
+{
+ return (validate_user (getenv("USER"), typed_passwd) == 1);
+}
+# undef passwd_valid_p
+# define passwd_valid_p vms_passwd_valid_p
+
+#endif /* VMS */
+
+#define SAMPLE_INPUT "MMMMMMMMMMMM"
+
+
+#undef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+typedef struct info_dialog_data info_dialog_data;
+
+
+#define MAX_BYTES_PER_CHAR 8 /* UTF-8 uses no more than 3, I think */
+#define MAX_PASSWD_CHARS 128 /* Longest possible passphrase */
+
+struct passwd_dialog_data {
+
+ saver_screen_info *prompt_screen;
+ int previous_mouse_x, previous_mouse_y;
+
+ /* "Characters" in the password may be a variable number of bytes long.
+ typed_passwd contains the raw bytes.
+ typed_passwd_char_size indicates the size in bytes of each character,
+ so that we can make backspace work.
+ */
+ char typed_passwd [MAX_PASSWD_CHARS * MAX_BYTES_PER_CHAR];
+ char typed_passwd_char_size [MAX_PASSWD_CHARS];
+
+ XtIntervalId timer;
+ int i_beam;
+
+ float ratio;
+ Position x, y;
+ Dimension width;
+ Dimension height;
+ Dimension border_width;
+
+ Bool echo_input;
+ Bool show_stars_p; /* "I regret that I have but one asterisk for my country."
+ -- Nathan Hale, 1776. */
+
+ char *heading_label;
+ char *body_label;
+ char *user_label;
+ mlstring *info_label;
+ /* The entry field shall only be displayed if prompt_label is not NULL */
+ mlstring *prompt_label;
+ char *date_label;
+ char *passwd_string;
+ Bool passwd_changed_p; /* Whether the user entry field needs redrawing */
+ Bool caps_p; /* Whether we saw a keypress with caps-lock on */
+ char *unlock_label;
+ char *login_label;
+ char *uname_label;
+
+ Bool show_uname_p;
+
+ XFontStruct *heading_font;
+ XFontStruct *body_font;
+ XFontStruct *label_font;
+ XFontStruct *passwd_font;
+ XFontStruct *date_font;
+ XFontStruct *button_font;
+ XFontStruct *uname_font;
+
+ Pixel foreground;
+ Pixel background;
+ Pixel border;
+ Pixel passwd_foreground;
+ Pixel passwd_background;
+ Pixel thermo_foreground;
+ Pixel thermo_background;
+ Pixel shadow_top;
+ Pixel shadow_bottom;
+ Pixel button_foreground;
+ Pixel button_background;
+
+ Dimension preferred_logo_width, logo_width;
+ Dimension preferred_logo_height, logo_height;
+ Dimension thermo_width;
+ Dimension internal_border;
+ Dimension shadow_width;
+
+ Dimension passwd_field_x, passwd_field_y;
+ Dimension passwd_field_width, passwd_field_height;
+
+ Dimension unlock_button_x, unlock_button_y;
+ Dimension unlock_button_width, unlock_button_height;
+
+ Dimension login_button_x, login_button_y;
+ Dimension login_button_width, login_button_height;
+
+ Dimension thermo_field_x, thermo_field_y;
+ Dimension thermo_field_height;
+
+ Pixmap logo_pixmap;
+ Pixmap logo_clipmask;
+ int logo_npixels;
+ unsigned long *logo_pixels;
+
+ Cursor passwd_cursor;
+ Bool unlock_button_down_p;
+ Bool login_button_down_p;
+ Bool login_button_p;
+ Bool login_button_enabled_p;
+ Bool button_state_changed_p; /* Refers to both buttons */
+
+ Pixmap save_under;
+ Pixmap user_entry_pixmap;
+};
+
+static void draw_passwd_window (saver_info *si);
+static void update_passwd_window (saver_info *si, const char *printed_passwd,
+ float ratio);
+static void destroy_passwd_window (saver_info *si);
+static void undo_vp_motion (saver_info *si);
+static void finished_typing_passwd (saver_info *si, passwd_dialog_data *pw);
+static void cleanup_passwd_window (saver_info *si);
+static void restore_background (saver_info *si);
+
+extern void xss_authenticate(saver_info *si, Bool verbose_p);
+
+static int
+new_passwd_window (saver_info *si)
+{
+ passwd_dialog_data *pw;
+ Screen *screen;
+ Colormap cmap;
+ char *f;
+ saver_screen_info *ssi = &si->screens [mouse_screen (si)];
+
+ pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
+ if (!pw)
+ return -1;
+
+ /* Display the button only if the "newLoginCommand" pref is non-null.
+ */
+ pw->login_button_p = (si->prefs.new_login_command &&
+ *si->prefs.new_login_command);
+
+ pw->passwd_cursor = XCreateFontCursor (si->dpy, XC_top_left_arrow);
+
+ pw->prompt_screen = ssi;
+
+ screen = pw->prompt_screen->screen;
+ cmap = DefaultColormapOfScreen (screen);
+
+ pw->show_stars_p = get_boolean_resource(si->dpy, "passwd.asterisks",
+ "Boolean");
+
+ pw->heading_label = get_string_resource (si->dpy, "passwd.heading.label",
+ "Dialog.Label.Label");
+ pw->body_label = get_string_resource (si->dpy, "passwd.body.label",
+ "Dialog.Label.Label");
+ pw->user_label = get_string_resource (si->dpy, "passwd.user.label",
+ "Dialog.Label.Label");
+ pw->unlock_label = get_string_resource (si->dpy, "passwd.unlock.label",
+ "Dialog.Button.Label");
+ pw->login_label = get_string_resource (si->dpy, "passwd.login.label",
+ "Dialog.Button.Label");
+
+ pw->date_label = get_string_resource (si->dpy, "dateFormat", "DateFormat");
+
+ if (!pw->heading_label)
+ pw->heading_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
+ if (!pw->body_label)
+ pw->body_label = strdup("ERROR: RESOURCES NOT INSTALLED CORRECTLY");
+ if (!pw->user_label) pw->user_label = strdup("ERROR");
+ if (!pw->date_label) pw->date_label = strdup("ERROR");
+ if (!pw->unlock_label) pw->unlock_label = strdup("ERROR (UNLOCK)");
+ if (!pw->login_label) pw->login_label = strdup ("ERROR (LOGIN)") ;
+
+ /* Put the version number in the label. */
+ {
+ char *s = (char *) malloc (strlen(pw->heading_label) + 20);
+ sprintf(s, pw->heading_label, si->version);
+ free (pw->heading_label);
+ pw->heading_label = s;
+ }
+
+ /* Get hostname info */
+ pw->uname_label = strdup(""); /* Initialy, write nothing */
+
+# ifdef HAVE_UNAME
+ {
+ struct utsname uts;
+
+ if (uname (&uts) == 0)
+ {
+#if 0 /* Get the full hostname */
+ {
+ char *s;
+ if ((s = strchr(uts.nodename, '.')))
+ *s = 0;
+ }