1 /* lock.c --- handling the password dialog for locking-mode.
2 * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* Athena locking code contributed by Jon A. Christopher <jac8782@tamu.edu> */
14 /* Copyright 1997, with the same permissions as above. */
20 #ifndef NO_LOCKING /* whole file */
22 #include <X11/Intrinsic.h>
23 #include "xscreensaver.h"
24 #include "resources.h"
28 #endif /* HAVE_SYSLOG */
31 ERROR! You must not include vroot.h in this file.
38 extern char *getenv(const char *name);
39 extern int validate_user(char *name, char *password);
42 vms_passwd_valid_p(char *pw, Bool verbose_p)
44 return (validate_user (getenv("USER"), typed_passwd) == 1);
46 # undef passwd_valid_p
47 # define passwd_valid_p vms_passwd_valid_p
53 #define MAX(a,b) ((a)>(b)?(a):(b))
55 enum passwd_state { pw_read, pw_ok, pw_null, pw_fail, pw_cancel, pw_time };
57 struct passwd_dialog_data {
59 enum passwd_state state;
60 char typed_passwd [80];
68 Dimension border_width;
77 XFontStruct *heading_font;
78 XFontStruct *body_font;
79 XFontStruct *label_font;
80 XFontStruct *passwd_font;
84 Pixel passwd_foreground;
85 Pixel passwd_background;
86 Pixel logo_foreground;
87 Pixel logo_background;
92 Dimension logo_height;
93 Dimension thermo_width;
94 Dimension internal_border;
95 Dimension shadow_width;
97 Dimension passwd_field_x, passwd_field_y;
98 Dimension passwd_field_width, passwd_field_height;
100 Dimension thermo_field_x, thermo_field_y;
101 Dimension thermo_field_height;
108 make_passwd_window (saver_info *si)
110 struct passwd *p = getpwuid (getuid ());
111 XSetWindowAttributes attrs;
112 unsigned long attrmask = 0;
113 Screen *screen = si->default_screen->screen;
114 passwd_dialog_data *pw = (passwd_dialog_data *) calloc (1, sizeof(*pw));
115 Colormap cmap = DefaultColormapOfScreen (screen);
120 pw->heading_label = get_string_resource ("passwd.heading.label",
121 "Dialog.Label.Label");
122 pw->body_label = get_string_resource ("passwd.body.label",
123 "Dialog.Label.Label");
124 pw->user_label = get_string_resource ("passwd.user.label",
125 "Dialog.Label.Label");
126 pw->passwd_label = get_string_resource ("passwd.passwd.label",
127 "Dialog.Label.Label");
129 if (!pw->heading_label)
130 pw->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
132 pw->body_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
133 if (!pw->user_label) pw->user_label = strdup("ERROR");
134 if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
136 /* Put the version number in the label. */
138 char *s = (char *) malloc (strlen(pw->heading_label) + 20);
139 sprintf(s, pw->heading_label, si->version);
140 free (pw->heading_label);
141 pw->heading_label = s;
144 pw->user_string = (p->pw_name ? p->pw_name : "???");
145 pw->passwd_string = strdup("");
147 f = get_string_resource ("passwd.headingFont", "Dialog.Font");
148 pw->heading_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
149 if (!pw->heading_font) pw->heading_font = XLoadQueryFont (si->dpy, "fixed");
152 f = get_string_resource("passwd.bodyFont", "Dialog.Font");
153 pw->body_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
154 if (!pw->body_font) pw->body_font = XLoadQueryFont (si->dpy, "fixed");
157 f = get_string_resource("passwd.labelFont", "Dialog.Font");
158 pw->label_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
159 if (!pw->label_font) pw->label_font = XLoadQueryFont (si->dpy, "fixed");
162 f = get_string_resource("passwd.passwdFont", "Dialog.Font");
163 pw->passwd_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
164 if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
167 pw->foreground = get_pixel_resource ("passwd.foreground",
170 pw->background = get_pixel_resource ("passwd.background",
174 if (pw->foreground == pw->background)
176 /* Make sure the error messages show up. */
177 pw->foreground = BlackPixelOfScreen (screen);
178 pw->background = WhitePixelOfScreen (screen);
181 pw->passwd_foreground = get_pixel_resource ("passwd.text.foreground",
182 "Dialog.Text.Foreground",
184 pw->passwd_background = get_pixel_resource ("passwd.text.background",
185 "Dialog.Text.Background",
187 pw->logo_foreground = get_pixel_resource ("passwd.logo.foreground",
188 "Dialog.Logo.Foreground",
190 pw->logo_background = get_pixel_resource ("passwd.logo.background",
191 "Dialog.Logo.Background",
193 pw->shadow_top = get_pixel_resource ("passwd.topShadowColor",
196 pw->shadow_bottom = get_pixel_resource ("passwd.bottomShadowColor",
200 pw->logo_width = get_integer_resource ("passwd.logo.width",
201 "Dialog.Logo.Width");
202 pw->logo_height = get_integer_resource ("passwd.logo.height",
203 "Dialog.Logo.Height");
204 pw->thermo_width = get_integer_resource ("passwd.thermometer.width",
205 "Dialog.Thermometer.Width");
206 pw->internal_border = get_integer_resource ("passwd.internalBorderWidth",
207 "Dialog.InternalBorderWidth");
208 pw->shadow_width = get_integer_resource ("passwd.shadowThickness",
209 "Dialog.ShadowThickness");
211 if (pw->logo_width == 0) pw->logo_width = 150;
212 if (pw->logo_height == 0) pw->logo_height = 150;
213 if (pw->internal_border == 0) pw->internal_border = 15;
214 if (pw->shadow_width == 0) pw->shadow_width = 4;
215 if (pw->thermo_width == 0) pw->thermo_width = pw->shadow_width;
218 int direction, ascent, descent;
224 /* Measure the heading_label. */
225 XTextExtents (pw->heading_font,
226 pw->heading_label, strlen(pw->heading_label),
227 &direction, &ascent, &descent, &overall);
228 if (overall.width > pw->width) pw->width = overall.width;
229 pw->height += ascent + descent;
231 /* Measure the body_label. */
232 XTextExtents (pw->body_font,
233 pw->body_label, strlen(pw->body_label),
234 &direction, &ascent, &descent, &overall);
235 if (overall.width > pw->width) pw->width = overall.width;
236 pw->height += ascent + descent;
239 Dimension w2 = 0, w3 = 0;
240 Dimension h2 = 0, h3 = 0;
241 const char *passwd_string = "MMMMMMMMMMMM";
243 /* Measure the user_label. */
244 XTextExtents (pw->label_font,
245 pw->user_label, strlen(pw->user_label),
246 &direction, &ascent, &descent, &overall);
247 if (overall.width > w2) w2 = overall.width;
248 h2 += ascent + descent;
250 /* Measure the passwd_label. */
251 XTextExtents (pw->label_font,
252 pw->passwd_label, strlen(pw->passwd_label),
253 &direction, &ascent, &descent, &overall);
254 if (overall.width > w2) w2 = overall.width;
255 h2 += ascent + descent;
257 /* Measure the user_string. */
258 XTextExtents (pw->passwd_font,
259 pw->user_string, strlen(pw->user_string),
260 &direction, &ascent, &descent, &overall);
261 overall.width += (pw->shadow_width * 4);
262 ascent += (pw->shadow_width * 4);
263 if (overall.width > w3) w3 = overall.width;
264 h3 += ascent + descent;
266 /* Measure the (maximally-sized, dummy) passwd_string. */
267 XTextExtents (pw->passwd_font,
268 passwd_string, strlen(passwd_string),
269 &direction, &ascent, &descent, &overall);
270 overall.width += (pw->shadow_width * 4);
271 ascent += (pw->shadow_width * 4);
272 if (overall.width > w3) w3 = overall.width;
273 h3 += ascent + descent;
275 w2 = w2 + w3 + (pw->shadow_width * 2);
278 if (w2 > pw->width) pw->width = w2;
282 pw->width += (pw->internal_border * 2);
283 pw->height += (pw->internal_border * 4);
285 pw->width += pw->thermo_width + (pw->shadow_width * 3);
287 if (pw->logo_height > pw->height)
288 pw->height = pw->logo_height;
289 else if (pw->height > pw->logo_height)
290 pw->logo_height = pw->height;
292 pw->logo_width = pw->logo_height;
294 pw->width += pw->logo_width;
297 attrmask |= CWOverrideRedirect; attrs.override_redirect = True;
298 attrmask |= CWEventMask; attrs.event_mask = ExposureMask|KeyPressMask;
301 Dimension w = WidthOfScreen(screen);
302 Dimension h = HeightOfScreen(screen);
303 if (si->prefs.debug_p) w /= 2;
304 pw->x = ((w + pw->width) / 2) - pw->width;
305 pw->y = ((h + pw->height) / 2) - pw->height;
306 if (pw->x < 0) pw->x = 0;
307 if (pw->y < 0) pw->y = 0;
310 pw->border_width = get_integer_resource ("passwd.borderWidth",
311 "Dialog.BorderWidth");
314 XCreateWindow (si->dpy,
315 RootWindowOfScreen(screen),
316 pw->x, pw->y, pw->width, pw->height, pw->border_width,
317 DefaultDepthOfScreen (screen), InputOutput,
318 DefaultVisualOfScreen(screen),
320 XSetWindowBackground (si->dpy, si->passwd_dialog, pw->background);
323 /* Before mapping the window, save the bits that are underneath the
324 rectangle the window will occlude. When we lower the window, we
325 restore these bits. This works, because the running screenhack
326 has already been sent SIGSTOP, so we know nothing else is drawing
331 pw->save_under = XCreatePixmap (si->dpy,
332 si->default_screen->screensaver_window,
333 pw->width + (pw->border_width*2) + 1,
334 pw->height + (pw->border_width*2) + 1,
335 si->default_screen->current_depth);
336 gcv.function = GXcopy;
337 gc = XCreateGC (si->dpy, pw->save_under, GCFunction, &gcv);
338 XCopyArea (si->dpy, si->default_screen->screensaver_window,
340 pw->x - pw->border_width, pw->y - pw->border_width,
341 pw->width + (pw->border_width*2) + 1,
342 pw->height + (pw->border_width*2) + 1,
344 XFreeGC (si->dpy, gc);
347 XMapRaised (si->dpy, si->passwd_dialog);
348 XSync (si->dpy, False);
352 draw_passwd_window (si);
353 XSync (si->dpy, False);
358 draw_passwd_window (saver_info *si)
360 passwd_dialog_data *pw = si->pw_data;
364 int x1, x2, x3, y1, y2;
368 height = (pw->heading_font->ascent + pw->heading_font->descent +
369 pw->body_font->ascent + pw->body_font->descent +
370 (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
371 (pw->passwd_font->ascent + pw->passwd_font->descent +
372 (pw->shadow_width * 4)))));
373 spacing = ((pw->height - (2 * pw->shadow_width) -
374 pw->internal_border - height)) / 8;
375 if (spacing < 0) spacing = 0;
377 gcv.foreground = pw->foreground;
378 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
379 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
380 x1 = pw->logo_width + pw->thermo_width + (pw->shadow_width * 3);
381 x3 = pw->width - (pw->shadow_width * 2);
382 y1 = (pw->shadow_width * 2) + spacing + spacing;
386 XSetFont (si->dpy, gc1, pw->heading_font->fid);
387 sw = string_width (pw->heading_font, pw->heading_label);
388 x2 = (x1 + ((x3 - x1 - sw) / 2));
389 y1 += spacing + pw->heading_font->ascent + pw->heading_font->descent;
390 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
391 pw->heading_label, strlen(pw->heading_label));
393 /* text below top heading
395 XSetFont (si->dpy, gc1, pw->body_font->fid);
396 y1 += spacing + pw->body_font->ascent + pw->body_font->descent;
397 sw = string_width (pw->body_font, pw->body_label);
398 x2 = (x1 + ((x3 - x1 - sw) / 2));
399 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
400 pw->body_label, strlen(pw->body_label));
403 tb_height = (pw->passwd_font->ascent + pw->passwd_font->descent +
404 (pw->shadow_width * 4));
406 /* the "User:" prompt
410 XSetForeground (si->dpy, gc1, pw->foreground);
411 XSetFont (si->dpy, gc1, pw->label_font->fid);
412 y1 += (spacing + tb_height);
413 x2 = (x1 + pw->internal_border +
414 MAX(string_width (pw->label_font, pw->user_label),
415 string_width (pw->label_font, pw->passwd_label)));
416 XDrawString (si->dpy, si->passwd_dialog, gc1,
417 x2 - string_width (pw->label_font, pw->user_label),
419 pw->user_label, strlen(pw->user_label));
421 /* the "Password:" prompt
423 y1 += (spacing + tb_height);
424 XDrawString (si->dpy, si->passwd_dialog, gc1,
425 x2 - string_width (pw->label_font, pw->passwd_label),
427 pw->passwd_label, strlen(pw->passwd_label));
430 XSetForeground (si->dpy, gc2, pw->passwd_background);
432 /* the "user name" text field
435 XSetForeground (si->dpy, gc1, pw->passwd_foreground);
436 XSetFont (si->dpy, gc1, pw->passwd_font->fid);
437 y1 += (spacing + tb_height);
438 x2 += (pw->shadow_width * 4);
440 pw->passwd_field_width = x3 - x2 - pw->internal_border;
441 pw->passwd_field_height = (pw->passwd_font->ascent +
442 pw->passwd_font->descent +
445 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
446 x2 - pw->shadow_width,
447 y1 - (pw->passwd_font->ascent + pw->passwd_font->descent),
448 pw->passwd_field_width, pw->passwd_field_height);
449 XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1,
450 pw->user_string, strlen(pw->user_string));
452 /* the "password" text field
454 y1 += (spacing + tb_height);
456 pw->passwd_field_x = x2 - pw->shadow_width;
457 pw->passwd_field_y = y1 - (pw->passwd_font->ascent +
458 pw->passwd_font->descent);
460 /* The shadow around the text fields
463 y1 += (spacing + (pw->shadow_width * 3));
464 x1 = x2 - (pw->shadow_width * 2);
465 x2 = pw->passwd_field_width + (pw->shadow_width * 2);
466 y2 = pw->passwd_field_height + (pw->shadow_width * 2);
468 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
471 pw->shadow_bottom, pw->shadow_top);
473 y1 += (spacing + pw->passwd_font->ascent + pw->passwd_font->descent +
474 (pw->shadow_width * 4));
475 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
478 pw->shadow_bottom, pw->shadow_top);
482 XSetForeground (si->dpy, gc1, pw->logo_foreground);
483 XSetForeground (si->dpy, gc2, pw->logo_background);
485 x1 = pw->shadow_width * 3;
486 y1 = pw->shadow_width * 3;
487 x2 = pw->logo_width - (pw->shadow_width * 6);
488 y2 = pw->logo_height - (pw->shadow_width * 6);
490 XFillRectangle (si->dpy, si->passwd_dialog, gc2, x1, y1, x2, y2);
491 skull (si->dpy, si->passwd_dialog, gc1, gc2,
492 x1 + pw->shadow_width, y1 + pw->shadow_width,
493 x2 - (pw->shadow_width * 2), y2 - (pw->shadow_width * 2));
497 pw->thermo_field_x = pw->logo_width + pw->shadow_width;
498 pw->thermo_field_y = pw->shadow_width * 3;
499 pw->thermo_field_height = pw->height - (pw->shadow_width * 6);
501 /* Solid border inside the logo box. */
502 XSetForeground (si->dpy, gc1, pw->foreground);
503 XDrawRectangle (si->dpy, si->passwd_dialog, gc1, x1, y1, x2-1, y2-1);
505 /* The shadow around the logo
507 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
508 pw->shadow_width * 2,
509 pw->shadow_width * 2,
510 pw->logo_width - (pw->shadow_width * 4),
511 pw->logo_height - (pw->shadow_width * 4),
513 pw->shadow_bottom, pw->shadow_top);
515 /* The shadow around the thermometer
517 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
519 pw->shadow_width * 2,
520 pw->thermo_width + (pw->shadow_width * 2),
521 pw->height - (pw->shadow_width * 4),
523 pw->shadow_bottom, pw->shadow_top);
525 /* Solid border inside the thermometer. */
526 XSetForeground (si->dpy, gc1, pw->foreground);
527 XDrawRectangle (si->dpy, si->passwd_dialog, gc1,
528 pw->logo_width + pw->shadow_width,
529 pw->shadow_width * 3,
530 pw->thermo_width - 1,
531 pw->height - (pw->shadow_width * 6) - 1);
533 /* The shadow around the whole window
535 draw_shaded_rectangle (si->dpy, si->passwd_dialog,
536 0, 0, pw->width, pw->height, pw->shadow_width,
537 pw->shadow_top, pw->shadow_bottom);
539 XFreeGC (si->dpy, gc1);
540 XFreeGC (si->dpy, gc2);
542 update_passwd_window (si, pw->passwd_string, pw->ratio);
547 update_passwd_window (saver_info *si, const char *printed_passwd, float ratio)
549 passwd_dialog_data *pw = si->pw_data;
555 gcv.foreground = pw->passwd_foreground;
556 gcv.font = pw->passwd_font->fid;
557 gc1 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground|GCFont, &gcv);
558 gcv.foreground = pw->passwd_background;
559 gc2 = XCreateGC (si->dpy, si->passwd_dialog, GCForeground, &gcv);
563 char *s = strdup (printed_passwd);
564 if (pw->passwd_string) free (pw->passwd_string);
565 pw->passwd_string = s;
568 /* the "password" text field
570 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
571 pw->passwd_field_x, pw->passwd_field_y,
572 pw->passwd_field_width, pw->passwd_field_height);
573 XDrawString (si->dpy, si->passwd_dialog, gc1,
574 pw->passwd_field_x + pw->shadow_width,
575 pw->passwd_field_y + (pw->passwd_font->ascent +
576 pw->passwd_font->descent),
577 pw->passwd_string, strlen(pw->passwd_string));
583 x = (pw->passwd_field_x + pw->shadow_width +
584 string_width (pw->passwd_font, pw->passwd_string));
585 y = pw->passwd_field_y + pw->shadow_width;
586 XDrawLine (si->dpy, si->passwd_dialog, gc1,
587 x, y, x, y + pw->passwd_font->ascent);
590 pw->i_beam = (pw->i_beam + 1) % 4;
595 y = pw->thermo_field_height * (1.0 - pw->ratio);
598 XFillRectangle (si->dpy, si->passwd_dialog, gc2,
599 pw->thermo_field_x + 1,
600 pw->thermo_field_y + 1,
603 XSetForeground (si->dpy, gc1, pw->logo_foreground);
604 XFillRectangle (si->dpy, si->passwd_dialog, gc1,
605 pw->thermo_field_x + 1,
606 pw->thermo_field_y + 1 + y,
608 MAX (0, pw->thermo_field_height - y - 2));
611 XFreeGC (si->dpy, gc1);
612 XFreeGC (si->dpy, gc2);
613 XSync (si->dpy, False);
618 destroy_passwd_window (saver_info *si)
620 passwd_dialog_data *pw = si->pw_data;
621 Screen *screen = si->default_screen->screen;
622 Colormap cmap = DefaultColormapOfScreen (screen);
623 Pixel black = BlackPixelOfScreen (screen);
624 Pixel white = WhitePixelOfScreen (screen);
627 XtRemoveTimeOut (pw->timer);
629 if (si->passwd_dialog)
631 XDestroyWindow (si->dpy, si->passwd_dialog);
632 si->passwd_dialog = 0;
639 gcv.function = GXcopy;
640 gc = XCreateGC (si->dpy, si->default_screen->screensaver_window,
642 XCopyArea (si->dpy, pw->save_under,
643 si->default_screen->screensaver_window, gc,
645 pw->width + (pw->border_width*2) + 1,
646 pw->height + (pw->border_width*2) + 1,
647 pw->x - pw->border_width, pw->y - pw->border_width);
648 XFreePixmap (si->dpy, pw->save_under);
650 XFreeGC (si->dpy, gc);
653 if (pw->heading_label) free (pw->heading_label);
654 if (pw->body_label) free (pw->body_label);
655 if (pw->user_label) free (pw->user_label);
656 if (pw->passwd_label) free (pw->passwd_label);
658 if (pw->heading_font) XFreeFont (si->dpy, pw->heading_font);
659 if (pw->body_font) XFreeFont (si->dpy, pw->body_font);
660 if (pw->label_font) XFreeFont (si->dpy, pw->label_font);
661 if (pw->passwd_font) XFreeFont (si->dpy, pw->passwd_font);
663 if (pw->foreground != black && pw->foreground != white)
664 XFreeColors (si->dpy, cmap, &pw->foreground, 1, 0L);
665 if (pw->background != black && pw->background != white)
666 XFreeColors (si->dpy, cmap, &pw->background, 1, 0L);
667 if (pw->passwd_foreground != black && pw->passwd_foreground != white)
668 XFreeColors (si->dpy, cmap, &pw->passwd_foreground, 1, 0L);
669 if (pw->passwd_background != black && pw->passwd_background != white)
670 XFreeColors (si->dpy, cmap, &pw->passwd_background, 1, 0L);
671 if (pw->logo_foreground != black && pw->logo_foreground != white)
672 XFreeColors (si->dpy, cmap, &pw->logo_foreground, 1, 0L);
673 if (pw->logo_background != black && pw->logo_background != white)
674 XFreeColors (si->dpy, cmap, &pw->logo_background, 1, 0L);
675 if (pw->shadow_top != black && pw->shadow_top != white)
676 XFreeColors (si->dpy, cmap, &pw->shadow_top, 1, 0L);
677 if (pw->shadow_bottom != black && pw->shadow_bottom != white)
678 XFreeColors (si->dpy, cmap, &pw->shadow_bottom, 1, 0L);
680 memset (pw, 0, sizeof(*pw));
691 passwd_animate_timer (XtPointer closure, XtIntervalId *id)
693 saver_info *si = (saver_info *) closure;
695 passwd_dialog_data *pw = si->pw_data;
699 pw->ratio -= (1.0 / ((double) si->prefs.passwd_timeout / (double) tick));
703 if (pw->state == pw_read)
707 update_passwd_window (si, 0, pw->ratio);
709 if (pw->state == pw_read)
710 pw->timer = XtAppAddTimeOut (si->app, tick, passwd_animate_timer,
715 idle_timer ((XtPointer) si, id);
720 handle_passwd_key (saver_info *si, XKeyEvent *event)
722 saver_preferences *p = &si->prefs;
723 passwd_dialog_data *pw = si->pw_data;
724 int pw_size = sizeof (pw->typed_passwd) - 1;
725 char *typed_passwd = pw->typed_passwd;
729 int size = XLookupString (event, s, 1, 0, 0);
731 if (size != 1) return;
737 case '\010': case '\177': /* Backspace */
741 typed_passwd [strlen(typed_passwd)-1] = 0;
744 case '\025': case '\030': /* Erase line */
745 memset (typed_passwd, 0, pw_size);
748 case '\012': case '\015': /* Enter */
749 if (pw->state != pw_read)
750 ; /* already done? */
751 else if (typed_passwd[0] == 0)
755 update_passwd_window (si, "Checking...", pw->ratio);
756 XSync (si->dpy, False);
757 if (passwd_valid_p (typed_passwd, p->verbose_p))
761 update_passwd_window (si, "", pw->ratio);
766 i = strlen (typed_passwd);
771 typed_passwd [i] = *s;
772 typed_passwd [i+1] = 0;
777 i = strlen(typed_passwd);
778 stars = (char *) malloc(i+1);
779 memset (stars, '*', i);
781 update_passwd_window (si, stars, pw->ratio);
787 passwd_event_loop (saver_info *si)
789 saver_preferences *p = &si->prefs;
792 passwd_animate_timer ((XtPointer) si, 0);
794 while (si->pw_data && si->pw_data->state == pw_read)
796 XtAppNextEvent (si->app, &event);
797 if (event.xany.window == si->passwd_dialog && event.xany.type == Expose)
798 draw_passwd_window (si);
799 else if (event.xany.type == KeyPress)
800 handle_passwd_key (si, &event.xkey);
802 XtDispatchEvent (&event);
805 switch (si->pw_data->state)
807 case pw_ok: msg = 0; break;
808 case pw_null: msg = ""; break;
809 case pw_time: msg = "Timed out!"; break;
810 default: msg = "Sorry!"; break;
813 if (si->pw_data->state == pw_fail)
814 si->unlock_failures++;
817 switch (si->pw_data->state)
820 fprintf (stderr, "%s: password correct.\n", blurb()); break;
822 fprintf (stderr, "%s: password incorrect!\n", blurb()); break;
825 fprintf (stderr, "%s: password entry cancelled.\n", blurb()); break;
827 fprintf (stderr, "%s: password entry timed out.\n", blurb()); break;
832 if (si->pw_data->state == pw_fail)
834 /* If they typed a password (as opposed to just hitting return) and
835 the password was invalid, log it.
837 struct passwd *pw = getpwuid (getuid ());
838 char *d = DisplayString (si->dpy);
839 char *u = (pw->pw_name ? pw->pw_name : "???");
847 # if defined(LOG_AUTHPRIV)
849 # elif defined(LOG_AUTH)
856 openlog (progname, opt, fac);
857 syslog (LOG_NOTICE, "FAILED LOGIN %d ON DISPLAY \"%s\", FOR \"%s\"",
858 si->unlock_failures, d, u);
861 #endif /* HAVE_SYSLOG */
863 if (si->pw_data->state == pw_fail)
864 XBell (si->dpy, False);
866 if (si->pw_data->state == pw_ok && si->unlock_failures != 0)
868 if (si->unlock_failures == 1)
869 fprintf (real_stderr,
870 "%s: WARNING: 1 failed attempt to unlock the screen.\n",
873 fprintf (real_stderr,
874 "%s: WARNING: %d failed attempts to unlock the screen.\n",
875 blurb(), si->unlock_failures);
876 fflush (real_stderr);
878 si->unlock_failures = 0;
883 si->pw_data->i_beam = 0;
884 update_passwd_window (si, msg, 0.0);
885 XSync (si->dpy, False);
888 /* Swallow all pending KeyPress/KeyRelease events. */
891 while (XCheckMaskEvent (si->dpy, KeyPressMask|KeyReleaseMask, &e))
899 unlock_p (saver_info *si)
901 saver_preferences *p = &si->prefs;
902 Screen *screen = si->default_screen->screen;
903 Colormap cmap = DefaultColormapOfScreen (screen);
907 fprintf (stderr, "%s: prompting for password.\n", blurb());
909 if (si->pw_data || si->passwd_dialog)
910 destroy_passwd_window (si);
912 make_passwd_window (si);
913 if (cmap) XInstallColormap (si->dpy, cmap);
915 passwd_event_loop (si);
917 status = (si->pw_data->state == pw_ok);
918 destroy_passwd_window (si);
920 cmap = si->default_screen->cmap;
921 if (cmap) XInstallColormap (si->dpy, cmap);
926 #endif /* !NO_LOCKING -- whole file */