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:
parent
08263367bc
commit
e3e911555a
@ -7,7 +7,7 @@ config SYSTEM_POPEN
|
|||||||
bool "popen()/pclose() Functions"
|
bool "popen()/pclose() Functions"
|
||||||
default n
|
default n
|
||||||
select SCHED_WAITPID
|
select SCHED_WAITPID
|
||||||
depends on NSH_LIBRARY && !BUILD_KERNEL
|
depends on NSH_LIBRARY
|
||||||
---help---
|
---help---
|
||||||
Enable support for the popen() and pclose() interfaces.
|
Enable support for the popen() and pclose() interfaces.
|
||||||
This will support execution of NSH commands from C code with
|
This will support execution of NSH commands from C code with
|
||||||
@ -15,6 +15,15 @@ config SYSTEM_POPEN
|
|||||||
|
|
||||||
if 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
|
config SYSTEM_POPEN_STACKSIZE
|
||||||
int "Shell stack size"
|
int "Shell stack size"
|
||||||
default 2048 if !ARCH_SIM
|
default 2048 if !ARCH_SIM
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#include "nshlib/nshlib.h"
|
#include "nshlib/nshlib.h"
|
||||||
|
|
||||||
@ -188,7 +189,7 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
|||||||
goto errout_with_pipe;
|
goto errout_with_pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize attributes for task_spawn(). */
|
/* Initialize attributes for task_spawn() (or posix_spawn()). */
|
||||||
|
|
||||||
errcode = posix_spawnattr_init(&attr);
|
errcode = posix_spawnattr_init(&attr);
|
||||||
if (errcode != 0)
|
if (errcode != 0)
|
||||||
@ -202,7 +203,7 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
|||||||
goto errout_with_attrs;
|
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;
|
param.sched_priority = CONFIG_SYSTEM_POPEN_PRIORITY;
|
||||||
errcode = posix_spawnattr_setschedparam(&attr, ¶m);
|
errcode = posix_spawnattr_setschedparam(&attr, ¶m);
|
||||||
@ -229,8 +230,8 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
errcode = posix_spawnattr_setflags(&attr,
|
errcode = posix_spawnattr_setflags(&attr,
|
||||||
POSIX_SPAWN_SETSCHEDPARAM |
|
POSIX_SPAWN_SETSCHEDPARAM |
|
||||||
POSIX_SPAWN_SETSCHEDULER);
|
POSIX_SPAWN_SETSCHEDULER);
|
||||||
if (errcode != 0)
|
if (errcode != 0)
|
||||||
{
|
{
|
||||||
goto errout_with_actions;
|
goto errout_with_actions;
|
||||||
@ -253,17 +254,25 @@ FILE *popen(FAR const char *command, FAR const char *mode)
|
|||||||
goto errout_with_actions;
|
goto errout_with_actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call task_spawn(), re-directing stdin or stdout appropriately */
|
/* Call task_spawn() (or posix_spawn), re-directing stdin or stdout
|
||||||
/* Start the built-in */
|
* appropriately.
|
||||||
|
*/
|
||||||
|
|
||||||
argv[0] = (FAR char *)command;
|
argv[0] = (FAR char *)command;
|
||||||
argv[1] = NULL;
|
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,
|
errcode = task_spawn(&container->shell, "popen", nsh_system, &file_actions,
|
||||||
&attr, argv, (FAR char * const *)NULL);
|
&attr, argv, (FAR char * const *)NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (errcode != 0)
|
if (errcode != 0)
|
||||||
{
|
{
|
||||||
serr("ERROR: task_spawn failed: %d\n", result);
|
serr("ERROR: Spawn failed: %d\n", result);
|
||||||
goto errout_with_actions;
|
goto errout_with_actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,6 +398,6 @@ int pclose(FILE *stream)
|
|||||||
|
|
||||||
return status;
|
return status;
|
||||||
#else
|
#else
|
||||||
return EXIT_SUCCESS;
|
return OK;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,15 @@ config SYSTEM_SYSTEM
|
|||||||
|
|
||||||
if 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
|
config SYSTEM_SYSTEM_STACKSIZE
|
||||||
int "system stack size"
|
int "system stack size"
|
||||||
default 2048 if !ARCH_SIM
|
default 2048 if !ARCH_SIM
|
||||||
|
@ -42,7 +42,9 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <spawn.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
#include "nshlib/nshlib.h"
|
#include "nshlib/nshlib.h"
|
||||||
|
|
||||||
@ -57,13 +59,13 @@
|
|||||||
* Use system to pass a command string to the NSH parser and wait for it
|
* Use system to pass a command string to the NSH parser and wait for it
|
||||||
* to finish executing.
|
* 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
|
* 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.
|
* function is still prototyped in nuttx/include/stdlib.h, however.
|
||||||
* 2. It cannot use /bin/sh since that program will not exist in most
|
* 2. It cannot use /bin/sh since that program will not exist in most
|
||||||
* embedded configurations. Rather, it will spawn a shell-specific
|
* 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.
|
* 3. REVISIT: There may be some issues with returned values.
|
||||||
* 4. Of course, only NSH commands will be supported so that still means
|
* 4. Of course, only NSH commands will be supported so that still means
|
||||||
* that many leveraged system() calls will still not be functional.
|
* that many leveraged system() calls will still not be functional.
|
||||||
@ -72,24 +74,90 @@
|
|||||||
|
|
||||||
int system(FAR char *cmd)
|
int system(FAR char *cmd)
|
||||||
{
|
{
|
||||||
FAR char *nshargv[2];
|
FAR char *argv[2];
|
||||||
int pid;
|
struct sched_param param;
|
||||||
|
posix_spawnattr_t attr;
|
||||||
|
pid_t pid;
|
||||||
|
int errcode;
|
||||||
int rc;
|
int rc;
|
||||||
int ret;
|
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);
|
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;
|
errcode = posix_spawnattr_init(&attr);
|
||||||
nshargv[1] = NULL;
|
if (errcode != 0)
|
||||||
|
|
||||||
pid = task_create("system", CONFIG_SYSTEM_SYSTEM_PRIORITY,
|
|
||||||
CONFIG_SYSTEM_SYSTEM_STACKSIZE, nsh_system,
|
|
||||||
(FAR char * const *)nshargv);
|
|
||||||
if (pid < 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, ¶m);
|
||||||
|
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 */
|
/* Wait for the shell to return */
|
||||||
@ -97,8 +165,18 @@ int system(FAR char *cmd)
|
|||||||
ret = waitpid(pid, &rc, 0);
|
ret = waitpid(pid, &rc, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
/* The errno variable has already been set */
|
||||||
|
|
||||||
|
rc = ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(void)posix_spawnattr_destroy(&attr);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
errout_with_attrs:
|
||||||
|
(void)posix_spawnattr_destroy(&attr);
|
||||||
|
|
||||||
|
errout:
|
||||||
|
set_errno(errcode);
|
||||||
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user