The minimal W32 pinnetry may now be used for W32.
authorWerner Koch <wk@gnupg.org>
Wed, 14 Apr 2010 11:28:54 +0000 (11:28 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 14 Apr 2010 11:28:54 +0000 (11:28 +0000)
13 files changed:
ChangeLog
NEWS
assuan/assuan-buffer.c
assuan/assuan-pipe-server.c
autogen.sh
configure.ac
pinentry/pinentry.c
pinentry/pinentry.h
secmem/secmem.c
secmem/util.c
w32/Makefile.am
w32/main.c
w32/pinentry-w32.rc

index 0b0362f..9e62864 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,38 @@
+2010-04-12  Werner Koch  <wk@g10code.com>
+
+       * w32/main.c (dlg_proc): Act on VK_RETURN.
+
+       * w32/pinentry-w32.rc: Include config.h. Add basic support for
+       small screens as used with WindowsCE.
+
+       * w32/Makefile.am (pinentry-w32.o): Add -I.. to the command.
+
+2010-04-08  Werner Koch  <wk@g10code.com>
+
+       * pinentry/pinentry.c [W32CE]: Do not include errno.h and
+       locale.h.
+       (pinentry_have_display) [W32CE]: Do not use getenv.
+       (pinentry_parse_opts) [W32CE]: No error diagnostics due to missing
+       errno.
+       (sleep) [W32CE]: New.
+       (option_handler) [W32CE]: Ignore option --debug-wait.
+       (getpid) [W32CE]: New.
+       (pinentry_loop): Use STDIN_FILENO and STDOUT_FILENO.
+       (pinentry_loop): Factor code out to ...
+       (pinentry_loop2): New.
+       * w32/main.c (w32_strerror) [W32CE]: Do not use FormatMessage.
+       (main) [W32CE]: Do not use LockSetForegroundWindow.
+       (set_dlg_item_text): Use wchar_t for static string.
+       * secmem/util.c [W32CE]: Do not include errno.h.
+       (xwrite) [W32CE]: Shortcut EINTR loop.
+
+2010-04-07  Werner Koch  <wk@g10code.com>
+
+       * autogen.sh: Modernized.
+
 2010-03-03  Werner Koch  <wk@g10code.com>
 
-       Release 0.8.0. 
+       Release 0.8.0.
 
 2010-03-02  Werner Koch  <wk@g10code.com>
 
 2007-11-19  Bernhard Herzog  <bernhard.herzog@intevation.de>  (wk)
 
        * qt/pinentrydialog.cpp (PinEntryDialog): Fixed crash
-       
+
 2007-11-19  Werner Koch  <wk@g10code.com>
 
        * gtk+-2/pinentry-gtk-2.c (create_window): Use again map-event and
 2005-01-27  Werner Koch  <wk@g10code.com>
 
        Released 0.7.2.
-       
+
        * gtk+-2/Makefile.am: Removed padlock-keyhole.xpm.
 
        * configure.ac: Use AC_GNU_SOURCE instead of the custom define.
        (dlg_proc): Set 'result' to -1 to indicate cancel.
        (ok_button_clicked): Adjusted. Set 'result' to the len of
        the PIN to indicate success.
-       
+
 2004-12-22  Werner Koch  <wk@g10code.com>
 
        * w32/main.c: Simplified.
        * w32/dialog.h, w32/dialog.c, w32/controller.h, w32/controller.c:
        Removed
-       
+
        * w32/resource.h, w32/pinentry-w32.rc, w32/main.c, w32/dialog.h
        * w32/dialog.c, w32/controller.h, w32/controller.c
        * w32/Makefile.am: New.  Based on Timo's work.
 
        Update to automake 1.9.
-       
+
        * autogen.sh (configure_ac): Add --build-w32 option.
-       * Makefile.am: Support for the W32 pinentry. 
+       * Makefile.am: Support for the W32 pinentry.
        * configure.ac: Ditto.  Reformatted some error messages.
        Define the usual conditionals for W32.
        Check for a couple of more usually required headers.
        (pinentry_loop) [DOSISH]: Don't do uid check.
 
        * secmem/util.c [DOSISH]: Disable UID stuff.
-       
+
 2004-09-27  Marcus Brinkmann  <marcus@g10code.de>
 
        * acinclude.m4 (IU_LIB_NCURSES, IU_LIB_CURSES, IU_LIB_TERMCAP):
        (SUBDIRS): Add pinentry_gtk_2.
 
        Submitted by Albrecht Dress albrecht.dress@arcor.de.
-       
+
 2004-08-04  Werner Koch  <wk@g10code.de>
 
        * pinentry/pinentry.c (usage): Print help to stdout.
        (pinentry_init): Add arg PGMNAME and store it.  Use it at all
        marked placed instead of the constant "pinentry".
        (usage): Use it here too.
-       * curses/pinentry-curses.c (main): Call pinentry_init with our name. 
+       * curses/pinentry-curses.c (main): Call pinentry_init with our name.
        * qt/main.cpp (main): Ditto.
-       * gtk/pinentry-gtk.c (main): Ditto. 
+       * gtk/pinentry-gtk.c (main): Ditto.
 
        * configure.ac: Check for mmap.
 
        * qt/main.cpp (main): Ditto. Fixed typo.
 
        * gtk/pinentry-gtk.c: Include memory.h.
-       
+
 2003-12-20  Marcus Brinkmann  <marcus@g10code.de>
 
        * pinentry/pinentry.h (struct pinentry): New member PARENT_WID.
        * qt/pinentrydialog.h: Declare SecQString and SecQLineEdit classes.
        (class PinEntryDialog): Disable property text (for now).  Adjust
        argument of setText and return value of text, as well as type of
-       _edit.  
+       _edit.
 
 2003-12-09  Werner Koch  <wk@gnupg.org>
 
 
 2003-02-15  Steffen Hansen  <steffen@klaralvdalens-datakonsult.se>
 
-       * qt/pinentrydialog.h, qt/pinentrydialog.cpp: Added icons 
+       * qt/pinentrydialog.h, qt/pinentrydialog.cpp: Added icons
          for error/non-error messages.
 
 2003-02-07  Marcus Brinkmann  <marcus@g10code.de>
 
 2003-02-04  Steffen Hansen  <steffen@klaralvdalens-datakonsult.se>
 
-       * qt/main.cpp: Work around '--display' option. This fixes 
+       * qt/main.cpp: Work around '--display' option. This fixes
          the pinentry-qt problem reported by several people lately.
 
 2003-01-24  Werner Koch  <wk@gnupg.org>
 
 2002-11-08  Werner Koch  <wk@gnupg.org>
 
-       * pinentry/pinentry-curses.c (convert_utf8_string): Renamed to 
+       * pinentry/pinentry-curses.c (convert_utf8_string): Renamed to
        * pinentry/pinentry.c (pinentry_utf8_to_local): this. Changed
        callers.
        (pinentry_local_to_utf8): New.
        * pinentry/pinentry.c: Include headers for getpid and sleep
        prototypes.
 
-       * secmem/util.h: Correctly declare functions taking no args. 
+       * secmem/util.h: Correctly declare functions taking no args.
 
        * gtk/pinentry-gtk.c: Move gtk headers to the top to avoid
        compiler warnings about shadowing index etc.
 2002-09-30  Werner Koch  <wk@gnupg.org>
 
         Released 0.6.5.
-       
+
        * qt/pinentrycontroller.cpp (optionHandler): Make sure that a
        value is returned.
        * configure.ac: Use -Wall also for C++.
 2002-05-24  Werner Koch  <wk@gnupg.org>
 
        * AUTHORS: Added Marcus
-       * README: Fixed spelling of Quintuple-Agent. 
+       * README: Fixed spelling of Quintuple-Agent.
 
 2002-05-13  Marcus Brinkmann  <marcus@g10code.de>
 
        Released 0.6.2.
-       
+
        * configure.ac: Set version number to 0.6.2.
        * NEWS: Add information for 0.6.2.
        * README: Update for release.
        * configure.ac: Use the new Qt checks instead the KDE checks.
        Replace "kde" with "qt" everywhere.
        * Makefile.am: Replace "kde" with "qt" everywhere.
-       
+
 2002-04-06  Marcus Brinkmann  <marcus@g10code.de>
 
        * acinclude.m4: Reworked the Qt and KDE checks, cutting out a lot
 2002-04-05  Marcus Brinkmann  <marcus@g10code.de>
 
        Released 0.6.0.
-       
+
        * configure.ac: Set version number to 0.6.
        * NEWS: Add information for 0.6.0.
        * secmem/Makefile.am (libsecmem_a_SOURCES): Replace secmem.h with memory.
 2002-01-04  Werner Koch  <wk@gnupg.org>
 
         Released 0.5.0.
-       
+
        * configure.ac: Bumbed version
 
        * util.h (xtoi_1, xtoi_2): New.
 2001-12-07  Werner Koch  <wk@gnupg.org>
 
         New package gpinentry based on quintuple-agent.
-       
+
         Removed all stuff except for the basic configuration stuff and
        what is needed to build gpinentry.  Also removed i18n support.
        * gpinentry.c: Renamed from secret-query.c
        Close stdout (and stderr unless debugging) even when not forking,
        so that normal usage inside eval is still possible.
        (agent): Exit gracefully on HUP, so that logging out now kills the
-       agent. 
+       agent.
 
        * README (Contact Information): Old URL - duh!
        (Using Secret Agent): We no longer fork per default.
 
 1999-11-08  Robert Bihlmeyer  <robbe@orcus.priv.at>
 
-       * agent.h (request_put): Add flags, deadline. Increase REQUEST_MAGIC. 
+       * agent.h (request_put): Add flags, deadline. Increase REQUEST_MAGIC.
        (reply_get): Ditto, and increase REPLY_MAGIC.
        * agent.c (store): Store flags, deadline in reply.
        (do_put): Hand flags, deadline from request on to store().
        (store): Set magic number in stored reply.
        (do_put): Set magic number in reply.
        (do_delete): Ditto.
-       (do_list): Ditto. 
+       (do_list): Ditto.
        (agent): Check magic number in request.
        * agentlib.c: Adapted.
        (send_request): Set magic number in request. Check it in reply.
        (main): Use it.
 
        * Makefile.am (INCLUDES): Put GTK_FLAGS and GLIB_FLAGS here. It
-       is the easiest way for sources needing it, and it won't hurt those 
+       is the easiest way for sources needing it, and it won't hurt those
        that don't.
        (agent.o): Explicit command removed accordingly.
 
        Make --debug switch cumulative.
        (cleanup): Shutdown secmem.
        (do_put): Use secmem for storage of secrets.
-       (do_delete): Use secmem_free(). Since this wipes the memory on its 
+       (do_delete): Use secmem_free(). Since this wipes the memory on its
        own, wipe() is superflous now.
        (agent): Use secmem for inbound requests.
        (delete_secret): New function, takes part of do_delete's
        Include i18n.h.
 
        * agentlib.c: Include i18n.h
-       
+
        * client.c (usage): New function.
        Usage-message made gettext-friendly.
        (xgetpass): Use perror() instead of fprintf().
        Check for socklen_t.
        * acconfig.h: Added a definition for it.
 
-       * client.c: Include packaged getopt.h if the system doesn't provide 
-       one. 
+       * client.c: Include packaged getopt.h if the system doesn't provide
+       one.
        * agent.c: Ditto.
        (create_socket): Replace AF_FILE, PF_FILE with AF_LOCAL, PF_LOCAL
        for portability.
 
        * NEWS: Updated.
 
-       * Makefile.am (agent.o): Mentioning the source explicitly does not 
+       * Makefile.am (agent.o): Mentioning the source explicitly does not
        work for srcdir!=builddir.
 
        * client.c (main): Function arguments are not always evaluated in
        * Makefile.am (client_SOURCES): Added agentlib.c, agentlib.h.
 
        * Makefile.am (INCLUDES): GLIB_CFLAGS moved again, this time to
-       the agent.o target. 
+       the agent.o target.
 
 1999-06-15  Robert Bihlmeyer  <robbe@orcus.priv.at>
 
        (do_list): Use it.
        (do_put): The hash key was overwritten - strdup it.
        Construct a GET reply and save that in the hash.
-       (do_get): Just send the preconstructed reply if the id is present, 
+       (do_get): Just send the preconstructed reply if the id is present,
        and failed_reply otherwise.
        (do_delete): Actually free the hashed stuff.
 
        * Makefile.am (EXTRA_DIST): Added autogen.sh, Thoughts,
        client-test.
        (TESTS): Added client-test.
-       (AUTOMAKE_OPTIONS): Added gnits. 
+       (AUTOMAKE_OPTIONS): Added gnits.
+
 
-       
- Copyright 2002, 2003 g10 Code GmbH
+ Copyright 2002, 2003, 2010 g10 Code GmbH
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
diff --git a/NEWS b/NEWS
index d0c2bfd..e972632 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Noteworthy changes in version 0.8.1 (unreleased)
+------------------------------------------------
+
+ * The W32 pinentry now supports WindowsCE.
+
+
 Noteworthy changes in version 0.8.0 (2010-03-03)
 ------------------------------------------------
 
index df09d3d..363d6cf 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <errno.h>
+#ifndef HAVE_W32CE_SYSTEM
+# include <errno.h>
+#endif
 #include <unistd.h>
 #include <assert.h>
 #ifdef USE_GNU_PTH
 # include <pth.h>
 #endif
+#ifdef HAVE_W32CE_SYSTEM
+# include <windows.h>
+#endif
+
 #include "assuan-defs.h"
 
 #ifdef HAVE_JNLIB_LOGGING
 #include "../jnlib/logging.h"
 #endif
 
+#ifdef HAVE_W32CE_SYSTEM
+const char *
+strerror (int e)
+{
+  return "error";
+}
+static int errno;
+#endif
+
 
 static const char *
 my_log_prefix (void)
@@ -51,16 +66,25 @@ writen ( int fd, const char *buffer, size_t length )
 {
   while (length)
     {
-#ifdef USE_GNU_PTH
-      int nwritten = pth_write (fd, buffer, length);
+      int nwritten;
+#ifdef HAVE_W32CE_SYSTEM
+      do 
+        {
+          if (!WriteFile ((HANDLE)fd, buffer, length, &nwritten, NULL))
+            nwritten = -1;
+        }
+      while (nwritten == -1 && GetLastError () == ERROR_PIPE_NOT_CONNECTED);
+#elif defined(USE_GNU_PTH)
+      nwritten = pth_write (fd, buffer, length);
 #else
-      int nwritten = write (fd, buffer, length);
+      nwritten = write (fd, buffer, length);
 #endif
-      
       if (nwritten < 0)
         {
+#ifndef HAVE_W32CE_SYSTEM
           if (errno == EINTR)
             continue;
+#endif
           return -1; /* write error */
         }
       length -= nwritten;
@@ -79,15 +103,25 @@ readline (int fd, char *buf, size_t buflen, int *r_nread, int *iseof)
   *r_nread = 0;
   while (nleft > 0)
     {
-#ifdef USE_GNU_PTH
-      int n = pth_read (fd, buf, nleft);
+      int n;
+#ifdef HAVE_W32CE_SYSTEM
+      do
+        {
+          if (!ReadFile ((HANDLE)fd, buf, nleft, &n, NULL))
+            n = -1;
+        }
+      while (n == -1 && GetLastError () == ERROR_PIPE_NOT_CONNECTED);
+#elif defined(USE_GNU_PTH)
+      n = pth_read (fd, buf, nleft);
 #else
-      int n = read (fd, buf, nleft);
+      n = read (fd, buf, nleft);
 #endif
       if (n < 0)
         {
+#ifndef HAVE_W32CE_SYSTEM
           if (errno == EINTR)
             continue;
+#endif
           return -1; /* read error */
         }
       else if (!n)
index 5c5d124..07373e1 100644 (file)
@@ -46,7 +46,7 @@ finish_connection (ASSUAN_CONTEXT ctx)
 
 
 /* Create a new context.  Note that the handlers are set up for a pipe
-   server/client - this wau we don't need extra dummy functions */
+   server/client - this way we don't need extra dummy functions */
 int
 _assuan_new_context (ASSUAN_CONTEXT *r_ctx)
 {
index 24f7a54..6ee0515 100755 (executable)
@@ -45,10 +45,48 @@ if test x"$1" = x"--force"; then
   shift
 fi
 
+# Begin list of optional variables sourced from ~/.gnupg-autogen.rc
+w32_toolprefixes=
+w32_extraoptions=
+w32ce_toolprefixes=
+w32ce_extraoptions=
+amd64_toolprefixes=
+# End list of optional variables sourced from ~/.gnupg-autogen.rc
+# What follows are variables which are sourced but default to 
+# environment variables or lacking them hardcoded values.
+#w32root=
+#w32ce_root=
+#amd64root=
+
+if [ -f "$HOME/.gnupg-autogen.rc" ]; then
+    echo "sourcing extra definitions from $HOME/.gnupg-autogen.rc"
+    . "$HOME/.gnupg-autogen.rc"
+fi
+
+# Convenience option to use certain configure options for some hosts.
+myhost="" 
+myhostsub=""
+case "$1" in
+    --build-w32)
+        myhost="w32"
+        ;;
+    --build-w32ce)
+        myhost="w32"
+        myhostsub="ce"
+        ;;
+    --build*)
+        echo "**Error**: invalid build option $1" >&2
+        exit 1
+        ;;
+    *)
+     ;;
+esac
+
+
 
 # ***** W32 build script *******
 # Used to cross-compile for Windows.
-if test "$1" = "--build-w32"; then
+if [ "$myhost" = "w32" ]; then
     tmp=`dirname $0`
     tsdir=`cd "$tmp"; pwd`
     shift
@@ -58,13 +96,26 @@ if test "$1" = "--build-w32"; then
     fi
     build=`$tsdir/config.guess`
 
-    [ -z "$w32root" ] && w32root="$HOME/w32root"
+    case $myhostsub in
+        ce)
+          [ -z "$w32ce_root" ] && w32root="$HOME/w32ce_root"
+          toolprefixes="$w32ce_toolprefixes arm-mingw32ce"
+          extraoptions="$w32ce_extraoptions --disable-pinentry-gtk2"
+          extraoptions="$extraoptions --disable-pinentry-qt4"
+          ;;
+        *)
+          [ -z "$w32root" ] && w32root="$HOME/w32root"
+          toolprefixes="$w32_toolprefixes i586-mingw32msvc"
+          toolprefixes="$toolprefixes i386-mingw32msvc mingw32"
+          extraoptions="$w32_extraoptions --enable-pinentry-gtk2"
+          ;;
+    esac
     echo "Using $w32root as standard install directory" >&2
     
 
     # Locate the cross compiler
     crossbindir=
