apps/system/system and popen: Adapt so that these can be used in the KERNEL build mode. In this case, simply replace task_spawn() with posix_spawn(). This depends on the existence of some environment where /bin/sh exists and can be used to execute one NSH command. For the case of system(), this change was more complete because it previously used task_create(). Now it uses either task_spawn() or posix_spawn(), depending upon the configuration.

This commit is contained in:
Gregory Nutt 2018-08-18 07:54:53 -06:00
parent 08263367bc
commit e3e911555a
4 changed files with 128 additions and 23 deletions

View File

@ -7,7 +7,7 @@ config SYSTEM_POPEN
bool "popen()/pclose() Functions"
default n
select SCHED_WAITPID
depends on NSH_LIBRARY && !BUILD_KERNEL
depends on NSH_LIBRARY
---help---
Enable support for the popen() and pclose() interfaces.
This will support execution of NSH commands from C code with
@ -15,6 +15,15 @@ config SYSTEM_POPEN
if SYSTEM_POPEN
config SYSTEM_POPEN_SHPATH
string "Path to shell command"
default "/bin/sh"
depends on BUILD_KERNEL
---help---
This is the full path to the program in a mounted file system that
implements the system() command. That is, a program that starts the
NSH shell, executes one command (in argv[1]), then exits.
config SYSTEM_POPEN_STACKSIZE
int "Shell stack size"
default 2048 if !ARCH_SIM

View File

@ -47,6 +47,7 @@
#include <sched.h>
#include <spawn.h>
#include <assert.h>
#include <debug.h>
#include "nshlib/nshlib.h"
@ -188,7 +189,7 @@ FILE *popen(FAR const char *command, FAR const char *mode)
goto errout_with_pipe;
}
/* Initialize attributes for task_spawn(). */
/* Initialize attributes for task_spawn() (or posix_spawn()). */
errcode = posix_spawnattr_init(&attr);
if (errcode != 0)
@ -202,7 +203,7 @@ FILE *popen(FAR const char *command, FAR const char *mode)
goto errout_with_attrs;
}
/* Set the correct task size and priority */
/* Set the correct stack size and priority */
param.sched_priority = CONFIG_SYSTEM_POPEN_PRIORITY;
errcode = posix_spawnattr_setschedparam(&attr, &param);
@ -229,8 +230,8 @@ FILE *popen(FAR const char *command, FAR const char *mode)
}
errcode = posix_spawnattr_setflags(&attr,
POSIX_SPAWN_SETSCHEDPARAM |
POSIX_SPAWN_SETSCHEDULER);
POSIX_SPAWN_SETSCHEDPARAM |
POSIX_SPAWN_SETSCHEDULER);
if (errcode != 0)
{
goto errout_with_actions;
@ -253,17 +254,25 @@ FILE *popen(FAR const char *command, FAR const char *mode)
goto errout_with_actions;
}
/* Call task_spawn(), re-directing stdin or stdout appropriately */
/* Start the built-in */
/* Call task_spawn() (or posix_spawn), re-directing stdin or stdout
* appropriately.
*/
argv[0] = (FAR char *)command;
argv[1] = NULL;
#ifdef CONFIG_BUILD_KERNEL
errcode = posix_spawn(&container->shell, CONFIG_SYSTEM_POPEN_SHPATH,
&file_actions, &attr, argv,
(FAR char * const *)NULL);
#else
errcode = task_spawn(&container->shell, "popen", nsh_system, &file_actions,
&attr, argv, (FAR char * const *)NULL);
#endif
if (errcode != 0)
{
serr("ERROR: task_spawn failed: %d\n", result);
serr("ERROR: Spawn failed: %d\n", result);
goto errout_with_actions;
}
@ -389,6 +398,6 @@ int pclose(FILE *stream)
return status;
#else
return EXIT_SUCCESS;
return OK;
#endif
}

View File

@ -14,6 +14,15 @@ config SYSTEM_SYSTEM
if SYSTEM_SYSTEM
config SYSTEM_SYSTEM_SHPATH
string "Path to shell command"
default "/bin/sh"
depends on BUILD_KERNEL
---help---
This is the full path to the program in a mounted file system that
implements the system() command. That is, a program that starts the
NSH shell, executes one command (in argv[1]), then exits.
config SYSTEM_SYSTEM_STACKSIZE
int "system stack size"
default 2048 if !ARCH_SIM

