Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions Documentation/applications/system/toybox/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
===================================
``toybox`` Toybox Command Suite
===================================

Overview
========

Toybox (https://landley.net/toybox/) is a 0BSD-licensed multi-call binary
providing a POSIX/LSB command suite and a small interactive shell. The
``toybox`` application downloads a pinned upstream release during the
build, patches it for NuttX, and builds it as a single NuttX task
(``PROGNAME=toybox``).

Run with no arguments it acts as an interactive ``toybox>`` command
prompt, suitable for use as the system's ``CONFIG_INIT_ENTRYPOINT``. Run
with arguments (``toybox ls``, ``toybox cat file``) it runs one command
and exits, which is how it is invoked as an NSH builtin.

Toybox does not depend on NSH in either direction. When both are enabled,
each can invoke the other at runtime: NSH via its own
``CONFIG_NSH_BUILTIN_APPS``, Toybox via ``CONFIG_SYSTEM_TOYBOX_BUILTIN_BRIDGE``.

Configuration
=============

Enable the application with ``CONFIG_SYSTEM_TOYBOX``, under
:menuselection:`System Libraries and NSH Add-Ons` in ``menuconfig``.

- ``CONFIG_SYSTEM_TOYBOX_VERSION`` -- upstream release tag to download
- ``CONFIG_SYSTEM_TOYBOX_PRIORITY``, ``CONFIG_SYSTEM_TOYBOX_STACKSIZE``
- ``CONFIG_SYSTEM_TOYBOX_BUILTIN_BRIDGE`` -- run other NuttX builtin
applications (``nsh``, ``hello``, ...) from the Toybox prompt

Which commands are built in is selected individually under the "Toybox
commands" submenu (one ``CONFIG_SYSTEM_TOYBOX_CMD_<NAME>`` option per
applet).

Usage
=====

.. code-block:: console

nsh> toybox ls /
nsh> toybox

The second form starts the interactive prompt; ``exit`` or ``quit``
leaves it.

Known limitations
=================