-    for host in i586-mingw32msvc i386-mingw32msvc mingw32; do
+    for host in $toolprefixes; do
         if ${host}-gcc --version >/dev/null 2>&1 ; then
             crossbindir=/usr/${host}/bin
             conf_CC="CC=${host}-gcc"
@@ -73,8 +124,10 @@ if test "$1" = "--build-w32"; then
     done
     if [ -z "$crossbindir" ]; then
         echo "Cross compiler kit not installed" >&2
-        echo "Under Debian GNU/Linux, you may install it using" >&2
-        echo "  apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2 
+        if [ -z "$sub" ]; then 
+          echo "Under Debian GNU/Linux, you may install it using" >&2
+          echo "  apt-get install mingw32 mingw32-runtime mingw32-binutils" >&2 
+        fi
         echo "Stop." >&2
         exit 1
     fi
@@ -89,11 +142,10 @@ if test "$1" = "--build-w32"; then
     ./configure --enable-maintainer-mode --prefix=${w32root} \
                 --host=${host} --build=${build} \
                 --disable-pinentry-gtk \
-                --enable-pinentry-gtk2 \
                 --disable-pinentry-qt  \
-                --with-lib-prefix=${w32root} \
                 --with-libiconv-prefix=${w32root} \
-                PKG_CONFIG_LIBDIR="$w32root/lib/pkgconfig" "$@"
+                PKG_CONFIG_LIBDIR="$w32root/lib/pkgconfig" \
+                ${extraoptions} "$@"
 
     rc=$?
     exit $rc
