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

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

commit 55b5561fdbaba3dab106fac61ca205b408e99b2c
Author: Xiang Xiao <[email protected]>
AuthorDate: Wed Apr 20 20:53:05 2022 +0800

    sched/task: Implement execle and execve
    
    Signed-off-by: Xiang Xiao <[email protected]>
---
 binfmt/binfmt_exec.c                               |   8 +-
 include/nuttx/binfmt/binfmt.h                      |   6 +-
 include/sys/syscall_lookup.h                       |   2 +-
 include/unistd.h                                   |   3 +
 libs/libc/unistd/Make.defs                         |   2 +-
 .../task_execv.c => libs/libc/unistd/lib_execle.c  | 104 +++++++++++++++------
 .../task_execv.c => libs/libc/unistd/lib_execv.c   |  44 +--------
 sched/task/Make.defs                               |   2 +-
 sched/task/{task_execv.c => task_execve.c}         |  10 +-
 syscall/syscall.csv                                |   2 +-
 10 files changed, 100 insertions(+), 83 deletions(-)

diff --git a/binfmt/binfmt_exec.c b/binfmt/binfmt_exec.c
index 5b23488891..222a7de72b 100644
--- a/binfmt/binfmt_exec.c
+++ b/binfmt/binfmt_exec.c
@@ -212,6 +212,9 @@ errout:
  *              program.
  *   argv     - A pointer to an array of string arguments. The end of the
  *              array is indicated with a NULL entry.
+ *   envp     - An array of character pointers to null-terminated strings
+ *              that provide the environment for the new process image.
+ *              The environment array is terminated by a null pointer.
  *   exports  - The address of the start of the caller-provided symbol
  *              table. This symbol table contains the addresses of symbols
  *              exported by the caller and made available for linking the
