2002-05-09 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Thu, 9 May 2002 05:35:59 +0000 (05:35 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 9 May 2002 05:35:59 +0000 (05:35 +0000)
* configure.ac: Add option --enable-fallback-curses and bind it to
the ncurses check.  Add automake conditional
BUILD_LIBPINENTRY_CURSES and FALLBACK_CURSES. Add preprocessor
symbol FALLBACK_CURSES.

* curses/Makefile.am (AM_CPPFLAGS): Add $(NCURSES_INCLUDE).
(LDADD): Add ../pinentry/libpinentry-curses.a.
* curses/pinentry-curses.c: Include "pinentry-curses.h".
Moved most of the meat to ...
* pinentry/pinentry-curses.c: ... here.  New file.  Make all
functions and global variables static.
(dialog_cmd_handler): Rename to ...
(curses_cmd_handler): ... this.
* pinentry/pinentry-curses.h: New file.
* pinentry/Makefile.am (noinst_LIBRARIES)
[BUILD_LIBPINENTRY_CURSES]: Add libpinentry-curses.a.
(libpinentry_curses_a_SOURCES): New target.

* gtk/Makefile.am (INCLUDES): Moved all to ...
(AM_CPPFLAGS): ... here.
[CURSES_FALLBACK]: Define ncurses_include and libcurses.
(AM_CPPFLAGS): Add $(ncurses_include).
(LDADD): Add $(libcurses).
* gtk/pinentry-gtk.c: Rename TIMEOUT to TIME_OUT to avoid conflict
with curses.h.
[CURSES_FALLBACK]: Include "pinentry-curses.h".
(button_clicked): Likewise.
(create_window): Likewise.
(cmd_handler): Renamed to ...
(gtk_cmd_handler): ... this.
(pinentry_cmd_handler): Set to gtk_cmd_handler.
(main) [CURSES_FALLBACK]: Initialize GTK+ only if environment
variable DISPLAY is set, otherwise fall back to curses dialog.

* pinentry/pinentry.h: Protect against multiple inclusion.

12 files changed:
ChangeLog
NEWS
README
TODO
configure.ac
curses/Makefile.am
curses/pinentry-curses.c
gtk/Makefile.am
gtk/pinentry-gtk.c
pinentry/Makefile.am
pinentry/pinentry.c
pinentry/pinentry.h

index 1dab15f..b1eb31a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2002-05-09  Marcus Brinkmann  <marcus@g10code.de>
+
+       * configure.ac: Add option --enable-fallback-curses and bind it to
+       the ncurses check.  Add automake conditional
+       BUILD_LIBPINENTRY_CURSES and FALLBACK_CURSES. Add preprocessor
+       symbol FALLBACK_CURSES.
+
+       * curses/Makefile.am (AM_CPPFLAGS): Add $(NCURSES_INCLUDE).
+       (LDADD): Add ../pinentry/libpinentry-curses.a.
+       * curses/pinentry-curses.c: Include "pinentry-curses.h".
+       Moved most of the meat to ...
+       * pinentry/pinentry-curses.c: ... here.  New file.  Make all
+       functions and global variables static.
+       (dialog_cmd_handler): Rename to ...
+       (curses_cmd_handler): ... this.
+       * pinentry/pinentry-curses.h: New file.
+       * pinentry/Makefile.am (noinst_LIBRARIES)
+       [BUILD_LIBPINENTRY_CURSES]: Add libpinentry-curses.a.
+       (libpinentry_curses_a_SOURCES): New target.
+
+       * gtk/Makefile.am (INCLUDES): Moved all to ...
+       (AM_CPPFLAGS): ... here.
+       [CURSES_FALLBACK]: Define ncurses_include and libcurses.
+       (AM_CPPFLAGS): Add $(ncurses_include).
+       (LDADD): Add $(libcurses).
+       * gtk/pinentry-gtk.c: Rename TIMEOUT to TIME_OUT to avoid conflict
+       with curses.h.
+       [CURSES_FALLBACK]: Include "pinentry-curses.h".
+       (button_clicked): Likewise.
+       (create_window): Likewise.
+       (cmd_handler): Renamed to ...
+       (gtk_cmd_handler): ... this.
+       (pinentry_cmd_handler): Set to gtk_cmd_handler.
+       (main) [CURSES_FALLBACK]: Initialize GTK+ only if environment
+       variable DISPLAY is set, otherwise fall back to curses dialog.
+
+       * pinentry/pinentry.h: Protect against multiple inclusion.
+
+2002-05-09  Marcus Brinkmann  <marcus@g10code.de>
+
+       * curses/pinentry-curses.c (dialog_create): Allow multi-line error
+       texts.
+
+       * pinentry/pinentry.c (cmd_seterror): Call strcpy_escaped, rather
+       than strcpy, to allow percent-escaping the error text.
+
 2002-04-25  Steffen Hansen  <steffen@hrhansen.dk>
 
        * pinentry-qt: Use ok and cancel value if
diff --git a/NEWS b/NEWS
index c024c1e..de5f296 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+  * Error texts can now be percent-escaped.
+
+  * The Curses pinentry supports multi-line error texts.
+
+  * The GTK+ pinentry can fall back to curses if no display is
+    available.
+
 Noteworthy changes in version 0.6.1 (2002-04-25)
 ------------------------------------------------
 
diff --git a/README b/README
index 125622c..182a8e0 100644 (file)
--- a/README
+++ b/README
@@ -14,6 +14,25 @@ Curses       --enable-pinentry-curses Curses library, for example ncurses
 GTK+   --enable-pinentry-gtk    Gimp Toolkit Library, eg libgtk and libglib
 Qt     --enable-pinentry-qt     Qt, eg libqt-mt
 
+The GTK+ pinentry can fall back to the curses mode.  The option to
+enable this is --enable-fallback-curses, but this is also detected
+automatically in the same way --enable-pinentry-curses is.  The
+fallback to curses also works if --disable-pinentry-curses is
+specified.  So to disable linking to curses completely you have to
+pass --disable-fallback-curses to the configure script as well.
+
+Examples:
+* To only build the GTK+ pinentry with curses support:
+./configure --enable-pinentry-gtk --enable-fallback-curses \
+       --disable-pinentry-curses --disable-pinentry-qt
+
+* To build the Qt pinentry, and the other pinentries if they are
+  supported:
+./configure --enable-pinentry-qt
+
+* To build everything that is supported (complete auto-detection):
+./configure
+
 Some of the code is taken from Robert Bihlmeyer's Quituple-Agent.  For
 security reasons, all internationalization has been removed.  The
 client is expected to tell the PIN entry the text strings to be
diff --git a/TODO b/TODO
index 41c2a21..db0c9e5 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,8 +3,8 @@
   (This is not so important, as pinentry is always restarted.)
 
 * The Qt and curses PIN entry should support enhanced mode (when it is
-  implemented).
+  implemented in gpg-agent).
 
 * The Qt PIN entry needs to use libpinentry (maybe).
 