@@ -158,4 +210,6 @@ $AUTOMAKE --gnu
 echo "Running autoconf${FORCE}..."
 $AUTOCONF${FORCE}
 
-echo "You may now run \"./configure --enable-maintainer-mode && make\"."
+echo "You may now run:
+  ./configure --enable-maintainer-mode && make
+"
index 04f10ae..5bfcc34 100644 (file)
@@ -31,8 +31,8 @@ min_automake_version="1.7.6"
 # specific feature can already be done under the assumption that the
 # SVN version is the most recent one in a branch.  To disable the SVN
 # version for the real release, set the my_issvn macro to no.
-m4_define(my_version, [0.8.0])
-m4_define(my_issvn, [no])
+m4_define(my_version, [0.8.1])
+m4_define(my_issvn, [yes])
 
 m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \
            | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)]))
@@ -71,14 +71,22 @@ AC_CHECK_TOOL(WINDRES, windres, :)
 
 have_dosish_system=no
 have_w32_system=no
+have_w32ce_system=no
 case "${host}" in
     *-mingw32*)
         AC_DEFINE(USE_ONLY_8DOT3,1,
-                  [set this to limit filenames to the 8.3 format])
-        AC_DEFINE(HAVE_DRIVE_LETTERS,1,
-                  [defined if we must run on a stupid file system])
+                  [Set this to limit filenames to the 8.3 format])
         have_dosish_system=yes
         have_w32_system=yes
