Made percent_escape more general.
authorWerner Koch <wk@gnupg.org>
Tue, 19 Jun 2007 09:11:11 +0000 (09:11 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 19 Jun 2007 09:11:11 +0000 (09:11 +0000)
Added regression tests support to jnlib.
W32 changes.

18 files changed:
AUTHORS
agent/ChangeLog
agent/gpg-agent.c
agent/w32main.c
doc/gpg-agent.texi
g10/gpg.c
jnlib/ChangeLog
jnlib/Makefile.am
jnlib/stringhelp.c
jnlib/stringhelp.h
jnlib/t-stringhelp.c [new file with mode: 0644]
jnlib/t-support.c [new file with mode: 0644]
jnlib/t-support.h [new file with mode: 0644]
jnlib/w32-afunix.c
scd/scdaemon.c
sm/gpgsm.c
tools/ChangeLog
tools/gpgconf-comp.c

diff --git a/AUTHORS b/AUTHORS
index 799a2ae..548bc8a 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -128,6 +128,9 @@ GnuPG.
 The RPM specs file scripts/gnupg.spec has been contributed by
 several people.
 
+The function build_argv in agent/w32main.c is based on code from
+Alexandre Julliard.
+
 
 Copyright
 =========
index e23cd99..1956455 100644 (file)
@@ -5,10 +5,14 @@
 
 2007-06-18  Werner Koch  <wk@g10code.com>
 
+       * w32main.c (build_argv): New.
+       (WinMain): Use it.
+
        * command.c (cmd_killagent) [W32]: New.
        (cmd_getinfo): New.
        * gpg-agent.c (get_agent_ssh_socket_name): New.
-
+       (no_force_standard_socket) New.
+       (create_server_socket): Use it.
        * Makefile.am (gpg_agent_res_ldflags): Pass windows option to ld.
 
 2007-06-14  Werner Koch  <wk@g10code.com>
index 419f376..8907e92 100644 (file)
@@ -93,6 +93,7 @@ enum cmd_and_opt_values
   oMinPassphraseLen,
   oUseStandardSocket,
   oNoUseStandardSocket,
+  oNoReuseStandardSocket,
 
   oIgnoreCacheForSigning,
   oAllowMarkTrusted,
@@ -130,6 +131,7 @@ static ARGPARSE_OPTS opts[] = {
   { oUseStandardSocket, "use-standard-socket", 0,
                       N_("use a standard location for the socket")},
   { oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
+  { oNoReuseStandardSocket, "no-reuse-standard-socket", 0, "@"},
 
   { oPinentryProgram, "pinentry-program", 2 ,
                                N_("|PGM|use PGM as the PIN-Entry program") },
@@ -186,6 +188,10 @@ static char *socket_name;
 /* Name of the communication socket used for ssh-agent-emulation.  */
 static char *socket_name_ssh;
 
+/* If set to true and a standard socket is requested, we won't try to
+   bind to a socket which is already in use.  */
+static int no_reuse_standard_socket;
+
 /* Default values for options passed to the pinentry. */
 static char *default_display;
 static char *default_ttyname;
@@ -215,7 +221,7 @@ static pid_t parent_pid = (pid_t)(-1);
 
 static char *create_socket_name (int use_standard_socket,
                                  char *standard_name, char *template);
-static int create_server_socket (int is_standard_name, const char *name);
+static int create_server_socket (int is_standard_name, char *name);
 static void create_directories (void);
 
 static void agent_init_default_ctrl (ctrl_t ctrl);
@@ -621,6 +627,7 @@ main (int argc, char **argv )
 
         case oUseStandardSocket: standard_socket = 1; break;
         case oNoUseStandardSocket: standard_socket = 0; break;
+        case oNoReuseStandardSocket: no_reuse_standard_socket = 1; break;
 
         case oKeepTTY: opt.keep_tty = 1; break;
         case oKeepDISPLAY: opt.keep_display = 1; break;
@@ -715,7 +722,7 @@ main (int argc, char **argv )
 #define GC_OPT_FLAG_NO_ARG_DESC        (1UL << 6)
 
       filename = make_filename (opt.homedir, "gpg-agent.conf", NULL );
-      filename_esc = percent_escape (filename);
+      filename_esc = percent_escape (filename, NULL);
 
       printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n",
               GC_OPT_FLAG_DEFAULT, filename_esc);
@@ -1226,10 +1233,10 @@ create_socket_name (int use_standard_socket,
 
 
 /* Create a Unix domain socket with NAME.  IS_STANDARD_NAME indicates
-   whether a non-random socket is used.  Returns the filedescriptor or
+   whether a non-random socket is used.  Returns the file descriptor or
    terminates the process in case of an error. */
 static int
-create_server_socket (int is_standard_name, const char *name)
+create_server_socket (int is_standard_name, char *name)
 {
   struct sockaddr_un *serv_addr;
   socklen_t len;
@@ -1257,14 +1264,16 @@ create_server_socket (int is_standard_name, const char *name)
 
 #ifdef HAVE_W32_SYSTEM
   rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
-  if (is_standard_name && rc == -1 )
+  if (is_standard_name && rc == -1 && errno == WSAEADDRINUSE
+      && !no_reuse_standard_socket)
     {
       remove (name);
-      rc = bind (fd, (struct sockaddr*) serv_addr, len);
+      rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
     }
 #else
   rc = bind (fd, (struct sockaddr*) serv_addr, len);
-  if (is_standard_name && rc == -1 && errno == EADDRINUSE)
+  if (is_standard_name && rc == -1 && errno == EADDRINUSE  
+      && !no_reuse_standard_socket)
     {
       remove (name);
       rc = bind (fd, (struct sockaddr*) serv_addr, len);
@@ -1272,9 +1281,15 @@ create_server_socket (int is_standard_name, const char *name)
 #endif
   if (rc == -1)
     {
+      /* We use gpg_strerror here because it allows us to get strings
+         for some W32 socket error codes.  */
       log_error (_("error binding socket to `%s': %s\n"),
-                serv_addr->sun_path, strerror (errno));
+                serv_addr->sun_path, 
+                 gpg_strerror (gpg_error_from_errno (errno)));
+      
       close (fd);
+      if (is_standard_name && no_reuse_standard_socket)
+        *name = 0; /* Inhibit removal of the socket by cleanup(). */
       agent_exit (2);
     }
 
index 5fccb7e..1760502 100644 (file)
@@ -1,5 +1,6 @@
 /* w32main.c - W32 main entry pint and taskbar support for the GnuPG Agent
  * Copyright (C) 2007 Free Software Foundation, Inc.
+ * Copyright 1996, 1998 Alexandre Julliard
  *
  * This file is part of GnuPG.
  *
@@ -37,6 +38,136 @@ static HINSTANCE glob_hinst;
 static HWND glob_hwnd;
 
 
+/* Build an argv array from the command in CMDLINE.  RESERVED is the
+   number of args to reserve before the first one.  This code is based
+   on Alexandre Julliard's LGPLed wine-0.9.34/dlls/kernel32/process.c
+   and modified to fit into our framework.  The function returns NULL
+   on error; on success an arry with the argiments is returned.  This
+   array has been allocaqted using a plain malloc (and not the usual
+   xtrymalloc). */
+static char **
+build_argv (char *cmdline_arg, int reserved)
+{
+  int argc;
+  char **argv;
+  char *cmdline, *s, *arg, *d;
+  int in_quotes, bs_count;
+
+  cmdline = malloc (strlen (cmdline_arg) + 1);
+  if (!cmdline)
+    return NULL;
+  strcpy (cmdline, cmdline_arg);
+
+  /* First determine the required size of the array.  */
+  argc = reserved + 1;
+  bs_count = 0;
+  in_quotes = 0;
+  s = cmdline;
+  for (;;)
+    {
+      if ( !*s || ((*s==' ' || *s=='\t') && !in_quotes)) /* A space.  */
+        {
+          argc++;
+          /* Skip the remaining spaces.  */
+          while (*s==' ' || *s=='\t') 
+            s++;
+          if (!*s)
+            break;
+          bs_count = 0;
+        } 
+      else if (*s=='\\')
+        {
+          bs_count++;
+          s++;
+        }
+      else if ( (*s == '\"') && !(bs_count & 1))
+        {
+          /* Unescaped '\"' */
+          in_quotes = !in_quotes;
+          bs_count=0;
+          s++;
+        } 
+      else /* A regular character. */
+        {
+          bs_count = 0;
+          s++;
+        }
+    }
+
+  argv = malloc (argc * sizeof *argv);
+  if (!argv)
+    {
+      free (cmdline);
+      return NULL;
+    }
+
+  /* Now actually parse the command line.  */
+  argc = reserved;
+  bs_count = 0;
+  in_quotes=0;
+  arg = d = s = cmdline;
+  while (*s)
+    {
+      if ((*s==' ' || *s=='\t') && !in_quotes)
+        {
+          /* Close the argument and copy it. */
+          *d = 0;
+          argv[argc++] = arg;
+
+          /* Skip the remaining spaces. */
+          do 
+            s++;
+          while (*s==' ' || *s=='\t');
+
+          /* Start with a new argument */
+          arg = d = s;
+          bs_count = 0;
+        } 
+      else if (*s=='\\') 
+        {
+          *d++ = *s++;
+          bs_count++;
+        } 
+      else if (*s=='\"') 
+        {
+          if ( !(bs_count & 1) )
+            {
+              /* Preceded by an even number of backslashes, this is
+                 half that number of backslashes, plus a '\"' which we
+                 discard.  */
+              d -= bs_count/2;
+              s++;
+              in_quotes = !in_quotes;
+            }
+          else 
+            {
+              /* Preceded by an odd number of backslashes, this is
+                 half that number of backslashes followed by a '\"'.  */
+              d = d - bs_count/2 - 1;
+              *d++ ='\"';
+              s++;
+            }
+          bs_count=0;
+        } 
+      else /* A regular character. */
+        {
+          *d++ = *s++;
+          bs_count = 0;
+        }
+    }
+
+  if (*arg)
+    {
+      *d = 0;
+      argv[argc++] = arg;
+    }
+  argv[argc] = NULL;
+
+  return argv;
+}
+
+
+
 /* Our window message processing function.  */
 static LRESULT CALLBACK 
 wndw_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@@ -155,24 +286,23 @@ w32_setup_taskbar (void)
 
 
 /* The main entry point for the Windows version.  We save away all GUI
-   related stuff, parse the commandline and finally call the real
+   related stuff, parse the command line and finally call the real
    main.  */
 int WINAPI
 WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
 {
-  /* Fixme: We need a parser for the command line.  Should be
-     available in some CRT code - need to see whether we can find a
-     GNU version.  For nopw we call gpg-agent with a couple of fixed arguments 
-   */
-  char *argv[] = { "gpg-agent.exe", "--daemon", "-v", "--debug-all", NULL };
+  char **argv;
+  int argc;
 
+  /* We use the GetCommandLine function because that also includes the
+     program name in contrast to the CMDLINE arg. */
+  argv = build_argv (GetCommandLineA (), 0);
+  if (!argv)
+    return 2; /* Can't do much about a malloc failure.  */
+  for (argc=0; argv[argc]; argc++)
+    ;
 
   glob_hinst = hinst;
 
-  return w32_main (DIM(argv)-1, argv);
+  return w32_main (argc, argv);
 }
-
-
-
-
-
index 3f04125..a079b30 100644 (file)
@@ -369,18 +369,20 @@ this option at runtime does not kill an already forked scdaemon.
 
 @item --use-standard-socket
 @itemx --no-use-standard-socket
+@itemx --no-reuse-standard-socket
 @opindex use-standard-socket
 @opindex no-use-standard-socket
+@opindex no-reuse-standard-socket
 By enabling this option @command{gpg-agent} will listen on the socket
 named @file{S.gpg-agent}, located in the home directory, and not create
 a random socket below a temporary directory.  Tools connecting to
 @command{gpg-agent} should first try to connect to the socket given in
 environment variable @var{GPG_AGENT_INFO} and the fall back to this
 socket.  This option may not be used if the home directory is mounted as
-a remote file system.  
-
-@noindent
-Note, that as of now, W32 systems default to this option.
+a remote file system.  If @option{--no-reuse-standard-socket} is used,
+@command{gpg-agent} will not try to reuse a socket which is already in
+use.  Note, that @option{--use-standard-socket} is the default on
+Windows systems.
 
 
 @item --display @var{string}
index 1e202f6..44ea804 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1456,7 +1456,7 @@ list_config(char *items)
 static void
 gpgconf_list (const char *configfile)
 {
-  char *configfile_esc = percent_escape (configfile);
+  char *configfile_esc = percent_escape (configfile, NULL);
 
   /* The following definitions are taken from gnupg/tools/gpgconf-comp.c.  */
 #define GC_OPT_FLAG_NONE       0UL
index f98b1a2..4826ce4 100644 (file)
@@ -1,3 +1,17 @@
+2007-06-19  Werner Koch  <wk@g10code.com>
+
+       * Makefile.am: Add support for regression tests.
+       * t-support.h, t-support.c: New.
+       * t-stringhelp.c: New.
+
+       * stringhelp.c (percent_escape): Add arg EXTRA to make it a more
+       general function.  Changed all callers.
+
+2007-06-18  Werner Koch  <wk@g10code.com>
+
+       * w32-afunix.c (_w32_sock_bind): Changed to properly detect an
+       already used socket.
+
 2007-06-18  Marcus Brinkmann  <marcus@g10code.de>
 
        * stringhelp.h (percent_escape): New prototype.
index 0f593bb..eb447b5 100644 (file)
@@ -23,6 +23,8 @@
 ## Process this file with automake to produce Makefile.in
 
 EXTRA_DIST = README
+noinst_PROGRAMS = $(module_tests)
+TESTS = $(module_tests)
 
 AM_CPPFLAGS = -I$(top_srcdir)/intl
 
@@ -51,3 +53,20 @@ endif
 # For GnuPG we don't need the xmalloc stuff.
 #       xmalloc.c xmalloc.h       
 
+
+#
+# Module tests.
+#
+# These tests should only be used at the canonical location of jnlib
+# which is the GnuPG package.  The reason for this is that t-support.c
+# defines replacements for the actual used memory allocation functions
+# so that there is no dependency on libgcrypt.
+#
+module_tests = t-stringhelp
+
+t_jnlib_src = t-support.c t-support.h 
+t_jnlib_ldadd = libjnlib.a $(LIBINTL) $(LIBICONV)
+
+t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src)
+t_stringhelp_LDADD = $(t_jnlib_ldadd)
+
index 49d91c0..2050cdd 100644 (file)
@@ -34,6 +34,8 @@
 #include "stringhelp.h"
 
 
+#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
+
 /*
  * Look for the substring SUB in buffer and return a pointer to that
  * substring in BUFFER or NULL if not found.
@@ -827,19 +829,19 @@ memrchr (const void *buffer, int c, size_t n)
 #endif /*HAVE_MEMRCHR*/
 
 \f
-/* Percent-escape the string STR by replacing colons with '%3a'.  */
+/* Percent-escape the string STR by replacing colons with '%3a'.  If
+   EXTRA is not NULL all characters in it are also escaped. */
 char *
-percent_escape (const char *str)
+percent_escape (const char *str, const char *extra)
 {
-  int i = 0;
-  int j = 0;
+  int i, j;
   char *ptr;
 
   if (!str)
     return NULL;
 
-  while (str[i])
-    if (str[i++] == ':')
+  for (i=j=0; str[i]; i++)
+    if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
       j++;
   ptr = jnlib_xmalloc (i + 2 * j + 1);
   i = 0;
@@ -851,6 +853,18 @@ percent_escape (const char *str)
          ptr[i++] = '3';
          ptr[i++] = 'a';
        }
+      else if (*str == '%')
+       {
+         ptr[i++] = '%';
+         ptr[i++] = '2';
+         ptr[i++] = '5';
+       }
+      else if (extra && strchr (extra, *str))
+        {
+         ptr[i++] = '%';
+          ptr[i++] = tohex_lower ((*str>>4)&15);
+          ptr[i++] = tohex_lower (*str&15);
+        }
       else
        ptr[i++] = *str;
       str++;
index fdd887b..5f08745 100644 (file)
@@ -117,8 +117,9 @@ isascii (int c)
 #endif
 #define STR2(v) STR(v)
 
-/* Percent-escape the string STR by replacing colons with '%3a'.  */
-char *percent_escape (const char *str);
+/* Percent-escape the string STR by replacing colons with '%3a'.  If
+   EXTRA is not NULL, also replace all characters given in EXTRA. */
+char *percent_escape (const char *str, const char *extra);
 
 
 #endif /*LIBJNLIB_STRINGHELP_H*/
diff --git a/jnlib/t-stringhelp.c b/jnlib/t-stringhelp.c
new file mode 100644 (file)
index 0000000..27bea89
--- /dev/null
@@ -0,0 +1,94 @@
+/* t-stringhelp.c - Regression tests for stringhelp.c
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "stringhelp.h"
+
+#include "t-support.h"
+
+
+
+static void
+test_percent_escape (void)
+{
+  char *result;
+  static struct {
+    const char *extra; 
+    const char *value; 
+    const char *expected;
+  } tests[] = 
+    {
+      { NULL, "", "" },
+      { NULL, "%", "%25" },
+      { NULL, "%%", "%25%25" },
+      { NULL, " %", " %25" },
+      { NULL, ":", "%3a" },
+      { NULL, " :", " %3a" },
+      { NULL, ": ", "%3a " },
+      { NULL, " : ", " %3a " },
+      { NULL, "::", "%3a%3a" },
+      { NULL, ": :", "%3a %3a" },
+      { NULL, "%:", "%25%3a" },
+      { NULL, ":%", "%3a%25" },
+      { "\\\n:", ":%", "%3a%25" },
+      { "\\\n:", "\\:%", "%5c%3a%25" },
+      { "\\\n:", "\n:%", "%0a%3a%25" },
+      { "\\\n:", "\xff:%", "\xff%3a%25" },
+      { "\\\n:", "\xfe:%", "\xfe%3a%25" },
+      { "\\\n:", "\x01:%", "\x01%3a%25" },
+      { "\x01",  "\x01:%", "%01%3a%25" },
+      { "\xfe",  "\xfe:%", "%fe%3a%25" },
+      { "\xfe",  "\xff:%", "\xff%3a%25" },
+
+      { NULL, NULL, NULL }
+    };
+  int testno;
+
+  result = percent_escape (NULL, NULL);
+  if (result)
+    fail (0);
+  for (testno=0; tests[testno].value; testno++)
+    {
+      result = percent_escape (tests[testno].value, tests[testno].extra);
+      if (!result)
+        fail (testno);
+      if (strcmp (result, tests[testno].expected))
+        fail (testno);
+      xfree (result);
+    }
+
+}
+
+
+
+
+int
+main (int argc, char **argv)
+{
+  test_percent_escape ();
+
+  return 0;
+}
+
diff --git a/jnlib/t-support.c b/jnlib/t-support.c
new file mode 100644 (file)
index 0000000..d9d50e9
--- /dev/null
@@ -0,0 +1,111 @@
+/* t-support.c - helper functions for the regression tests.
+ * Copyright (C) 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "t-support.h"
+
+/* Replacements for the malloc functions as used here. */
+
+static void
+out_of_memory (void)
+{
+  fprintf (stderr,"error: out of core in regression tests: %s\n",
+           strerror (errno));
+  exit (2);
+}
+
+
+void *
+gcry_malloc (size_t n)
+{
+  return malloc (n);
+}
+
+void *
+gcry_xmalloc (size_t n)
+{
+  void *p = malloc (n);
+  if (!p)
+    out_of_memory ();
+  return p;
+}
+
+char *
+gcry_strdup (const char *string)
+{
+  return malloc (strlen (string)+1);
+}
+
+
+void *
+gcry_realloc (void *a, size_t n)
+{
+  return realloc (a, n);
+}
+
+void *
+gcry_xrealloc (void *a, size_t n)
+{
+  void *p = realloc (a, n);
+  if (!p)
+    out_of_memory ();
+  return p;
+}
+
+
+
+void *
+gcry_calloc (size_t n, size_t m)
+{
+  return calloc (n, m);
+}
+
+void *
+gcry_xcalloc (size_t n, size_t m)
+{
+  void *p = calloc (n, m);
+  if (!p)
+    out_of_memory ();
+  return p;
+}
+
+
+char *
+gcry_xstrdup (const char *string)
+{
+  void *p = malloc (strlen (string)+1);
+  if (!p)
+    out_of_memory ();
+  strcpy (p, string);
+  return p;
+}
+
+void
+gcry_free (void *a)
+{
+  if (a)
+    free (a);
+}
diff --git a/jnlib/t-support.h b/jnlib/t-support.h
new file mode 100644 (file)
index 0000000..661dfb4
--- /dev/null
@@ -0,0 +1,52 @@
+/* t-support.h - Helper for the regression tests
+ * Copyright (C) 2007  Free Software Foundation, Inc.
+ *
+ * This file is part of JNLIB.
+ *
+ * JNLIB is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JNLIB is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef LIBJNLIB_T_SUPPORT_H
+#define LIBJNLIB_T_SUPPORT_H 1
+
+#ifdef GCRYPT_VERSION
+#error The regression tests should not include with gcrypt.h
+#endif
+
+/* Repalcement prototypes. */
+void *gcry_xmalloc (size_t n);
+void *gcry_xcalloc (size_t n, size_t m);
+void *gcry_xrealloc (void *a, size_t n);
+char *gcry_xstrdup (const char * a);
+void  gcry_free (void *a);
+
+/* Map the used xmalloc functions to those implemented by t-support.c */
+#define xmalloc(a)    gcry_xmalloc ( (a) )
+#define xcalloc(a,b)  gcry_xcalloc ( (a), (b) )
+#define xrealloc(a,n) gcry_xrealloc ( (a), (n) )
+#define xstrdup(a)    gcry_xstrdup ( (a) )
+#define xfree(a)      gcry_free ( (a) )
+
+
+/* Macros to print the result of a test.  */
+#define pass()  do { ; } while(0)
+#define fail(a)  do { fprintf (stderr, "%s:%d: test %d failed\n",\
+                               __FILE__,__LINE__, (a));          \
+                     exit (1);                                   \
+                   } while(0)
+
+
+#endif /*LIBJNLIB_T_SUPPORT_H*/
index dcce423..16132a2 100644 (file)
 #ifdef _WIN32
 #include <stdio.h>
 #include <windows.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 #include <io.h>
 #include <errno.h>
 
 #include "w32-afunix.h"
 
+#ifndef S_IRGRP
+# define S_IRGRP 0
+# define S_IWGRP 0
+#endif
+
+
 int
 _w32_close (int fd)
 {
@@ -81,34 +89,56 @@ _w32_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
 
 
 int
-_w32_sock_bind (int sockfd, struct sockaddr * addr, int addrlen)
+_w32_sock_bind (int sockfd, struct sockaddr *addr, int addrlen)
 {
   if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
     {
       struct sockaddr_in myaddr;
-      struct sockaddr_un * unaddr;
-      FILE * fp;
+      struct sockaddr_un *unaddr;
+      int filefd;
+      FILE *fp;
       int len = sizeof myaddr;
       int rc;
 
+      unaddr = (struct sockaddr_un *)addr;
+
       myaddr.sin_port = 0;
       myaddr.sin_family = AF_INET;
       myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
 
+      filefd = open (unaddr->sun_path, 
+                     (O_WRONLY|O_CREAT|O_EXCL|O_BINARY), 
+                     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
+      if (filefd == -1)
+        {
+          if (errno == EEXIST)
+            errno = WSAEADDRINUSE;
+          return -1;
+        }
+      fp = fdopen (filefd, "wb");
+      if (!fp)
+        { 
+          int save_e = errno;
+          close (filefd);
+          errno = save_e;
+          return -1;
+        }
+
       rc = bind (sockfd, (struct sockaddr *)&myaddr, len);
+      if (!rc)
+        rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
       if (rc)
-        return rc;
-      rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
-      if (rc)
-        return rc;
-      unaddr = (struct sockaddr_un *)addr;
-      fp = fopen (unaddr->sun_path, "wb");
-      if (!fp)
-        return -1;
+        {
+          int save_e = errno;
+          fclose (fp);
+          remove (unaddr->sun_path);
+          errno = save_e;
+          return rc;
+        }
       fprintf (fp, "%d", myaddr.sin_port);
       fclose (fp);
 
-      /* we need this later. */
+      /* The caller expects these values. */
       unaddr->sun_family = myaddr.sin_family;
       unaddr->sun_port = myaddr.sin_port;
       unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
index 4e45907..f9a9992 100644 (file)
@@ -551,7 +551,7 @@ main (int argc, char **argv )
 #define GC_OPT_FLAG_NO_ARG_DESC        (1UL << 6)
       if (!config_filename)
         filename = make_filename (opt.homedir, "scdaemon.conf", NULL );
-      filename_esc = percent_escape (filename);
+      filename_esc = percent_escape (filename, NULL);
 
       printf ("gpgconf-scdaemon.conf:%lu:\"%s\n",
               GC_OPT_FLAG_DEFAULT, filename_esc);
index 11b759b..f6d2b84 100644 (file)
@@ -1393,7 +1393,7 @@ main ( int argc, char **argv)
            a default, which is described by the value of the ARGDEF field.  */
 #define GC_OPT_FLAG_NO_ARG_DESC        (1UL << 6)
 
-       char *config_filename_esc = percent_escape (opt.config_filename);
+       char *config_filename_esc = percent_escape (opt.config_filename, NULL);
 
         printf ("gpgconf-gpgsm.conf:%lu:\"%s\n",
                 GC_OPT_FLAG_DEFAULT, config_filename_esc);
index c30ef79..f36c33a 100644 (file)
@@ -1,3 +1,8 @@
+2007-06-19  Werner Koch  <wk@g10code.com>
+
+       * gpgconf-comp.c (percent_escape): Rename to my_percent_escape.
+       Changed all callers.
+
 2007-06-18  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgconf-comp.c (retrieve_options_from_file): Close LIST_FILE.
index 368d498..caf09d3 100644 (file)
@@ -984,7 +984,7 @@ my_dgettext (const char *domain, const char *msgid)
 /* Percent-Escape special characters.  The string is valid until the
    next invocation of the function.  */
 static char *
-percent_escape (const char *src)
+my_percent_escape (const char *src)
 {
   static char *esc_str;
   static int esc_str_len;
@@ -1083,7 +1083,8 @@ gc_component_list_components (FILE *out)
     {
       const char *desc = gc_component[idx].desc;
       desc = my_dgettext (gc_component[idx].desc_domain, desc);
-      fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc));
+      fprintf (out, "%s:%s\n",
+               gc_component[idx].name,  my_percent_escape (desc));
     }
 }
 
@@ -1174,7 +1175,7 @@ list_one_option (const gc_option_t *option, FILE *out)
     fprintf (out, " %s", gc_level[option->level].name);
 
   /* The description field.  */
-  fprintf (out, ":%s", desc ? percent_escape (desc) : "");
+  fprintf (out, ":%s", desc ? my_percent_escape (desc) : "");
   
   /* The type field.  */
   fprintf (out, ":%u", option->arg_type);
@@ -1188,7 +1189,7 @@ list_one_option (const gc_option_t *option, FILE *out)
             gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
 
   /* The argument name field.  */
-  fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : "");
+  fprintf (out, ":%s", arg_name ? my_percent_escape (arg_name) : "");
   if (arg_name)
     xfree (arg_name);
 
@@ -1458,7 +1459,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
                }
              else if (gc_arg_type[option->arg_type].fallback
                       == GC_ARG_TYPE_STRING)
-               opt_value = xasprintf ("\"%s", percent_escape (value));
+               opt_value = xasprintf ("\"%s", my_percent_escape (value));
              else
                {
                  /* FIXME: Verify that the number is sane.  */
@@ -1549,12 +1550,12 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
             really append.  */
          if (list)
            {
-             new_list = xasprintf ("%s,\"%s", list, percent_escape (start));
+             new_list = xasprintf ("%s,\"%s", list, my_percent_escape (start));
              xfree (list);
              list = new_list;
            }
          else
-           list = xasprintf ("\"%s", percent_escape (start));
+           list = xasprintf ("\"%s", my_percent_escape (start));
        }
       if (length < 0 || ferror (list_file))
        gc_error (1, errno, "can not read list file %s", list_pathname);