- ``ps`` builds but lists no processes: it parses Linux's
``/proc/<pid>/stat``, which has no equivalent in NuttX's procfs.
- ``grep -r`` is unreliable against procfs.
53 changes: 53 additions & 0 deletions boards/arm/stm32f4/stm32f4discovery/configs/toybox/defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_ARCH_FPU is not set
CONFIG_ALLOW_MIT_COMPONENTS=y
CONFIG_ARCH="arm"
CONFIG_ARCH_BOARD="stm32f4discovery"
CONFIG_ARCH_BOARD_STM32F4_DISCOVERY=y
CONFIG_ARCH_BUTTONS=y
CONFIG_ARCH_CHIP="stm32f4"
CONFIG_ARCH_CHIP_STM32=y
CONFIG_ARCH_CHIP_STM32F407VG=y
CONFIG_ARCH_CHIP_STM32F4=y
CONFIG_ARCH_SETJMP_H=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_EXAMPLES_HELLO=y
CONFIG_FS_NOTIFY=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_HOST_WINDOWS=y
CONFIG_INIT_ENTRYPOINT="toybox_main"
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBC_LOCALE=y
CONFIG_LIBC_LOCALTIME=y
CONFIG_LINE_MAX=64
CONFIG_MM_REGIONS=2
CONFIG_PIPES=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_STM32_JTAG_SW_ENABLE=y
CONFIG_STM32_PWR=y
CONFIG_STM32_SPI1=y
CONFIG_STM32_USART2=y
CONFIG_SYSTEM_TOYBOX=y
CONFIG_USART2_RXBUFSIZE=128
CONFIG_USART2_SERIAL_CONSOLE=y
CONFIG_USART2_TXBUFSIZE=128
79 changes: 79 additions & 0 deletions boards/sim/sim/sim/configs/toybox/defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
CONFIG_ARCH="sim"
CONFIG_ARCH_BOARD="sim"
CONFIG_ARCH_BOARD_SIM=y
CONFIG_ARCH_CHIP="sim"
CONFIG_ARCH_SIM=y
CONFIG_BOARDCTL=y
CONFIG_BOARDCTL_APP_SYMTAB=y
CONFIG_BOARDCTL_MKRD=y
CONFIG_BOARDCTL_POWEROFF=y
CONFIG_BOARD_LOOPSPERMSEC=0
CONFIG_BOOT_RUNFROMEXTSRAM=y
CONFIG_COVERAGE_ALL=y
CONFIG_COVERAGE_TOOLCHAIN=y
CONFIG_DEBUG_ASSERTIONS=y
CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEV_GPIO=y
CONFIG_DEV_LOOP=y
CONFIG_ETC_FATDEVNO=2
CONFIG_ETC_ROMFS=y
CONFIG_ETC_ROMFSDEVNO=1
CONFIG_EXAMPLES_GPIO=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_FAT_LCNAMES=y
CONFIG_FAT_LFN=y
CONFIG_FS_BINFS=y
CONFIG_FS_FAT=y
CONFIG_FS_HOSTFS=y
CONFIG_FS_PROCFS=y
CONFIG_FS_RAMMAP=y
CONFIG_FS_ROMFS=y
CONFIG_GPIO_LOWER_HALF=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="toybox_main"
CONFIG_IOEXPANDER=y
CONFIG_IOEXPANDER_DUMMY=y
CONFIG_LIBC_ENVPATH=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBC_LOCALE=y
CONFIG_LIBC_LOCALE_CATALOG=y
CONFIG_LIBC_LOCALE_GETTEXT=y
CONFIG_LIBC_LOCALTIME=y
Comment thread
acassis marked this conversation as resolved.
CONFIG_LIBC_MAX_EXITFUNS=1
CONFIG_LIBC_NUMBERED_ARGS=y
CONFIG_NDEBUG=y
CONFIG_PATH_INITIAL="/bin"
CONFIG_PIPES=y
CONFIG_PSEUDOFS_ATTRIBUTES=y
CONFIG_PSEUDOFS_FILE=y
CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_EDIT_EMACS=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_RTC=y
CONFIG_RTC_ARCH=y
CONFIG_RTC_DRIVER=y
CONFIG_SCHED_BACKTRACE=y
CONFIG_SCHED_EVENTS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SCHED_WAITPID=y
CONFIG_SIM_HOSTFS=y
CONFIG_SIM_WALLTIME_SIGNAL=y
CONFIG_START_MONTH=6
CONFIG_START_YEAR=2008
CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_DUMPSTACK=y
CONFIG_SYSTEM_GCOV=y
CONFIG_SYSTEM_READLINE=y
CONFIG_SYSTEM_TOYBOX=y
CONFIG_TESTING_OSTEST=y
29 changes: 23 additions & 6 deletions fs/inode/fs_inodesearch.c
Original file line number Diff line number Diff line change
Expand Up @@ -558,15 +558,32 @@ FAR const char *inode_nextname(FAR const char *name)
name++;
}

/* Skip single '.' path segment, but not '..' */
/* Skip single '.' path segment, but not '..'. This includes a lone
* trailing '.' as the final path component (e.g. "/foo/."), which
* refers to "foo" itself the same way "/foo/./" would -- without this,
* a trailing '.' is instead treated as a literal child name to look up
* under "foo" and fails to resolve, since no real node is ever named
* ".", rather than resolving to the node the search already reached.
*/

if (*name == '.' && *(name + 1) == '/')
if (*name == '.' && (*(name + 1) == '/' || *(name + 1) == '\0'))
{
/* If there is a '/' after '.',
* continue searching from the next character
*/
if (*(name + 1) == '/')
{
/* If there is a '/' after '.',
* continue searching from the next character
*/

name = inode_nextname(name);
name = inode_nextname(name);
}
else
{
/* Lone trailing '.': point past it, at the terminating NUL,
* the same as if the path had ended one character earlier.
*/

name++;
}
}