-* The curses pinentry doesn't grok \n in error message.
+* The Qt PIN entry needs to support fallback to curses.
index 366c69f..c84cc9a 100644 (file)
@@ -75,27 +75,41 @@ dnl
 AC_ARG_ENABLE(pinentry-curses,
             AC_HELP_STRING([--enable-pinentry-curses], [build curses pinentry]),
             pinentry_curses=$enableval, pinentry_curses=maybe)
+AC_ARG_ENABLE(fallback-curses,
+            AC_HELP_STRING([--enable-fallback-curses], [include curses fallback]),
+            fallback_curses=$enableval, fallback_curses=maybe)
 
 dnl
-dnl Checks for curses libraries.  Deal correctly with $pinentry_curses = maybe.
+dnl Checks for curses libraries.  Deal correctly with $pinentry_curses = maybe
+dnl and $fallback_curses = maybe.
 dnl
-if test "$pinentry_curses" != "no"; then
+if test "$pinentry_curses" != "no" -o "$fallback_curses" != "no"; then
   IU_LIB_CURSES
 fi
-if test "$pinentry_curses" != no -a "$LIBCURSES"; then
-  pinentry_curses=yes
+if test "$LIBCURSES"; then
+  if test "$pinentry_curses" != "no"; then
+    pinentry_curses=yes
+  fi
+  if test "$fallback_curses" != "no"; then
+    fallback_curses=yes
+    AC_DEFINE(FALLBACK_CURSES, 1,
+             [The GUI pinentries should fall back to curses if X is not available.])
+  fi
 else
-  if test "$pinentry_curses" = yes; then
+  if test "$pinentry_curses" = "yes" -o "$fallback_curses" = "yes"; then
     AC_MSG_ERROR([[
 *** The curses library is required. The latest version of
 *** ncurses is always available from ftp://ftp.gnu.org/gnu/ncurses/.
 ]])
   fi
   pinentry_curses=no
