This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 1f4f75294b1aa578d0e779dafb9099873aebedcd
Author: Marco Casaroli <[email protected]>
AuthorDate: Fri Oct 30 11:59:09 2026 +0100

    libs/libc: Put the string of putenv() into the environment, as POSIX does.
    
    POSIX declares "int putenv(char *string)": the string itself becomes
    part of the environment, so a later change to the string changes the
    environment.  <stdlib.h> and libc had "const char *", and putenv()
    copied the string.  A program that declares putenv() itself with the
    POSIX prototype failed to compile with conflicting types, and a change
    to the string after the call did not change the environment.
    
    Use "char *" in <stdlib.h>, in the function and in libc.csv.  putenv()
    now puts the string itself into the array of libc, in the place of the
    old name=value pair or at the end.  libc does not free it:
    env_removevar() and env_release() free only the blocks of env_alloc().
    "NAME=" now sets NAME to an empty value, as in POSIX; before, it removed
    NAME.
    
    env_setvar() was only there so that putenv() could give the name part
    of its string to setenv().  Move it back into setenv().
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 include/stdlib.h               |   2 +-
 libs/libc/environ/env_putenv.c |  40 +++++++++++--
 libs/libc/environ/env_setenv.c | 125 ++++++++++++++++++-----------------------
 libs/libc/environ/environ.h    |  22 --------
 libs/libc/libc.csv             |   2 +-
 5 files changed, 92 insertions(+), 99 deletions(-)

diff --git a/include/stdlib.h b/include/stdlib.h
index e5a18f26585..0782f0b3803 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -182,7 +182,7 @@ int       getloadavg(FAR double loadavg[], int nelem);
 FAR char ***get_environ_ptr(void);
 FAR char *getenv(FAR const char *name);
 FAR char *secure_getenv(FAR const char *name);
-int       putenv(FAR const char *string);
+int       putenv(FAR char *string);
 int       clearenv(void);
 int       setenv(FAR const char *name, FAR const char *value, int overwrite);
 int       unsetenv(FAR const char *name);
diff --git a/libs/libc/environ/env_putenv.c b/libs/libc/environ/env_putenv.c
index 579119bc7c4..acc8c881997 100644
--- a/libs/libc/environ/env_putenv.c
+++ b/libs/libc/environ/env_putenv.c
@@ -24,9 +24,11 @@
  * Included Files
  ****************************************************************************/
 
+#include <assert.h>
 #include <string.h>
 #include <errno.h>
 
+#include <nuttx/mutex.h>
 #include <nuttx/tls.h>
 
 #include "environ.h"
@@ -46,6 +48,10 @@
  *   name does exist, then the value of name in the environment is changed to
  *   value.
  *
+ *   As POSIX requires, the string itself becomes part of the environment:
+ *   a later change to the string changes the environment.  libc does not
+ *   copy or free it.
+ *
  * Input Parameters:
  *   name=value string describing the environment setting to add/modify
  *
@@ -57,9 +63,11 @@
  *
  ****************************************************************************/
 
-int putenv(FAR const char *string)
+int putenv(FAR char *string)
 {
-  FAR const char *pequal;
+  FAR struct task_info_s *info = task_get_info();
+  FAR char *pequal;
+  ssize_t idx;
   int ret;
 
   /* Verify that a string was passed */
@@ -78,9 +86,33 @@ int putenv(FAR const char *string)
       return OK;
     }
 
-  /* Then let env_setvar do all of the work */
+  DEBUGASSERT(info != NULL);
+
+  nxrmutex_lock(&info->ta_lock);
+
+  /* environ must be an array of libc with room for one more entry */
+
+  ret = env_reserve(info, 1);
+  if (ret >= 0)
+    {
+      /* Put the string itself in the place of the old name=value pair, or
+       * at the end.
+       */
+
+      idx = env_findvar(info, string, pequal - string);
+      if (idx >= 0)
+        {
+          info->ta_envp[idx] = string;
+        }
+      else
+        {
+          info->ta_envp[info->ta_envc++] = string;
+          info->ta_envp[info->ta_envc]   = NULL;
+        }
+    }
+
+  nxrmutex_unlock(&info->ta_lock);
 