return name;
Expand Down
9 changes: 9 additions & 0 deletions include/sys/wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ pid_t wait(FAR int *stat_loc);
int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options);
pid_t waitpid(pid_t pid, FAR int *stat_loc, int options);

/* wait4() is waitpid() plus the reaped child's struct rusage in one call.
* struct rusage is forward-declared here (not #include <sys/resource.h>)
* since it is only ever used as a pointer type in this prototype.
*/

struct rusage;
pid_t wait4(pid_t pid, FAR int *stat_loc, int options,
FAR struct rusage *rusage);

#undef EXTERN
#if defined(__cplusplus)
}
Expand Down
10 changes: 9 additions & 1 deletion libs/libc/grp/lib_getgrbufr.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,15 @@ int getgrbuf_r(gid_t gid, FAR const char *name, FAR const char *passwd,

namesize = strlen(name) + 1;
passwdsize = strlen(passwd) + 1;
padlen = sizeof(FAR void *) - ((uintptr_t)buf % sizeof(FAR char *));

/* Bytes needed to round 'buf' up to the next pointer-aligned address.
* The two's-complement modulo trick below yields 0 when 'buf' is
* already aligned; "sizeof(void *) - (addr % sizeof(void *))" (the
* previous formula) does not, always returning a full alignment unit
* in that case, which made the buflen check below always fail.
*/

padlen = (-(uintptr_t)buf) % sizeof(FAR void *);
reqdlen = sizeof(FAR void *) + namesize + passwdsize;

if (buflen < padlen + reqdlen)
Expand Down
4 changes: 4 additions & 0 deletions libs/libc/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ set(SRCS
lib_confstr.c
lib_ulimit.c)

if(CONFIG_SCHED_WAITPID)
list(APPEND SRCS lib_wait4.c)
endif()

if(NOT CONFIG_SCHED_USER_IDENTITY)
list(
APPEND
Expand Down
4 changes: 4 additions & 0 deletions libs/libc/unistd/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ CSRCS += lib_getsid.c lib_getgroups.c lib_setpgid.c lib_setsid.c
CSRCS += lib_lockf.c lib_flock.c lib_getpass.c
CSRCS += lib_chdir.c lib_fchdir.c lib_confstr.c lib_ulimit.c

ifeq ($(CONFIG_SCHED_WAITPID),y)
CSRCS += lib_wait4.c
endif

ifneq ($(CONFIG_SCHED_USER_IDENTITY),y)
CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c
CSRCS += lib_seteuid.c lib_setegid.c lib_geteuid.c lib_getegid.c
Expand Down
64 changes: 64 additions & 0 deletions libs/libc/unistd/lib_wait4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/****************************************************************************
* libs/libc/unistd/lib_wait4.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <sys/wait.h>
#include <sys/resource.h>

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: wait4
*
* Description:
* wait4() is waitpid() plus the reaped child's resource usage in one
* call. Built entirely on top of the existing waitpid()/getrusage()
* primitives (each already correctly proxied across build separation --
* waitpid() is a real syscall, getrusage() is plain libc), so this needs
* no syscall plumbing of its own and works unmodified in flat,
* protected, and kernel builds alike.
*
* NuttX's getrusage() only supports RUSAGE_SELF/RUSAGE_CHILDREN (not a
* specific pid), so the returned usage is exact only when the caller has
* a single outstanding child at a time.
*
****************************************************************************/

pid_t wait4(pid_t pid, FAR int *stat_loc, int options,
FAR struct rusage *rusage)
{
pid_t ret = waitpid(pid, stat_loc, options);

if (ret > 0 && rusage != NULL)
{
getrusage(RUSAGE_CHILDREN, rusage);
}

return ret;
}
Loading