Add test code, but it's still segfaulting.
[oweals/gnunet.git] / src / util / os_installation.c
index d500580bfa36a20c9ea29c6217ebb374ea766026..ea6361a92db4424ef6006132db4b35eea93844d5 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2006 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2006-2014 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
 */
 
 /**
 #include <unistr.h> /* for u16_to_u8 */
 
 #include "platform.h"
 #include <unistr.h> /* for u16_to_u8 */
 
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_configuration_lib.h"
-#include "gnunet_disk_lib.h"
-#include "gnunet_os_lib.h"
-#include "gnunet_strings_lib.h"
+#include "gnunet_util_lib.h"
 #if DARWIN
 #include <mach-o/ldsyms.h>
 #include <mach-o/dyld.h>
 #if DARWIN
 #include <mach-o/ldsyms.h>
 #include <mach-o/dyld.h>
+#elif WINDOWS
+#include <windows.h>
 #endif
 
 #endif
 
+
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
 
+
 #if LINUX
 /**
  * Try to determine path by reading /proc/PID/exe
 #if LINUX
 /**
  * Try to determine path by reading /proc/PID/exe
@@ -65,7 +65,7 @@ get_path_from_proc_maps ()
   while (NULL != fgets (line, sizeof (line), f))
   {
     if ((1 ==
   while (NULL != fgets (line, sizeof (line), f))
   {
     if ((1 ==
-         SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%1023s", dir)) &&
+         SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%1023s", dir)) &&
         (NULL != (lgu = strstr (dir, "libgnunetutil"))))
     {
       lgu[0] = '\0';
         (NULL != (lgu = strstr (dir, "libgnunetutil"))))
     {
       lgu[0] = '\0';
@@ -101,7 +101,7 @@ get_path_from_proc_exe ()
   lnk[size] = '\0';
   while ((lnk[size] != '/') && (size > 0))
     size--;
   lnk[size] = '\0';
   while ((lnk[size] != '/') && (size > 0))
     size--;
-  /* test for being in lib/gnunet/libexec/ */
+  /* test for being in lib/gnunet/libexec/ or lib/MULTIARCH/gnunet/libexec */
   if ( (size > strlen ("/gnunet/libexec/")) &&
        (0 == strcmp ("/gnunet/libexec/",
                     &lnk[size - strlen ("/gnunet/libexec/")])) )
   if ( (size > strlen ("/gnunet/libexec/")) &&
        (0 == strcmp ("/gnunet/libexec/",
                     &lnk[size - strlen ("/gnunet/libexec/")])) )
@@ -116,12 +116,13 @@ get_path_from_proc_exe ()
 }
 #endif
 
 }
 #endif
 
-#if WINDOWS
 
 
+#if WINDOWS
 static HINSTANCE dll_instance;
 
 
 static HINSTANCE dll_instance;
 
 
-/* GNUNET_util_cl_init() in common_logging.c is preferred.
+/**
+ * GNUNET_util_cl_init() in common_logging.c is preferred.
  * This function is only for thread-local storage (not used in GNUnet)
  * and hInstance saving.
  */
  * This function is only for thread-local storage (not used in GNUnet)
  * and hInstance saving.
  */
@@ -172,7 +173,7 @@ get_path_from_module_filename ()
     real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t));
   } while (real_pathlen >= pathlen && pathlen < 16*1024);
   if (real_pathlen >= pathlen)
     real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t));
   } while (real_pathlen >= pathlen && pathlen < 16*1024);
   if (real_pathlen >= pathlen)
-    GNUNET_abort ();
+    GNUNET_assert (0);
   /* To be safe */
   modulepath[real_pathlen] = '\0';
 
   /* To be safe */
   modulepath[real_pathlen] = '\0';
 
@@ -214,7 +215,7 @@ get_path_from_module_filename ()
   /* modulepath is GNUNET_PREFIX */
   u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length);
   if (NULL == u8_string)
   /* modulepath is GNUNET_PREFIX */
   u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length);
   if (NULL == u8_string)