+  fallback_curses=no
 fi
+AM_CONDITIONAL(BUILD_LIBPINENTRY_CURSES, test "$pinentry_curses" = "yes" -o "$fallback_curses" = "yes")
 AM_CONDITIONAL(BUILD_PINENTRY_CURSES, test "$pinentry_curses" = "yes")
+AM_CONDITIONAL(FALLBACK_CURSES, test "$fallback_curses" = "yes")
 
-if test "$pinentry_curses" = "yes"; then
+if test "$pinentry_curses" = "yes" -o "$fallback_curses" = "yes"; then
 dnl Additional checks for Curses pinentry.
 AM_ICONV
 fi
@@ -213,4 +227,6 @@ AC_MSG_NOTICE([
        Curses Pinentry: $pinentry_curses
        GTK+ Pinentry: $pinentry_gtk
        Qt Pinentry: $pinentry_qt
+
+       Fallback to Curses: $fallback_curses
 ])
index 1d3a6eb..a5772e0 100644 (file)
@@ -21,8 +21,9 @@
 
 bin_PROGRAMS = pinentry-curses
 
-AM_CPPFLAGS = -I$(top_srcdir)/pinentry
-LDADD = ../pinentry/libpinentry.a ../assuan/libassuan.a ../secmem/libsecmem.a \
+AM_CPPFLAGS = $(NCURSES_INCLUDE) -I$(top_srcdir)/pinentry
+LDADD = ../pinentry/libpinentry.a ../pinentry/libpinentry-curses.a \
+       ../assuan/libassuan.a ../secmem/libsecmem.a \
        $(LIBCAP) $(LIBCURSES) $(LIBICONV)
 
 pinentry_curses_SOURCES = pinentry-curses.c
index db3c457..1d65d61 100644 (file)
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
-#include <assert.h>
-#include <curses.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <unistd.h>
+
 #include <stdlib.h>
-#include <locale.h>
-#include <iconv.h>
-#include <langinfo.h>
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
 
 #include "pinentry.h"
+#include "pinentry-curses.h"
 
