]> Savannah Git Hosting - gnulib.git/commitdiff
windows-spawn: Export another auxiliary function.
authorBruno Haible <bruno@clisp.org>
Thu, 24 Dec 2020 21:18:18 +0000 (22:18 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 24 Dec 2020 21:18:18 +0000 (22:18 +0100)
* lib/windows-spawn.h (compose_envblock): New declaration.
* lib/windows-spawn.c (compose_envblock): New function, extracted from
spawnpvech.
(spawnpvech): Use it.

ChangeLog
lib/windows-spawn.c
lib/windows-spawn.h

index ba8a7d904694ac4f9b33861620e0b59f79916217..d140497d8cad9516282dc3c7497177c929d50340 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2020-12-24  Bruno Haible  <bruno@clisp.org>
+
+       windows-spawn: Export another auxiliary function.
+       * lib/windows-spawn.h (compose_envblock): New declaration.
+       * lib/windows-spawn.c (compose_envblock): New function, extracted from
+       spawnpvech.
+       (spawnpvech): Use it.
+
 2020-12-24  Bruno Haible  <bruno@clisp.org>
 
        windows-spawn: Export an auxiliary function.
index cc29196ecfe70acce5cbcc26f990f12a79c8021e..b0a6dda9c0b526e61623883033b98350715da762 100644 (file)
@@ -244,6 +244,65 @@ compose_command (const char * const *argv)
   return command;
 }
 
+char *
+compose_envblock (const char * const *envp)
+{
+  /* This is a bit hairy, because we don't have a lock that would prevent other
+     threads from making modifications in ENVP.  So, just make sure we don't
+     crash; but if other threads are making modifications, part of the result
+     may be wrong.  */
+ retry:
+  {
+    /* Guess the size of the needed block of memory.
+       The guess will be exact if other threads don't make modifications.  */
+    size_t total_size = 0;
+    const char * const *ep;
+    const char *p;
+    for (ep = envp; (p = *ep) != NULL; ep++)
+      total_size += strlen (p) + 1;
+    size_t envblock_size = total_size;
+
+    /* Allocate the block of memory.  */
+    char *envblock = (char *) malloc (envblock_size + 1);
+    if (envblock == NULL)
+      {
+        errno = ENOMEM;
+        return NULL;
+      }
+    size_t envblock_used = 0;
+    for (ep = envp; (p = *ep) != NULL; ep++)
+      {
+        size_t size = strlen (p) + 1;
+        if (envblock_used + size > envblock_size)
+          {
+            /* Other threads did modifications.  Need more memory.  */
+            envblock_size += envblock_size / 2;
+            if (envblock_used + size > envblock_size)
+              envblock_size = envblock_used + size;
+
+            char *new_envblock = (char *) realloc (envblock, envblock_size + 1);
+            if (new_envblock == NULL)
+              {
+                free (envblock);
+                errno = ENOMEM;
+                return NULL;
+              }
+            envblock = new_envblock;
+          }
+        memcpy (envblock + envblock_used, p, size);
+        envblock_used += size;
+        if (envblock[envblock_used - 1] != '\0')
+          {
+            /* Other threads did modifications.  Restart.  */
+            free (envblock);
+            goto retry;
+          }
+      }
+    envblock[envblock_used] = '\0';
+    return envblock;
+  }
+}
+
 intptr_t
 spawnpvech (int mode,
             const char *progname, const char * const *argv,
@@ -278,45 +337,10 @@ spawnpvech (int mode,
   if (envp == NULL)
     envblock = NULL;
   else
-   retry:
     {
-      /* Guess the size of the needed block of memory.
-         The guess will be exact if other threads don't make modifications.  */
-      size_t total_size = 0;
-      const char * const *ep;
-      const char *p;
-      for (ep = envp; (p = *ep) != NULL; ep++)
-        total_size += strlen (p) + 1;
-      size_t envblock_size = total_size;
-      envblock = (char *) malloc (envblock_size + 1);
+      envblock = compose_envblock (envp);
       if (envblock == NULL)
         goto out_of_memory_2;
-      size_t envblock_used = 0;
-      for (ep = envp; (p = *ep) != NULL; ep++)
-        {
-          size_t size = strlen (p) + 1;
-          if (envblock_used + size > envblock_size)
-            {
-              /* Other threads did modifications.  Need more memory.  */
-              envblock_size += envblock_size / 2;
-              if (envblock_used + size > envblock_size)
-                envblock_size = envblock_used + size;
-
-              char *new_envblock = (char *) realloc (envblock, envblock_size + 1);
-              if (new_envblock == NULL)
-                goto out_of_memory_3;
-              envblock = new_envblock;
-            }
-          memcpy (envblock + envblock_used, p, size);
-          envblock_used += size;
-          if (envblock[envblock_used - 1] != '\0')
-            {
-              /* Other threads did modifications.  Restart.  */
-              free (envblock);
-              goto retry;
-            }
-        }
-      envblock[envblock_used] = '\0';
     }
 
   /* CreateProcess
index cb9d3fab12a4110bd34e6e249e652f9d7a85f986..90f45e15ea7925c4efe3ac9d754ecff11f8c6932 100644 (file)
@@ -72,6 +72,13 @@ extern const char ** prepare_spawn (const char * const *argv,
    NULL is returned, with errno set.  */
 extern char * compose_command (const char * const *argv);
 
+/* Composes the block of memory that contains the environment variables.
+   ENVP must contain an environment (a NULL-terminated array of string of the
+   form VARIABLE=VALUE).
+   Returns a freshly allocated block of memory.  In case of memory allocation
+   failure, NULL is returned, with errno set.  */
+extern char * compose_envblock (const char * const *envp);
+
 /* Creates a subprocess.
    MODE is either P_WAIT or P_NOWAIT.
    PROGNAME is the program to invoke.