+        case "${host}" in 
+          *-mingw32ce*)
+            have_w32ce_system=yes
+            ;;
+          *)
+            AC_DEFINE(HAVE_DRIVE_LETTERS,1,
+                      [Defined if the OS supports drive letters.])
+            ;;
+        esac
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         # OS/2 with the EMX environment
@@ -103,8 +111,12 @@ AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes)
 
 if test "$have_w32_system" = yes; then
    AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system])
+   if test "$have_w32ce_system" = yes; then
+      AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE])
+   fi
 fi
 AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
+AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
 
 
 
index af5bd20..a66f4be 100644 (file)
 #include <config.h>
 #endif
 
-#include <errno.h>
+#ifndef HAVE_W32CE_SYSTEM
+# include <errno.h>
+#endif
 #include <stdlib.h>
 #include <string.h>
 #include <getopt.h>
 #include <unistd.h>
-#include <locale.h>
+#ifndef HAVE_W32CE_SYSTEM
+# include <locale.h>
+#endif
 #ifdef HAVE_LANGINFO_H
 #include <langinfo.h>
 #endif
 #include <limits.h>
+#ifdef HAVE_W32CE_SYSTEM
+# include <windows.h>
+#endif
 
 #if defined FALLBACK_CURSES || defined PINENTRY_CURSES || defined PINENTRY_GTK
 #include <iconv.h>
