ftp://ftp.zenez.com/pub/SCO/Skunk96/UnixWare/FreeBird/x11/utils/xscreensaver-1.18...
[xscreensaver] / driver / lock.c
index 48b2f5260480544723bc54933e49195223138ac8..92137aa821a70ec9077d19dbf29cdb3d5dfb5fee 100644 (file)
@@ -1,11 +1,11 @@
-/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+/*    xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
  *
  * 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.
  */
 
 #include <string.h>
 #endif
 
+#ifdef  HAVE_SHADOW
+#include <shadow.h>
+#endif
+
 #include <pwd.h>
 #include <stdio.h>
 
@@ -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;
 }
+\f
+#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[] = "\
 <Key>BackSpace:                backspace()\n\
 <Key>Delete:           backspace()\n\
@@ -176,8 +210,10 @@ Ctrl<Key>J:                done()\n\
 Ctrl<Key>M:            done()\n\
 <Key>:                 keypress()\n\
 ";
+
 #else
 static char translations[] = "<Key>: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);
 }