aboutsummaryrefslogtreecommitdiff
path: root/apps/nshlib
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-09-17 18:18:44 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-09-17 18:18:44 +0000
commit57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff (patch)
tree25d07d14e920d31c0b1947c9ca586f2a01fc32d8 /apps/nshlib
downloadpx4-firmware-57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff.tar.gz
px4-firmware-57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff.tar.bz2
px4-firmware-57623d42ebb04f0a0b9e6eb7c0847a3ece2aa0ff.zip
Resync new repository with old repo r5166
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5153 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/nshlib')
-rw-r--r--apps/nshlib/Kconfig494
-rw-r--r--apps/nshlib/Make.defs40
-rw-r--r--apps/nshlib/Makefile131
-rw-r--r--apps/nshlib/README.txt1170
-rw-r--r--apps/nshlib/nsh.h611
-rw-r--r--apps/nshlib/nsh_apps.c187
-rw-r--r--apps/nshlib/nsh_console.c432
-rw-r--r--apps/nshlib/nsh_console.h159
-rw-r--r--apps/nshlib/nsh_consolemain.c170
-rw-r--r--apps/nshlib/nsh_dbgcmds.c355
-rw-r--r--apps/nshlib/nsh_ddcmd.c643
-rw-r--r--apps/nshlib/nsh_envcmds.c338
-rw-r--r--apps/nshlib/nsh_fscmds.c1299
-rw-r--r--apps/nshlib/nsh_init.c102
-rw-r--r--apps/nshlib/nsh_mmcmds.c96
-rw-r--r--apps/nshlib/nsh_mntcmds.c434
-rw-r--r--apps/nshlib/nsh_netcmds.c864
-rw-r--r--apps/nshlib/nsh_netinit.c171
-rw-r--r--apps/nshlib/nsh_parse.c1550
-rw-r--r--apps/nshlib/nsh_proccmds.c310
-rw-r--r--apps/nshlib/nsh_romfsetc.c124
-rw-r--r--apps/nshlib/nsh_romfsimg.h89
-rw-r--r--apps/nshlib/nsh_telnetd.c187
-rw-r--r--apps/nshlib/nsh_test.c438
-rw-r--r--apps/nshlib/nsh_timcmds.c331
-rw-r--r--apps/nshlib/nsh_usbdev.c243
-rw-r--r--apps/nshlib/rcS.template5
27 files changed, 10973 insertions, 0 deletions
diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig
new file mode 100644
index 000000000..c0f7d6a92
--- /dev/null
+++ b/apps/nshlib/Kconfig
@@ -0,0 +1,494 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config NSH_LIBRARY
+ bool "NSH Library"
+ default n
+ select SYSTEM_READLINE
+ ---help---
+ Build the NSH support library. This is used, for example, by examples/nsh
+ in order to implement the full NuttShell (NSH).
+
+if NSH_LIBRARY
+config NSH_BUILTIN_APPS
+ bool "Enable built-in applications"
+ default y
+ depends on NAMEDAPP
+ ---help---
+ Support external registered, "named" applications that can be
+ executed from the NSH command line (see apps/README.txt for
+ more information). This options requires support for named applications
+ (NAMEDAPP).
+
+menu "Disable Individual commands"
+config NSH_DISABLE_CAT
+ bool "Disable cat"
+ default n
+config NSH_DISABLE_CD
+ bool "Disable cd"
+ default n
+config NSH_DISABLE_CP
+ bool "Disable cp"
+ default n
+config NSH_DISABLE_DD
+ bool "Disable dd"
+ default n
+config NSH_DISABLE_ECHO
+ bool "Disable echo"
+ default n
+config NSH_DISABLE_EXEC
+ bool "Disable exec"
+ default n
+config NSH_DISABLE_EXIT
+ bool "Disable exit"
+ default n
+config NSH_DISABLE_FREE
+ bool "Disable free"
+ default n
+config NSH_DISABLE_GET
+ bool "Disable get"
+ default n
+config NSH_DISABLE_HELP
+ bool "Disable help"
+ default n
+config NSH_DISABLE_IFCONFIG
+ bool "Disable ifconfig"
+ default n
+config NSH_DISABLE_KILL
+ bool "Disable kill"
+ default n
+config NSH_DISABLE_LOSETUP
+ bool "Disable losetup"
+ default n
+config NSH_DISABLE_LS
+ bool "Disable ls"
+ default n
+config NSH_DISABLE_MB
+ bool "Disable mb"
+ default n
+config NSH_DISABLE_MKDIR
+ bool "Disable mkdir"
+ default n
+config NSH_DISABLE_MKFATFS
+ bool "Disable mkfatfs"
+ default n
+config NSH_DISABLE_MKFIFO
+ bool "Disable mkfifo"
+ default n
+config NSH_DISABLE_MKRD
+ bool "Disable mkrd"
+ default n
+config NSH_DISABLE_MH
+ bool "Disable mh"
+ default n
+config NSH_DISABLE_MOUNT
+ bool "Disable mount"
+ default n
+config NSH_DISABLE_MW
+ bool "Disable mw"
+ default n
+config NSH_DISABLE_NSFMOUNT
+ bool "Disable nfsmount"
+ default n
+config NSH_DISABLE_PS
+ bool "Disable ps"
+ default n
+config NSH_DISABLE_PING
+ bool "Disable ping"
+ default n
+config NSH_DISABLE_PUT
+ bool "Disable put"
+ default n
+config NSH_DISABLE_PWD
+ bool "Disable pwd"
+ default n
+config NSH_DISABLE_RM
+ bool "Disable rm"
+ default n
+config NSH_DISABLE_RMDIR
+ bool "Disable rmdir"
+ default n
+config NSH_DISABLE_SET
+ bool "Disable set"
+ default n
+config NSH_DISABLE_SH
+ bool "Disable sh"
+ default n
+config NSH_DISABLE_SLEEP
+ bool "Disable sleep"
+ default n
+config NSH_DISABLE_TEST
+ bool "Disable test"
+ default n
+config NSH_DISABLE_UMOUNT
+ bool "Disable umount"
+ default n
+config NSH_DISABLE_UNSET
+ bool "Disable unset"
+ default n
+config NSH_DISABLE_USLEEP
+ bool "Disable usleep"
+ default n
+config NSH_DISABLE_WGET
+ bool "Disable wget"
+ default n
+config NSH_DISABLE_XD
+ bool "Disable xd"
+ default n
+endmenu
+
+config NSH_FILEIOSIZE
+ int "NSH I/O buffer size"
+ default 1024
+ ---help---
+ Size of a static I/O buffer used for file access (ignored if
+ there is no filesystem). Default is 1024.
+
+config NSH_STRERROR
+ bool "Use strerror()"
+ default n
+ depends on LIBC_STRERROR
+ ---help---
+ strerror(errno) makes more readable output but strerror() is
+ very large and will not be used unless this setting is 'y'
+ This setting depends upon the strerror() having been enabled
+ with LIBC_STRERROR.
+
+config NSH_LINELEN
+ int "Max command line length"
+ default 80
+ ---help---
+ The maximum length of one command line and of one output line.
+ Default: 80
+
+config NSH_NESTDEPTH
+ int "Maximum command nesting"
+ default 3
+ ---help---
+ The maximum number of nested if-then[-else]-fi sequences that
+ are permissable. Default: 3
+
+config NSH_DISABLESCRIPT
+ bool "Disable script support"
+ default n
+ ---help---
+ This can be set to 'y' to suppress support for scripting. This
+ setting disables the 'sh', 'test', and '[' commands and the
+ if-then[-else]-fi construct. This would only be set on systems
+ where a minimal footprint is a necessity and scripting is not.
+
+config NSH_DISABLEBG
+ bool "Disable background commands"
+ default n
+ ---help---
+ This can be set to 'y' to suppress support for background
+ commands. This setting disables the 'nice' command prefix and
+ the '&' command suffix. This would only be set on systems
+ where a minimal footprint is a necessity and background command
+ execution is not.
+
+config NSH_MMCSDMINOR
+ int "MMC/SD minor device number"
+ default 0
+ ---help---
+ If the architecture supports an MMC/SD slot and if the NSH
+ architecture specific logic is present, this option will provide
+ the MMC/SD minor number, i.e., the MMC/SD block driver will
+ be registered as /dev/mmcsdN where N is the minor number.
+ Default is zero.
+
+config NSH_ROMFSETC
+ bool "Support ROMFS start-up script"
+ default n
+ depends on FS_ROMFS
+ ---help---
+ Mount a ROMFS filesystem at /etc and provide a startup script
+ at /etc/init.d/rcS. The default startup script will mount
+ a FAT FS RAMDISK at /tmp but the logic is easily extensible.
+
+endif
+
+if NSH_ROMFSETC
+config NSH_ROMFSMOUNTPT
+ string "ROMFS mount point"
+ default "/etc"
+ ---help---
+ The default mountpoint for the ROMFS volume is /etc, but that
+ can be changed with this setting. This must be a absolute path
+ beginning with '/'.
+
+config NSH_INITSCRIPT
+ string "Relative path to startup script"
+ default "init.d/rcS"
+ ---help---
+ This is the relative path to the startup script within the mountpoint.
+ The default is init.d/rcS. This is a relative path and must not
+ start with '/'.
+
+config NSH_ROMFSDEVNO
+ int "ROMFS block device minor number"
+ default 0
+ ---help---
+ This is the minor number of the ROMFS block device. The default is
+ '0' corresponding to /dev/ram0.
+
+config NSH_ROMFSSECTSIZE
+ int "ROMFS sector size"
+ default 64
+ ---help---
+ This is the sector size to use with the ROMFS volume. Since the
+ default volume is very small, this defaults to 64 but should be
+ increased if the ROMFS volume were to be become large. Any value
+ selected must be a power of 2.
+
+config NSH_FATDEVNO
+ int "FAT block device minor number"
+ default 0
+ depends on FS_FAT
+ ---help---
+ When the default rcS file used when NSH_ROMFSETC is selected, it
+ will mount a FAT FS under /tmp. This is the minor number of the FAT
+ FS block device. The default is '1' corresponding to /dev/ram1.
+
+config NSH_FATSECTSIZE
+ int "FAT sector size"
+ default 512
+ depends on FS_FAT
+ ---help---
+ When the default rcS file used when NSH_ROMFSETC is selected, it
+ will mount a FAT FS under /tmp. This is the sector size use with the
+ FAT FS. Default is 512.
+
+config NSH_FATNSECTORS
+ int "FAT number of sectors"
+ default 1024
+ depends on FS_FAT
+ ---help---
+ When the default rcS file used when NSH_ROMFSETC is selected, it
+ will mount a FAT FS under /tmp. This is the number of sectors to use
+ with the FAT FS. Defualt is 1024. The amount of memory used by the
+ FAT FS will be NSH_FATSECTSIZE * NSH_FATNSECTORS bytes.
+
+config NSH_FATMOUNTPT
+ string "FAT mount point"
+ default "/tmp"
+ depends on FS_FAT
+ ---help---
+ When the default rcS file used when NSH_ROMFSETC is selected, it
+ will mount a FAT FS under /tmp. This is the location where the FAT
+ FS will be mounted. Default is "/tmp".
+
+endif
+
+if NSH_LIBRARY
+config NSH_CONSOLE
+ bool "Use console"
+ default y
+ ---help---
+ If NSH_CONSOLE is set to 'y', then a character driver
+ console front-end is selected (/dev/console).
+
+ Normally, the serial console device is a UART and RS-232
+ interface. However, if CONFIG_USBDEV is defined, then a USB
+ serial device may, instead, be used if the one of
+ the following are defined:
+
+ CONFIG_PL2303 and CONFIG_PL2303_CONSOLE - Sets up the
+ Prolifics PL2303 emulation as a console device at /dev/console.
+
+ CONFIG_CDCACM and CONFIG_CDCACM_CONSOLE - Sets up the
+ CDC/ACM serial device as a console device at dev/console.
+
+ CONFIG_NSH_USBCONSOLE and CONFIG_NSH_USBCONDEV - Sets up the
+ some other USB serial device as the NSH console (not necessarily
+ dev/console).
+
+config NSH_USBCONSOLE
+ bool "Use a USB console"
+ default n
+ depends on NSH_CONSOLE && USBDEV
+ ---help---
+ If defined, then the an arbitrary USB device may be used
+ to as the NSH console. In this case, CONFIG_NSH_USBCONDEV
+ must be defined to indicate which USB device to use as
+ the console.
+
+config NSH_USBCONDEV
+ string "USB console device"
+ default "/dev/ttyACM0"
+ depends on NSH_USBCONSOLE
+ ---help---
+ If CONFIG_NSH_USBCONSOLE is set to 'y', then CONFIG_NSH_USBCONDEV
+ must also be set to select the USB device used to support
+ the NSH console. This should be set to the quoted name of a
+ readable/write-able USB driver such as:
+ CONFIG_NSH_USBCONDEV="/dev/ttyACM0".
+
+config UBSDEV_MINOR
+ int "USB console device minor number"
+ default 0
+ depends on NSH_USBCONSOLE
+ ---help---
+ If there are more than one USB devices, then a USB device
+ minor number may also need to be provided. Default: 0
+
+menu "USB Trace Support"
+ depends on USBDEV && (DEBUG || USBDEV_TRACE)
+
+config NSH_USBDEV_TRACEINIT
+ bool "Show initialization events"
+ default n
+ ---help---
+ Show initialization events
+
+config NSH_USBDEV_TRACECLASS
+ bool "Show class driver events"
+ default n
+ ---help---
+ Show class driver events
+
+config NSH_USBDEV_TRACETRANSFERS
+ bool "Show data transfer events"
+ default n
+ ---help---
+ Show data transfer events
+
+config NSH_USBDEV_TRACECONTROLLER
+ bool "Show controller events"
+ default n
+ ---help---
+ Show controller events
+
+config NSH_USBDEV_TRACEINTERRUPTS
+ bool "Show interrupt-related events"
+ default n
+ ---help---
+ Show interrupt-related events
+
+endmenu
+
+config NSH_CONDEV
+ bool "Default console device"
+ default "/dev/console"
+ depends on NSH_CONSOLE && !NSH_USBCONSOLE
+ ---help---
+ If NSH_CONSOLE is set to 'y', then NSH_CONDEV
+ may also be set to select the serial device used to support
+ the NSH console. This should be set to the quoted name of a
+ readable/write-able character driver such as:
+ NSH_CONDEV="/dev/ttyS1". This is useful, for example,
+ to separate the NSH command line from the system console when
+ the system console is used to provide debug output. Default:
+ stdin and stdout (probably "/dev/console")
+
+ NOTE: When any other device other than /dev/console is used
+ for a user interface, (1) linefeeds (\n) will not be expanded to
+ carriage return / linefeeds (\r\n). You will need to set
+ your terminal program to account for this. And (2) input is
+ not automatically echoed so you will have to turn local echo on.
+
+config NSH_ARCHINIT
+ bool "Have architecture-specific initialization"
+ default n
+ ---help---
+ Set if your board provides architecture specific initialization
+ via the board-specific function nsh_archinitialize(). This
+ function will be called early in NSH initialization to allow
+ board logic to do such things as configure MMC/SD slots.
+
+config NSH_TELNET
+ bool "Use Telnet console"
+ default n
+ depends on NET && NET_TCP
+ ---help---
+ If NSH_TELNET is set to 'y', then a TELENET
+ server front-end is selected. When this option is provided,
+ you may log into NuttX remotely using telnet in order to
+ access NSH.
+
+endif
+
+if NSH_TELNET
+config NSH_TELNETD_PORT
+ int "Telnet port number"
+ default 23
+ ---help---
+ The telnet daemon will listen on this TCP port number for connections.
+ Default: 23
+
+config NSH_TELNETD_DAEMONPRIO
+ int "Telnet daemon priority"
+ default 100
+ ---help---
+ Priority of the Telnet daemon. Default: 100
+
+config NSH_TELNETD_DAEMONSTACKSIZE
+ int "Telnet daemon stack size"
+ default 2048
+ ---help---
+ Stack size allocated for the Telnet daemon. Default: 2048
+
+config NSH_TELNETD_CLIENTPRIO
+ int "Telnet client priority"
+ default 100
+ ---help---
+ Priority of the Telnet client. Default: 100
+
+config NSH_TELNETD_CLIENTSTACKSIZE
+ int "Telnet client stack size"
+ default 2048
+ ---help---
+ Stack size allocated for the Telnet client. Default: 2048
+
+config NSH_IOBUFFER_SIZE
+ int "Telnet I/O buffer size"
+ default 512
+ ---help---
+ Determines the size of the I/O buffer to use for sending/
+ receiving TELNET commands/reponses. Default: 512
+endif
+
+config NSH_DHCPC
+ bool "Use DHCP to get IP address"
+ default n
+ depends on NSH_LIBRARY && NET && NET_UDP && NET_BROADCAST
+ ---help---
+ Obtain the IP address via DHCP.
+
+ Per RFC2131 (p. 9), the DHCP client must be prepared to receive DHCP
+ messages of up to 576 bytes (excluding Ethernet, IP, or UDP headers and FCS).
+
+config NSH_IPADDR
+ hex "Target IP address"
+ default 0x10000002
+ depends on NSH_LIBRARY && NET && !NSH_DHCPC
+ ---help---
+ If NSH_DHCPC is NOT set, then the static IP address must be provided.
+ This is a 32-bit integer value in host order. So, as an example,
+ 0x10000002 would be 10.0.0.2.
+
+config NSH_DRIPADDR
+ hex "Router IP address"
+ default 0x10000001
+ depends on NSH_LIBRARY && NET && !NSH_DHCPC
+ ---help---
+ Default router IP address (aka, Gateway). This is a 32-bit integer
+ value in host order. So, as an example, 0x10000001 would be 10.0.0.1.
+
+config NSH_NETMASK
+ hex "Network mask"
+ default 0xffffff00
+ depends on NSH_LIBRARY && NET && !NSH_DHCPC
+ ---help---
+ Network mask. This is a 32-bit integer value in host order. So, as
+ an example, 0xffffff00 would be 255.255.255.0.
+
+config NSH_NOMAC
+ bool "Hardware has no MAC address"
+ default n
+ depends on NSH_LIBRARY && NET
+ ---help---
+ Set if your ethernet hardware has no built-in MAC address.
+ If set, a bogus MAC will be assigned.
diff --git a/apps/nshlib/Make.defs b/apps/nshlib/Make.defs
new file mode 100644
index 000000000..2bacb5b79
--- /dev/null
+++ b/apps/nshlib/Make.defs
@@ -0,0 +1,40 @@
+############################################################################
+# 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 += nshlib
+endif
+
diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile
new file mode 100644
index 000000000..f616374bf
--- /dev/null
+++ b/apps/nshlib/Makefile
@@ -0,0 +1,131 @@
+############################################################################
+# apps/nshlib/Makefile
+#
+# Copyright (C) 2011-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.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# NSH Library
+
+ASRCS =
+CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_fscmds.c nsh_ddcmd.c \
+ nsh_proccmds.c nsh_mmcmds.c nsh_envcmds.c nsh_dbgcmds.c
+
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+CSRCS += nsh_apps.c
+endif
+
+ifeq ($(CONFIG_NSH_ROMFSETC),y)
+CSRCS += nsh_romfsetc.c
+endif
+
+ifeq ($(CONFIG_NET),y)
+CSRCS += nsh_netinit.c nsh_netcmds.c
+endif
+
+ifeq ($(CONFIG_RTC),y)
+CSRCS += nsh_timcmds.c
+endif
+
+ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
+CSRCS += nsh_mntcmds.c
+endif
+
+ifeq ($(CONFIG_NSH_CONSOLE),y)
+CSRCS += nsh_consolemain.c
+endif
+
+ifeq ($(CONFIG_NSH_TELNET),y)
+CSRCS += nsh_telnetd.c
+endif
+
+ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
+CSRCS += nsh_test.c
+endif
+
+ifeq ($(CONFIG_USBDEV),y)
+CSRCS += nsh_usbdev.c
+endif
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(WINTOOL),y)
+ BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
+else
+ BIN = "$(APPDIR)/libapps$(LIBEXT)"
+endif
+
+ROOTDEPPATH = --dep-path .
+VPATH =
+
+# Build targets
+
+all: .built
+.PHONY: context .depend depend clean distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $(BIN), $${obj}); \
+ done ; )
+ @touch .built
+
+context:
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) \
+ $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ @rm -f *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend
+
+-include Make.dep
+
diff --git a/apps/nshlib/README.txt b/apps/nshlib/README.txt
new file mode 100644
index 000000000..0f6aee759
--- /dev/null
+++ b/apps/nshlib/README.txt
@@ -0,0 +1,1170 @@
+apps/nshlib
+^^^^^^^^^^^
+
+ This directory contains the NuttShell (NSH) library. This library can be
+ linked with other logic to provide a simple shell application for NuttX.
+
+ - Console/NSH Front End
+ - Command Overview
+ - Conditional Command Execution
+ - Built-In Variables
+ - Current Working Directory
+ Environment Variables
+ - NSH Start-Up Script
+ - Simple Commands
+ - NSH Configuration Settings
+ Command Dependencies on Configuration Settings
+ NSH-Specific Configuration Settings
+ - Common Problems
+
+Console/NSH Front End
+^^^^^^^^^^^^^^^^^^^^^
+
+ Using settings in the configuration file, NSH may be configured to
+ use either the serial stdin/out or a telnet connection as the console
+ or BOTH. When NSH is started, you will see the following welcome on
+ either console:
+
+ NuttShell (NSH)
+ nsh>
+
+ 'nsh>' is the NSH prompt and indicates that you may enter a command
+ from the console.
+
+Command Overview
+^^^^^^^^^^^^^^^^
+
+ This directory contains the NuttShell (NSH). This is a simple
+ shell-like application. At present, NSH supports the following commands
+ forms:
+
+ Simple command: <cmd>
+ Command with re-directed output: <cmd> > <file>
+ <cmd> >> <file>
+ Background command: <cmd> &
+ Re-directed background command: <cmd> > <file> &
+ <cmd> >> <file> &
+
+ Where:
+
+ <cmd> is any one of the simple commands listed later.
+ <file> is the full or relative path to any writable object
+ in the filesystem name space (file or character driver).
+ Such objects will be referred to simply as files throughout
+ this README.
+
+ NSH executes at the mid-priority (128). Backgrounded commands can
+ be made to execute at higher or lower priorities using nice:
+
+ [nice [-d <niceness>>]] <cmd> [> <file>|>> <file>] [&]
+
+ Where <niceness> is any value between -20 and 19 where lower
+ (more negative values) correspond to higher priorities. The
+ default niceness is 10.
+
+Conditional Command Execution
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ An if-then[-else]-fi construct is also supported in order to
+ support conditional execution of commands. This works from the
+ command line but is primarily intended for use within NSH scripts
+ (see the sh commnd). The syntax is as follows:
+
+ if <cmd>
+ then
+ [sequence of <cmd>]
+ else
+ [sequence of <cmd>]
+ fi
+
+Built-In Variables
+^^^^^^^^^^^^^^^^^^
+
+ $? - The result of the last simple command execution
+
+Current Working Directory
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ All path arguments to commands may be either an absolute path or a
+ path relative to the current working directory. The current working
+ directory is set using the 'cd' command and can be queried either
+ by using the 'pwd' command or by using the 'echo $PWD' command.
+
+ Environment Variables:
+ ----------------------
+
+ PWD - The current working directory
+ OLDPWD - The previous working directory
+
+NSH Start-Up Script
+^^^^^^^^^^^^^^^^^^^
+
+NSH supports options to provide a start up script for NSH. In general
+this capability is enabled with CONFIG_NSH_ROMFSETC, but has
+several other related configuration options as described in the final
+section of this README. This capability also depends on:
+
+ - CONFIG_DISABLE_MOUNTPOINT not set
+ - CONFIG_NFILE_DESCRIPTORS > 4
+ - CONFIG_FS_ROMFS
+
+Default Start-Up Behavior
+-------------------------
+
+The implementation that is provided is intended to provide great flexibility
+for the use of Start-Up files. This paragraph will discuss the general
+behavior when all of the configuration options are set to the default
+values.
+
+In this default case, enabling CONFIG_NSH_ROMFSETC will cause
+NSH to behave as follows at NSH startup time:
+
+- NSH will create a read-only RAM disk (a ROM disk), containing a tiny
+ ROMFS filesystem containing the following:
+
+ |--init.d/
+ `-- rcS
+
+ Where rcS is the NSH start-up script
+
+- NSH will then mount the ROMFS filesystem at /etc, resulting in:
+
+ |--dev/
+ | `-- ram0
+ `--etc/
+ `--init.d/
+ `-- rcS
+
+- By default, the contents of rcS script are:
+
+ # Create a RAMDISK and mount it at XXXRDMOUNTPOUNTXXX
+
+ mkrd -m 1 -s 512 1024
+ mkfatfs /dev/ram1
+ mount -t vfat /dev/ram1 /tmp
+
+- NSH will execute the script at /etc/init.d/rcS at start-up (before the
+ first NSH prompt. After execution of the script, the root FS will look
+ like:
+
+ |--dev/
+ | |-- ram0
+ | `-- ram1
+ |--etc/
+ | `--init.d/
+ | `-- rcS
+ `--tmp/
+
+Modifying the ROMFS Image
+-------------------------
+
+The contents of the /etc directory are retained in the file
+apps/nshlib/nsh_romfsimg.h (OR, if CONFIG_NSH_ARCHROMFS
+is defined, include/arch/board/rcs.template). In order to modify
+the start-up behavior, there are three things to study:
+
+1. Configuration Options.
+ The additional CONFIG_NSH_ROMFSETC configuration options
+ discussed in the final section of this README.
+
+2. tools/mkromfsimg.sh Script.
+ The script tools/mkromfsimg.sh creates nsh_romfsimg.h.
+ It is not automatically executed. If you want to change the
+ configuration settings associated with creating and mounting
+ the /tmp directory, then it will be necessary to re-generate
+ this header file using the mkromfsimg.sh script.
+
+ The behavior of this script depends upon three things:
+
+ - The configuration settings of the installed NuttX configuration.
+ - The genromfs tool (available from http://romfs.sourceforge.net).
+ - The file apps/nshlib/rcS.template (OR, if
+ CONFIG_NSH_ARCHROMFS is defined, include/arch/board/rcs.template)
+
+3. rcS.template.
+ The file apps/nshlib/rcS.template contains the general form
+ of the rcS file; configured values are plugged into this
+ template file to produce the final rcS file.
+
+NOTE:
+
+ apps/nshlib/rcS.template generates the standard, default
+ nsh_romfsimg.h file. If CONFIG_NSH_ARCHROMFS is defined
+ in the NuttX configuration file, then a custom, board-specific
+ nsh_romfsimg.h file residing in configs/<board>/include will be
+ used. NOTE when the OS is configured, include/arch/board will
+ be linked to configs/<board>/include.
+
+All of the startup-behavior is contained in rcS.template. The
+role of mkromfsimg.sh is to (1) apply the specific configuration
+settings to rcS.template to create the final rcS, and (2) to
+generate the header file nsh_romfsimg.h containg the ROMFS
+file system image.
+
+Simple Commands
+^^^^^^^^^^^^^^^
+
+o [ <expression> ]
+o test <expression>
+
+ These are two alternative forms of the same command. They support
+ evaluation of a boolean expression which sets $?. This command
+ is used most frequently as the conditional command following the
+ 'if' in the if-then[-else]-fi construct.
+
+ Expression 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
+
+o cat <path> [<path> [<path> ...]]
+
+ This command copies and concatentates all of the files at <path>
+ to the console (or to another file if the output is redirected).
+
+o cd [<dir-path>|-|~|..]
+
+ Changes the current working directory (PWD). Also sets the
+ previous working directory environment variable (OLDPWD).
+
+ FORMS:
+ ------
+
+ 'cd <dir-path>' sets the current working directory to <dir-path>.
+ 'cd -' sets the current working directory to the previous
+ working directory ($OLDPWD). Equivalent to 'cd $OLDPWD'.
+ 'cd' or 'cd ~' set the current working directory to the 'home'
+ directory. The 'home' directory can be configured by setting
+ CONFIG_LIB_HOMEDIR in the configuration file. The default
+ 'home' directory is '/'.
+ 'cd ..' sets the current working directory to the parent directory.
+
+o cp <source-path> <dest-path>
+
+ Copy of the contents of the file at <source-path> to the location
+ in the filesystem indicated by <path-path>
+
+o date [-s "MMM DD HH:MM:SS YYYY"]
+
+ Show or set the current date and time. This command is only supported
+ if the platform supported RTC hardware (CONFIG_RTC=y).
+
+ Only one format is used both on display and when setting the date/time:
+ MMM DD HH:MM:SS YYYY. For example,
+
+ data -s "Sep 1 11:30:00 2011"
+
+ 24-hour time format is assumed.
+
+o dd if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] [skip=<sectors>]
+
+ Copy blocks from <infile> to <outfile>. <nfile> or <outfile> may
+ be the path to a standard file, a character device, or a block device.
+
+ Examples:
+
+ 1. Read from character device, write to regular file. This will
+ create a new file of the specified size filled with zero.
+
+ nsh> dd if=/dev/zero of=/tmp/zeros bs=64 count=16
+ nsh> ls -l /tmp
+ /tmp:
+ -rw-rw-rw- 1024 ZEROS
+
+ 2. Read from character device, write to block device. This will
+ fill the entire block device with zeros.
+
+ nsh> ls -l /dev
+ /dev:
+ brw-rw-rw- 0 ram0
+ crw-rw-rw- 0 zero
+ nsh> dd if=/dev/zero of=/dev/ram0
+
+ 3. Read from a block devic, write to a character device. This
+ will read the entire block device and dump the contents in
+ the bit bucket.
+
+ nsh> ls -l /dev
+ /dev:
+ crw-rw-rw- 0 null
+ brw-rw-rw- 0 ram0
+ nsh> dd if=/dev/ram0 of=/dev/null
+
+o df
+
+ Show the state of each mounted volume.
+
+ Example:
+
+ nsh> mount
+ /etc type romfs
+ /tmp type vfat
+ nsh> df
+ Block Number
+ Size Blocks Used Available Mounted on
+ 64 6 6 0 /etc
+ 512 985 2 983 /tmp
+ nsh>
+
+o echo [<string|$name> [<string|$name>...]]
+
+ Copy the sequence of strings and expanded environment variables to
+ console out (or to a file if the output is re-directed).
+
+o exec <hex-address>
+
+ Execute the user logic at address <hex-address>. NSH will pause
+ until the execution unless the user logic is executed in background
+ via 'exec <hex-address> &'
+
+o exit
+
+ Exit NSH. Only useful if you have started some other tasks (perhaps
+ using the 'exec' command') and you would like to have NSH out of the
+ way.
+
+o free
+
+ Show the current state of the memory allocator. For example,
+
+ nsh> free
+ free
+ total used free largest
+ Mem: 4194288 1591552 2602736 2601584
+
+ Where:
+ total - This is the total size of memory allocated for use
+ by malloc in bytes.
+ used - This is the total size of memory occupied by
+ chunks handed out by malloc.
+ free - This is the total size of memory occupied by
+ free (not in use) chunks.
+ largest - Size of the largest free (not in use) chunk
+
+o get [-b|-n] [-f <local-path>] -h <ip-address> <remote-path>
+
+ Use TFTP to copy the file at <remote-address> from the host whose IP
+ address is identified by <ip-address>. Other options:
+
+ -f <local-path>
+ The file will be saved relative to the current working directory
+ unless <local-path> is provided.
+ -b|-n
+ Selects either binary ("octect") or test ("netascii") transfer
+ mode. Default: text.
+
+o help [-v] [<cmd>]
+
+ Presents summary information about NSH commands to console. Options:
+
+ -v
+ Show verbose output will full command usage
+
+ <cmd>
+ Show full command usage only for this command
+
+o ifconfig
+
+ Show the current configuration of the network, for example:
+
+ nsh> ifconfig
+ eth0 HWaddr 00:18:11:80:10:06
+ IPaddr:10.0.0.2 DRaddr:10.0.0.1 Mask:255.255.255.0
+
+ if uIP statistics are enabled (CONFIG_NET_STATISTICS), then
+ this command will also show the detailed state of uIP.
+
+o kill -<signal> <pid>
+
+ Send the <signal> to the task identified by <pid>.
+
+o losetup [-d <dev-path>] | [[-o <offset>] [-r] <ldev-path> <file-path>]
+
+ Setup or teardown the loop device:
+
+ 1. Teardown the setup for the loop device at <dev-path>:
+
+ losetup d <dev-path>
+
+ 2. Setup the loop device at <dev-path> to access the file at <file-path>
+ as a block device:
+
+ losetup [-o <offset>] [-r] <dev-path> <file-path>
+
+ Example:
+
+ nsh> dd if=/dev/zero of=/tmp/image bs=512 count=512
+ nsh> ls -l /tmp
+ /tmp:
+ -rw-rw-rw- 262144 IMAGE
+ nsh> losetup /dev/loop0 /tmp/image
+ nsh> ls -l /dev
+ /dev:
+ brw-rw-rw- 0 loop0
+ nsh> mkfatfs /dev/loop0
+ nsh> mount -t vfat /dev/loop0 /mnt/example
+ nsh> ls -l /mnt
+ ls -l /mnt
+ /mnt:
+ drw-rw-rw- 0 example/
+ nsh> echo "This is a test" >/mnt/example/atest.txt
+ nsh> ls -l /mnt/example
+ /mnt/example:
+ -rw-rw-rw- 16 ATEST.TXT
+ nsh> cat /mnt/example/atest.txt
+ This is a test
+ nsh>
+
+o ls [-lRs] <dir-path>
+
+ Show the contents of the directory at <dir-path>. NOTE:
+ <dir-path> must refer to a directory and no other filesystem
+ object.
+
+ Options:
+ --------
+
+ -R Show the constents of specified directory and all of its
+ sub-directories.
+ -s Show the size of the files along with the filenames in the
+ listing
+ -l Show size and mode information along with the filenames
+ in the listing.
+
+o mb <hex-address>[=<hex-value>][ <hex-byte-count>]
+o mh <hex-address>[=<hex-value>][ <hex-byte-count>]
+o mw <hex-address>[=<hex-value>][ <hex-byte-count>]
+
+ Access memory using byte size access (mb), 16-bit accesses (mh),
+ or 32-bit access (mw). In each case,
+
+ <hex-address>. Specifies the address to be accessed. The current
+ value at that address will always be read and displayed.
+ <hex-address>=<hex-value>. Read the value, then write <hex-value>
+ to the location.
+ <hex-byte-count>. Perform the mb, mh, or mw operation on a total
+ of <hex-byte-count> bytes, increment the <hex-address> appropriately
+ after each access
+
+ Example
+
+ nsh> mh 0 16
+ 0 = 0x0c1e
+ 2 = 0x0100
+ 4 = 0x0c1e
+ 6 = 0x0110
+ 8 = 0x0c1e
+ a = 0x0120
+ c = 0x0c1e
+ e = 0x0130
+ 10 = 0x0c1e
+ 12 = 0x0140
+ 14 = 0x0c1e
+ nsh>
+
+o mkdir <path>
+
+ Create the directory at <path>. All components of of <path>
+ except the final directory name must exist on a mounted file
+ system; the final directory must not.
+
+ Recall that NuttX uses a pseudo filesystem for its root file system.
+ The mkdir command can only be used to create directories in volumes
+ set up with the mount command; it cannot be used to create directories
+ in the pseudo filesystem.
+
+ Example:
+ ^^^^^^^^
+
+ nsh> mkdir /mnt/fs/tmp
+ nsh> ls -l /mnt/fs
+ /mnt/fs:
+ drw-rw-rw- 0 TESTDIR/
+ drw-rw-rw- 0 TMP/
+ nsh>
+
+o mkfatfs <path>
+
+ Format a fat file system on the block device specified by path.
+ NSH provides this command to access the mkfatfs() NuttX API.
+ This block device must reside in the NuttX pseudo filesystem and
+ must have been created by some call to register_blockdriver() (see
+ include/nuttx/fs/fs.h).
+
+o mkfifo <path>
+
+ Creates a FIFO character device anywhere in the pseudo file system,
+ creating whatever pseudo directories that may be needed to complete
+ the full path. By convention, however, device drivers are place in
+ the standard /dev directory. After it is created, the FIFO device
+ may be used as any other device driver. NSH provides this command
+ to access the mkfifo() NuttX API.
+
+ Example:
+ ^^^^^^^^
+
+ nsh> ls -l /dev
+ /dev:
+ crw-rw-rw- 0 console
+ crw-rw-rw- 0 null
+ brw-rw-rw- 0 ram0
+ nsh> mkfifo /dev/fifo
+ nsh> ls -l /dev
+ ls -l /dev
+ /dev:
+ crw-rw-rw- 0 console
+ crw-rw-rw- 0 fifo
+ crw-rw-rw- 0 null
+ brw-rw-rw- 0 ram0
+ nsh>
+
+o mkrd [-m <minor>] [-s <sector-size>] <nsectors>
+
+ Create a ramdisk consisting of <nsectors>, each of size
+ <sector-size> (or 512 bytes if <sector-size> is not specified.
+ The ramdisk will be registered as /dev/ram<n> (if <n> is not
+ specified, mkrd will attempt to register the ramdisk as
+ /dev/ram0.
+
+ Example:
+ ^^^^^^^^
+
+ nsh> ls /dev
+ /dev:
+ console
+ null
+ ttyS0
+ ttyS1
+ nsh> mkrd 1024
+ nsh> ls /dev
+ /dev:
+ console
+ null
+ ram0
+ ttyS0
+ ttyS1
+ nsh>
+
+ Once the ramdisk has been created, it may be formatted using
+ the mkfatfs command and mounted using the mount command.
+
+ Example:
+ ^^^^^^^^
+ nsh> mkrd 1024
+ nsh> mkfatfs /dev/ram0
+ nsh> mount -t vfat /dev/ram0 /tmp
+ nsh> ls /tmp
+ /tmp:
+ nsh>
+
+o mount [-t <fstype> <block-device> <dir-path>]
+
+ The mount command performs one of two different operations. If no
+ paramters are provided on the command line after the mount command,
+ then the 'mount' command will enumerate all of the current
+ mountpoints on the console.
+
+ If the mount parameters are provied on the command after the 'mount'
+ command, then the 'mount' command will mount a file system in the
+ NuttX pseudo-file system. 'mount' performs a three way association,
+ binding:
+
+ File system. The '-t <fstype>' option identifies the type of
+ file system that has been formatted on the <block-device>. As
+ of this writing, vfat is the only supported value for <fstype>
+
+ Block Device. The <block-device> argument is the full or relative
+ path to a block driver inode in the pseudo filesystem. By convention,
+ this is a name under the /dev sub-directory. This <block-device>
+ must have been previously formatted with the same file system
+ type as specified by <fstype>
+
+ Mount Point. The mount point is the location in the pseudo file
+ system where the mounted volume will appear. This mount point
+ can only reside in the NuttX pseudo filesystem. By convention, this
+ mount point is a subdirectory under /mnt. The mount command will
+ create whatever pseudo directories that may be needed to complete
+ the full path but the full path must not already exist.
+
+ After the volume has been mounted in the NuttX pseudo file
+ system, it may be access in the same way as other objects in the
+ file system.
+
+ Examples:
+ ^^^^^^^^^
+
+ nsh> ls -l /dev
+ /dev:
+ crw-rw-rw- 0 console
+ crw-rw-rw- 0 null
+ brw-rw-rw- 0 ram0
+ nsh> ls /mnt
+ nsh: ls: no such directory: /mnt
+ nsh> mount -t vfat /dev/ram0 /mnt/fs
+ nsh> ls -l /mnt/fs/testdir
+ /mnt/fs/testdir:
+ -rw-rw-rw- 15 TESTFILE.TXT
+ nsh> echo "This is a test" >/mnt/fs/testdir/example.txt
+ nsh> ls -l /mnt/fs/testdir
+ /mnt/fs/testdir:
+ -rw-rw-rw- 15 TESTFILE.TXT
+ -rw-rw-rw- 16 EXAMPLE.TXT
+ nsh> cat /mnt/fs/testdir/example.txt
+ This is a test
+ nsh>
+
+ nsh> mount
+ /etc type romfs
+ /tmp type vfat
+ /mnt/fs type vfat
+
+o mv <old-path> <new-path>
+
+ Rename the file object at <old-path> to <new-path>. Both paths must
+ reside in the same mounted filesystem.
+
+o nfsmount <server-address> <mount-point> <remote-path>
+
+ Mount the remote NFS server directory <remote-path> at <mount-point> on the target machine.
+ <server-address> is the IP address of the remote server.
+
+o ps
+
+ Show the currently active threads and tasks. For example,
+
+ nsh> ps
+ PID PRI SCHD TYPE NP STATE NAME
+ 0 0 FIFO TASK READY Idle Task()
+ 1 128 RR TASK RUNNING init()
+ 2 128 FIFO TASK WAITSEM nsh_telnetmain()
+ 3 100 RR PTHREAD WAITSEM <pthread>(21)
+ nsh>
+
+o ping [-c <count>] [-i <interval>] <ip-address>
+
+ Test the network communication with a remote peer. Example,
+
+ nsh> 10.0.0.1
+ PING 10.0.0.1 56 bytes of data
+ 56 bytes from 10.0.0.1: icmp_seq=1 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=2 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=3 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=4 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=5 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=6 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=7 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=8 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=9 time=0 ms
+ 56 bytes from 10.0.0.1: icmp_seq=10 time=0 ms
+ 10 packets transmitted, 10 received, 0% packet loss, time 10190 ms
+ nsh>
+
+o put [-b|-n] [-f <remote-path>] -h <ip-address> <local-path>
+
+ Copy the file at <local-address> to the host whose IP address is
+ identified by <ip-address>. Other options:
+
+ -f <remote-path>
+ The file will be saved with the same name on the host unless
+ unless <local-path> is provided.
+ -b|-n
+ Selects either binary ("octect") or test ("netascii") transfer
+ mode. Default: text.
+
+o pwd
+
+ Show the current working directory.
+
+ nsh> cd /dev
+ nsh> pwd
+ /dev
+ nsh>
+
+ Same as 'echo $PWD'
+
+ nsh> echo $PWD
+ /dev
+ nsh>
+
+o rm <file-path>
+
+ Remove the specified <file-path> name from the mounted file system.
+ Recall that NuttX uses a pseudo filesystem for its root file system.
+ The rm command can only be used to remove (unlink) files in volumes
+ set up with the mount command; it cannot be used to remove names from
+ the pseudo filesystem.
+
+ Example:
+ ^^^^^^^^
+
+ nsh> ls /mnt/fs/testdir
+ /mnt/fs/testdir:
+ TESTFILE.TXT
+ EXAMPLE.TXT
+ nsh> rm /mnt/fs/testdir/example.txt
+ nsh> ls /mnt/fs/testdir
+ /mnt/fs/testdir:
+ TESTFILE.TXT
+ nsh>
+
+o rmdir <dir-path>
+
+ Remove the specified <dir-path> directory from the mounted file system.
+ Recall that NuttX uses a pseudo filesystem for its root file system. The
+ rmdir command can only be used to remove directories from volumes set up
+ with the mount command; it cannot be used to remove directories from the
+ pseudo filesystem.
+
+ Example:
+ ^^^^^^^^
+
+ nsh> mkdir /mnt/fs/tmp
+ nsh> ls -l /mnt/fs
+ /mnt/fs:
+ drw-rw-rw- 0 TESTDIR/
+ drw-rw-rw- 0 TMP/
+ nsh> rmdir /mnt/fs/tmp
+ nsh> ls -l /mnt/fs
+ ls -l /mnt/fs
+ /mnt/fs:
+ drw-rw-rw- 0 TESTDIR/
+ nsh>
+
+o set <name> <value>
+
+ Set the environment variable <name> to the sting <value>.
+ For example,
+
+ nsh> echo $foobar
+
+ nsh> set foobar foovalue
+ nsh> echo $foobar
+ foovalue
+ nsh>
+
+o sh <script-path>
+
+ Execute the sequence of NSH commands in the file referred
+ to by <script-path>.
+
+o sleep <sec>
+
+ Pause execution (sleep) of <sec> seconds.
+
+o unset <name>
+
+ Remove the value associated with the environment variable
+ <name>. Example:
+
+ nsh> echo $foobar
+ foovalue
+ nsh> unset foobar
+ nsh> echo $foobar
+
+ nsh>
+
+o usleep <usec>
+
+ Pause execution (sleep) of <usec> microseconds.
+
+o wget [-o <local-path>] <url>
+
+ Use HTTP to copy the file at <url> to the current directory.
+ Options:
+
+ -o <local-path>
+ The file will be saved relative to the current working directory
+ and with the same name as on the HTTP server unless <local-path>
+ is provided.
+
+o xd <hex-address> <byte-count>
+
+ Dump <byte-count> bytes of data from address <hex-address>
+
+ Example:
+ ^^^^^^^^
+
+ nsh> xd 410e0 512
+ Hex dump:
+ 0000: 00 00 00 00 9c 9d 03 00 00 00 00 01 11 01 10 06 ................
+ 0010: 12 01 11 01 25 08 13 0b 03 08 1b 08 00 00 02 24 ....%..........$
+ ...
+ 01f0: 08 3a 0b 3b 0b 49 13 00 00 04 13 01 01 13 03 08 .:.;.I..........
+ nsh>
+
+NSH Configuration Settings
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The availability of the above commands depends upon features that
+may or may not be enabled in the NuttX configuration file. The
+following table indicates the dependency of each command on NuttX
+configuration settings. General configuration settings are discussed
+in the NuttX Porting Guide. Configuration settings specific to NSH
+as discussed at the bottom of this README file.
+
+Command Dependencies on Configuration Settings
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Command Depends on Configuration
+ ---------- --------------------------
+ [ !CONFIG_NSH_DISABLESCRIPT
+ cat CONFIG_NFILE_DESCRIPTORS > 0
+ cd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0
+ cp CONFIG_NFILE_DESCRIPTORS > 0
+ dd CONFIG_NFILE_DESCRIPTORS > 0
+ df !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE (see note 3)
+ echo --
+ exec --
+ exit --
+ free --
+ get CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET_BUFSIZE >= 558 (see note 1)
+ help --
+ ifconfig CONFIG_NET
+ kill !CONFIG_DISABLE_SIGNALS
+ losetup !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0
+ ls CONFIG_NFILE_DESCRIPTORS > 0
+ mb,mh,mw ---
+ mkdir !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4)
+ mkfatfs !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_FAT
+ mkfifo CONFIG_NFILE_DESCRIPTORS > 0
+ mkrd !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4)
+ mount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE (see note 3)
+ mv !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4)
+ nfsmount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET && CONFIG_NFS
+ ping CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING && !CONFIG_DISABLE_CLOCK && !CONFIG_DISABLE_SIGNALS
+ ps --
+ put CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NET_BUFSIZE >= 558 (see note 1,2)
+ pwd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0
+ rm !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4)
+ rmdir !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE (see note 4)
+ set !CONFIG_DISABLE_ENVIRON
+ sh CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !CONFIG_NSH_DISABLESCRIPT
+ sleep !CONFIG_DISABLE_SIGNALS
+ test !CONFIG_NSH_DISABLESCRIPT
+ umount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_READABLE
+ unset !CONFIG_DISABLE_ENVIRON
+ usleep !CONFIG_DISABLE_SIGNALS
+ get CONFIG_NET && CONFIG_NET_TCP && CONFIG_NFILE_DESCRIPTORS > 0
+ xd ---
+
+* NOTES:
+ 1. Because of hardware padding, the actual buffersize required for put and get
+ operations size may be larger.
+ 2. Special TFTP server start-up optionss will probably be required to permit
+ creation of file for the correct operation of the put command.
+ 3. CONFIG_FS_READABLE is not a user configuration but is set automatically
+ if any readable filesystem is selected. At present, this is either CONFIG_FS_FAT
+ and CONFIG_FS_ROMFS.
+ 4. CONFIG_FS_WRITABLE is not a user configuration but is set automatically
+ if any writable filesystem is selected. At present, this is only CONFIG_FS_FAT.
+
+In addition, each NSH command can be individually disabled via one of the following
+settings. All of these settings make the configuration of NSH potentially complex but
+also allow it to squeeze into very small memory footprints.
+
+ CONFIG_NSH_DISABLE_CAT, CONFIG_NSH_DISABLE_CD, CONFIG_NSH_DISABLE_CP,
+ CONFIG_NSH_DISABLE_DD, CONFIG_NSH_DISABLE_DF, CONFIG_NSH_DISABLE_ECHO,
+ CONFIG_NSH_DISABLE_EXEC, CONFIG_NSH_DISABLE_EXIT, CONFIG_NSH_DISABLE_FREE,
+ CONFIG_NSH_DISABLE_GET, CONFIG_NSH_DISABLE_HELP, CONFIG_NSH_DISABLE_IFCONFIG,
+ CONFIG_NSH_DISABLE_KILL, CONFIG_NSH_DISABLE_LOSETUP, CONFIG_NSH_DISABLE_LS,
+ CONFIG_NSH_DISABLE_MB, CONFIG_NSH_DISABLE_MKDIR, CONFIG_NSH_DISABLE_MKFATFS,
+ CONFIG_NSH_DISABLE_MKFIFO, CONFIG_NSH_DISABLE_MKRD, CONFIG_NSH_DISABLE_MH,
+ CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW, CONFIG_NSH_DISABLE_MV,
+ CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_PS, CONFIG_NSH_DISABLE_PING,
+ CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD, CONFIG_NSH_DISABLE_RM,
+ CONFIG_NSH_DISABLE_RMDIR, CONFIG_NSH_DISABLE_SET, CONFIG_NSH_DISABLE_SH,
+ CONFIG_NSH_DISABLE_SLEEP, CONFIG_NSH_DISABLE_TEST, CONFIG_NSH_DISABLE_UMOUNT,
+ CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_USLEEP, CONFIG_NSH_DISABLE_WGET,
+ CONFIG_NSH_DISABLE_XD
+
+Verbose help output can be suppressed by defining CONFIG_NSH_HELP_TERSE. In that
+case, the help command is still available but will be slightly smaller.
+
+NSH-Specific Configuration Settings
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ The behavior of NSH can be modified with the following settings in
+ the configs/<board-name>/defconfig file:
+
+ * CONFIG_NSH_BUILTIN_APPS
+ Support external registered, "named" applications that can be
+ executed from the NSH command line (see apps/README.txt for
+ more information).
+
+ * CONFIG_NSH_FILEIOSIZE
+ Size of a static I/O buffer used for file access (ignored if
+ there is no filesystem). Default is 1024.
+
+ * CONFIG_NSH_STRERROR
+ strerror(errno) makes more readable output but strerror() is
+ very large and will not be used unless this setting is 'y'.
+ This setting depends upon the strerror() having been enabled
+ with CONFIG_LIBC_STRERROR.
+
+ * CONFIG_NSH_LINELEN
+ The maximum length of one command line and of one output line.
+ Default: 80
+
+ * CONFIG_NSH_NESTDEPTH
+ The maximum number of nested if-then[-else]-fi sequences that
+ are permissable. Default: 3
+
+ * CONFIG_NSH_DISABLESCRIPT
+ This can be set to 'y' to suppress support for scripting. This
+ setting disables the 'sh', 'test', and '[' commands and the
+ if-then[-else]-fi construct. This would only be set on systems
+ where a minimal footprint is a necessity and scripting is not.
+
+ * CONFIG_NSH_DISABLEBG
+ This can be set to 'y' to suppress support for background
+ commands. This setting disables the 'nice' command prefix and
+ the '&' command suffix. This would only be set on systems
+ where a minimal footprint is a necessity and background command
+ execution is not.
+
+ * CONFIG_NSH_MMCSDMINOR
+ If the architecture supports an MMC/SD slot and if the NSH
+ architecture specific logic is present, this option will provide
+ the MMC/SD minor number, i.e., the MMC/SD block driver will
+ be registered as /dev/mmcsdN where N is the minor number.
+ Default is zero.
+
+ * CONFIG_NSH_ROMFSETC
+ Mount a ROMFS filesystem at /etc and provide a startup script
+ at /etc/init.d/rcS. The default startup script will mount
+ a FAT FS RAMDISK at /tmp but the logic is easily extensible.
+
+ * CONFIG_NSH_CONSOLE
+ If CONFIG_NSH_CONSOLE is set to 'y', then a serial
+ console front-end is selected.
+
+ Normally, the serial console device is a UART and RS-232
+ interface. However, if CONFIG_USBDEV is defined, then a USB
+ serial device may, instead, be used if the one of
+ the following are defined:
+
+ CONFIG_PL2303 and CONFIG_PL2303_CONSOLE - Sets up the
+ Prolifics PL2303 emulation as a console device
+ at /dev/console.
+
+ CONFIG_CDCACM and CONFIG_CDCACM_CONSOLE - Sets up the
+ CDC/ACM serial device as a console device at
+ dev/console.
+
+ CONFIG_NSH_USBCONSOLE
+ If defined, then the an arbitrary USB device may be used
+ to as the NSH console. In this case, CONFIG_NSH_USBCONDEV
+ must be defined to indicate which USB device to use as
+ the console.
+
+ CONFIG_NSH_USBCONDEV
+ If CONFIG_NSH_USBCONSOLE is set to 'y', then CONFIG_NSH_USBCONDEV
+ must also be set to select the USB device used to support
+ the NSH console. This should be set to the quoted name of a
+ readable/write-able USB driver such as:
+ CONFIG_NSH_USBCONDEV="/dev/ttyACM0".
+
+ If there are more than one USB devices, then a USB device
+ minor number may also need to be provided:
+
+ CONFIG_NSH_UBSDEV_MINOR
+ The minor device number of the USB device. Default: 0
+
+ If USB tracing is enabled (CONFIG_USBDEV_TRACE), then NSH will
+ initialize USB tracing as requested by the following. Default:
+ Only USB errors are traced.
+
+ CONFIG_NSH_USBDEV_TRACEINIT
+ Show initialization events
+ CONFIG_NSH_USBDEV_TRACECLASS
+ Show class driver events
+ CONFIG_NSH_USBDEV_TRACETRANSFERS
+ Show data transfer events
+ CONFIG_NSH_USBDEV_TRACECONTROLLER
+ Show controller events
+ CONFIG_NSH_USBDEV_TRACEINTERRUPTS
+ Show interrupt-related events.
+
+ * CONFIG_NSH_CONDEV
+ If CONFIG_NSH_CONSOLE is set to 'y', then CONFIG_NSH_CONDEV
+ may also be set to select the serial device used to support
+ the NSH console. This should be set to the quoted name of a
+ readable/write-able character driver such as:
+ CONFIG_NSH_CONDEV="/dev/ttyS1". This is useful, for example,
+ to separate the NSH command line from the system console when
+ the system console is used to provide debug output. Default:
+ stdin and stdout (probably "/dev/console")
+
+ NOTE: When any other device other than /dev/console is used
+ for a user interface, (1) linefeeds (\n) will not be expanded to
+ carriage return / linefeeds (\r\n). You will need to set
+ your terminal program to account for this. And (2) input is
+ not automatically echoed so you will have to turn local echo on.
+
+ * CONFIG_NSH_TELNET
+ If CONFIG_NSH_TELNET is set to 'y', then a TELENET
+ server front-end is selected. When this option is provided,
+ you may log into NuttX remotely using telnet in order to
+ access NSH.
+
+ * CONFIG_NSH_ARCHINIT
+ Set if your board provides architecture specific initialization
+ via the board-specific function nsh_archinitialize(). This
+ function will be called early in NSH initialization to allow
+ board logic to do such things as configure MMC/SD slots.
+
+ If Telnet is selected for the NSH console, then we must configure
+ the resources used by the Telnet daemon and by the Telnet clients.
+
+ * CONFIG_NSH_TELNETD_PORT - The telnet daemon will listen on this
+ TCP port number for connections. Default: 23
+
+ * CONFIG_NSH_TELNETD_DAEMONPRIO - Priority of the Telnet daemon.
+ Default: SCHED_PRIORITY_DEFAULT
+
+ * CONFIG_NSH_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the
+ Telnet daemon. Default: 2048
+
+ * CONFIG_NSH_TELNETD_CLIENTPRIO- Priority of the Telnet client.
+ Default: SCHED_PRIORITY_DEFAULT
+
+ * CONFIG_NSH_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the
+ Telnet client. Default: 2048
+
+ One or both of CONFIG_NSH_CONSOLE and CONFIG_NSH_TELNET
+ must be defined. If CONFIG_NSH_TELNET is selected, then there some
+ other configuration settings that apply:
+
+ * CONFIG_NET=y
+ Of course, networking must be enabled
+
+ * CONFIG_NSOCKET_DESCRIPTORS
+ And, of course, you must allocate some socket descriptors.
+
+ * CONFIG_NET_TCP=y
+ TCP/IP support is required for telnet (as well as various other TCP-related
+ configuration settings).
+
+ * CONFIG_NSH_IOBUFFER_SIZE
+ Determines the size of the I/O buffer to use for sending/
+ receiving TELNET commands/reponses
+
+ * CONFIG_NSH_DHCPC
+ Obtain the IP address via DHCP.
+
+ * CONFIG_NSH_IPADDR
+ If CONFIG_NSH_DHCPC is NOT set, then the static IP
+ address must be provided.
+
+ * CONFIG_NSH_DRIPADDR
+ Default router IP address
+
+ * CONFIG_NSH_NETMASK
+ Network mask
+
+ * CONFIG_NSH_NOMAC
+ Set if your ethernet hardware has no built-in MAC address.
+ If set, a bogus MAC will be assigned.
+
+ If you use DHCPC, then some special configuration network options are
+ required. These include:
+
+ * CONFIG_NET=y
+ Of course, networking must be enabled
+
+ * CONFIG_NSOCKET_DESCRIPTORS
+ And, of course, you must allocate some socket descriptors.
+
+ * CONFIG_NET_UDP=y
+ UDP support is required for DHCP (as well as various other UDP-related
+ configuration settings)
+
+ * CONFIG_NET_BROADCAST=y
+ UDP broadcast support is needed.
+
+ * CONFIG_NET_BUFSIZE=650 (or larger)
+ Per RFC2131 (p. 9), the DHCP client must be prepared to receive DHCP
+ messages of up to 576 bytes (excluding Ethernet, IP, or UDP headers and FCS).
+
+ If CONFIG_NSH_ROMFSETC is selected, then the following additional
+ configuration setting apply:
+
+ * CONFIG_NSH_ROMFSMOUNTPT
+ The default mountpoint for the ROMFS volume is /etc, but that
+ can be changed with this setting. This must be a absolute path
+ beginning with '/'.
+
+ * CONFIG_NSH_INITSCRIPT
+ This is the relative path to the startup script within the mountpoint.
+ The default is init.d/rcS. This is a relative path and must not
+ start with '/'.
+
+ * CONFIG_NSH_ROMFSDEVNO
+ This is the minor number of the ROMFS block device. The default is
+ '0' corresponding to /dev/ram0.
+
+ * CONFIG_NSH_ROMFSSECTSIZE
+ This is the sector size to use with the ROMFS volume. Since the
+ default volume is very small, this defaults to 64 but should be
+ increased if the ROMFS volume were to be become large. Any value
+ selected must be a power of 2.
+
+ When the default rcS file used when CONFIG_NSH_ROMFSETC is
+ selected, it will mount a FAT FS under /tmp. The following selections
+ describe that FAT FS.
+
+ * CONFIG_NSH_FATDEVNO
+ This is the minor number of the FAT FS block device. The default is
+ '1' corresponding to /dev/ram1.
+
+ * CONFIG_NSH_FATSECTSIZE
+ This is the sector size use with the FAT FS. Default is 512.
+
+ * CONFIG_NSH_FATNSECTORS
+ This is the number of sectors to use with the FAT FS. Defalt is
+ 1024. The amount of memory used by the FAT FS will be
+ CONFIG_NSH_FATSECTSIZE * CONFIG_NSH_FATNSECTORS
+ bytes.
+
+ * CONFIG_NSH_FATMOUNTPT
+ This is the location where the FAT FS will be mounted. Default
+ is /tmp.
+
+Common Problems
+^^^^^^^^^^^^^^^
+
+ Problem:
+ Using NSH over serial, the "nsh>" prompt repeats over and over again
+ with no serial input.
+ Usual Cause:
+ NSH over serial needs to use the interrupt driven serial driver
+ (drivers/serial/serial.c) not the polled serial driver (drivers/serial/lowconsole.c).
+ Make sure that the polled console is disabled in the OS configuration
+ file, .config. That file should have CONFIG_DEV_LOWCONSOLE=n for
+ NSH over serial.
+
+ Problem:
+ The function 'readline' is undefined.
+ Usual Cause:
+ The following is missing from your appconfig file:
+
+ CONFIGURED_APPS += system/readline
+
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
new file mode 100644
index 000000000..dac91ba05
--- /dev/null
+++ b/apps/nshlib/nsh.h
@@ -0,0 +1,611 @@
+/****************************************************************************
+ * apps/nshlib/nsh.h
+ *
+ * Copyright (C) 2007-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.
+ *
+ ****************************************************************************/
+
+#ifndef __APPS_NSHLIB_NSH_H
+#define __APPS_NSHLIB_NSH_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+
+#include <nuttx/usb/usbdev_trace.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+/* The background commands require pthread support */
+
+#ifdef CONFIG_DISABLE_PTHREAD
+# ifndef CONFIG_NSH_DISABLEBG
+# define CONFIG_NSH_DISABLEBG 1
+# endif
+#endif
+
+/* Telnetd requires networking support */
+
+#ifndef CONFIG_NET
+# undef CONFIG_NSH_TELNET
+#endif
+
+/* One front end must be defined */
+
+#if !defined(CONFIG_NSH_CONSOLE) && !defined(CONFIG_NSH_TELNET)
+# error "No NSH front end defined"
+#endif
+
+/* If a USB device is selected for the NSH console then we need to handle some
+ * special start-up conditions.
+ */
+
+#undef HAVE_USB_CONSOLE
+#if defined(CONFIG_USBDEV)
+
+/* Check for a PL2303 serial console. Use console device "/dev/console". */
+
+# if defined(CONFIG_PL2303) && defined(CONFIG_PL2303_CONSOLE)
+# define HAVE_USB_CONSOLE 1
+
+/* Check for a CDC/ACM serial console. Use console device "/dev/console". */
+
+# elif defined(CONFIG_CDCACM) && defined(CONFIG_CDCACM_CONSOLE)
+# define HAVE_USB_CONSOLE 1
+
+/* Check for other USB console. USB console device must be provided in CONFIG_NSH_CONDEV */
+
+# elif defined(CONFIG_NSH_USBCONSOLE)
+# define HAVE_USB_CONSOLE 1
+# endif
+#endif
+
+/* Defaults for the USB console */
+
+#ifdef HAVE_USB_CONSOLE
+
+/* The default USB console device minor number is 0*/
+
+# ifndef CONFIG_NSH_UBSDEV_MINOR
+# define CONFIG_NSH_UBSDEV_MINOR 0
+# endif
+
+/* The default console device is always /dev/console */
+
+# ifndef CONFIG_NSH_USBCONDEV
+# define CONFIG_NSH_USBCONDEV "/dev/console"
+# endif
+
+/* USB trace settings */
+
+#ifdef CONFIG_NSH_USBDEV_TRACEINIT
+# define TRACE_INIT_BITS (TRACE_INIT_BIT)
+#else
+# define TRACE_INIT_BITS (0)
+#endif
+
+#define TRACE_ERROR_BITS (TRACE_DEVERROR_BIT|TRACE_CLSERROR_BIT)
+
+#ifdef CONFIG_NSH_USBDEV_TRACECLASS
+# define TRACE_CLASS_BITS (TRACE_CLASS_BIT|TRACE_CLASSAPI_BIT|TRACE_CLASSSTATE_BIT)
+#else
+# define TRACE_CLASS_BITS (0)
+#endif
+
+#ifdef CONFIG_NSH_USBDEV_TRACETRANSFERS
+# define TRACE_TRANSFER_BITS (TRACE_OUTREQQUEUED_BIT|TRACE_INREQQUEUED_BIT|TRACE_READ_BIT|\
+ TRACE_WRITE_BIT|TRACE_COMPLETE_BIT)
+#else
+# define TRACE_TRANSFER_BITS (0)
+#endif
+
+#ifdef CONFIG_NSH_USBDEV_TRACECONTROLLER
+# define TRACE_CONTROLLER_BITS (TRACE_EP_BIT|TRACE_DEV_BIT)
+#else
+# define TRACE_CONTROLLER_BITS (0)
+#endif
+
+#ifdef CONFIG_NSH_USBDEV_TRACEINTERRUPTS
+# define TRACE_INTERRUPT_BITS (TRACE_INTENTRY_BIT|TRACE_INTDECODE_BIT|TRACE_INTEXIT_BIT)
+#else
+# define TRACE_INTERRUPT_BITS (0)
+#endif
+
+#define TRACE_BITSET (TRACE_INIT_BITS|TRACE_ERROR_BITS|TRACE_CLASS_BITS|\
+ TRACE_TRANSFER_BITS|TRACE_CONTROLLER_BITS|TRACE_INTERRUPT_BITS)
+
+#endif
+
+/* If Telnet is selected for the NSH console, then we must configure
+ * the resources used by the Telnet daemon and by the Telnet clients.
+ *
+ * CONFIG_NSH_TELNETD_PORT - The telnet daemon will listen on this.
+ * port. Default: 23
+ * CONFIG_NSH_TELNETD_DAEMONPRIO - Priority of the Telnet daemon.
+ * Default: SCHED_PRIORITY_DEFAULT
+ * CONFIG_NSH_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the
+ * Telnet daemon. Default: 2048
+ * CONFIG_NSH_TELNETD_CLIENTPRIO- Priority of the Telnet client.
+ * Default: SCHED_PRIORITY_DEFAULT
+ * CONFIG_NSH_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the
+ * Telnet client. Default: 2048
+ */
+
+#ifndef CONFIG_NSH_TELNETD_PORT
+# define CONFIG_NSH_TELNETD_PORT 23
+#endif
+
+#ifndef CONFIG_NSH_TELNETD_DAEMONPRIO
+# define CONFIG_NSH_TELNETD_DAEMONPRIO SCHED_PRIORITY_DEFAULT
+#endif
+
+#ifndef CONFIG_NSH_TELNETD_DAEMONSTACKSIZE
+# define CONFIG_NSH_TELNETD_DAEMONSTACKSIZE 2048
+#endif
+
+#ifndef CONFIG_NSH_TELNETD_CLIENTPRIO
+# define CONFIG_NSH_TELNETD_CLIENTPRIO SCHED_PRIORITY_DEFAULT
+#endif
+
+#ifndef CONFIG_NSH_TELNETD_CLIENTSTACKSIZE
+# define CONFIG_NSH_TELNETD_CLIENTSTACKSIZE 2048
+#endif
+
+/* Verify support for ROMFS /etc directory support options */
+
+#ifdef CONFIG_NSH_ROMFSETC
+# ifdef CONFIG_DISABLE_MOUNTPOINT
+# error "Mountpoint support is disabled"
+# undef CONFIG_NSH_ROMFSETC
+# endif
+# if CONFIG_NFILE_DESCRIPTORS < 4
+# error "Not enough file descriptors"
+# undef CONFIG_NSH_ROMFSETC
+# endif
+# ifndef CONFIG_FS_ROMFS
+# error "ROMFS support not enabled"
+# undef CONFIG_NSH_ROMFSETC
+# endif
+# ifndef CONFIG_NSH_ROMFSMOUNTPT
+# define CONFIG_NSH_ROMFSMOUNTPT "/etc"
+# endif
+# ifdef CONFIG_NSH_INIT
+# ifndef CONFIG_NSH_INITSCRIPT
+# define CONFIG_NSH_INITSCRIPT "init.d/rcS"
+# endif
+# endif
+# undef NSH_INITPATH
+# define NSH_INITPATH CONFIG_NSH_ROMFSMOUNTPT "/" CONFIG_NSH_INITSCRIPT
+# ifndef CONFIG_NSH_ROMFSDEVNO
+# define CONFIG_NSH_ROMFSDEVNO 0
+# endif
+# ifndef CONFIG_NSH_ROMFSSECTSIZE
+# define CONFIG_NSH_ROMFSSECTSIZE 64
+# endif
+# define NSECTORS(b) (((b)+CONFIG_NSH_ROMFSSECTSIZE-1)/CONFIG_NSH_ROMFSSECTSIZE)
+# define STR_RAMDEVNO(m) #m
+# define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m)
+# define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_NSH_ROMFSDEVNO)
+#else
+# undef CONFIG_NSH_ROMFSMOUNTPT
+# undef CONFIG_NSH_INIT
+# undef CONFIG_NSH_INITSCRIPT
+# undef CONFIG_NSH_ROMFSDEVNO
+# undef CONFIG_NSH_ROMFSSECTSIZE
+#endif
+
+/* This is the maximum number of arguments that will be accepted for a command */
+
+#define NSH_MAX_ARGUMENTS 6
+
+/* strerror() produces much nicer output but is, however, quite large and
+ * will only be used if CONFIG_NSH_STRERROR is defined. Note that the strerror
+ * interface must also have been enabled with CONFIG_LIBC_STRERROR.
+ */
+
+#ifndef CONFIG_LIBC_STRERROR
+# undef CONFIG_NSH_STRERROR
+#endif
+
+#ifdef CONFIG_NSH_STRERROR
+# define NSH_ERRNO strerror(errno)
+# define NSH_ERRNO_OF(err) strerror(err)
+#else
+# define NSH_ERRNO (errno)
+# define NSH_ERRNO_OF(err) (err)
+#endif
+
+/* Maximum size of one command line (telnet or serial) */
+
+#ifndef CONFIG_NSH_LINELEN
+# define CONFIG_NSH_LINELEN 80
+#endif
+
+/* The following two settings are used only in the telnetd interface */
+
+#ifndef CONFIG_NSH_IOBUFFER_SIZE
+# define CONFIG_NSH_IOBUFFER_SIZE 512
+#endif
+
+/* The maximum number of nested if-then[-else]-fi sequences that
+ * are permissable.
+ */
+
+#ifndef CONFIG_NSH_NESTDEPTH
+# define CONFIG_NSH_NESTDEPTH 3
+#endif
+
+/* Define to enable dumping of all input/output buffers */
+
+#undef CONFIG_NSH_TELNETD_DUMPBUFFER
+#undef CONFIG_NSH_FULLPATH
+
+/* Make sure that the home directory is defined */
+
+#ifndef CONFIG_LIB_HOMEDIR
+# define CONFIG_LIB_HOMEDIR "/"
+#endif
+
+/* Stubs used when working directory is not supported */
+
+#if CONFIG_NFILE_DESCRIPTORS <= 0 || defined(CONFIG_DISABLE_ENVIRON)
+# define nsh_getfullpath(v,p) ((char*)(p))
+# define nsh_freefullpath(p)
+#endif
+
+/* The size of the I/O buffer may be specified in the
+ * configs/<board-name>defconfig file -- provided that it is at least as
+ * large as PATH_MAX.
+ */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+# ifdef CONFIG_NSH_FILEIOSIZE
+# if CONFIG_NSH_FILEIOSIZE > (PATH_MAX + 1)
+# define IOBUFFERSIZE CONFIG_NSH_FILEIOSIZE
+# else
+# define IOBUFFERSIZE (PATH_MAX + 1)
+# endif
+# else
+# define IOBUFFERSIZE 1024
+# endif
+# else
+# define IOBUFFERSIZE (PATH_MAX + 1)
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+enum nsh_parser_e
+{
+ NSH_PARSER_NORMAL = 0,
+ NSH_PARSER_IF,
+ NSH_PARSER_THEN,
+ NSH_PARSER_ELSE
+};
+
+struct nsh_state_s
+{
+ uint8_t ns_ifcond : 1; /* Value of command in 'if' statement */
+ uint8_t ns_disabled : 1; /* TRUE: Unconditionally disabled */
+ uint8_t ns_unused : 4;
+ uint8_t ns_state : 2; /* Parser state (see enum nsh_parser_e) */
+};
+
+struct nsh_parser_s
+{
+#ifndef CONFIG_NSH_DISABLEBG
+ bool np_bg; /* true: The last command executed in background */
+#endif
+ bool np_redirect; /* true: Output from the last command was re-directed */
+ bool np_fail; /* true: The last command failed */
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ uint8_t np_ndx; /* Current index into np_st[] */
+#endif
+#ifndef CONFIG_NSH_DISABLEBG
+ int np_nice; /* "nice" value applied to last background cmd */
+#endif
+
+ /* This is a stack of parser state information. It supports nested
+ * execution of commands that span multiple lines (like if-then-else-fi)
+ */
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ struct nsh_state_s np_st[CONFIG_NSH_NESTDEPTH];
+#endif
+};
+
+struct nsh_vtbl_s; /* Defined in nsh_console.h */
+typedef int (*cmd_t)(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern const char g_nshgreeting[];
+extern const char g_nshprompt[];
+extern const char g_nshsyntax[];
+extern const char g_fmtargrequired[];
+extern const char g_fmtarginvalid[];
+extern const char g_fmtargrange[];
+extern const char g_fmtcmdnotfound[];
+extern const char g_fmtnosuch[];
+extern const char g_fmttoomanyargs[];
+extern const char g_fmtdeepnesting[];
+extern const char g_fmtcontext[];
+extern const char g_fmtcmdfailed[];
+extern const char g_fmtcmdoutofmemory[];
+extern const char g_fmtinternalerror[];
+#ifndef CONFIG_DISABLE_SIGNALS
+extern const char g_fmtsignalrecvd[];
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* Initialization */
+
+#ifdef CONFIG_NSH_ROMFSETC
+int nsh_romfsetc(void);
+#else
+# define nsh_romfsetc() (-ENOSYS)
+#endif
+
+#ifdef CONFIG_NET
+int nsh_netinit(void);
+#else
+# define nsh_netinit() (-ENOSYS)
+#endif
+
+#ifdef HAVE_USB_CONSOLE
+int nsh_usbconsole(void);
+#else
+# define nsh_usbconsole() (-ENOSYS)
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT)
+int nsh_script(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *path);
+#endif
+
+/* Architecture-specific initialization */
+
+#ifdef CONFIG_NSH_ARCHINIT
+int nsh_archinitialize(void);
+#else
+# define nsh_archinitialize() (-ENOSYS)
+#endif
+
+/* Message handler */
+
+int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline);
+
+/* Application interface */
+
+#ifdef CONFIG_NSH_BUILTIN_APPS
+int nsh_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd, FAR char **argv);
+#endif
+
+/* Working directory support */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+FAR const char *nsh_getcwd(void);
+char *nsh_getfullpath(FAR struct nsh_vtbl_s *vtbl, const char *relpath);
+void nsh_freefullpath(char *relpath);
+#endif
+
+/* Debug */
+
+void nsh_dumpbuffer(FAR struct nsh_vtbl_s *vtbl, const char *msg,
+ const uint8_t *buffer, ssize_t nbytes);
+
+/* USB debug support */
+
+#if defined(CONFIG_USBDEV_TRACE) && defined(HAVE_USB_CONSOLE)
+void nsh_usbtrace(void);
+#else
+# define nsh_usbtrace()
+#endif
+
+/* Shell command handlers */
+
+#ifndef CONFIG_NSH_DISABLE_ECHO
+ int cmd_echo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_EXEC
+ int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_MB
+ int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_MH
+ int cmd_mh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_MW
+ int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_FREE
+ int cmd_free(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_PS
+ int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+#ifndef CONFIG_NSH_DISABLE_XD
+ int cmd_xd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+
+#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST)
+ int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+
+#ifndef CONFIG_DISABLE_CLOCK
+# if defined (CONFIG_RTC) && !defined(CONFIG_NSH_DISABLE_DATE)
+ int cmd_date(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_CAT
+ int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_CP
+ int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_DD
+ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_LS
+ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# if defined(CONFIG_SYSLOG) && defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_NSH_DISABLE_DMESG)
+ int cmd_dmesg(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# if CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT)
+# ifndef CONFIG_NSH_DISABLE_SH
+ int cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# endif /* CONFIG_NFILE_STREAMS && !CONFIG_NSH_DISABLESCRIPT */
+# ifndef CONFIG_DISABLE_MOUNTPOINT
+# ifndef CONFIG_NSH_DISABLE_LOSETUP
+ int cmd_losetup(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_MKFIFO
+ int cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifdef CONFIG_FS_READABLE
+# ifndef CONFIG_NSH_DISABLE_DF
+ int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_MOUNT
+ int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_UMOUNT
+ int cmd_umount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifdef CONFIG_FS_WRITABLE
+# ifndef CONFIG_NSH_DISABLE_MKDIR
+ int cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_MKRD
+ int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_MV
+ int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_RM
+ int cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_RMDIR
+ int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# endif /* CONFIG_FS_WRITABLE */
+# endif /* CONFIG_FS_READABLE */
+# ifdef CONFIG_FS_FAT
+# ifndef CONFIG_NSH_DISABLE_MKFATFS
+ int cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# endif /* CONFIG_FS_FAT */
+# endif /* !CONFIG_DISABLE_MOUNTPOINT */
+# if !defined(CONFIG_DISABLE_ENVIRON)
+# ifndef CONFIG_NSH_DISABLE_CD
+ int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_PWD
+ int cmd_pwd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# endif /* !CONFIG_DISABLE_MOUNTPOINT */
+#endif /* CONFIG_NFILE_DESCRIPTORS */
+
+#if defined(CONFIG_NET)
+# ifndef CONFIG_NSH_DISABLE_IFCONFIG
+ int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_GET
+ int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_PUT
+ int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif
+#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_WGET
+ int cmd_wget(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
+# ifndef CONFIG_NSH_DISABLE_PING
+ int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && \
+ defined(CONFIG_FS_READABLE) && defined(CONFIG_NFS)
+# ifndef CONFIG_NSH_DISABLE_NFSMOUNT
+ int cmd_nfsmount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif
+#endif
+
+#ifndef CONFIG_DISABLE_ENVIRON
+# ifndef CONFIG_NSH_DISABLE_SET
+ int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_UNSET
+ int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif /* CONFIG_DISABLE_ENVIRON */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+# ifndef CONFIG_NSH_DISABLE_KILL
+ int cmd_kill(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_SLEEP
+ int cmd_sleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+# ifndef CONFIG_NSH_DISABLE_USLEEP
+ int cmd_usleep(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+# endif
+#endif /* CONFIG_DISABLE_SIGNALS */
+
+#endif /* __APPS_NSHLIB_NSH_H */
diff --git a/apps/nshlib/nsh_apps.c b/apps/nshlib/nsh_apps.c
new file mode 100644
index 000000000..e335c2e2c
--- /dev/null
+++ b/apps/nshlib/nsh_apps.c
@@ -0,0 +1,187 @@
+/****************************************************************************
+ * apps/nshlib/nsh_apps.c
+ *
+ * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Author: Uros Platise <uros.platise@isotel.eu>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_SCHED_WAITPID
+# include <sys/wait.h>
+#endif
+
+#include <stdbool.h>
+#include <errno.h>
+#include <string.h>
+
+#include <apps/apps.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#ifdef CONFIG_NSH_BUILTIN_APPS
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_execapp
+ *
+ * Description:
+ * Attempt to execute the application task whose name is 'cmd'
+ *
+ * Returned Value:
+ * <0 If exec_namedapp() 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_execapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv)
+{
+ int ret = OK;
+
+ /* Lock the scheduler to prevent the application from running until the
+ * waitpid() has been called.
+ */
+
+ sched_lock();
+
+ /* Try to find and execute the command within the list of builtin
+ * applications.
+ */
+
+ ret = exec_namedapp(cmd, (FAR const char **)argv);
+ if (ret >= 0)
+ {
+ /* The application was successfully started (but still blocked because the
+ * scheduler is locked). If the application was not backgrounded, then we
+ * need to wait here for the application to exit.
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ if (vtbl->np.np_bg == false)
+ {
+ int rc = 0;
+
+ /* Wait for the application to exit. Since we have locked the
+ * scheduler above, we know that the application has not yet
+ * started and there is no possibility that it has already exited.
+ * The scheduler will be unlocked while waitpid is waiting and the
+ * application will be able to run.
+ */
+
+ ret = waitpid(ret, &rc, 0);
+ if (ret >= 0)
+ {
+ /* We can't return the exact status (nsh has nowhere to put it)
+ * so just pass back zero/nonzero in a fashion that doesn't look
+ * like an error.
+ */
+
+ ret = (rc == 0) ? OK : 1;
+
+ /* TODO: Set the environment variable '?' to a string corresponding
+ * to WEXITSTATUS(rc) so that $? will expand to the exit status of
+ * the most recently executed task.
+ */
+ }
+ }
+ else
+#endif
+ {
+ struct sched_param param;
+ sched_getparam(0, &param);
+ nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
+
+ /* Backgrounded commands always 'succeed' as long as we can start
+ * them.
+ */
+
+ ret = OK;
+ }
+ }
+
+ sched_unlock();
+
+ /* If exec_namedapp() or waitpid() failed, then return the negated errno
+ * value.
+ */
+
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NSH_BUILTIN_APPS */
diff --git a/apps/nshlib/nsh_console.c b/apps/nshlib/nsh_console.c
new file mode 100644
index 000000000..b066e71f5
--- /dev/null
+++ b/apps/nshlib/nsh_console.c
@@ -0,0 +1,432 @@
+/****************************************************************************
+ * apps/nshlib/nsh_serial.c
+ *
+ * Copyright (C) 2007-2009, 2011-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 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 <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct serialsave_s
+{
+ int cn_outfd; /* Re-directed output file descriptor */
+ FILE *cn_outstream; /* Re-directed output stream */
+};
+
+/****************************************************************************
+ * 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, 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);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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;
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************
+ * Name: nsh_closeifnotclosed
+ *
+ * Description:
+ * Close the output stream if it is not the standard output 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_outfd = -1;
+ pstate->cn_outstream = NULL;
+ }
+}
+
+/****************************************************************************
+ * 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 (ssize_t)ERROR;
+ }
+
+ /* Write the data to the output stream */
+
+ ret = fwrite(buffer, 1, nbytes, pstate->cn_outstream);
+ if (ret < 0)
+ {
+ dbg("[%d] Failed to send buffer: %d\n", pstate->cn_outfd, errno);
+ }
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nsh_consoleoutput
+ *
+ * Description:
+ * Print a string to the currently selected stream.
+ *
+ ****************************************************************************/
+
+static int nsh_consoleoutput(FAR struct nsh_vtbl_s *vtbl, 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_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_CONDEV
+ (void)fclose(pstate->cn_constream);
+#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_outstream);
+ }
+
+ /* Save the current fd and stream values. These will be restored
+ * when nsh_consoleundirect() is called.
+ */
+
+ ssave->cn_outfd = pstate->cn_outfd;
+ 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_outfd = ssave->cn_outfd;
+ 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)
+{
+ struct console_stdio_s *pstate = (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.linebuffer = nsh_consolelinebuffer;
+ pstate->cn_vtbl.redirect = nsh_consoleredirect;
+ pstate->cn_vtbl.undirect = nsh_consoleundirect;
+ pstate->cn_vtbl.exit = nsh_consoleexit;
+
+ /* (Re-) open the console input device */
+
+#ifdef CONFIG_NSH_CONDEV
+ pstate->cn_confd = open(CONFIG_NSH_CONDEV, O_RDWR);
+ if (pstate->cn_confd < 0)
+ {
+ free(pstate);
+ return NULL;
+ }
+
+ /* Create a standard C stream on the console device */
+
+ pstate->cn_constream = fdopen(pstate->cn_confd, "r+");
+ if (!pstate->cn_constream)
+ {
+ close(pstate->cn_confd);
+ free(pstate);
+ return NULL;
+ }
+#endif
+
+ /* Initialize the output stream */
+
+ pstate->cn_outfd = OUTFD(pstate);
+ pstate->cn_outstream = OUTSTREAM(pstate);
+ }
+ return pstate;
+}
diff --git a/apps/nshlib/nsh_console.h b/apps/nshlib/nsh_console.h
new file mode 100644
index 000000000..53e8c7897
--- /dev/null
+++ b/apps/nshlib/nsh_console.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+ * apps/nshlib/nsh_console.h
+ *
+ * Copyright (C) 2007-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.
+ *
+ ****************************************************************************/
+
+#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>
+
+/****************************************************************************
+ * 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_output(v, fmt...) (v)->output(v, ##fmt)
+#else
+# define nsh_output vtbl->output
+#endif
+
+/* Size of info to be saved in call to nsh_redirect */
+
+#define SAVE_SIZE (sizeof(int) + sizeof(FILE*) + sizeof(bool))
+
+/* Are we using the NuttX console for I/O? Or some other character device? */
+
+#ifdef CONFIG_NSH_CONDEV
+# define INFD(p) ((p)->cn_confd)
+# define INSTREAM(p) ((p)->cn_constream)
+# define OUTFD(p) ((p)->cn_confd)
+# define OUTSTREAM(p) ((p)->cn_constream)
+#else
+# define INFD(p) 0
+# define INSTREAM(p) stdin
+# define OUTFD(p) 1
+# define OUTSTREAM(p) stdout
+#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 (*output)(FAR struct nsh_vtbl_s *vtbl, 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 exitstatus);
+
+ /* 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_NSH_CONDEV
+ int cn_confd; /* Console I/O file descriptor */
+#endif
+ int cn_outfd; /* Output file descriptor (possibly redirected) */
+#ifdef CONFIG_NSH_CONDEV
+ FILE *cn_constream; /* Console I/O stream (possibly redirected) */
+#endif
+ FILE *cn_outstream; /* Output stream */
+
+ /* 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 */
diff --git a/apps/nshlib/nsh_consolemain.c b/apps/nshlib/nsh_consolemain.c
new file mode 100644
index 000000000..6b51be470
--- /dev/null
+++ b/apps/nshlib/nsh_consolemain.c
@@ -0,0 +1,170 @@
+/****************************************************************************
+ * apps/nshlib/nsh_consolemain.c
+ *
+ * Copyright (C) 2007-2009, 2011-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 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 <apps/readline.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_consolemain
+ *
+ * Description:
+ * This interfaces maybe to called or started with task_start to start a
+ * single an NSH instance that operates on stdin and stdout (/dev/console).
+ * This function does not return.
+ *
+ * Input Parameters:
+ * Standard task start-up arguements. 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 nonzero value is returned (1).
+ *
+ ****************************************************************************/
+
+int nsh_consolemain(int argc, char *argv[])
+{
+ FAR struct console_stdio_s *pstate = nsh_newconsole();
+ int ret;
+
+ DEBUGASSERT(pstate);
+
+ /* If we are using a USB serial console, then we will have to wait for the
+ * USB to be connected to the host.
+ */
+
+#ifdef HAVE_USB_CONSOLE
+ ret = nsh_usbconsole();
+ DEBUGASSERT(ret == OK);
+#endif
+
+ /* Present a greeting */
+
+ fputs(g_nshgreeting, pstate->cn_outstream);
+ fflush(pstate->cn_outstream);
+
+ /* Execute the startup script */
+
+#ifdef CONFIG_NSH_ROMFSETC
+ (void)nsh_script(&pstate->cn_vtbl, "init", NSH_INITPATH);
+#endif
+
+ /* Then enter the command line parsing loop */
+
+ for (;;)
+ {
+ /* For the case of debugging the USB console... dump collected USB trace data */
+
+ nsh_usbtrace();
+
+ /* Display the prompt string */
+
+ fputs(g_nshprompt, pstate->cn_outstream);
+ fflush(pstate->cn_outstream);
+
+ /* Get the next line of input */
+
+ ret = readline(pstate->cn_line, CONFIG_NSH_LINELEN,
+ INSTREAM(pstate), OUTSTREAM(pstate));
+ if (ret > 0)
+ {
+ /* Parse process the command */
+
+ (void)nsh_parse(&pstate->cn_vtbl, pstate->cn_line);
+ fflush(pstate->cn_outstream);
+ }
+
+ /* Readline normally returns the number of characters read,
+ * but will return 0 on end of file or a negative value
+ * if an error occurs. Either will cause the session to
+ * terminate.
+ */
+
+ else
+ {
+ fprintf(pstate->cn_outstream, g_fmtcmdfailed, "nsh_consolemain",
+ "readline", NSH_ERRNO_OF(-ret));
+ nsh_exit(&pstate->cn_vtbl, 1);
+ }
+ }
+
+ /* Clean up */
+
+ nsh_exit(&pstate->cn_vtbl, 0);
+
+ /* We do not get here, but this is necessary to keep some compilers happy */
+
+ return OK;
+}
diff --git a/apps/nshlib/nsh_dbgcmds.c b/apps/nshlib/nsh_dbgcmds.c
new file mode 100644
index 000000000..384b377f3
--- /dev/null
+++ b/apps/nshlib/nsh_dbgcmds.c
@@ -0,0 +1,355 @@
+/****************************************************************************
+ * apps/nshlib/dbg_dbgcmds.c
+ *
+ * Copyright (C) 2008-2009, 2011-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/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct dbgmem_s
+{
+ bool dm_write; /* true: perfrom write operation */
+ void *dm_addr; /* Address to access */
+ uint32_t dm_value; /* Value to write */
+ unsigned int dm_count; /* The number of bytes to access */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mem_parse
+ ****************************************************************************/
+
+int mem_parse(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv,
+ struct dbgmem_s *mem)
+{
+ char *pcvalue = strchr(argv[1], '=');
+ unsigned long lvalue = 0;
+
+ /* Check if we are writing a value */
+
+ if (pcvalue)
+ {
+ *pcvalue = '\0';
+ pcvalue++;
+
+ lvalue = (unsigned long)strtol(pcvalue, NULL, 16);
+ if (lvalue > 0xffffffff)
+ {
+ 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 = (void*)((uintptr_t)strtol(argv[1], NULL, 16));
+
+ /* Get the number of bytes to access */
+
+ if (argc > 2)
+ {
+ mem->dm_count = (unsigned int)strtol(argv[2], NULL, 16);
+ }
+ else
+ {
+ mem->dm_count = 1;
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_mb
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_MB
+int cmd_mb(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct dbgmem_s mem;
+ volatile uint8_t *ptr;
+ int ret;
+ int i;
+
+ 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_output(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, char **argv)
+{
+ struct dbgmem_s mem;
+ volatile uint16_t *ptr;
+ int ret;
+ int i;
+
+ 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_output(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, char **argv)
+{
+ struct dbgmem_s mem;
+ volatile uint32_t *ptr;
+ int ret;
+ int i;
+
+ 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, const char *msg,
+ 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
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_XD
+int cmd_xd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ FAR char *addr;
+ FAR char *endptr;
+ int nbytes;
+
+ addr = (char*)((uintptr_t)strtol(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
diff --git a/apps/nshlib/nsh_ddcmd.c b/apps/nshlib/nsh_ddcmd.c
new file mode 100644
index 000000000..40a3710b1
--- /dev/null
+++ b/apps/nshlib/nsh_ddcmd.c
@@ -0,0 +1,643 @@
+/****************************************************************************
+ * apps/nshlib/nsh_ddcmd.c
+ *
+ * Copyright (C) 2008-2009, 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/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 <nuttx/fs/fs.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_NSH_DISABLE_DD)
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* If no sector size is specified wity 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
+
+/* Function pointer calls are only need if block drivers are supported
+ * (or, rather, if mount points are supported in the file system)
+ */
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+# define DD_INFD ((dd)->inf.fd)
+# define DD_INHANDLE ((dd)->inf.handle)
+# define DD_OUTFD ((dd)->outf.fd)
+# define DD_OUTHANDLE ((dd)->outf.handle)
+# define DD_READ(dd) ((dd)->infread(dd))
+# define DD_WRITE(dd) ((dd)->outfwrite(dd))
+# define DD_INCLOSE(dd) ((dd)->infclose(dd))
+# define DD_OUTCLOSE(dd) ((dd)->outfclose(dd))
+#else
+# define DD_INFD ((dd)->infd)
+# undef DD_INHANDLE
+# define DD_OUTFD ((dd)->outfd)
+# undef DD_OUTHANDLE
+# define DD_READ(dd) dd_readch(dd)
+# define DD_WRITE(dd) dd_writech(dd)
+# define DD_INCLOSE(dd) dd_infclosech(dd)
+# define DD_OUTCLOSE(dd) dd_outfclosech(dd)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct dd_s
+{
+ FAR struct nsh_vtbl_s *vtbl;
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ union
+ {
+ FAR void *handle; /* BCH lib handle for block device*/
+ int fd; /* File descriptor of the character device */
+ } inf;
+#else
+ int infd; /* File descriptor of the input device */
+#endif
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ union
+ {
+ FAR void *handle; /* BCH lib handle for block device*/
+ int fd; /* File descriptor of the character device */
+ } outf;
+#else
+ int outfd; /* File descriptor of the output device */
+#endif
+
+ 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 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 */
+
+ /* Function pointers to handle differences between block and character devices */
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ int (*infread)(struct dd_s *dd);
+ void (*infclose)(struct dd_s *dd);
+ int (*outfwrite)(struct dd_s *dd);
+ void (*outfclose)(struct dd_s *dd);
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const char g_dd[] = "dd";
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: dd_outfcloseblk
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static void dd_outfcloseblk(struct dd_s *dd)
+{
+ (void)bchlib_teardown(DD_OUTHANDLE);
+}
+#endif
+
+
+/****************************************************************************
+ * Name: dd_outfclosech
+ ****************************************************************************/
+
+static void dd_outfclosech(struct dd_s *dd)
+{
+ (void)close(DD_OUTFD);
+}
+
+/****************************************************************************
+ * Name: dd_infcloseblk
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static void dd_infcloseblk(struct dd_s *dd)
+{
+ (void)bchlib_teardown(DD_INHANDLE);
+}
+#endif
+
+/****************************************************************************
+ * Name: dd_infclosech
+ ****************************************************************************/
+
+static void dd_infclosech(struct dd_s *dd)
+{
+ (void)close(DD_INFD);
+}
+
+/****************************************************************************
+ * Name: dd_writeblk
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static int dd_writeblk(struct dd_s *dd)
+{
+ ssize_t nbytes;
+ off_t offset = (dd->sector - dd->skip) * dd->sectsize;
+
+ /* Write the sector at the specified offset */
+
+ nbytes = bchlib_write(DD_OUTHANDLE, (char*)dd->buffer, offset, dd->sectsize);
+ if (nbytes < 0)
+ {
+ /* bchlib_write return -EFBIG on attempts to write past the end of
+ * the device.
+ */
+
+ if (nbytes == -EFBIG)
+ {
+ dd->eof = true; /* Set end-of-file */
+ }
+ else
+ {
+ FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
+ nsh_output(vtbl, g_fmtcmdfailed, g_dd, "bshlib_write", NSH_ERRNO_OF(-nbytes));
+ return ERROR;
+ }
+ }
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: dd_writech
+ ****************************************************************************/
+
+static int dd_writech(struct dd_s *dd)
+{
+ 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_output(vtbl, g_fmtcmdfailed, g_dd, "write", NSH_ERRNO_OF(-nbytes));
+ return ERROR;
+ }
+
+ written += nbytes;
+ buffer += nbytes;
+ }
+ while (written < dd->sectsize);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: dd_readblk
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static int dd_readblk(struct dd_s *dd)
+{
+ ssize_t nbytes;
+ off_t offset = dd->sector * dd->sectsize;
+
+ nbytes = bchlib_read(DD_INHANDLE, (char*)dd->buffer, offset, dd->sectsize);
+ if (nbytes < 0)
+ {
+ FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
+ nsh_output(vtbl, g_fmtcmdfailed, g_dd, "bshlib_read", NSH_ERRNO_OF(-nbytes));
+ return ERROR;
+ }
+
+ /* bchlib_read return 0 on attempts to write past the end of the device. */
+
+ dd->nbytes = nbytes;
+ dd->eof = (nbytes == 0);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: dd_readch
+ ****************************************************************************/
+
+static int dd_readch(struct dd_s *dd)
+{
+ 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_output(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
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static int dd_filetype(const char *filename)
+{
+ struct stat sb;
+ int ret;
+
+ /* Get the type of the file */
+
+ ret = stat(filename, &sb);
+ if (ret < 0)
+ {
+ return ERROR; /* Return -1 on failure */
+ }
+
+ return S_ISBLK(sb.st_mode); /* Return true(1) if block, false(0) if char */
+}
+#endif
+
+/****************************************************************************
+ * Name: dd_infopen
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static inline int dd_infopen(const char *name, struct dd_s *dd)
+{
+ FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
+ int ret;
+ int type;
+
+ /* Get the type of the input file */
+
+ type = dd_filetype(name);
+ if (type < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, g_dd, "stat", NSH_ERRNO_OF(-type));
+ return type;
+ }
+
+ /* Open the input file */
+
+ if (!type)
+ {
+ DD_INFD = open(name, O_RDONLY);
+ if (DD_INFD < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
+ return ERROR;
+ }
+
+ dd->infread = dd_readch; /* Character oriented read */
+ dd->infclose = dd_infclosech;
+ }
+ else
+ {
+ ret = bchlib_setup(name, true, &DD_INHANDLE);
+ if (ret < 0)
+ {
+ return ERROR;
+ }
+
+ dd->infread = dd_readblk;
+ dd->infclose = dd_infcloseblk;
+ }
+ return OK;
+}
+#else
+static inline int dd_infopen(const char *name, struct dd_s *dd)
+{
+ DD_INFD = open(name, O_RDONLY);
+ if (DD_INFD < 0)
+ {
+ FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
+ nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
+ return ERROR;
+ }
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: dd_outfopen
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+static inline int dd_outfopen(const char *name, struct dd_s *dd)
+{
+ int type;
+ int ret = OK;
+
+ /* Get the type of the output file */
+
+ type = dd_filetype(name);
+
+ /* Open the block driver for input */
+
+ if (type == true)
+ {
+ ret = bchlib_setup(name, true, &DD_OUTHANDLE);
+ if (ret < 0)
+ {
+ return ERROR;
+ }
+
+ dd->outfwrite = dd_writeblk; /* Block oriented write */
+ dd->outfclose = dd_outfcloseblk;
+ }
+
+ /* Otherwise, the file is character oriented or does not exist */
+
+ else
+ {
+ DD_OUTFD = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (DD_OUTFD < 0)
+ {
+ FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
+ nsh_output(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
+ return ERROR;
+ }
+
+ dd->outfwrite = dd_writech; /* Character oriented write */
+ dd->outfclose = dd_outfclosech;
+ }
+ return OK;
+}
+#else
+static inline int dd_outfopen(const char *name, struct dd_s *dd)
+{
+ DD_OUTFD = open(name, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (DD_OUTFD < 0)
+ {
+ nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO);
+ return ERROR;
+ }
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_dd
+ ****************************************************************************/
+
+int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct dd_s dd;
+ char *infile = NULL;
+ char *outfile = NULL;
+ 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 */
+#ifndef CONFIG_NSH_DISABLE_DD
+ dd.infread = readch; /* Character oriented read */
+ dd.infclose = noclose; /* Don't close stdin */
+#endif
+#endif
+ /* If no OF= option is provided on the command line, then write
+ * to stdout.
+ */
+
+#ifdef CAN_PIPE_FROM_STD
+ DD_OUTDF = 1; /* stdout */
+#ifndef CONFIG_NSH_DISABLE_DD
+ dd.outfwrite = writech; /* Character oriented write */
+ dd.outfclose = noclose; /* Don't close stdout */
+#endif
+#endif
+
+ /* Parse command line parameters */
+
+ for (i = 1; i < argc; i++)
+ {
+ if (strncmp(argv[i], "if=", 3) == 0)
+ {
+ infile = nsh_getfullpath(vtbl, &argv[i][3]);
+ }
+ else if (strncmp(argv[i], "of=", 3) == 0)
+ {
+ 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 || !outfile)
+ {
+ nsh_output(vtbl, g_fmtargrequired, g_dd);
+ goto errout_with_paths;
+ }
+#endif
+
+ if (dd.skip < 0 || dd.skip > dd.nsectors)
+ {
+ nsh_output(vtbl, g_fmtarginvalid, g_dd);
+ goto errout_with_paths;
+ }
+
+ /* Allocate the I/O buffer */
+
+ dd.buffer = malloc(dd.sectsize);
+ if (!dd.buffer)
+ {
+ nsh_output(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 */
+
+ 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;
+
+errout_with_outf:
+ DD_INCLOSE(&dd);
+errout_with_inf:
+ DD_OUTCLOSE(&dd);
+ free(dd.buffer);
+errout_with_paths:
+ if (infile)
+ {
+ free(infile);
+ }
+ if (outfile)
+ {
+ free(outfile);
+ }
+ return ret;
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS && !CONFIG_NSH_DISABLE_DD */
+
diff --git a/apps/nshlib/nsh_envcmds.c b/apps/nshlib/nsh_envcmds.c
new file mode 100644
index 000000000..07b775517
--- /dev/null
+++ b/apps/nshlib/nsh_envcmds.c
@@ -0,0 +1,338 @@
+/****************************************************************************
+ * apps/nshlib/nsh_envcmds.c
+ *
+ * Copyright (C) 2007-2009, 2011-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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+static const char g_pwd[] = "PWD";
+static const char g_oldpwd[] = "OLDPWD";
+static const char g_home[] = CONFIG_LIB_HOMEDIR;
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_getwd
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(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)
+ {
+ val = g_home;
+ }
+ return val;
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_getdirpath
+ ****************************************************************************/
+
+static inline char *nsh_getdirpath(FAR struct nsh_vtbl_s *vtbl,
+ const char *dirpath, const char *relpath)
+{
+ char *alloc;
+ int len;
+
+ /* Handle the special case where the dirpath is simply "/" */
+
+ if (strcmp(dirpath, "/") == 0)
+ {
+ len = strlen(relpath) + 2;
+ alloc = (char*)malloc(len);
+ if (alloc)
+ {
+ sprintf(alloc, "/%s", relpath);
+ }
+ }
+ else
+ {
+ len = strlen(dirpath) + strlen(relpath) + 2;
+ alloc = (char*)malloc(len);
+ if (alloc)
+ {
+ sprintf(alloc, "%s/%s", dirpath, relpath);
+ }
+ }
+
+ if (!alloc)
+ {
+ nsh_output(vtbl, g_fmtcmdoutofmemory, "nsh_getdirpath");
+ }
+ return alloc;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_getwd
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+FAR const char *nsh_getcwd(void)
+{
+ return nsh_getwd(g_pwd);
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_getfullpath
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+char *nsh_getfullpath(FAR struct nsh_vtbl_s *vtbl, 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
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+void nsh_freefullpath(char *relpath)
+{
+ if (relpath)
+ {
+ free(relpath);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_cd
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+#ifndef CONFIG_NSH_DISABLE_CD
+int cmd_cd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ const char *path = argv[1];
+ char *alloc = NULL;
+ 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 workding directory */
+
+ ret = chdir(path);
+ if (ret != 0)
+ {
+ nsh_output(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;
+
+ /* echo each argument, separated by a space as it must have been on the
+ * command line
+ */
+
+ for (i = 1; i < argc; i++)
+ {
+ nsh_output(vtbl, "%s ", argv[i]);
+ }
+ nsh_output(vtbl, "\n");
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_pwd
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(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_DISABLE_ENVIRON
+#ifndef CONFIG_NSH_DISABLE_SET
+int cmd_set(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ int ret = setenv(argv[1], argv[2], TRUE);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "setenv", NSH_ERRNO);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_unset
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_ENVIRON
+#ifndef CONFIG_NSH_DISABLE_UNSET
+int cmd_unset(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ int ret = unsetenv(argv[1]);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unsetenv", NSH_ERRNO);
+ }
+ return ret;
+}
+#endif
+#endif
diff --git a/apps/nshlib/nsh_fscmds.c b/apps/nshlib/nsh_fscmds.c
new file mode 100644
index 000000000..1a9f2eb57
--- /dev/null
+++ b/apps/nshlib/nsh_fscmds.c
@@ -0,0 +1,1299 @@
+/****************************************************************************
+ * apps/nshlib/nsh_fscmds.c
+ *
+ * Copyright (C) 2007-2009, 2011-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/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+# include <sys/stat.h>
+# include <fcntl.h>
+# if !defined(CONFIG_DISABLE_MOUNTPOINT)
+# ifdef CONFIG_FS_READABLE /* Need at least one filesytem in configuration */
+# include <sys/mount.h>
+# include <nuttx/ramdisk.h>
+# endif
+# ifdef CONFIG_FS_FAT
+# include <nuttx/fs/mkfatfs.h>
+# endif
+# ifdef CONFIG_NFS
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <nuttx/fs/nfs.h>
+# endif
+# ifdef CONFIG_RAMLOG_SYSLOG
+# include <nuttx/ramlog.h>
+# endif
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <limits.h>
+#include <libgen.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define LSFLAGS_SIZE 1
+#define LSFLAGS_LONG 2
+#define LSFLAGS_RECURSIVE 4
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef int (*direntry_handler_t)(FAR struct nsh_vtbl_s *, const char *,
+ struct dirent *, void *);
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Common buffer for file I/O. Note the use of this common buffer precludes
+ * multiple copies of NSH running concurrently. It should be allocated per
+ * NSH instance and retained in the "vtbl" as is done for the telnet
+ * connection.
+ */
+
+static char g_iobuffer[IOBUFFERSIZE];
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trim_dir
+ ****************************************************************************/
+
+static void trim_dir(char *arg)
+{
+ /* Skip any trailing '/' characters (unless it is also the leading '/') */
+
+ int len = strlen(arg) - 1;
+ while (len > 0 && arg[len] == '/')
+ {
+ arg[len] = '\0';
+ len--;
+ }
+}
+
+/****************************************************************************
+ * Name: nsh_getdirpath
+ ****************************************************************************/
+
+static char *nsh_getdirpath(const char *path, const char *file)
+{
+ /* Handle the case where all that is left is '/' */
+
+ if (strcmp(path, "/") == 0)
+ {
+ sprintf(g_iobuffer, "/%s", file);
+ }
+ else
+ {
+ sprintf(g_iobuffer, "%s/%s", path, file);
+ }
+
+ g_iobuffer[PATH_MAX] = '\0';
+ return strdup(g_iobuffer);
+}
+
+/****************************************************************************
+ * Name: foreach_direntry
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+static int foreach_direntry(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *dirpath,
+ direntry_handler_t handler, void *pvarg)
+{
+ DIR *dirp;
+ int ret = OK;
+
+ /* Trim trailing '/' from directory names */
+
+#ifdef CONFIG_NSH_FULLPATH
+ trim_dir(arg);
+#endif
+
+ /* Open the directory */
+
+ dirp = opendir(dirpath);
+
+ if (!dirp)
+ {
+ /* Failed to open the directory */
+
+ nsh_output(vtbl, g_fmtnosuch, cmd, "directory", dirpath);
+ return ERROR;
+ }
+
+ /* Read each directory entry */
+
+ for (;;)
+ {
+ struct dirent *entryp = readdir(dirp);
+ if (!entryp)
+ {
+ /* 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: ls_specialdir
+ ****************************************************************************/
+
+static inline int ls_specialdir(const char *dir)
+{
+ /* '.' and '..' directories are not listed like normal directories */
+
+ return (strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0);
+}
+
+/****************************************************************************
+ * Name: ls_handler
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+static int ls_handler(FAR struct nsh_vtbl_s *vtbl, const char *dirpath, struct dirent *entryp, void *pvarg)
+{
+ unsigned int lsflags = (unsigned int)pvarg;
+ int ret;
+
+ /* Check if any options will require that we stat the file */
+
+ if ((lsflags & (LSFLAGS_SIZE|LSFLAGS_LONG)) != 0)
+ {
+ struct stat buf;
+ char *fullpath = nsh_getdirpath(dirpath, entryp->d_name);
+
+ /* Yes, stat the file */
+
+ ret = stat(fullpath, &buf);
+ free(fullpath);
+ if (ret != 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, "ls", "stat", NSH_ERRNO);
+ return ERROR;
+ }
+
+ if ((lsflags & LSFLAGS_LONG) != 0)
+ {
+ char details[] = "----------";
+ if (S_ISDIR(buf.st_mode))
+ {
+ details[0]='d';
+ }
+ else if (S_ISCHR(buf.st_mode))
+ {
+ details[0]='c';
+ }
+ else if (S_ISBLK(buf.st_mode))
+ {
+ details[0]='b';
+ }
+
+ if ((buf.st_mode & S_IRUSR) != 0)
+ {
+ details[1]='r';
+ }
+
+ if ((buf.st_mode & S_IWUSR) != 0)
+ {
+ details[2]='w';
+ }
+
+ if ((buf.st_mode & S_IXUSR) != 0)
+ {
+ details[3]='x';
+ }
+
+ if ((buf.st_mode & S_IRGRP) != 0)
+ {
+ details[4]='r';
+ }
+
+ if ((buf.st_mode & S_IWGRP) != 0)
+ {
+ details[5]='w';
+ }
+
+ if ((buf.st_mode & S_IXGRP) != 0)
+ {
+ details[6]='x';
+ }
+
+ if ((buf.st_mode & S_IROTH) != 0)
+ {
+ details[7]='r';
+ }
+
+ if ((buf.st_mode & S_IWOTH) != 0)
+ {
+ details[8]='w';
+ }
+
+ if ((buf.st_mode & S_IXOTH) != 0)
+ {
+ details[9]='x';
+ }
+
+ nsh_output(vtbl, " %s", details);
+ }
+
+ if ((lsflags & LSFLAGS_SIZE) != 0)
+ {
+ nsh_output(vtbl, "%8d", buf.st_size);
+ }
+ }
+
+ /* then provide the filename that is common to normal and verbose output */
+
+#ifdef CONFIG_NSH_FULLPATH
+ nsh_output(vtbl, " %s/%s", arg, entryp->d_name);
+#else
+ nsh_output(vtbl, " %s", entryp->d_name);
+#endif
+
+ if (DIRENT_ISDIRECTORY(entryp->d_type) && !ls_specialdir(entryp->d_name))
+ {
+ nsh_output(vtbl, "/\n");
+ }
+ else
+ {
+ nsh_output(vtbl, "\n");
+ }
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: ls_recursive
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+static int ls_recursive(FAR struct nsh_vtbl_s *vtbl, const char *dirpath,
+ struct dirent *entryp, void *pvarg)
+{
+ int ret = OK;
+
+ /* Is this entry a directory (and not one of the special directories, . and ..)? */
+
+ if (DIRENT_ISDIRECTORY(entryp->d_type) && !ls_specialdir(entryp->d_name))
+ {
+ /* Yes.. */
+
+ char *newpath;
+ newpath = nsh_getdirpath(dirpath, entryp->d_name);
+
+ /* List the directory contents */
+
+ nsh_output(vtbl, "%s:\n", newpath);
+
+ /* Traverse the directory */
+
+ ret = foreach_direntry(vtbl, "ls", newpath, ls_handler, pvarg);
+ if (ret == 0)
+ {
+ /* Then recurse to list each directory within the directory */
+
+ ret = foreach_direntry(vtbl, "ls", newpath, ls_recursive, pvarg);
+ free(newpath);
+ }
+ }
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cat_common
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_CAT
+static int cat_common(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR const char *filename)
+{
+ char buffer[IOBUFFERSIZE];
+ int fd;
+ int ret = OK;
+
+ /* Open the file for reading */
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", 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) */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if (errval == EINTR)
+ {
+ nsh_output(vtbl, g_fmtsignalrecvd, cmd);
+ }
+ else
+#endif
+ {
+ nsh_output(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, nbytesread);
+ if (n < 0)
+ {
+ int errval = errno;
+
+ /* EINTR is not an error (but will stop stop the cat) */
+
+ #ifndef CONFIG_DISABLE_SIGNALS
+ if (errval == EINTR)
+ {
+ nsh_output(vtbl, g_fmtsignalrecvd, cmd);
+ }
+ else
+#endif
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "write", NSH_ERRNO);
+ }
+
+ ret = ERROR;
+ break;
+ }
+ else
+ {
+ nbyteswritten += n;
+ }
+ }
+ }
+
+ /* Otherwise, it is the end of file */
+
+ else
+ {
+ break;
+ }
+ }
+
+ (void)close(fd);
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_cat
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_CAT
+int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *fullpath;
+ int i;
+ int ret = OK;
+
+ /* Loop for each file name on the command line */
+
+ for (i = 1; i < argc && ret == OK; i++)
+ {
+ /* Get the fullpath to the file */
+
+ fullpath = nsh_getfullpath(vtbl, argv[i]);
+ if (!fullpath)
+ {
+ ret = ERROR;
+ }
+ else
+ {
+ /* Dump the file to the console */
+
+ ret = cat_common(vtbl, argv[0], fullpath);
+
+ /* Free the allocated full path */
+
+ nsh_freefullpath(fullpath);
+ }
+ }
+
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_dmesg
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SYSLOG) && \
+ defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_NSH_DISABLE_DMESG)
+int cmd_dmesg(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return cat_common(vtbl, argv[0], CONFIG_SYSLOG_DEVPATH);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_cp
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_CP
+int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct stat buf;
+ char *srcpath = NULL;
+ char *destpath = NULL;
+ char *allocpath = NULL;
+ int oflags = O_WRONLY|O_CREAT|O_TRUNC;
+ int rdfd;
+ int wrfd;
+ int ret = ERROR;
+
+ /* Get the full path to the source file */
+
+ srcpath = nsh_getfullpath(vtbl, argv[1]);
+ if (!srcpath)
+ {
+ goto errout;
+ }
+
+ /* Open the source file for reading */
+
+ rdfd = open(srcpath, O_RDONLY);
+ if (rdfd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ goto errout_with_srcpath;
+ }
+
+ /* Get the full path to the destination file or directory */
+
+ destpath = nsh_getfullpath(vtbl, argv[2]);
+ if (!destpath)
+ {
+ goto errout_with_rdfd;
+ }
+
+ /* Check if the destination is a directory */
+
+ ret = stat(destpath, &buf);
+ if (ret == 0)
+ {
+ /* Something exists here... is it a directory? */
+
+ if (S_ISDIR(buf.st_mode))
+ {
+ /* Yes, it is a directory. Remove any trailing '/' characters from the path */
+
+ trim_dir(argv[2]);
+
+ /* Construct the full path to the new file */
+
+ allocpath = nsh_getdirpath(argv[2], basename(argv[1]) );
+ if (!allocpath)
+ {
+ nsh_output(vtbl, g_fmtcmdoutofmemory, argv[0]);
+ goto errout_with_destpath;
+ }
+
+ /* Open then dest for writing */
+
+ nsh_freefullpath(destpath);
+ destpath = allocpath;
+ }
+ else if (!S_ISREG(buf.st_mode))
+ {
+ /* Maybe it is a driver? */
+
+ oflags = O_WRONLY;
+ }
+ }
+
+ /* Now open the destination */
+
+ wrfd = open(destpath, oflags, 0666);
+ if (wrfd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ goto errout_with_allocpath;
+ }
+
+ /* Now copy the file */
+
+ for (;;)
+ {
+ int nbytesread;
+ int nbyteswritten;
+
+ do
+ {
+ nbytesread = read(rdfd, g_iobuffer, IOBUFFERSIZE);
+ if (nbytesread == 0)
+ {
+ /* End of file */
+
+ ret = OK;
+ goto errout_with_wrfd;
+ }
+ else if (nbytesread < 0)
+ {
+ /* EINTR is not an error (but will still stop the copy) */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if (errno == EINTR)
+ {
+ nsh_output(vtbl, g_fmtsignalrecvd, argv[0]);
+ }
+ else
+#endif
+ {
+ /* Read error */
+
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "read", NSH_ERRNO);
+ }
+ goto errout_with_wrfd;
+ }
+ }
+ while (nbytesread <= 0);
+
+ do
+ {
+ nbyteswritten = write(wrfd, g_iobuffer, nbytesread);
+ if (nbyteswritten >= 0)
+ {
+ nbytesread -= nbyteswritten;
+ }
+ else
+ {
+ /* EINTR is not an error (but will still stop the copy) */
+
+#ifndef CONFIG_DISABLE_SIGNALS
+ if (errno == EINTR)
+ {
+ nsh_output(vtbl, g_fmtsignalrecvd, argv[0]);
+ }
+ else
+#endif
+ {
+ /* Read error */
+
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "write", NSH_ERRNO);
+ }
+ goto errout_with_wrfd;
+ }
+ }
+ while (nbytesread > 0);
+ }
+
+errout_with_wrfd:
+ close(wrfd);
+
+errout_with_allocpath:
+ if (allocpath)
+ {
+ free(allocpath);
+ }
+
+errout_with_destpath:
+ if (destpath && !allocpath)
+ {
+ nsh_freefullpath(destpath);
+ }
+
+errout_with_rdfd:
+ close(rdfd);
+
+errout_with_srcpath:
+ if (srcpath)
+ {
+ nsh_freefullpath(srcpath);
+ }
+errout:
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_losetup
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)
+#ifndef CONFIG_NSH_DISABLE_LOSETUP
+int cmd_losetup(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *loopdev = NULL;
+ char *filepath = NULL;
+ bool teardown = false;
+ bool readonly = false;
+ off_t offset = 0;
+ bool badarg = false;
+ int ret = ERROR;
+ int option;
+
+ /* Get the losetup options: Two forms are supported:
+ *
+ * losetup -d <loop-device>
+ * losetup [-o <offset>] [-r] <loop-device> <filename>
+ *
+ * NOTE that the -o and -r options are accepted with the -d option, but
+ * will be ignored.
+ */
+
+ while ((option = getopt(argc, argv, "d:o:r")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'd':
+ loopdev = nsh_getfullpath(vtbl, optarg);
+ teardown = true;
+ break;
+
+ case 'o':
+ offset = atoi(optarg);
+ break;
+
+ case 'r':
+ readonly = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ badarg = true;
+ break;
+ }
+ }
+
+ /* If a bad argument was encountered, then return without processing the command */
+
+ if (badarg)
+ {
+ goto errout_with_paths;
+ }
+
+ /* If this is not a tear down operation, then additional command line
+ * parameters are required.
+ */
+
+ if (!teardown)
+ {
+ /* There must be two arguments on the command line after the options */
+
+ if (optind + 1 < argc)
+ {
+ loopdev = nsh_getfullpath(vtbl, argv[optind]);
+ optind++;
+
+ filepath = nsh_getfullpath(vtbl, argv[optind]);
+ optind++;
+ }
+ else
+ {
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ goto errout_with_paths;
+ }
+ }
+
+ /* There should be nothing else on the command line */
+
+ if (optind < argc)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ goto errout_with_paths;
+ }
+
+ /* Perform the teardown operation */
+
+ if (teardown)
+ {
+ /* Tear down the loop device. */
+
+ ret = loteardown(loopdev);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "loteardown", NSH_ERRNO_OF(-ret));
+ goto errout_with_paths;
+ }
+ }
+ else
+ {
+ /* Set up the loop device */
+
+ ret = losetup(loopdev, filepath, 512, offset, readonly);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "losetup", NSH_ERRNO_OF(-ret));
+ goto errout_with_paths;
+ }
+ }
+
+ /* Free memory */
+
+errout_with_paths:
+ if (loopdev)
+ {
+ free(loopdev);
+ }
+
+ if (filepath)
+ {
+ free(filepath);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_ls
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_LS
+int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ const char *relpath;
+ unsigned int lsflags = 0;
+ char *fullpath;
+ bool badarg = false;
+ int ret;
+
+ /* Get the ls options */
+
+ int option;
+ while ((option = getopt(argc, argv, "lRs")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'l':
+ lsflags |= (LSFLAGS_SIZE|LSFLAGS_LONG);
+ break;
+
+ case 'R':
+ lsflags |= LSFLAGS_RECURSIVE;
+ break;
+
+ case 's':
+ lsflags |= LSFLAGS_SIZE;
+ break;
+
+ case '?':
+ default:
+ nsh_output(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 argument after the options */
+
+ if (optind + 1 < argc)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ return ERROR;
+ }
+ else if (optind >= argc)
+ {
+#ifndef CONFIG_DISABLE_ENVIRON
+ relpath = nsh_getcwd();
+#else
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ return ERROR;
+#endif
+ }
+ else
+ {
+ relpath = argv[optind];
+ }
+
+ /* Get the fullpath to the directory */
+
+ fullpath = nsh_getfullpath(vtbl, relpath);
+ if (!fullpath)
+ {
+ return ERROR;
+ }
+
+ /* List the directory contents */
+
+ nsh_output(vtbl, "%s:\n", fullpath);
+ ret = foreach_direntry(vtbl, "ls", fullpath, ls_handler, (void*)lsflags);
+ if (ret == OK && (lsflags & LSFLAGS_RECURSIVE) != 0)
+ {
+ /* Then recurse to list each directory within the directory */
+
+ ret = foreach_direntry(vtbl, "ls", fullpath, ls_recursive, (void*)lsflags);
+ }
+ nsh_freefullpath(fullpath);
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_mkdir
+ ****************************************************************************/
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#ifndef CONFIG_NSH_DISABLE_MKDIR
+int cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *fullpath = nsh_getfullpath(vtbl, argv[1]);
+ int ret = ERROR;
+
+ if (fullpath)
+ {
+ ret = mkdir(fullpath, 0777);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkdir", NSH_ERRNO);
+ }
+ nsh_freefullpath(fullpath);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_mkfatfs
+ ****************************************************************************/
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_FAT)
+#ifndef CONFIG_NSH_DISABLE_MKFATFS
+int cmd_mkfatfs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct fat_format_s fmt = FAT_FORMAT_INITIALIZER;
+ char *fullpath = nsh_getfullpath(vtbl, argv[1]);
+ int ret = ERROR;
+
+ if (fullpath)
+ {
+ ret = mkfatfs(fullpath, &fmt);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfatfs", NSH_ERRNO);
+ }
+ nsh_freefullpath(fullpath);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_mkfifo
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_MKFIFO
+int cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *fullpath = nsh_getfullpath(vtbl, argv[1]);
+ int ret = ERROR;
+
+ if (fullpath)
+ {
+ ret = mkfifo(fullpath, 0777);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mkfifo", NSH_ERRNO);
+ }
+ nsh_freefullpath(fullpath);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_mkrd
+ ****************************************************************************/
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#ifndef CONFIG_NSH_DISABLE_MKRD
+int cmd_mkrd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ const char *fmt;
+ uint8_t *buffer;
+ uint32_t nsectors;
+ bool badarg = false;
+ int sectsize = 512;
+ int minor = 0;
+ int ret;
+
+ /* Get the mkrd options */
+
+ int option;
+ while ((option = getopt(argc, argv, ":m:s:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'm':
+ minor = atoi(optarg);
+ if (minor < 0 || minor > 255)
+ {
+ nsh_output(vtbl, g_fmtargrange, argv[0]);
+ badarg = true;
+ }
+ break;
+
+ case 's':
+ sectsize = atoi(optarg);
+ if (minor < 0 || minor > 16384)
+ {
+ nsh_output(vtbl, g_fmtargrange, argv[0]);
+ badarg = true;
+ }
+ break;
+
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(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)
+ {
+ nsectors = (uint32_t)atoi(argv[optind]);
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout_with_fmt;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout_with_fmt;
+ }
+
+ /* Allocate the memory backing up the ramdisk */
+
+ buffer = (uint8_t*)malloc(sectsize * nsectors);
+ if (!buffer)
+ {
+ fmt = g_fmtcmdoutofmemory;
+ goto errout_with_fmt;
+ }
+
+#ifdef CONFIG_DEBUG_VERBOSE
+ memset(buffer, 0, sectsize * nsectors);
+#endif
+ dbg("RAMDISK at %p\n", buffer);
+
+ /* Then register the ramdisk */
+
+ ret = ramdisk_register(minor, buffer, nsectors, sectsize, true);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "ramdisk_register", NSH_ERRNO_OF(-ret));
+ free(buffer);
+ return ERROR;
+ }
+ return ret;
+
+errout_with_fmt:
+ nsh_output(vtbl, fmt, argv[0]);
+ return ERROR;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_mv
+ ****************************************************************************/
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#ifndef CONFIG_NSH_DISABLE_MV
+int cmd_mv(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *oldpath;
+ char *newpath;
+ int ret;
+
+ /* Get the full path to the old and new file paths */
+
+ oldpath = nsh_getfullpath(vtbl, argv[1]);
+ if (!oldpath)
+ {
+ return ERROR;
+ }
+
+ newpath = nsh_getfullpath(vtbl, argv[2]);
+ if (!newpath)
+ {
+ nsh_freefullpath(newpath);
+ return ERROR;
+ }
+
+ /* Perform the mount */
+
+ ret = rename(oldpath, newpath);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rename", NSH_ERRNO);
+ }
+
+ /* Free the file paths */
+
+ nsh_freefullpath(oldpath);
+ nsh_freefullpath(newpath);
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_rm
+ ****************************************************************************/
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#ifndef CONFIG_NSH_DISABLE_RM
+int cmd_rm(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *fullpath = nsh_getfullpath(vtbl, argv[1]);
+ int ret = ERROR;
+
+ if (fullpath)
+ {
+ ret = unlink(fullpath);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "unlink", NSH_ERRNO);
+ }
+ nsh_freefullpath(fullpath);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_rmdir
+ ****************************************************************************/
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+#ifndef CONFIG_NSH_DISABLE_RMDIR
+int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *fullpath = nsh_getfullpath(vtbl, argv[1]);
+ int ret = ERROR;
+
+ if (fullpath)
+ {
+ ret = rmdir(fullpath);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rmdir", NSH_ERRNO);
+ }
+ nsh_freefullpath(fullpath);
+ }
+ return ret;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: nsh_script
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT)
+int nsh_script(FAR struct nsh_vtbl_s *vtbl, const char *cmd, const char *path)
+{
+ char *fullpath;
+ FILE *stream;
+ char *buffer;
+ char *pret;
+ int ret = ERROR;
+
+ /* The path to the script may be 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)
+ {
+ /* Open the file containing the script */
+
+ stream = fopen(fullpath, "r");
+ if (!stream)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "fopen", NSH_ERRNO);
+ nsh_freefullpath(fullpath);
+ return ERROR;
+ }
+
+ /* Loop, processing each command line in the script file (or
+ * until an error occurs)
+ */
+
+ do
+ {
+ /* Get the next line of input from the file */
+
+ fflush(stdout);
+ pret = fgets(buffer, CONFIG_NSH_LINELEN, stream);
+ if (pret)
+ {
+ /* Parse process the command. NOTE: this is recursive...
+ * we got to cmd_sh via a call to nsh_parse. So some
+ * considerable amount of stack may be used.
+ */
+
+ ret = nsh_parse(vtbl, buffer);
+ }
+ }
+ while (pret && ret == OK);
+ fclose(stream);
+ }
+
+ nsh_freefullpath(fullpath);
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_sh
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT)
+#ifndef CONFIG_NSH_DISABLE_SH
+int cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return nsh_script(vtbl, argv[0], argv[1]);
+}
+#endif
+#endif
diff --git a/apps/nshlib/nsh_init.c b/apps/nshlib/nsh_init.c
new file mode 100644
index 000000000..7c7e78ea1
--- /dev/null
+++ b/apps/nshlib/nsh_init.c
@@ -0,0 +1,102 @@
+/****************************************************************************
+ * apps/nshlib/nsh_init.c
+ *
+ * Copyright (C) 2007-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 "nsh.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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)
+{
+ /* Mount the /etc filesystem */
+
+ (void)nsh_romfsetc();
+
+ /* Perform architecture-specific initialization (if available) */
+
+ (void)nsh_archinitialize();
+
+ /* Bring up the network */
+
+ (void)nsh_netinit();
+}
+
diff --git a/apps/nshlib/nsh_mmcmds.c b/apps/nshlib/nsh_mmcmds.c
new file mode 100644
index 000000000..545ae60ad
--- /dev/null
+++ b/apps/nshlib/nsh_mmcmds.c
@@ -0,0 +1,96 @@
+/****************************************************************************
+ * apps/nshlib/nsh_mmcmds.c
+ *
+ * Copyright (C) 2011-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 <stdlib.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_free
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_FREE
+int cmd_free(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct mallinfo mem;
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ mem = mallinfo();
+#else
+ (void)mallinfo(&mem);
+#endif
+
+ nsh_output(vtbl, " total used free largest\n");
+ nsh_output(vtbl, "Mem: %11d%11d%11d%11d\n",
+ mem.arena, mem.uordblks, mem.fordblks, mem.mxordblk);
+
+ return OK;
+}
+#endif /* !CONFIG_NSH_DISABLE_FREE */
diff --git a/apps/nshlib/nsh_mntcmds.c b/apps/nshlib/nsh_mntcmds.c
new file mode 100644
index 000000000..690d027ca
--- /dev/null
+++ b/apps/nshlib/nsh_mntcmds.c
@@ -0,0 +1,434 @@
+/****************************************************************************
+ * apps/nshlib/nsh_mntcmds.c
+ *
+ * Copyright (C) 2007-2009, 2011-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/types.h>
+#include <sys/mount.h>
+#include <sys/statfs.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: df_handler
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT)
+static int df_handler(FAR const char *mountpoint,
+ FAR struct statfs *statbuf, FAR void *arg)
+{
+ FAR struct nsh_vtbl_s *vtbl = (FAR struct nsh_vtbl_s *)arg;
+
+ DEBUGASSERT(mountpoint && statbuf && vtbl);
+
+ nsh_output(vtbl, "%6ld %8ld %8ld %8ld %s\n",
+ statbuf->f_bsize, statbuf->f_blocks,
+ statbuf->f_blocks - statbuf->f_bavail, statbuf->f_bavail,
+ mountpoint);
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: mount_handler
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT)
+static int mount_handler(FAR const char *mountpoint,
+ FAR struct statfs *statbuf, FAR void *arg)
+{
+ FAR struct nsh_vtbl_s *vtbl = (FAR struct nsh_vtbl_s *)arg;
+ FAR const char *fstype;
+
+ DEBUGASSERT(mountpoint && statbuf && vtbl);
+
+ /* Get the file system type */
+
+ switch (statbuf->f_type)
+ {
+#ifdef CONFIG_FS_FAT
+ case MSDOS_SUPER_MAGIC:
+ fstype = "vfat";
+ break;
+#endif
+
+#ifdef CONFIG_FS_ROMFS
+ case ROMFS_MAGIC:
+ fstype = "romfs";
+ break;
+#endif
+
+#ifdef CONFIG_APPS_BINDIR
+ case BINFS_MAGIC:
+ fstype = "bindir";
+ break;
+#endif
+
+#ifdef CONFIG_FS_NXFFS
+ case NXFFS_MAGIC:
+ fstype = "nxffs";
+ break;
+#endif
+
+#ifdef CONFIG_NFS
+ case NFS_SUPER_MAGIC:
+ fstype = "nfs";
+ break;
+#endif
+
+ default:
+ fstype = "Unrecognized";
+ break;
+ }
+
+ nsh_output(vtbl, " %s type %s\n", mountpoint, fstype);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: mount_show
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT)
+static inline int mount_show(FAR struct nsh_vtbl_s *vtbl, FAR const char *progname)
+{
+ return foreach_mountpoint(mount_handler, (FAR void *)vtbl);
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_df
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_DF)
+int cmd_df(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ nsh_output(vtbl, " Block Number\n");
+ nsh_output(vtbl, " Size Blocks Used Available Mounted on\n");
+
+ return foreach_mountpoint(df_handler, (FAR void *)vtbl);
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_mount
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_MOUNT)
+int cmd_mount(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ FAR char *source;
+ FAR char *target;
+ FAR char *filesystem = NULL;
+ bool badarg = false;
+ int option;
+ int ret;
+
+ /* The mount command behaves differently if no parameters are provided */
+
+ if (argc < 2)
+ {
+ return mount_show(vtbl, argv[0]);
+ }
+
+ /* 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, ":t:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 't':
+ filesystem = optarg;
+ break;
+
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(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 are two required arguments after the options: the source and target
+ * paths.
+ */
+
+ if (optind + 2 < argc)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, argv[0]);
+ return ERROR;
+ }
+ else if (optind + 2 > argc)
+ {
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ return ERROR;
+ }
+
+ /* While the above parsing for the -t argument looks nice, the -t argument
+ * not really optional.
+ */
+
+ if (!filesystem)
+ {
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ return ERROR;
+ }
+
+ /* The source and target paths might be relative to the current
+ * working directory.
+ */
+
+ source = nsh_getfullpath(vtbl, argv[optind]);
+ if (!source)
+ {
+ return ERROR;
+ }
+
+ target = nsh_getfullpath(vtbl, argv[optind+1]);
+ if (!target)
+ {
+ nsh_freefullpath(source);
+ return ERROR;
+ }
+
+ /* Perform the mount */
+
+ ret = mount(source, target, filesystem, 0, NULL);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "mount", NSH_ERRNO);
+ }
+
+ nsh_freefullpath(source);
+ nsh_freefullpath(target);
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_nfsmount
+ ****************************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !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;
+ bool badarg = false;
+#ifdef CONFIG_NET_IPv6
+ FAR struct sockaddr_in6 *sin;
+ struct in6_addr inaddr;
+#else
+ FAR struct sockaddr_in *sin;
+ struct in_addr inaddr;
+#endif
+ int ret;
+
+ /* If a bad argument was encountered, then return without processing the
+ * command.
+ */
+
+ if (badarg)
+ {
+ return ERROR;
+ }
+
+ /* 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;
+ }
+
+ /* The local mount point path (lpath) might be relative to the current working
+ * directory.
+ */
+
+ lpath = nsh_getfullpath(vtbl, argv[2]);
+ if (!lpath)
+ {
+ return ERROR;
+ }
+
+ /* Get the remote mount point path */
+
+ rpath = argv[3];
+
+ /* Convert the IP address string into its binary form */
+
+#ifdef CONFIG_NET_IPv6
+ ret = inet_pton(AF_INET6, address, &inaddr);
+#else
+ ret = inet_pton(AF_INET, address, &inaddr);
+#endif
+ if (ret != 1)
+ {
+ nsh_freefullpath(lpath);
+ return ERROR;
+ }
+
+ /* Place all of the NFS arguements into the nfs_args structure */
+
+ memset(&data, 0, sizeof(data));
+
+#ifdef CONFIG_NET_IPv6
+ sin = (FAR struct sockaddr_in6 *)&data.addr;
+ sin->sin_family = AF_INET6;
+ sin->sin_port = htons(NFS_PMAPPORT);
+ memcpy(&sin->sin6_addr, &inaddr, sizeof(struct in6_addr));
+ data.addrlen = sizeof(struct sockaddr_in6);
+#else
+ sin = (FAR struct sockaddr_in *)&data.addr;
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(NFS_PMAPPORT);
+ sin->sin_addr = inaddr;
+ data.addrlen = sizeof(struct sockaddr_in);
+#endif
+
+ data.sotype = SOCK_DGRAM;
+ data.path = rpath;
+ data.flags = 0; /* 0=Use all defaults */
+
+ /* Perform the mount */
+
+ ret = mount(NULL, lpath, "nfs", 0, (FAR void *)&data);
+ if (ret < 0)
+ {
+ nsh_output(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 CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !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_output(vtbl, g_fmtcmdfailed, argv[0], "umount", NSH_ERRNO);
+ }
+ nsh_freefullpath(fullpath);
+ }
+
+ return ret;
+}
+#endif
diff --git a/apps/nshlib/nsh_netcmds.c b/apps/nshlib/nsh_netcmds.c
new file mode 100644
index 000000000..cfea5a08a
--- /dev/null
+++ b/apps/nshlib/nsh_netcmds.c
@@ -0,0 +1,864 @@
+/****************************************************************************
+ * apps/nshlib/nsh_netcmds.c
+ *
+ * Copyright (C) 2007-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>
+#ifdef CONFIG_NET
+
+#include <sys/stat.h> /* Needed for open */
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sched.h>
+#include <fcntl.h> /* Needed for open */
+#include <libgen.h> /* Needed for basename */
+#include <errno.h>
+
+#include <nuttx/net/net.h>
+#include <nuttx/clock.h>
+#include <net/ethernet.h>
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arch.h>
+#include <netinet/ether.h>
+
+#ifdef CONFIG_NET_STATISTICS
+# include <nuttx/net/uip/uip.h>
+#endif
+
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
+# include <apps/netutils/uiplib.h>
+#endif
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+# include <apps/netutils/uiplib.h>
+# include <apps/netutils/tftp.h>
+#endif
+
+#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_WGET
+# include <apps/netutils/uiplib.h>
+# include <apps/netutils/webclient.h>
+# endif
+#endif
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define DEFAULT_PING_DATALEN 56
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+struct tftpc_args_s
+{
+ bool binary; /* true:binary ("octect") false:text ("netascii") */
+ bool allocated; /* true: destpath is allocated */
+ char *destpath; /* Path at destination */
+ const char *srcpath; /* Path at src */
+ in_addr_t ipaddr; /* Host IP address */
+};
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
+static uint16_t g_pingid = 0;
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ping_newid
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
+static inline uint16_t ping_newid(void)
+{
+ irqstate_t save = irqsave();
+ uint16_t ret = ++g_pingid;
+ irqrestore(save);
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: uip_statistics
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_STATISTICS) && !defined(CONFIG_NSH_DISABLE_IFCONFIG)
+static inline void uip_statistics(FAR struct nsh_vtbl_s *vtbl)
+{
+ nsh_output(vtbl, "uIP IP ");
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " TCP");
+#endif
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " UDP");
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " ICMP");
+#endif
+ nsh_output(vtbl, "\n");
+
+ /* Received packets */
+
+ nsh_output(vtbl, "Received %04x",uip_stat.ip.recv);
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " %04x",uip_stat.tcp.recv);
+#endif
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " %04x",uip_stat.udp.recv);
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " %04x",uip_stat.icmp.recv);
+#endif
+ nsh_output(vtbl, "\n");
+
+ /* Dropped packets */
+
+ nsh_output(vtbl, "Dropped %04x",uip_stat.ip.drop);
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " %04x",uip_stat.tcp.drop);
+#endif
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " %04x",uip_stat.udp.drop);
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " %04x",uip_stat.icmp.drop);
+#endif
+ nsh_output(vtbl, "\n");
+
+ nsh_output(vtbl, " IP VHL: %04x HBL: %04x\n",
+ uip_stat.ip.vhlerr, uip_stat.ip.hblenerr);
+ nsh_output(vtbl, " LBL: %04x Frg: %04x\n",
+ uip_stat.ip.lblenerr, uip_stat.ip.fragerr);
+
+ nsh_output(vtbl, " Checksum %04x",uip_stat.ip.chkerr);
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " %04x",uip_stat.tcp.chkerr);
+#endif
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " %04x",uip_stat.udp.chkerr);
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " ----");
+#endif
+ nsh_output(vtbl, "\n");
+
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " TCP ACK: %04x SYN: %04x\n",
+ uip_stat.tcp.ackerr, uip_stat.tcp.syndrop);
+ nsh_output(vtbl, " RST: %04x %04x\n",
+ uip_stat.tcp.rst, uip_stat.tcp.synrst);
+#endif
+
+ nsh_output(vtbl, " Type %04x",uip_stat.ip.protoerr);
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " ----");
+#endif
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " ----");
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " %04x",uip_stat.icmp.typeerr);
+#endif
+ nsh_output(vtbl, "\n");
+
+ /* Sent packets */
+
+ nsh_output(vtbl, "Sent ----",uip_stat.ip.sent);
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " %04x",uip_stat.tcp.sent);
+#endif
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " %04x",uip_stat.udp.sent);
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " %04x",uip_stat.icmp.sent);
+#endif
+ nsh_output(vtbl, "\n");
+
+#ifdef CONFIG_NET_TCP
+ nsh_output(vtbl, " Rexmit ---- %04x",uip_stat.tcp.rexmit);
+#ifdef CONFIG_NET_UDP
+ nsh_output(vtbl, " ----");
+#endif
+#ifdef CONFIG_NET_ICMP
+ nsh_output(vtbl, " ----");
+#endif
+ nsh_output(vtbl, "\n");
+#endif
+ nsh_output(vtbl, "\n");
+}
+#else
+# define uip_statistics(vtbl)
+#endif
+
+
+/****************************************************************************
+ * Name: ifconfig_callback
+ ****************************************************************************/
+
+int ifconfig_callback(FAR struct uip_driver_s *dev, void *arg)
+{
+ struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg;
+ struct in_addr addr;
+
+ nsh_output(vtbl, "%s\tHWaddr %s\n", dev->d_ifname, ether_ntoa(&dev->d_mac));
+ addr.s_addr = dev->d_ipaddr;
+ nsh_output(vtbl, "\tIPaddr:%s ", inet_ntoa(addr));
+ addr.s_addr = dev->d_draddr;
+ nsh_output(vtbl, "DRaddr:%s ", inet_ntoa(addr));
+ addr.s_addr = dev->d_netmask;
+ nsh_output(vtbl, "Mask:%s\n\n", inet_ntoa(addr));
+ return OK;
+}
+
+/****************************************************************************
+ * Name: tftpc_parseargs
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+int tftpc_parseargs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv,
+ struct tftpc_args_s *args)
+{
+ FAR const char *fmt = g_fmtarginvalid;
+ bool badarg = false;
+ int option;
+
+ /* Get the ping options */
+
+ memset(args, 0, sizeof(struct tftpc_args_s));
+ while ((option = getopt(argc, argv, ":bnf:h:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'b':
+ args->binary = true;
+ break;
+
+ case 'n':
+ args->binary = false;
+ break;
+
+ case 'f':
+ args->destpath = optarg;
+ break;
+
+ case 'h':
+ if (!uiplib_ipaddrconv(optarg, (FAR unsigned char*)&args->ipaddr))
+ {
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ badarg = true;
+ }
+ break;
+
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(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 one parameter left on the command-line */
+
+ if (optind == argc-1)
+ {
+ args->srcpath = argv[optind];
+ }
+
+ /* optind == argc means that there is nothing left on the command-line */
+
+ else if (optind >= argc)
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ /* optind < argc-1 means that there are too many arguments on the
+ * command-line
+ */
+
+ else
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+
+ /* The HOST IP address is also required */
+
+ if (!args->ipaddr)
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ /* If the destpath was not provided, then we have do a little work. */
+
+ if (!args->destpath)
+ {
+ char *tmp1;
+ char *tmp2;
+
+ /* Copy the srcpath... baseanme might modify it */
+
+ fmt = g_fmtcmdoutofmemory;
+ tmp1 = strdup(args->srcpath);
+ if (!tmp1)
+ {
+ goto errout;
+ }
+
+ /* Get the basename of the srcpath */
+
+ tmp2 = basename(tmp1);
+ if (!tmp2)
+ {
+ free(tmp1);
+ goto errout;
+ }
+
+ /* Use that basename as the destpath */
+
+ args->destpath = strdup(tmp2);
+ free(tmp1);
+ if (!args->destpath)
+ {
+ goto errout;
+ }
+ args->allocated = true;
+ }
+
+ return OK;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ return ERROR;
+}
+#endif
+
+/****************************************************************************
+ * Name: wget_callback
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_WGET
+static void wget_callback(FAR char **buffer, int offset, int datend,
+ FAR int *buflen, FAR void *arg)
+{
+ (void)write((int)arg, &((*buffer)[offset]), datend - offset);
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_get
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_GET
+int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct tftpc_args_s args;
+ char *fullpath;
+
+ /* Parse the input parameter list */
+
+ if (tftpc_parseargs(vtbl, argc, argv, &args) != OK)
+ {
+ return ERROR;
+ }
+
+ /* Get the full path to the local file */
+
+ fullpath = nsh_getfullpath(vtbl, args.srcpath);
+
+ /* Then perform the TFTP get operation */
+
+ if (tftpget(args.srcpath, fullpath, args.ipaddr, args.binary) != OK)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "tftpget", NSH_ERRNO);
+ }
+
+ /* Release any allocated memory */
+
+ if (args.allocated)
+ {
+ free(args.destpath);
+ }
+ free(fullpath);
+ return OK;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_ifconfig
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_IFCONFIG
+int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct in_addr addr;
+ in_addr_t ip;
+
+ /* With one or no arguments, ifconfig simply shows the status of ethernet
+ * device:
+ *
+ * ifconfig
+ * ifconfig [nic_name]
+ */
+
+ if (argc <= 2)
+ {
+ netdev_foreach(ifconfig_callback, vtbl);
+ uip_statistics(vtbl);
+ return OK;
+ }
+
+ /* If both the network interface name and an IP address are supplied as
+ * arguments, then ifconfig will set the address of the ethernet device:
+ *
+ * ifconfig nic_name ip_address
+ */
+
+ /* Set host ip address */
+
+ ip = addr.s_addr = inet_addr(argv[2]);
+ uip_sethostaddr(argv[1], &addr);
+
+ /* Set gateway */
+
+ ip = NTOHL(ip);
+ ip &= ~0x000000ff;
+ ip |= 0x00000001;
+
+ addr.s_addr = HTONL(ip);
+ uip_setdraddr(argv[1], &addr);
+
+ /* Set netmask */
+
+ addr.s_addr = inet_addr("255.255.255.0");
+ uip_setnetmask(argv[1], &addr);
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_ping
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
+#ifndef CONFIG_NSH_DISABLE_PING
+int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ FAR const char *fmt = g_fmtarginvalid;
+ const char *staddr;
+ uip_ipaddr_t ipaddr;
+ uint32_t start;
+ uint32_t next;
+ uint32_t dsec = 10;
+ uint16_t id;
+ bool badarg = false;
+ int count = 10;
+ int option;
+ int seqno;
+ int replies = 0;
+ int elapsed;
+ int tmp;
+ int i;
+
+ /* Get the ping options */
+
+ while ((option = getopt(argc, argv, ":c:i:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'c':
+ count = atoi(optarg);
+ if (count < 1 || count > 10000)
+ {
+ nsh_output(vtbl, g_fmtargrange, argv[0]);
+ badarg = true;
+ }
+ break;
+
+ case 'i':
+ tmp = atoi(optarg);
+ if (tmp < 1 || tmp >= 4294)
+ {
+ nsh_output(vtbl, g_fmtargrange, argv[0]);
+ badarg = true;
+ }
+ else
+ {
+ dsec = 10 * tmp;
+ }
+ break;
+
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(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)
+ {
+ staddr = argv[optind];
+ if (!uiplib_ipaddrconv(staddr, (FAR unsigned char*)&ipaddr))
+ {
+ goto errout;
+ }
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ /* Get the ID to use */
+
+ id = ping_newid();
+
+ /* Loop for the specified count */
+
+ nsh_output(vtbl, "PING %s %d bytes of data\n", staddr, DEFAULT_PING_DATALEN);
+ start = g_system_timer;
+ for (i = 1; i <= count; i++)
+ {
+ /* Send the ECHO request and wait for the response */
+
+ next = g_system_timer;
+ seqno = uip_ping(ipaddr, id, i, DEFAULT_PING_DATALEN, dsec);
+
+ /* Was any response returned? We can tell if a non-negative sequence
+ * number was returned.
+ */
+
+ if (seqno >= 0 && seqno <= i)
+ {
+ /* Get the elpased time from the time that the request was
+ * sent until the response was received. If we got a response
+ * to an earlier request, then fudge the elpased time.
+ */
+
+ elapsed = TICK2MSEC(g_system_timer - next);
+ if (seqno < i)
+ {
+ elapsed += 100*dsec*(i - seqno);
+ }
+
+ /* Report the receipt of the reply */
+
+ nsh_output(vtbl, "%d bytes from %s: icmp_seq=%d time=%d ms\n",
+ DEFAULT_PING_DATALEN, staddr, seqno, elapsed);
+ replies++;
+ }
+
+ /* Wait for the remainder of the interval. If the last seqno<i,
+ * then this is a bad idea... we will probably lose the response
+ * to the current request!
+ */
+
+ elapsed = TICK2DSEC(g_system_timer - next);
+ if (elapsed < dsec)
+ {
+ usleep(100000*dsec);
+ }
+ }
+
+ /* Get the total elapsed time */
+
+ elapsed = TICK2MSEC(g_system_timer - start);
+
+ /* Calculate the percentage of lost packets */
+
+ tmp = (100*(count - replies) + (count >> 1)) / count;
+
+ nsh_output(vtbl, "%d packets transmitted, %d received, %d%% packet loss, time %d ms\n",
+ count, replies, tmp, elapsed);
+ return OK;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ return ERROR;
+}
+#endif
+#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */
+
+/****************************************************************************
+ * Name: cmd_put
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_PUT
+int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct tftpc_args_s args;
+ char *fullpath;
+
+ /* Parse the input parameter list */
+
+ if (tftpc_parseargs(vtbl, argc, argv, &args) != OK)
+ {
+ return ERROR;
+ }
+
+ /* Get the full path to the local file */
+
+ fullpath = nsh_getfullpath(vtbl, args.srcpath);
+
+ /* Then perform the TFTP put operation */
+
+ if (tftpput(fullpath, args.destpath, args.ipaddr, args.binary) != OK)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "tftpput", NSH_ERRNO);
+ }
+
+ /* Release any allocated memory */
+
+ if (args.allocated)
+ {
+ free(args.destpath);
+ }
+ free(fullpath);
+ return OK;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_wget
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0
+#ifndef CONFIG_NSH_DISABLE_WGET
+int cmd_wget(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *localfile = NULL;
+ char *allocfile = NULL;
+ char *buffer = NULL;
+ char *fullpath = NULL;
+ char *url;
+ const char *fmt;
+ bool badarg = false;
+ int option;
+ int fd = -1;
+ int ret;
+
+ /* Get the wget options */
+
+ while ((option = getopt(argc, argv, ":o:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'o':
+ localfile = optarg;
+ break;
+
+ case ':':
+ nsh_output(vtbl, g_fmtargrequired, argv[0]);
+ badarg = true;
+ break;
+
+ case '?':
+ default:
+ nsh_output(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)
+ {
+ url = argv[optind];
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ /* Get the local file name */
+
+ if (!localfile)
+ {
+ allocfile = strdup(url);
+ localfile = basename(allocfile);
+ }
+
+ /* Get the full path to the local file */
+
+ fullpath = nsh_getfullpath(vtbl, localfile);
+
+ /* Open the local file for writing */
+
+ fd = open(fullpath, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "open", NSH_ERRNO);
+ ret = ERROR;
+ goto exit;
+ }
+
+ /* Allocate an I/O buffer */
+
+ buffer = malloc(512);
+ if (!buffer)
+ {
+ fmt = g_fmtcmdoutofmemory;
+ goto errout;
+ }
+
+ /* And perform the wget */
+
+ ret = wget(url, buffer, 512, wget_callback, (FAR void *)fd);
+ if (ret < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "wget", NSH_ERRNO);
+ goto exit;
+ }
+
+ /* Free allocated resources */
+
+exit:
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ if (allocfile)
+ {
+ free(allocfile);
+ }
+ if (fullpath)
+ {
+ free(fullpath);
+ }
+ if (buffer)
+ {
+ free(buffer);
+ }
+ return ret;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ ret = ERROR;
+ goto exit;
+}
+#endif
+#endif
+
+#endif /* CONFIG_NET */
diff --git a/apps/nshlib/nsh_netinit.c b/apps/nshlib/nsh_netinit.c
new file mode 100644
index 000000000..bc845c4ed
--- /dev/null
+++ b/apps/nshlib/nsh_netinit.c
@@ -0,0 +1,171 @@
+/****************************************************************************
+ * apps/nshlib/nsh_netinit.c
+ *
+ * Copyright (C) 2010-2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * This is influenced by similar logic from uIP:
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * 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 of the Institute 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 INSTITUTE 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 INSTITUTE 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 <debug.h>
+
+#include <net/if.h>
+
+#include <apps/netutils/uiplib.h>
+#if defined(CONFIG_NSH_DHCPC)
+# include <apps/netutils/resolv.h>
+# include <apps/netutils/dhcpc.h>
+#endif
+
+#include "nsh.h"
+
+#ifdef CONFIG_NET
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_netinit
+ *
+ * Description:
+ * Initialize the network per the selected NuttX configuration
+ *
+ ****************************************************************************/
+
+int nsh_netinit(void)
+{
+ struct in_addr addr;
+#if defined(CONFIG_NSH_DHCPC)
+ FAR void *handle;
+#endif
+#if defined(CONFIG_NSH_DHCPC) || defined(CONFIG_NSH_NOMAC)
+ uint8_t mac[IFHWADDRLEN];
+#endif
+
+/* Many embedded network interfaces must have a software assigned MAC */
+
+#ifdef CONFIG_NSH_NOMAC
+ mac[0] = 0x00;
+ mac[1] = 0xe0;
+ mac[2] = 0xde;
+ mac[3] = 0xad;
+ mac[4] = 0xbe;
+ mac[5] = 0xef;
+ uip_setmacaddr("eth0", mac);
+#endif
+
+ /* Set up our host address */
+
+#if !defined(CONFIG_NSH_DHCPC)
+ addr.s_addr = HTONL(CONFIG_NSH_IPADDR);
+#else
+ addr.s_addr = 0;
+#endif
+ uip_sethostaddr("eth0", &addr);
+
+ /* Set up the default router address */
+
+ addr.s_addr = HTONL(CONFIG_NSH_DRIPADDR);
+ uip_setdraddr("eth0", &addr);
+
+ /* Setup the subnet mask */
+
+ addr.s_addr = HTONL(CONFIG_NSH_NETMASK);
+ uip_setnetmask("eth0", &addr);
+
+#if defined(CONFIG_NSH_DHCPC)
+ /* Set up the resolver */
+
+ resolv_init();
+#endif
+
+#if defined(CONFIG_NSH_DHCPC)
+ /* Get the MAC address of the NIC */
+
+ uip_getmacaddr("eth0", mac);
+
+ /* Set up the DHCPC modules */
+
+ handle = dhcpc_open(&mac, IFHWADDRLEN);
+
+ /* Get an IP address. Note that there is no logic for renewing the IP address in this
+ * example. The address should be renewed in ds.lease_time/2 seconds.
+ */
+
+ if (handle)
+ {
+ struct dhcpc_state ds;
+ (void)dhcpc_request(handle, &ds);
+ uip_sethostaddr("eth1", &ds.ipaddr);
+ if (ds.netmask.s_addr != 0)
+ {
+ uip_setnetmask("eth0", &ds.netmask);
+ }
+ if (ds.default_router.s_addr != 0)
+ {
+ uip_setdraddr("eth0", &ds.default_router);
+ }
+ if (ds.dnsaddr.s_addr != 0)
+ {
+ resolv_conf(&ds.dnsaddr);
+ }
+ dhcpc_close(handle);
+ }
+#endif
+
+ return OK;
+}
+
+#endif /* CONFIG_NET */
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
new file mode 100644
index 000000000..ba597a062
--- /dev/null
+++ b/apps/nshlib/nsh_parse.c
@@ -0,0 +1,1550 @@
+/****************************************************************************
+ * apps/nshlib/nsh_parse.c
+ *
+ * Copyright (C) 2007-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/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 <errno.h>
+#include <debug.h>
+
+#include <nuttx/version.h>
+
+#ifndef CONFIG_NSH_DISABLEBG
+# include <pthread.h>
+#endif
+
+#ifdef CONFIG_NSH_BUILTIN_APPS
+# include <apps/apps.h>
+#endif
+#include <apps/nsh.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Argument list size
+ *
+ * argv[0]: The command name.
+ * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
+ * argv[argc-3]: Possibly '>' or '>>'
+ * argv[argc-2]: Possibly <file>
+ * argv[argc-1]: Possibly '&' (if pthreads are enabled)
+ * argv[argc]: NULL terminating pointer
+ *
+ * Maximum size is NSH_MAX_ARGUMENTS+5
+ */
+
+#ifndef CONFIG_NSH_DISABLEBG
+# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+5)
+#else
+# define MAX_ARGV_ENTRIES (NSH_MAX_ARGUMENTS+4)
+#endif
+
+/* Help command summary layout */
+
+#define MAX_CMDLEN 12
+#define CMDS_PER_LINE 6
+
+#define NUM_CMDS ((sizeof(g_cmdmap)/sizeof(struct cmdmap_s)) - 1)
+#define NUM_CMD_ROWS ((NUM_CMDS + (CMDS_PER_LINE-1)) / CMDS_PER_LINE)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct cmdmap_s
+{
+ const char *cmd; /* Name of the command */
+ cmd_t handler; /* Function that handles the command */
+ uint8_t minargs; /* Minimum number of arguments (including command) */
+ uint8_t maxargs; /* Maximum number of arguments (including command) */
+ const char *usage; /* Usage instructions for 'help' command */
+};
+
+#ifndef CONFIG_NSH_DISABLEBG
+struct cmdarg_s
+{
+ FAR struct nsh_vtbl_s *vtbl; /* For front-end interaction */
+ int fd; /* FD for output redirection */
+ int argc; /* Number of arguments in argv */
+ FAR char *argv[MAX_ARGV_ENTRIES]; /* Argument list */
+};
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_EXIT
+static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const char g_delim[] = " \t\n";
+static const char g_redirect1[] = ">";
+static const char g_redirect2[] = ">>";
+static const char g_exitstatus[] = "$?";
+static const char g_success[] = "0";
+static const char g_failure[] = "1";
+
+static const struct cmdmap_s g_cmdmap[] =
+{
+#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST)
+ { "[", cmd_lbracket, 4, NSH_MAX_ARGUMENTS, "<expression> ]" },
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+ { "?", cmd_help, 1, 1, NULL },
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_CAT
+ { "cat", cmd_cat, 2, NSH_MAX_ARGUMENTS, "<path> [<path> [<path> ...]]" },
+# endif
+#ifndef CONFIG_DISABLE_ENVIRON
+# ifndef CONFIG_NSH_DISABLE_CD
+ { "cd", cmd_cd, 1, 2, "[<dir-path>|-|~|..]" },
+# endif
+#endif
+# ifndef CONFIG_NSH_DISABLE_CP
+ { "cp", cmd_cp, 3, 3, "<source-path> <dest-path>" },
+# endif
+#endif
+
+#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE)
+ { "date", cmd_date, 1, 3, "[-s \"MMM DD HH:MM:SS YYYY\"]" },
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_NSH_DISABLE_DD)
+ { "dd", cmd_dd, 3, 6, "if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] [skip=<sectors>]" },
+# endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT) && \
+ defined(CONFIG_FS_READABLE) && !defined(CONFIG_NSH_DISABLE_DF)
+ { "df", cmd_df, 1, 1, NULL },
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SYSLOG) && \
+ defined(CONFIG_RAMLOG_SYSLOG) && !defined(CONFIG_NSH_DISABLE_DMESG)
+ { "dmesg", cmd_dmesg, 1, 1, NULL },
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_ECHO
+# ifndef CONFIG_DISABLE_ENVIRON
+ { "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[<string|$name> [<string|$name>...]]" },
+# else
+ { "echo", cmd_echo, 0, NSH_MAX_ARGUMENTS, "[<string> [<string>...]]" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_EXEC
+ { "exec", cmd_exec, 2, 3, "<hex-address>" },
+#endif
+#ifndef CONFIG_NSH_DISABLE_EXIT
+ { "exit", cmd_exit, 1, 1, NULL },
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_FREE
+ { "free", cmd_free, 1, 1, NULL },
+#endif
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_GET
+ { "get", cmd_get, 4, 7, "[-b|-n] [-f <local-path>] -h <ip-address> <remote-path>" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+# ifdef CONFIG_NSH_HELP_TERSE
+ { "help", cmd_help, 1, 2, "[<cmd>]" },
+#else
+ { "help", cmd_help, 1, 3, "[-v] [<cmd>]" },
+# endif
+#endif
+
+#ifdef CONFIG_NET
+# ifndef CONFIG_NSH_DISABLE_IFCONFIG
+ { "ifconfig", cmd_ifconfig, 1, 3, "[nic_name [ip]]" },
+# endif
+#endif
+
+#ifndef CONFIG_DISABLE_SIGNALS
+# ifndef CONFIG_NSH_DISABLE_KILL
+ { "kill", cmd_kill, 3, 3, "-<signal> <pid>" },
+# endif
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)
+# ifndef CONFIG_NSH_DISABLE_LOSETUP
+ { "losetup", cmd_losetup, 3, 6, "[-d <dev-path>] | [[-o <offset>] [-r] <dev-path> <file-path>]" },
+# endif
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_LS
+ { "ls", cmd_ls, 1, 5, "[-lRs] <dir-path>" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_MB
+ { "mb", cmd_mb, 2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+# ifndef CONFIG_NSH_DISABLE_MKDIR
+ { "mkdir", cmd_mkdir, 2, 2, "<path>" },
+# endif
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_FAT)
+# ifndef CONFIG_NSH_DISABLE_MKFATFS
+ { "mkfatfs", cmd_mkfatfs, 2, 2, "<path>" },
+# endif
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_MKFIFO
+ { "mkfifo", cmd_mkfifo, 2, 2, "<path>" },
+# endif
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+# ifndef CONFIG_NSH_DISABLE_MKRD
+ { "mkrd", cmd_mkrd, 2, 6, "[-m <minor>] [-s <sector-size>] <nsectors>" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_MH
+ { "mh", cmd_mh, 2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
+# ifndef CONFIG_NSH_DISABLE_MOUNT
+ { "mount", cmd_mount, 1, 5, "[-t <fstype> <block-device> <mount-point>]" },
+# endif
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+# ifndef CONFIG_NSH_DISABLE_MV
+ { "mv", cmd_mv, 3, 3, "<old-path> <new-path>" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_MW
+ { "mw", cmd_mw, 2, 3, "<hex-address>[=<hex-value>][ <hex-byte-count>]" },
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && \
+ defined(CONFIG_NET) && defined(CONFIG_NFS)
+# ifndef CONFIG_NSH_DISABLE_NFSMOUNT
+ { "nfsmount", cmd_nfsmount, 4, 4, "<server-address> <mount-point> <remote-path>" },
+# endif
+#endif
+
+#if defined(CONFIG_NET) && defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
+ !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
+# ifndef CONFIG_NSH_DISABLE_PING
+ { "ping", cmd_ping, 2, 6, "[-c <count>] [-i <interval>] <ip-address>" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_PS
+ { "ps", cmd_ps, 1, 1, NULL },
+#endif
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_PUT
+ { "put", cmd_put, 4, 7, "[-b|-n] [-f <remote-path>] -h <ip-address> <local-path>" },
+# endif
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
+# ifndef CONFIG_NSH_DISABLE_PWD
+ { "pwd", cmd_pwd, 1, 1, NULL },
+# endif
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_WRITABLE)
+# ifndef CONFIG_NSH_DISABLE_RM
+ { "rm", cmd_rm, 2, 2, "<file-path>" },
+# endif
+# ifndef CONFIG_NSH_DISABLE_RMDIR
+ { "rmdir", cmd_rmdir, 2, 2, "<dir-path>" },
+# endif
+#endif
+
+#ifndef CONFIG_DISABLE_ENVIRON
+# ifndef CONFIG_NSH_DISABLE_SET
+ { "set", cmd_set, 3, 3, "<name> <value>" },
+# endif
+#endif
+
+#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_NSH_DISABLESCRIPT)
+# ifndef CONFIG_NSH_DISABLE_SH
+ { "sh", cmd_sh, 2, 2, "<script-path>" },
+# endif
+#endif
+
+#ifndef CONFIG_DISABLE_SIGNALS
+# ifndef CONFIG_NSH_DISABLE_SLEEP
+ { "sleep", cmd_sleep, 2, 2, "<sec>" },
+# endif
+#endif
+
+#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST)
+ { "test", cmd_test, 3, NSH_MAX_ARGUMENTS, "<expression>" },
+#endif
+
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
+# ifndef CONFIG_NSH_DISABLE_UMOUNT
+ { "umount", cmd_umount, 2, 2, "<dir-path>" },
+# endif
+#endif
+
+#ifndef CONFIG_DISABLE_ENVIRON
+# ifndef CONFIG_NSH_DISABLE_UNSET
+ { "unset", cmd_unset, 2, 2, "<name>" },
+# endif
+#endif
+
+#ifndef CONFIG_DISABLE_SIGNALS
+# ifndef CONFIG_NSH_DISABLE_USLEEP
+ { "usleep", cmd_usleep, 2, 2, "<usec>" },
+# endif
+#endif
+
+#if defined(CONFIG_NET_TCP) && CONFIG_NFILE_DESCRIPTORS > 0
+# ifndef CONFIG_NSH_DISABLE_WGET
+ { "wget", cmd_wget, 2, 4, "[-o <local-path>] <url>" },
+# endif
+#endif
+
+#ifndef CONFIG_NSH_DISABLE_XD
+ { "xd", cmd_xd, 3, 3, "<hex-address> <byte-count>" },
+#endif
+ { NULL, NULL, 1, 1, NULL }
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* If NuttX versioning information is available, Include that information
+ * in the NSH greeting.
+ */
+
+#if CONFIG_VERSION_MAJOR != 0 || CONFIG_VERSION_MINOR != 0
+const char g_nshgreeting[] = "\nNuttShell (NSH) NuttX-" CONFIG_VERSION_STRING "\n";
+#else
+const char g_nshgreeting[] = "\nNuttShell (NSH)\n";
+#endif
+
+/* The NSH prompt */
+
+const char g_nshprompt[] = "nsh> ";
+
+/* Common, message formats */
+
+const char g_nshsyntax[] = "nsh: %s: syntax error\n";
+const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n";
+const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n";
+const char g_fmtargrange[] = "nsh: %s: value out of range\n";
+const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n";
+const char g_fmtnosuch[] = "nsh: %s: no such %s: %s\n";
+const char g_fmttoomanyargs[] = "nsh: %s: too many arguments\n";
+const char g_fmtdeepnesting[] = "nsh: %s: nesting too deep\n";
+const char g_fmtcontext[] = "nsh: %s: not valid in this context\n";
+#ifdef CONFIG_NSH_STRERROR
+const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %s\n";
+#else
+const char g_fmtcmdfailed[] = "nsh: %s: %s failed: %d\n";
+#endif
+const char g_fmtcmdoutofmemory[] = "nsh: %s: out of memory\n";
+const char g_fmtinternalerror[] = "nsh: %s: Internal error\n";
+#ifndef CONFIG_DISABLE_SIGNALS
+const char g_fmtsignalrecvd[] = "nsh: %s: Interrupted by signal\n";
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: help_cmdlist
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+static inline void help_cmdlist(FAR struct nsh_vtbl_s *vtbl)
+{
+ int i;
+ int j;
+ int k;
+
+ /* Print the command name in NUM_CMD_ROWS rows with CMDS_PER_LINE commands
+ * on each line.
+ */
+
+ for (i = 0; i < NUM_CMD_ROWS; i++)
+ {
+ nsh_output(vtbl, " ");
+ for (j = 0, k = i; j < CMDS_PER_LINE && k < NUM_CMDS; j++, k += NUM_CMD_ROWS)
+ {
+ nsh_output(vtbl, "%-12s", g_cmdmap[k].cmd);
+ }
+
+ nsh_output(vtbl, "\n");
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: help_usage
+ ****************************************************************************/
+
+#if !defined(CONFIG_NSH_DISABLE_HELP) && !defined(CONFIG_NSH_HELP_TERSE)
+static inline void help_usage(FAR struct nsh_vtbl_s *vtbl)
+{
+ nsh_output(vtbl, "NSH command forms:\n");
+#ifndef CONFIG_NSH_DISABLEBG
+ nsh_output(vtbl, " [nice [-d <niceness>>]] <cmd> [> <file>|>> <file>] [&]\n");
+#else
+ nsh_output(vtbl, " <cmd> [> <file>|>> <file>]\n");
+#endif
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ nsh_output(vtbl, "OR\n");
+ nsh_output(vtbl, " if <cmd>\n");
+ nsh_output(vtbl, " then\n");
+ nsh_output(vtbl, " [sequence of <cmd>]\n");
+ nsh_output(vtbl, " else\n");
+ nsh_output(vtbl, " [sequence of <cmd>]\n");
+ nsh_output(vtbl, " fi\n\n");
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: help_showcmd
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+static void help_showcmd(FAR struct nsh_vtbl_s *vtbl,
+ FAR const struct cmdmap_s *cmdmap)
+{
+ if (cmdmap->usage)
+ {
+ nsh_output(vtbl, " %s %s\n", cmdmap->cmd, cmdmap->usage);
+ }
+ else
+ {
+ nsh_output(vtbl, " %s\n", cmdmap->cmd);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: help_cmd
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+static int help_cmd(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd)
+{
+ FAR const struct cmdmap_s *cmdmap;
+
+ /* Find the command in the command table */
+
+ for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++)
+ {
+ /* Is this the one we are looking for? */
+
+ if (strcmp(cmdmap->cmd, cmd) == 0)
+ {
+ /* Yes... show it */
+
+ nsh_output(vtbl, "%s usage:", cmd);
+ help_showcmd(vtbl, cmdmap);
+ return OK;
+ }
+ }
+
+ nsh_output(vtbl, g_fmtcmdnotfound, cmd);
+ return ERROR;
+}
+#endif
+
+/****************************************************************************
+ * Name: help_allcmds
+ ****************************************************************************/
+
+#if !defined(CONFIG_NSH_DISABLE_HELP) && !defined(CONFIG_NSH_HELP_TERSE)
+static inline void help_allcmds(FAR struct nsh_vtbl_s *vtbl)
+{
+ FAR const struct cmdmap_s *cmdmap;
+
+ /* Show all of the commands in the command table */
+
+ for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++)
+ {
+ help_showcmd(vtbl, cmdmap);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: help_builtins
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+static inline void help_builtins(FAR struct nsh_vtbl_s *vtbl)
+{
+#ifdef CONFIG_NSH_BUILTIN_APPS
+ FAR const char *name;
+ int i;
+
+ /* List the set of available built-in commands */
+
+ nsh_output(vtbl, "\nBuiltin Apps:\n");
+ for (i = 0; (name = namedapp_getname(i)) != NULL; i++)
+ {
+ nsh_output(vtbl, " %s\n", name);
+ }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_help
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_HELP
+static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ FAR const char *cmd = NULL;
+#ifndef CONFIG_NSH_HELP_TERSE
+ bool verbose = false;
+ int i;
+#endif
+
+ /* The command may be followed by a verbose option */
+
+#ifndef CONFIG_NSH_HELP_TERSE
+ i = 1;
+ if (argc > i)
+ {
+ if (strcmp(argv[i], "-v") == 0)
+ {
+ verbose = true;
+ i++;
+ }
+ }
+
+ /* The command line may end with a command name */
+
+ if (argc > i)
+ {
+ cmd = argv[i];
+ }
+
+ /* Show the generic usage if verbose is requested */
+
+ if (verbose)
+ {
+ help_usage(vtbl);
+ }
+#else
+ if (argc > 1)
+ {
+ cmd = argv[1];
+ }
+#endif
+
+ /* Are we showing help on a single command? */
+
+ if (cmd)
+ {
+ /* Yes.. show the single command */
+
+ help_cmd(vtbl, cmd);
+ }
+ else
+ {
+ /* In verbose mode, show detailed help for all commands */
+
+#ifndef CONFIG_NSH_HELP_TERSE
+ if (verbose)
+ {
+ nsh_output(vtbl, "Where <cmd> is one of:\n");
+ help_allcmds(vtbl);
+ }
+
+ /* Otherwise, just show the list of command names */
+
+ else
+#endif
+ {
+ help_cmd(vtbl, "help");
+ nsh_output(vtbl, "\n");
+ help_cmdlist(vtbl);
+ }
+
+ /* And show the list of built-in applications */
+
+ help_builtins(vtbl);
+ }
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_unrecognized
+ ****************************************************************************/
+
+static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ nsh_output(vtbl, g_fmtcmdnotfound, argv[0]);
+ return ERROR;
+}
+
+/****************************************************************************
+ * Name: cmd_exit
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_EXIT
+static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ nsh_exit(vtbl, 0);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_execute
+ *
+ * Description:
+ * Exectue the command in argv[0]
+ *
+ * Returned Value:
+ * <0 If exec_namedapp() fails, then the negated errno value
+ * is returned.
+ * -1 (ERRROR) if the command was unsuccessful
+ * 0 (OK) if the command was successful
+ * 1 if an application task was spawned successfully, but
+ * returned failure exit status.
+ *
+ ****************************************************************************/
+
+static int nsh_execute(FAR struct nsh_vtbl_s *vtbl, int argc, char *argv[])
+{
+ const struct cmdmap_s *cmdmap;
+ const char *cmd;
+ cmd_t handler = cmd_unrecognized;
+ int ret;
+
+ /* The form of argv is:
+ *
+ * argv[0]: The command name. This is argv[0] when the arguments
+ * are, finally, received by the command vtblr
+ * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
+ * argv[argc]: NULL terminating pointer
+ */
+
+ cmd = argv[0];
+
+ /* Try to find a command in the application library. */
+
+#ifdef CONFIG_NSH_BUILTIN_APPS
+ ret = nsh_execapp(vtbl, cmd, argv);
+
+ /* If the built-in application was successfully started, return OK
+ * or 1 (if the application returned a non-zero exit status).
+ */
+
+ if (ret >= 0)
+ {
+ return ret;
+ }
+#endif
+
+ /* See if the command is one that we understand */
+
+ for (cmdmap = g_cmdmap; cmdmap->cmd; cmdmap++)
+ {
+ if (strcmp(cmdmap->cmd, cmd) == 0)
+ {
+ /* Check if a valid number of arguments was provided. We
+ * do this simple, imperfect checking here so that it does
+ * not have to be performed in each command.
+ */
+
+ if (argc < cmdmap->minargs)
+ {
+ /* Fewer than the minimum number were provided */
+
+ nsh_output(vtbl, g_fmtargrequired, cmd);
+ return ERROR;
+ }
+ else if (argc > cmdmap->maxargs)
+ {
+ /* More than the maximum number were provided */
+
+ nsh_output(vtbl, g_fmttoomanyargs, cmd);
+ return ERROR;
+ }
+ else
+ {
+ /* A valid number of arguments were provided (this does
+ * not mean they are right).
+ */
+
+ handler = cmdmap->handler;
+ break;
+ }
+ }
+ }
+
+ ret = handler(vtbl, argc, argv);
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nsh_releaseargs
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLEBG
+static void nsh_releaseargs(struct cmdarg_s *arg)
+{
+ FAR struct nsh_vtbl_s *vtbl = arg->vtbl;
+ int i;
+
+ /* If the output was redirected, then file descriptor should
+ * be closed. The created task has its one, independent copy of
+ * the file descriptor
+ */
+
+ if (vtbl->np.np_redirect)
+ {
+ (void)close(arg->fd);
+ }
+
+ /* Released the cloned vtbl instance */
+
+ nsh_release(vtbl);
+
+ /* Release the cloned args */
+
+ for (i = 0; i < arg->argc; i++)
+ {
+ free(arg->argv[i]);
+ }
+ free(arg);
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_child
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLEBG
+static pthread_addr_t nsh_child(pthread_addr_t arg)
+{
+ struct cmdarg_s *carg = (struct cmdarg_s *)arg;
+ int ret;
+
+ dbg("BG %s\n", carg->argv[0]);
+
+ /* Execute the specified command on the child thread */
+
+ ret = nsh_execute(carg->vtbl, carg->argc, carg->argv);
+
+ /* Released the cloned arguments */
+
+ dbg("BG %s complete\n", carg->argv[0]);
+ nsh_releaseargs(carg);
+ return (void*)ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_cloneargs
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLEBG
+static inline struct cmdarg_s *nsh_cloneargs(FAR struct nsh_vtbl_s *vtbl,
+ int fd, int argc, char *argv[])
+{
+ struct cmdarg_s *ret = (struct cmdarg_s *)zalloc(sizeof(struct cmdarg_s));
+ int i;
+
+ if (ret)
+ {
+ ret->vtbl = vtbl;
+ ret->fd = fd;
+ ret->argc = argc;
+
+ for (i = 0; i < argc; i++)
+ {
+ ret->argv[i] = strdup(argv[i]);
+ }
+ }
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_argument
+ ****************************************************************************/
+
+char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr)
+{
+ char *pbegin = *saveptr;
+ char *pend = NULL;
+ const char *term;
+#ifndef CONFIG_DISABLE_ENVIRON
+ bool quoted = false;
+#endif
+
+ /* Find the beginning of the next token */
+
+ for (;
+ *pbegin && strchr(g_delim, *pbegin) != NULL;
+ pbegin++);
+
+ /* If we are at the end of the string with nothing
+ * but delimiters found, then return NULL.
+ */
+
+ if (!*pbegin)
+ {
+ return NULL;
+ }
+
+ /* Does the token begin with '>' -- redirection of output? */
+
+ if (*pbegin == '>')
+ {
+ /* Yes.. does it begin with ">>"? */
+
+ if (*(pbegin + 1) == '>')
+ {
+ *saveptr = pbegin + 2;
+ pbegin = (char*)g_redirect2;
+ }
+ else
+ {
+ *saveptr = pbegin + 1;
+ pbegin = (char*)g_redirect1;
+ }
+ }
+
+ /* Does the token begin with '#' -- comment */
+
+ else if (*pbegin == '#')
+ {
+ /* Return NULL meaning that we are at the end of the line */
+
+ *saveptr = pbegin;
+ pbegin = NULL;
+ }
+ else
+ {
+ /* Otherwise, we are going to have to parse to find the end of
+ * the token. Does the token begin with '"'?
+ */
+
+ if (*pbegin == '"')
+ {
+ /* Yes.. then only another '"' can terminate the string */
+
+ pbegin++;
+ term = "\"";
+#ifndef CONFIG_DISABLE_ENVIRON
+ quoted = true;
+#endif
+ }
+ else
+ {
+ /* No, then any of the usual terminators will terminate the argument */
+
+ term = g_delim;
+ }
+
+ /* Find the end of the string */
+
+ for (pend = pbegin + 1;
+ *pend && strchr(term, *pend) == NULL;
+ pend++);
+
+ /* pend either points to the end of the string or to
+ * the first delimiter after the string.
+ */
+
+ if (*pend)
+ {
+ /* Turn the delimiter into a null terminator */
+
+ *pend++ = '\0';
+ }
+
+ /* Save the pointer where we left off */
+
+ *saveptr = pend;
+
+#ifndef CONFIG_DISABLE_ENVIRON
+ /* Check for references to environment variables */
+
+ if (pbegin[0] == '$' && !quoted)
+ {
+ /* Check for built-in variables */
+
+ if (strcmp(pbegin, g_exitstatus) == 0)
+ {
+ if (vtbl->np.np_fail)
+ {
+ return (char*)g_failure;
+ }
+ else
+ {
+ return (char*)g_success;
+ }
+ }
+
+ /* Not a built-in? Return the value of the environment variable with this name */
+
+ else
+ {
+ char *value = getenv(pbegin+1);
+ if (value)
+ {
+ return value;
+ }
+ else
+ {
+ return (char*)"";
+ }
+ }
+ }
+#endif
+ }
+
+ /* Return the beginning of the token. */
+
+ return pbegin;
+}
+
+/****************************************************************************
+ * Name: nsh_cmdenabled
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+static inline bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
+{
+ struct nsh_parser_s *np = &vtbl->np;
+ bool ret = !np->np_st[np->np_ndx].ns_disabled;
+ if (ret)
+ {
+ switch (np->np_st[np->np_ndx].ns_state)
+ {
+ case NSH_PARSER_NORMAL :
+ case NSH_PARSER_IF:
+ default:
+ break;
+
+ case NSH_PARSER_THEN:
+ ret = !np->np_st[np->np_ndx].ns_ifcond;
+ break;
+
+ case NSH_PARSER_ELSE:
+ ret = np->np_st[np->np_ndx].ns_ifcond;
+ break;
+ }
+ }
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_ifthenelse
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+static inline int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr)
+{
+ struct nsh_parser_s *np = &vtbl->np;
+ FAR char *cmd = *ppcmd;
+ bool disabled;
+
+ if (cmd)
+ {
+ /* Check if the command is preceeded by "if" */
+
+ if (strcmp(cmd, "if") == 0)
+ {
+ /* Get the cmd following the if */
+
+ *ppcmd = nsh_argument(vtbl, saveptr);
+ if (!*ppcmd)
+ {
+ nsh_output(vtbl, g_fmtarginvalid, "if");
+ goto errout;
+ }
+
+ /* Verify that "if" is valid in this context */
+
+ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_NORMAL &&
+ np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN &&
+ np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE)
+ {
+ nsh_output(vtbl, g_fmtcontext, "if");
+ goto errout;
+ }
+
+ /* Check if we have exceeded the maximum depth of nesting */
+
+ if (np->np_ndx >= CONFIG_NSH_NESTDEPTH-1)
+ {
+ nsh_output(vtbl, g_fmtdeepnesting, "if");
+ goto errout;
+ }
+
+ /* "Push" the old state and set the new state */
+
+ disabled = !nsh_cmdenabled(vtbl);
+ np->np_ndx++;
+ np->np_st[np->np_ndx].ns_state = NSH_PARSER_IF;
+ np->np_st[np->np_ndx].ns_disabled = disabled;
+ np->np_st[np->np_ndx].ns_ifcond = false;
+ }
+ else if (strcmp(cmd, "then") == 0)
+ {
+ /* Get the cmd following the then -- there shouldn't be one */
+
+ *ppcmd = nsh_argument(vtbl, saveptr);
+ if (*ppcmd)
+ {
+ nsh_output(vtbl, g_fmtarginvalid, "then");
+ goto errout;
+ }
+
+ /* Verify that "then" is valid in this context */
+
+ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_IF)
+ {
+ nsh_output(vtbl, g_fmtcontext, "then");
+ goto errout;
+ }
+ np->np_st[np->np_ndx].ns_state = NSH_PARSER_THEN;
+ }
+ else if (strcmp(cmd, "else") == 0)
+ {
+ /* Get the cmd following the else -- there shouldn't be one */
+
+ *ppcmd = nsh_argument(vtbl, saveptr);
+ if (*ppcmd)
+ {
+ nsh_output(vtbl, g_fmtarginvalid, "else");
+ goto errout;
+ }
+
+ /* Verify that "then" is valid in this context */
+
+ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN)
+ {
+ nsh_output(vtbl, g_fmtcontext, "else");
+ goto errout;
+ }
+ np->np_st[np->np_ndx].ns_state = NSH_PARSER_ELSE;
+ }
+ else if (strcmp(cmd, "fi") == 0)
+ {
+ /* Get the cmd following the fi -- there should be one */
+
+ *ppcmd = nsh_argument(vtbl, saveptr);
+ if (*ppcmd)
+ {
+ nsh_output(vtbl, g_fmtarginvalid, "fi");
+ goto errout;
+ }
+
+ /* Verify that "fi" is valid in this context */
+
+ if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN &&
+ np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE)
+ {
+ nsh_output(vtbl, g_fmtcontext, "fi");
+ goto errout;
+ }
+
+ if (np->np_ndx < 1) /* Shouldn't happen */
+ {
+ nsh_output(vtbl, g_fmtinternalerror, "if");
+ goto errout;
+ }
+
+ /* "Pop" the previous state */
+
+ np->np_ndx--;
+ }
+ else if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
+ {
+ nsh_output(vtbl, g_fmtcontext, cmd);
+ goto errout;
+ }
+ }
+ return OK;
+
+errout:
+ np->np_ndx = 0;
+ np->np_st[0].ns_state = NSH_PARSER_NORMAL;
+ np->np_st[0].ns_disabled = false;
+ np->np_st[0].ns_ifcond = false;
+ return ERROR;
+}
+#endif
+
+/****************************************************************************
+ * Name: nsh_saveresult
+ ****************************************************************************/
+
+static inline int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result)
+{
+ struct nsh_parser_s *np = &vtbl->np;
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
+ {
+ np->np_fail = false;
+ np->np_st[np->np_ndx].ns_ifcond = result;
+ return OK;
+ }
+ else
+#endif
+ {
+ np->np_fail = result;
+ return result ? ERROR : OK;
+ }
+}
+
+/****************************************************************************
+ * Name: nsh_nice
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLEBG
+static inline int nsh_nice(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr)
+{
+ FAR char *cmd = *ppcmd;
+
+ vtbl->np.np_nice = 0;
+ if (cmd)
+ {
+ /* Check if the command is preceded by "nice" */
+
+ if (strcmp(cmd, "nice") == 0)
+ {
+ /* Nicenesses range from -20 (most favorable scheduling) to 19
+ * (least favorable). Default is 10.
+ */
+
+ vtbl->np.np_nice = 10;
+
+ /* Get the cmd (or -d option of nice command) */
+
+ cmd = nsh_argument(vtbl, saveptr);
+ if (cmd && strcmp(cmd, "-d") == 0)
+ {
+ FAR char *val = nsh_argument(vtbl, saveptr);
+ if (val)
+ {
+ char *endptr;
+ vtbl->np.np_nice = (int)strtol(val, &endptr, 0);
+ if (vtbl->np.np_nice > 19 || vtbl->np.np_nice < -20 ||
+ endptr == val || *endptr != '\0')
+ {
+ nsh_output(vtbl, g_fmtarginvalid, "nice");
+ return ERROR;
+ }
+ cmd = nsh_argument(vtbl, saveptr);
+ }
+ }
+
+ /* Return the real command name */
+
+ *ppcmd = cmd;
+ }
+ }
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_parse
+ *
+ * Description:
+ * This function parses and executes one NSH command.
+ *
+ ****************************************************************************/
+
+int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
+{
+ FAR char *argv[MAX_ARGV_ENTRIES];
+ FAR char *saveptr;
+ FAR char *cmd;
+ FAR char *redirfile = NULL;
+ int fd = -1;
+ int oflags = 0;
+ int argc;
+ int ret;
+
+ /* Initialize parser state */
+
+ memset(argv, 0, MAX_ARGV_ENTRIES*sizeof(FAR char *));
+#ifndef CONFIG_NSH_DISABLEBG
+ vtbl->np.np_bg = false;
+#endif
+ vtbl->np.np_redirect = false;
+
+ /* Parse out the command at the beginning of the line */
+
+ saveptr = cmdline;
+ cmd = nsh_argument(vtbl, &saveptr);
+
+ /* Handler if-then-else-fi */
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ if (nsh_ifthenelse(vtbl, &cmd, &saveptr) != 0)
+ {
+ goto errout;
+ }
+#endif
+
+ /* Handle nice */
+
+#ifndef CONFIG_NSH_DISABLEBG
+ if (nsh_nice(vtbl, &cmd, &saveptr) != 0)
+ {
+ goto errout;
+ }
+#endif
+
+ /* Check if any command was provided -OR- if command processing is
+ * currently disabled.
+ */
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ if (!cmd || !nsh_cmdenabled(vtbl))
+#else
+ if (!cmd)
+#endif
+ {
+ /* An empty line is not an error and an unprocessed command cannot
+ * generate an error, but neither should they change the last
+ * command status.
+ */
+
+ return OK;
+ }
+
+ /* Parse all of the arguments following the command name. The form
+ * of argv is:
+ *
+ * argv[0]: The command name.
+ * argv[1]: The beginning of argument (up to NSH_MAX_ARGUMENTS)
+ * argv[argc-3]: Possibly '>' or '>>'
+ * argv[argc-2]: Possibly <file>
+ * argv[argc-1]: Possibly '&'
+ * argv[argc]: NULL terminating pointer
+ *
+ * Maximum size is NSH_MAX_ARGUMENTS+5
+ */
+
+ argv[0] = cmd;
+ for (argc = 1; argc < MAX_ARGV_ENTRIES-1; argc++)
+ {
+ argv[argc] = nsh_argument(vtbl, &saveptr);
+ if (!argv[argc])
+ {
+ break;
+ }
+ }
+
+ argv[argc] = NULL;
+
+ /* Check if the command should run in background */
+
+#ifndef CONFIG_NSH_DISABLEBG
+ if (argc > 1 && strcmp(argv[argc-1], "&") == 0)
+ {
+ vtbl->np.np_bg = true;
+ argv[argc-1] = NULL;
+ argc--;
+ }
+#endif
+
+ /* Check if the output was re-directed using > or >> */
+
+ if (argc > 2)
+ {
+ /* Check for redirection to a new file */
+
+ if (strcmp(argv[argc-2], g_redirect1) == 0)
+ {
+ vtbl->np.np_redirect = true;
+ oflags = O_WRONLY|O_CREAT|O_TRUNC;
+ redirfile = nsh_getfullpath(vtbl, argv[argc-1]);
+ argc -= 2;
+ }
+
+ /* Check for redirection by appending to an existing file */
+
+ else if (strcmp(argv[argc-2], g_redirect2) == 0)
+ {
+ vtbl->np.np_redirect = true;
+ oflags = O_WRONLY|O_CREAT|O_APPEND;
+ redirfile = nsh_getfullpath(vtbl, argv[argc-1]);
+ argc -= 2;
+ }
+ }
+
+ /* Redirected output? */
+
+ if (vtbl->np.np_redirect)
+ {
+ /* Open the redirection file. This file will eventually
+ * be closed by a call to either nsh_release (if the command
+ * is executed in the background) or by nsh_undirect if the
+ * command is executed in the foreground.
+ */
+
+ fd = open(redirfile, oflags, 0666);
+ nsh_freefullpath(redirfile);
+ redirfile = NULL;
+
+ if (fd < 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "open", NSH_ERRNO);
+ goto errout;
+ }
+ }
+
+ /* Check if the maximum number of arguments was exceeded */
+
+ if (argc > NSH_MAX_ARGUMENTS)
+ {
+ nsh_output(vtbl, g_fmttoomanyargs, cmd);
+ }
+
+ /* Handle the case where the command is executed in background.
+ * However is app is to be started as namedapp new process will
+ * be created anyway, so skip this step. */
+
+#ifndef CONFIG_NSH_DISABLEBG
+ if (vtbl->np.np_bg
+#ifdef CONFIG_NSH_BUILTIN_APPS
+ && namedapp_isavail(argv[0]) < 0
+#endif
+ )
+ {
+ struct sched_param param;
+ struct nsh_vtbl_s *bkgvtbl;
+ struct cmdarg_s *args;
+ pthread_attr_t attr;
+ pthread_t thread;
+
+ /* Get a cloned copy of the vtbl with reference count=1.
+ * after the command has been processed, the nsh_release() call
+ * at the end of nsh_child() will destroy the clone.
+ */
+
+ bkgvtbl = nsh_clone(vtbl);
+ if (!bkgvtbl)
+ {
+ goto errout_with_redirect;
+ }
+
+ /* Create a container for the command arguments */
+
+ args = nsh_cloneargs(bkgvtbl, fd, argc, argv);
+ if (!args)
+ {
+ nsh_release(bkgvtbl);
+ goto errout_with_redirect;
+ }
+
+ /* Handle redirection of output via a file descriptor */
+
+ if (vtbl->np.np_redirect)
+ {
+ (void)nsh_redirect(bkgvtbl, fd, NULL);
+ }
+
+ /* Get the execution priority of this task */
+
+ ret = sched_getparam(0, &param);
+ if (ret != 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "sched_getparm", NSH_ERRNO);
+ nsh_releaseargs(args);
+ nsh_release(bkgvtbl);
+ goto errout;
+ }
+
+ /* Determine the priority to execute the command */
+
+ if (vtbl->np.np_nice != 0)
+ {
+ int priority = param.sched_priority - vtbl->np.np_nice;
+ if (vtbl->np.np_nice < 0)
+ {
+ int max_priority = sched_get_priority_max(SCHED_NSH);
+ if (priority > max_priority)
+ {
+ priority = max_priority;
+ }
+ }
+ else
+ {
+ int min_priority = sched_get_priority_min(SCHED_NSH);
+ if (priority < min_priority)
+ {
+ priority = min_priority;
+ }
+ }
+ param.sched_priority = priority;
+ }
+
+ /* Set up the thread attributes */
+
+ (void)pthread_attr_init(&attr);
+ (void)pthread_attr_setschedpolicy(&attr, SCHED_NSH);
+ (void)pthread_attr_setschedparam(&attr, &param);
+
+ /* Execute the command as a separate thread at the appropriate priority */
+
+ ret = pthread_create(&thread, &attr, nsh_child, (pthread_addr_t)args);
+ if (ret != 0)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "pthread_create", NSH_ERRNO_OF(ret));
+ nsh_releaseargs(args);
+ nsh_release(bkgvtbl);
+ goto errout;
+ }
+
+ nsh_output(vtbl, "%s [%d:%d]\n", cmd, thread, param.sched_priority);
+ }
+ else
+#endif
+ {
+ uint8_t save[SAVE_SIZE];
+
+ /* Handle redirection of output via a file descriptor */
+
+ if (vtbl->np.np_redirect)
+ {
+ nsh_redirect(vtbl, fd, save);
+ }
+
+ /* Then execute the command in "foreground" -- i.e., while the user waits
+ * for the next prompt. nsh_execute will return:
+ *
+ * -1 (ERRROR) if the command was unsuccessful
+ * 0 (OK) if the command was successful
+ * 1 if an application task was spawned successfully, but
+ * returned failure exit status.
+ */
+
+ ret = nsh_execute(vtbl, argc, argv);
+
+ /* Restore the original output. Undirect will close the redirection
+ * file descriptor.
+ */
+
+ if (vtbl->np.np_redirect)
+ {
+ nsh_undirect(vtbl, save);
+ }
+
+ /* Treat both errors and non-zero return codes as "errors" so that
+ * it is possible to test for non-zero returns in nsh scripts.
+ */
+
+ if (ret != OK)
+ {
+ goto errout;
+ }
+ }
+
+ /* Return success if the command succeeded (or at least, starting of the
+ * command task succeeded).
+ */
+
+ return nsh_saveresult(vtbl, false);
+
+#ifndef CONFIG_NSH_DISABLEBG
+errout_with_redirect:
+ if (vtbl->np.np_redirect)
+ {
+ close(fd);
+ }
+#endif
+errout:
+ return nsh_saveresult(vtbl, true);
+}
diff --git a/apps/nshlib/nsh_proccmds.c b/apps/nshlib/nsh_proccmds.c
new file mode 100644
index 000000000..487214501
--- /dev/null
+++ b/apps/nshlib/nsh_proccmds.c
@@ -0,0 +1,310 @@
+/****************************************************************************
+ * apps/nshlib/nsh_proccmds.c
+ *
+ * Copyright (C) 2007-2009, 2011-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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sched.h>
+#include <errno.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* The returned value should be zero for sucess or TRUE or non zero for
+ * failure or FALSE.
+ */
+
+typedef int (*exec_t)(void);
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_PS
+static const char *g_statenames[] =
+{
+ "INVALID ",
+ "PENDING ",
+ "READY ",
+ "RUNNING ",
+ "INACTIVE",
+ "WAITSEM ",
+#ifndef CONFIG_DISABLE_MQUEUE
+ "WAITSIG ",
+#endif
+#ifndef CONFIG_DISABLE_MQUEUE
+ "MQNEMPTY",
+ "MQNFULL "
+#endif
+};
+
+static const char *g_ttypenames[4] =
+{
+ "TASK ",
+ "PTHREAD",
+ "KTHREAD",
+ "--?-- "
+};
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: ps_task
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_PS
+static void ps_task(FAR _TCB *tcb, FAR void *arg)
+{
+ struct nsh_vtbl_s *vtbl = (struct nsh_vtbl_s*)arg;
+#if CONFIG_MAX_TASK_ARGS > 2
+ int i;
+#endif
+
+ /* Show task status */
+
+ nsh_output(vtbl, "%5d %3d %4s %7s%c%c %8s ",
+ tcb->pid, tcb->sched_priority,
+ tcb->flags & TCB_FLAG_ROUND_ROBIN ? "RR " : "FIFO",
+ g_ttypenames[(tcb->flags & TCB_FLAG_TTYPE_MASK) >> TCB_FLAG_TTYPE_SHIFT],
+ tcb->flags & TCB_FLAG_NONCANCELABLE ? 'N' : ' ',
+ tcb->flags & TCB_FLAG_CANCEL_PENDING ? 'P' : ' ',
+ g_statenames[tcb->task_state]);
+
+ /* Show task name and arguments */
+
+ nsh_output(vtbl, "%s(", tcb->argv[0]);
+
+ /* Special case 1st argument (no comma) */
+
+ if (tcb->argv[1])
+ {
+ nsh_output(vtbl, "%p", tcb->argv[1]);
+ }
+
+ /* Then any additional arguments */
+
+#if CONFIG_MAX_TASK_ARGS > 2
+ for (i = 2; i <= CONFIG_MAX_TASK_ARGS && tcb->argv[i]; i++)
+ {
+ nsh_output(vtbl, ", %p", tcb->argv[i]);
+ }
+#endif
+ nsh_output(vtbl, ")\n");
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_exec
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_EXEC
+int cmd_exec(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ char *endptr;
+ uintptr_t addr;
+
+ addr = (uintptr_t)strtol(argv[1], &endptr, 0);
+ if (!addr || endptr == argv[1] || *endptr != '\0')
+ {
+ nsh_output(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, "PID PRI SCHD TYPE NP STATE NAME\n");
+ sched_foreach(ps_task, vtbl);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_kill
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_SIGNALS
+#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 athe 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_output(vtbl, g_fmtnosuch, argv[0], "task", argv[2]);
+ return ERROR;
+
+ case EPERM:
+ case ENOSYS:
+ default:
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "kill", NSH_ERRNO);
+ return ERROR;
+ }
+
+invalid_arg:
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_sleep
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_SIGNALS
+#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_output(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+ sleep(secs);
+ return OK;
+}
+#endif
+#endif
+
+/****************************************************************************
+ * Name: cmd_usleep
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_SIGNALS
+#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_output(vtbl, g_fmtarginvalid, argv[0]);
+ return ERROR;
+ }
+ usleep(usecs);
+ return OK;
+}
+#endif
+#endif
diff --git a/apps/nshlib/nsh_romfsetc.c b/apps/nshlib/nsh_romfsetc.c
new file mode 100644
index 000000000..4134b45a3
--- /dev/null
+++ b/apps/nshlib/nsh_romfsetc.c
@@ -0,0 +1,124 @@
+/****************************************************************************
+ * 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 <debug.h>
+#include <errno.h>
+
+#include <nuttx/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>
+#else
+# include "nsh_romfsimg.h"
+#endif
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_romfsetc
+ ****************************************************************************/
+
+int nsh_romfsetc(void)
+{
+ int ret;
+
+ /* Create a ROM disk for the /etc filesystem */
+
+ ret = romdisk_register(CONFIG_NSH_ROMFSDEVNO, romfs_img,
+ NSECTORS(romfs_img_len), CONFIG_NSH_ROMFSSECTSIZE);
+ if (ret < 0)
+ {
+ dbg("nsh: romdisk_register failed: %d\n", -ret);
+ return ERROR;
+ }
+
+ /* Mount the file system */
+
+ vdbg("Mounting ROMFS filesystem at target=%s with source=%s\n",
+ CONFIG_NSH_ROMFSMOUNTPT, MOUNT_DEVNAME);
+
+ ret = mount(MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, "romfs", MS_RDONLY, NULL);
+ if (ret < 0)
+ {
+ dbg("nsh: mount(%s,%s,romfs) failed: %d\n",
+ MOUNT_DEVNAME, CONFIG_NSH_ROMFSMOUNTPT, errno);
+ return ERROR;
+ }
+ return OK;
+}
+
+#endif /* CONFIG_NSH_ROMFSETC */
+
diff --git a/apps/nshlib/nsh_romfsimg.h b/apps/nshlib/nsh_romfsimg.h
new file mode 100644
index 000000000..49b0ad166
--- /dev/null
+++ b/apps/nshlib/nsh_romfsimg.h
@@ -0,0 +1,89 @@
+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
+};
+unsigned int romfs_img_len = 1024;
diff --git a/apps/nshlib/nsh_telnetd.c b/apps/nshlib/nsh_telnetd.c
new file mode 100644
index 000000000..0117aad04
--- /dev/null
+++ b/apps/nshlib/nsh_telnetd.c
@@ -0,0 +1,187 @@
+/****************************************************************************
+ * apps/nshlib/nsh_telnetd.c
+ *
+ * Copyright (C) 2007-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 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 <unistd.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <apps/netutils/telnetd.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#ifdef CONFIG_NSH_TELNET
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_telnetmain
+ ****************************************************************************/
+
+int nsh_telnetmain(int argc, char *argv[])
+{
+ FAR struct console_stdio_s *pstate = nsh_newconsole();
+ DEBUGASSERT(pstate != NULL);
+
+ dbg("Session [%d] Started\n", getpid());
+
+ /* Present a greeting */
+
+ fputs(g_nshgreeting, pstate->cn_outstream);
+ fflush(pstate->cn_outstream);
+
+ /* Execute the startup script */
+
+#if defined(CONFIG_NSH_ROMFSETC) && !defined(CONFIG_NSH_CONSOLE)
+ (void)nsh_script(&pstate->cn_vtbl, "init", NSH_INITPATH);
+#endif
+
+ /* Then enter the command line parsing loop */
+
+ for (;;)
+ {
+ /* Display the prompt string */
+
+ fputs(g_nshprompt, pstate->cn_outstream);
+ fflush(pstate->cn_outstream);
+
+ /* Get the next line of input from the Telnet client */
+
+ if (fgets(pstate->cn_line, CONFIG_NSH_LINELEN, INSTREAM(pstate)) != NULL)
+ {
+ /* Parse process the received Telnet command */
+
+ (void)nsh_parse(&pstate->cn_vtbl, pstate->cn_line);
+ fflush(pstate->cn_outstream);
+ }
+ else
+ {
+ fprintf(pstate->cn_outstream, g_fmtcmdfailed, "nsh_telnetmain",
+ "fgets", NSH_ERRNO);
+ nsh_exit(&pstate->cn_vtbl, 1);
+ }
+ }
+
+ /* Clean up */
+
+ nsh_exit(&pstate->cn_vtbl, 0);
+
+ /* We do not get here, but this is necessary to keep some compilers happy */
+
+ 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:
+ * None. All of the properties of the Telnet daemon are controlled by
+ * NuttX configuration setting.
+ *
+ * Returned Values:
+ * Zero if the Telnet daemon was successfully started. A negated errno
+ * value will be returned on failure.
+ *
+ ****************************************************************************/
+
+int nsh_telnetstart(void)
+{
+ struct telnetd_config_s config;
+ int ret;
+
+ /* 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 */
+
+ vdbg("Starting the Telnet daemon\n");
+ ret = telnetd_start(&config);
+ if (ret < 0)
+ {
+ dbg("Failed to tart the Telnet daemon: %d\n", ret);
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NSH_TELNET */
diff --git a/apps/nshlib/nsh_test.c b/apps/nshlib/nsh_test.c
new file mode 100644
index 000000000..6e1b65e5f
--- /dev/null
+++ b/apps/nshlib/nsh_test.c
@@ -0,0 +1,438 @@
+/****************************************************************************
+ * apps/nshlib/nsh_test.c
+ *
+ * Copyright (C) 2008, 2011-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.
+ *
+ ****************************************************************************/
+
+/* 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)
+
+/****************************************************************************
+ * 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_output(vtbl, g_nshsyntax, "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)
+{
+ if (strcmp(argv[argc-1], "]") != 0)
+ {
+ nsh_output(vtbl, g_nshsyntax, argv[0]);
+ return ERROR;
+ }
+ else
+ {
+ return expression(vtbl, argc-2, &argv[1]);
+ }
+}
+
+#endif /* !CONFIG_NSH_DISABLESCRIPT && !CONFIG_NSH_DISABLE_TEST */
diff --git a/apps/nshlib/nsh_timcmds.c b/apps/nshlib/nsh_timcmds.c
new file mode 100644
index 000000000..bc2bda6f4
--- /dev/null
+++ b/apps/nshlib/nsh_timcmds.c
@@ -0,0 +1,331 @@
+/****************************************************************************
+ * apps/nshlib/dbg_timcmds.c
+ *
+ * Copyright (C) 2011-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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define MAX_TIME_STRING 80
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(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
+ ****************************************************************************/
+
+#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(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
+ ****************************************************************************/
+
+#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_NSH_DISABLE_DATE)
+static inline int date_showtime(FAR struct nsh_vtbl_s *vtbl, FAR const char *name)
+{
+ static const char format[] = "%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_output(vtbl, g_fmtcmdfailed, name, "clock_gettime", NSH_ERRNO);
+ return ERROR;
+ }
+
+ /* Break the current time up into the format needed by strftime */
+
+ (void)gmtime_r((FAR const time_t*)&ts.tv_sec, &tm);
+
+ /* Show the current time in the requested format */
+
+ (void)strftime(timbuf, MAX_TIME_STRING, format, &tm);
+ nsh_output(vtbl, "%s\n", timbuf);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: date_settime
+ ****************************************************************************/
+
+#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(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;
+
+ /* 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_output(vtbl, g_fmtcmdfailed, name, "clock_settime", NSH_ERRNO);
+ return ERROR;
+ }
+ return OK;
+
+errout_bad_parm:
+ nsh_output(vtbl, g_fmtarginvalid, name);
+ return ERROR;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cmd_date
+ ****************************************************************************/
+
+#if defined (CONFIG_RTC) && !defined(CONFIG_DISABLE_CLOCK) && !defined(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;
+ bool badarg = false;
+ 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 = '?' */
+ {
+ /* We need to parse to the end anyway so that getopt stays healthy */
+
+ badarg = true;
+ }
+ }
+
+ /* If a bad argument was encountered then exit with an error */
+
+ if (badarg)
+ {
+ 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_output(vtbl, errfmt, argv[0]);
+ return ERROR;
+}
+#endif
diff --git a/apps/nshlib/nsh_usbdev.c b/apps/nshlib/nsh_usbdev.c
new file mode 100644
index 000000000..3d123532a
--- /dev/null
+++ b/apps/nshlib/nsh_usbdev.c
@@ -0,0 +1,243 @@
+/****************************************************************************
+ * apps/nshlib/nsh_usbdev.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.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_CDCACM
+# include <nuttx/usb/pl2303.h>
+#endif
+
+#include "nsh.h"
+
+#ifdef CONFIG_USBDEV
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG) || defined(CONFIG_NSH_USBCONSOLE)
+# define trmessage lib_lowprintf
+#else
+# define trmessage printf
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_tracecallback
+ ****************************************************************************/
+
+#ifdef CONFIG_USBDEV_TRACE
+static int nsh_tracecallback(struct usbtrace_s *trace, void *arg)
+{
+ usbtrace_trprintf((trprintf_t)trmessage, trace->event, trace->value);
+ return 0;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_usbconsole
+ ****************************************************************************/
+
+#ifdef HAVE_USB_CONSOLE
+int nsh_usbconsole(void)
+{
+ char inch;
+ ssize_t nbytes;
+ int nlc;
+ int fd;
+ int ret;
+
+ /* Initialize any USB tracing options that were requested */
+
+#ifdef CONFIG_USBDEV_TRACE
+ usbtrace_enable(TRACE_BITSET);
+#endif
+
+ /* 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.
+ */
+
+ /* Initialize the USB serial driver */
+
+#if defined(CONFIG_PL2303) || defined(CONFIG_CDCACM)
+#ifdef CONFIG_CDCACM
+ ret = cdcacm_initialize(CONFIG_NSH_UBSDEV_MINOR, NULL);
+#else
+ ret = usbdev_serialinitialize(CONFIG_NSH_UBSDEV_MINOR);
+#endif
+ DEBUGASSERT(ret == OK);
+#endif
+
+ /* 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 waiting 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;
+ }
+ }
+ while (nlc < 3);
+
+ /* Make sure the stdin, stdout, and stderr are closed */
+
+ (void)fclose(stdin);
+ (void)fclose(stdout);
+ (void)fclose(stderr);
+
+ /* Dup the fd to create standard fd 0-2 */
+
+ (void)dup2(fd, 0);
+ (void)dup2(fd, 1);
+ (void)dup2(fd, 2);
+
+ /* We can close the original file descriptor now (unless it was one of 0-2) */
+
+ if (fd > 2)
+ {
+ close(fd);
+ }
+
+ /* fdopen to get the stdin, stdout and stderr streams. The following logic depends
+ * on the fact that the library layer will allocate FILEs in order. And since
+ * we closed stdin, stdout, and stderr above, that is what we should get.
+ *
+ * fd = 0 is stdin (read-only)
+ * fd = 1 is stdout (write-only, append)
+ * fd = 2 is stderr (write-only, append)
+ */
+
+ (void)fdopen(0, "r");
+ (void)fdopen(1, "a");
+ (void)fdopen(2, "a");
+ return OK;
+}
+
+#endif /* HAVE_USB_CONSOLE */
+
+/****************************************************************************
+ * Name: nsh_usbtrace
+ ****************************************************************************/
+
+#if defined(CONFIG_USBDEV_TRACE) && defined(HAVE_USB_CONSOLE)
+void nsh_usbtrace(void)
+{
+ (void)usbtrace_enumerate(nsh_tracecallback, NULL);
+}
+#endif
+
+#endif /* CONFIG_USBDEV */
diff --git a/apps/nshlib/rcS.template b/apps/nshlib/rcS.template
new file mode 100644
index 000000000..996f37fb1
--- /dev/null
+++ b/apps/nshlib/rcS.template
@@ -0,0 +1,5 @@
+# Create a RAMDISK and mount it at XXXRDMOUNTPOUNTXXX
+
+mkrd -m XXXMKRDMINORXXX -s XXMKRDSECTORSIZEXXX XXMKRDBLOCKSXXX
+mkfatfs /dev/ramXXXMKRDMINORXXX
+mount -t vfat /dev/ramXXXMKRDMINORXXX XXXRDMOUNTPOUNTXXX