summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2020-12-24 22:18:18 +0100
committerBruno Haible <bruno@clisp.org>2020-12-24 22:18:18 +0100
commitd1ae9c694e5418850c71884ccd22a293d9b3e29b (patch)
tree3b2a8768375f204947e28fa5aa6b1a2333621b32
parentf8199b3ae12a94f79994e1c1e2389fe024ffa6fb (diff)
downloadgnulib-d1ae9c694e5418850c71884ccd22a293d9b3e29b.tar.gz
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.
-rw-r--r--ChangeLog8
-rw-r--r--lib/windows-spawn.c96
-rw-r--r--lib/windows-spawn.h7
3 files changed, 75 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index ba8a7d9046..d140497d8c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
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.
* lib/windows-spawn.h (compose_command): New declaration.
* lib/windows-spawn.c (compose_command): New function, extracted from
diff --git a/lib/windows-spawn.c b/lib/windows-spawn.c
index cc29196ecf..b0a6dda9c0 100644
--- a/lib/windows-spawn.c
+++ b/lib/windows-spawn.c
@@ -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
diff --git a/lib/windows-spawn.h b/lib/windows-spawn.h
index cb9d3fab12..90f45e15ea 100644
--- a/lib/windows-spawn.h
+++ b/lib/windows-spawn.h
@@ -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.