@@ -226,11 +229,12 @@ errout:
  ****************************************************************************/
 
 int exec(FAR const char *filename, FAR char * const *argv,
-         FAR const struct symtab_s *exports, int nexports)
+         FAR char * const *envp, FAR const struct symtab_s *exports,
+         int nexports)
 {
   int ret;
 
-  ret = exec_spawn(filename, argv, NULL, exports, nexports, NULL);
+  ret = exec_spawn(filename, argv, envp, exports, nexports, NULL);
   if (ret < 0)
     {
       set_errno(-ret);
diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h
index 6ebeec446e..8c17d8f53b 100644
--- a/include/nuttx/binfmt/binfmt.h
+++ b/include/nuttx/binfmt/binfmt.h
@@ -309,6 +309,9 @@ int exec_module(FAR const struct binary_s *binp,
  *              program.
  *   argv     - A pointer to an array of string arguments. The end of the
  *              array is indicated with a NULL entry.
+ *   envp     - An array of character pointers to null-terminated strings
+ *              that provide the environment for the new process image.
+ *              The environment array is terminated by a null pointer.
  *   exports  - The address of the start of the caller-provided symbol
  *              table. This symbol table contains the addresses of symbols
  *              exported by the caller and made available for linking the
@@ -322,7 +325,8 @@ int exec_module(FAR const struct binary_s *binp,
  ****************************************************************************/
 
 int exec(FAR const char *filename, FAR char * const *argv,
-         FAR const struct symtab_s *exports, int nexports);
+         FAR char * const *envp, FAR const struct symtab_s *exports,
+         int nexports);
 
 /****************************************************************************
  * Name: exec_spawn
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index d183f0931e..201ea50846 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -151,7 +151,7 @@ SYSCALL_LOOKUP(up_assert,                  2)
 #endif
 #ifdef CONFIG_LIBC_EXECFUNCS
   SYSCALL_LOOKUP(posix_spawn,              6)
-  SYSCALL_LOOKUP(execv,                    2)
+  SYSCALL_LOOKUP(execve,                   3)
 #endif
 #endif
 
diff --git a/include/unistd.h b/include/unistd.h
index d2fd98827b..de35eb42dd 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -368,7 +368,10 @@ int     lchown(FAR const char *path, uid_t owner, gid_t 
group);
 
 #ifdef CONFIG_LIBC_EXECFUNCS
 int     execl(FAR const char *path, FAR const char *arg0, ...);
+int     execle(FAR const char *path, FAR const char *arg0, ...);
 int     execv(FAR const char *path, FAR char * const argv[]);
+int     execve(FAR const char *path, FAR char *const argv[],
+               FAR char *const envp[]);
 #endif
 
 /* Byte operations */
diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs
index 35e9e6d5ec..926f1c7b9c 100644
--- a/libs/libc/unistd/Make.defs
+++ b/libs/libc/unistd/Make.defs
@@ -39,7 +39,7 @@ CSRCS += lib_chdir.c lib_getcwd.c lib_restoredir.c
 endif
 
 ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
-CSRCS += lib_execl.c
+CSRCS += lib_execl.c lib_execle.c lib_execv.c
 endif
 
 ifneq ($(CONFIG_DISABLE_MOUNTPOINTS),y)
diff --git a/sched/task/task_execv.c b/libs/libc/unistd/lib_execle.c
similarity index 68%
copy from sched/task/task_execv.c
copy to libs/libc/unistd/lib_execle.c
index b4472e8289..5bbdea0e10 100644
--- a/sched/task/task_execv.c
+++ b/libs/libc/unistd/lib_execle.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/task/task_execv.c
+ * libs/libc/unistd/lib_execle.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,13 +24,12 @@
 
 #include <nuttx/config.h>
 
+#include <stdarg.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <debug.h>
 
-#include <nuttx/binfmt/binfmt.h>
-#include <nuttx/binfmt/symtab.h>
+#include "libc.h"
 
 #ifdef CONFIG_LIBC_EXECFUNCS
 
@@ -38,6 +37,16 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* This is an artificial limit to detect error conditions where an argv[]
+ * list is not properly terminated.
+ */
+
+#define MAX_EXECL_ARGS 256
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -47,7 +56,7 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: execv
+ * Name: execle
  *
  * Description:
  *   The standard 'exec' family of functions will replace the current process
@@ -75,15 +84,12 @@
  *   The non-standard binfmt function 'exec()' needs to have (1) a symbol
  *   table that provides the list of symbols exported by the base code, and
  *   (2) the number of symbols in that table.  This information is currently
- *   provided to 'exec()' from 'exec[l|v]()' via NuttX configuration
- *   settings:
+ *   provided to 'exec()' from 'exec[l|v]()' via NuttX configuration setting:
  *
- *     CONFIG_LIBC_EXECFUNCS          : Enable exec[l|v] support
- *     CONFIG_EXECFUNCS_HAVE_SYMTAB   : Defined if there is a pre-defined
- *                                      symbol table
- *     CONFIG_EXECFUNCS_SYMTAB_ARRAY  : Symbol table name used by exec[l|v]
- *     CONFIG_EXECFUNCS_NSYMBOLS_VAR  : Variable holding number of symbols
- *                                      in the table
+ *     CONFIG_LIBC_EXECFUNCS         : Enable exec[l|v] support
+ *     CONFIG_EXECFUNCS_SYMTAB_ARRAY : Symbol table name used by exec[l|v]
+ *     CONFIG_EXECFUNCS_NSYMBOLS_VAR : Variable holding number of symbols in
+ *                                     the table
  *
  *   As a result of the above, the current implementations of 'execl()' and
  *   'execv()' suffer from some incompatibilities that may or may not be
@@ -98,8 +104,8 @@
  *     is defined in the configuration, then this may be a relative path
  *     from the current working directory.  Otherwise, path must be the
  *     absolute path to the program.
- *   argv - A pointer to an array of string arguments.  The end of the
- *     array is indicated with a NULL entry.
+ *   ... - A list of the string arguments to be recevied by the
+ *     program.  Zero indicates the end of the list.
  *
  * Returned Value:
  *   This function does not return on success.  On failure, it will return
@@ -107,35 +113,71 @@
  *
  ****************************************************************************/
 
-int execv(FAR const char *path, FAR char * const argv[])
+int execle(FAR const char *path, FAR const char *arg0, ...)
 {
-  FAR const struct symtab_s *symtab;
-  int nsymbols;
+  FAR char *arg = (FAR char *)arg0;
+  FAR char **argv;
+  FAR char **envp;
+  size_t nargs;
+  va_list ap;
+  int argc;
   int ret;
 
-  /* Get the current symbol table selection */
+  /* Count the number of arguments */
+
+  va_start(ap, arg0);
+  nargs = 0;
 
-  exec_getsymtab(&symtab, &nsymbols);
+  while (arg != NULL)
+    {
+      /* Yes.. increment the number of arguments.  Here is a sanity
+       * check to prevent running away with an unterminated argv[] list.
+       * MAX_EXECL_ARGS should be sufficiently large that this never
+       * happens in normal usage.
+       */
+
+      if (++nargs > MAX_EXECL_ARGS)
+        {
+          set_errno(E2BIG);
+          va_end(ap);
+          return ERROR;
+        }
+
+      arg = va_arg(ap, FAR char *);
+    }
 
-  /* Start the task */
+  envp = va_arg(ap, FAR char **);
+  va_end(ap);
 
-  ret = exec(path, (FAR char * const *)argv, symtab, nsymbols);
-  if (ret < 0)
+  /* Allocate a temporary argv[] array */
+
+  argv = (FAR char **)lib_malloc((nargs + 1) * sizeof(FAR char *));
+  if (argv == NULL)
     {
-      serr("ERROR: exec failed: %d\n", get_errno());
+      set_errno(ENOMEM);
       return ERROR;
     }
 
-  /* Then exit */
+  argv[0] = (FAR char *)arg0;
+
+  /* Collect the arguments into the argv[] array */
+
+  va_start(ap, arg0);
+  for (argc = 1; argc <= nargs; argc++)
+    {
+      argv[argc] = va_arg(ap, FAR char *);
+    }
+
+  va_end(ap);
+
+  /* Then let execv() do the real work */
 
-  exit(0);
+  ret = execv(path, argv, envp);
 
-  /* We should not get here, but might be needed by some compilers.  Other,
-   * smarter compilers might complain that this code is unreachable.  You
-   * just can't win.
-   */
+  /* Free the allocated argv[] list */
 
-  return ERROR;
+  lib_free(argv);
+  return ret;
 }
 
 #endif /* CONFIG_LIBC_EXECFUNCS */
diff --git a/sched/task/task_execv.c b/libs/libc/unistd/lib_execv.c
similarity index 80%
copy from sched/task/task_execv.c
copy to libs/libc/unistd/lib_execv.c
index b4472e8289..59f0bc3491 100644
--- a/sched/task/task_execv.c
+++ b/libs/libc/unistd/lib_execv.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/task/task_execv.c
+ * libs/libc/unistd/lib_execv.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,24 +24,10 @@
 
 #include <nuttx/config.h>
 
-#include <stdlib.h>
 #include <unistd.h>
-#include <errno.h>
-#include <debug.h>
-
-#include <nuttx/binfmt/binfmt.h>
-#include <nuttx/binfmt/symtab.h>
 
 #ifdef CONFIG_LIBC_EXECFUNCS
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -109,33 +95,7 @@
 
 int execv(FAR const char *path, FAR char * const argv[])
 {
-  FAR const struct symtab_s *symtab;
-  int nsymbols;
-  int ret;
-
-  /* Get the current symbol table selection */
-
-  exec_getsymtab(&symtab, &nsymbols);
-
-  /* Start the task */
-
-  ret = exec(path, (FAR char * const *)argv, symtab, nsymbols);
-  if (ret < 0)
-    {
-      serr("ERROR: exec failed: %d\n", get_errno());
-      return ERROR;
-    }
-
-  /* Then exit */
-
-  exit(0);
-
-  /* We should not get here, but might be needed by some compilers.  Other,
-   * smarter compilers might complain that this code is unreachable.  You
-   * just can't win.
-   */
-
-  return ERROR;
+  return execve(path, argv, NULL);
 }
 
 #endif /* CONFIG_LIBC_EXECFUNCS */
diff --git a/sched/task/Make.defs b/sched/task/Make.defs
index 85b893e642..406ea35a0b 100644
--- a/sched/task/Make.defs
+++ b/sched/task/Make.defs
@@ -45,7 +45,7 @@ endif
 
 ifneq ($(CONFIG_BINFMT_DISABLE),y)
 ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
-CSRCS += task_execv.c task_posixspawn.c
+CSRCS += task_execve.c task_posixspawn.c
 endif
 endif
 
diff --git a/sched/task/task_execv.c b/sched/task/task_execve.c
similarity index 93%
rename from sched/task/task_execv.c
rename to sched/task/task_execve.c
index b4472e8289..555271effe 100644
--- a/sched/task/task_execv.c
+++ b/sched/task/task_execve.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/task/task_execv.c
+ * sched/task/task_execve.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -100,6 +100,9 @@
  *     absolute path to the program.
  *   argv - A pointer to an array of string arguments.  The end of the
  *     array is indicated with a NULL entry.
+ *   envp - An array of character pointers to null-terminated strings that
+ *     provide the environment for the new process image. The environment
+ *     array is terminated by a null pointer.
  *
  * Returned Value:
  *   This function does not return on success.  On failure, it will return
@@ -107,7 +110,8 @@
  *
  ****************************************************************************/
 
-int execv(FAR const char *path, FAR char * const argv[])
+int execve(FAR const char *path, FAR char * const argv[],
+           FAR char *const envp[])
 {
   FAR const struct symtab_s *symtab;
   int nsymbols;
@@ -119,7 +123,7 @@ int execv(FAR const char *path, FAR char * const argv[])
 
   /* Start the task */
 
-  ret = exec(path, (FAR char * const *)argv, symtab, nsymbols);
+  ret = exec(path, argv, envp, symtab, nsymbols);
   if (ret < 0)
     {
       serr("ERROR: exec failed: %d\n", get_errno());
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index 0705de96a2..2b0b8148b0 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -24,7 +24,7 @@
 "dup2","unistd.h","","int","int","int"
 "eventfd","sys/eventfd.h","defined(CONFIG_EVENT_FD)","int","unsigned int","int"
 "exec","nuttx/binfmt/binfmt.h","!defined(CONFIG_BINFMT_DISABLE) && 
!defined(CONFIG_BUILD_KERNEL)","int","FAR const char *","FAR char * const 
*","FAR const struct symtab_s *","int"
-"execv","unistd.h","!defined(CONFIG_BINFMT_DISABLE) && 
defined(CONFIG_LIBC_EXECFUNCS)","int","FAR const char *","FAR char * const 
[]|FAR char * const *"
+"execve","unistd.h","!defined(CONFIG_BINFMT_DISABLE) && 
defined(CONFIG_LIBC_EXECFUNCS)","int","FAR const char *","FAR char * const 
[]|FAR char * const *","FAR char * const []|FAR char * const *"
 "exit","stdlib.h","","noreturn","int"
 "fchmod","sys/stat.h","","int","int","mode_t"
 "fchown","unistd.h","","int","int","uid_t","gid_t"

Reply via email to