-#define STRING_OK "<OK>"
-#define STRING_CANCEL "<Cancel>"
-
-int init_screen;
-
-typedef enum
-  {
-    DIALOG_POS_NONE,
-    DIALOG_POS_PIN,
-    DIALOG_POS_OK,
-    DIALOG_POS_CANCEL
-  }
-dialog_pos_t;
-
-struct dialog
-{
-  dialog_pos_t pos;
-  int pin_y;
-  int pin_x;
-  /* Width of the PIN field.  */
-  int pin_size;
-  /* Cursor location in PIN field.  */
-  int pin_loc;
-  char *pin;
-  int pin_max;
-  /* Length of PIN.  */
-  int pin_len;
-
-  int ok_y;
-  int ok_x;
-  char *ok;
-  int cancel_y;
-  int cancel_x;
-  char *cancel;
-};
-typedef struct dialog *dialog_t;
-
-\f
-char *
-convert_utf8_string (char *lc_ctype, char *text)
-{
-  char *old_ctype;
-  char *target_encoding;
-  iconv_t cd;
-  char *input = text;
-  size_t input_len = strlen (text) + 1;
-  char *output;
-  size_t output_len;
-  char *output_buf;
-  size_t processed;
-
-  /* If no locale setting could be determined, simply copy the
-     string.  */
-  if (!lc_ctype)
-    return strdup (text);
-
-  old_ctype = strdup (setlocale (LC_CTYPE, NULL));
-  if (!old_ctype)
-    return NULL;
-  setlocale (LC_CTYPE, lc_ctype);
-  target_encoding = nl_langinfo (CODESET);
-  setlocale (LC_CTYPE, old_ctype);
-  free (old_ctype);
-
-  /* This is overkill, but simplifies the iconv invocation greatly.  */
-  output_len = input_len * MB_LEN_MAX;
-  output_buf = output = malloc (output_len);
-  if (!output)
-    return NULL;
-
-  cd = iconv_open (target_encoding, "UTF-8");
-  if (cd == (iconv_t) -1)
-    {
-      free (output);
-      return NULL;
-    }
-  processed = iconv (cd, &input, &input_len, &output, &output_len);
-  iconv_close (cd);
-  if (processed == (size_t) -1 || input_len)
-    {
-      free (output_buf);
-      return NULL;
-    }
-  return output_buf;
-}
-
-
-static int
-dialog_create (pinentry_t pinentry, dialog_t dialog)
-{
-  int err = 0;
-  int size_y;
-  int size_x;
-  int y;
-  int x;
-  int ypos;
-  int xpos;
-  int description_x = 0;
-  char *description = NULL;
-  char *error = NULL;
-  char *prompt = NULL;
-  char *ok = NULL;
-  char *cancel = NULL;
-
-  if (pinentry->description)
-    {
-      description = convert_utf8_string (pinentry->lc_ctype,
-                                        pinentry->description);
-      if (!description)
-       {
-         err = 1;
-         goto out;
-       }
-    }
-  if (pinentry->error)
-    {
-      error = convert_utf8_string (pinentry->lc_ctype,
-                                  pinentry->error);
-      if (!error)
-       {
-         err = 1;
-         goto out;
-       }
-    }
-  if (pinentry->prompt)
-    {
-      prompt = convert_utf8_string (pinentry->lc_ctype,
-                                   pinentry->prompt);
-      if (!prompt)
-       {
-         err = 1;
-         goto out;
-       }
-    }
-  if (pinentry->ok)
-    {
-      int len = strlen (pinentry->ok);
-      ok = malloc (len + 3);
-      if (!ok)
-       {
-         err = 1;
-         goto out;
-       }
-      ok[0] = '<';
-      memcpy (&ok[1], pinentry->ok, len);
-      ok[len + 1] = '>';
-      ok[len + 2] = '\0';
-    }
-  if (pinentry->cancel)
-    {
-      int len = strlen (pinentry->cancel);
-      cancel = malloc (len + 3);
-      if (!cancel)
-       {
-         err = 1;
-         goto out;
-       }
-      cancel[0] = '<';
-      memcpy (&cancel[1], pinentry->cancel, len);
-      cancel[len + 1] = '>';
-      cancel[len + 2] = '\0';
-    }
-
-  dialog->ok = convert_utf8_string (pinentry->lc_ctype,
-                                   ok ? ok : STRING_OK);
-  dialog->cancel = convert_utf8_string (pinentry->lc_ctype,
-                                       cancel ? cancel : STRING_CANCEL);
-  if (!dialog->ok || !dialog->cancel)
-    {
-      err = 1;
-      goto out;
-    }
-  getmaxyx (stdscr, size_y, size_x);
-
-  /* Check if all required lines fit on the screen.  */
-  y = 1;               /* Top frame.  */
-  if (description)
-    {
-      char *p = description;
-      int desc_x = 0;
-
-      while (*p)
-       {
-         if (*(p++) == '\n')
-           {
-             if (desc_x > description_x)
-               description_x = desc_x;
-             y++;
-             desc_x = 0;
-           }
-         else
-           desc_x++;
-       }
-      if (desc_x > description_x)
-       description_x = desc_x;
-      y += 2;          /* Description.  */
-    }
-      
-  if (pinentry->pin)
-    {
-      if (error)
-       y += 2;         /* Error message.  */
-      y += 2;          /* Pin entry field.  */
-    }
-  y += 2;              /* OK/Cancel and bottom frame.  */
-  
-  if (y > size_y)
-    {
-      err = 1;
-      goto out;
-    }
-
-  /* Check if all required columns fit on the screen.  */
-  x = 0;
-  if (description)
-    {
-      int new_x = description_x;
-      if (new_x > size_x - 4)
-       new_x = size_x - 4;
-      if (new_x > x)
-       x = new_x;
-    }
-  if (pinentry->pin)
-    {
-#define MIN_PINENTRY_LENGTH 40
-      int new_x;
-
-      if (error)
-       {
-         new_x = strlen (error);
-         if (new_x > size_x - 4)
-           new_x = size_x - 4;
-         if (new_x > x)
-           x = new_x;
-       }
-
-      new_x = MIN_PINENTRY_LENGTH;
-      if (prompt)
-       new_x += strlen (prompt) + 1;   /* One space after prompt.  */
-      if (new_x > size_x - 4)
-       new_x = size_x - 4;
-      if (new_x > x)
-       x = new_x;
-    }
-  /* We position the buttons after the first and second third of the
-     width.  Account for rounding.  */
-  if (x < 2 * strlen (dialog->ok))
-    x = 2 * strlen (dialog->ok);
-  if (x < 2 * strlen (dialog->cancel))
-    x = 2 * strlen (dialog->cancel);
-
-  /* Add the frame.  */
-  x += 4;
-
-  if (x > size_x)
-    {
-      err = 1;
-      goto out;
-    }
-
-  dialog->pos = DIALOG_POS_NONE;
-  dialog->pin = pinentry->pin;
-  dialog->pin_max = pinentry->pin_len;
-  dialog->pin_loc = 0;
-  dialog->pin_len = 0;
-  ypos = (size_y - y) / 2;
-  xpos = (size_x - x) / 2;
-  move (ypos, xpos);
-  addch (ACS_ULCORNER);
-  hline (0, x - 2);
-  move (ypos, xpos + x - 1);
-  addch (ACS_URCORNER);
-  move (ypos + 1, xpos + x - 1);
-  vline (0, y - 2);
-  move (ypos + y - 1, xpos);
-  addch (ACS_LLCORNER);
-  hline (0, x - 2);
-  move (ypos + y - 1, xpos + x - 1);
-  addch (ACS_LRCORNER);
-  ypos++;
-  if (description)
-    {
-      char *p = description;
-      int i = 0;
-
-      while (*p)
-       {
-         move (ypos, xpos);
-         addch (ACS_VLINE);
-         addch (' ');
-         while (*p && *p != '\n')
-           if (i < x - 4)
-             {
-               i++;
-               addch ((unsigned char) *(p++));
-             }
-         if (*p == '\n')
-           p++;
-         i = 0;
-         ypos++;
-       }
-      move (ypos, xpos);
-      addch (ACS_VLINE);
-      ypos++;
-    }
-  if (pinentry->pin)
-    {
-      int i;
-
-      if (error)
-       {
-         char *p = error;
-         i = strlen (error);
-         move (ypos, xpos);
-         addch (ACS_VLINE);
-         addch (' ');
-         if (i > x - 4)
-           i = x - 4;
-         if (has_colors () && COLOR_PAIRS >= 1)
-           attron (COLOR_PAIR(1) | A_BOLD);
-         else
-           standout ();
-         while (i-- > 0)
-           addch ((unsigned char) *(p++));
-         if (has_colors () && COLOR_PAIRS >= 1)
-           attroff (COLOR_PAIR(1) | A_BOLD);
-         else
-           standend ();
-         ypos++;
-         move (ypos, xpos);
-         addch (ACS_VLINE);
-         ypos++;
-       }
-
-      move (ypos, xpos);
-      addch (ACS_VLINE);
-      addch (' ');
-
-      dialog->pin_y = ypos;
-      dialog->pin_x = xpos + 2;
-      dialog->pin_size = x - 4;
-      if (prompt)
-       {
-         char *p = prompt;
-         i = strlen (prompt);
-         if (i > x - 4 - MIN_PINENTRY_LENGTH)
-           i = x - 4 - MIN_PINENTRY_LENGTH;
-         dialog->pin_x += i + 1;
-         dialog->pin_size -= i + 1;
-         while (i-- > 0)
-           addch ((unsigned char) *(p++));
-         addch (' ');
-       }
-      for (i = 0; i < dialog->pin_size; i++)
-       addch ('_');
-      ypos++;
-      move (ypos, xpos);
-      addch (ACS_VLINE);
-      ypos++;
-    }
-  move (ypos, xpos);
-  addch (ACS_VLINE);
-  dialog->ok_y = ypos;
-  /* Calculating the left edge of the left button, rounding down.  */
-  dialog->ok_x = xpos + 2 + ((x - 4) / 2 - strlen (dialog->ok)) / 2;
-  move (dialog->ok_y, dialog->ok_x);
-  addstr (dialog->ok);
-  dialog->cancel_y = ypos;
-  /* Calculating the left edge of the right button, rounding up.  */
-  dialog->cancel_x = xpos + x - 2 - ((x - 4) / 2 + strlen (dialog->cancel)) / 2;
-  move (dialog->cancel_y, dialog->cancel_x);
-  addstr (dialog->cancel);
-
- out:
-  if (ok)
-    free (ok);
-  if (cancel)
-    free (cancel);
-  if (description)
-    free (description);
-  if (error)
-    free (error);
-  if (prompt)
-    free (prompt);
-  return err;
-}
-
-\f
-static void
-set_cursor_state (int on)
-{
-  static int normal_state = -1;
-  static int on_last;
-
-  if (normal_state < 0 && !on)
-    {
-      normal_state = curs_set (0);
-      on_last = on;
-    }
-  else if (on != on_last)
-    {
-      curs_set (on ? normal_state : 0);
-      on_last = on;
-    }
-}
-
-int
-dialog_switch_pos (dialog_t diag, dialog_pos_t new_pos)
-{
-  if (new_pos != diag->pos)
-    {
-      switch (diag->pos)
-       {
-       case DIALOG_POS_OK:
-         move (diag->ok_y, diag->ok_x);
-         addstr (diag->ok);
-         break;
-       case DIALOG_POS_CANCEL:
-         move (diag->cancel_y, diag->cancel_x);
-         addstr (diag->cancel);
-         break;
-       default:
-         break;
-       }
-      diag->pos = new_pos;
-      switch (diag->pos)
-       {
-       case DIALOG_POS_PIN:
-         move (diag->pin_y, diag->pin_x + diag->pin_loc);
-         set_cursor_state (1);
-         break;
-       case DIALOG_POS_OK:
-         move (diag->ok_y, diag->ok_x);
-         standout ();
-         addstr (diag->ok);
-         standend ();
-         set_cursor_state (0);
-         break;
-       case DIALOG_POS_CANCEL:
-         move (diag->cancel_y, diag->cancel_x);
-         standout ();
-         addstr (diag->cancel);
-         standend ();
-         set_cursor_state (0);
-         break;
-       case DIALOG_POS_NONE:
-         set_cursor_state (0);
-         break;
-       }
-      refresh ();
-    }
-}
-
-/* XXX Assume that field width is at least > 5.  */
-static void
-dialog_input (dialog_t diag, int chr)
-{
-  int old_loc = diag->pin_loc;
-  assert (diag->pin);
-  assert (diag->pos == DIALOG_POS_PIN);
-
-  switch (chr)
-    {
-    case KEY_BACKSPACE:
-      if (diag->pin_len > 0)
-       {
-         diag->pin_len--;
-         diag->pin_loc--;
-         if (diag->pin_loc == 0 && diag->pin_len > 0)
-           {
-             diag->pin_loc = diag->pin_size - 5;
-             if (diag->pin_loc > diag->pin_len)
-               diag->pin_loc = diag->pin_len;
-           }
-       }
-      break;
-
-    default:
-      if (chr > 0 && chr < 256 && diag->pin_len < diag->pin_max)
-       {
-         diag->pin[diag->pin_len] = (char) chr;
-         diag->pin_len++;
-         diag->pin_loc++;
-         if (diag->pin_loc == diag->pin_size && diag->pin_len < diag->pin_max)
-           {
-             diag->pin_loc = 5;
-             if (diag->pin_loc < diag->pin_size - (diag->pin_max + 1 - diag->pin_len))
-               diag->pin_loc = diag->pin_size - (diag->pin_max + 1 - diag->pin_len);
-           }
-       }
-      break;
-    }
-
-  if (old_loc < diag->pin_loc)
-    {
-      move (diag->pin_y, diag->pin_x + old_loc);
-      while (old_loc++ < diag->pin_loc)
-       addch ('*');
-    }
-  else if (old_loc > diag->pin_loc)
-    {
-      move (diag->pin_y, diag->pin_x + diag->pin_loc);
-      while (old_loc-- > diag->pin_loc)
-       addch ('_');
-    }
-  move (diag->pin_y, diag->pin_x + diag->pin_loc);
-}
-
-static int
-dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
-{
-  struct dialog diag;
-  FILE *ttyfi = 0;
-  FILE *ttyfo = 0;
-  SCREEN *screen = 0;
-  int done = 0;
-
-  /* Open the desired terminal if necessary.  */
-  if (tty_name)
-    {
-      ttyfi = fopen (tty_name, "r");
-      if (ttyfi < 0)
-       return -1;
-      ttyfo = fopen (tty_name, "w");
-      if (ttyfo < 0)
-       {
-         int err = errno;
-         fclose (ttyfi);
-         errno = err;
-         return -1;
-       }
-      screen = newterm (tty_type, ttyfo, ttyfi);
-      set_term (screen);
-    }
-  else
-    {
-      if (!init_screen)
-       {
-         init_screen = 1;
-         initscr ();
-       }
-      else
-       clear ();
-    }
-  
-  keypad (stdscr, TRUE); /* Enable keyboard mapping.  */
-  nonl ();             /* Tell curses not to do NL->CR/NL on output.  */
-  cbreak ();           /* Take input chars one at a time, no wait for \n.  */
-  noecho ();           /* Don't echo input - in color.  */
-  refresh ();
-
-  if (has_colors ())
-    {
-      start_color ();
-
-      if (COLOR_PAIRS >= 1)
-       init_pair (1, COLOR_RED, COLOR_BLACK);
-    }
-
-  /* XXX */
-  if (dialog_create (pinentry, &diag))
-    return -2;
-  dialog_switch_pos (&diag, diag.pin ? DIALOG_POS_PIN : DIALOG_POS_OK);
-
-  do
-    {
-      int c;
-
-      c = getch ();     /* Refresh, accept single keystroke of input.  */
-
-      switch (c)
-       {
-       case KEY_LEFT:
-       case KEY_UP:
-         switch (diag.pos)
-           {
-           case DIALOG_POS_OK:
-             if (diag.pin)
-               dialog_switch_pos (&diag, DIALOG_POS_PIN);
-             break;
-           case DIALOG_POS_CANCEL:
-             dialog_switch_pos (&diag, DIALOG_POS_OK);
-             break;
-           default:
-             break;
-           }
-         break;
-
-       case KEY_RIGHT:
-       case KEY_DOWN:
-         switch (diag.pos)
-           {
-           case DIALOG_POS_PIN:
-             dialog_switch_pos (&diag, DIALOG_POS_OK);
-             break;
-           case DIALOG_POS_OK:
-             dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
-             break;
-           default:
-             break;
-           }
-         break;
-
-       case '\t':
-         switch (diag.pos)
-           {
-           case DIALOG_POS_PIN:
-             dialog_switch_pos (&diag, DIALOG_POS_OK);
-             break;
-           case DIALOG_POS_OK:
-             dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
-             break;
-           case DIALOG_POS_CANCEL:
-             if (diag.pin)
-               dialog_switch_pos (&diag, DIALOG_POS_PIN);
-             else
-               dialog_switch_pos (&diag, DIALOG_POS_OK);
-             break;
-           default:
-             break;
-           }
-         break;
-  
-       case '\e':
-         done = -2;
-         break;
-
-       case '\r':
-         switch (diag.pos)
-           {
-           case DIALOG_POS_PIN:
-           case DIALOG_POS_OK:
-             done = 1;
-             break;
-           case DIALOG_POS_CANCEL:
-             done = -2;
-             break;
-           }
-         break;
-
-       default:
-         if (diag.pos == DIALOG_POS_PIN)
-           dialog_input (&diag, c);
-       }
-    }
-  while (!done);
-
-  set_cursor_state (1);
-  endwin ();
-  if (screen)
-    delscreen (screen);
-
-  if (ttyfi)
-    fclose (ttyfi);
-  if (ttyfo)
-    fclose (ttyfo);
-  /* XXX Factor out into dialog_release or something.  */
-  free (diag.ok);
-  free (diag.cancel);
-  return diag.pin ? (done < 0 ? -1 : diag.pin_len) : (done < 0 ? 0 : 1);
-}
-
-static int
-dialog_cmd_handler (pinentry_t pinentry)
-{
-  return dialog_run (pinentry, pinentry->ttyname, pinentry->ttytype);
-}
-
-pinentry_cmd_handler_t pinentry_cmd_handler = dialog_cmd_handler;
+pinentry_cmd_handler_t pinentry_cmd_handler = curses_cmd_handler;
 
 \f
 int 
