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"