View File

@ -42,7 +42,9 @@
#include <sys/wait.h>
#include <stdlib.h>
#include <sched.h>
#include <spawn.h>
#include <assert.h>
#include <debug.h>
#include "nshlib/nshlib.h"
@ -57,13 +59,13 @@
* Use system to pass a command string to the NSH parser and wait for it
* to finish executing.
*
* This is an experimental version with known incompatibilies:
* This is an experimental version with known incompatibilities:
*
* 1. It is not a part of libc due to its close association with NSH. The
* function is still prototyped in nuttx/include/stdlib.h, however.
* 2. It cannot use /bin/sh since that program will not exist in most
* embedded configurations. Rather, it will spawn a shell-specific
* system command -- currenly only NSH.
* system command -- currently only NSH.
* 3. REVISIT: There may be some issues with returned values.
* 4. Of course, only NSH commands will be supported so that still means
* that many leveraged system() calls will still not be functional.
@ -72,24 +74,90 @@
int system(FAR char *cmd)
{
FAR char *nshargv[2];
int pid;
FAR char *argv[2];
struct sched_param param;
posix_spawnattr_t attr;
pid_t pid;
int errcode;
int rc;
int ret;
/* REVISIT: If cmd is NULL, then system() should return a non-zero value to
* indicate if the command processor is available or zero if it is not.
*/
DEBUGASSERT(cmd != NULL);
/* Spawn nsh_system() which will execute the command under the shell */
/* Initialize attributes for task_spawn() (or posix_spawn()). */
nshargv[0] = cmd;
nshargv[1] = NULL;
pid = task_create("system", CONFIG_SYSTEM_SYSTEM_PRIORITY,
CONFIG_SYSTEM_SYSTEM_STACKSIZE, nsh_system,
(FAR char * const *)nshargv);
if (pid < 0)
errcode = posix_spawnattr_init(&attr);
if (errcode != 0)
{
return EXIT_FAILURE;
goto errout;
}
/* Set the correct stack size and priority */
param.sched_priority = CONFIG_SYSTEM_SYSTEM_PRIORITY;
errcode = posix_spawnattr_setschedparam(&attr, &param);
if (errcode != 0)
{
goto errout_with_attrs;
}
errcode = task_spawnattr_setstacksize(&attr, CONFIG_SYSTEM_SYSTEM_STACKSIZE);
if (errcode != 0)
{
goto errout_with_attrs;
}
/* If robin robin scheduling is enabled, then set the scheduling policy
* of the new task to SCHED_RR before it has a chance to run.
*/
#if CONFIG_RR_INTERVAL > 0
errcode = posix_spawnattr_setschedpolicy(&attr, SCHED_RR);
if (errcode != 0)
{
goto errout_with_attrs;
}
errcode = posix_spawnattr_setflags(&attr,
POSIX_SPAWN_SETSCHEDPARAM |
POSIX_SPAWN_SETSCHEDULER);
if (errcode != 0)
{
goto errout_with_attrs;
}
#else
errcode = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSCHEDPARAM);
if (errcode != 0)
{
goto errout_with_attrs;
}
#endif
/* Spawn nsh_system() which will execute the command under the shell. */
argv[0] = cmd;
argv[1] = NULL;
#ifdef CONFIG_BUILD_KERNEL
errcode = posix_spawn(&pid, CONFIG_SYSTEM_OPEN_SHPATH, NULL, &attr,
argv, (FAR char * const *)NULL);
#else
errcode = task_spawn(&pid, "popen", nsh_system, NULL, &attr,
argv, (FAR char * const *)NULL);
#endif
/* Release the attributes and check for an error from the spawn operation */
if (errcode != 0)
{
serr("ERROR: Spawn failed: %d\n", result);
goto errout_with_attrs;
}
/* Wait for the shell to return */
@ -97,8 +165,18 @@ int system(FAR char *cmd)
ret = waitpid(pid, &rc, 0);
if (ret < 0)
{
return EXIT_FAILURE;
/* The errno variable has already been set */
rc = ERROR;
}
(void)posix_spawnattr_destroy(&attr);
return rc;
errout_with_attrs:
(void)posix_spawnattr_destroy(&attr);
errout:
set_errno(errcode);
return ERROR;
}