-    GNUNET_abort ();
+    GNUNET_assert (0);
 
   upath = GNUNET_malloc (u8_string_length + 1);
   memcpy (upath, u8_string, u8_string_length);
 
   upath = GNUNET_malloc (u8_string_length + 1);
   memcpy (upath, u8_string, u8_string_length);
@@ -227,6 +228,7 @@ get_path_from_module_filename ()
 }
 #endif
 
 }
 #endif
 
+
 #if DARWIN
 /**
  * Signature of the '_NSGetExecutablePath" function.
 #if DARWIN
 /**
  * Signature of the '_NSGetExecutablePath" function.
@@ -292,7 +294,7 @@ get_path_from_dyld_image ()
   c = _dyld_image_count ();
   for (i = 0; i < c; i++)
   {
   c = _dyld_image_count ();
   for (i = 0; i < c; i++)
   {
-    if (_dyld_get_image_header (i) != &_mh_dylib_header)
+    if (((const void *) _dyld_get_image_header (i)) != (const void *)&_mh_dylib_header)
       continue;
     path = _dyld_get_image_name (i);
     if ( (NULL == path) || (0 == strlen (path)) )
       continue;
     path = _dyld_get_image_name (i);
     if ( (NULL == path) || (0 == strlen (path)) )
@@ -416,8 +418,7 @@ os_get_gnunet_path ()
     return ret;
   /* other attempts here */
   LOG (GNUNET_ERROR_TYPE_ERROR,
     return ret;
   /* other attempts here */
   LOG (GNUNET_ERROR_TYPE_ERROR,
-       _
-       ("Could not determine installation path for %s.  Set `%s' environment variable.\n"),
+       _("Could not determine installation path for %s.  Set `%s' environment variable.\n"),
        "GNUnet", "GNUNET_PREFIX");
   return NULL;
 }
        "GNUnet", "GNUNET_PREFIX");
   return NULL;
 }
@@ -453,7 +454,7 @@ os_get_exec_path ()
 
 /**
  * @brief get the path to a specific GNUnet installation directory or,
 
 /**
  * @brief get the path to a specific GNUnet installation directory or,
- * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory
+ * with #GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory
  * @author Milan
  * @return a pointer to the dir path (to be freed by the caller)
  */
  * @author Milan
  * @return a pointer to the dir path (to be freed by the caller)
  */
@@ -464,6 +465,8 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
   const char *dirname;
   char *execpath = NULL;
   char *tmp;
   const char *dirname;
   char *execpath = NULL;
   char *tmp;
+  char *multiarch;
+  char *libdir;
   int isbasedir;
 
   /* if wanted, try to get the current app's bin/ */
   int isbasedir;
 
   /* if wanted, try to get the current app's bin/ */
@@ -512,6 +515,17 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
     execpath[n - 4] = '\0';
     n -= 4;
   }
     execpath[n - 4] = '\0';
     n -= 4;
   }
+  multiarch = NULL;
+  if (NULL != (libdir = strstr (execpath, "/lib/")))
+  {
+    /* test for multi-arch path of the form "PREFIX/lib/MULTIARCH/";
+       here we need to re-add 'multiarch' to lib and libexec paths later! */
+    multiarch = &libdir[5];
+    if (NULL == strchr (multiarch, '/'))
+      libdir[0] = '\0'; /* Debian multiarch format, cut of from 'execpath' but preserve in multicarch */
+    else
+      multiarch = NULL; /* maybe not, multiarch still has a '/', which is not OK */
+  }
   /* in case this was a directory named foo-bin, remove "foo-" */
   while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
     execpath[--n] = '\0';
   /* in case this was a directory named foo-bin, remove "foo-" */
   while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR))
     execpath[--n] = '\0';
