summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-17 18:32:13 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-17 18:32:13 +0000
commit68453d683cb221e509258d71bddf207a330a1656 (patch)
tree677aa6a3af5241be04684f2d02eb0e719234b68c /apps
parentd8d9cc8a96cdc2219af7bec8142e7633779fd685 (diff)
downloadnuttx-68453d683cb221e509258d71bddf207a330a1656.tar.gz
nuttx-68453d683cb221e509258d71bddf207a330a1656.tar.bz2
nuttx-68453d683cb221e509258d71bddf207a330a1656.zip
NSH will now run files from the file system; Add logic to unload and clean-up after running a task from a file system; Extensions to builtin apps from Mike Smith
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5529 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps')
-rw-r--r--apps/ChangeLog.txt3
-rw-r--r--apps/builtin/builtin_list.c79
-rw-r--r--apps/examples/nsh/nsh_main.c38
-rw-r--r--apps/nshlib/Kconfig11
-rw-r--r--apps/nshlib/Makefile4
-rw-r--r--apps/nshlib/nsh.h5
-rw-r--r--apps/nshlib/nsh_builtin.c27
-rw-r--r--apps/nshlib/nsh_fileapps.c298
-rw-r--r--apps/nshlib/nsh_parse.c37
9 files changed, 494 insertions, 8 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 14eb78950..ba8dec613 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -485,3 +485,6 @@
argument is now optional. Many files systems do not need
a source and it is really stupid to have to enter a bogus
source parameter.
+ * apps/nshlib/nsh_fileapp.c: Add the ability to execute a file
+ from a file system using posix_spawn().
+ * apps/builtin/: Extensions from Mike Smith.
diff --git a/apps/builtin/builtin_list.c b/apps/builtin/builtin_list.c
new file mode 100644
index 000000000..a5556bf54
--- /dev/null
+++ b/apps/builtin/builtin_list.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * apps/builtin/builtin_list.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Authors: Uros Platise <uros.platise@isotel.eu>
+ * Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#include "builtin_proto.h"
+
+const struct builtin_s g_builtins[] =
+{
+# include "builtin_list.h"
+ { NULL, 0, 0, 0 }
+};
+
+const int g_builtin_count = sizeof(g_builtins) / sizeof(g_builtins[0]);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
diff --git a/apps/examples/nsh/nsh_main.c b/apps/examples/nsh/nsh_main.c
index 97792cb2a..d9bfc2018 100644
--- a/apps/examples/nsh/nsh_main.c
+++ b/apps/examples/nsh/nsh_main.c
@@ -46,6 +46,12 @@
#include <errno.h>
#include <nuttx/arch.h>
+#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
+#include <nuttx/binfmt/builtin.h>
+#endif
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+#include <nuttx/binfmt/symtab.h>
+#endif
#include <apps/nsh.h>
@@ -75,6 +81,21 @@
* Public Data
****************************************************************************/
+/* If posix_spawn() is enabled as required for CONFIG_NSH_FILE_APPS, then
+ * a symbol table is needed by the internals of posix_spawn(). The symbol
+ * table is needed to support ELF and NXFLAT binaries to dynamically link to
+ * the base code. However, if only the BINFS file system is supported, then
+ * no Makefile is needed.
+ *
+ * This is a kludge to plug the missing file system in the case where BINFS
+ * is used. REVISIT: This will, of course, be in the way if you want to
+ * support ELF or NXFLAT binaries!
+ */
+
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+const struct symtab_s CONFIG_EXECFUNCS_SYMTAB[1];
+#endif
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -98,6 +119,23 @@ int nsh_main(int argc, char *argv[])
up_cxxinitialize();
#endif
+ /* Make sure that we are using our symbol take */
+
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+ exec_setsymtab(CONFIG_EXECFUNCS_SYMTAB, 0);
+#endif
+
+ /* Register the BINFS file system */
+
+#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
+ ret = builtin_initialize();
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR: builtin_initialize failed: %d\n", ret);
+ exitval = 1;
+ }
+#endif
+
/* Initialize the NSH library */
nsh_initialize();
diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig
index e60e9c480..f6a5aa045 100644
--- a/apps/nshlib/Kconfig
+++ b/apps/nshlib/Kconfig
@@ -14,7 +14,7 @@ config NSH_LIBRARY
if NSH_LIBRARY
config NSH_BUILTIN_APPS
bool "Enable built-in applications"
- default y
+ default n
depends on BUILTIN
---help---
Support external registered, "built-in" applications that can be
@@ -22,6 +22,15 @@ config NSH_BUILTIN_APPS
more information). This options requires support for builtin
applications (BUILTIN).
+config NSH_FILE_APPS
+ bool "Enable execution of program files"
+ default n
+ depends on LIBC_EXECFUNCS
+ ---help---
+ Support execution of program files residing within a file
+ system. This options requires support for the posix_spawn()
+ interface (LIBC_EXECFUNCS).
+
menu "Disable Individual commands"
config NSH_DISABLE_BASE64DEC
diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile
index 5c5269685..948f43d52 100644
--- a/apps/nshlib/Makefile
+++ b/apps/nshlib/Makefile
@@ -47,6 +47,10 @@ ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
CSRCS += nsh_builtin.c
endif
+ifeq ($(CONFIG_NSH_FILE_APPS),y)
+CSRCS += nsh_fileapps.c
+endif
+
ifeq ($(CONFIG_NSH_ROMFSETC),y)
CSRCS += nsh_romfsetc.c
endif
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index 253a803f8..64099a8df 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -495,6 +495,11 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
FAR char **argv, FAR const char *redirfile, int oflags);
#endif
+#ifdef CONFIG_NSH_FILE_APPS
+int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags);
+#endif
+
/* Working directory support */
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
diff --git a/apps/nshlib/nsh_builtin.c b/apps/nshlib/nsh_builtin.c
index ba39e8dfe..2d23ca8d8 100644
--- a/apps/nshlib/nsh_builtin.c
+++ b/apps/nshlib/nsh_builtin.c
@@ -51,6 +51,7 @@
#endif
#include <stdbool.h>
+#include <signal.h>
#include <errno.h>
#include <string.h>
@@ -129,20 +130,34 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
ret = exec_builtin(cmd, (FAR const char **)argv, redirfile, oflags);
if (ret >= 0)
{
- /* The application was successfully started (but still blocked because
- * the scheduler is locked). If the application was not backgrounded,
- * then we need to wait here for the application to exit. These really
- * only works works with the following options:
+ /* The application was successfully started with pre-emption disabled.
+ * In the simplest cases, the application will not have run because the
+ * the scheduler is locked. but in the case were I/O redirected, a
+ * proxy task ran and, as result, so may have the application.
+ *
+ * If the application did not run and if the application was not
+ * backgrounded, then we need to wait here for the application to
+ * exit. This only works works with the following options:
*
* - CONFIG_NSH_DISABLEBG - Do not run commands in background
* - CONFIG_SCHED_WAITPID - Required to run external commands in
* foreground
- *
- * These concepts do not apply cleanly to the external applications.
*/
#ifdef CONFIG_SCHED_WAITPID
+ /* Check if the application is still running */
+
+ if (kill(ret, 0) < 0)
+ {
+ /* It is not running. In this case, we have no idea if the
+ * application ran successfully or not. Let's assume that is
+ * did.
+ */
+
+ return 0;
+ }
+
/* CONFIG_SCHED_WAITPID is selected, so we may run the command in
* foreground unless we were specifically requested to run the command
* in background (and running commands in background is enabled).
diff --git a/apps/nshlib/nsh_fileapps.c b/apps/nshlib/nsh_fileapps.c
new file mode 100644
index 000000000..7f9f58e53
--- /dev/null
+++ b/apps/nshlib/nsh_fileapps.c
@@ -0,0 +1,298 @@
+/****************************************************************************
+ * apps/nshlib/nsh_fileapps.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_SCHED_WAITPID
+# include <sys/wait.h>
+#endif
+
+#include <stdbool.h>
+#include <signal.h>
+#include <spawn.h>
+#include <errno.h>
+#include <string.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#ifdef CONFIG_NSH_FILE_APPS
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_fileapp
+ *
+ * Description:
+ * Attempt to execute the application task whose name is 'cmd'
+ *
+ * Returned Value:
+ * <0 If exec_builtin() fails, then the negated errno value
+ * is returned.
+ * -1 (ERROR) if the application task corresponding to 'cmd' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'cmd' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ ****************************************************************************/
+
+int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags)
+{
+ posix_spawn_file_actions_t file_actions;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int ret;
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ /* posix_spawn_file_actions_init returns a positive errno value on
+ * failure.
+ */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "posix_spawn_file_actions_init",
+ NSH_ERRNO_OF(ret));
+ goto errout;
+ }
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ /* posix_spawnattr_init returns a positive errno value on failure. */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "posix_spawnattr_init",
+ NSH_ERRNO);
+ goto errout_with_actions;
+ }
+
+ /* Handle re-direction of output */
+
+ if (redirfile)
+ {
+ ret = posix_spawn_file_actions_addopen(&file_actions, 1, redirfile,
+ oflags, 0644);
+ if (ret != 0)
+ {
+ /* posix_spawn_file_actions_addopen returns a positive errno
+ * value on failure.
+ */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd,
+ "posix_spawn_file_actions_addopen",
+ NSH_ERRNO);
+ goto errout_with_attrs;
+ }
+ }
+
+ /* Lock the scheduler to prevent the application from running until the
+ * waitpid() has been called.
+ */
+
+ sched_lock();
+
+ /* Execute the program. posix_spawnp returns a positive errno value on
+ * failure.
+ */
+
+ ret = posix_spawnp(&pid, cmd, &file_actions, &attr, &argv[1], NULL);
+ if (ret == OK)
+ {
+ /* The application was successfully started with pre-emption disabled.
+ * In the simplest cases, the application will not have run because the
+ * the scheduler is locked. but in the case were I/O redirected, a
+ * proxy task ran and, as result, so may have the application.
+ *
+ * If the application did not run and if the application was not
+ * backgrounded, then we need to wait here for the application to
+ * exit. This only works works with the following options:
+ *
+ * - CONFIG_NSH_DISABLEBG - Do not run commands in background
+ * - CONFIG_SCHED_WAITPID - Required to run external commands in
+ * foreground
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ /* Check if the application is still running */
+
+ if (kill(ret, 0) < 0)
+ {
+ /* It is not running. In this case, we have no idea if the
+ * application ran successfully or not. Let's assume that is
+ * did.
+ */
+
+ return 0;
+ }
+
+ /* CONFIG_SCHED_WAITPID is selected, so we may run the command in
+ * foreground unless we were specifically requested to run the command
+ * in background (and running commands in background is enabled).
+ */
+
+# ifndef CONFIG_NSH_DISABLEBG
+ if (vtbl->np.np_bg == false)
+# endif /* CONFIG_NSH_DISABLEBG */
+ {
+ int rc = 0;
+
+ /* Wait for the application to exit. Since we have locked the
+ * scheduler above, we know that the application has not yet
+ * started and there is no possibility that it has already exited.
+ * The scheduler will be unlocked while waitpid is waiting and the
+ * application will be able to run.
+ */
+
+ ret = waitpid(pid, &rc, 0);
+ if (ret >= 0)
+ {
+ /* We can't return the exact status (nsh has nowhere to put it)
+ * so just pass back zero/nonzero in a fashion that doesn't look
+ * like an error.
+ */
+
+ ret = (rc == 0) ? OK : 1;
+
+ /* TODO: Set the environment variable '?' to a string corresponding
+ * to WEXITSTATUS(rc) so that $? will expand to the exit status of
+ * the most recently executed task.
+ */
+ }
+ }
+# ifndef CONFIG_NSH_DISABLEBG
+ else
+# endif /* CONFIG_NSH_DISABLEBG */
+#endif /* CONFIG_SCHED_WAITPID */
+
+ /* We get here if either:
+ *
+ * - CONFIG_SCHED_WAITPID is not selected meaning that all commands
+ * have to be run in background, or
+ * - CONFIG_SCHED_WAITPID and CONFIG_NSH_DISABLEBG are both selected, but the
+ * user requested to run the command in background.
+ *
+ * NOTE that the case of a) CONFIG_SCHED_WAITPID is not selected and
+ * b) CONFIG_NSH_DISABLEBG selected cannot be supported. In that event, all
+ * commands will have to run in background. The waitpid() API must be
+ * available to support running the command in foreground.
+ */
+
+#if !defined(CONFIG_SCHED_WAITPID) || !defined(CONFIG_NSH_DISABLEBG)
+ {
+ struct sched_param param;
+ sched_getparam(ret, &param);
+ nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
+
+ /* Backgrounded commands always 'succeed' as long as we can start
+ * them.
+ */
+
+ ret = OK;
+ }
+#endif /* !CONFIG_SCHED_WAITPID || !CONFIG_NSH_DISABLEBG */
+ }
+
+ sched_unlock();
+
+ /* Free attibutes and file actions. Ignoring return values in the case
+ * of an error.
+ */
+
+errout_with_actions:
+ (void)posix_spawn_file_actions_destroy(&file_actions);
+
+errout_with_attrs:
+ (void)posix_spawnattr_destroy(&attr);
+
+errout:
+ /* Most posix_spawn interfaces return a positive errno value on failure
+ * and do not set the errno variable.
+ */
+
+ if (ret > 0)
+ {
+ /* Set the errno value and return -1 */
+
+ set_errno(ret);
+ ret = ERROR;
+ }
+ else if (ret < 0)
+ {
+ /* Return -1 on failure. errno should have been set. */
+
+ ret = ERROR;
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NSH_FILE_APPS */
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index ef4125a63..f679d9b32 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -61,6 +61,7 @@
#ifdef CONFIG_NSH_BUILTIN_APPS
# include <nuttx/binfmt/builtin.h>
#endif
+
#include <apps/nsh.h>
#include "nsh.h"
@@ -1398,6 +1399,40 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
nsh_output(vtbl, g_fmttoomanyargs, cmd);
}
+ /* Does this command correspond to an application filename?
+ * nsh_fileapp() returns:
+ *
+ * -1 (ERROR) if the application task corresponding to 'argv[0]' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'argv[0]' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ * Note the priority if not effected by nice-ness.
+ */
+
+#ifdef CONFIG_NSH_FILE_APPS
+ ret = nsh_fileapp(vtbl, argv[0], argv, redirfile, oflags);
+ if (ret >= 0)
+ {
+ /* nsh_fileapp() returned 0 or 1. This means that the builtin
+ * command was successfully started (although it may not have ran
+ * successfully). So certainly it is not an NSH command.
+ */
+
+ return nsh_saveresult(vtbl, ret != OK);
+ }
+
+ /* No, not a built in command (or, at least, we were unable to start a
+ * builtin command of that name). Treat it like an NSH command.
+ */
+
+#endif
+
/* Does this command correspond to a builtin command?
* nsh_builtin() returns:
*
@@ -1414,7 +1449,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
* Note the priority if not effected by nice-ness.
*/
-#ifdef CONFIG_NSH_BUILTIN_APPS
+#if defined(CONFIG_NSH_BUILTIN_APPS) && (!defined(CONFIG_NSH_FILE_APPS) || !defined(CONFIG_FS_BINFS))
ret = nsh_builtin(vtbl, argv[0], argv, redirfile, oflags);
if (ret >= 0)
{