-  ret = env_setvar(string, pequal - string, pequal + 1, TRUE);
   if (ret < 0)
     {
       set_errno(-ret);
diff --git a/libs/libc/environ/env_setenv.c b/libs/libc/environ/env_setenv.c
index edf4619587b..6294ef28836 100644
--- a/libs/libc/environ/env_setenv.c
+++ b/libs/libc/environ/env_setenv.c
@@ -39,20 +39,70 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: env_setvar
+ * Name: setenv
+ *
+ * Description:
+ *   The setenv() function adds the variable name to the environment with the
+ *   specified 'value' if the variable 'name" does not exist. If the 'name'
+ *   does exist in the environment, then its value is changed to 'value' if
+ *   'overwrite' is non-zero; if 'overwrite' is zero, then the value of name
+ *   unaltered.
+ *
+ * Input Parameters:
+ *   name - The name of the variable to change
+ *   value - The new value of the variable
+ *   overwrite - Replace any existing value if non-zero.
+ *
+ * Returned Value:
+ *   Zero on success
+ *
+ * Assumptions:
+ *   Not called from an interrupt handler
+ *
  ****************************************************************************/
 
-int env_setvar(FAR const char *name, size_t namelen,
-               FAR const char *value, int overwrite)
+int setenv(FAR const char *name, FAR const char *value, int overwrite)
 {
   FAR struct task_info_s *info = task_get_info();
   FAR char *pvar;
   ssize_t idx;
+  size_t namelen;
   size_t varlen;
   int ret;
 
+  /* Verify input parameter */
+
+  if (!name)
+    {
+      set_errno(EINVAL);
+      return ERROR;
+    }
+
+  /* if no value is provided, then this is the same as unsetenv (unless
+   * overwrite is false)
+   */
+
+  if (!value || *value == '\0')
+    {
+      /* If overwrite is set then this is the same as unsetenv */
+
+      if (overwrite)
+        {
+          return unsetenv(name);
+        }
+      else
+        {
+          /* Otherwise, it is a request to remove a variable without
+           * altering it?
+           */
+
+          return OK;
+        }
+    }
+
   DEBUGASSERT(info != NULL);
 
+  namelen = strlen(name);
   nxrmutex_lock(&info->ta_lock);
 
   /* environ must be an array of libc with room for one more entry */
@@ -82,13 +132,6 @@ int env_setvar(FAR const char *name, size_t namelen,
       env_removevar(info, idx);
     }
 
-  /* An empty value removes the variable */
-
-  if (*value == '\0')
-    {
-      goto out;
-    }
-
   /* Get the size of the new name=value string.
    * The +2 is for the '=' and for null terminator
    */
@@ -104,74 +147,14 @@ int env_setvar(FAR const char *name, size_t namelen,
 
   /* Now, put the new name=value string into the environment */
 
-  snprintf(pvar, varlen, "%.*s=%s", (int)namelen, name, value);
+  snprintf(pvar, varlen, "%s=%s", name, value);
 
   info->ta_envp[info->ta_envc++] = pvar;
   info->ta_envp[info->ta_envc]   = NULL;
 
 out:
   nxrmutex_unlock(&info->ta_lock);
-  return ret;
-}
-
-/****************************************************************************
- * Name: setenv
- *
- * Description:
- *   The setenv() function adds the variable name to the environment with the
- *   specified 'value' if the variable 'name" does not exist. If the 'name'
- *   does exist in the environment, then its value is changed to 'value' if
- *   'overwrite' is non-zero; if 'overwrite' is zero, then the value of name
- *   unaltered.
- *
- * Input Parameters:
- *   name - The name of the variable to change
- *   value - The new value of the variable
- *   overwrite - Replace any existing value if non-zero.
- *
- * Returned Value:
- *   Zero on success
- *
- * Assumptions:
- *   Not called from an interrupt handler
- *
- ****************************************************************************/
-
-int setenv(FAR const char *name, FAR const char *value, int overwrite)
-{
-  int ret;
-
-  /* Verify input parameter */
-
-  if (!name)
-    {
-      set_errno(EINVAL);
-      return ERROR;
-    }
-
-  /* if no value is provided, then this is the same as unsetenv (unless
-   * overwrite is false)
-   */
-
-  if (!value || *value == '\0')
-    {
-      /* If overwrite is set then this is the same as unsetenv */
-
-      if (overwrite)
-        {
-          return unsetenv(name);
-        }
-      else
-        {
-          /* Otherwise, it is a request to remove a variable without
-           * altering it?
-           */
-
-          return OK;
-        }
-    }
 
-  ret = env_setvar(name, strlen(name), value, overwrite);
   if (ret < 0)
     {
       set_errno(-ret);
diff --git a/libs/libc/environ/environ.h b/libs/libc/environ/environ.h
index c51d44c2871..8a3f7d85b50 100644
--- a/libs/libc/environ/environ.h
+++ b/libs/libc/environ/environ.h
@@ -78,28 +78,6 @@ extern "C"
 ssize_t env_findvar(FAR struct task_info_s *info, FAR const char *pname,
                     size_t namelen);
 
-/****************************************************************************
- * Name: env_setvar
- *
- * Description:
- *   setenv() with the length of the name, so that putenv() can pass the
- *   name part of its string without a copy.  An empty value removes the
- *   variable, as in setenv().
- *
- * Input Parameters:
- *   name      - The name of the variable.  It needs no terminating NUL.
- *   namelen   - The length of the name.
- *   value     - The new value of the variable.
- *   overwrite - Replace any existing value if non-zero.
- *
- * Returned Value:
- *   Zero (OK) on success; a negated errno value on failure.
- *
- ****************************************************************************/
-
-int env_setvar(FAR const char *name, size_t namelen,
-               FAR const char *value, int overwrite);
-
 /****************************************************************************
  * Name: env_alloc
  *
diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv
index 4c7eac03c32..73d2ebd5751 100644
--- a/libs/libc/libc.csv
+++ b/libs/libc/libc.csv
@@ -269,7 +269,7 @@
 
"pthread_setname_np","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","const
 char *"
 "pthread_setspecific","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && 
CONFIG_TLS_NELEM > 0","int","pthread_key_t","FAR const void *"
 "pthread_yield","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","void"
-"putenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *"
+"putenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR char *"
 "puts","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR const IPTR char *"
 "putwc","wchar.h","defined(CONFIG_FILE_STREAM)","wint_t","wchar_t","FAR FILE *"
 
"putwc_unlocked","wchar.h","defined(CONFIG_FILE_STREAM)","wint_t","wchar_t","FAR
 FILE *"

Reply via email to