@@ -527,31 +541,50 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
   case GNUNET_OS_IPK_LIBDIR:
     if (isbasedir)
     {
   case GNUNET_OS_IPK_LIBDIR:
     if (isbasedir)
     {
-      dirname =
-          DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
-      tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
-      sprintf (tmp, "%s%s", execpath, dirname);
-      if ( (GNUNET_YES !=
-           GNUNET_DISK_directory_test (tmp, GNUNET_YES)) &&
-          (4 == sizeof (void *)) )
+      GNUNET_asprintf (&tmp,
+                       "%s%s%s%s%s",
+                       execpath,
+                       DIR_SEPARATOR_STR "lib",
+                       (NULL != multiarch) ? DIR_SEPARATOR_STR : "",
+                       (NULL != multiarch) ? multiarch : "",
+                       DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR);
+      if (GNUNET_YES ==
+          GNUNET_DISK_directory_test (tmp, GNUNET_YES))
+      {
+        GNUNET_free (execpath);
+        return tmp;
+      }
+      GNUNET_free (tmp);
+      tmp = NULL;
+      if (4 == sizeof (void *))
       {
       {
-       GNUNET_free (tmp);
        dirname =
          DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
        dirname =
          DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
-       tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
-       sprintf (tmp, "%s%s", execpath, dirname);
+       GNUNET_asprintf (&tmp,
+                         "%s%s",
+                         execpath,
+                         dirname);
       }
       }
-      if ( (GNUNET_YES !=
-           GNUNET_DISK_directory_test (tmp, GNUNET_YES)) &&
-          (8 == sizeof (void *)) )
+      if (8 == sizeof (void *))
       {
        dirname =
          DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
       {
        dirname =
          DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
+       GNUNET_asprintf (&tmp,
+                         "%s%s",
+                         execpath,
+                         dirname);
+      }
+
+      if ( (NULL != tmp) &&
+           (GNUNET_YES ==
+            GNUNET_DISK_directory_test (tmp, GNUNET_YES)) )
+      {
+        GNUNET_free (execpath);
+        return tmp;
       }
       GNUNET_free (tmp);
     }
       }
       GNUNET_free (tmp);
     }
-    else
-      dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
+    dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR;
     break;
   case GNUNET_OS_IPK_DATADIR:
     dirname =
     break;
   case GNUNET_OS_IPK_DATADIR:
     dirname =
@@ -574,42 +607,63 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
     if (isbasedir)
     {
       dirname =
     if (isbasedir)
     {
       dirname =
-        DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
-        "libexec" DIR_SEPARATOR_STR;
-      tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
-      sprintf (tmp, "%s%s", execpath, dirname);
-      if ( (GNUNET_YES !=
-           GNUNET_DISK_directory_test (tmp, GNUNET_YES)) &&
-          (4 == sizeof (void *)) )
+        DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR;
+      GNUNET_asprintf (&tmp,
+                       "%s%s%s%s",
+                       execpath,
+                       DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR,
+                       (NULL != multiarch) ? multiarch : "",
+                       dirname);
+      if (GNUNET_YES ==
+          GNUNET_DISK_directory_test (tmp, GNUNET_YES))
+      {
+        GNUNET_free (execpath);
+        return tmp;
+      }
+      GNUNET_free (tmp);
+      tmp = NULL;
+      if (4 == sizeof (void *))
       {
       {
-       GNUNET_free (tmp);
        dirname =
          DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
          "libexec" DIR_SEPARATOR_STR;
        dirname =
          DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
          "libexec" DIR_SEPARATOR_STR;
-       tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
-       sprintf (tmp, "%s%s", execpath, dirname);
+       GNUNET_asprintf (&tmp,
+                         "%s%s",
+                         execpath,
+                         dirname);
       }
       }
-      if ( (GNUNET_YES !=
-           GNUNET_DISK_directory_test (tmp, GNUNET_YES)) &&
-          (8 == sizeof (void *)) )
+      if (8 == sizeof (void *))
       {
        dirname =
          DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
          "libexec" DIR_SEPARATOR_STR;
       {
        dirname =
          DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
          "libexec" DIR_SEPARATOR_STR;
+       GNUNET_asprintf (&tmp,
+                         "%s%s",
+                         execpath,
+                         dirname);
+      }
+      if ( (NULL != tmp) &&
+           (GNUNET_YES ==
+            GNUNET_DISK_directory_test (tmp, GNUNET_YES)) )
+      {
+        GNUNET_free (execpath);
+        return tmp;
       }
       }
+
       GNUNET_free (tmp);
     }
       GNUNET_free (tmp);
     }
