nuttx-apps/examples/posix_spawn/spawn_main.c
Xiang Xiao 857158451b Unify the void cast usage
1.Remove void cast for function because many place ignore the returned value witout cast
2.Replace void cast for variable with UNUSED macro

Change-Id: Ie644129a563244a6397036789c4c3ea83c4e9b09
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2020-01-02 23:21:01 +08:00

460 lines
14 KiB
C

/****************************************************************************
* examples/posix_spawn/spawn_main.c
*
* Copyright (C) 2013, 2018 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>
#include <nuttx/compiler.h>
#include <sys/mount.h>
#include <sys/boardctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <spawn.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/drivers/ramdisk.h>
#include <nuttx/symtab.h>
#include "filesystem/romfs.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Check configuration. This is not all of the configuration settings that
* are required -- only the more obvious.
*/
#ifdef CONFIG_BINFMT_DISABLE
# error "The binary loader is disabled (CONFIG_BINFMT_DISABLE)!"
#endif
#ifndef CONFIG_ELF
# error "You must select CONFIG_ELF in your configuration file"
#endif
#ifndef CONFIG_FS_ROMFS
# error "You must select CONFIG_FS_ROMFS in your configuration file"
#endif
#ifdef CONFIG_DISABLE_MOUNTPOINT
# error "You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file"
#endif
#ifdef CONFIG_BINFMT_DISABLE
# error "You must not disable loadable modules via CONFIG_BINFMT_DISABLE in your configuration file"
#endif
#ifndef CONFIG_LIB_BOARDCTL
# error "This configuration requires CONFIG_LIB_BOARDCTL"
#endif
#ifndef CONFIG_BOARDCTL_APP_SYMTAB
# error "You must enable the symobol table interface with CONFIG_BOARDCTL_APP_SYMTAB"
#endif
/* Describe the ROMFS file system */
#define SECTORSIZE 512
#define NSECTORS(b) (((b)+SECTORSIZE-1)/SECTORSIZE)
#define MOUNTPT "/mnt/romfs"
#ifndef CONFIG_EXAMPLES_ELF_DEVMINOR
# define CONFIG_EXAMPLES_ELF_DEVMINOR 0
#endif
#ifndef CONFIG_EXAMPLES_ELF_DEVPATH
# define CONFIG_EXAMPLES_ELF_DEVPATH "/dev/ram0"
#endif
/* If CONFIG_DEBUG_FEATURES is enabled, use info/err instead of printf so that the
* output will be synchronous with the debug output.
*/
#ifdef CONFIG_CPP_HAVE_VARARGS
# ifdef CONFIG_DEBUG_FEATURES
# define message(format, ...) _info(format, ##__VA_ARGS__)
# define errmsg(format, ...) _err(format, ##__VA_ARGS__)
# else
# define message(format, ...) printf(format, ##__VA_ARGS__)
# define errmsg(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
# endif
#else
# ifdef CONFIG_DEBUG_FEATURES
# define message _info
# define errmsg _err
# else
# define message printf
# define errmsg printf
# endif
#endif
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static unsigned int g_mminitial; /* Initial memory usage */
static unsigned int g_mmstep; /* Memory Usage at beginning of test step */
static const char delimiter[] =
"****************************************************************************";
static const char g_redirect[] = "redirect";
static const char g_hello[] = "hello";
static const char g_data[] = "testdata.txt";
static char fullpath[128];
static char * const g_argv[4] =
{ "Argument 1", "Argument 2", "Argument 3", NULL };
/****************************************************************************
* Symbols from Auto-Generated Code
****************************************************************************/
extern const struct symtab_s g_spawn_exports[];
extern const int g_spawn_nexports;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mm_update
****************************************************************************/
static void mm_update(FAR unsigned int *previous, FAR const char *msg)
{
struct mallinfo mmcurrent;
/* Get the current memory usage */
#ifdef CONFIG_CAN_PASS_STRUCTS
mmcurrent = mallinfo();
#else
mallinfo(&mmcurrent);
#endif
/* Show the change from the previous time */
printf("\nMemory Usage %s:\n", msg);
printf(" Before: %8u After: %8u Change: %8d\n",
*previous, mmcurrent.uordblks, (int)mmcurrent.uordblks - (int)*previous);
/* Set up for the next test */
*previous = mmcurrent.uordblks;
}
/****************************************************************************
* Name: mm_initmonitor
****************************************************************************/
static void mm_initmonitor(void)
{
struct mallinfo mmcurrent;
#ifdef CONFIG_CAN_PASS_STRUCTS
mmcurrent = mallinfo();
#else
mallinfo(&mmcurrent);
#endif
g_mminitial = mmcurrent.uordblks;
g_mmstep = mmcurrent.uordblks;
printf("Initial memory usage: %d\n", mmcurrent.uordblks);
}
/****************************************************************************
* Name: testheader
****************************************************************************/
static inline void testheader(FAR const char *progname)
{
message("\n%s\n* Executing %s\n%s\n\n", delimiter, progname, delimiter);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: spawn_main
****************************************************************************/
int main(int argc, FAR char *argv[])
{
struct boardioc_symtab_s symdesc;
posix_spawn_file_actions_t file_actions;
posix_spawnattr_t attr;
FAR const char *filepath;
pid_t pid;
int ret;
/* Initialize the memory monitor */
mm_initmonitor();
/* Create a ROM disk for the ROMFS filesystem */
message("Registering romdisk at /dev/ram%d\n", CONFIG_EXAMPLES_ELF_DEVMINOR);
ret = romdisk_register(CONFIG_EXAMPLES_ELF_DEVMINOR, (FAR uint8_t *)romfs_img,
NSECTORS(romfs_img_len), SECTORSIZE);
if (ret < 0)
{
errmsg("ERROR: romdisk_register failed: %d\n", ret);
exit(1);
}
mm_update(&g_mmstep, "after romdisk_register");
/* Mount the file system */
message("Mounting ROMFS filesystem at target=%s with source=%s\n",
MOUNTPT, CONFIG_EXAMPLES_ELF_DEVPATH);
ret = mount(CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, "romfs", MS_RDONLY, NULL);
if (ret < 0)
{
errmsg("ERROR: mount(%s,%s,romfs) failed: %s\n",
CONFIG_EXAMPLES_ELF_DEVPATH, MOUNTPT, errno);
}
mm_update(&g_mmstep, "after mount");
/* Does the system support the PATH variable? Has the PATH variable
* already been set? If YES and NO, then set the PATH variable to
* the ROMFS mountpoint.
*/
#if defined(CONFIG_LIB_ENVPATH) && !defined(CONFIG_PATH_INITIAL)
setenv("PATH", MOUNTPT, 1);
#endif
/* Make sure that we are using our symbol tablee */
symdesc.symtab = (FAR struct symtab_s *)g_spawn_exports; /* Discard 'const' */
symdesc.nsymbols = g_spawn_nexports;
boardctl(BOARDIOC_APP_SYMTAB, (uintptr_t)&symdesc);
/*************************************************************************
* Case 1: Simple program with arguments
*************************************************************************/
/* Output a separator so that we can clearly discriminate the output of
* this program from the others.
*/
testheader(g_hello);
/* Initialize the attributes file actions structure */
ret = posix_spawn_file_actions_init(&file_actions);
if (ret != 0)
{
errmsg("ERROR: posix_spawn_file_actions_init failed: %d\n", ret);
}
posix_spawn_file_actions_dump(&file_actions);
ret = posix_spawnattr_init(&attr);
if (ret != 0)
{
errmsg("ERROR: posix_spawnattr_init failed: %d\n", ret);
}
posix_spawnattr_dump(&attr);
mm_update(&g_mmstep, "after file_action/attr init");
/* If the binary loader does not support the PATH variable, then
* create the full path to the executable program. Otherwise,
* use the relative path so that the binary loader will have to
* search the PATH variable to find the executable.
*/
#ifdef CONFIG_LIB_ENVPATH
filepath = g_hello;
#else
snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_hello);
filepath = fullpath;
#endif
/* Execute the program */
mm_update(&g_mmstep, "before posix_spawn");
ret = posix_spawn(&pid, filepath, &file_actions, &attr, NULL, (FAR char * const*)&g_argv);
if (ret != 0)
{
errmsg("ERROR: posix_spawn failed: %d\n", ret);
}
sleep(4);
mm_update(&g_mmstep, "after posix_spawn");
/* Free attributes and file actions */
ret = posix_spawn_file_actions_destroy(&file_actions);
if (ret != 0)
{
errmsg("ERROR: posix_spawn_file_actions_destroy failed: %d\n", ret);
}
posix_spawn_file_actions_dump(&file_actions);
ret = posix_spawnattr_destroy(&attr);
if (ret != 0)
{
errmsg("ERROR: posix_spawnattr_destroy failed: %d\n", ret);
}
posix_spawnattr_dump(&attr);
mm_update(&g_mmstep, "after file_action/attr destruction");
/*************************************************************************
* Case 2: Simple program with redirection of stdin to a file input
*************************************************************************/
/* Output a separator so that we can clearly discriminate the output of
* this program from the others.
*/
testheader(g_redirect);
/* Initialize the attributes file actions structure */
ret = posix_spawn_file_actions_init(&file_actions);
if (ret != 0)
{
errmsg("ERROR: posix_spawn_file_actions_init failed: %d\n", ret);
}
posix_spawn_file_actions_dump(&file_actions);
ret = posix_spawnattr_init(&attr);
if (ret != 0)
{
errmsg("ERROR: posix_spawnattr_init failed: %d\n", ret);
}
posix_spawnattr_dump(&attr);
mm_update(&g_mmstep, "after file_action/attr init");
/* Set up to close stdin (0) and open testdata.txt as the program input */
ret = posix_spawn_file_actions_addclose(&file_actions, 0);
if (ret != 0)
{
errmsg("ERROR: posix_spawn_file_actions_addclose failed: %d\n", ret);
}
posix_spawn_file_actions_dump(&file_actions);
snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_data);
ret = posix_spawn_file_actions_addopen(&file_actions, 0, fullpath, O_RDONLY, 0644);
if (ret != 0)
{
errmsg("ERROR: posix_spawn_file_actions_addopen failed: %d\n", ret);
}
posix_spawn_file_actions_dump(&file_actions);
mm_update(&g_mmstep, "after adding file_actions");
/* If the binary loader does not support the PATH variable, then
* create the full path to the executable program. Otherwise,
* use the relative path so that the binary loader will have to
* search the PATH variable to find the executable.
*/
#ifdef CONFIG_LIB_ENVPATH
filepath = g_redirect;
#else
snprintf(fullpath, 128, "%s/%s", MOUNTPT, g_redirect);
filepath = fullpath;
#endif
/* Execute the program */
mm_update(&g_mmstep, "before posix_spawn");
ret = posix_spawn(&pid, filepath, &file_actions, &attr, NULL, NULL);
if (ret != 0)
{
errmsg("ERROR: posix_spawn failed: %d\n", ret);
}
sleep(2);
mm_update(&g_mmstep, "after posix_spawn");
/* Free attibutes and file actions */
ret = posix_spawn_file_actions_destroy(&file_actions);
if (ret != 0)
{
errmsg("ERROR: posix_spawn_file_actions_destroy failed: %d\n", ret);
}
posix_spawn_file_actions_dump(&file_actions);
ret = posix_spawnattr_destroy(&attr);
if (ret != 0)
{
errmsg("ERROR: posix_spawnattr_destroy failed: %d\n", ret);
}
posix_spawnattr_dump(&attr);
mm_update(&g_mmstep, "after file_action/attr destruction");
/* Clean-up */
mm_update(&g_mmstep, "End-of-Test");
return 0;
}