index 61a682e..37e17d8 100644 (file)
 
 bin_PROGRAMS = pinentry-gtk
 
-INCLUDES = $(GLIB_CFLAGS) $(GTK_CFLAGS)
+if FALLBACK_CURSES
+ncurses_include = $(NCURSES_INCLUDE)
+libcurses = ../pinentry/libpinentry-curses.a $(LIBCURSES) $(LIBICONV)
+else
+ncurses_include =
+libcurses =
+endif
 
-AM_CPPFLAGS = -I$(top_srcdir)/secmem -I$(top_srcdir)/pinentry
+AM_CPPFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS) $(ncurses_include) \
+       -I$(top_srcdir)/secmem -I$(top_srcdir)/pinentry
 LDADD = ../pinentry/libpinentry.a ../assuan/libassuan.a ../secmem/libsecmem.a \
-       $(LIBCAP) $(GTK_LIBS)
+       $(LIBCAP) $(GTK_LIBS) $(libcurses)
 
 pinentry_gtk_SOURCES = pinentry-gtk.c \
        gtksecentry.c gtksecentry.h
index 1a71bbe..6732b84 100644 (file)
 #include "gtksecentry.h"
 #include "pinentry.h"
 
+#ifdef FALLBACK_CURSES
+#include "pinentry-curses.h"
+#endif
+
 #define PGMNAME "pinentry-gtk"
 
 static pinentry_t pinentry;
 static int passphrase_ok = 0;
 static int confirm_yes = 0;
 