@@ -41,6 +48,9 @@
 #include "secmem-util.h"
 #include "pinentry.h"
 
+#ifdef HAVE_W32CE_SYSTEM
+#define getpid() GetCurrentProcessId ()
+#endif
 
 /* Keep the name of our program here. */
 static char this_pgmname[50]; 
@@ -87,7 +97,6 @@ struct pinentry pinentry =
   };
 
 \f
-
 #if defined FALLBACK_CURSES || defined PINENTRY_CURSES || defined PINENTRY_GTK
 char *
 pinentry_utf8_to_local (char *lc_ctype, char *text)
@@ -377,11 +386,13 @@ pinentry_init (const char *pgmname)
 int
 pinentry_have_display (int argc, char **argv)
 {
+#ifndef HAVE_W32CE_SYSTEM
   const char *s;
 
   s = getenv ("DISPLAY");
   if (s && *s)
     return 1;
+#endif
   for (; argc; argc--, argv++)
     if (!strcmp (*argv, "--display"))
       return 1;
@@ -516,7 +527,9 @@ pinentry_parse_opts (int argc, char *argv[])
          pinentry.display = strdup (optarg);
          if (!pinentry.display)
            {
+#ifndef HAVE_W32CE_SYSTEM
              fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
              exit (EXIT_FAILURE);
            }
          break; 
@@ -524,7 +537,9 @@ pinentry_parse_opts (int argc, char *argv[])
          pinentry.ttyname = strdup (optarg);
          if (!pinentry.ttyname)
            {
+#ifndef HAVE_W32CE_SYSTEM
              fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
              exit (EXIT_FAILURE);
            }
          break;
@@ -532,7 +547,9 @@ pinentry_parse_opts (int argc, char *argv[])
          pinentry.ttytype = strdup (optarg);
          if (!pinentry.ttytype)
            {
+#ifndef HAVE_W32CE_SYSTEM
              fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
              exit (EXIT_FAILURE);
            }
          break;
@@ -540,7 +557,9 @@ pinentry_parse_opts (int argc, char *argv[])
          pinentry.lc_ctype = strdup (optarg);
          if (!pinentry.lc_ctype)
            {
+#ifndef HAVE_W32CE_SYSTEM
              fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
              exit (EXIT_FAILURE);
            }
          break;
@@ -548,7 +567,9 @@ pinentry_parse_opts (int argc, char *argv[])
          pinentry.lc_messages = strdup (optarg);
          if (!pinentry.lc_messages)
            {
+#ifndef HAVE_W32CE_SYSTEM
              fprintf (stderr, "%s: %s\n", this_pgmname, strerror (errno));
+#endif
              exit (EXIT_FAILURE);
            }
          break;
@@ -590,10 +611,12 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
     pinentry.grab = 1;
   else if (!strcmp (key, "debug-wait"))
     {
+#ifndef HAVE_W32CE_SYSTEM
       fprintf (stderr, "%s: waiting for debugger - my pid is %u ...\n",
               this_pgmname, (unsigned int) getpid());
       sleep (*value?atoi (value):5);
       fprintf (stderr, "%s: ... okay\n", this_pgmname);
+#endif
     }
   else if (!strcmp (key, "display"))
     {
@@ -908,7 +931,7 @@ cmd_getpin (ASSUAN_CONTEXT ctx, char *line)
 }
 
 
-/* Note that the option --one-button is hack to allow the use of old
+/* Note that the option --one-button is hack to allow the use of old
    pinentries while the caller is ignoring the result.  Given that
    options have never been used or flagged as an error the new option
    is an easy way to enable the messsage mode while not requiring to
@@ -1033,11 +1056,8 @@ register_commands (ASSUAN_CONTEXT ctx)
 }
 
 
-/* Start the pinentry event loop.  The program will start to process
-   Assuan commands until it is finished or an error occurs.  If an
-   error occurs, -1 is returned.  Otherwise, 0 is returned.  */
 int
-pinentry_loop (void)
+pinentry_loop2 (int infd, int outfd)
 {
   int rc;
   int filedes[2];
@@ -1052,8 +1072,8 @@ pinentry_loop (void)
   /* For now we use a simple pipe based server so that we can work
      from scripts.  We will later add options to run as a daemon and
      wait for requests on a Unix domain socket.  */
-  filedes[0] = 0;
-  filedes[1] = 1;
+  filedes[0] = infd;
+  filedes[1] = outfd;
   rc = assuan_init_pipe_server (&ctx, filedes);
   if (rc)
     {
@@ -1098,3 +1118,13 @@ pinentry_loop (void)
   assuan_deinit_server (ctx);
   return 0;
 }
+
+
+/* Start the pinentry event loop.  The program will start to process
+   Assuan commands until it is finished or an error occurs.  If an
+   error occurs, -1 is returned.  Otherwise, 0 is returned.  */
+int
+pinentry_loop (void)
+{
+  return pinentry_loop2 (STDIN_FILENO, STDOUT_FILENO);
+}
index 95d134f..b34d796 100644 (file)
@@ -147,6 +147,9 @@ typedef int (*pinentry_cmd_handler_t) (pinentry_t pin);
    error.  Otherwise, 0 is returned.  */
 int pinentry_loop (void);
 
+/* The same as above but allows to specify the i/o descriptors. */
+int pinentry_loop2 (int infd, int outfd);
+
 
 /* Convert the UTF-8 encoded string TEXT to the encoding given in
    LC_CTYPE.  Return NULL on error. */
index f28afb0..fed7e97 100644 (file)
@@ -21,7 +21,9 @@
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
+#ifndef HAVE_W32CE_SYSTEM
 #include <errno.h>
+#endif
 #include <stdarg.h>
 #include <unistd.h>
 #if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
index c8267c2..68cde3c 100644 (file)
@@ -19,7 +19,9 @@
 #define _GNU_SOURCE 1
 
 #include <unistd.h>
-#include <errno.h>
+#ifdef HAVE_W32CE_SYSTEM
+# include <errno.h>
+#endif
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -50,7 +52,13 @@ xwrite(int fd, const void *data, size_t bytes)
     {
       do
         written = write (fd, ptr, todo);
-      while (written == -1 && errno == EINTR);
+      while (
+#ifdef HAVE_W32CE_SYSTEM
+             0
+#else
+             written == -1 && errno == EINTR
+#endif
+             );
       if (written < 0)
         break;
     }
index f541658..b2e2f8f 100644 (file)
@@ -36,5 +36,5 @@ pinentry_w32_LDADD = pinentry-w32.o \
 
 
 pinentry-w32.o: pinentry-w32.rc resource.h
-       $(WINDRES) -v -o $@ $< 
+       $(WINDRES) -I.. -v -o $@ $< 
 
index d13f217..6bd0bfb 100644 (file)
 #include <stdlib.h>
 #define WINVER 0x0403  /* Required for SendInput.  */
 #include <windows.h>
+#ifdef HAVE_W32CE_SYSTEM
+# include <winioctl.h>
+# include <sipapi.h>
+#endif
 
 #include "pinentry.h"
 #include "memory.h"
@@ -37,8 +41,9 @@
 
 
 /* This function pointer gets initialized in main.  */
+#ifndef HAVE_W32CE_SYSTEM
 static WINUSERAPI BOOL WINAPI (*lock_set_foreground_window)(UINT);
-
+#endif
 
 static int w32_cmd_handler (pinentry_t pe);
 static void ok_button_clicked (HWND dlg, pinentry_t pe);
@@ -51,10 +56,12 @@ static int confirm_mode;
 static int passphrase_ok;
 static int confirm_yes;
 
-static FILE *debugfp;
+/* The file descriptors for the loop.  */
+static int w32_infd;
+static int w32_outfd;
 
 
-/* Connect this module to the pinnetry framework.  */
+/* Connect this module to the pinentry framework.  */
 pinentry_cmd_handler_t pinentry_cmd_handler = w32_cmd_handler;
 
 
@@ -66,13 +73,51 @@ w32_strerror (int ec)
   
   if (ec == -1)
     ec = (int)GetLastError ();
+#ifdef HAVE_W32CE_SYSTEM
+  /* There is only a wchar_t FormatMessage.  It does not make much
+     sense to play the conversion game; we print only the code.  */
+  snprintf (strerr, sizeof strerr, "ec=%d", ec);
+#else
   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
                  strerr, sizeof strerr - 1, NULL);
+#endif
   return strerr;    
 }
 
 