-    else
-      dirname =
-        DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
-        "libexec" DIR_SEPARATOR_STR;
+    dirname =
+      DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \
+      "libexec" DIR_SEPARATOR_STR;
     break;
   default:
     GNUNET_free (execpath);
     return NULL;
   }
     break;
   default:
     GNUNET_free (execpath);
     return NULL;
   }
-  tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1);
-  sprintf (tmp, "%s%s", execpath, dirname);
+  GNUNET_asprintf (&tmp,
+                   "%s%s",
+                   execpath,
+                   dirname);
   GNUNET_free (execpath);
   return tmp;
 }
   GNUNET_free (execpath);
   return tmp;
 }
@@ -626,19 +680,24 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
 char *
 GNUNET_OS_get_libexec_binary_path (const char *progname)
 {
 char *
 GNUNET_OS_get_libexec_binary_path (const char *progname)
 {
+  static char *cache;
   char *libexecdir;
   char *binary;
 
   char *libexecdir;
   char *binary;
 
-  if (DIR_SEPARATOR == progname[0])
+  if ( (DIR_SEPARATOR == progname[0]) ||
+       (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (progname, GNUNET_NO, NULL, NULL)) )
     return GNUNET_strdup (progname);
     return GNUNET_strdup (progname);
-  libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR);
+  if (NULL != cache)
+    libexecdir = cache;
+  else
+    libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR);
   if (NULL == libexecdir)
     return GNUNET_strdup (progname);
   GNUNET_asprintf (&binary,
                   "%s%s",
                   libexecdir,
                   progname);
   if (NULL == libexecdir)
     return GNUNET_strdup (progname);
   GNUNET_asprintf (&binary,
                   "%s%s",
                   libexecdir,
                   progname);
-  GNUNET_free (libexecdir);
+  cache = libexecdir;
   return binary;
 }
 
   return binary;
 }
 
@@ -651,18 +710,24 @@ GNUNET_OS_get_libexec_binary_path (const char *progname)
  *
  * @param binary the name of the file to check.
  *        W32: must not have an .exe suffix.
  *
  * @param binary the name of the file to check.
  *        W32: must not have an .exe suffix.
- * @return GNUNET_YES if the file is SUID,
- *         GNUNET_NO if not SUID (but binary exists)
- *         GNUNET_SYSERR on error (no such binary or not executable)
+ * @param check_suid input true if the binary should be checked for SUID (*nix)
+ *        W32: checks if the program has sufficient privileges by executing this
+ *             binary with the -d flag. -d omits a programs main loop and only
+ *             executes all privileged operations in an binary.
+ * @param params parameters used for w32 privilege checking (can be NULL for != w32 )
+ * @return #GNUNET_YES if the file is SUID (*nix) or can be executed with current privileges (W32),
+ *         #GNUNET_NO if not SUID (but binary exists),
+ *         #GNUNET_SYSERR on error (no such binary or not executable)
  */
 int
  */
 int