-static GtkWidget *entry, *insure, *timeout;
+static GtkWidget *entry, *insure, *time_out;
 
 /* ok - Return to the command handler routine.  */
 static void 
@@ -133,7 +137,7 @@ button_clicked (GtkWidget *widget, gpointer data)
                  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(insure)) ?
                  "insure"
                  : "",
-                 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(timeout)));
+                 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(time_out)));
         }
 
       s = gtk_secure_entry_get_text (GTK_SECURE_ENTRY(entry));
@@ -263,11 +267,11 @@ create_window (int confirm_mode)
           gtk_box_pack_start(GTK_BOX(sbox), w, FALSE, FALSE, 0);
           gtk_widget_show(w);
           
-          timeout = gtk_spin_button_new
+          time_out = gtk_spin_button_new
             (GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, HUGE_VAL,
                                                1, 60, 60)),2,0);
-          gtk_box_pack_start (GTK_BOX(sbox), timeout, FALSE, FALSE, 0);
-          gtk_widget_show (timeout);
+          gtk_box_pack_start (GTK_BOX(sbox), time_out, FALSE, FALSE, 0);
+          gtk_widget_show (time_out);
        
           w = gtk_label_new ("seconds");
           gtk_box_pack_start (GTK_BOX(sbox), w, FALSE, FALSE, 0); 