+
+#ifdef HAVE_W32CE_SYSTEM
+/* Create a pipe.  WRITE_END shall have the opposite value of the one
+   pssed to _assuan_w32ce_prepare_pipe; see there for more
+   details.  */
+#define GPGCEDEV_IOCTL_MAKE_PIPE                                        \
+  CTL_CODE (FILE_DEVICE_STREAMS, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS)
+static HANDLE
+w32ce_finish_pipe (int rvid, int write_end)
+{
+  HANDLE hd;
+
+  hd = CreateFile (L"GPG1:", write_end? GENERIC_WRITE : GENERIC_READ,
+                   FILE_SHARE_READ | FILE_SHARE_WRITE,
+                   NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
+  if (hd != INVALID_HANDLE_VALUE)
+    {
+      if (!DeviceIoControl (hd, GPGCEDEV_IOCTL_MAKE_PIPE,
+                            &rvid, sizeof rvid, NULL, 0, NULL, NULL))
+        {
+          DWORD lastrc = GetLastError ();
+          CloseHandle (hd);
+          hd = INVALID_HANDLE_VALUE;
+          SetLastError (lastrc);
+        }
+    }
+
+  return hd;
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
 /* static HWND */
 /* show_window_hierarchy (HWND parent, int level) */
 /* { */
@@ -161,11 +206,32 @@ utf8_to_wchar (const char *string)
 }
 
 
+/* Raie the software input panel.  */
+#ifdef HAVE_W32CE_SYSTEM
+static void
+raise_sip (HWND dlg)
+{
+  SIPINFO si;
+
+  SetForegroundWindow (dlg);
+
+  memset (&si, 0, sizeof si);
+  si.cbSize = sizeof si;
+
+  if (SipGetInfo (&si)) 
+    {
+      si.fdwFlags |= SIPF_ON;
+      SipSetInfo (&si);
+    }
+}
+#endif
+
 /* Center the window CHILDWND with the desktop as its parent
    window.  STYLE is passed as second arg to SetWindowPos.*/
 static void
 center_window (HWND childwnd, HWND style) 
 {     
+#ifndef HAVE_W32CE_SYSTEM
   HWND parwnd;
   RECT rchild, rparent;    
   HDC hdc;
@@ -199,6 +265,7 @@ center_window (HWND childwnd, HWND style)
   if (style == HWND_TOPMOST || style == HWND_NOTOPMOST)
     flags = SWP_NOMOVE | SWP_NOSIZE;
   SetWindowPos (childwnd, style? style : NULL, xnew, ynew, 0, 0, flags);
+#endif
 }
 
 
@@ -206,6 +273,7 @@ center_window (HWND childwnd, HWND style)
 static void
 move_mouse_and_click (HWND hwnd)
 {
+#ifndef HAVE_W32CE_SYSTEM
   RECT rect;
   HDC hdc;
   int wscreen, hscreen, x, y, normx, normy;
@@ -250,6 +318,7 @@ move_mouse_and_click (HWND hwnd)
 
   if ( SendInput (idx, inp, sizeof (INPUT)) != idx && debugfp )
     fprintf (debugfp, "SendInput failed: %s\n", w32_strerror (-1));
+#endif
 }
 
 
@@ -278,14 +347,14 @@ static void
 set_dlg_item_text (HWND dlg, int item, const char *string)
 {
   if (!string || !*string)
-    SetDlgItemText (dlg, item, "");
+    SetDlgItemTextW (dlg, item, L"");
   else
     {
       wchar_t *wbuf;
       
       wbuf = utf8_to_wchar (string);
       if (!wbuf)
-        SetDlgItemText (dlg, item, "[out of core]");
+        SetDlgItemTextW (dlg, item, L"[out of core]");
       else
         {
           SetDlgItemTextW (dlg, item, wbuf);
@@ -364,7 +433,7 @@ dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
 
       ShowWindow (dlg, SW_SHOW);
       move_mouse_and_click ( GetDlgItem (dlg, IDC_PINENT_PROMPT) );
-
+      raise_sip (dlg);
       break;
 
     case WM_COMMAND:
@@ -384,6 +453,18 @@ dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
          break;
        }
       break;
+
+     case WM_KEYDOWN: 
+       if (wparam == VK_RETURN)
+         {
+           if (confirm_mode)
+             confirm_yes = 1;
+           else
+             ok_button_clicked (dlg, pe);
+           EndDialog (dlg, TRUE);
+         }
+       break;
+
     }
   return FALSE;
 }
@@ -451,19 +532,99 @@ w32_cmd_handler (pinentry_t pe)
 }
 
 
