Add nuttx to the system framework, which is 10.1.0
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
############################################################################
|
||||
# apps/nshlib/Make.defs
|
||||
# Adds selected applications to apps/ build
|
||||
#
|
||||
# Copyright (C) 2012 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifeq ($(CONFIG_NSH_LIBRARY),y)
|
||||
CONFIGURED_APPS += $(APPDIR)/nshlib
|
||||
endif
|
||||
@@ -0,0 +1,131 @@
|
||||
############################################################################
|
||||
# apps/nshlib/Makefile
|
||||
#
|
||||
# Copyright (C) 2011-2013, 2016 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# NSH Library
|
||||
|
||||
CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_script.c nsh_system.c
|
||||
CSRCS += nsh_command.c nsh_fscmds.c nsh_ddcmd.c nsh_proccmds.c nsh_mmcmds.c
|
||||
CSRCS += nsh_timcmds.c nsh_envcmds.c nsh_syscmds.c nsh_dbgcmds.c
|
||||
|
||||
ifeq ($(CONFIG_FILE_STREAM),y)
|
||||
CSRCS += nsh_session.c
|
||||
ifeq ($(CONFIG_NSH_CONSOLE_LOGIN),y)
|
||||
CSRCS += nsh_login.c
|
||||
endif
|
||||
else
|
||||
CSRCS += nsh_stdsession.c
|
||||
ifeq ($(CONFIG_NSH_CONSOLE_LOGIN),y)
|
||||
CSRCS += nsh_stdlogin.c
|
||||
endif
|
||||
endif
|
||||
|
||||
CSRCS += nsh_fsutils.c
|
||||
|
||||
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_VARS),y)
|
||||
CSRCS += nsh_vars.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_ROMFSETC),y)
|
||||
CSRCS += nsh_romfsetc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
CSRCS += nsh_netcmds.c
|
||||
|
||||
ifeq ($(CONFIG_NET_ROUTE),y)
|
||||
CSRCS += nsh_routecmds.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
|
||||
CSRCS += nsh_mntcmds.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MODULE),y)
|
||||
ifneq ($(CONFIG_NSH_DISABLE_MODCMDS),y)
|
||||
CSRCS += nsh_modcmds.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_CONSOLE),y)
|
||||
CSRCS += nsh_consolemain.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NSH_DISABLE_PRINTF),y)
|
||||
CSRCS += nsh_printf.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_TELNET),y)
|
||||
CSRCS += nsh_telnetd.c
|
||||
ifeq ($(CONFIG_NSH_TELNET_LOGIN),y)
|
||||
CSRCS += nsh_telnetlogin.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
|
||||
CSRCS += nsh_test.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USBDEV),y)
|
||||
CSRCS += nsh_usbconsole.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_ALTCONDEV),y)
|
||||
CSRCS += nsh_altconsole.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_USBDEV_TRACE),y)
|
||||
CSRCS += nsh_usbtrace.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NETUTILS_CODECS),y)
|
||||
CSRCS += nsh_codeccmd.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_LOGIN_PASSWD),y)
|
||||
CSRCS += nsh_passwdcmds.c
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,331 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_altconsole.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
* Author: Alan Carvalho de Assis <acassis@gmail.com>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#include "netutils/netinit.h"
|
||||
|
||||
#if defined(CONFIG_NSH_ALTCONDEV) && !defined(HAVE_USB_CONSOLE)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_clone_console
|
||||
*
|
||||
* Description:
|
||||
* Clone stdout and stderr to alternatives devices
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_clone_console(FAR struct console_stdio_s *pstate)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/* Open the alternative standard error device */
|
||||
|
||||
fd = open(CONFIG_NSH_ALTSTDERR, O_WRONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Flush stderr: we only flush stderr if we opened the alternative one */
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
/* Associate the new opened file descriptor to stderr */
|
||||
|
||||
dup2(fd, 2);
|
||||
|
||||
/* Close the console device that we just opened */
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Open the alternative standard output device */
|
||||
|
||||
fd = open(CONFIG_NSH_ALTSTDOUT, O_WRONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Flush stdout: we only flush stdout if we opened the alternative one */
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
/* Associate the new opened file descriptor to stdout */
|
||||
|
||||
dup2(fd, 1);
|
||||
|
||||
/* Close the console device that we just opened */
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* Setup the stderr */
|
||||
|
||||
pstate->cn_errfd = 2;
|
||||
pstate->cn_errstream = fdopen(pstate->cn_errfd, "a");
|
||||
if (!pstate->cn_errstream)
|
||||
{
|
||||
free(pstate);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Setup the stdout */
|
||||
|
||||
pstate->cn_outfd = 1;
|
||||
pstate->cn_outstream = fdopen(pstate->cn_outfd, "a");
|
||||
if (!pstate->cn_outstream)
|
||||
{
|
||||
free(pstate);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_wait_inputdev
|
||||
*
|
||||
* Description:
|
||||
* Wait for the input device to be ready
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_wait_inputdev(FAR struct console_stdio_s *pstate,
|
||||
FAR const char *msg)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/* Don't start the NSH console until the input device is ready. Chances
|
||||
* are, we get here with no functional stdin. For example a USB keyboard
|
||||
* device will not be available until the device is connected to the host
|
||||
* and enumerated.
|
||||
*/
|
||||
|
||||
/* Open the USB keyboard device for read-only access */
|
||||
|
||||
do
|
||||
{
|
||||
/* Try to open the alternative stdin device */
|
||||
|
||||
fd = open(CONFIG_NSH_ALTSTDIN, O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
int errcode = errno;
|
||||
|
||||
/* ENOENT means that the USB device is not yet connected and,
|
||||
* hence, has no entry under /dev. If the USB driver still
|
||||
* exists under /dev (because other threads still have the driver
|
||||
* open), then we might also get ENODEV. Anything else would
|
||||
* be really bad.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(errcode == ENOENT || errcode == ENODEV);
|
||||
#endif
|
||||
|
||||
/* Let the user know that we are waiting */
|
||||
|
||||
if (msg)
|
||||
{
|
||||
/* Show the waiting message only one time after the failure
|
||||
* to open the keyboard device.
|
||||
*/
|
||||
|
||||
puts(msg);
|
||||
fflush(stdout);
|
||||
msg = NULL;
|
||||
}
|
||||
|
||||
/* Sleep a bit and try again */
|
||||
|
||||
sleep(2);
|
||||
}
|
||||
}
|
||||
while (fd < 0);
|
||||
|
||||
/* Okay.. we have successfully opened the input device. Did
|
||||
* we just re-open fd 0?
|
||||
*/
|
||||
|
||||
if (fd != 0)
|
||||
{
|
||||
/* No.. Dup the fd to create standard fd 0. stdin should not know. */
|
||||
|
||||
dup2(fd, 0);
|
||||
|
||||
/* Setup the input console */
|
||||
|
||||
pstate->cn_confd = 0;
|
||||
|
||||
/* Create a standard C stream on the console device */
|
||||
|
||||
pstate->cn_constream = fdopen(pstate->cn_confd, "r+");
|
||||
if (!pstate->cn_constream)
|
||||
{
|
||||
free(pstate);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Close the input device that we just opened */
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consolemain (USB console version)
|
||||
*
|
||||
* Description:
|
||||
* This interfaces maybe to called or started with task_start to start a
|
||||
* single an NSH instance that operates on stdin and stdout. This
|
||||
* function does not return.
|
||||
*
|
||||
* This function handles generic /dev/console character devices for output
|
||||
* but uses a special USB keyboard device for input. The USB keyboard
|
||||
* requires some special operations to handle the cases where the session
|
||||
* input is lost when the USB keyboard is unplugged and restarted when the
|
||||
* USB keyboard is plugged in again.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard task start-up arguments. These are not used. argc may be
|
||||
* zero and argv may be NULL.
|
||||
*
|
||||
* Returned Values:
|
||||
* This function does not return nor does it ever exit (unless the user
|
||||
* executes the NSH exit command).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_consolemain(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = nsh_newconsole();
|
||||
FAR const char *msg;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(pstate);
|
||||
|
||||
/* Initialize any USB tracing options that were requested */
|
||||
|
||||
#ifdef CONFIG_NSH_USBDEV_TRACE
|
||||
usbtrace_enable(TRACE_BITSET);
|
||||
#endif
|
||||
|
||||
/* Execute the one-time start-up script.
|
||||
* Any output will go to /dev/console.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSETC
|
||||
nsh_initscript(&pstate->cn_vtbl);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_NETINIT
|
||||
/* Bring up the network */
|
||||
|
||||
netinit_bringup();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_ARCHINIT) && defined(CONFIG_BOARDCTL_FINALINIT)
|
||||
/* Perform architecture-specific final-initialization (if configured) */
|
||||
|
||||
boardctl(BOARDIOC_FINALINIT, 0);
|
||||
#endif
|
||||
|
||||
/* First map stderr and stdout to alternative devices */
|
||||
|
||||
ret = nsh_clone_console(pstate);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Now loop, executing creating a session for each USB connection */
|
||||
|
||||
msg = "Waiting for a keyboard...\n";
|
||||
for (; ; )
|
||||
{
|
||||
/* Wait for the USB to be connected to the host and switch
|
||||
* standard I/O to the USB serial device.
|
||||
*/
|
||||
|
||||
ret = nsh_wait_inputdev(pstate, msg);
|
||||
|
||||
DEBUGASSERT(ret == OK);
|
||||
UNUSED(ret);
|
||||
|
||||
/* Execute the session */
|
||||
|
||||
nsh_session(pstate, true, argc, argv);
|
||||
|
||||
/* We lost the connection. Wait for the keyboard to
|
||||
* be re-connected.
|
||||
*/
|
||||
|
||||
msg = "Please re-connect the keyboard...\n";
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_USB_KEYBOARD && !HAVE_USB_CONSOLE */
|
||||
@@ -0,0 +1,278 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_builtin.c
|
||||
*
|
||||
* Originally by:
|
||||
*
|
||||
* Copyright (C) 2011 Uros Platise. All rights reserved.
|
||||
* Author: Uros Platise <uros.platise@isotel.eu>
|
||||
*
|
||||
* With subsequent updates, modifications, and general maintenance by:
|
||||
*
|
||||
* Copyright (C) 2011-2013, 2019 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/ioctl.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/lib/builtin.h>
|
||||
#include "builtin/builtin.h"
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_BUILTIN_APPS
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_builtin
|
||||
*
|
||||
* 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_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
|
||||
FAR char **argv, FAR const char *redirfile, int oflags)
|
||||
{
|
||||
#if !defined(CONFIG_NSH_DISABLEBG) && defined(CONFIG_SCHED_CHILD_STATUS)
|
||||
struct sigaction act;
|
||||
struct sigaction old;
|
||||
#endif
|
||||
int ret = OK;
|
||||
|
||||
/* Lock the scheduler in an attempt to prevent the application from
|
||||
* running until waitpid() has been called.
|
||||
*/
|
||||
|
||||
sched_lock();
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLEBG) && defined(CONFIG_SCHED_CHILD_STATUS)
|
||||
/* Ignore the child status if run the application on background. */
|
||||
|
||||
if (vtbl->np.np_bg == true)
|
||||
{
|
||||
act.sa_handler = SIG_DFL;
|
||||
act.sa_flags = SA_NOCLDWAIT;
|
||||
sigemptyset(&act.sa_mask);
|
||||
|
||||
sigaction(SIGCHLD, &act, &old);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_DISABLEBG */
|
||||
|
||||
/* Try to find and execute the command within the list of builtin
|
||||
* applications.
|
||||
*/
|
||||
|
||||
ret = exec_builtin(cmd, (FAR char * const *)argv, redirfile, oflags);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* 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 where I/O was redirected,
|
||||
* a proxy task ran and broke our lock. As result, the application may
|
||||
* have aso ran if its priority was higher than than the priority of
|
||||
* this thread.
|
||||
*
|
||||
* If the application did not run to completion 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
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Setup up to receive SIGINT if control-C entered. The return
|
||||
* value is ignored because this console device may not support
|
||||
* SIGINT.
|
||||
*/
|
||||
|
||||
ioctl(stdout->fs_fd, TIOCSCTTY, ret);
|
||||
|
||||
/* Wait for the application to exit. We did lock the scheduler
|
||||
* above, but that does not guarantee that the application did not
|
||||
* already run to completion in the case where I/O was redirected.
|
||||
* Here the scheduler will be unlocked while waitpid is waiting
|
||||
* and if the application has not yet run, it will now be able to
|
||||
* do so.
|
||||
*
|
||||
* Also, if CONFIG_SCHED_HAVE_PARENT is defined waitpid() might
|
||||
* fail even if task is still active: If the I/O was re-directed
|
||||
* by a proxy task, then the ask is a child of the proxy, and not
|
||||
* this task. waitpid() fails with ECHILD in either case.
|
||||
*
|
||||
* NOTE: WUNTRACED does nothing in the default case, but in the
|
||||
* case the where CONFIG_SIG_SIGSTOP_ACTION=y, the built-in app
|
||||
* may also be stopped. In that case WUNTRACED will force
|
||||
* waitpid() to return with ECHILD.
|
||||
*/
|
||||
|
||||
ret = waitpid(ret, &rc, WUNTRACED);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* If the child thread does not exist, waitpid() will return
|
||||
* the error ECHLD. Since we know that the task was
|
||||
* successfully started, this must be one of the cases
|
||||
* described above; we have to assume that the task already
|
||||
* exit'ed. In this case, we have no idea if the application
|
||||
* ran successfully or not (because NuttX does not retain exit
|
||||
* status of child tasks). Let's assume that is did run
|
||||
* successfully.
|
||||
*/
|
||||
|
||||
int errcode = errno;
|
||||
if (errcode == ECHILD)
|
||||
{
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "waitpid",
|
||||
NSH_ERRNO_OF(errcode));
|
||||
}
|
||||
}
|
||||
|
||||
/* Waitpid completed the wait successfully */
|
||||
|
||||
else
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
}
|
||||
|
||||
ioctl(stdout->fs_fd, TIOCSCTTY, -1);
|
||||
}
|
||||
# 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)
|
||||
{
|
||||
# ifdef CONFIG_SCHED_CHILD_STATUS
|
||||
|
||||
/* Restore the old actions */
|
||||
|
||||
sigaction(SIGCHLD, &old, NULL);
|
||||
# endif
|
||||
struct sched_param param;
|
||||
sched_getparam(ret, ¶m);
|
||||
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();
|
||||
|
||||
/* If exec_builtin() or waitpid() failed, then return -1 (ERROR) with the
|
||||
* errno value set appropriately.
|
||||
*/
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_BUILTIN_APPS */
|
||||
@@ -0,0 +1,597 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_codeccmd.c
|
||||
*
|
||||
* This file is part of NuttX, contributed by Darcy Gong
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Darcy Gong 2012-10-30
|
||||
*
|
||||
* 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_NETUTILS_CODECS
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sched.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#if defined(CONFIG_NSH_DISABLE_URLENCODE) && defined(CONFIG_NSH_DISABLE_URLDECODE)
|
||||
# undef CONFIG_CODECS_URLCODE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CODECS_URLCODE
|
||||
#include "netutils/urldecode.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_DISABLE_BASE64ENC) && defined(CONFIG_NSH_DISABLE_BASE64DEC)
|
||||
# undef CONFIG_CODECS_BASE64
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CODECS_BASE64
|
||||
#include "netutils/base64.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
|
||||
#include "netutils/md5.h"
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_CODECS_BUFSIZE
|
||||
# define CONFIG_NSH_CODECS_BUFSIZE 128
|
||||
#endif
|
||||
|
||||
#undef NEED_CMD_CODECS_PROC
|
||||
#undef HAVE_CODECS_URLENCODE
|
||||
#undef HAVE_CODECS_URLDECODE
|
||||
#undef HAVE_CODECS_BASE64ENC
|
||||
#undef HAVE_CODECS_BASE64DEC
|
||||
#undef HAVE_CODECS_HASH_MD5
|
||||
|
||||
#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLENCODE)
|
||||
# define HAVE_CODECS_URLENCODE 1
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CODECS_URLCODE) && !defined(CONFIG_NSH_DISABLE_URLDECODE)
|
||||
# define HAVE_CODECS_URLDECODE 1
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64ENC)
|
||||
# define HAVE_CODECS_BASE64ENC 1
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CODECS_BASE64) && !defined(CONFIG_NSH_DISABLE_BASE64DEC)
|
||||
# define HAVE_CODECS_BASE64DEC 1
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CODECS_HASH_MD5) && !defined(CONFIG_NSH_DISABLE_MD5)
|
||||
# define HAVE_CODECS_HASH_MD5 1
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CODECS_URLENCODE) || defined(HAVE_CODECS_URLDECODE) || \
|
||||
defined(HAVE_CODECS_BASE64ENC) || defined(HAVE_CODECS_BASE64DEC) || \
|
||||
defined(HAVE_CODECS_HASH_MD5)
|
||||
# define NEED_CMD_CODECS_PROC 1
|
||||
#endif
|
||||
|
||||
#define CODEC_MODE_URLENCODE 1
|
||||
#define CODEC_MODE_URLDECODE 2
|
||||
#define CODEC_MODE_BASE64ENC 3
|
||||
#define CODEC_MODE_BASE64DEC 4
|
||||
#define CODEC_MODE_HASH_MD5 5
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef void (*codec_callback_t)(FAR char *src, int srclen, FAR char *dest,
|
||||
FAR int *destlen, int mode);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: urlencode_cb
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_URLENCODE
|
||||
static void urlencode_cb(FAR char *src, int srclen, FAR char *dest,
|
||||
FAR int *destlen, int mode)
|
||||
{
|
||||
urlencode(src, srclen, dest, destlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: urldecode_cb
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_URLDECODE
|
||||
static void urldecode_cb(FAR char *src, int srclen, FAR char *dest,
|
||||
FAR int *destlen, int mode)
|
||||
{
|
||||
urldecode(src, srclen, dest, destlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: b64enc_cb
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_BASE64ENC
|
||||
static void b64enc_cb(FAR char *src, int srclen, FAR char *dest,
|
||||
FAR int *destlen, int mode)
|
||||
{
|
||||
if (mode == 0)
|
||||
{
|
||||
base64_encode((unsigned char *)src, srclen,
|
||||
(unsigned char *)dest, (size_t *)destlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
base64w_encode((unsigned char *)src, srclen,
|
||||
(unsigned char *)dest, (size_t *)destlen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: b64dec_cb
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_BASE64DEC
|
||||
static void b64dec_cb(FAR char *src, int srclen, FAR char *dest,
|
||||
FAR int *destlen, int mode)
|
||||
{
|
||||
if (mode == 0)
|
||||
{
|
||||
base64_decode((unsigned char *)src, srclen,
|
||||
(unsigned char *)dest, (size_t *)destlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
base64w_decode((unsigned char *)src, srclen,
|
||||
(unsigned char *)dest, (size_t *)destlen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: md5_cb
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
static void md5_cb(FAR char *src, int srclen, FAR char *dest,
|
||||
FAR int *destlen, int mode)
|
||||
{
|
||||
md5_update((MD5_CTX *)dest, (unsigned char *)src, srclen);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: calc_codec_buffsize
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NEED_CMD_CODECS_PROC
|
||||
static int calc_codec_buffsize(int srclen, uint8_t mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case CODEC_MODE_URLENCODE:
|
||||
return srclen * 3 + 1;
|
||||
|
||||
case CODEC_MODE_URLDECODE:
|
||||
return srclen + 1;
|
||||
|
||||
case CODEC_MODE_BASE64ENC:
|
||||
return ((srclen + 2) / 3 * 4) + 1;
|
||||
|
||||
case CODEC_MODE_BASE64DEC:
|
||||
return (srclen / 4 * 3 + 2) + 1;
|
||||
|
||||
case CODEC_MODE_HASH_MD5:
|
||||
return 32 + 1;
|
||||
|
||||
default:
|
||||
return srclen + 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_codecs_proc
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NEED_CMD_CODECS_PROC
|
||||
static int cmd_codecs_proc(FAR struct nsh_vtbl_s *vtbl, int argc,
|
||||
char **argv, uint8_t mode,
|
||||
codec_callback_t func)
|
||||
{
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
static const unsigned char hexchars[] = "0123456789abcdef";
|
||||
MD5_CTX ctx;
|
||||
unsigned char mac[16];
|
||||
FAR unsigned char *src;
|
||||
FAR char *dest;
|
||||
#endif
|
||||
|
||||
FAR char *localfile = NULL;
|
||||
FAR char *srcbuf = NULL;
|
||||
FAR char *destbuf = NULL;
|
||||
FAR char *fullpath = NULL;
|
||||
FAR const char *fmt;
|
||||
FAR char *sdata;
|
||||
bool badarg = false;
|
||||
bool isfile = false;
|
||||
bool iswebsafe = false;
|
||||
int option;
|
||||
int fd = -1;
|
||||
int buflen = 0;
|
||||
int srclen = 0;
|
||||
int ret = OK;
|
||||
|
||||
/* Get the command options */
|
||||
|
||||
while ((option = getopt(argc, argv, ":fw")) != ERROR)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case 'f':
|
||||
isfile = true;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_CODECS_BASE64
|
||||
case 'w':
|
||||
iswebsafe = true;
|
||||
|
||||
if (!(mode == CODEC_MODE_BASE64ENC ||
|
||||
mode == CODEC_MODE_BASE64DEC))
|
||||
{
|
||||
badarg = true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ':':
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
badarg = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
badarg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a bad argument was encountered, then return without processing
|
||||
* the command
|
||||
*/
|
||||
|
||||
if (badarg)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* There should be exactly on parameter left on the command-line */
|
||||
|
||||
if (optind == argc - 1)
|
||||
{
|
||||
sdata = argv[optind];
|
||||
}
|
||||
else if (optind >= argc)
|
||||
{
|
||||
fmt = g_fmttoomanyargs;
|
||||
goto errout;
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt = g_fmtargrequired;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
if (mode == CODEC_MODE_HASH_MD5)
|
||||
{
|
||||
md5_init(&ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isfile)
|
||||
{
|
||||
/* Get the local file name */
|
||||
|
||||
localfile = sdata;
|
||||
|
||||
/* Get the full path to the local file */
|
||||
|
||||
fullpath = nsh_getfullpath(vtbl, localfile);
|
||||
|
||||
/* Open the local file for reading */
|
||||
|
||||
fd = open(fullpath, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
|
||||
ret = ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
srcbuf = malloc(CONFIG_NSH_CODECS_BUFSIZE + 2);
|
||||
if (!srcbuf)
|
||||
{
|
||||
fmt = g_fmtcmdoutofmemory;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CODECS_BASE64ENC
|
||||
if (mode == CODEC_MODE_BASE64ENC)
|
||||
{
|
||||
srclen = CONFIG_NSH_CODECS_BUFSIZE / 3 * 3;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
srclen = CONFIG_NSH_CODECS_BUFSIZE;
|
||||
}
|
||||
|
||||
buflen = calc_codec_buffsize(srclen + 2, mode);
|
||||
destbuf = malloc(buflen);
|
||||
if (!destbuf)
|
||||
{
|
||||
fmt = g_fmtcmdoutofmemory;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
memset(srcbuf, 0, srclen + 2);
|
||||
ret = read(fd, srcbuf, srclen);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
|
||||
ret = ERROR;
|
||||
goto exit;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CODECS_URLDECODE
|
||||
if (mode == CODEC_MODE_URLDECODE)
|
||||
{
|
||||
if (srcbuf[srclen - 1] == '%')
|
||||
{
|
||||
ret += read(fd, &srcbuf[srclen], 2);
|
||||
}
|
||||
else if (srcbuf[srclen - 2] == '%')
|
||||
{
|
||||
ret += read(fd, &srcbuf[srclen], 1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
memset(destbuf, 0, buflen);
|
||||
if (func)
|
||||
{
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
if (mode == CODEC_MODE_HASH_MD5)
|
||||
{
|
||||
func(srcbuf, ret, (char *)&ctx, &buflen, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
func(srcbuf, ret, destbuf, &buflen, iswebsafe ? 1 : 0);
|
||||
nsh_output(vtbl, "%s", destbuf);
|
||||
}
|
||||
}
|
||||
|
||||
buflen = calc_codec_buffsize(srclen + 2, mode);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
if (mode == CODEC_MODE_HASH_MD5)
|
||||
{
|
||||
int i;
|
||||
|
||||
md5_final(mac, &ctx);
|
||||
src = mac;
|
||||
dest = destbuf;
|
||||
for (i = 0; i < 16; i++, src++)
|
||||
{
|
||||
*dest++ = hexchars[(*src) >> 4];
|
||||
*dest++ = hexchars[(*src) & 0x0f];
|
||||
}
|
||||
|
||||
*dest = '\0';
|
||||
nsh_output(vtbl, "%s\n", destbuf);
|
||||
}
|
||||
|
||||
#endif
|
||||
ret = OK;
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcbuf = sdata;
|
||||
srclen = strlen(sdata);
|
||||
buflen = calc_codec_buffsize(srclen, mode);
|
||||
destbuf = malloc(buflen);
|
||||
if (!destbuf)
|
||||
{
|
||||
fmt = g_fmtcmdoutofmemory;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
memset(destbuf, 0, buflen);
|
||||
if (func)
|
||||
{
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
if (mode == CODEC_MODE_HASH_MD5)
|
||||
{
|
||||
int i;
|
||||
|
||||
func(srcbuf, srclen, (char *)&ctx, &buflen, 0);
|
||||
md5_final(mac, &ctx);
|
||||
src = mac;
|
||||
dest = destbuf;
|
||||
for (i = 0; i < 16; i++, src++)
|
||||
{
|
||||
*dest++ = hexchars[(*src) >> 4];
|
||||
*dest++ = hexchars[(*src) & 0x0f];
|
||||
}
|
||||
|
||||
*dest = '\0';
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
func(srcbuf, srclen, destbuf, &buflen, iswebsafe ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%s\n", destbuf);
|
||||
srcbuf = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
|
||||
if (srcbuf)
|
||||
{
|
||||
free(srcbuf);
|
||||
}
|
||||
|
||||
if (destbuf)
|
||||
{
|
||||
free(destbuf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
nsh_output(vtbl, fmt, argv[0]);
|
||||
ret = ERROR;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_urlencode
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_URLENCODE
|
||||
int cmd_urlencode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_URLENCODE,
|
||||
urlencode_cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_urldecode
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_URLDECODE
|
||||
int cmd_urldecode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_URLDECODE,
|
||||
urldecode_cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_base64encode
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_BASE64ENC
|
||||
int cmd_base64encode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_BASE64ENC, b64enc_cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_base64decode
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_BASE64DEC
|
||||
int cmd_base64decode(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_BASE64DEC, b64dec_cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_md5
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CODECS_HASH_MD5
|
||||
int cmd_md5(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return cmd_codecs_proc(vtbl, argc, argv, CODEC_MODE_HASH_MD5, md5_cb);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NETUTILS_CODECS */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,497 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_console.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2013, 2015 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 Gregory Nutt 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
struct serialsave_s
|
||||
{
|
||||
int cn_errfd; /* Re-directed error output file descriptor */
|
||||
int cn_outfd; /* Re-directed output file descriptor */
|
||||
FILE *cn_errstream; /* Re-directed error output stream */
|
||||
FILE *cn_outstream; /* Re-directed output stream */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl);
|
||||
#endif
|
||||
static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl);
|
||||
static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const void *buffer, size_t nbytes);
|
||||
static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *fmt, ...);
|
||||
static int nsh_erroroutput(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *fmt, ...);
|
||||
static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl);
|
||||
static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd,
|
||||
FAR uint8_t *save);
|
||||
static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR uint8_t *save);
|
||||
static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus)
|
||||
noreturn_function;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_openifnotopen
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_openifnotopen(struct console_stdio_s *pstate)
|
||||
{
|
||||
/* The stream is open in a lazy fashion. This is done because the file
|
||||
* descriptor may be opened on a different task than the stream.
|
||||
*/
|
||||
|
||||
if (!pstate->cn_outstream)
|
||||
{
|
||||
pstate->cn_outstream = fdopen(pstate->cn_outfd, "w");
|
||||
if (!pstate->cn_outstream)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_NSH_ALTCONDEV)
|
||||
/* If the alternative console is not enabled then stderr = stdout */
|
||||
|
||||
pstate->cn_errfd = pstate->cn_outfd;
|
||||
pstate->cn_errstream = pstate->cn_outstream;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_closeifnotclosed
|
||||
*
|
||||
* Description:
|
||||
* Close the output stream if it is not the standard output stream.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
static void nsh_closeifnotclosed(struct console_stdio_s *pstate)
|
||||
{
|
||||
if (pstate->cn_outstream == OUTSTREAM(pstate))
|
||||
{
|
||||
fflush(OUTSTREAM(pstate));
|
||||
pstate->cn_outfd = OUTFD(pstate);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pstate->cn_outstream)
|
||||
{
|
||||
fflush(pstate->cn_outstream);
|
||||
fclose(pstate->cn_outstream);
|
||||
}
|
||||
else if (pstate->cn_outfd >= 0 && pstate->cn_outfd != OUTFD(pstate))
|
||||
{
|
||||
close(pstate->cn_outfd);
|
||||
}
|
||||
|
||||
pstate->cn_errfd = -1;
|
||||
pstate->cn_outfd = -1;
|
||||
pstate->cn_errstream = NULL;
|
||||
pstate->cn_outstream = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consolewrite
|
||||
*
|
||||
* Description:
|
||||
* write a buffer to the remote shell window.
|
||||
*
|
||||
* Currently only used by cat.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const void *buffer, size_t nbytes)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
ssize_t ret;
|
||||
|
||||
/* The stream is open in a lazy fashion. This is done because the file
|
||||
* descriptor may be opened on a different task than the stream. The
|
||||
* actual open will then occur with the first output from the new task.
|
||||
*/
|
||||
|
||||
if (nsh_openifnotopen(pstate) != 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Write the data to the output stream */
|
||||
|
||||
ret = fwrite(buffer, 1, nbytes, pstate->cn_outstream);
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: [%d] Failed to send buffer: %d\n",
|
||||
pstate->cn_outfd, errno);
|
||||
}
|
||||
|
||||
/* Flush the data to the output stream */
|
||||
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consoleoutput
|
||||
*
|
||||
* Description:
|
||||
* Print a string to the currently selected stream.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *fmt, ...)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
/* The stream is open in a lazy fashion. This is done because the file
|
||||
* descriptor may be opened on a different task than the stream. The
|
||||
* actual open will then occur with the first output from the new task.
|
||||
*/
|
||||
|
||||
if (nsh_openifnotopen(pstate) != 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vfprintf(pstate->cn_outstream, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_erroroutput
|
||||
*
|
||||
* Description:
|
||||
* Print a string to the currently selected error stream.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_erroroutput(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *fmt, ...)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
/* The stream is open in a lazy fashion. This is done because the file
|
||||
* descriptor may be opened on a different task than the stream. The
|
||||
* actual open will then occur with the first output from the new task.
|
||||
*/
|
||||
|
||||
if (nsh_openifnotopen(pstate) != 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vfprintf(pstate->cn_errstream, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consolelinebuffer
|
||||
*
|
||||
* Description:
|
||||
* Return a reference to the current line buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR char *nsh_consolelinebuffer(FAR struct nsh_vtbl_s *vtbl)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
return pstate->cn_line;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consoleclone
|
||||
*
|
||||
* Description:
|
||||
* Make an independent copy of the vtbl
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
static FAR struct nsh_vtbl_s *nsh_consoleclone(FAR struct nsh_vtbl_s *vtbl)
|
||||
{
|
||||
FAR struct console_stdio_s *pclone = nsh_newconsole();
|
||||
return &pclone->cn_vtbl;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consolerelease
|
||||
*
|
||||
* Description:
|
||||
* Release the cloned instance
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_consolerelease(FAR struct nsh_vtbl_s *vtbl)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
|
||||
/* Close the output stream */
|
||||
|
||||
nsh_closeifnotclosed(pstate);
|
||||
|
||||
/* Close the console stream */
|
||||
|
||||
#ifdef CONFIG_NSH_ALTCONDEV
|
||||
fclose(pstate->cn_constream);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_VARS
|
||||
/* Free any NSH variables */
|
||||
|
||||
if (pstate->varp != NULL)
|
||||
{
|
||||
free(pstate->varp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Then release the vtable container */
|
||||
|
||||
free(pstate);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consoleredirect
|
||||
*
|
||||
* Description:
|
||||
* Set up for redirected output. This function is called from nsh_parse()
|
||||
* in two different contexts:
|
||||
*
|
||||
* 1) Redirected background commands of the form: command > xyz.text &
|
||||
*
|
||||
* In this case:
|
||||
* - vtbl: A newly allocated and initialized instance created by
|
||||
* nsh_consoleclone,
|
||||
* - fd:- The file descriptor of the redirected output
|
||||
* - save: NULL
|
||||
*
|
||||
* nsh_consolerelease() will perform the clean-up when the clone is
|
||||
* destroyed.
|
||||
*
|
||||
* 2) Redirected foreground commands of the form: command > xyz.txt
|
||||
*
|
||||
* In this case:
|
||||
* - vtbl: The current state structure,
|
||||
* - fd: The file descriptor of the redirected output
|
||||
* - save: Where to save the re-directed registers.
|
||||
*
|
||||
* nsh_consoleundirect() will perform the clean-up after the redirected
|
||||
* command completes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_consoleredirect(FAR struct nsh_vtbl_s *vtbl, int fd,
|
||||
FAR uint8_t *save)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
FAR struct serialsave_s *ssave = (FAR struct serialsave_s *)save;
|
||||
|
||||
/* Case 1: Redirected foreground commands */
|
||||
|
||||
if (ssave)
|
||||
{
|
||||
/* pstate->cn_outstream and cn_outfd refer refer to the
|
||||
* currently opened output stream. If the output stream is open, flush
|
||||
* any pending output.
|
||||
*/
|
||||
|
||||
if (pstate->cn_outstream)
|
||||
{
|
||||
fflush(pstate->cn_errstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
}
|
||||
|
||||
/* Save the current fd and stream values. These will be restored
|
||||
* when nsh_consoleundirect() is called.
|
||||
*/
|
||||
|
||||
ssave->cn_errfd = pstate->cn_errfd;
|
||||
ssave->cn_outfd = pstate->cn_outfd;
|
||||
ssave->cn_errstream = pstate->cn_errstream;
|
||||
ssave->cn_outstream = pstate->cn_outstream;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nsh_consoleclone() set pstate->cn_outfd and cn_outstream to refer
|
||||
* to standard out. We just want to leave these alone and overwrite
|
||||
* them with the fd for the re-directed stream.
|
||||
*/
|
||||
}
|
||||
|
||||
/* In either case, set the fd of the new, re-directed output and nullify
|
||||
* the output stream (it will be fdopen'ed if it is used).
|
||||
*/
|
||||
|
||||
pstate->cn_outfd = fd;
|
||||
pstate->cn_outstream = NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consoleundirect
|
||||
*
|
||||
* Description:
|
||||
* Set up for redirected output
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_consoleundirect(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR uint8_t *save)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
FAR struct serialsave_s *ssave = (FAR struct serialsave_s *)save;
|
||||
|
||||
nsh_closeifnotclosed(pstate);
|
||||
pstate->cn_errfd = ssave->cn_errfd;
|
||||
pstate->cn_outfd = ssave->cn_outfd;
|
||||
pstate->cn_errstream = ssave->cn_errstream;
|
||||
pstate->cn_outstream = ssave->cn_outstream;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consoleexit
|
||||
*
|
||||
* Description:
|
||||
* Exit the shell task
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_consoleexit(FAR struct nsh_vtbl_s *vtbl, int exitstatus)
|
||||
{
|
||||
/* Destroy ourself then exit with the provided status */
|
||||
|
||||
nsh_consolerelease(vtbl);
|
||||
exit(exitstatus);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_newconsole
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct console_stdio_s *nsh_newconsole(void)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate =
|
||||
(FAR struct console_stdio_s *)zalloc(sizeof(struct console_stdio_s));
|
||||
|
||||
if (pstate)
|
||||
{
|
||||
/* Initialize the call table */
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
pstate->cn_vtbl.clone = nsh_consoleclone;
|
||||
pstate->cn_vtbl.release = nsh_consolerelease;
|
||||
#endif
|
||||
pstate->cn_vtbl.write = nsh_consolewrite;
|
||||
pstate->cn_vtbl.output = nsh_consoleoutput;
|
||||
pstate->cn_vtbl.error = nsh_erroroutput;
|
||||
pstate->cn_vtbl.linebuffer = nsh_consolelinebuffer;
|
||||
pstate->cn_vtbl.exit = nsh_consoleexit;
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLESCRIPT
|
||||
/* Set the initial option flags */
|
||||
|
||||
pstate->cn_vtbl.np.np_flags = NSH_NP_SET_OPTIONS_INIT;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
pstate->cn_vtbl.redirect = nsh_consoleredirect;
|
||||
pstate->cn_vtbl.undirect = nsh_consoleundirect;
|
||||
|
||||
/* Initialize the error stream */
|
||||
|
||||
pstate->cn_errfd = ERRFD(pstate);
|
||||
pstate->cn_errstream = ERRSTREAM(pstate);
|
||||
|
||||
/* Initialize the output stream */
|
||||
|
||||
pstate->cn_outfd = OUTFD(pstate);
|
||||
pstate->cn_outstream = OUTSTREAM(pstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
return pstate;
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_console.h
|
||||
*
|
||||
* Copyright (C) 2007-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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NSHLIB_NSH_CONSOLE_H
|
||||
#define __APPS_NSHLIB_NSH_CONSOLE_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Method access macros */
|
||||
|
||||
#define nsh_clone(v) (v)->clone(v)
|
||||
#define nsh_release(v) (v)->release(v)
|
||||
#define nsh_write(v,b,n) (v)->write(v,b,n)
|
||||
#define nsh_linebuffer(v) (v)->linebuffer(v)
|
||||
#define nsh_redirect(v,f,s) (v)->redirect(v,f,s)
|
||||
#define nsh_undirect(v,s) (v)->undirect(v,s)
|
||||
#define nsh_exit(v,s) (v)->exit(v,s)
|
||||
|
||||
#ifdef CONFIG_CPP_HAVE_VARARGS
|
||||
# define nsh_error(v, ...) (v)->error(v, ##__VA_ARGS__)
|
||||
# define nsh_output(v, ...) (v)->output(v, ##__VA_ARGS__)
|
||||
#else
|
||||
# define nsh_error vtbl->error
|
||||
# define nsh_output vtbl->output
|
||||
#endif
|
||||
|
||||
/* Size of info to be saved in call to nsh_redirect
|
||||
* See struct serialsave_s in nsh_console.c
|
||||
*/
|
||||
|
||||
#define SAVE_SIZE (2 * sizeof(int) + 2 * sizeof(FILE*))
|
||||
|
||||
/* Are we using the NuttX console for I/O? Or some other character device? */
|
||||
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
# ifdef CONFIG_NSH_ALTCONDEV
|
||||
|
||||
# if !defined(CONFIG_NSH_ALTSTDIN) && !defined(CONFIG_NSH_ALTSTDOUT) && \
|
||||
!defined(CONFIG_NSH_ALTSTDERR)
|
||||
# error CONFIG_NSH_ALTCONDEV selected but CONFIG_NSH_ALTSTDxxx not provided
|
||||
# endif
|
||||
|
||||
# define INFD(p) ((p)->cn_confd)
|
||||
# define INSTREAM(p) ((p)->cn_constream)
|
||||
# define OUTFD(p) ((p)->cn_outfd)
|
||||
# define OUTSTREAM(p) ((p)->cn_outstream)
|
||||
# define ERRFD(p) ((p)->cn_errfd)
|
||||
# define ERRSTREAM(p) ((p)->cn_errstream)
|
||||
|
||||
# else
|
||||
|
||||
# define INFD(p) 0
|
||||
# define INSTREAM(p) stdin
|
||||
# define OUTFD(p) 1
|
||||
# define OUTSTREAM(p) stdout
|
||||
# define ERRFD(p) 2
|
||||
# define ERRSTREAM(p) stderr
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This describes a generic console front-end */
|
||||
|
||||
struct nsh_vtbl_s
|
||||
{
|
||||
/* This function pointers are "hooks" into the front end logic to
|
||||
* handle things like output of command results, redirection, etc.
|
||||
* -- all of which must be done in a way that is unique to the nature
|
||||
* of the front end.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
FAR struct nsh_vtbl_s *(*clone)(FAR struct nsh_vtbl_s *vtbl);
|
||||
void (*addref)(FAR struct nsh_vtbl_s *vtbl);
|
||||
void (*release)(FAR struct nsh_vtbl_s *vtbl);
|
||||
#endif
|
||||
ssize_t (*write)(FAR struct nsh_vtbl_s *vtbl, FAR const void *buffer,
|
||||
size_t nbytes);
|
||||
int (*error)(FAR struct nsh_vtbl_s *vtbl, FAR const char *fmt, ...);
|
||||
int (*output)(FAR struct nsh_vtbl_s *vtbl, FAR const char *fmt, ...);
|
||||
FAR char *(*linebuffer)(FAR struct nsh_vtbl_s *vtbl);
|
||||
void (*redirect)(FAR struct nsh_vtbl_s *vtbl, int fd, FAR uint8_t *save);
|
||||
void (*undirect)(FAR struct nsh_vtbl_s *vtbl, FAR uint8_t *save);
|
||||
void (*exit)(FAR struct nsh_vtbl_s *vtbl, int status) noreturn_function;
|
||||
|
||||
#ifdef NSH_HAVE_IOBUFFER
|
||||
/* Common buffer for file I/O. */
|
||||
|
||||
char iobuffer[IOBUFFERSIZE];
|
||||
#endif
|
||||
|
||||
/* Parser state data */
|
||||
|
||||
struct nsh_parser_s np;
|
||||
};
|
||||
|
||||
/* This structure describes a console front-end that is based on stdin and
|
||||
* stdout (which is all of the supported console types at the time being).
|
||||
*/
|
||||
|
||||
struct console_stdio_s
|
||||
{
|
||||
/* NSH front-end call table */
|
||||
|
||||
struct nsh_vtbl_s cn_vtbl;
|
||||
|
||||
/* NSH input/output streams */
|
||||
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
#ifdef CONFIG_NSH_ALTCONDEV
|
||||
int cn_confd; /* Console I/O file descriptor */
|
||||
#endif
|
||||
int cn_outfd; /* Output file descriptor (possibly redirected) */
|
||||
int cn_errfd; /* Error Output file descriptor (possibly redirected) */
|
||||
#ifdef CONFIG_NSH_ALTCONDEV
|
||||
FILE *cn_constream; /* Console I/O stream (possibly redirected) */
|
||||
#endif
|
||||
FILE *cn_outstream; /* Output stream */
|
||||
FILE *cn_errstream; /* Error Output stream */
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_VARS
|
||||
/* Allocation and size of NSH variables */
|
||||
|
||||
FAR char *varp;
|
||||
size_t varsz;
|
||||
#endif
|
||||
|
||||
/* Line input buffer */
|
||||
|
||||
char cn_line[CONFIG_NSH_LINELEN];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Defined in nsh_console.c *************************************************/
|
||||
|
||||
FAR struct console_stdio_s *nsh_newconsole(void);
|
||||
|
||||
#endif /* __APPS_NSHLIB_NSH_CONSOLE_H */
|
||||
@@ -0,0 +1,123 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_consolemain.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-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 Gregory Nutt 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 <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/boardctl.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#include "netutils/netinit.h"
|
||||
|
||||
#if !defined(CONFIG_NSH_ALTCONDEV) && !defined(HAVE_USB_CONSOLE) && \
|
||||
!defined(HAVE_USB_KEYBOARD)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consolemain (Normal character device version)
|
||||
*
|
||||
* Description:
|
||||
* This interfaces may be to called or started with task_start to start a
|
||||
* single an NSH instance that operates on stdin and stdout. This
|
||||
* function does not normally return (see below).
|
||||
*
|
||||
* This version of nsh_consolmain handles generic /dev/console character
|
||||
* devices (see nsh_usbconsole.c and usb_usbkeyboard for other versions
|
||||
* for special USB console devices).
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard task start-up arguments. These are not used. argc may be
|
||||
* zero and argv may be NULL.
|
||||
*
|
||||
* Returned Values:
|
||||
* This function does not normally return. exit() is usually called to
|
||||
* terminate the NSH session. This function will return in the event of
|
||||
* an error. In that case, a non-zero value is returned (EXIT_FAILURE=1).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_consolemain(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = nsh_newconsole();
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(pstate != NULL);
|
||||
|
||||
#ifdef CONFIG_NSH_USBDEV_TRACE
|
||||
/* Initialize any USB tracing options that were requested */
|
||||
|
||||
usbtrace_enable(TRACE_BITSET);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSETC
|
||||
/* Execute the start-up script */
|
||||
|
||||
nsh_initscript(&pstate->cn_vtbl);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_NETINIT
|
||||
/* Bring up the network */
|
||||
|
||||
netinit_bringup();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_ARCHINIT) && defined(CONFIG_BOARDCTL_FINALINIT)
|
||||
/* Perform architecture-specific final-initialization (if configured) */
|
||||
|
||||
boardctl(BOARDIOC_FINALINIT, 0);
|
||||
#endif
|
||||
|
||||
/* Execute the session */
|
||||
|
||||
ret = nsh_session(pstate, true, argc, argv);
|
||||
|
||||
/* Exit upon return */
|
||||
|
||||
nsh_exit(&pstate->cn_vtbl, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_USB_CONSOLE && !HAVE_USB_KEYBOARD !HAVE_SLCD_CONSOLE */
|
||||
@@ -0,0 +1,514 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/dbg_dbgcmds.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2011-2012, 2015, 2017-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 <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#undef NSH_HAVE_MEMCMDS
|
||||
#if !defined(CONFIG_NSH_DISABLE_MB) || !defined(CONFIG_NSH_DISABLE_MH) || \
|
||||
!defined(CONFIG_NSH_DISABLE_MW)
|
||||
# define NSH_HAVE_MEMCMDS 1
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_MEMCMDS
|
||||
struct dbgmem_s
|
||||
{
|
||||
bool dm_write; /* true: perform write operation */
|
||||
FAR void *dm_addr; /* Address to access */
|
||||
uint32_t dm_value; /* Value to write */
|
||||
unsigned int dm_count; /* The number of bytes to access */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mem_parse
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_MEMCMDS
|
||||
static int mem_parse(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv,
|
||||
FAR struct dbgmem_s *mem)
|
||||
{
|
||||
FAR char *pcvalue = strchr(argv[1], '=');
|
||||
unsigned long lvalue = 0;
|
||||
|
||||
/* Check if we are writing a value */
|
||||
|
||||
if (pcvalue)
|
||||
{
|
||||
*pcvalue = '\0';
|
||||
pcvalue++;
|
||||
|
||||
lvalue = strtoul(pcvalue, NULL, 16);
|
||||
if (lvalue > 0xffffffffl)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mem->dm_write = true;
|
||||
mem->dm_value = (uint32_t)lvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem->dm_write = false;
|
||||
mem->dm_value = 0;
|
||||
}
|
||||
|
||||
/* Get the address to be accessed */
|
||||
|
||||
mem->dm_addr = (FAR void *)((uintptr_t)strtoul(argv[1], NULL, 16));
|
||||
|
||||
/* Get the number of bytes to access */
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
mem->dm_count = (unsigned int)strtoul(argv[2], NULL, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem->dm_count = 1;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_mb
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_MB
|
||||
int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
struct dbgmem_s mem;
|
||||
FAR volatile uint8_t *ptr;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
ret = mem_parse(vtbl, argc, argv, &mem);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Loop for the number of requested bytes */
|
||||
|
||||
for (i = 0, ptr = (volatile uint8_t *)mem.dm_addr; i < mem.dm_count;
|
||||
i++, ptr++)
|
||||
{
|
||||
/* Print the value at the address */
|
||||
|
||||
nsh_output(vtbl, " %p = 0x%02x", ptr, *ptr);
|
||||
|
||||
/* Are we supposed to write a value to this address? */
|
||||
|
||||
if (mem.dm_write)
|
||||
{
|
||||
/* Yes, was the supplied value within range? */
|
||||
|
||||
if (mem.dm_value > 0x000000ff)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrange, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Write the value and re-read the address so that we print its
|
||||
* current value (if the address is a process address, then the
|
||||
* value read might not necessarily be the value written).
|
||||
*/
|
||||
|
||||
*ptr = (uint8_t)mem.dm_value;
|
||||
nsh_output(vtbl, " -> 0x%02x", *ptr);
|
||||
}
|
||||
|
||||
/* Make sure we end it with a newline */
|
||||
|
||||
nsh_output(vtbl, "\n", *ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_mh
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_MH
|
||||
int cmd_mh(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
struct dbgmem_s mem;
|
||||
FAR volatile uint16_t *ptr;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
ret = mem_parse(vtbl, argc, argv, &mem);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Loop for the number of requested bytes */
|
||||
|
||||
for (i = 0, ptr = (volatile uint16_t *)mem.dm_addr;
|
||||
i < mem.dm_count;
|
||||
i += 2, ptr++)
|
||||
{
|
||||
/* Print the value at the address */
|
||||
|
||||
nsh_output(vtbl, " %p = 0x%04x", ptr, *ptr);
|
||||
|
||||
/* Are we supposed to write a value to this address? */
|
||||
|
||||
if (mem.dm_write)
|
||||
{
|
||||
/* Yes, was the supplied value within range? */
|
||||
|
||||
if (mem.dm_value > 0x0000ffff)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrange, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Write the value and re-read the address so that we print its
|
||||
* current value (if the address is a process address, then the
|
||||
* value read might not necessarily be the value written).
|
||||
*/
|
||||
|
||||
*ptr = (uint16_t)mem.dm_value;
|
||||
nsh_output(vtbl, " -> 0x%04x", *ptr);
|
||||
}
|
||||
|
||||
/* Make sure we end it with a newline */
|
||||
|
||||
nsh_output(vtbl, "\n", *ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_mw
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_MW
|
||||
int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
struct dbgmem_s mem;
|
||||
FAR volatile uint32_t *ptr;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
ret = mem_parse(vtbl, argc, argv, &mem);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Loop for the number of requested bytes */
|
||||
|
||||
for (i = 0, ptr = (volatile uint32_t *)mem.dm_addr; i < mem.dm_count;
|
||||
i += 4, ptr++)
|
||||
{
|
||||
/* Print the value at the address */
|
||||
|
||||
nsh_output(vtbl, " %p = 0x%08x", ptr, *ptr);
|
||||
|
||||
/* Are we supposed to write a value to this address? */
|
||||
|
||||
if (mem.dm_write)
|
||||
{
|
||||
/* Write the value and re-read the address so that we print its
|
||||
* current value (if the address is a process address, then the
|
||||
* value read might not necessarily be the value written).
|
||||
*/
|
||||
|
||||
*ptr = mem.dm_value;
|
||||
nsh_output(vtbl, " -> 0x%08x", *ptr);
|
||||
}
|
||||
|
||||
/* Make sure we end it with a newline */
|
||||
|
||||
nsh_output(vtbl, "\n", *ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_dumpbuffer
|
||||
****************************************************************************/
|
||||
|
||||
void nsh_dumpbuffer(FAR struct nsh_vtbl_s *vtbl, FAR const char *msg,
|
||||
FAR const uint8_t *buffer, ssize_t nbytes)
|
||||
{
|
||||
char line[128];
|
||||
int ch;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
nsh_output(vtbl, "%s:\n", msg);
|
||||
for (i = 0; i < nbytes; i += 16)
|
||||
{
|
||||
sprintf(line, "%04x: ", i);
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
if (i + j < nbytes)
|
||||
{
|
||||
sprintf(&line[strlen(line)], "%02x ", buffer[i + j]);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(&line[strlen(line)], " ");
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
if (i + j < nbytes)
|
||||
{
|
||||
ch = buffer[i + j];
|
||||
sprintf(&line[strlen(line)], "%c",
|
||||
ch >= 0x20 && ch <= 0x7e ? ch : '.');
|
||||
}
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%s\n", line);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_xd, hex dump of memory
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_XD
|
||||
int cmd_xd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
FAR char *addr;
|
||||
FAR char *endptr;
|
||||
int nbytes;
|
||||
|
||||
addr = (FAR char *)((uintptr_t)strtoul(argv[1], &endptr, 16));
|
||||
if (argv[0][0] == '\0' || *endptr != '\0')
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nbytes = (int)strtol(argv[2], &endptr, 0);
|
||||
if (argv[0][0] == '\0' || *endptr != '\0' || nbytes < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nsh_dumpbuffer(vtbl, "Hex dump", (uint8_t *)addr, nbytes);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_hexdump, hex dump of files
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_HEXDUMP
|
||||
int cmd_hexdump(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
FAR uint8_t *buffer;
|
||||
char msg[32];
|
||||
off_t position;
|
||||
int fd;
|
||||
int ret = OK;
|
||||
#ifdef CONFIG_NSH_CMDOPT_HEXDUMP
|
||||
off_t skip = 0;
|
||||
off_t count = 0xfffffff;
|
||||
off_t dumpbytes;
|
||||
int x;
|
||||
#endif
|
||||
|
||||
/* Open the file for reading */
|
||||
|
||||
fd = open(argv[1], O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "hexdump", "open", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
buffer = (FAR uint8_t *)malloc(IOBUFFERSIZE);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
close(fd);
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "hexdump", "malloc", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NSH_CMDOPT_HEXDUMP
|
||||
for (x = 2; x < argc; x++)
|
||||
{
|
||||
if (strncmp(argv[x], "skip=", 5) == 0)
|
||||
{
|
||||
skip = atoi(&argv[x][5]);
|
||||
}
|
||||
else if (strncmp(argv[x], "count=", 6) == 0)
|
||||
{
|
||||
count = atoi(&argv[x][6]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
position = 0;
|
||||
for (; ; )
|
||||
{
|
||||
int nbytesread = read(fd, buffer, IOBUFFERSIZE);
|
||||
|
||||
/* Check for read errors */
|
||||
|
||||
if (nbytesread < 0)
|
||||
{
|
||||
int errval = errno;
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "hexdump", "read",
|
||||
NSH_ERRNO_OF(errval));
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
else if (nbytesread > 0)
|
||||
{
|
||||
#ifdef CONFIG_NSH_CMDOPT_HEXDUMP
|
||||
if (position < skip)
|
||||
{
|
||||
/* Skip bytes until we reach the skip point */
|
||||
|
||||
position += nbytesread;
|
||||
if (position > skip)
|
||||
{
|
||||
dumpbytes = position - skip;
|
||||
if (dumpbytes > count)
|
||||
{
|
||||
dumpbytes = count;
|
||||
}
|
||||
|
||||
snprintf(msg, sizeof(msg), "%s at %08jx", argv[1],
|
||||
(uintmax_t)skip);
|
||||
nsh_dumpbuffer(vtbl, msg,
|
||||
&buffer[nbytesread - (position - skip)],
|
||||
dumpbytes);
|
||||
|
||||
if (count > dumpbytes)
|
||||
{
|
||||
count -= dumpbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't print if we are in skip mode */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Limit dumpbuffer to count if less than a full buffer needed */
|
||||
|
||||
if (nbytesread > count)
|
||||
{
|
||||
nbytesread = count;
|
||||
}
|
||||
#endif
|
||||
|
||||
snprintf(msg, sizeof(msg), "%s at %08jx", argv[1],
|
||||
(uintmax_t)position);
|
||||
nsh_dumpbuffer(vtbl, msg, buffer, nbytesread);
|
||||
position += nbytesread;
|
||||
|
||||
#ifdef CONFIG_NSH_CMDOPT_HEXDUMP
|
||||
if (count > nbytesread)
|
||||
{
|
||||
count -= nbytesread;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
break; /* EOF */
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_irqinfo
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_IRQINFO
|
||||
int cmd_irqinfo(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0], CONFIG_NSH_PROC_MOUNTPOINT "/irqs");
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,410 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_ddcmd.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2012, 2015 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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DD
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* If no sector size is specified with BS=, then the following default value
|
||||
* is used.
|
||||
*/
|
||||
|
||||
#define DEFAULT_SECTSIZE 512
|
||||
|
||||
/* At present, piping of input and output are not support, i.e., both of=
|
||||
* and if= arguments are required.
|
||||
*/
|
||||
|
||||
#undef CAN_PIPE_FROM_STD
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct dd_s
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl;
|
||||
|
||||
int infd; /* File descriptor of the input device */
|
||||
int outfd; /* File descriptor of the output device */
|
||||
uint32_t nsectors; /* Number of sectors to transfer */
|
||||
uint32_t sector; /* The current sector number */
|
||||
uint32_t skip; /* The number of sectors skipped on input */
|
||||
bool eof; /* true: The end of the input or output file has been hit */
|
||||
uint16_t sectsize; /* Size of one sector */
|
||||
uint16_t nbytes; /* Number of valid bytes in the buffer */
|
||||
uint8_t *buffer; /* Buffer of data to write to the output file */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const char g_dd[] = "dd";
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dd_write
|
||||
****************************************************************************/
|
||||
|
||||
static int dd_write(FAR struct dd_s *dd)
|
||||
{
|
||||
FAR uint8_t *buffer = dd->buffer;
|
||||
uint16_t written ;
|
||||
ssize_t nbytes;
|
||||
|
||||
/* Is the out buffer full (or is this the last one)? */
|
||||
|
||||
written = 0;
|
||||
do
|
||||
{
|
||||
nbytes = write(dd->outfd, buffer, dd->sectsize - written);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
|
||||
nsh_error(vtbl, g_fmtcmdfailed, g_dd, "write",
|
||||
NSH_ERRNO_OF(-nbytes));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
written += nbytes;
|
||||
buffer += nbytes;
|
||||
}
|
||||
while (written < dd->sectsize);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dd_read
|
||||
****************************************************************************/
|
||||
|
||||
static int dd_read(FAR struct dd_s *dd)
|
||||
{
|
||||
FAR uint8_t *buffer = dd->buffer;
|
||||
ssize_t nbytes;
|
||||
|
||||
dd->nbytes = 0;
|
||||
do
|
||||
{
|
||||
nbytes = read(dd->infd, buffer, dd->sectsize - dd->nbytes);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
|
||||
nsh_error(vtbl, g_fmtcmdfailed, g_dd, "read",
|
||||
NSH_ERRNO_OF(-nbytes));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
dd->nbytes += nbytes;
|
||||
buffer += nbytes;
|
||||
}
|
||||
while (dd->nbytes < dd->sectsize && nbytes > 0);
|
||||
|
||||
dd->eof |= (dd->nbytes == 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dd_infopen
|
||||
****************************************************************************/
|
||||
|
||||
static inline int dd_infopen(FAR const char *name, FAR struct dd_s *dd)
|
||||
{
|
||||
dd->infd = open(name, O_RDONLY);
|
||||
if (dd->infd < 0)
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
|
||||
nsh_error(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dd_outfopen
|
||||
****************************************************************************/
|
||||
|
||||
static inline int dd_outfopen(FAR const char *name, FAR struct dd_s *dd)
|
||||
{
|
||||
dd->outfd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (dd->outfd < 0)
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
|
||||
nsh_error(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_dd
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
struct dd_s dd;
|
||||
FAR char *infile = NULL;
|
||||
FAR char *outfile = NULL;
|
||||
#ifdef CONFIG_NSH_CMDOPT_DD_STATS
|
||||
struct timespec ts0;
|
||||
struct timespec ts1;
|
||||
uint64_t elapsed;
|
||||
uint64_t total;
|
||||
#endif
|
||||
int ret = ERROR;
|
||||
int i;
|
||||
|
||||
/* Initialize the dd structure */
|
||||
|
||||
memset(&dd, 0, sizeof(struct dd_s));
|
||||
dd.vtbl = vtbl; /* For nsh_output */
|
||||
dd.sectsize = DEFAULT_SECTSIZE; /* Sector size if 'bs=' not provided */
|
||||
dd.nsectors = 0xffffffff; /* MAX_UINT32 */
|
||||
|
||||
/* If no IF= option is provided on the command line, then read
|
||||
* from stdin.
|
||||
*/
|
||||
|
||||
#ifdef CAN_PIPE_FROM_STD
|
||||
dd->infd = 0; /* stdin */
|
||||
#endif
|
||||
|
||||
/* If no OF= option is provided on the command line, then write
|
||||
* to stdout.
|
||||
*/
|
||||
|
||||
#ifdef CAN_PIPE_FROM_STD
|
||||
dd->outfd = 1; /* stdout */
|
||||
#endif
|
||||
|
||||
/* Parse command line parameters */
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (strncmp(argv[i], "if=", 3) == 0)
|
||||
{
|
||||
if (infile != NULL)
|
||||
{
|
||||
free(infile);
|
||||
}
|
||||
|
||||
infile = nsh_getfullpath(vtbl, &argv[i][3]);
|
||||
}
|
||||
else if (strncmp(argv[i], "of=", 3) == 0)
|
||||
{
|
||||
if (outfile != NULL)
|
||||
{
|
||||
free(outfile);
|
||||
}
|
||||
|
||||
outfile = nsh_getfullpath(vtbl, &argv[i][3]);
|
||||
}
|
||||
else if (strncmp(argv[i], "bs=", 3) == 0)
|
||||
{
|
||||
dd.sectsize = atoi(&argv[i][3]);
|
||||
}
|
||||
else if (strncmp(argv[i], "count=", 6) == 0)
|
||||
{
|
||||
dd.nsectors = atoi(&argv[i][6]);
|
||||
}
|
||||
else if (strncmp(argv[i], "skip=", 5) == 0)
|
||||
{
|
||||
dd.skip = atoi(&argv[i][5]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CAN_PIPE_FROM_STD
|
||||
if (infile == NULL || outfile == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrequired, g_dd);
|
||||
goto errout_with_paths;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate the I/O buffer */
|
||||
|
||||
dd.buffer = malloc(dd.sectsize);
|
||||
if (!dd.buffer)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdoutofmemory, g_dd);
|
||||
goto errout_with_paths;
|
||||
}
|
||||
|
||||
/* Open the input file */
|
||||
|
||||
ret = dd_infopen(infile, &dd);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_paths;
|
||||
}
|
||||
|
||||
/* Open the output file */
|
||||
|
||||
ret = dd_outfopen(outfile, &dd);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_inf;
|
||||
}
|
||||
|
||||
/* Then perform the data transfer */
|
||||
|
||||
#ifdef CONFIG_NSH_CMDOPT_DD_STATS
|
||||
#ifdef CONFIG_CLOCK_MONOTONIC
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts0);
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
dd.sector = 0;
|
||||
while (!dd.eof && dd.nsectors > 0)
|
||||
{
|
||||
/* Read one sector from from the input */
|
||||
|
||||
ret = dd_read(&dd);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_outf;
|
||||
}
|
||||
|
||||
/* Has the incoming data stream ended? */
|
||||
|
||||
if (!dd.eof)
|
||||
{
|
||||
/* Pad with zero if necessary (at the end of file only) */
|
||||
|
||||
for (i = dd.nbytes; i < dd.sectsize; i++)
|
||||
{
|
||||
dd.buffer[i] = 0;
|
||||
}
|
||||
|
||||
/* Write one sector to the output file */
|
||||
|
||||
if (dd.sector >= dd.skip)
|
||||
{
|
||||
ret = dd_write(&dd);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_outf;
|
||||
}
|
||||
|
||||
/* Decrement to show that a sector was written */
|
||||
|
||||
dd.nsectors--;
|
||||
}
|
||||
|
||||
/* Increment the sector number */
|
||||
|
||||
dd.sector++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
|
||||
#ifdef CONFIG_NSH_CMDOPT_DD_STATS
|
||||
#ifdef CONFIG_CLOCK_MONOTONIC
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts1);
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts1);
|
||||
#endif
|
||||
|
||||
elapsed = (((uint64_t)ts1.tv_sec * NSEC_PER_SEC) + ts1.tv_nsec);
|
||||
elapsed -= (((uint64_t)ts0.tv_sec * NSEC_PER_SEC) + ts0.tv_nsec);
|
||||
elapsed /= NSEC_PER_MSEC; /* msec */
|
||||
|
||||
total = ((uint64_t)dd.sector * (uint64_t)dd.sectsize);
|
||||
|
||||
nsh_output(vtbl, "%llu bytes copied, %u msec, ",
|
||||
total, (unsigned int)elapsed);
|
||||
nsh_output(vtbl, "%u KB/s\n" ,
|
||||
(unsigned int)((double)total / (double)elapsed));
|
||||
#endif
|
||||
|
||||
errout_with_outf:
|
||||
close(dd.outfd);
|
||||
|
||||
errout_with_inf:
|
||||
close(dd.infd);
|
||||
free(dd.buffer);
|
||||
|
||||
errout_with_paths:
|
||||
if (infile)
|
||||
{
|
||||
nsh_freefullpath(infile);
|
||||
}
|
||||
|
||||
if (outfile)
|
||||
{
|
||||
nsh_freefullpath(outfile);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_NSH_DISABLE_DD */
|
||||
@@ -0,0 +1,582 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_envcmds.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2012, 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
static const char g_pwd[] = "PWD";
|
||||
#ifndef CONFIG_NSH_DISABLE_CD
|
||||
static const char g_oldpwd[] = "OLDPWD";
|
||||
#endif
|
||||
static const char g_home[] = CONFIG_LIB_HOMEDIR;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_getwd
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
static inline FAR const char *nsh_getwd(const char *wd)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
/* If no working directory is defined, then default to the home directory */
|
||||
|
||||
val = getenv(wd);
|
||||
if (val == NULL)
|
||||
{
|
||||
val = g_home;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_getdirpath
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
static inline char *nsh_getdirpath(FAR struct nsh_vtbl_s *vtbl,
|
||||
const char *dirpath, const char *relpath)
|
||||
{
|
||||
FAR char *alloc;
|
||||
int len;
|
||||
|
||||
/* Handle the special case where the dirpath is simply "/" */
|
||||
|
||||
if (strcmp(dirpath, "/") == 0)
|
||||
{
|
||||
len = strlen(relpath) + 2;
|
||||
alloc = (FAR char *)malloc(len);
|
||||
if (alloc)
|
||||
{
|
||||
sprintf(alloc, "/%s", relpath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = strlen(dirpath) + strlen(relpath) + 2;
|
||||
alloc = (FAR char *)malloc(len);
|
||||
if (alloc)
|
||||
{
|
||||
sprintf(alloc, "%s/%s", dirpath, relpath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!alloc)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdoutofmemory, "nsh_getdirpath");
|
||||
}
|
||||
|
||||
return alloc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_dumpvar
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NSH_VARS) && !defined(CONFIG_NSH_DISABLE_SET)
|
||||
static int nsh_dumpvar(FAR struct nsh_vtbl_s *vtbl, FAR void *arg,
|
||||
FAR const char *pair)
|
||||
{
|
||||
nsh_output(vtbl, "%s\n", pair);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_getwd
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
FAR const char *nsh_getcwd(void)
|
||||
{
|
||||
return nsh_getwd(g_pwd);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_getfullpath
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
FAR char *nsh_getfullpath(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *relpath)
|
||||
{
|
||||
const char *wd;
|
||||
|
||||
/* Handle some special cases */
|
||||
|
||||
if (!relpath || relpath[0] == '\0')
|
||||
{
|
||||
/* No relative path provided */
|
||||
|
||||
return strdup(g_home);
|
||||
}
|
||||
else if (relpath[0] == '/')
|
||||
{
|
||||
return strdup(relpath);
|
||||
}
|
||||
|
||||
/* Get the path to the current working directory */
|
||||
|
||||
wd = nsh_getcwd();
|
||||
|
||||
/* Fake the '.' directory */
|
||||
|
||||
if (strcmp(relpath, ".") == 0)
|
||||
{
|
||||
return strdup(wd);
|
||||
}
|
||||
|
||||
/* Return the full path */
|
||||
|
||||
return nsh_getdirpath(vtbl, wd, relpath);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_freefullpath
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
void nsh_freefullpath(FAR char *fullpath)
|
||||
{
|
||||
if (fullpath)
|
||||
{
|
||||
free(fullpath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_cd
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
#ifndef CONFIG_NSH_DISABLE_CD
|
||||
int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR const char *path = argv[1];
|
||||
FAR char *alloc = NULL;
|
||||
FAR char *fullpath = NULL;
|
||||
int ret = OK;
|
||||
|
||||
/* Check for special arguments */
|
||||
|
||||
if (argc < 2 || strcmp(path, "~") == 0)
|
||||
{
|
||||
path = g_home;
|
||||
}
|
||||
else if (strcmp(path, "-") == 0)
|
||||
{
|
||||
alloc = strdup(nsh_getwd(g_oldpwd));
|
||||
path = alloc;
|
||||
}
|
||||
else if (strcmp(path, "..") == 0)
|
||||
{
|
||||
alloc = strdup(nsh_getcwd());
|
||||
path = dirname(alloc);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullpath = nsh_getfullpath(vtbl, path);
|
||||
path = fullpath;
|
||||
}
|
||||
|
||||
/* Set the new working directory */
|
||||
|
||||
ret = chdir(path);
|
||||
if (ret != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "chdir", NSH_ERRNO);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
/* Free any memory that was allocated */
|
||||
|
||||
if (alloc)
|
||||
{
|
||||
free(alloc);
|
||||
}
|
||||
|
||||
if (fullpath)
|
||||
{
|
||||
nsh_freefullpath(fullpath);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_echo
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_ECHO
|
||||
int cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int s = 1;
|
||||
|
||||
if (argc > 1 && 0 == strncmp(argv[1], "-n", 2))
|
||||
{
|
||||
s = 2;
|
||||
}
|
||||
|
||||
/* echo each argument, separated by a space as it must have been on the
|
||||
* command line.
|
||||
*/
|
||||
|
||||
for (i = s; i < argc; i++)
|
||||
{
|
||||
if (i != s)
|
||||
{
|
||||
nsh_output(vtbl, " ");
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%s", argv[i]);
|
||||
}
|
||||
|
||||
if (1 == s)
|
||||
{
|
||||
nsh_output(vtbl, "\n");
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_env
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_ENV
|
||||
int cmd_env(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0],
|
||||
CONFIG_NSH_PROC_MOUNTPOINT "/self/group/env");
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_pwd
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
#ifndef CONFIG_NSH_DISABLE_PWD
|
||||
int cmd_pwd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "%s\n", nsh_getcwd());
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_set
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_SET
|
||||
int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR char *value;
|
||||
int ret = OK;
|
||||
#ifdef NSH_HAVE_VARS
|
||||
int ndx = 1;
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLESCRIPT
|
||||
FAR char *popt;
|
||||
const char opts[] = NSH_NP_SET_OPTIONS;
|
||||
int op;
|
||||
|
||||
#ifdef CONFIG_NSH_VARS
|
||||
/* Set with no arguments will show all of the NSH variables */
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
ret = nsh_foreach_var(vtbl, nsh_dumpvar, NULL);
|
||||
nsh_output(vtbl, "\n");
|
||||
return ret < 0 ? ERROR : OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef NSH_HAVE_VARS
|
||||
/* Support set [{+|-}{e|x|xe|ex}] [<name> <value>] */
|
||||
|
||||
if (argc == 2 || argc == 4)
|
||||
#else
|
||||
/* Support set [{+|-}{e|x|xe|ex}] */
|
||||
|
||||
#endif
|
||||
{
|
||||
if (strlen(argv[1]) < 2)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0], "set", NSH_ERRNO);
|
||||
}
|
||||
else
|
||||
{
|
||||
op = argv[1][0];
|
||||
if (op != '-' && op != '+')
|
||||
{
|
||||
ret = -EINVAL;
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0], "set", NSH_ERRNO);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = &argv[1][1];
|
||||
while (*value && *value != ' ')
|
||||
{
|
||||
popt = strchr(opts, *value++);
|
||||
if (popt == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid,
|
||||
argv[0], "set", NSH_ERRNO);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (op == '+')
|
||||
{
|
||||
vtbl->np.np_flags |= 1 << (popt - opts);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtbl->np.np_flags &= ~(1 << (popt - opts));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NSH_HAVE_VARS
|
||||
if (ret == OK)
|
||||
{
|
||||
ndx = 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NSH_HAVE_VARS
|
||||
if (ret == OK && (argc == 3 || argc == 4))
|
||||
#endif
|
||||
#endif /* CONFIG_NSH_DISABLESCRIPT */
|
||||
#ifdef NSH_HAVE_VARS
|
||||
{
|
||||
#if defined(CONFIG_NSH_VARS) && !defined(CONFIG_DISABLE_ENVIRON)
|
||||
FAR char *oldvalue;
|
||||
#endif
|
||||
|
||||
/* Trim whitespace from the value */
|
||||
|
||||
value = nsh_trimspaces(argv[ndx + 1]);
|
||||
|
||||
#ifdef CONFIG_NSH_VARS
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
/* Check if the NSH variable has already been promoted to an group-
|
||||
* wide environment variable.
|
||||
*
|
||||
* REVISIT: Is this the correct behavior? Bash would create/modify
|
||||
* a local variable that shadows the environment variable.
|
||||
*/
|
||||
|
||||
oldvalue = getenv(argv[ndx]);
|
||||
if (oldvalue == NULL)
|
||||
#endif
|
||||
{
|
||||
/* Set the NSH variable */
|
||||
|
||||
ret = nsh_setvar(vtbl, argv[ndx], value);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "nsh_setvar",
|
||||
NSH_ERRNO_OF(-ret));
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NSH_VARS */
|
||||
|
||||
#if !defined(CONFIG_DISABLE_ENVIRON)
|
||||
#ifdef CONFIG_NSH_VARS
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Set the environment variable */
|
||||
|
||||
ret = setenv(argv[ndx], value, TRUE);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "setenv",
|
||||
NSH_ERRNO);
|
||||
}
|
||||
}
|
||||
#endif /* !CONFIG_DISABLE_ENVIRON */
|
||||
}
|
||||
#endif /* NSH_HAVE_VARS */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NSH_DISABLE_SET */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_unset
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_UNSET
|
||||
int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
#if defined(CONFIG_NSH_VARS) || !defined(CONFIG_DISABLE_ENVIRON)
|
||||
int status;
|
||||
#endif
|
||||
int ret = OK;
|
||||
|
||||
#if defined(CONFIG_NSH_VARS)
|
||||
/* Unset NSH variable */
|
||||
|
||||
status = nsh_unsetvar(vtbl, argv[1]);
|
||||
if (status < 0 && status != -ENOENT)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "nsh_unsetvar",
|
||||
NSH_ERRNO_OF(-status));
|
||||
ret = ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_DISABLE_ENVIRON)
|
||||
/* Unset environment variable */
|
||||
|
||||
status = unsetenv(argv[1]);
|
||||
if (status < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO);
|
||||
ret = ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_export
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_EXPORT
|
||||
int cmd_export(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR const char *value = "";
|
||||
int status;
|
||||
int ret = OK;
|
||||
|
||||
/* Get the value from the command line if provided. argc may be either 2
|
||||
* or 3
|
||||
*/
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
value = argv[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR const char *tmp;
|
||||
|
||||
/* Try to get the value from the NSH variable */
|
||||
|
||||
tmp = nsh_getvar(vtbl, argv[1]);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
value = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the environment variable to the selected value */
|
||||
|
||||
status = setenv(argv[1], value, TRUE);
|
||||
if (status < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO);
|
||||
ret = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unset NSH variable.
|
||||
*
|
||||
* REVISIT: Is this the correct behavior? Bash would retain
|
||||
* a local variable that shadows the environment variable.
|
||||
*/
|
||||
|
||||
status = nsh_unsetvar(vtbl, argv[1]);
|
||||
if (status < 0 && status != -ENOENT)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "nsh_unsetvar",
|
||||
NSH_ERRNO_OF(-status));
|
||||
ret = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_fileapps.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#ifdef CONFIG_SCHED_WAITPID
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <spawn.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_FILE_APPS
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_fileapp
|
||||
*
|
||||
* Description:
|
||||
* Attempt to execute the application task whose name is 'cmd'
|
||||
*
|
||||
* Returned Value:
|
||||
* <0 If posix_spawn() 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 rc = 0;
|
||||
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_error(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_error(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_error(vtbl, g_fmtcmdfailed, cmd,
|
||||
"posix_spawn_file_actions_addopen",
|
||||
NSH_ERRNO);
|
||||
goto errout_with_attrs;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the scheduler in an attempt to prevent the application from
|
||||
* running until 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 where I/O was redirected,
|
||||
* a proxy task ran and broke our lock. As result, the application may
|
||||
* have aso ran if its priority was higher than than the priority of
|
||||
* this thread.
|
||||
*
|
||||
* If the application did not run to completion 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
|
||||
/* 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 */
|
||||
{
|
||||
/* Setup up to receive SIGINT if control-C entered. The return
|
||||
* value is ignored because this console device may not support
|
||||
* SIGINT.
|
||||
*/
|
||||
|
||||
ioctl(stdout->fs_fd, TIOCSCTTY, pid);
|
||||
|
||||
/* Wait for the application to exit. We did lock the scheduler
|
||||
* above, but that does not guarantee that the application did not
|
||||
* already run to completion in the case where I/O was redirected.
|
||||
* Here the scheduler will be unlocked while waitpid is waiting
|
||||
* and if the application has not yet run, it will now be able to
|
||||
* do so.
|
||||
*
|
||||
* NOTE: WUNTRACED does nothing in the default case, but in the
|
||||
* case the where CONFIG_SIG_SIGSTOP_ACTION=y, the file app
|
||||
* may also be stopped. In that case WUNTRACED will force
|
||||
* waitpid() to return with ECHILD.
|
||||
*/
|
||||
|
||||
ret = waitpid(pid, &rc, WUNTRACED);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* If the child thread doesn't exist, waitpid() will return the
|
||||
* error ECHLD. Since we know that the task was successfully
|
||||
* started, this must be one of the cases described above; we
|
||||
* have to assume that the task already exit'ed. In this case,
|
||||
* we have no idea if the application ran successfully or not
|
||||
* (because NuttX does not retain exit status of child tasks).
|
||||
* Let's assume that is did run successfully.
|
||||
*/
|
||||
|
||||
int errcode = errno;
|
||||
if (errcode == ECHILD)
|
||||
{
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "waitpid",
|
||||
NSH_ERRNO_OF(errcode));
|
||||
}
|
||||
}
|
||||
|
||||
/* Waitpid completed the wait successfully */
|
||||
|
||||
else
|
||||
{
|
||||
/* Ignore the returned child pid */
|
||||
|
||||
ret = OK;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
}
|
||||
|
||||
ioctl(stdout->fs_fd, TIOCSCTTY, -1);
|
||||
}
|
||||
# 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, ¶m);
|
||||
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 attributes and file actions. Ignoring return values in the case
|
||||
* of an error.
|
||||
*/
|
||||
|
||||
errout_with_actions:
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
|
||||
errout_with_attrs:
|
||||
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 */
|
||||
|
||||
errno = ret;
|
||||
ret = ERROR;
|
||||
}
|
||||
else if (ret < 0)
|
||||
{
|
||||
/* Return -1 on failure. errno should have been set. */
|
||||
|
||||
ret = ERROR;
|
||||
}
|
||||
else if (rc != 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 = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_FILE_APPS */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,447 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_fsutils.c
|
||||
*
|
||||
* Copyright (C) 2015 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 <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_catfile
|
||||
*
|
||||
* Description:
|
||||
* Dump the contents of a file to the current NSH terminal.
|
||||
*
|
||||
* Input Paratemets:
|
||||
* vtbl - session vtbl
|
||||
* cmd - NSH command name to use in error reporting
|
||||
* filepath - The full path to the file to be dumped
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; -1 (ERROR) on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_CATFILE
|
||||
int nsh_catfile(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
|
||||
FAR const char *filepath)
|
||||
{
|
||||
FAR char *buffer;
|
||||
int fd;
|
||||
int ret = OK;
|
||||
|
||||
/* Open the file for reading */
|
||||
|
||||
fd = open(filepath, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
#if defined(CONFIG_NSH_PROC_MOUNTPOINT)
|
||||
if (strncmp(filepath, CONFIG_NSH_PROC_MOUNTPOINT,
|
||||
strlen(CONFIG_NSH_PROC_MOUNTPOINT)) == 0)
|
||||
{
|
||||
nsh_error(vtbl,
|
||||
"nsh: %s: Could not open %s (is procfs mounted?): %d\n",
|
||||
cmd, filepath, NSH_ERRNO);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO);
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
buffer = (FAR char *)malloc(IOBUFFERSIZE);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
close(fd);
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "malloc", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* And just dump it byte for byte into stdout */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
int nbytesread = read(fd, buffer, IOBUFFERSIZE);
|
||||
|
||||
/* Check for read errors */
|
||||
|
||||
if (nbytesread < 0)
|
||||
{
|
||||
int errval = errno;
|
||||
|
||||
/* EINTR is not an error (but will stop stop the cat) */
|
||||
|
||||
if (errval == EINTR)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtsignalrecvd, cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "read",
|
||||
NSH_ERRNO_OF(errval));
|
||||
}
|
||||
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for data successfully read */
|
||||
|
||||
else if (nbytesread > 0)
|
||||
{
|
||||
int nbyteswritten = 0;
|
||||
|
||||
while (nbyteswritten < nbytesread)
|
||||
{
|
||||
ssize_t n = nsh_write(vtbl, buffer + nbyteswritten,
|
||||
nbytesread - nbyteswritten);
|
||||
if (n < 0)
|
||||
{
|
||||
int errcode = errno;
|
||||
|
||||
/* EINTR is not an error (but will stop stop the cat) */
|
||||
|
||||
if (errcode == EINTR)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtsignalrecvd, cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "write",
|
||||
NSH_ERRNO_OF(errcode));
|
||||
}
|
||||
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
nbyteswritten += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, it is the end of file */
|
||||
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE that the following NSH prompt may appear on the same line as file
|
||||
* content. The IEEE Std requires that "The standard output shall
|
||||
* contain the sequence of bytes read from the input files. Nothing else
|
||||
* shall be written to the standard output." Reference:
|
||||
* https://pubs.opengroup.org/onlinepubs/009695399/utilities/cat.html.
|
||||
*/
|
||||
|
||||
/* Close the input file and return the result */
|
||||
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_readfile
|
||||
*
|
||||
* Description:
|
||||
* Read a small file into a user-provided buffer. The data is assumed to
|
||||
* be a string and is guaranteed to be NUL-termined. An error occurs if
|
||||
* the file content (+terminator) will not fit into the provided 'buffer'.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtbl - The console vtable
|
||||
* filepath - The full path to the file to be read
|
||||
* buffer - The user-provided buffer into which the file is read.
|
||||
* buflen - The size of the user provided buffer
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; -1 (ERROR) is returned on any
|
||||
* failure to read the fil into the buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_READFILE
|
||||
int nsh_readfile(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
|
||||
FAR const char *filepath, FAR char *buffer, size_t buflen)
|
||||
{
|
||||
FAR char *bufptr;
|
||||
size_t remaining;
|
||||
ssize_t nread;
|
||||
ssize_t ntotal;
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
/* Open the file */
|
||||
|
||||
fd = open(filepath, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Read until we hit the end of the file, until we have exhausted the
|
||||
* buffer space, or until some irrecoverable error occurs
|
||||
*/
|
||||
|
||||
ntotal = 0; /* No bytes read yet */
|
||||
*buffer = '\0'; /* NUL terminate the empty buffer */
|
||||
bufptr = buffer; /* Working pointer */
|
||||
remaining = buflen - 1; /* Reserve one byte for a NUL terminator */
|
||||
ret = ERROR; /* Assume failure */
|
||||
|
||||
do
|
||||
{
|
||||
nread = read(fd, bufptr, remaining);
|
||||
if (nread < 0)
|
||||
{
|
||||
/* Read error */
|
||||
|
||||
int errcode = errno;
|
||||
DEBUGASSERT(errcode > 0);
|
||||
|
||||
/* EINTR is not a read error. It simply means that a signal was
|
||||
* received while waiting for the read to complete.
|
||||
*/
|
||||
|
||||
if (errcode != EINTR)
|
||||
{
|
||||
/* Fatal error */
|
||||
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "read", NSH_ERRNO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (nread == 0)
|
||||
{
|
||||
/* End of file */
|
||||
|
||||
ret = OK;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Successful read. Make sure that the buffer is null terminated */
|
||||
|
||||
DEBUGASSERT(nread <= remaining);
|
||||
ntotal += nread;
|
||||
buffer[ntotal] = '\0';
|
||||
|
||||
/* Bump up the read count and continuing reading to the end of
|
||||
* file.
|
||||
*/
|
||||
|
||||
bufptr += nread;
|
||||
remaining -= nread;
|
||||
}
|
||||
}
|
||||
while (buflen > 0);
|
||||
|
||||
/* Close the file and return. */
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_foreach_direntry
|
||||
*
|
||||
* Description:
|
||||
* Call the provided 'handler' for each entry found in the directory at
|
||||
* 'dirpath'.
|
||||
*
|
||||
* Input Parameters
|
||||
* vtbl - The console vtable
|
||||
* cmd - NSH command name to use in error reporting
|
||||
* dirpath - The full path to the directory to be traversed
|
||||
* handler - The handler to be called for each entry of the directory
|
||||
* pvarg - User provided argument to be passed to the 'handler'
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) returned on success; -1 (ERROR) returned on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_FOREACH_DIRENTRY
|
||||
int nsh_foreach_direntry(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
|
||||
FAR const char *dirpath,
|
||||
nsh_direntry_handler_t handler, void *pvarg)
|
||||
{
|
||||
DIR *dirp;
|
||||
int ret = OK;
|
||||
|
||||
/* Open the directory */
|
||||
|
||||
dirp = opendir(dirpath);
|
||||
if (dirp == NULL)
|
||||
{
|
||||
/* Failed to open the directory */
|
||||
|
||||
#if defined(CONFIG_NSH_PROC_MOUNTPOINT)
|
||||
if (strncmp(dirpath, CONFIG_NSH_PROC_MOUNTPOINT,
|
||||
strlen(CONFIG_NSH_PROC_MOUNTPOINT)) == 0)
|
||||
{
|
||||
nsh_error(vtbl,
|
||||
"nsh: %s: Could not open %s (is procfs mounted?): %d\n",
|
||||
cmd, dirpath, NSH_ERRNO);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nsh_error(vtbl, g_fmtnosuch, cmd, "directory", dirpath);
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Read each directory entry */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
FAR struct dirent *entryp = readdir(dirp);
|
||||
if (entryp == NULL)
|
||||
{
|
||||
/* Finished with this directory */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call the handler with this directory entry */
|
||||
|
||||
if (handler(vtbl, dirpath, entryp, pvarg) < 0)
|
||||
{
|
||||
/* The handler reported a problem */
|
||||
|
||||
ret = ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_trimdir
|
||||
*
|
||||
* Description:
|
||||
* Skip any trailing '/' characters (unless it is also the leading '/')
|
||||
*
|
||||
* Input Parameters:
|
||||
* dirpath - The directory path to be trimmed. May be modified!
|
||||
*
|
||||
* Returned value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_TRIMDIR
|
||||
void nsh_trimdir(FAR char *dirpath)
|
||||
{
|
||||
/* Skip any trailing '/' characters (unless it is also the leading '/') */
|
||||
|
||||
int len = strlen(dirpath) - 1;
|
||||
while (len > 0 && dirpath[len] == '/')
|
||||
{
|
||||
dirpath[len] = '\0';
|
||||
len--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_trimspaces
|
||||
*
|
||||
* Description:
|
||||
* Trim any leading or trailing spaces from a string.
|
||||
*
|
||||
* Input Parameters:
|
||||
* str - The string to be trimmed. May be modified!
|
||||
*
|
||||
* Returned value:
|
||||
* The new string pointer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef NSH_HAVE_TRIMSPACES
|
||||
FAR char *nsh_trimspaces(FAR char *str)
|
||||
{
|
||||
FAR char *trimmed;
|
||||
int ndx;
|
||||
|
||||
/* Strip leading whitespace from the value */
|
||||
|
||||
for (trimmed = str;
|
||||
*trimmed != '\0' && isspace(*trimmed);
|
||||
trimmed++);
|
||||
|
||||
/* Strip trailing whitespace from the value */
|
||||
|
||||
for (ndx = strlen(trimmed) - 1;
|
||||
ndx >= 0 && isspace(trimmed[ndx]);
|
||||
ndx--)
|
||||
{
|
||||
trimmed[ndx] = '\0';
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_init.c
|
||||
*
|
||||
* Copyright (C) 2007-2012, 2014-2015 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 <sys/boardctl.h>
|
||||
|
||||
#include "system/readline.h"
|
||||
#include "nshlib/nshlib.h"
|
||||
|
||||
#include "nsh.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NSH_READLINE) && defined(CONFIG_READLINE_TABCOMPLETION) && \
|
||||
defined(CONFIG_READLINE_HAVE_EXTMATCH)
|
||||
static const struct extmatch_vtable_s g_nsh_extmatch =
|
||||
{
|
||||
nsh_extmatch_count, /* count_matches */
|
||||
nsh_extmatch_getname /* getname */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_initialize
|
||||
*
|
||||
* Description:
|
||||
* This nterfaces is used to initialize the NuttShell (NSH).
|
||||
* nsh_initialize() should be called one during application start-up prior
|
||||
* to executing either nsh_consolemain() or nsh_telnetstart().
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nsh_initialize(void)
|
||||
{
|
||||
#if defined(CONFIG_NSH_READLINE) && defined(CONFIG_READLINE_TABCOMPLETION)
|
||||
/* Configure the NSH prompt */
|
||||
|
||||
readline_prompt(g_nshprompt);
|
||||
|
||||
#ifdef CONFIG_READLINE_HAVE_EXTMATCH
|
||||
/* Set up for tab completion on NSH commands */
|
||||
|
||||
readline_extmatch(&g_nsh_extmatch);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Mount the /etc filesystem */
|
||||
|
||||
(void)nsh_romfsetc();
|
||||
|
||||
#ifdef CONFIG_NSH_ARCHINIT
|
||||
/* Perform architecture-specific initialization (if configured) */
|
||||
|
||||
boardctl(BOARDIOC_INIT, 0);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_login.c
|
||||
*
|
||||
* Copyright (C) 2016, 2019 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
# include "system/cle.h"
|
||||
#else
|
||||
# include "system/readline.h"
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_CONSOLE_LOGIN
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_token
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_token(FAR struct console_stdio_s *pstate,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
FAR char *start;
|
||||
FAR char *endp1;
|
||||
bool quoted = false;
|
||||
|
||||
/* Find the start of token. Either (1) the first non-white space
|
||||
* character on the command line or (2) the character immediately after
|
||||
* a quotation mark.
|
||||
*/
|
||||
|
||||
for (start = pstate->cn_line; *start; start++)
|
||||
{
|
||||
/* Does the token open with a quotation mark */
|
||||
|
||||
if (*start == '"')
|
||||
{
|
||||
/* Yes.. break out with start set to the character after the
|
||||
* quotation mark.
|
||||
*/
|
||||
|
||||
quoted = true;
|
||||
start++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* No, then any non-whitespace is the first character of the token */
|
||||
|
||||
else if (!isspace(*start))
|
||||
{
|
||||
/* Break out with start set to the first character of the token */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the terminating character after the token on the command line. The
|
||||
* terminating character is either (1) the matching quotation mark, or (2)
|
||||
* any whitespace.
|
||||
*/
|
||||
|
||||
for (endp1 = start; *endp1; endp1++)
|
||||
{
|
||||
/* Did the token begin with a quotation mark? */
|
||||
|
||||
if (quoted)
|
||||
{
|
||||
/* Yes.. then only the matching quotation mark (or end of string)
|
||||
* terminates
|
||||
*/
|
||||
|
||||
if (*endp1 == '"')
|
||||
{
|
||||
/* Break out... endp1 points to closing quotation mark */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No.. any whitespace (or end of string) terminates */
|
||||
|
||||
else if (isspace(*endp1))
|
||||
{
|
||||
/* Break out... endp1 points to first while space encountered */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace terminating character with a NUL terminator */
|
||||
|
||||
*endp1 = '\0';
|
||||
|
||||
/* Copied the token into the buffer */
|
||||
|
||||
strncpy(buffer, start, buflen);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_login
|
||||
*
|
||||
* Description:
|
||||
* Prompt the user for a username and password. Return a failure if valid
|
||||
* credentials are not returned (after some retries.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_login(FAR struct console_stdio_s *pstate)
|
||||
{
|
||||
char username[16];
|
||||
char password[16];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Loop for the configured number of retries */
|
||||
|
||||
for (i = 0; i < CONFIG_NSH_LOGIN_FAILCOUNT; i++)
|
||||
{
|
||||
/* Ask for the login username */
|
||||
|
||||
username[0] = '\0';
|
||||
fputs(g_userprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* readline() returns EOF on failure */
|
||||
|
||||
ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate), OUTSTREAM(pstate));
|
||||
if (ret != EOF)
|
||||
{
|
||||
/* Parse out the username */
|
||||
|
||||
nsh_token(pstate, username, sizeof(username));
|
||||
}
|
||||
|
||||
/* Ask for the login password */
|
||||
|
||||
fputs(g_passwordprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
password[0] = '\0';
|
||||
if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate)) != NULL)
|
||||
{
|
||||
/* Parse out the password */
|
||||
|
||||
nsh_token(pstate, password, sizeof(password));
|
||||
|
||||
/* Verify the username and password */
|
||||
|
||||
#if defined(CONFIG_NSH_LOGIN_PASSWD)
|
||||
ret = passwd_verify(username, password);
|
||||
if (PASSWORD_VERIFY_MATCH(ret))
|
||||
|
||||
#elif defined(CONFIG_NSH_LOGIN_PLATFORM)
|
||||
ret = platform_user_verify(username, password);
|
||||
if (PASSWORD_VERIFY_MATCH(ret))
|
||||
|
||||
#elif defined(CONFIG_NSH_LOGIN_FIXED)
|
||||
if (strcmp(password, CONFIG_NSH_LOGIN_PASSWORD) == 0 &&
|
||||
strcmp(username, CONFIG_NSH_LOGIN_USERNAME) == 0)
|
||||
#else
|
||||
# error No user verification method selected
|
||||
#endif
|
||||
{
|
||||
fputs(g_loginsuccess, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs(g_badcredentials, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
#if CONFIG_NSH_LOGIN_FAILDELAY > 0
|
||||
usleep(CONFIG_NSH_LOGIN_FAILDELAY * 1000L);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Too many failed login attempts */
|
||||
|
||||
fputs(g_loginfailure, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_CONSOLE_LOGIN */
|
||||
@@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_mmcmds.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2017 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 "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLE_FREE) && defined(NSH_HAVE_CATFILE)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_free
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_free(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0], CONFIG_NSH_PROC_MOUNTPOINT "/meminfo");
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_NSH_DISABLE_FREE && NSH_HAVE_CATFILE */
|
||||
@@ -0,0 +1,382 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_mntcmds.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <nuttx/fs/nfs.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_df
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_DF)
|
||||
#ifdef NSH_HAVE_CATFILE
|
||||
int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
#if defined(HAVE_DF_HUMANREADBLE) && defined(HAVE_DF_BLOCKOUTPUT)
|
||||
if (argc > 1 && strcmp(argv[1], "-h") == 0)
|
||||
#endif
|
||||
#ifdef HAVE_DF_HUMANREADBLE
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0],
|
||||
CONFIG_NSH_PROC_MOUNTPOINT "/fs/usage");
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_DF_HUMANREADBLE) && defined(HAVE_DF_BLOCKOUTPUT)
|
||||
else
|
||||
#endif
|
||||
#ifdef HAVE_DF_BLOCKOUTPUT
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0],
|
||||
CONFIG_NSH_PROC_MOUNTPOINT "/fs/blocks");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_mount
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_MOUNT)
|
||||
int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR const char *source;
|
||||
FAR char *fullsource;
|
||||
FAR const char *target;
|
||||
FAR char *fulltarget;
|
||||
FAR const char *filesystem = NULL;
|
||||
FAR const char *options = NULL;
|
||||
bool badarg = false;
|
||||
int option;
|
||||
int ret;
|
||||
|
||||
/* The mount command behaves differently if no parameters are provided. */
|
||||
|
||||
#if defined(NSH_HAVE_CATFILE) && defined(HAVE_MOUNT_LIST)
|
||||
if (argc < 2)
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0],
|
||||
CONFIG_NSH_PROC_MOUNTPOINT "/fs/mount");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the mount options. NOTE: getopt() is not thread safe nor re-
|
||||
* entrant. To keep its state proper for the next usage, it is necessary
|
||||
* to parse to the end of the line even if an error occurs. If an error
|
||||
* occurs, this logic just sets 'badarg' and continues.
|
||||
*/
|
||||
|
||||
while ((option = getopt(argc, argv, ":o:t:")) != ERROR)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case 't':
|
||||
filesystem = optarg;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
options = optarg;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
badarg = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
badarg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a bad argument was encountered, then return without processing the
|
||||
* command.
|
||||
*/
|
||||
|
||||
if (badarg)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* There may be one or two required arguments after the options: the source
|
||||
* and target paths. Some file systems do not require the source parameter
|
||||
* so if there is only one parameter left, it must be the target.
|
||||
*/
|
||||
|
||||
if (optind >= argc)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
source = NULL;
|
||||
target = argv[optind];
|
||||
optind++;
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
source = target;
|
||||
target = argv[optind];
|
||||
optind++;
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
nsh_error(vtbl, g_fmttoomanyargs, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* While the above parsing for the -t argument looks nice, the -t argument
|
||||
* not really optional.
|
||||
*/
|
||||
|
||||
if (!filesystem)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* The source and target paths might be relative to the current
|
||||
* working directory.
|
||||
*/
|
||||
|
||||
fullsource = NULL;
|
||||
fulltarget = NULL;
|
||||
|
||||
if (source)
|
||||
{
|
||||
fullsource = nsh_getfullpath(vtbl, source);
|
||||
if (!fullsource)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
fulltarget = nsh_getfullpath(vtbl, target);
|
||||
if (!fulltarget)
|
||||
{
|
||||
ret = ERROR;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Perform the mount */
|
||||
|
||||
ret = mount(fullsource, fulltarget, filesystem, 0, options);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
|
||||
}
|
||||
|
||||
errout:
|
||||
if (fullsource)
|
||||
{
|
||||
nsh_freefullpath(fullsource);
|
||||
}
|
||||
|
||||
if (fulltarget)
|
||||
{
|
||||
nsh_freefullpath(fulltarget);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_nfsmount
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_NET) && \
|
||||
defined(CONFIG_NFS) && !defined(CONFIG_NSH_DISABLE_NFSMOUNT)
|
||||
int cmd_nfsmount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
struct nfs_args data;
|
||||
FAR char *address;
|
||||
FAR char *lpath;
|
||||
FAR char *rpath;
|
||||
int ret;
|
||||
|
||||
/* The fist argument on the command line should be the NFS server IP
|
||||
* address in standard IPv4 (or IPv6) dot format.
|
||||
*/
|
||||
|
||||
address = argv[1];
|
||||
if (!address)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get the remote mount point path */
|
||||
|
||||
rpath = argv[3];
|
||||
|
||||
/* Place all of the NFS arguments into the nfs_args structure */
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
/* Convert the IP address string into its binary form */
|
||||
|
||||
#ifdef CONFIG_LIBC_NETDB
|
||||
if (data.addrlen == 0)
|
||||
{
|
||||
FAR struct addrinfo *res;
|
||||
char serv[16];
|
||||
|
||||
itoa(NFS_PMAPPORT, serv, 10);
|
||||
ret = getaddrinfo(address, serv, NULL, &res);
|
||||
if (ret == OK)
|
||||
{
|
||||
data.addrlen = res->ai_addrlen;
|
||||
memcpy(&data.addr, res->ai_addr, res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (data.addrlen == 0)
|
||||
{
|
||||
FAR struct sockaddr_in6 *sin;
|
||||
|
||||
sin = (FAR struct sockaddr_in6 *)&data.addr;
|
||||
ret = inet_pton(AF_INET6, address, &sin->sin6_addr);
|
||||
if (ret == 1)
|
||||
{
|
||||
sin->sin6_family = AF_INET6;
|
||||
sin->sin6_port = htons(NFS_PMAPPORT);
|
||||
data.addrlen = sizeof(struct sockaddr_in6);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (data.addrlen == 0)
|
||||
{
|
||||
FAR struct sockaddr_in *sin;
|
||||
|
||||
sin = (FAR struct sockaddr_in *)&data.addr;
|
||||
ret = inet_pton(AF_INET, address, &sin->sin_addr);
|
||||
if (ret == 1)
|
||||
{
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = htons(NFS_PMAPPORT);
|
||||
data.addrlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.addrlen == 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (argc > 4 && strcmp(argv[4], "udp") == 0)
|
||||
{
|
||||
data.sotype = SOCK_DGRAM;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.sotype = SOCK_STREAM;
|
||||
}
|
||||
|
||||
data.path = rpath;
|
||||
data.flags = 0; /* 0=Use all defaults */
|
||||
|
||||
/* The local mount point path (lpath) might be relative to the current
|
||||
* working directory.
|
||||
*/
|
||||
|
||||
lpath = nsh_getfullpath(vtbl, argv[2]);
|
||||
if (!lpath)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Perform the mount */
|
||||
|
||||
ret = mount(NULL, lpath, "nfs", 0, (FAR void *)&data);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
|
||||
}
|
||||
|
||||
/* We no longer need the allocated mount point path */
|
||||
|
||||
nsh_freefullpath(lpath);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_umount
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_UMOUNT)
|
||||
int cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
char *fullpath = nsh_getfullpath(vtbl, argv[1]);
|
||||
int ret = ERROR;
|
||||
|
||||
if (fullpath)
|
||||
{
|
||||
/* Perform the umount */
|
||||
|
||||
ret = umount(fullpath);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO);
|
||||
}
|
||||
|
||||
nsh_freefullpath(fullpath);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,192 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_modcmds.c
|
||||
*
|
||||
* Copyright (C) 2015 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/module.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_insmod
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_insmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR void *handle;
|
||||
|
||||
/* Usage: insmod <filepath> <modulename> */
|
||||
|
||||
/* Install the module */
|
||||
|
||||
handle = insmod(argv[1], argv[2]);
|
||||
if (handle == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "insmod", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_rmmod
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_rmmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR void *handle;
|
||||
int ret;
|
||||
|
||||
/* Usage: rmmod <modulename> */
|
||||
|
||||
/* Get the module handle associated with the name */
|
||||
|
||||
handle = modhandle(argv[1]);
|
||||
if (handle == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "modhandle", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Remove the module */
|
||||
|
||||
ret = rmmod(handle);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "rmmod", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_lsmod
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
|
||||
int cmd_lsmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FILE *stream;
|
||||
|
||||
/* Usage: lsmod */
|
||||
|
||||
/* Open /proc/modules */
|
||||
|
||||
stream = fopen("/proc/modules", "r");
|
||||
if (stream == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "fopen", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Output a Header */
|
||||
|
||||
nsh_output(vtbl, "%-16s %8s %8s %8s %8s %8s %8s %8s %8s\n",
|
||||
"NAME", "INIT", "UNINIT", "ARG", "NEXPORTS", "TEXT", "SIZE",
|
||||
"DATA", "SIZE");
|
||||
|
||||
/* Read each line from the procfs "file" */
|
||||
|
||||
while (fgets(vtbl->iobuffer, IOBUFFERSIZE, stream) != NULL)
|
||||
{
|
||||
FAR char *modulename;
|
||||
FAR char *initializer;
|
||||
FAR char *uninitializer;
|
||||
FAR char *arg;
|
||||
FAR char *nexports;
|
||||
FAR char *text;
|
||||
FAR char *textsize;
|
||||
FAR char *data;
|
||||
FAR char *datasize;
|
||||
FAR char *lasts;
|
||||
|
||||
/* Form of returned data is:
|
||||
*
|
||||
* "%s,%p,%p,%p,%p,%lu,%p,%lu\n"
|
||||
*
|
||||
* 1) Module name (string)
|
||||
* 2) Initializer address (hex)
|
||||
* 3) Uninitializer address (hex)
|
||||
* 4) Uninitializer argument (hex)
|
||||
* 5) .text address (hex)
|
||||
* 6) Size of .text (decimal)
|
||||
* 7) .bss/.data address (hex)
|
||||
* 8) Size of .bss/.data (decimal)
|
||||
*/
|
||||
|
||||
modulename = strtok_r(vtbl->iobuffer, ",\n", &lasts);
|
||||
initializer = strtok_r(NULL, ",\n", &lasts);
|
||||
uninitializer = strtok_r(NULL, ",\n", &lasts);
|
||||
arg = strtok_r(NULL, ",\n", &lasts);
|
||||
nexports = strtok_r(NULL, ",\n", &lasts);
|
||||
text = strtok_r(NULL, ",\n", &lasts);
|
||||
textsize = strtok_r(NULL, ",\n", &lasts);
|
||||
data = strtok_r(NULL, ",\n", &lasts);
|
||||
datasize = strtok_r(NULL, ",\n", &lasts);
|
||||
|
||||
nsh_output(vtbl, "%-16s %8s %8s %8s %8s %8s %8s %8s %8s\n",
|
||||
modulename,
|
||||
initializer ? initializer : "",
|
||||
uninitializer ? uninitializer : "",
|
||||
arg ? arg : "",
|
||||
nexports ? nexports : "",
|
||||
text ? text : "",
|
||||
textsize ? textsize : "",
|
||||
data ? data : "",
|
||||
datasize ? datasize : "");
|
||||
}
|
||||
|
||||
fclose(stream);
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_MODULE */
|
||||
|
||||
#endif /* CONFIG_MODULE && !CONFIG_NSH_DISABLE_MODCMDS */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_passwdcmds.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && \
|
||||
defined(CONFIG_NSH_LOGIN_PASSWD) && \
|
||||
!defined(CONFIG_FSUTILS_PASSWD_READONLY)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_useradd
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_USERADD
|
||||
int cmd_useradd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = passwd_adduser(argv[1], argv[2]);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "passwd_adduser",
|
||||
NSH_ERRNO_OF(-ret));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* !CONFIG_NSH_DISABLE_USERADD */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_userdel
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_USERDEL
|
||||
int cmd_userdel(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = passwd_deluser(argv[1]);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "passwd_deluser",
|
||||
NSH_ERRNO_OF(-ret));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* !CONFIG_NSH_DISABLE_USERDEL */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_useradd
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_PASSWD
|
||||
int cmd_passwd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = passwd_update(argv[1], argv[2]);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "passwd_update",
|
||||
NSH_ERRNO_OF(-ret));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* !CONFIG_NSH_DISABLE_USERADD */
|
||||
|
||||
#endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NSH_LOGIN_PASSWD &&
|
||||
* !CONFIG_FSUTILS_PASSWD_READONLY */
|
||||
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_printf.c
|
||||
*
|
||||
* Copyright (C) 2016 Alan Carvalho de Assis. All rights reserved.
|
||||
* Author: Alan Carvalho de Assis <acassis@gmail.com>
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_printf
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_PRINTF
|
||||
int cmd_printf(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR char *fmt;
|
||||
char ch;
|
||||
uint32_t value;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
/* parse each argument, detecting the right action to take
|
||||
* case it doesn't starts with a format then just print it
|
||||
*/
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
fmt = argv[i];
|
||||
|
||||
/* Is it really a FORMAT ? */
|
||||
|
||||
if (fmt[0] == '\\')
|
||||
{
|
||||
fmt++;
|
||||
ch = fmt[0];
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case 'x':
|
||||
fmt++;
|
||||
value = strtoul(fmt, NULL, 16);
|
||||
len = strnlen(fmt, 10);
|
||||
|
||||
if (len >= 7)
|
||||
{
|
||||
nsh_output(vtbl, "%c%c%c%c", value & 0xff,
|
||||
(value & 0xff00) >> 8,
|
||||
(value & 0xff0000) >> 16,
|
||||
(value & 0xff000000) >> 24);
|
||||
}
|
||||
else if (len >= 3)
|
||||
{
|
||||
nsh_output(vtbl, "%c%c", value & 0xff,
|
||||
(value & 0xff00) >> 8);
|
||||
}
|
||||
else if (len >= 1)
|
||||
{
|
||||
nsh_output(vtbl, "%c", value & 0xff);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
nsh_output(vtbl, "\n");
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
nsh_output(vtbl, "\r");
|
||||
break;
|
||||
|
||||
case 't':
|
||||
nsh_output(vtbl, "\t");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_output(vtbl, "%s", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,723 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_proccmds.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2012, 2014-2015, 2019 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_PROC_MOUNTPOINT
|
||||
# define CONFIG_NSH_PROC_MOUNTPOINT "/proc"
|
||||
#endif
|
||||
|
||||
/* See include/nuttx/sched.h: */
|
||||
|
||||
#undef HAVE_GROUPID
|
||||
|
||||
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
|
||||
# define HAVE_GROUPID 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DISABLE_PTHREAD
|
||||
# undef HAVE_GROUPID
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* The returned value should be zero for success or TRUE or non zero for
|
||||
* failure or FALSE.
|
||||
*/
|
||||
|
||||
typedef int (*exec_t)(void);
|
||||
|
||||
/* This structure represents the parsed task characteristics */
|
||||
|
||||
struct nsh_taskstatus_s
|
||||
{
|
||||
FAR const char *td_type; /* Thread type */
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
#ifdef HAVE_GROUPID
|
||||
FAR const char *td_groupid; /* Group ID */
|
||||
#else
|
||||
FAR const char *td_ppid; /* Parent thread ID */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
FAR const char *td_cpu; /* CPU */
|
||||
#endif
|
||||
FAR const char *td_state; /* Thread state */
|
||||
FAR const char *td_event; /* Thread wait event */
|
||||
FAR const char *td_flags; /* Thread flags */
|
||||
FAR const char *td_priority; /* Thread priority */
|
||||
FAR const char *td_policy; /* Thread scheduler */
|
||||
FAR const char *td_sigmask; /* Signal mask */
|
||||
};
|
||||
|
||||
/* Status strings */
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_PS
|
||||
#if 0 /* Not used */
|
||||
static const char g_name[] = "Name:";
|
||||
#endif
|
||||
|
||||
static const char g_type[] = "Type:";
|
||||
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
#ifdef HAVE_GROUPID
|
||||
static const char g_groupid[] = "Group:";
|
||||
#else
|
||||
static const char g_ppid[] = "PPID:";
|
||||
#endif
|
||||
#endif /* CONFIG_SCHED_HAVE_PARENT */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static const char g_cpu[] = "CPU:";
|
||||
#endif
|
||||
|
||||
static const char g_state[] = "State:";
|
||||
static const char g_flags[] = "Flags:";
|
||||
static const char g_priority[] = "Priority:";
|
||||
static const char g_scheduler[] = "Scheduler:";
|
||||
static const char g_sigmask[] = "SigMask:";
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLE_PSSTACKUSAGE)
|
||||
static const char g_stacksize[] = "StackSize:";
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
static const char g_stackused[] = "StackUsed:";
|
||||
#endif
|
||||
#endif /* !CONFIG_NSH_DISABLE_PSSTACKUSAGE */
|
||||
#endif /* !CONFIG_NSH_DISABLE_PS */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_parse_statusline
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_PS
|
||||
static void nsh_parse_statusline(FAR char *line,
|
||||
FAR struct nsh_taskstatus_s *status)
|
||||
{
|
||||
/* Parse the task status.
|
||||
*
|
||||
* Format:
|
||||
*
|
||||
* 111111111122222222223
|
||||
* 123456789012345678901234567890
|
||||
* Name: xxxx... Task/thread name
|
||||
* (See CONFIG_TASK_NAME_SIZE)
|
||||
* Type: xxxxxxx {Task, pthread, Kthread, Invalid}
|
||||
* Type: xxxxxxx {Task, pthread, Kthread, Invalid}
|
||||
* PPID: xxxxx Parent thread ID
|
||||
* State: xxxxxxxx,xxxxxxxxx {Invalid, Waiting, Ready, Running,
|
||||
* Inactive}, {Unlock, Semaphore, Signal,
|
||||
* MQ empty, MQ full}
|
||||
* Flags: xxx N,P,X
|
||||
* Priority: nnn Decimal, 0-255
|
||||
* Scheduler: xxxxxxxxxxxxxx {SCHED_FIFO, SCHED_RR, SCHED_SPORADIC,
|
||||
* SCHED_OTHER}
|
||||
* Sigmask: nnnnnnnn Hexadecimal, 32-bit
|
||||
*/
|
||||
|
||||
#if 0 /* Not used */
|
||||
/* Task name */
|
||||
|
||||
if (strncmp(line, g_name, strlen(g_name)) == 0)
|
||||
{
|
||||
/* Not used */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* Task/thread type */
|
||||
|
||||
if (strncmp(line, g_type, strlen(g_type)) == 0)
|
||||
{
|
||||
/* Save the thread type */
|
||||
|
||||
status->td_type = nsh_trimspaces(&line[12]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
#ifdef HAVE_GROUPID
|
||||
else if (strncmp(line, g_groupid, strlen(g_groupid)) == 0)
|
||||
{
|
||||
/* Save the Group ID */
|
||||
|
||||
status->td_groupid = nsh_trimspaces(&line[12]);
|
||||
}
|
||||
#else
|
||||
else if (strncmp(line, g_ppid, strlen(g_ppid)) == 0)
|
||||
{
|
||||
/* Save the parent thread id */
|
||||
|
||||
status->td_ppid = nsh_trimspaces(&line[12]);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
else if (strncmp(line, g_cpu, strlen(g_cpu)) == 0)
|
||||
{
|
||||
/* Save the current CPU */
|
||||
|
||||
status->td_cpu = nsh_trimspaces(&line[12]);
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (strncmp(line, g_state, strlen(g_state)) == 0)
|
||||
{
|
||||
FAR char *ptr;
|
||||
|
||||
/* Save the thread state */
|
||||
|
||||
status->td_state = nsh_trimspaces(&line[12]);
|
||||
|
||||
/* Check if an event follows the state */
|
||||
|
||||
ptr = strchr(status->td_state, ',');
|
||||
if (ptr != NULL)
|
||||
{
|
||||
*ptr++ = '\0';
|
||||
status->td_event = nsh_trimspaces(ptr);
|
||||
}
|
||||
}
|
||||
else if (strncmp(line, g_flags, strlen(g_flags)) == 0)
|
||||
{
|
||||
status->td_flags = nsh_trimspaces(&line[12]);
|
||||
}
|
||||
else if (strncmp(line, g_priority, strlen(g_priority)) == 0)
|
||||
{
|
||||
FAR char *ptr = nsh_trimspaces(&line[12]);
|
||||
status->td_priority = ptr;
|
||||
|
||||
/* If priority inheritance is enabled, use current pri, ignore base */
|
||||
|
||||
while (isdigit(*ptr))
|
||||
{
|
||||
++ptr;
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
else if (strncmp(line, g_scheduler, strlen(g_scheduler)) == 0)
|
||||
{
|
||||
/* Skip over the SCHED_ part of the policy. Result is max 8 bytes. */
|
||||
|
||||
status->td_policy = nsh_trimspaces(&line[12 + 6]);
|
||||
}
|
||||
else if (strncmp(line, g_sigmask, strlen(g_sigmask)) == 0)
|
||||
{
|
||||
status->td_sigmask = nsh_trimspaces(&line[12]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ps_callback
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_PS
|
||||
static int ps_callback(FAR struct nsh_vtbl_s *vtbl, FAR const char *dirpath,
|
||||
FAR struct dirent *entryp, FAR void *pvarg)
|
||||
{
|
||||
struct nsh_taskstatus_s status;
|
||||
FAR char *filepath;
|
||||
FAR char *line;
|
||||
FAR char *nextline;
|
||||
int ret;
|
||||
int i;
|
||||
#if !defined(CONFIG_NSH_DISABLE_PSSTACKUSAGE)
|
||||
uint32_t stack_size;
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_used;
|
||||
uint32_t stack_filled;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Task/thread entries in the /proc directory will all be (1) directories
|
||||
* with (2) all numeric names.
|
||||
*/
|
||||
|
||||
if (!DIRENT_ISDIRECTORY(entryp->d_type))
|
||||
{
|
||||
/* Not a directory... skip this entry */
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Check each character in the name */
|
||||
|
||||
for (i = 0; i < NAME_MAX && entryp->d_name[i] != '\0'; i++)
|
||||
{
|
||||
if (!isdigit(entryp->d_name[i]))
|
||||
{
|
||||
/* Name contains something other than a numeric character */
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set all pointers to the empty string. */
|
||||
|
||||
status.td_type = "";
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
#ifdef HAVE_GROUPID
|
||||
status.td_groupid = "";
|
||||
#else
|
||||
status.td_ppid = "";
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
status.td_cpu = "";
|
||||
#endif
|
||||
status.td_state = "";
|
||||
status.td_event = "";
|
||||
status.td_flags = "";
|
||||
status.td_priority = "";
|
||||
status.td_policy = "";
|
||||
status.td_sigmask = "";
|
||||
|
||||
/* Read the task status */
|
||||
|
||||
filepath = NULL;
|
||||
ret = asprintf(&filepath, "%s/%s/status", dirpath, entryp->d_name);
|
||||
if (ret < 0 || filepath == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "ps", "asprintf", NSH_ERRNO);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = nsh_readfile(vtbl, "ps", filepath, vtbl->iobuffer, IOBUFFERSIZE);
|
||||
free(filepath);
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Parse the task status. */
|
||||
|
||||
nextline = vtbl->iobuffer;
|
||||
do
|
||||
{
|
||||
/* Find the beginning of the next line and NUL-terminate the
|
||||
* current line.
|
||||
*/
|
||||
|
||||
line = nextline;
|
||||
for (nextline++;
|
||||
*nextline != '\n' && *nextline != '\0';
|
||||
nextline++);
|
||||
|
||||
if (*nextline == '\n')
|
||||
{
|
||||
*nextline++ = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
nextline = NULL;
|
||||
}
|
||||
|
||||
/* Parse the current line */
|
||||
|
||||
nsh_parse_statusline(line, &status);
|
||||
}
|
||||
while (nextline != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, print the status information */
|
||||
|
||||
nsh_output(vtbl, "%5s ", entryp->d_name);
|
||||
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
#ifdef HAVE_GROUPID
|
||||
nsh_output(vtbl, "%5s ", status.td_groupid);
|
||||
#else
|
||||
nsh_output(vtbl, "%5s ", status.td_ppid);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
nsh_output(vtbl, "%3s ", status.td_cpu);
|
||||
#endif
|
||||
|
||||
nsh_output(vtbl, "%3s %-8s %-7s %3s %-8s %-9s ",
|
||||
status.td_priority, status.td_policy, status.td_type,
|
||||
status.td_flags, status.td_state, status.td_event);
|
||||
nsh_output(vtbl, "%-8s ", status.td_sigmask);
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLE_PSSTACKUSAGE)
|
||||
/* Get the StackSize and StackUsed */
|
||||
|
||||
stack_size = 0;
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
stack_used = 0;
|
||||
#endif
|
||||
filepath = NULL;
|
||||
|
||||
ret = asprintf(&filepath, "%s/%s/stack", dirpath, entryp->d_name);
|
||||
if (ret < 0 || filepath == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "ps", "asprintf", NSH_ERRNO);
|
||||
vtbl->iobuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = nsh_readfile(vtbl, "ps", filepath, vtbl->iobuffer,
|
||||
IOBUFFERSIZE);
|
||||
free(filepath);
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
nextline = vtbl->iobuffer;
|
||||
do
|
||||
{
|
||||
/* Find the beginning of the next line and NUL-terminate the
|
||||
* current line.
|
||||
*/
|
||||
|
||||
line = nextline;
|
||||
for (nextline++;
|
||||
*nextline != '\n' && *nextline != '\0';
|
||||
nextline++);
|
||||
|
||||
if (*nextline == '\n')
|
||||
{
|
||||
*nextline++ = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
nextline = NULL;
|
||||
}
|
||||
|
||||
/* Parse the current line
|
||||
*
|
||||
* Format:
|
||||
*
|
||||
* 111111111122222222223
|
||||
* 123456789012345678901234567890
|
||||
* StackBase: xxxxxxxxxx
|
||||
* StackSize: xxxx
|
||||
* StackUsed: xxxx
|
||||
*/
|
||||
|
||||
if (strncmp(line, g_stacksize, strlen(g_stacksize)) == 0)
|
||||
{
|
||||
stack_size = (uint32_t)atoi(&line[12]);
|
||||
}
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
else if (strncmp(line, g_stackused, strlen(g_stackused)) == 0)
|
||||
{
|
||||
stack_used = (uint32_t)atoi(&line[12]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
while (nextline != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%06u ", (unsigned int)stack_size);
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
nsh_output(vtbl, "%06u ", (unsigned int)stack_used);
|
||||
|
||||
stack_filled = 0;
|
||||
if (stack_size > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 * stack_used / stack_size;
|
||||
}
|
||||
|
||||
/* Additionally print a '!' if the stack is filled more than 80% */
|
||||
|
||||
nsh_output(vtbl, "%3d.%1d%%%c ",
|
||||
stack_filled / 10, stack_filled % 10,
|
||||
(stack_filled >= 10 * 80 ? '!' : ' '));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NSH_HAVE_CPULOAD
|
||||
/* Get the CPU load */
|
||||
|
||||
filepath = NULL;
|
||||
ret = asprintf(&filepath, "%s/%s/loadavg", dirpath, entryp->d_name);
|
||||
if (ret < 0 || filepath == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "ps", "asprintf", NSH_ERRNO);
|
||||
vtbl->iobuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = nsh_readfile(vtbl, "ps", filepath, vtbl->iobuffer, IOBUFFERSIZE);
|
||||
free(filepath);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
vtbl->iobuffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%6s ", nsh_trimspaces(vtbl->iobuffer));
|
||||
#endif
|
||||
|
||||
/* Read the task/thread command line */
|
||||
|
||||
filepath = NULL;
|
||||
ret = asprintf(&filepath, "%s/%s/cmdline", dirpath, entryp->d_name);
|
||||
|
||||
if (ret < 0 || filepath == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "ps", "asprintf", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = nsh_readfile(vtbl, "ps", filepath, vtbl->iobuffer, IOBUFFERSIZE);
|
||||
free(filepath);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%s\n", nsh_trimspaces(vtbl->iobuffer));
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_exec
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_EXEC
|
||||
int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
|
||||
{
|
||||
FAR char *endptr;
|
||||
uintptr_t addr;
|
||||
|
||||
addr = (uintptr_t)strtol(argv[1], &endptr, 0);
|
||||
if (!addr || endptr == argv[1] || *endptr != '\0')
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "Calling %p\n", (exec_t)addr);
|
||||
return ((exec_t)addr)();
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_ps
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_PS
|
||||
int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
nsh_output(vtbl, "%5s ", "PID");
|
||||
|
||||
#ifdef CONFIG_SCHED_HAVE_PARENT
|
||||
#ifdef HAVE_GROUPID
|
||||
nsh_output(vtbl, "%5s ", "GROUP");
|
||||
#else
|
||||
nsh_output(vtbl, "%5s ", "PPID");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
nsh_output(vtbl, "%3s ", "CPU");
|
||||
#endif
|
||||
|
||||
nsh_output(vtbl, "%3s %-8s %-7s %3s %-8s %-9s ",
|
||||
"PRI", "POLICY", "TYPE", "NPX", "STATE", "EVENT");
|
||||
nsh_output(vtbl, "%-8s ", "SIGMASK");
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLE_PSSTACKUSAGE)
|
||||
nsh_output(vtbl, "%6s ", "STACK");
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
nsh_output(vtbl, "%6s ", "USED");
|
||||
nsh_output(vtbl, "%7s ", "FILLED");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NSH_HAVE_CPULOAD
|
||||
nsh_output(vtbl, "%6s ", "CPU");
|
||||
#endif
|
||||
nsh_output(vtbl, "%s\n", "COMMAND");
|
||||
|
||||
return nsh_foreach_direntry(vtbl, "ps", CONFIG_NSH_PROC_MOUNTPOINT,
|
||||
ps_callback, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_kill
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_KILL
|
||||
int cmd_kill(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
char *ptr;
|
||||
char *endptr;
|
||||
long signal;
|
||||
long pid;
|
||||
|
||||
/* Check incoming parameters. The first parameter should be "-<signal>" */
|
||||
|
||||
ptr = argv[1];
|
||||
if (*ptr != '-' || ptr[1] < '0' || ptr[1] > '9')
|
||||
{
|
||||
goto invalid_arg;
|
||||
}
|
||||
|
||||
/* Extract the signal number */
|
||||
|
||||
signal = strtol(&ptr[1], &endptr, 0);
|
||||
|
||||
/* The second parameter should be <pid> */
|
||||
|
||||
ptr = argv[2];
|
||||
if (*ptr < '0' || *ptr > '9')
|
||||
{
|
||||
goto invalid_arg;
|
||||
}
|
||||
|
||||
/* Extract the pid */
|
||||
|
||||
pid = strtol(ptr, &endptr, 0);
|
||||
|
||||
/* Send the signal. Kill return values:
|
||||
*
|
||||
* EINVAL An invalid signal was specified.
|
||||
* EPERM The process does not have permission to send the signal to any
|
||||
* of the target processes.
|
||||
* ESRCH The pid or process group does not exist.
|
||||
* ENOSYS Do not support sending signals to process groups.
|
||||
*/
|
||||
|
||||
if (kill((pid_t)pid, (int)signal) == 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
goto invalid_arg;
|
||||
|
||||
case ESRCH:
|
||||
nsh_error(vtbl, g_fmtnosuch, argv[0], "task", argv[2]);
|
||||
return ERROR;
|
||||
|
||||
case EPERM:
|
||||
case ENOSYS:
|
||||
default:
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "kill", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
invalid_arg:
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_sleep
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_SLEEP
|
||||
int cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
char *endptr;
|
||||
long secs;
|
||||
|
||||
secs = strtol(argv[1], &endptr, 0);
|
||||
if (!secs || endptr == argv[1] || *endptr != '\0')
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
sleep(secs);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_usleep
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_USLEEP
|
||||
int cmd_usleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
char *endptr;
|
||||
long usecs;
|
||||
|
||||
usecs = strtol(argv[1], &endptr, 0);
|
||||
if (!usecs || endptr == argv[1] || *endptr != '\0')
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
usleep(usecs);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_romfsetc.c
|
||||
*
|
||||
* Copyright (C) 2008-2012 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 <sys/mount.h>
|
||||
#include <sys/boardctl.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/drivers/ramdisk.h>
|
||||
|
||||
#include "nsh.h"
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSETC
|
||||
|
||||
/* Should we use the default ROMFS image? Or a custom, board-specific
|
||||
* ROMFS image?
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NSH_ARCHROMFS
|
||||
# include <arch/board/nsh_romfsimg.h>
|
||||
#elif defined(CONFIG_NSH_CUSTOMROMFS)
|
||||
# include CONFIG_NSH_CUSTOMROMFS_HEADER
|
||||
#else /* if defined(CONFIG_NSH_DEFAULTROMFS) */
|
||||
# include "nsh_romfsimg.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DISABLE_MOUNTPOINT
|
||||
# error You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_CROMFSETC)
|
||||
# ifndef CONFIG_FS_CROMFS
|
||||
# error You must select CONFIG_FS_CROMFS in your configuration file
|
||||
# endif
|
||||
#else
|
||||
# ifndef CONFIG_FS_ROMFS
|
||||
# error You must select CONFIG_FS_ROMFS in your configuration file
|
||||
# endif
|
||||
# ifndef CONFIG_BOARDCTL_ROMDISK
|
||||
# error You must select CONFIG_BOARDCTL_ROMDISK in your configuration file
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_romfsetc
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_romfsetc(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifndef CONFIG_NSH_CROMFSETC
|
||||
struct boardioc_romdisk_s desc;
|
||||
|
||||
/* Create a ROM disk for the /etc filesystem */
|
||||
|
||||
desc.minor = CONFIG_NSH_ROMFSDEVNO; /* Minor device number of the RAM disk. */
|
||||
desc.nsectors = NSECTORS(romfs_img_len); /* The number of sectors in the RAM disk */
|
||||
desc.sectsize = CONFIG_NSH_ROMFSSECTSIZE; /* The size of one sector in bytes */
|
||||
desc.image = romfs_img; /* File system image */
|
||||
|
||||
ret = boardctl(BOARDIOC_ROMDISK, (uintptr_t)&desc);
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: boardctl(BOARDIOC_ROMDISK) failed: %d\n", -ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Mount the file system */
|
||||
|
||||
finfo("Mounting ROMFS filesystem at target=%s with source=%s\n",
|
||||
CONFIG_NSH_ROMFSMOUNTPT, MOUNT_DEVNAME);
|
||||
|
||||
#if defined(CONFIG_NSH_CROMFSETC)
|
||||
ret = mount(MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, "cromfs", MS_RDONLY,
|
||||
NULL);
|
||||
#else
|
||||
ret = mount(MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, "romfs", MS_RDONLY,
|
||||
NULL);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
{
|
||||
ferr("ERROR: mount(%s,%s,romfs) failed: %d\n",
|
||||
MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, errno);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_ROMFSETC */
|
||||
@@ -0,0 +1,90 @@
|
||||
const unsigned char romfs_img[] = {
|
||||
0x2d, 0x72, 0x6f, 0x6d, 0x31, 0x66, 0x73, 0x2d, 0x00, 0x00, 0x01, 0x50,
|
||||
0x9f, 0x13, 0x82, 0x87, 0x4e, 0x53, 0x48, 0x49, 0x6e, 0x69, 0x74, 0x56,
|
||||
0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
|
||||
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x97,
|
||||
0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0x80, 0x2e, 0x2e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x68, 0x2d, 0x96, 0x03, 0x69, 0x6e, 0x69, 0x74, 0x2e, 0x64, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
|
||||
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xff, 0xff, 0x00,
|
||||
0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x6e, 0x8d, 0x9c, 0xab, 0x58, 0x72, 0x63, 0x53, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x52,
|
||||
0x41, 0x4d, 0x44, 0x49, 0x53, 0x4b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x20, 0x61, 0x74, 0x20, 0x2f,
|
||||
0x74, 0x6d, 0x70, 0x0a, 0x0a, 0x6d, 0x6b, 0x72, 0x64, 0x20, 0x2d, 0x6d,
|
||||
0x20, 0x32, 0x20, 0x2d, 0x73, 0x20, 0x35, 0x31, 0x32, 0x20, 0x31, 0x30,
|
||||
0x32, 0x34, 0x0a, 0x6d, 0x6b, 0x66, 0x61, 0x74, 0x66, 0x73, 0x20, 0x2f,
|
||||
0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x32, 0x0a, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x20, 0x2d, 0x74, 0x20, 0x76, 0x66, 0x61, 0x74, 0x20, 0x2f,
|
||||
0x64, 0x65, 0x76, 0x2f, 0x72, 0x61, 0x6d, 0x32, 0x20, 0x2f, 0x74, 0x6d,
|
||||
0x70, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd1, 0xd1, 0xff, 0xe0, 0x2e, 0x2e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const unsigned int romfs_img_len = 1024;
|
||||
@@ -0,0 +1,772 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_routecmds.c
|
||||
*
|
||||
* Copyright (C) 2013, 2017 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "netutils/netlib.h"
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#if defined(CONFIG_NET) && defined(CONFIG_NET_ROUTE)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int slash_notation(FAR char *arg)
|
||||
{
|
||||
FAR char *sptr;
|
||||
FAR char *ptr;
|
||||
|
||||
/* If an address contains a /, then the netmask is imply by the following
|
||||
* numeric value.
|
||||
*/
|
||||
|
||||
sptr = strchr(arg, '/');
|
||||
if (sptr != NULL)
|
||||
{
|
||||
/* Make sure that everything following the slash is a decimal digit. */
|
||||
|
||||
ptr = sptr + 1;
|
||||
while (isdigit(*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* There should be nothing be digits after the slash and up to the
|
||||
* NULL terminator.
|
||||
*/
|
||||
|
||||
if (*ptr == '\0')
|
||||
{
|
||||
*sptr++ = '\0';
|
||||
return atoi(sptr);
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_addroute
|
||||
*
|
||||
* nsh> addroute <target> [<netmask>] <router>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_ADDROUTE
|
||||
int cmd_addroute(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct sockaddr_in ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct sockaddr_in6 ipv6;
|
||||
#endif
|
||||
} target;
|
||||
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct sockaddr_in ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct sockaddr_in6 ipv6;
|
||||
#endif
|
||||
} netmask;
|
||||
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct sockaddr_in ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct sockaddr_in6 ipv6;
|
||||
#endif
|
||||
} router;
|
||||
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct in_addr ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct in6_addr ipv6;
|
||||
#endif
|
||||
} inaddr;
|
||||
|
||||
sa_family_t family;
|
||||
int rtrndx;
|
||||
int shift;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* First, check if we are setting the default route */
|
||||
|
||||
if (strcmp(argv[1], "default") == 0)
|
||||
{
|
||||
/* We are expecting an ip and an interface name to follow. */
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
else if (argc > 4)
|
||||
{
|
||||
nsh_error(vtbl, g_fmttoomanyargs, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Convert the target IP address string into its binary form */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
family = PF_INET;
|
||||
|
||||
ret = inet_pton(AF_INET, argv[2], &inaddr.ipv4);
|
||||
if (ret != 1)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
family = PF_INET6;
|
||||
|
||||
ret = inet_pton(AF_INET6, argv[2], &inaddr.ipv6);
|
||||
if (ret != 1)
|
||||
#endif
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (family == PF_INET)
|
||||
{
|
||||
ret = netlib_set_dripv4addr(argv[3], &inaddr.ipv4);
|
||||
if (ret != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET6)
|
||||
{
|
||||
ret = netlib_set_dripv6addr(argv[3], &inaddr.ipv6);
|
||||
if (ret != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Check if slash notation is used with the target address */
|
||||
|
||||
shift = slash_notation(argv[1]);
|
||||
|
||||
/* There will be 2 or 3 arguments, depending on if slash notation is
|
||||
* used.
|
||||
*/
|
||||
|
||||
if (shift > 0 && argc != 3)
|
||||
{
|
||||
nsh_error(vtbl, g_fmttoomanyargs, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
else if (shift < 0 && argc != 4)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Convert the target IP address string into its binary form */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
family = PF_INET;
|
||||
|
||||
ret = inet_pton(AF_INET, argv[1], &inaddr.ipv4);
|
||||
if (ret != 1)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
family = PF_INET6;
|
||||
|
||||
ret = inet_pton(AF_INET6, argv[1], &inaddr.ipv6);
|
||||
if (ret != 1)
|
||||
#endif
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to have a socket (any socket) in order to perform the ioctl */
|
||||
|
||||
sockfd = socket(family, NETLIB_SOCK_TYPE, 0);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "socket", NSH_ERRNO);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Format the target sockaddr instance */
|
||||
|
||||
memset(&target, 0, sizeof(target));
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
target.ipv4.sin_family = AF_INET;
|
||||
target.ipv4.sin_addr = inaddr.ipv4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
target.ipv6.sin6_family = AF_INET6;
|
||||
memcpy(&target.ipv6.sin6_addr, &inaddr.ipv6,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert the netmask IP address string into its binary form */
|
||||
|
||||
if (shift >= 0)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
/* /0 -> 0x00000000
|
||||
* /8 -> 0xff000000
|
||||
* /24 -> 0xffffff00
|
||||
* /32 -> 0xffffffff
|
||||
*/
|
||||
|
||||
if (shift > 32)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
inaddr.ipv4.s_addr = htonl(0xffffffff << (32 - shift));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
|
||||
/* /0 -> 0000:0000:0000:0000:0000:0000:0000:0000
|
||||
* /16 -> ffff:0000:0000:0000:0000:0000:0000:0000
|
||||
* /32 -> ffff:ffff:0000:0000:0000:0000:0000:0000
|
||||
* ...
|
||||
* /128 -> ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
*/
|
||||
|
||||
memset(&inaddr.ipv6, 0, sizeof(struct sockaddr_in6));
|
||||
for (i = 0; i < 8 && shift >= 16; i++, shift -= 16)
|
||||
{
|
||||
inaddr.ipv6.s6_addr16[i] = 0xffff;
|
||||
}
|
||||
|
||||
if (shift > 16 || (shift > 0 && i >= 8))
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
/* /0 -> 0x0000
|
||||
* /1 -> 0x8000
|
||||
* /2 -> 0xc000
|
||||
* ...
|
||||
* /16 -> 0xffff
|
||||
*/
|
||||
|
||||
if (shift > 0)
|
||||
{
|
||||
inaddr.ipv6.s6_addr16[i] = htons(0xffff << (16 - shift));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
rtrndx = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Slash notation not used.. mask should follow the target address */
|
||||
|
||||
ret = inet_pton(family, argv[2], &inaddr);
|
||||
if (ret != 1)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
rtrndx = 3;
|
||||
}
|
||||
|
||||
/* Format the netmask sockaddr instance */
|
||||
|
||||
memset(&netmask, 0, sizeof(netmask));
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
netmask.ipv4.sin_family = AF_INET;
|
||||
netmask.ipv4.sin_addr = inaddr.ipv4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
netmask.ipv6.sin6_family = AF_INET6;
|
||||
memcpy(&netmask.ipv6.sin6_addr, &inaddr.ipv6,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert the router IP address string into its binary form */
|
||||
|
||||
ret = inet_pton(family, argv[rtrndx], &inaddr);
|
||||
if (ret != 1)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
/* Format the router sockaddr instance */
|
||||
|
||||
memset(&router, 0, sizeof(router));
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
router.ipv4.sin_family = AF_INET;
|
||||
router.ipv4.sin_addr = inaddr.ipv4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
router.ipv6.sin6_family = AF_INET6;
|
||||
memcpy(&router.ipv6.sin6_addr, &inaddr.ipv6,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Then add the route */
|
||||
|
||||
ret = addroute(sockfd,
|
||||
(FAR struct sockaddr_storage *)&target,
|
||||
(FAR struct sockaddr_storage *)&netmask,
|
||||
(FAR struct sockaddr_storage *)&router);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "addroute", NSH_ERRNO);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
return OK;
|
||||
|
||||
errout_with_sockfd:
|
||||
close(sockfd);
|
||||
errout:
|
||||
return ERROR;
|
||||
}
|
||||
#endif /* !CONFIG_NSH_DISABLE_ADDROUTE */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_delroute
|
||||
*
|
||||
* nsh> delroute <target> [<netmask>]
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DELROUTE
|
||||
int cmd_delroute(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct sockaddr_in ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct sockaddr_in6 ipv6;
|
||||
#endif
|
||||
} target;
|
||||
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct sockaddr_in ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct sockaddr_in6 ipv6;
|
||||
#endif
|
||||
} netmask;
|
||||
|
||||
union
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
struct in_addr ipv4;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
struct in6_addr ipv6;
|
||||
#endif
|
||||
} inaddr;
|
||||
|
||||
sa_family_t family;
|
||||
int shift;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* Check if slash notation is used with the target address */
|
||||
|
||||
shift = slash_notation(argv[1]);
|
||||
|
||||
/* There will be 1 or 2 arguments, depending on if slash notation is
|
||||
* used.
|
||||
*/
|
||||
|
||||
if (shift > 0 && argc != 2)
|
||||
{
|
||||
nsh_error(vtbl, g_fmttoomanyargs, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
else if (shift < 0 && argc != 3)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtargrequired, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Convert the target IP address string into its binary form */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
family = PF_INET;
|
||||
|
||||
ret = inet_pton(AF_INET, argv[1], &inaddr.ipv4);
|
||||
if (ret != 1)
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
family = PF_INET6;
|
||||
|
||||
ret = inet_pton(AF_INET6, argv[1], &inaddr.ipv6);
|
||||
if (ret != 1)
|
||||
#endif
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need to have a socket (any socket) in order to perform the ioctl */
|
||||
|
||||
sockfd = socket(family, NETLIB_SOCK_TYPE, 0);
|
||||
if (sockfd < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "socket", NSH_ERRNO);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Format the target sockaddr instance */
|
||||
|
||||
memset(&target, 0, sizeof(target));
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
target.ipv4.sin_family = AF_INET;
|
||||
target.ipv4.sin_addr = inaddr.ipv4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
target.ipv6.sin6_family = AF_INET6;
|
||||
memcpy(&target.ipv6.sin6_addr, &inaddr.ipv6,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert the netmask IP address string into its binary form */
|
||||
|
||||
if (shift >= 0)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
/* /0 -> 0x00000000
|
||||
* /8 -> 0xff000000
|
||||
* /24 -> 0xffffff00
|
||||
* /32 -> 0xffffffff
|
||||
*/
|
||||
|
||||
if (shift > 32)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
inaddr.ipv4.s_addr = htonl(0xffffffff << (32 - shift));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
|
||||
/* /0 -> 0000:0000:0000:0000:0000:0000:0000:0000
|
||||
* /16 -> ffff:0000:0000:0000:0000:0000:0000:0000
|
||||
* /32 -> ffff:ffff:0000:0000:0000:0000:0000:0000
|
||||
* ...
|
||||
* /128 -> ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
|
||||
*/
|
||||
|
||||
memset(&inaddr.ipv6, 0, sizeof(struct sockaddr_in6));
|
||||
for (i = 0; i < 8 && shift >= 16; i++, shift -= 16)
|
||||
{
|
||||
inaddr.ipv6.s6_addr16[i] = 0xffff;
|
||||
}
|
||||
|
||||
if (shift > 16 || (shift > 0 && i >= 8))
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
/* /0 -> 0x0000
|
||||
* /1 -> 0x8000
|
||||
* /2 -> 0xc000
|
||||
* ...
|
||||
* /16 -> 0xffff
|
||||
*/
|
||||
|
||||
if (shift > 0)
|
||||
{
|
||||
inaddr.ipv6.s6_addr16[i] = htons(0xffff << (16 - shift));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Slash notation not used.. mask should follow the target address */
|
||||
|
||||
ret = inet_pton(family, argv[2], &inaddr);
|
||||
if (ret != 1)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the netmask sockaddr instance */
|
||||
|
||||
memset(&netmask, 0, sizeof(netmask));
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == PF_INET)
|
||||
#endif
|
||||
{
|
||||
netmask.ipv4.sin_family = AF_INET;
|
||||
netmask.ipv4.sin_addr = inaddr.ipv4;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
netmask.ipv6.sin6_family = AF_INET6;
|
||||
memcpy(&netmask.ipv6.sin6_addr, &inaddr.ipv6,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Then delete the route */
|
||||
|
||||
ret = delroute(sockfd,
|
||||
(FAR struct sockaddr_storage *)&target,
|
||||
(FAR struct sockaddr_storage *)&netmask);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "delroute", NSH_ERRNO);
|
||||
goto errout_with_sockfd;
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
return OK;
|
||||
|
||||
errout_with_sockfd:
|
||||
close(sockfd);
|
||||
errout:
|
||||
return ERROR;
|
||||
}
|
||||
#endif /* !CONFIG_NSH_DISABLE_DELROUTE */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_route
|
||||
*
|
||||
* nsh> route <ipv4|ipv6>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_ROUTE
|
||||
int cmd_route(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
bool ipv6 = false;
|
||||
#endif
|
||||
|
||||
/* If both IPv4 and IPv6 and defined then there will be exactly one
|
||||
* argument. Otherwise no arguments are required, but an addition
|
||||
* argument is accepted.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
if (strcmp(argv[1], "ipv4") == 0)
|
||||
{
|
||||
ipv6 = false;
|
||||
}
|
||||
else if (strcmp(argv[1], "ipv6") == 0)
|
||||
{
|
||||
ipv6 = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
#elif defined(CONFIG_NET_IPv4)
|
||||
if (argc == 2 && strcmp(argv[1], "ipv4") != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
#else
|
||||
if (argc == 2 && strcmp(argv[1], "ipv6") != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Then just cat the procfs file containing the routing table info */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (!ipv6)
|
||||
#endif
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0],
|
||||
CONFIG_NSH_PROC_MOUNTPOINT "/net/route/ipv4");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return nsh_catfile(vtbl, argv[0],
|
||||
CONFIG_NSH_PROC_MOUNTPOINT "/net/route/ipv6");
|
||||
}
|
||||
#endif
|
||||
|
||||
return ERROR; /* Shouldn't get here */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_ROUTE */
|
||||
@@ -0,0 +1,221 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_script.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-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>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#if defined(CONFIG_FILE_STREAM) && !defined(CONFIG_NSH_DISABLESCRIPT)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_script
|
||||
*
|
||||
* Description:
|
||||
* Execute the NSH script at path.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
|
||||
FAR const char *path)
|
||||
{
|
||||
FAR char *fullpath;
|
||||
FAR FILE *savestream;
|
||||
FAR char *buffer;
|
||||
FAR char *pret;
|
||||
int ret = ERROR;
|
||||
|
||||
/* The path to the script may relative to the current working directory */
|
||||
|
||||
fullpath = nsh_getfullpath(vtbl, path);
|
||||
if (!fullpath)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get a reference to the common input buffer */
|
||||
|
||||
buffer = nsh_linebuffer(vtbl);
|
||||
if (buffer)
|
||||
{
|
||||
/* Save the parent stream in case of nested script processing */
|
||||
|
||||
savestream = vtbl->np.np_stream;
|
||||
|
||||
/* Open the file containing the script */
|
||||
|
||||
vtbl->np.np_stream = fopen(fullpath, "r");
|
||||
if (!vtbl->np.np_stream)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, cmd, "fopen", NSH_ERRNO);
|
||||
|
||||
/* Free the allocated path */
|
||||
|
||||
nsh_freefullpath(fullpath);
|
||||
|
||||
/* Restore the parent script stream */
|
||||
|
||||
vtbl->np.np_stream = savestream;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Loop, processing each command line in the script file (or
|
||||
* until an error occurs)
|
||||
*/
|
||||
|
||||
do
|
||||
{
|
||||
/* Flush any output generated by the previous line */
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_LOOPS
|
||||
/* Get the current file position. This is used to control
|
||||
* looping. If a loop begins in the next line, then this file
|
||||
* offset will be needed to locate the top of the loop in the
|
||||
* script file. Note that ftell will return -1 on failure.
|
||||
*/
|
||||
|
||||
vtbl->np.np_foffs = ftell(vtbl->np.np_stream);
|
||||
vtbl->np.np_loffs = 0;
|
||||
|
||||
if (vtbl->np.np_foffs < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, "loop", "ftell", NSH_ERRNO);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now read the next line from the script file */
|
||||
|
||||
pret = fgets(buffer, CONFIG_NSH_LINELEN, vtbl->np.np_stream);
|
||||
if (pret)
|
||||
{
|
||||
/* Parse process the command. NOTE: this is recursive...
|
||||
* we got to cmd_source via a call to nsh_parse. So some
|
||||
* considerable amount of stack may be used.
|
||||
*/
|
||||
|
||||
if ((vtbl->np.np_flags & NSH_PFLAG_SILENT) == 0)
|
||||
{
|
||||
nsh_output(vtbl, "%s", buffer);
|
||||
}
|
||||
|
||||
ret = nsh_parse(vtbl, buffer);
|
||||
}
|
||||
}
|
||||
while (pret && (ret == OK || (vtbl->np.np_flags & NSH_PFLAG_IGNORE)));
|
||||
|
||||
/* Close the script file */
|
||||
|
||||
fclose(vtbl->np.np_stream);
|
||||
|
||||
/* Restore the parent script stream */
|
||||
|
||||
vtbl->np.np_stream = savestream;
|
||||
}
|
||||
|
||||
/* Free the allocated path */
|
||||
|
||||
nsh_freefullpath(fullpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_initscript
|
||||
*
|
||||
* Description:
|
||||
* Attempt to execute the configured initialization script. This script
|
||||
* should be executed once when NSH starts. nsh_initscript is idempotent
|
||||
* and may, however, be called multiple times (the script will be executed
|
||||
* once.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSETC
|
||||
int nsh_initscript(FAR struct nsh_vtbl_s *vtbl)
|
||||
{
|
||||
static bool initialized;
|
||||
bool already;
|
||||
int ret = OK;
|
||||
|
||||
/* Atomic test and set of the initialized flag */
|
||||
|
||||
sched_lock();
|
||||
already = initialized;
|
||||
initialized = true;
|
||||
sched_unlock();
|
||||
|
||||
/* If we have not already executed the init script, then do so now */
|
||||
|
||||
if (!already)
|
||||
{
|
||||
ret = nsh_script(vtbl, "init", NSH_INITPATH);
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLESCRIPT
|
||||
/* Reset the option flags */
|
||||
|
||||
vtbl->np.np_flags = NSH_NP_SET_OPTIONS_INIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_loginscript
|
||||
*
|
||||
* Description:
|
||||
* Attempt to execute the configured login script. This script
|
||||
* should be executed when each NSH session starts.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSRC
|
||||
int nsh_loginscript(FAR struct nsh_vtbl_s *vtbl)
|
||||
{
|
||||
return nsh_script(vtbl, "login", NSH_RCPATH);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_NSH_ROMFSETC */
|
||||
|
||||
#endif /* CONFIG_FILE_STREAM && !CONFIG_NSH_DISABLESCRIPT */
|
||||
@@ -0,0 +1,219 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_session.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2014, 2016, 2019 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
# include "system/cle.h"
|
||||
#else
|
||||
# include "system/readline.h"
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_session
|
||||
*
|
||||
* Description:
|
||||
* This is the common session login on any NSH session. This function
|
||||
* returns when an error reading from the input stream occurs, presumably
|
||||
* signaling the end of the session.
|
||||
*
|
||||
* This function:
|
||||
* - Performs the login sequence if so configured
|
||||
* - Executes the NSH login script
|
||||
* - Presents a greeting
|
||||
* - Then provides a prompt then gets and processes the command line.
|
||||
* - This continues until an error occurs, then the session returns.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pstate - Abstracts the underlying session.
|
||||
*
|
||||
* Returned Values:
|
||||
* EXIT_SUCCESS or EXIT_FAILURE is returned.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_session(FAR struct console_stdio_s *pstate,
|
||||
bool login, int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl;
|
||||
int ret = EXIT_FAILURE;
|
||||
|
||||
DEBUGASSERT(pstate);
|
||||
vtbl = &pstate->cn_vtbl;
|
||||
|
||||
if (login)
|
||||
{
|
||||
#ifdef CONFIG_NSH_CONSOLE_LOGIN
|
||||
/* Login User and Password Check */
|
||||
|
||||
if (nsh_login(pstate) != OK)
|
||||
{
|
||||
nsh_exit(vtbl, 1);
|
||||
return -1; /* nsh_exit does not return */
|
||||
}
|
||||
#endif /* CONFIG_NSH_CONSOLE_LOGIN */
|
||||
|
||||
/* Present a greeting and possibly a Message of the Day (MOTD) */
|
||||
|
||||
fputs(g_nshgreeting, pstate->cn_outstream);
|
||||
|
||||
#ifdef CONFIG_NSH_MOTD
|
||||
#ifdef CONFIG_NSH_PLATFORM_MOTD
|
||||
/* Output the platform message of the day */
|
||||
|
||||
platform_motd(vtbl->iobuffer, IOBUFFERSIZE);
|
||||
fprintf(pstate->cn_outstream, "%s\n", vtbl->iobuffer);
|
||||
|
||||
#else
|
||||
/* Output the fixed message of the day */
|
||||
|
||||
fprintf(pstate->cn_outstream, "%s\n", g_nshmotd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* Execute the login script */
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSRC
|
||||
nsh_loginscript(vtbl);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
/* Then enter the command line parsing loop */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* For the case of debugging the USB console...
|
||||
* dump collected USB trace data
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NSH_USBDEV_TRACE
|
||||
nsh_usbtrace();
|
||||
#endif
|
||||
|
||||
/* Get the next line of input. readline() returns EOF
|
||||
* on end-of-file or any read failure.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
/* cle() normally returns the number of characters read, but will
|
||||
* return a negated errno value on end of file or if an error
|
||||
* occurs. Either will cause the session to terminate.
|
||||
*/
|
||||
|
||||
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate), OUTSTREAM(pstate));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
|
||||
"cle", NSH_ERRNO_OF(-ret));
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
/* Display the prompt string */
|
||||
|
||||
fputs(g_nshprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* readline() normally returns the number of characters read, but
|
||||
* will return EOF on end of file or if an error occurs. EOF
|
||||
* will cause the session to terminate.
|
||||
*/
|
||||
|
||||
ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate), OUTSTREAM(pstate));
|
||||
if (ret == EOF)
|
||||
{
|
||||
/* NOTE: readline() does not set the errno variable, but
|
||||
* perhaps we will be lucky and it will still be valid.
|
||||
*/
|
||||
|
||||
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
|
||||
"readline", NSH_ERRNO);
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Parse process the command */
|
||||
|
||||
nsh_parse(vtbl, pstate->cn_line);
|
||||
fflush(pstate->cn_outstream);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
ret = nsh_output(vtbl, "Usage: %s [<script-path>|-c <command>]\n",
|
||||
argv[0]);
|
||||
}
|
||||
else if (strcmp(argv[1], "-c") != 0)
|
||||
{
|
||||
#if defined(CONFIG_FILE_STREAM) && !defined(CONFIG_NSH_DISABLESCRIPT)
|
||||
/* Execute the shell script */
|
||||
|
||||
ret = nsh_script(vtbl, argv[0], argv[1]);
|
||||
#endif
|
||||
}
|
||||
else if (argc >= 3)
|
||||
{
|
||||
/* Parse process the command */
|
||||
|
||||
ret = nsh_parse(vtbl, argv[2]);
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
fflush(pstate->cn_outstream);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_stdlogin.c
|
||||
*
|
||||
* Copyright (C) 2016, 2019 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
# include "system/cle.h"
|
||||
#else
|
||||
# include "system/readline.h"
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_CONSOLE_LOGIN
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_stdtoken
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_stdtoken(FAR struct console_stdio_s *pstate,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
FAR char *start;
|
||||
FAR char *endp1;
|
||||
bool quoted = false;
|
||||
|
||||
/* Find the start of token. Either (1) the first non-white space
|
||||
* character on the command line or (2) the character immediately after
|
||||
* a quotation mark.
|
||||
*/
|
||||
|
||||
for (start = pstate->cn_line; *start; start++)
|
||||
{
|
||||
/* Does the token open with a quotation mark */
|
||||
|
||||
if (*start == '"')
|
||||
{
|
||||
/* Yes.. break out with start set to the character after the
|
||||
* quotation mark.
|
||||
*/
|
||||
|
||||
quoted = true;
|
||||
start++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* No, then any non-whitespace is the first character of the token */
|
||||
|
||||
else if (!isspace(*start))
|
||||
{
|
||||
/* Break out with start set to the first character of the token */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the terminating character after the token on the command line. The
|
||||
* terminating character is either (1) the matching quotation mark, or (2)
|
||||
* any whitespace.
|
||||
*/
|
||||
|
||||
for (endp1 = start; *endp1; endp1++)
|
||||
{
|
||||
/* Did the token begin with a quotation mark? */
|
||||
|
||||
if (quoted)
|
||||
{
|
||||
/* Yes.. then only the matching quotation mark (or end of string)
|
||||
* terminates
|
||||
*/
|
||||
|
||||
if (*endp1 == '"')
|
||||
{
|
||||
/* Break out... endp1 points to closing quotation mark */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No.. any whitespace (or end of string) terminates */
|
||||
|
||||
else if (isspace(*endp1))
|
||||
{
|
||||
/* Break out... endp1 points to first while space encountered */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace terminating character with a NUL terminator */
|
||||
|
||||
*endp1 = '\0';
|
||||
|
||||
/* Copied the token into the buffer */
|
||||
|
||||
strncpy(buffer, start, buflen);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_stdlogin
|
||||
*
|
||||
* Description:
|
||||
* Prompt the user for a username and password. Return a failure if valid
|
||||
* credentials are not returned (after some retries.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_stdlogin(FAR struct console_stdio_s *pstate)
|
||||
{
|
||||
char username[16];
|
||||
char password[16];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Loop for the configured number of retries */
|
||||
|
||||
for (i = 0; i < CONFIG_NSH_LOGIN_FAILCOUNT; i++)
|
||||
{
|
||||
/* Get the response, handling all possible cases */
|
||||
|
||||
username[0] = '\0';
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
/* cle() returns a negated errno value on failure */
|
||||
|
||||
ret = cle(pstate->cn_line, g_userprompt, CONFIG_NSH_LINELEN,
|
||||
stdin, stdout);
|
||||
if (ret >= 0)
|
||||
#else
|
||||
/* Ask for the login username */
|
||||
|
||||
printf("%s", g_userprompt);
|
||||
|
||||
/* readline() returns EOF on failure */
|
||||
|
||||
ret = std_readline(pstate->cn_line, CONFIG_NSH_LINELEN);
|
||||
if (ret != EOF)
|
||||
#endif
|
||||
{
|
||||
/* Parse out the username */
|
||||
|
||||
nsh_stdtoken(pstate, username, sizeof(username));
|
||||
}
|
||||
|
||||
/* Ask for the login password */
|
||||
|
||||
printf("%s", g_passwordprompt);
|
||||
|
||||
password[0] = '\0';
|
||||
if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN, stdin) != NULL)
|
||||
{
|
||||
/* Parse out the password */
|
||||
|
||||
nsh_stdtoken(pstate, password, sizeof(password));
|
||||
|
||||
/* Verify the username and password */
|
||||
|
||||
#if defined(CONFIG_NSH_LOGIN_PASSWD)
|
||||
ret = passwd_verify(username, password);
|
||||
if (PASSWORD_VERIFY_MATCH(ret))
|
||||
|
||||
#elif defined(CONFIG_NSH_LOGIN_PLATFORM)
|
||||
ret = platform_user_verify(username, password);
|
||||
if (PASSWORD_VERIFY_MATCH(ret))
|
||||
|
||||
#elif defined(CONFIG_NSH_LOGIN_FIXED)
|
||||
if (strcmp(password, CONFIG_NSH_LOGIN_PASSWORD) == 0 &&
|
||||
strcmp(username, CONFIG_NSH_LOGIN_USERNAME) == 0)
|
||||
#else
|
||||
# error No user verification method selected
|
||||
#endif
|
||||
{
|
||||
printf("%s", g_loginsuccess);
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", g_badcredentials);
|
||||
#if CONFIG_NSH_LOGIN_FAILDELAY > 0
|
||||
usleep(CONFIG_NSH_LOGIN_FAILDELAY * 1000L);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Too many failed login attempts */
|
||||
|
||||
printf("%s", g_loginfailure);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_CONSOLE_LOGIN */
|
||||
@@ -0,0 +1,200 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_stdsession.c
|
||||
*
|
||||
* Copyright (C) 2013-2014, 2016, 2019 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
# include "system/cle.h"
|
||||
#else
|
||||
# include "system/readline.h"
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_session
|
||||
*
|
||||
* Description:
|
||||
* This is the common session logic or an NSH session that uses only stdin
|
||||
* and stdout.
|
||||
*
|
||||
* This function:
|
||||
* - Executes the NSH logic script
|
||||
* - Presents a greeting
|
||||
* - Then provides a prompt then gets and processes the command line.
|
||||
* - This continues until an error occurs, then the session returns.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pstate - Abstracts the underlying session.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_session(FAR struct console_stdio_s *pstate,
|
||||
bool login, int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct nsh_vtbl_s *vtbl;
|
||||
int ret = EXIT_FAILURE;
|
||||
|
||||
DEBUGASSERT(pstate);
|
||||
vtbl = &pstate->cn_vtbl;
|
||||
|
||||
if (login)
|
||||
{
|
||||
#ifdef CONFIG_NSH_CONSOLE_LOGIN
|
||||
/* Login User and Password Check */
|
||||
|
||||
if (nsh_stdlogin(pstate) != OK)
|
||||
{
|
||||
nsh_exit(vtbl, 1);
|
||||
return -1; /* nsh_exit does not return */
|
||||
}
|
||||
#endif /* CONFIG_NSH_CONSOLE_LOGIN */
|
||||
|
||||
/* Present a greeting and possibly a Message of the Day (MOTD) */
|
||||
|
||||
printf("%s", g_nshgreeting);
|
||||
|
||||
#ifdef CONFIG_NSH_MOTD
|
||||
# ifdef CONFIG_NSH_PLATFORM_MOTD
|
||||
/* Output the platform message of the day */
|
||||
|
||||
platform_motd(vtbl->iobuffer, IOBUFFERSIZE);
|
||||
printf("%s\n", vtbl->iobuffer);
|
||||
|
||||
# else
|
||||
/* Output the fixed message of the day */
|
||||
|
||||
printf("%s\n", g_nshmotd);
|
||||
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
/* Then enter the command line parsing loop */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* For the case of debugging the USB console...
|
||||
* dump collected USB trace data
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NSH_USBDEV_TRACE
|
||||
nsh_usbtrace();
|
||||
#endif
|
||||
|
||||
/* Get the next line of input. */
|
||||
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
/* cle() normally returns the number of characters read, but will
|
||||
* return a negated errno value on end of file or if an error
|
||||
* occurs. Either will cause the session to terminate.
|
||||
*/
|
||||
|
||||
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
|
||||
stdin, stdout);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf(g_fmtcmdfailed,
|
||||
"nsh_session", "cle", NSH_ERRNO_OF(-ret));
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
/* Display the prompt string */
|
||||
|
||||
printf("%s", g_nshprompt);
|
||||
|
||||
/* readline () normally returns the number of characters read, but
|
||||
* will return EOF on end of file or if an error occurs. Either
|
||||
* will cause the session to terminate.
|
||||
*/
|
||||
|
||||
ret = std_readline(pstate->cn_line, CONFIG_NSH_LINELEN);
|
||||
if (ret == EOF)
|
||||
{
|
||||
/* NOTE: readline() does not set the errno variable, but
|
||||
* perhaps we will be lucky and it will still be valid.
|
||||
*/
|
||||
|
||||
printf(g_fmtcmdfailed, "nsh_session", "readline", NSH_ERRNO);
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Parse process the command */
|
||||
|
||||
nsh_parse(vtbl, pstate->cn_line);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
ret = nsh_output(vtbl, "Usage: %s [<script-path>|-c <command>]\n",
|
||||
argv[0]);
|
||||
}
|
||||
else if (strcmp(argv[1], "-c") != 0)
|
||||
{
|
||||
#if defined(CONFIG_FILE_STREAM) && !defined(CONFIG_NSH_DISABLESCRIPT)
|
||||
/* Execute the shell script */
|
||||
|
||||
ret = nsh_script(vtbl, argv[0], argv[1]);
|
||||
#endif
|
||||
}
|
||||
else if (argc >= 3)
|
||||
{
|
||||
/* Parse process the command */
|
||||
|
||||
ret = nsh_parse(vtbl, argv[2]);
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
fflush(pstate->cn_outstream);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,535 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_syscmds.c
|
||||
*
|
||||
* Copyright (C) 2015 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/rptun/rptun.h>
|
||||
#include <sys/boardctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_BOARD_CUSTOM
|
||||
# ifndef CONFIG_ARCH_BOARD_CUSTOM_NAME
|
||||
# define BOARD_NAME g_unknown
|
||||
# else
|
||||
# define BOARD_NAME CONFIG_ARCH_BOARD_CUSTOM_NAME
|
||||
# endif
|
||||
#else
|
||||
# ifndef CONFIG_ARCH_BOARD
|
||||
# define BOARD_NAME g_unknown
|
||||
# else
|
||||
# define BOARD_NAME CONFIG_ARCH_BOARD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define UNAME_KERNEL (1 << 0)
|
||||
#define UNAME_NODE (1 << 1)
|
||||
#define UNAME_RELEASE (1 << 2)
|
||||
#define UNAME_VERISON (1 << 3)
|
||||
#define UNAME_MACHINE (1 << 4)
|
||||
#define UNAME_PLATFORM (1 << 5)
|
||||
#define UNAME_UNKNOWN (1 << 6)
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
# define UNAME_ALL (UNAME_KERNEL | UNAME_NODE | UNAME_RELEASE | \
|
||||
UNAME_VERISON | UNAME_MACHINE | UNAME_PLATFORM)
|
||||
#else
|
||||
# define UNAME_ALL (UNAME_KERNEL | UNAME_RELEASE | UNAME_VERISON | \
|
||||
UNAME_MACHINE | UNAME_PLATFORM)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_UNAME
|
||||
static const char g_unknown[] = "unknown";
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_shutdown
|
||||
****************************************************************************/
|
||||
|
||||
#if (defined(CONFIG_BOARDCTL_POWEROFF) || defined(CONFIG_BOARDCTL_RESET)) && \
|
||||
!defined(CONFIG_NSH_DISABLE_SHUTDOWN)
|
||||
|
||||
int cmd_shutdown(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
#if defined(CONFIG_BOARDCTL_POWEROFF) && defined(CONFIG_BOARDCTL_RESET)
|
||||
/* If both shutdown and reset are supported, then a single option may
|
||||
* be provided to select the reset behavior (--reboot). We know here
|
||||
* that argc is either 1 or 2.
|
||||
*/
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
/* Verify that the single argument is --reboot */
|
||||
|
||||
if (strcmp(argv[1], "--reboot") != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Invoke the BOARDIOC_RESET board control to reset the board. If
|
||||
* the board_reset() function returns, then it was not possible to
|
||||
* reset the board due to some constraints.
|
||||
*/
|
||||
|
||||
boardctl(BOARDIOC_RESET, EXIT_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invoke the BOARDIOC_POWEROFF board control to shutdown the board.
|
||||
* If the board_power_off function returns, then it was not possible
|
||||
* to power-off the* board due to some constraints.
|
||||
*/
|
||||
|
||||
boardctl(BOARDIOC_POWEROFF, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_BOARDCTL_RESET)
|
||||
/* Only reset behavior is supported and we already know that exactly one
|
||||
* argument has been provided.
|
||||
*/
|
||||
|
||||
/* Verify that the single argument is --reboot */
|
||||
|
||||
if (strcmp(argv[1], "--reboot") != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Invoke the BOARDIOC_RESET board control to reset the board. If
|
||||
* the board_reset() function returns, then it was not possible to
|
||||
* reset the board due to some constraints.
|
||||
*/
|
||||
|
||||
boardctl(BOARDIOC_RESET, EXIT_SUCCESS);
|
||||
|
||||
#else
|
||||
/* Only the reset behavior is supported and we already know that there is
|
||||
* no argument to the command.
|
||||
*/
|
||||
|
||||
/* Invoke the BOARDIOC_POWEROFF board control to shutdown the board. If
|
||||
* the board_power_off function returns, then it was not possible to power-
|
||||
* off the board due to some constraints.
|
||||
*/
|
||||
|
||||
boardctl(BOARDIOC_POWEROFF, EXIT_SUCCESS);
|
||||
#endif
|
||||
|
||||
/* boarctl() will not return in any case. It if does, it means that
|
||||
* there was a problem with the shutdown/resaet operation.
|
||||
*/
|
||||
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "boardctl", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
#endif /* CONFIG_BOARDCTL_POWEROFF && !CONFIG_NSH_DISABLE_SHUTDOWN */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_pmconfig
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_PM) && !defined(CONFIG_NSH_DISABLE_PMCONFIG)
|
||||
int cmd_pmconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
struct boardioc_pm_ctrl_s ctrl =
|
||||
{
|
||||
};
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
int current_state;
|
||||
int normal_count;
|
||||
int idle_count;
|
||||
int standby_count;
|
||||
int sleep_count;
|
||||
|
||||
ctrl.action = BOARDIOC_PM_QUERYSTATE;
|
||||
boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)&ctrl);
|
||||
current_state = ctrl.state;
|
||||
|
||||
ctrl.action = BOARDIOC_PM_STAYCOUNT;
|
||||
ctrl.state = PM_NORMAL;
|
||||
boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)&ctrl);
|
||||
normal_count = ctrl.count;
|
||||
|
||||
ctrl.state = PM_IDLE;
|
||||
boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)&ctrl);
|
||||
idle_count = ctrl.count;
|
||||
|
||||
ctrl.state = PM_STANDBY;
|
||||
boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)&ctrl);
|
||||
standby_count = ctrl.count;
|
||||
|
||||
ctrl.state = PM_SLEEP;
|
||||
boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)&ctrl);
|
||||
sleep_count = ctrl.count;
|
||||
|
||||
nsh_output(vtbl, "Current state %d, PM stay [%d, %d, %d, %d]\n",
|
||||
current_state, normal_count, idle_count, standby_count, sleep_count);
|
||||
}
|
||||
else if (argc == 3)
|
||||
{
|
||||
if (strcmp(argv[1], "stay") == 0)
|
||||
{
|
||||
ctrl.action = BOARDIOC_PM_STAY;
|
||||
}
|
||||
else if (strcmp(argv[1], "relax") == 0)
|
||||
{
|
||||
ctrl.action = BOARDIOC_PM_RELAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_output(vtbl, g_fmtarginvalid, argv[1]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (strcmp(argv[2], "normal") == 0)
|
||||
{
|
||||
ctrl.state = PM_NORMAL;
|
||||
}
|
||||
else if (strcmp(argv[2], "idle") == 0)
|
||||
{
|
||||
ctrl.state = PM_IDLE;
|
||||
}
|
||||
else if (strcmp(argv[2], "standby") == 0)
|
||||
{
|
||||
ctrl.state = PM_STANDBY;
|
||||
}
|
||||
else if (strcmp(argv[2], "sleep") == 0)
|
||||
{
|
||||
ctrl.state = PM_SLEEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_output(vtbl, g_fmtarginvalid, argv[2]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
boardctl(BOARDIOC_PM_CONTROL, (uintptr_t)&ctrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_error(vtbl, g_fmttoomanyargs, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_poweroff
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_BOARDCTL_POWEROFF) && !defined(CONFIG_NSH_DISABLE_POWEROFF)
|
||||
int cmd_poweroff(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
/* Invoke the BOARDIOC_POWEROFF board control to shutdown the board. If
|
||||
* the board_power_off function returns, then it was not possible to power-
|
||||
* off the board due to some constraints.
|
||||
*/
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
boardctl(BOARDIOC_POWEROFF, atoi(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
boardctl(BOARDIOC_POWEROFF, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* boarctl() will not return in any case. It if does, it means that
|
||||
* there was a problem with the shutdown operation.
|
||||
*/
|
||||
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "boardctl", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_reboot
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_BOARDCTL_RESET) && !defined(CONFIG_NSH_DISABLE_REBOOT)
|
||||
int cmd_reboot(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
/* Invoke the BOARDIOC_RESET board control to reset the board. If
|
||||
* the board_reset() function returns, then it was not possible to
|
||||
* reset the board due to some constraints.
|
||||
*/
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
boardctl(BOARDIOC_RESET, atoi(argv[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
boardctl(BOARDIOC_RESET, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* boarctl() will not return in this case. It if does, it means that
|
||||
* there was a problem with the reset operation.
|
||||
*/
|
||||
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "boardctl", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_rptun
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_RPTUN) && !defined(CONFIG_NSH_DISABLE_RPTUN)
|
||||
int cmd_rptun(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
int cmd;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
nsh_output(vtbl, g_fmtargrequired, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "start") == 0)
|
||||
{
|
||||
cmd = RPTUNIOC_START;
|
||||
}
|
||||
else if (strcmp(argv[1], "stop") == 0)
|
||||
{
|
||||
cmd = RPTUNIOC_STOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
nsh_output(vtbl, g_fmtarginvalid, argv[1]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
fd = open(argv[2], 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
nsh_output(vtbl, g_fmtarginvalid, argv[2]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ioctl(fd, cmd, 0);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_uname
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_UNAME
|
||||
int cmd_uname(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR const char *str;
|
||||
struct utsname info;
|
||||
unsigned int set;
|
||||
int option;
|
||||
bool badarg;
|
||||
bool first;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Get the uname options */
|
||||
|
||||
set = 0;
|
||||
badarg = false;
|
||||
|
||||
while ((option = getopt(argc, argv, "asonrvmpi")) != ERROR)
|
||||
{
|
||||
switch (option)
|
||||
{
|
||||
case 'a':
|
||||
set = UNAME_ALL;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 's':
|
||||
set |= UNAME_KERNEL;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
case 'n':
|
||||
set |= UNAME_NODE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'r':
|
||||
set |= UNAME_RELEASE;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
set |= UNAME_VERISON;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
set |= UNAME_MACHINE;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (set != UNAME_ALL)
|
||||
{
|
||||
set |= UNAME_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
set |= UNAME_PLATFORM;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
badarg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a bad argument was encountered, then return without processing the
|
||||
* command
|
||||
*/
|
||||
|
||||
if (badarg)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* If nothing is provided on the command line, the default is -s */
|
||||
|
||||
if (set == 0)
|
||||
{
|
||||
set = UNAME_KERNEL;
|
||||
}
|
||||
|
||||
/* Get uname data */
|
||||
|
||||
ret = uname(&info);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "uname", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Process each option */
|
||||
|
||||
first = true;
|
||||
for (i = 0; set != 0; i++)
|
||||
{
|
||||
unsigned int mask = (1 << i);
|
||||
if ((set & mask) != 0)
|
||||
{
|
||||
set &= ~mask;
|
||||
switch (i)
|
||||
{
|
||||
case 0: /* print the kernel/operating system name */
|
||||
str = info.sysname;
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
case 1: /* Print noname */
|
||||
str = info.nodename;
|
||||
break;
|
||||
#endif
|
||||
case 2: /* Print the kernel release */
|
||||
str = info.release;
|
||||
break;
|
||||
|
||||
case 3: /* Print the kernel version */
|
||||
str = info.version;
|
||||
break;
|
||||
|
||||
case 4: /* Print the machine hardware name */
|
||||
str = info.machine;
|
||||
break;
|
||||
|
||||
case 5: /* Print the machine platform name */
|
||||
str = BOARD_NAME;
|
||||
break;
|
||||
|
||||
case 6: /* Print "unknown" */
|
||||
str = g_unknown;
|
||||
break;
|
||||
|
||||
default:
|
||||
nsh_error(vtbl, g_fmtarginvalid, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (!first)
|
||||
{
|
||||
nsh_output(vtbl, " ");
|
||||
}
|
||||
|
||||
nsh_output(vtbl, str);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "\n");
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_system.c
|
||||
*
|
||||
* Copyright (C) 2016 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_system
|
||||
*
|
||||
* Description:
|
||||
* This is the NSH-specific implementation of the standard system()
|
||||
* command.
|
||||
*
|
||||
* NOTE: This assumes that other NSH instances have previously ran and so
|
||||
* common NSH logic is already initialized.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard task start-up arguments. Expects argc == 2 with argv[1] being
|
||||
* the command to execute
|
||||
*
|
||||
* Returned Values:
|
||||
* EXIT_SUCCESS or EXIT_FAILURE
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_system(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = nsh_newconsole();
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(pstate != NULL);
|
||||
|
||||
/* Execute the session */
|
||||
|
||||
ret = nsh_session(pstate, false, argc, argv);
|
||||
|
||||
/* Exit upon return */
|
||||
|
||||
nsh_exit(&pstate->cn_vtbl, ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_telnetd.c
|
||||
*
|
||||
* Copyright (C) 2007-2013, 2016-2017, 2019 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "netutils/telnetd.h"
|
||||
|
||||
#ifdef CONFIG_TELNET_CHARACTER_MODE
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
# include "system/cle.h"
|
||||
#else
|
||||
# include "system/readline.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_TELNET
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum telnetd_state_e
|
||||
{
|
||||
TELNETD_NOTRUNNING = 0,
|
||||
TELNETD_STARTED,
|
||||
TELNETD_RUNNING
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnetmain
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_telnetmain(int argc, char *argv[])
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = nsh_newconsole();
|
||||
FAR struct nsh_vtbl_s *vtbl;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(pstate != NULL);
|
||||
vtbl = &pstate->cn_vtbl;
|
||||
|
||||
ninfo("Session [%d] Started\n", getpid());
|
||||
|
||||
#ifdef CONFIG_NSH_TELNET_LOGIN
|
||||
/* Login User and Password Check */
|
||||
|
||||
if (nsh_telnetlogin(pstate) != OK)
|
||||
{
|
||||
nsh_exit(vtbl, 1);
|
||||
return -1; /* nsh_exit does not return */
|
||||
}
|
||||
#endif /* CONFIG_NSH_TELNET_LOGIN */
|
||||
|
||||
/* The following logic mostly the same as the login in nsh_session.c. It
|
||||
* differs only in that gets() is called to get the command instead of
|
||||
* readline().
|
||||
*/
|
||||
|
||||
/* Present a greeting and possibly a Message of the Day (MOTD) */
|
||||
|
||||
fputs(g_nshgreeting, pstate->cn_outstream);
|
||||
|
||||
#ifdef CONFIG_NSH_MOTD
|
||||
# ifdef CONFIG_NSH_PLATFORM_MOTD
|
||||
/* Output the platform message of the day */
|
||||
|
||||
platform_motd(vtbl->iobuffer, IOBUFFERSIZE);
|
||||
fprintf(pstate->cn_outstream, "%s\n", vtbl->iobuffer);
|
||||
|
||||
# else
|
||||
/* Output the fixed message of the day */
|
||||
|
||||
fprintf(pstate->cn_outstream, "%s\n", g_nshmotd);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* Execute the login script */
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSRC
|
||||
nsh_loginscript(vtbl);
|
||||
#endif
|
||||
|
||||
/* Then enter the command line parsing loop */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Get the next line of input from the Telnet client */
|
||||
|
||||
#ifdef CONFIG_TELNET_CHARACTER_MODE
|
||||
#ifdef CONFIG_NSH_CLE
|
||||
/* cle() returns a negated errno value on failure (errno is not set) */
|
||||
|
||||
ret = cle(pstate->cn_line, g_nshprompt, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate), OUTSTREAM(pstate));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_telnetmain",
|
||||
"cle", NSH_ERRNO_OF(-ret));
|
||||
nsh_exit(vtbl, 1);
|
||||
}
|
||||
#else
|
||||
/* Display the prompt string */
|
||||
|
||||
fputs(g_nshprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* readline() returns EOF on failure (errno is not set) */
|
||||
|
||||
ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate), OUTSTREAM(pstate));
|
||||
if (ret == EOF)
|
||||
{
|
||||
/* NOTE: readline() does not set the errno variable, but perhaps we
|
||||
* will be lucky and it will still be valid.
|
||||
*/
|
||||
|
||||
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_telnetmain",
|
||||
"readline", NSH_ERRNO);
|
||||
nsh_exit(vtbl, 1);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
/* Display the prompt string */
|
||||
|
||||
fputs(g_nshprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* fgets() returns NULL on failure (errno will be set) */
|
||||
|
||||
if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate)) == NULL)
|
||||
{
|
||||
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_telnetmain",
|
||||
"fgets", NSH_ERRNO);
|
||||
nsh_exit(vtbl, 1);
|
||||
}
|
||||
|
||||
ret = strlen(pstate->cn_line);
|
||||
#endif
|
||||
|
||||
/* Parse process the received Telnet command */
|
||||
|
||||
nsh_parse(vtbl, pstate->cn_line);
|
||||
fflush(pstate->cn_outstream);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
|
||||
nsh_exit(vtbl, 0);
|
||||
|
||||
/* We do not get here, but this is necessary to keep some compilers happy */
|
||||
|
||||
UNUSED(ret);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnetstart
|
||||
*
|
||||
* Description:
|
||||
* nsh_telnetstart() starts the Telnet daemon that will allow multiple
|
||||
* NSH connections via Telnet. This function returns immediately after
|
||||
* the daemon has been started.
|
||||
*
|
||||
* Input Parameters:
|
||||
* family - Provides the IP family to use by the server. May be either
|
||||
* AF_INET or AF_INET6. This is needed because both both may be
|
||||
* enabled in the configuration.
|
||||
*
|
||||
* All of the other properties of the Telnet daemon are controlled by
|
||||
* NuttX configuration settings.
|
||||
*
|
||||
* Returned Values:
|
||||
* The task ID of the Telnet daemon was successfully started. A negated
|
||||
* errno value will be returned on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_telnetstart(sa_family_t family)
|
||||
{
|
||||
static enum telnetd_state_e state = TELNETD_NOTRUNNING;
|
||||
int ret = OK;
|
||||
|
||||
if (state == TELNETD_NOTRUNNING)
|
||||
{
|
||||
struct telnetd_config_s config;
|
||||
|
||||
/* There is a tiny race condition here if two tasks were to try to
|
||||
* start the Telnet daemon concurrently.
|
||||
*/
|
||||
|
||||
state = TELNETD_STARTED;
|
||||
|
||||
/* Initialize any USB tracing options that were requested. If
|
||||
* standard console is also defined, then we will defer this step to
|
||||
* the standard console.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NSH_USBDEV_TRACE) && !defined(CONFIG_NSH_CONSOLE)
|
||||
usbtrace_enable(TRACE_BITSET);
|
||||
#endif
|
||||
|
||||
/* Execute the startup script. If standard console is also defined,
|
||||
* then we will not bother with the initscript here (although it is
|
||||
* safe to call nsh_initscript multiple times).
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NSH_ROMFSETC) && !defined(CONFIG_NSH_CONSOLE)
|
||||
nsh_initscript(vtbl);
|
||||
#endif
|
||||
|
||||
/* Perform architecture-specific final-initialization(if configured) */
|
||||
|
||||
#if defined(CONFIG_NSH_ARCHINIT) && \
|
||||
defined(CONFIG_BOARDCTL_FINALINIT) && \
|
||||
!defined(CONFIG_NSH_CONSOLE)
|
||||
boardctl(BOARDIOC_FINALINIT, 0);
|
||||
#endif
|
||||
|
||||
/* Configure the telnet daemon */
|
||||
|
||||
config.d_port = HTONS(CONFIG_NSH_TELNETD_PORT);
|
||||
config.d_priority = CONFIG_NSH_TELNETD_DAEMONPRIO;
|
||||
config.d_stacksize = CONFIG_NSH_TELNETD_DAEMONSTACKSIZE;
|
||||
config.t_priority = CONFIG_NSH_TELNETD_CLIENTPRIO;
|
||||
config.t_stacksize = CONFIG_NSH_TELNETD_CLIENTSTACKSIZE;
|
||||
config.t_entry = nsh_telnetmain;
|
||||
|
||||
/* Start the telnet daemon */
|
||||
|
||||
ninfo("Starting the Telnet daemon\n");
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (family == AF_UNSPEC || family == AF_INET)
|
||||
{
|
||||
config.d_family = AF_INET;
|
||||
ret = telnetd_start(&config);
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: Failed to start the Telnet IPv4 daemon: %d\n",
|
||||
ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = TELNETD_RUNNING;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (family == AF_UNSPEC || family == AF_INET6)
|
||||
{
|
||||
config.d_family = AF_INET6;
|
||||
ret = telnetd_start(&config);
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: Failed to start the Telnet IPv6 daemon: %d\n",
|
||||
ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = TELNETD_RUNNING;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state == TELNETD_STARTED)
|
||||
{
|
||||
state = TELNETD_NOTRUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_telnetd
|
||||
*
|
||||
* Description:
|
||||
* The Telnet daemon may be started either programmatically by calling
|
||||
* nsh_telnetstart() or it may be started from the NSH command line using
|
||||
* this telnetd command.
|
||||
*
|
||||
* This command would be suppressed with CONFIG_NSH_DISABLE_TELNETD
|
||||
* normally because the Telnet daemon is automatically started in
|
||||
* nsh_main.c. The exception is when CONFIG_NETINIT_NETLOCAL is selected.
|
||||
* IN that case, the network is not enabled at initialization but rather
|
||||
* must be enabled from the NSH command line or via other applications.
|
||||
*
|
||||
* In that case, calling nsh_telnetstart() before the the network is
|
||||
* initialized will fail.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None. All of the properties of the Telnet daemon are controlled by
|
||||
* NuttX configuration setting.
|
||||
*
|
||||
* Returned Values:
|
||||
* OK is returned on success; ERROR is return on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_TELNETD
|
||||
int cmd_telnetd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
sa_family_t family = AF_UNSPEC;
|
||||
|
||||
/* If both IPv6 and IPv4 are enabled, then the address family must
|
||||
* be specified on the command line.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
if (argc >= 2)
|
||||
{
|
||||
family = (strcmp(argv[1], "ipv6") == 0) ? AF_INET6 : AF_INET;
|
||||
}
|
||||
#endif
|
||||
|
||||
return nsh_telnetstart(family) < 0 ? ERROR : OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NSH_TELNET */
|
||||
@@ -0,0 +1,258 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_telnetlogin.c
|
||||
*
|
||||
* Copyright (C) 2007-2013, 2016 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 Gregory Nutt 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_TELNET_LOGIN
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define TELNET_IAC 255
|
||||
#define TELNET_WILL 251
|
||||
#define TELNET_WONT 252
|
||||
#define TELNET_DO 253
|
||||
#define TELNET_DONT 254
|
||||
#define TELNET_USE_ECHO 1
|
||||
#define TELNET_NOTUSE_ECHO 0
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnetecho
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_telnetecho(FAR struct console_stdio_s *pstate,
|
||||
uint8_t is_use)
|
||||
{
|
||||
uint8_t optbuf[4];
|
||||
optbuf[0] = TELNET_IAC;
|
||||
optbuf[1] = (is_use == TELNET_USE_ECHO) ? TELNET_WILL : TELNET_DO;
|
||||
optbuf[2] = 1;
|
||||
optbuf[3] = 0;
|
||||
fputs((char *)optbuf, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnettoken
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_telnettoken(FAR struct console_stdio_s *pstate,
|
||||
FAR char *buffer, size_t buflen)
|
||||
{
|
||||
FAR char *start;
|
||||
FAR char *endp1;
|
||||
bool quoted = false;
|
||||
|
||||
/* Find the start of token. Either (1) the first non-white space
|
||||
* character on the command line or (2) the character immediately after
|
||||
* a quotation mark.
|
||||
*/
|
||||
|
||||
for (start = pstate->cn_line; *start; start++)
|
||||
{
|
||||
/* Does the token open with a quotation mark */
|
||||
|
||||
if (*start == '"')
|
||||
{
|
||||
/* Yes.. break out with start set to the character after the
|
||||
* quotation mark.
|
||||
*/
|
||||
|
||||
quoted = true;
|
||||
start++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* No, then any non-whitespace is the first character of the token */
|
||||
|
||||
else if (!isspace(*start))
|
||||
{
|
||||
/* Break out with start set to the first character of the token */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the terminating character after the token on the command line. The
|
||||
* terminating character is either (1) the matching quotation mark, or (2)
|
||||
* any whitespace.
|
||||
*/
|
||||
|
||||
for (endp1 = start; *endp1; endp1++)
|
||||
{
|
||||
/* Did the token begin with a quotation mark? */
|
||||
|
||||
if (quoted)
|
||||
{
|
||||
/* Yes.. then only the matching quotation mark (or end of string)
|
||||
* terminates
|
||||
*/
|
||||
|
||||
if (*endp1 == '"')
|
||||
{
|
||||
/* Break out... endp1 points to closing quotation mark */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No.. any whitespace (or end of string) terminates */
|
||||
|
||||
else if (isspace(*endp1))
|
||||
{
|
||||
/* Break out... endp1 points to first while space encountered */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace terminating character with a NUL terminator */
|
||||
|
||||
*endp1 = '\0';
|
||||
|
||||
/* Copied the token into the buffer */
|
||||
|
||||
strncpy(buffer, start, buflen);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_telnetlogin
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_telnetlogin(FAR struct console_stdio_s *pstate)
|
||||
{
|
||||
char username[16];
|
||||
char password[16];
|
||||
int i;
|
||||
|
||||
/* Present the NSH Telnet greeting */
|
||||
|
||||
fputs(g_telnetgreeting, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
/* Loop for the configured number of retries */
|
||||
|
||||
for (i = 0; i < CONFIG_NSH_LOGIN_FAILCOUNT; i++)
|
||||
{
|
||||
/* Ask for the login username */
|
||||
|
||||
fputs(g_userprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
|
||||
username[0] = '\0';
|
||||
if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate)) != NULL)
|
||||
{
|
||||
/* Parse out the username */
|
||||
|
||||
nsh_telnettoken(pstate, username, sizeof(username));
|
||||
}
|
||||
|
||||
/* Ask for the login password */
|
||||
|
||||
fputs(g_passwordprompt, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
nsh_telnetecho(pstate, TELNET_NOTUSE_ECHO);
|
||||
|
||||
password[0] = '\0';
|
||||
if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN,
|
||||
INSTREAM(pstate)) != NULL)
|
||||
{
|
||||
/* Parse out the password */
|
||||
|
||||
nsh_telnettoken(pstate, password, sizeof(password));
|
||||
|
||||
/* Verify the username and password */
|
||||
|
||||
#if defined(CONFIG_NSH_LOGIN_PASSWD)
|
||||
if (PASSWORD_VERIFY_MATCH(passwd_verify(username, password)))
|
||||
#elif defined(CONFIG_NSH_LOGIN_PLATFORM)
|
||||
if (PASSWORD_VERIFY_MATCH(platform_user_verify(username,
|
||||
password)))
|
||||
#elif defined(CONFIG_NSH_LOGIN_FIXED)
|
||||
if (strcmp(password, CONFIG_NSH_LOGIN_PASSWORD) == 0 &&
|
||||
strcmp(username, CONFIG_NSH_LOGIN_USERNAME) == 0)
|
||||
#else
|
||||
# error No user verification method selected
|
||||
#endif
|
||||
{
|
||||
fputs(g_loginsuccess, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
nsh_telnetecho(pstate, TELNET_USE_ECHO);
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
fputs(g_badcredentials, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
#if CONFIG_NSH_LOGIN_FAILDELAY > 0
|
||||
usleep(CONFIG_NSH_LOGIN_FAILDELAY * 1000L);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
nsh_telnetecho(pstate, TELNET_USE_ECHO);
|
||||
}
|
||||
|
||||
/* Too many failed login attempts */
|
||||
|
||||
fputs(g_loginfailure, pstate->cn_outstream);
|
||||
fflush(pstate->cn_outstream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_TELNET_LOGIN */
|
||||
@@ -0,0 +1,453 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_test.c
|
||||
*
|
||||
* Copyright (C) 2008, 2011-2012, 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Test syntax:
|
||||
*
|
||||
* expression = simple-expression | !expression |
|
||||
* expression -o expression | expression -a expression
|
||||
*
|
||||
* simple-expression = unary-expression | binary-expression
|
||||
*
|
||||
* unary-expression = string-unary | file-unary
|
||||
*
|
||||
* string-unary = -n string | -z string
|
||||
*
|
||||
* file-unary = -b file | -c file | -d file | -e file | -f file |
|
||||
* -r file | -s file | -w file
|
||||
*
|
||||
* binary-expression = string-binary | numeric-binary
|
||||
*
|
||||
* string-binary = string = string | string == string | string != string
|
||||
*
|
||||
* numeric-binary = integer -eq integer | integer -ge integer |
|
||||
* integer -gt integer | integer -le integer |
|
||||
* integer -lt integer | integer -ne integer
|
||||
*
|
||||
* Note that the smallest expression consists of two strings.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define TEST_TRUE OK
|
||||
#define TEST_FALSE ERROR
|
||||
#define TEST_ERROR 1
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binaryexpression
|
||||
****************************************************************************/
|
||||
|
||||
static inline int binaryexpression(FAR struct nsh_vtbl_s *vtbl, char **argv)
|
||||
{
|
||||
char *endptr;
|
||||
long integer1;
|
||||
long integer2;
|
||||
|
||||
/* STRING2 = STRING2 */
|
||||
|
||||
if (strcmp(argv[1], "=") == 0 || strcmp(argv[1], "==") == 0)
|
||||
{
|
||||
/* Return true if the strings are identical */
|
||||
|
||||
return strcmp(argv[0], argv[2]) == 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* STRING1 != STRING2 */
|
||||
|
||||
if (strcmp(argv[1], "!=") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return strcmp(argv[0], argv[2]) != 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* The remaining operators assuming that the two values are integers */
|
||||
|
||||
integer1 = strtol(argv[0], &endptr, 0);
|
||||
if (argv[0][0] == '\0' || *endptr != '\0')
|
||||
{
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
integer2 = strtol(argv[2], &endptr, 0);
|
||||
if (argv[2][0] == '\0' || *endptr != '\0')
|
||||
{
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
/* INTEGER1 -eq INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-eq") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 == integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -ge INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-ge") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 >= integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -gt INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-gt") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 > integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -le INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-le") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 <= integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -lt INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-lt") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 < integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -ne INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-ne") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 != integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unaryexpression
|
||||
****************************************************************************/
|
||||
|
||||
static inline int unaryexpression(FAR struct nsh_vtbl_s *vtbl, char **argv)
|
||||
{
|
||||
struct stat buf;
|
||||
char *fullpath;
|
||||
int ret;
|
||||
|
||||
/* -n STRING */
|
||||
|
||||
if (strcmp(argv[0], "-n") == 0)
|
||||
{
|
||||
/* Return true if the length of the string is non-zero */
|
||||
|
||||
return strlen(argv[1]) != 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -z STRING */
|
||||
|
||||
if (strcmp(argv[0], "-z") == 0)
|
||||
{
|
||||
/* Return true if the length of the string is zero */
|
||||
|
||||
return strlen(argv[1]) == 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* All of the remaining assume that the following argument is the
|
||||
* path to a file.
|
||||
*/
|
||||
|
||||
fullpath = nsh_getfullpath(vtbl, argv[1]);
|
||||
if (!fullpath)
|
||||
{
|
||||
return TEST_FALSE;
|
||||
}
|
||||
|
||||
ret = stat(fullpath, &buf);
|
||||
nsh_freefullpath(fullpath);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
/* The file does not exist (or another error occurred) -- return
|
||||
* FALSE.
|
||||
*/
|
||||
|
||||
return TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -b FILE */
|
||||
|
||||
if (strcmp(argv[0], "-b") == 0)
|
||||
{
|
||||
/* Return true if the path is a block device */
|
||||
|
||||
return S_ISBLK(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -c FILE */
|
||||
|
||||
if (strcmp(argv[0], "-c") == 0)
|
||||
{
|
||||
/* Return true if the path is a character device */
|
||||
|
||||
return S_ISCHR(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -d FILE */
|
||||
|
||||
if (strcmp(argv[0], "-d") == 0)
|
||||
{
|
||||
/* Return true if the path is a directory */
|
||||
|
||||
return S_ISDIR(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -e FILE */
|
||||
|
||||
if (strcmp(argv[0], "-e") == 0)
|
||||
{
|
||||
/* Return true if the file exists */
|
||||
|
||||
return TEST_TRUE;
|
||||
}
|
||||
|
||||
/* -f FILE */
|
||||
|
||||
if (strcmp(argv[0], "-f") == 0)
|
||||
{
|
||||
/* Return true if the path refers to a regular file */
|
||||
|
||||
return S_ISREG(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -r FILE */
|
||||
|
||||
if (strcmp(argv[0], "-r") == 0)
|
||||
{
|
||||
/* Return true if the file is readable */
|
||||
|
||||
return (buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) != 0 ?
|
||||
TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -s FILE */
|
||||
|
||||
if (strcmp(argv[0], "-s") == 0)
|
||||
{
|
||||
/* Return true if the size of the file is greater than zero */
|
||||
|
||||
return buf.st_size > 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -w FILE */
|
||||
|
||||
if (strcmp(argv[0], "-w") == 0)
|
||||
{
|
||||
/* Return true if the file is write-able */
|
||||
|
||||
return (buf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0 ?
|
||||
TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* Unrecognized operator */
|
||||
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: expression
|
||||
****************************************************************************/
|
||||
|
||||
static int expression(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int value;
|
||||
int i = 0;
|
||||
|
||||
/* Check for unary operations on expressions */
|
||||
|
||||
if (strcmp(argv[0], "!") == 0)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
|
||||
return expression(vtbl, argc - 1, &argv[1]) == TEST_TRUE ?
|
||||
TEST_FALSE : TEST_TRUE;
|
||||
}
|
||||
|
||||
/* Check for unary operations on simple, typed arguments */
|
||||
|
||||
else if (argv[0][0] == '-')
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
|
||||
i += 2;
|
||||
value = unaryexpression(vtbl, argv);
|
||||
}
|
||||
|
||||
/* Check for binary operations on simple, typed arguments */
|
||||
|
||||
else
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
|
||||
i += 3;
|
||||
value = binaryexpression(vtbl, argv);
|
||||
}
|
||||
|
||||
/* Test if there any failure */
|
||||
|
||||
if (value == TEST_ERROR)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
|
||||
/* Is there anything after the simple expression? */
|
||||
|
||||
if (i < argc)
|
||||
{
|
||||
/* EXPRESSION -a EXPRESSION */
|
||||
|
||||
if (strcmp(argv[i], "-a") == 0)
|
||||
{
|
||||
if (value != TEST_TRUE)
|
||||
{
|
||||
return TEST_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
return expression(vtbl, argc - i, &argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* EXPRESSION -o EXPRESSION */
|
||||
|
||||
else if (strcmp(argv[i], "-o") == 0)
|
||||
{
|
||||
if (value == TEST_TRUE)
|
||||
{
|
||||
return TEST_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
return expression(vtbl, argc - i, &argv[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
errout_syntax:
|
||||
nsh_error(vtbl, g_fmtsyntax, "test");
|
||||
return TEST_FALSE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_test
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return expression(vtbl, argc - 1, &argv[1]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_lbracket
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
/* Verify that the closing right bracket is the last thing on the command
|
||||
* line.
|
||||
*/
|
||||
|
||||
if (strcmp(argv[argc - 1], "]") != 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtsyntax, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Then perform the test on the arguments enclosed by the left and right
|
||||
* brackets.
|
||||
*/
|
||||
|
||||
return expression(vtbl, argc - 2, &argv[1]);
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_NSH_DISABLESCRIPT && !CONFIG_NSH_DISABLE_TEST */
|
||||
@@ -0,0 +1,426 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/dbg_timcmds.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2014, 2019 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 <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define MAX_TIME_STRING 80
|
||||
|
||||
#ifdef CONFIG_CLOCK_MONOTONIC
|
||||
# define TIME_CLOCK CLOCK_MONOTONIC
|
||||
#else
|
||||
# define TIME_CLOCK CLOCK_REALTIME
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DATE
|
||||
static FAR const char * const g_datemontab[] =
|
||||
{
|
||||
"jan", "feb", "mar", "apr", "may", "jun",
|
||||
"jul", "aug", "sep", "oct", "nov", "dec"
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: date_month
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DATE
|
||||
static inline int date_month(FAR const char *abbrev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
if (strncasecmp(g_datemontab[i], abbrev, 3) == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: date_gettime
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DATE
|
||||
static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *name)
|
||||
{
|
||||
static const char format[] = "%a, %b %d %H:%M:%S %Y";
|
||||
struct timespec ts;
|
||||
struct tm tm;
|
||||
char timbuf[MAX_TIME_STRING];
|
||||
int ret;
|
||||
|
||||
/* Get the current time */
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, name, "clock_gettime", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Break the current time up into the format needed by strftime */
|
||||
|
||||
if (gmtime_r((FAR const time_t *)&ts.tv_sec, &tm) == NULL)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, name, "gmtime_r", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Show the current time in the requested format */
|
||||
|
||||
ret = strftime(timbuf, MAX_TIME_STRING, format, &tm);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, name, "strftime", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
nsh_output(vtbl, "%s\n", timbuf);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: date_settime
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DATE
|
||||
static inline int date_settime(FAR struct nsh_vtbl_s *vtbl,
|
||||
FAR const char *name, FAR char *newtime)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct tm tm;
|
||||
FAR char *token;
|
||||
FAR char *saveptr;
|
||||
long result;
|
||||
int ret;
|
||||
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
|
||||
/* Only this date format is supported: MMM DD HH:MM:SS YYYY */
|
||||
|
||||
/* Get the month abbreviation */
|
||||
|
||||
token = strtok_r(newtime, " \t", &saveptr);
|
||||
if (token == NULL)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
tm.tm_mon = date_month(token);
|
||||
if (tm.tm_mon < 0)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
/* Get the day of the month.
|
||||
* NOTE: Accepts day-of-month up to 31 for all months
|
||||
*/
|
||||
|
||||
token = strtok_r(NULL, " \t", &saveptr);
|
||||
if (token == NULL)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
result = strtol(token, NULL, 10);
|
||||
if (result < 1 || result > 31)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
tm.tm_mday = (int)result;
|
||||
|
||||
/* Get the hours */
|
||||
|
||||
token = strtok_r(NULL, " \t:", &saveptr);
|
||||
if (token == NULL)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
result = strtol(token, NULL, 10);
|
||||
if (result < 0 || result > 23)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
tm.tm_hour = (int)result;
|
||||
|
||||
/* Get the minutes */
|
||||
|
||||
token = strtok_r(NULL, " \t:", &saveptr);
|
||||
if (token == NULL)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
result = strtol(token, NULL, 10);
|
||||
if (result < 0 || result > 59)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
tm.tm_min = (int)result;
|
||||
|
||||
/* Get the seconds */
|
||||
|
||||
token = strtok_r(NULL, " \t:", &saveptr);
|
||||
if (token == NULL)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
result = strtol(token, NULL, 10);
|
||||
if (result < 0 || result > 61)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
tm.tm_sec = (int)result;
|
||||
|
||||
/* And finally the year */
|
||||
|
||||
token = strtok_r(NULL, " \t", &saveptr);
|
||||
if (token == NULL)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
result = strtol(token, NULL, 10);
|
||||
if (result < 1900 || result > 2100)
|
||||
{
|
||||
goto errout_bad_parm;
|
||||
}
|
||||
|
||||
tm.tm_year = (int)result - 1900;
|
||||
|
||||
/* Convert this to the right form, then set the timer */
|
||||
|
||||
ts.tv_sec = mktime(&tm);
|
||||
ts.tv_nsec = 0;
|
||||
|
||||
ret = clock_settime(CLOCK_REALTIME, &ts);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, name, "clock_settime", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
errout_bad_parm:
|
||||
nsh_error(vtbl, g_fmtarginvalid, name);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_time
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_TIME
|
||||
int cmd_time(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
struct timespec start;
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
bool bgsave;
|
||||
#endif
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
bool redirsave;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
/* Get the current time */
|
||||
|
||||
ret = clock_gettime(TIME_CLOCK, &start);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed, argv[0], "clock_gettime", NSH_ERRNO);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Save state */
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
bgsave = vtbl->np.np_bg;
|
||||
#endif
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
redirsave = vtbl->np.np_redirect;
|
||||
#endif
|
||||
|
||||
/* Execute the command */
|
||||
|
||||
ret = nsh_parse(vtbl, argv[1]);
|
||||
if (ret >= 0)
|
||||
{
|
||||
struct timespec end;
|
||||
struct timespec diff;
|
||||
|
||||
/* Get and print the elapsed time */
|
||||
|
||||
ret = clock_gettime(TIME_CLOCK, &end);
|
||||
if (ret < 0)
|
||||
{
|
||||
nsh_error(vtbl, g_fmtcmdfailed,
|
||||
argv[0], "clock_gettime", NSH_ERRNO);
|
||||
ret = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
diff.tv_sec = end.tv_sec - start.tv_sec;
|
||||
if (start.tv_nsec > end.tv_nsec)
|
||||
{
|
||||
diff.tv_sec--;
|
||||
end.tv_nsec += 1000000000;
|
||||
}
|
||||
|
||||
diff.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||
nsh_output(vtbl, "\n%lu.%04lu sec\n", (unsigned long)diff.tv_sec,
|
||||
(unsigned long)diff.tv_nsec / 100000);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore state */
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLEBG
|
||||
vtbl->np.np_bg = bgsave;
|
||||
#endif
|
||||
#ifdef CONFIG_FILE_STREAM
|
||||
vtbl->np.np_redirect = redirsave;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_date
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DATE
|
||||
int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
FAR char *newtime = NULL;
|
||||
FAR const char *errfmt;
|
||||
int option;
|
||||
int ret;
|
||||
|
||||
/* Get the date options: date [-s time] [+FORMAT] */
|
||||
|
||||
while ((option = getopt(argc, argv, "s:")) != ERROR)
|
||||
{
|
||||
if (option == 's')
|
||||
{
|
||||
/* We will be setting the time */
|
||||
|
||||
newtime = optarg;
|
||||
}
|
||||
else /* option = '?' */
|
||||
{
|
||||
errfmt = g_fmtarginvalid;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* optind < argc-1 means that there are additional, unexpected arguments on
|
||||
* th command-line
|
||||
*/
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
errfmt = g_fmttoomanyargs;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Display or set the time */
|
||||
|
||||
if (newtime)
|
||||
{
|
||||
ret = date_settime(vtbl, argv[0], newtime);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = date_showtime(vtbl, argv[0]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
errout:
|
||||
nsh_error(vtbl, errfmt, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,344 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_usbconsole.c
|
||||
*
|
||||
* Copyright (C) 2012-2014, 2016 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 <sys/boardctl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#ifdef CONFIG_CDCACM
|
||||
# include <nuttx/usb/cdcacm.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PL2303
|
||||
# include <nuttx/usb/pl2303.h>
|
||||
#endif
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#include "netutils/netinit.h"
|
||||
|
||||
#ifdef HAVE_USB_CONSOLE
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_configstdio
|
||||
*
|
||||
* Description:
|
||||
* Configure standard I/O
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void nsh_configstdio(int fd)
|
||||
{
|
||||
/* Make sure the stdout, and stderr are flushed */
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
/* Dup the fd to create standard fd 0-2 */
|
||||
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_nullstdio
|
||||
*
|
||||
* Description:
|
||||
* Use /dev/null for standard I/O
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_nullstdio(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/* Open /dev/null for read/write access */
|
||||
|
||||
fd = open("/dev/null", O_RDWR);
|
||||
if (fd >= 0)
|
||||
{
|
||||
/* Configure standard I/O to use /dev/null */
|
||||
|
||||
nsh_configstdio(fd);
|
||||
|
||||
/* We can close the original file descriptor now (unless it was one of
|
||||
* 0-2)
|
||||
*/
|
||||
|
||||
if (fd > 2)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_waitusbready
|
||||
*
|
||||
* Description:
|
||||
* Wait for the USB console device to be ready
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_waitusbready(FAR struct console_stdio_s *pstate)
|
||||
{
|
||||
char inch;
|
||||
ssize_t nbytes;
|
||||
int nlc;
|
||||
int fd;
|
||||
|
||||
/* Don't start the NSH console until the console device is ready. Chances
|
||||
* are, we get here with no functional console. The USB console will not
|
||||
* be available until the device is connected to the host and until the
|
||||
* host-side application opens the connection.
|
||||
*/
|
||||
|
||||
restart:
|
||||
|
||||
/* Open the USB serial device for read/write access */
|
||||
|
||||
do
|
||||
{
|
||||
/* Try to open the console */
|
||||
|
||||
fd = open(CONFIG_NSH_USBCONDEV, O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
/* ENOTCONN means that the USB device is not yet connected.
|
||||
* Anything else is bad.
|
||||
*/
|
||||
|
||||
DEBUGASSERT(errno == ENOTCONN);
|
||||
|
||||
/* Sleep a bit and try again */
|
||||
|
||||
sleep(2);
|
||||
}
|
||||
}
|
||||
while (fd < 0);
|
||||
|
||||
/* Now wait until we successfully read a carriage return a few times.
|
||||
* That is a sure way of know that there is something at the other end of
|
||||
* the USB serial connection that is ready to talk with us. The user needs
|
||||
* to hit ENTER a few times to get things started.
|
||||
*/
|
||||
|
||||
nlc = 0;
|
||||
do
|
||||
{
|
||||
/* Read one byte */
|
||||
|
||||
inch = 0;
|
||||
nbytes = read(fd, &inch, 1);
|
||||
|
||||
/* Is it a carriage return (or maybe a newline)? */
|
||||
|
||||
if (nbytes == 1 && (inch == '\n' || inch == '\r'))
|
||||
{
|
||||
/* Yes.. increment the count */
|
||||
|
||||
nlc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No.. Reset the count. We need to see 3 in a row to continue. */
|
||||
|
||||
nlc = 0;
|
||||
|
||||
/* If a read error occurred (nbytes < 0) or an end-of-file was
|
||||
* encountered (nbytes == 0), then close the driver and start
|
||||
* over.
|
||||
*/
|
||||
|
||||
if (nbytes <= 0)
|
||||
{
|
||||
close(fd);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (nlc < 3);
|
||||
|
||||
/* Configure standard I/O */
|
||||
|
||||
nsh_configstdio(fd);
|
||||
|
||||
/* We can close the original file descriptor (unless it was one of 0-2) */
|
||||
|
||||
if (fd > 2)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_consolemain (USB console version)
|
||||
*
|
||||
* Description:
|
||||
* This interfaces maybe to called or started with task_start to start a
|
||||
* single an NSH instance that operates on stdin and stdout. This
|
||||
* function does not return.
|
||||
*
|
||||
* This function handles generic /dev/console character devices, or
|
||||
* special USB console devices. The USB console requires some special
|
||||
* operations to handle the cases where the session is lost when the
|
||||
* USB device is unplugged and restarted when the USB device is plugged
|
||||
* in again.
|
||||
*
|
||||
* Input Parameters:
|
||||
* Standard task start-up arguments. These are not used. argc may be
|
||||
* zero and argv may be NULL.
|
||||
*
|
||||
* Returned Values:
|
||||
* This function does not return nor does it ever exit (unless the user
|
||||
* executes the NSH exit command).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_consolemain(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = nsh_newconsole();
|
||||
struct boardioc_usbdev_ctrl_s ctrl;
|
||||
FAR void *handle;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(pstate);
|
||||
|
||||
/* Initialize any USB tracing options that were requested */
|
||||
|
||||
#ifdef CONFIG_NSH_USBDEV_TRACE
|
||||
usbtrace_enable(TRACE_BITSET);
|
||||
#endif
|
||||
|
||||
/* Initialize the USB serial driver */
|
||||
|
||||
#if defined(CONFIG_PL2303) || defined(CONFIG_CDCACM)
|
||||
#ifdef CONFIG_CDCACM
|
||||
|
||||
ctrl.usbdev = BOARDIOC_USBDEV_CDCACM;
|
||||
ctrl.action = BOARDIOC_USBDEV_CONNECT;
|
||||
ctrl.instance = CONFIG_NSH_USBDEV_MINOR;
|
||||
ctrl.handle = &handle;
|
||||
|
||||
#else
|
||||
|
||||
ctrl.usbdev = BOARDIOC_USBDEV_PL2303;
|
||||
ctrl.action = BOARDIOC_USBDEV_CONNECT;
|
||||
ctrl.instance = CONFIG_NSH_USBDEV_MINOR;
|
||||
ctrl.handle = &handle;
|
||||
|
||||
#endif
|
||||
|
||||
ret = boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
|
||||
UNUSED(ret); /* Eliminate warning if not used */
|
||||
DEBUGASSERT(ret == OK);
|
||||
#endif
|
||||
|
||||
/* Configure to use /dev/null if we do not have a valid console. */
|
||||
|
||||
#ifndef CONFIG_DEV_CONSOLE
|
||||
nsh_nullstdio();
|
||||
#endif
|
||||
|
||||
/* Execute the one-time start-up script (output may go to /dev/null) */
|
||||
|
||||
#ifdef CONFIG_NSH_ROMFSETC
|
||||
nsh_initscript(&pstate->cn_vtbl);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NSH_NETINIT
|
||||
/* Bring up the network */
|
||||
|
||||
netinit_bringup();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_ARCHINIT) && defined(CONFIG_BOARDCTL_FINALINIT)
|
||||
/* Perform architecture-specific final-initialization (if configured) */
|
||||
|
||||
boardctl(BOARDIOC_FINALINIT, 0);
|
||||
#endif
|
||||
|
||||
/* Now loop, executing creating a session for each USB connection */
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Wait for the USB to be connected to the host and switch
|
||||
* standard I/O to the USB serial device.
|
||||
*/
|
||||
|
||||
ret = nsh_waitusbready(pstate);
|
||||
UNUSED(ret); /* Eliminate warning if not used */
|
||||
DEBUGASSERT(ret == OK);
|
||||
|
||||
/* Execute the session */
|
||||
|
||||
nsh_session(pstate, true, argc, argv);
|
||||
|
||||
/* Switch to /dev/null because we probably no longer have a
|
||||
* valid console device.
|
||||
*/
|
||||
|
||||
nsh_nullstdio();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_USB_CONSOLE */
|
||||
@@ -0,0 +1,135 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_usbtrace.c
|
||||
*
|
||||
* Copyright (C) 2014 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 <stdio.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#ifdef CONFIG_NSH_USBDEV_TRACE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_tracecallback
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_tracecallback
|
||||
*
|
||||
* Description:
|
||||
* This is part of the USB trace logic
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int usbtrace_syslog(FAR const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
/* Let vsyslog do the real work */
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsyslog(LOG_INFO, fmt, ap);
|
||||
va_end(ap);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_tracecallback
|
||||
*
|
||||
* Description:
|
||||
* This is part of the USB trace logic
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int nsh_tracecallback(struct usbtrace_s *trace, void *arg)
|
||||
{
|
||||
usbtrace_trprintf(usbtrace_syslog, trace->event, trace->value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_usbtrace
|
||||
*
|
||||
* Description:
|
||||
* The function is called from the nsh_session() to dump USB data to the
|
||||
* SYSLOG device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Values:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void nsh_usbtrace(void)
|
||||
{
|
||||
usbtrace_enumerate(nsh_tracecallback, NULL);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NSH_USBDEV_TRACE */
|
||||
@@ -0,0 +1,421 @@
|
||||
/****************************************************************************
|
||||
* apps/nshlib/nsh_vars.c
|
||||
*
|
||||
* Copyright (C) 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_VARS
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_cmpname
|
||||
****************************************************************************/
|
||||
|
||||
static bool nsh_cmpname(const char *pszname, const char *peqname)
|
||||
{
|
||||
/* Search until we find anything different in the two names */
|
||||
|
||||
for (; *pszname == *peqname; pszname++, peqname++)
|
||||
{
|
||||
}
|
||||
|
||||
/* On success, pszname will end with '\0' and peqname with '=' */
|
||||
|
||||
if (*pszname == '\0' && *peqname == '=')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_findvar
|
||||
*
|
||||
* Description:
|
||||
* Search the provided NSH console structure for the variable of the
|
||||
* specified name.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pstate - The console state containing NSH variable array to be searched.
|
||||
* name - The variable name to find
|
||||
*
|
||||
* Returned Value:
|
||||
* A pointer to the name=value string in the NSH variable buffer
|
||||
*
|
||||
* Assumptions:
|
||||
* - Not called from an interrupt handler
|
||||
* - Pre-emption is disabled by caller
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *nsh_findvar(FAR struct console_stdio_s *pstate,
|
||||
FAR const char *name)
|
||||
{
|
||||
FAR char *ptr;
|
||||
FAR char *end;
|
||||
|
||||
/* Verify input parameters */
|
||||
|
||||
DEBUGASSERT(pstate != NULL && name != NULL);
|
||||
|
||||
/* Search for a name=value string with matching name */
|
||||
|
||||
end = &pstate->varp[pstate->varsz];
|
||||
for (ptr = pstate->varp;
|
||||
ptr < end && !nsh_cmpname(name, ptr);
|
||||
ptr += (strlen(ptr) + 1));
|
||||
|
||||
/* Check for success */
|
||||
|
||||
return (ptr < end) ? ptr : NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_removevar
|
||||
*
|
||||
* Description:
|
||||
* Remove the referenced name=value pair from the NSH variable buffer
|
||||
*
|
||||
* Input Parameters:
|
||||
* pstate - The task pstate with the NSH variable buffer containing the
|
||||
* name=value pair
|
||||
* pair - A pointer to the name=value pair in the restroom
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int nsh_removevar(FAR struct console_stdio_s *pstate, FAR char *pair)
|
||||
{
|
||||
FAR char *end; /* Pointer to the end+1 of the NSH variable buffer */
|
||||
int alloc; /* Size of the allocated NSH variable buffer */
|
||||
int ret = ERROR;
|
||||
|
||||
/* Verify that the pointer lies within the NSH variable region */
|
||||
|
||||
alloc = pstate->varsz; /* Size of the allocated NSH variable buffer */
|
||||
end = &pstate->varp[alloc]; /* Pointer to the end+1 of the NSH variable buffer */
|
||||
|
||||
if (pair >= pstate->varp && pair < end)
|
||||
{
|
||||
/* Set up for the removal */
|
||||
|
||||
int len = strlen(pair) + 1; /* Length of name=value string to remove */
|
||||
FAR char *src = &pair[len]; /* Address of name=value string after */
|
||||
FAR char *dest = pair; /* Location to move the next string */
|
||||
int count = end - src; /* Number of bytes to move (might be zero) */
|
||||
|
||||
/* Move all of the NSH variable strings after the removed one 'down.'
|
||||
* this is inefficient, but probably not high duty.
|
||||
*/
|
||||
|
||||
while (count-- > 0)
|
||||
{
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
/* Then set to the new allocation size. The caller is expected to
|
||||
* call realloc at some point but we don't do that here because the
|
||||
* caller may add more stuff to the NSH variable buffer.
|
||||
*/
|
||||
|
||||
pstate->varsz -= len;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_getvar, nsh_setvar, and nsh_setvar
|
||||
*
|
||||
* Description:
|
||||
* Get, set, or unset an NSH variable.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtbl - NSH session data
|
||||
* name - The name of the variable to get or set
|
||||
* value - The value to use with nsh_setvar()
|
||||
*
|
||||
* Returned value:
|
||||
* nsh_getvar() returns a read-only reference to the variable value on
|
||||
* success or NULL on failure.
|
||||
* nset_unsetvar() returns OK on success or an negated errno value on
|
||||
* failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_getvar
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *nsh_getvar(FAR struct nsh_vtbl_s *vtbl, FAR const char *name)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
FAR char *pair;
|
||||
FAR char *value = NULL;
|
||||
|
||||
DEBUGASSERT(pstate != NULL && name != NULL);
|
||||
|
||||
/* Check if the variable exists */
|
||||
|
||||
if ((pair = nsh_findvar(pstate, name)) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* It does! Get the value sub-string from the name=value string */
|
||||
|
||||
value = strchr(pair, '=');
|
||||
DEBUGASSERT(value != NULL);
|
||||
|
||||
/* Adjust the pointer so that it points to the value right after the '=' */
|
||||
|
||||
value++;
|
||||
return value;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_setvar
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_SET
|
||||
int nsh_setvar(FAR struct nsh_vtbl_s *vtbl, FAR const char *name,
|
||||
FAR const char *value)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
FAR char *pair;
|
||||
FAR char *newvarp;
|
||||
int newsize;
|
||||
int varlen;
|
||||
|
||||
DEBUGASSERT(pstate != NULL && name != NULL && value != NULL);
|
||||
|
||||
/* Check if the variable already exists */
|
||||
|
||||
if (pstate->varp != NULL &&
|
||||
(pair = nsh_findvar(pstate, name)) != NULL)
|
||||
{
|
||||
/* Yes.. Remove the name=value pair from the NSH variable buffer. It
|
||||
* will be added again below.
|
||||
*/
|
||||
|
||||
nsh_removevar(pstate, pair);
|
||||
}
|
||||
|
||||
/* Get the size of the new name=value string. The +2 is for the '=' and
|
||||
* for null terminator
|
||||
*/
|
||||
|
||||
varlen = strlen(name) + strlen(value) + 2;
|
||||
|
||||
/* Then allocate or reallocate the NSH variable buffer */
|
||||
|
||||
if (pstate->varp != NULL)
|
||||
{
|
||||
newsize = pstate->varsz + varlen;
|
||||
newvarp = (FAR char *)realloc(pstate->varp, newsize);
|
||||
if (newvarp == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pair = &newvarp[pstate->varsz];
|
||||
}
|
||||
else
|
||||
{
|
||||
newsize = varlen;
|
||||
newvarp = (FAR char *)malloc(varlen);
|
||||
if (!newvarp)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pair = newvarp;
|
||||
}
|
||||
|
||||
/* Save the new buffer and size */
|
||||
|
||||
pstate->varp = newvarp;
|
||||
pstate->varsz = newsize;
|
||||
|
||||
/* Now, put the new name=value string into the NSH variable buffer */
|
||||
|
||||
sprintf(pair, "%s=%s", name, value);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_unsetvar
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_NSH_DISABLE_UNSET) || !defined(CONFIG_NSH_DISABLE_EXPORT)
|
||||
int nsh_unsetvar(FAR struct nsh_vtbl_s *vtbl, FAR const char *name)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
FAR char *pair;
|
||||
FAR char *newvarp;
|
||||
int newsize;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(name != NULL && pstate != NULL);
|
||||
|
||||
/* Check if the variable exists */
|
||||
|
||||
if (pstate != NULL && (pair = nsh_findvar(pstate, name)) != NULL)
|
||||
{
|
||||
/* It does! Remove the name=value pair from the NSH variables. */
|
||||
|
||||
nsh_removevar(pstate, pair);
|
||||
|
||||
/* Reallocate the new NSH variable buffer */
|
||||
|
||||
newsize = pstate->varsz;
|
||||
if (newsize <= 0)
|
||||
{
|
||||
/* Free the old NSH variable (if there was one) */
|
||||
|
||||
if (pstate->varp != NULL)
|
||||
{
|
||||
free(pstate->varp);
|
||||
pstate->varp = NULL;
|
||||
}
|
||||
|
||||
pstate->varsz = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reallocate the NSH variable buffer to reclaim a little memory */
|
||||
|
||||
newvarp = (FAR char *)realloc(pstate->varp, newsize);
|
||||
if (newvarp == NULL)
|
||||
{
|
||||
return -ENOMEM; /* Shouldn't happen when realloc'ing down */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Save the new NSH variable pointer (it might have changed due
|
||||
* to reallocation).
|
||||
*/
|
||||
|
||||
pstate->varp = newvarp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sched_unlock();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_foreach_var
|
||||
*
|
||||
* Description:
|
||||
* Visit each name-value pair in the environment.
|
||||
*
|
||||
* Input Parameters:
|
||||
* vtbl - NSH session data
|
||||
* cb - The callback function to be invoked for each environment
|
||||
* variable.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero if the all NSH variables have been traversed. A non-zero value
|
||||
* means that the callback function requested early termination by
|
||||
* returning a nonzero value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_SET
|
||||
int nsh_foreach_var(FAR struct nsh_vtbl_s *vtbl, nsh_foreach_var_t cb,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
|
||||
FAR char *ptr;
|
||||
FAR char *end;
|
||||
int ret = OK;
|
||||
|
||||
/* Verify input parameters */
|
||||
|
||||
DEBUGASSERT(pstate != NULL && cb != NULL);
|
||||
|
||||
/* Search for a name=value string with matching name */
|
||||
|
||||
end = &pstate->varp[pstate->varsz];
|
||||
for (ptr = pstate->varp; ptr < end; ptr += (strlen(ptr) + 1))
|
||||
{
|
||||
/* Perform the callback */
|
||||
|
||||
ret = cb(vtbl, arg, ptr);
|
||||
|
||||
/* Terminate the traversal early if the callback so requests by
|
||||
* returning a non-zero value.
|
||||
*/
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NSH_VARS */
|
||||
@@ -0,0 +1,5 @@
|
||||
# Create a RAMDISK and mount it at XXXRDMOUNTPOINTXXX
|
||||
|
||||
mkrd -m XXXMKRDMINORXXX -s XXMKRDSECTORSIZEXXX XXMKRDBLOCKSXXX
|
||||
mkfatfs /dev/ramXXXMKRDMINORXXX
|
||||
mount -t vfat /dev/ramXXXMKRDMINORXXX XXXRDMOUNTPOINTXXX
|
||||
Reference in New Issue
Block a user