@@ -324,7 +328,7 @@ create_window (int confirm_mode)
 
 
 static int
-cmd_handler (pinentry_t pe)
+gtk_cmd_handler (pinentry_t pe)
 {
   GtkWidget *w;
   int want_pass = !!pe->pin;
@@ -350,16 +354,21 @@ cmd_handler (pinentry_t pe)
     return confirm_yes;
 }
 
-pinentry_cmd_handler_t pinentry_cmd_handler = cmd_handler;
+pinentry_cmd_handler_t pinentry_cmd_handler = gtk_cmd_handler;
 
 int 
 main (int argc, char *argv[])
 {
   pinentry_init ();
 
-  /* FIXME: Initialize gtk_init only if DISPLAY is set, if it is not
-     set, a curses based dialog should be used.  */
+#ifdef FALLBACK_CURSES
+  if (getenv ("DISPLAY"))
+    gtk_init (&argc, &argv);
+  else
+    pinentry_cmd_handler = curses_cmd_handler;
+#else
   gtk_init (&argc, &argv);
+#endif
 
   /* Consumes all arguments.  */
   if (pinentry_parse_opts (argc, argv))
index 9155f13..fbb93fd 100644 (file)
 
 ## Process this file with automake to produce Makefile.in
 
-noinst_LIBRARIES = libpinentry.a
+if BUILD_LIBPINENTRY_CURSES
+pinentry_curses = libpinentry-curses.a
+else
+pinentry_curses =
+endif
+
+noinst_LIBRARIES = libpinentry.a $(pinentry_curses)
 
 AM_CPPFLAGS = -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem
 
 libpinentry_a_SOURCES = pinentry.h pinentry.c
+libpinentry_curses_a_SOURCES = pinentry-curses.h pinentry-curses.c
index 399dd3d..06cee5c 100644 (file)
@@ -323,7 +323,7 @@ cmd_seterror (ASSUAN_CONTEXT ctx, char *line)
   if (!newe)
     return ASSUAN_Out_Of_Core;
 
-  strcpy (newe, line);
+  strcpy_escaped (newe, line);
   if (pinentry.error)
     free (pinentry.error);
   pinentry.error = newe;
index a8b37ce..cde8ba7 100644 (file)
@@ -18,6 +18,9 @@
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA  */
 
+#ifndef PINENTRY_H
+#define PINENTRY_H
+
 struct pinentry
 {
   /* The description to display, or NULL.  */
@@ -80,3 +83,5 @@ char *pinentry_setbufferlen (pinentry_t pin, int len);
 \f
 /* The caller must define this variable to process assuan commands.  */
 extern pinentry_cmd_handler_t pinentry_cmd_handler;
+
+#endif /* PINENTRY_H */