+/* WindowsCE uses a very strange way of handling the standard streams.
+   There is a function SetStdioPath to associate a standard stream
+   with a file or a device but what we really want is to use pipes as
+   standard streams.  Despite that we implement pipes using a device,
+   we would have some limitations on the number of open pipes due to
+   the 3 character limit of device file name.  Thus we don't take this
+   path.  Another option would be to install a file system driver with
+   support for pipes; this would allow us to get rid of the device
+   name length limitation.  However, with GnuPG we can get away be
+   redefining the standard streams and passing the handles to be used
+   on the command line.  This has also the advantage that it makes
+   creating a process much easier and does not require the
+   SetStdioPath set and restore game.  The caller needs to pass the
+   rendezvous ids using up to three options:
+
+     -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
+
+   They are all optional but they must be the first arguments on the
+   command line.  Parsing stops as soon as an invalid option is found.
+   These rendezvous ids are then used to finish the pipe creation.*/
+#ifdef HAVE_W32CE_SYSTEM
+static void
+parse_std_file_handles (int *argcp, char ***argvp)
+{
+  int argc = *argcp;
+  char **argv = *argvp;
+  const char *s;
+  int fd;
+  int i;
+  int fixup = 0;
+
+  if (!argc)
+    return;
+
+  for (argc--, argv++; argc; argc--, argv++)
+    {
+      s = *argv;
+      if (*s == '-' && s[1] == '&' && s[2] == 'S'
+          && (s[3] == '0' || s[3] == '1' || s[3] == '2')
+          && s[4] == '=' 
+          && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
+        {
+          if (s[5] == 'n')
+            fd = (int)(-1);
+          else
+            fd = (int)w32ce_finish_pipe (atoi (s+5), s[3] != '0');
+          if (s[3] == '0' && fd != -1)
+            w32_infd = fd;
+          else if (s[3] == '1' && fd != -1)
+            w32_outfd = fd;
+          fixup++;
+        }
+      else
+        break;
+    }
+
+  if (fixup)
+    {
+      argc = *argcp;
+      argc -= fixup;
+      *argcp = argc;
+
+      argv = *argvp;
+      for (i=1; i < argc; i++)
+        argv[i] = argv[i + fixup];
+      for (; i < argc + fixup; i++)
+        argv[i] = NULL;
+    }
+
+
+}
+#endif /*HAVE_W32CE_SYSTEM*/
+
+
 int
 main (int argc, char **argv)
 {
+#ifndef HAVE_W32CE_SYSTEM
   void *handle;
+#endif
+
+  w32_infd = STDIN_FILENO;
+  w32_outfd = STDOUT_FILENO;
+
+#ifdef HAVE_W32CE_SYSTEM
+  parse_std_file_handles (&argc, &argv);
+#endif
 
   pinentry_init (PGMNAME);
 
   /* Consumes all arguments.  */
   if (pinentry_parse_opts (argc, argv))
-    {
-      printf ("pinentry-w32 (pinentry) " VERSION "\n");
-      exit (EXIT_SUCCESS);
-    }
+    exit (EXIT_SUCCESS);
 
 /*   debugfp = fopen ("pinentry.log", "w"); */
 /*   if (!debugfp) */
@@ -471,6 +632,7 @@ main (int argc, char **argv)
 
   /* We need to load a function because that one is only available
      since W2000 but not in older NTs.  */
+#ifndef HAVE_W32CE_SYSTEM
   handle = LoadLibrary ("user32.dll");
   if (handle)
     {
@@ -481,9 +643,13 @@ main (int argc, char **argv)
       else
         CloseHandle (handle);
     }
+#endif
 
-  if (pinentry_loop ())
+  if (pinentry_loop2 (w32_infd, w32_outfd))
     return 1;
 
+#ifdef HAVE_W32CE_SYSTEM
+  Sleep (400);
+#endif
   return 0;
 }
index c8a9960..a4816bc 100755 (executable)
@@ -1,5 +1,5 @@
-/* dialog.rc - Resource definitions
-   Copyright (C) 2004 g10 Code GmbH
+/* dialog.rc - Resource definitions                             -*- c -*-
+   Copyright (C) 2004, 2010 g10 Code GmbH
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -16,7 +16,7 @@
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA  */
 
-
+#include <config.h>
 #include <winuser.h>
 #include "resource.h"
 
  * Main dialog 
  */
 
+#ifdef HAVE_W32CE_SYSTEM
+
+IDD_PINENT DIALOG DISCARDABLE  0, 0, 150, 100
+STYLE DS_MODALFRAME | DS_SYSMODAL | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Pinentry"
+FONT 8, "MS Shell Dlg"
+BEGIN
+    LTEXT           "", IDC_PINENT_DESC, 2, 2, 140, 24
+    LTEXT           "", IDC_PINENT_ERR, 2, 30, 140, 12
+
+    LTEXT           "", IDC_PINENT_PROMPT, 2, 56, 20, 12
+    EDITTEXT        IDC_PINENT_TEXT, 30, 56, 100, 12, ES_PASSWORD | ES_AUTOHSCROLL
+
+    DEFPUSHBUTTON   "O&K", IDOK, 2, 70, 50, 14
+    PUSHBUTTON      "&Cancel", IDCANCEL, 60, 70, 50, 14
+
+END
+
+#else /* Standard Windows.  */
+
 IDD_PINENT DIALOG DISCARDABLE  0, 0, 186, 125
 STYLE DS_MODALFRAME | DS_SYSMODAL | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Pinentry"
@@ -37,5 +57,6 @@ BEGIN
     LTEXT           "", IDC_PINENT_ERR, 6, 82, 170, 9
 END
 
+#endif /* Standard Windows.  */