>From d1ae9c694e5418850c71884ccd22a293d9b3e29b Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 24 Dec 2020 22:18:18 +0100 Subject: [PATCH 4/7] 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. --- ChangeLog | 8 +++++ lib/windows-spawn.c | 96 +++++++++++++++++++++++++++++++++-------------------- lib/windows-spawn.h | 7 ++++ 3 files changed, 75 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index ba8a7d9..d140497 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2020-12-24 Bruno Haible + 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 + 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 cc29196..b0a6dda 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 cb9d3fa..90f45e1 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. -- 2.7.4