-GNUNET_OS_check_helper_binary (const char *binary)
+GNUNET_OS_check_helper_binary (const char *binary,
+                               int check_suid,
+                               const char *params)
 {
   struct stat statbuf;
   char *p;
   char *pf;
 #ifdef MINGW
 {
   struct stat statbuf;
   char *p;
   char *pf;
 #ifdef MINGW
-  SOCKET rawsock;
   char *binaryexe;
 
   GNUNET_asprintf (&binaryexe, "%s.exe", binary);
   char *binaryexe;
 
   GNUNET_asprintf (&binaryexe, "%s.exe", binary);
@@ -699,7 +764,8 @@ GNUNET_OS_check_helper_binary (const char *binary)
 #endif
   if (NULL == p)
   {
 #endif
   if (NULL == p)
   {
-    LOG (GNUNET_ERROR_TYPE_INFO, _("Could not find binary `%s' in PATH!\n"),
+    LOG (GNUNET_ERROR_TYPE_INFO,
+         _("Could not find binary `%s' in PATH!\n"),
          binary);
     return GNUNET_SYSERR;
   }
          binary);
     return GNUNET_SYSERR;
   }
@@ -723,40 +789,66 @@ GNUNET_OS_check_helper_binary (const char *binary)
     GNUNET_free (p);
     return GNUNET_SYSERR;
   }
     GNUNET_free (p);
     return GNUNET_SYSERR;
   }
+  if (check_suid){
 #ifndef MINGW
 #ifndef MINGW
-  if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid))
-  {
-    GNUNET_free (p);
-    return GNUNET_YES;
-  }
-  /* binary exists, but not SUID */
-  GNUNET_free (p);
-  return GNUNET_NO;
-#else
-  GNUNET_free (p);
-  {
-    static int once; /* remember result from previous runs... */
-
-    if (0 == once)
+    if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid))
     {
     {
-      rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
-      if (INVALID_SOCKET == rawsock)
-       {
-         DWORD err = GetLastError ();
-         
-         LOG (GNUNET_ERROR_TYPE_DEBUG,
-              "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) failed! GLE = %d\n", err);
-         once = -1;
-         return GNUNET_NO;           /* not running as administrator */
-       }
-      once = 1;
-      closesocket (rawsock);
+      GNUNET_free (p);
+      return GNUNET_YES;
     }
     }
-    if (-1 == once)
-      return GNUNET_NO;
-    return GNUNET_YES;
-  }
+    /* binary exists, but not SUID */
+#else
+    STARTUPINFO start;
+    char parameters[512];
+    PROCESS_INFORMATION proc;
+    DWORD exit_value;
+
+    GNUNET_snprintf (parameters,
+                    sizeof (parameters),
+                    "-d %s", params);
+    memset (&start, 0, sizeof (start));
+    start.cb = sizeof (start);
+    memset (&proc, 0, sizeof (proc));
+
+
+    // Start the child process.
+    if ( ! (CreateProcess( p,   // current windows (2k3 and up can handle / instead of \ in paths))
+        parameters,           // execute dryrun/priviliege checking mode
+        NULL,           // Process handle not inheritable
+        NULL,           // Thread handle not inheritable
+        FALSE,          // Set handle inheritance to FALSE
+        CREATE_DEFAULT_ERROR_MODE, // No creation flags
+        NULL,           // Use parent's environment block
+        NULL,           // Use parent's starting directory
+        &start,            // Pointer to STARTUPINFO structure
+        &proc )           // Pointer to PROCESS_INFORMATION structure
+                               ))
+      {
+        LOG (GNUNET_ERROR_TYPE_ERROR,
+             _("CreateProcess failed for binary %s (%d).\n"),
+             p, GetLastError());
+        return GNUNET_SYSERR;
+    }
+
+    // Wait until child process exits.
+    WaitForSingleObject( proc.hProcess, INFINITE );
+
+    if ( ! GetExitCodeProcess (proc.hProcess, &exit_value)){
+        LOG (GNUNET_ERROR_TYPE_ERROR,
+             _("GetExitCodeProcess failed for binary %s (%d).\n"),
+             p, GetLastError() );
+        return GNUNET_SYSERR;
+      }
+    // Close process and thread handles.
+    CloseHandle( proc.hProcess );
+    CloseHandle( proc.hThread );
+
+    if (!exit_value)
+      return GNUNET_YES;
 #endif
 #endif
+    }
+  GNUNET_free (p);
+  return GNUNET_NO;
 }
 
 
 }