nuttx-apps/nshlib/nsh_command.c
Michal Lenc f81a094283 nshlib: add support for pkill command
This command looks through the currently running processes and kills
the those that match the selection criteria. This way system can send
signal to processes by name and without knowing the IDs.

Example (kill application hello):
	pkill -15 hello

The command can be turned off by NSH_DISABLE_PKILL option and depends
on FS_PROCFS.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
2024-09-23 08:40:54 +08:00

1330 lines
37 KiB
C

/****************************************************************************
* apps/nshlib/nsh_command.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#ifdef CONFIG_NSH_BUILTIN_APPS
# include <nuttx/lib/builtin.h>
#endif
#if defined(CONFIG_SYSTEM_READLINE) && defined(CONFIG_READLINE_HAVE_EXTMATCH)
# include "system/readline.h"
#endif
#include "nsh.h"
#include "nsh_console.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Help command summary layout */
#define HELP_LINELEN 80
#define HELP_TABSIZE 4
#define NUM_CMDS ((sizeof(g_cmdmap)/sizeof(struct cmdmap_s)) - 1)
/* Help marco for nsh command */
#ifdef CONFIG_NSH_DISABLE_HELP
# define CMD_MAP(cmd, handler, min, max, usage) \
{ cmd, handler, min, max }
#else
# define CMD_MAP(cmd, handler, min, max, usage) \
{ cmd, handler, min, max, usage }
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct cmdmap_s
{
FAR const char *cmd; /* Name of the command */
nsh_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) */
#ifndef CONFIG_NSH_DISABLE_HELP
FAR const char *usage; /* Usage instructions for 'help' command */
#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_HELP
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
#endif
#ifndef CONFIG_NSH_DISABLESCRIPT
static int cmd_true(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
static int cmd_false(FAR struct nsh_vtbl_s *vtbl, int argc,
FAR char **argv);
#endif
#ifndef CONFIG_NSH_DISABLE_EXIT
static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
#endif
#ifndef CONFIG_NSH_DISABLE_EXPR
static int cmd_expr(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv);
#endif
static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc,
FAR char **argv);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct cmdmap_s g_cmdmap[] =
{
#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_SOURCE)
CMD_MAP(".", cmd_source, 2, 2, "<script-path>"),
#endif
#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST)
CMD_MAP("[", cmd_lbracket,
4, CONFIG_NSH_MAXARGUMENTS, "<expression> ]"),
#endif
#ifndef CONFIG_NSH_DISABLE_HELP
CMD_MAP("?", cmd_help, 1, 1, NULL),
#endif
#if defined(CONFIG_NET) && defined(CONFIG_NET_ROUTE) && !defined(CONFIG_NSH_DISABLE_ADDROUTE)
CMD_MAP("addroute", cmd_addroute, 3, 4, "<target> [<netmask>] <router>"),
#endif
#ifdef CONFIG_NSH_ALIAS
CMD_MAP("alias", cmd_alias, 1, CONFIG_NSH_MAXARGUMENTS,
"[name[=value] ... ]"),
CMD_MAP("unalias", cmd_unalias, 1, CONFIG_NSH_MAXARGUMENTS,
"[-a] name [name ... ]"),
#endif
#if defined(CONFIG_NET) && defined(CONFIG_NET_ARP) && !defined(CONFIG_NSH_DISABLE_ARP)
CMD_MAP("arp", cmd_arp, 1, 6,
"[-i <ifname>] [-a <ipaddr>|-d <ipaddr>|-s <ipaddr> <hwaddr>]"),
#endif
#if defined(CONFIG_NETUTILS_CODECS) && defined(CONFIG_CODECS_BASE64)
# ifndef CONFIG_NSH_DISABLE_BASE64DEC
CMD_MAP("base64dec", cmd_base64decode,
2, 4, "[-w] [-f] <string or filepath>"),
# endif
# ifndef CONFIG_NSH_DISABLE_BASE64ENC
CMD_MAP("base64enc", cmd_base64encode,
2, 4, "[-w] [-f] <string or filepath>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_BASENAME
CMD_MAP("basename", cmd_basename, 2, 3, "<path> [<suffix>]"),
#endif
#if defined(CONFIG_BOARDCTL_BOOT_IMAGE) && !defined(CONFIG_NSH_DISABLE_BOOT)
CMD_MAP("boot", cmd_boot, 1, 3, "[<image path> [<header size>]]"),
#endif
#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_LOOPS)
CMD_MAP("break", cmd_break, 1, 1, NULL),
#endif
#ifndef CONFIG_NSH_DISABLE_CAT
CMD_MAP("cat", cmd_cat, 1, CONFIG_NSH_MAXARGUMENTS,
"[<path> [<path> [<path> ...]]]"),
#endif
#ifndef CONFIG_DISABLE_ENVIRON
# ifndef CONFIG_NSH_DISABLE_CD
CMD_MAP("cd", cmd_cd, 1, 2, "[<dir-path>|-|~|..]"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_CP
CMD_MAP("cp", cmd_cp, 3, 4, "[-r] <source-path> <dest-path>"),
#endif
#ifndef CONFIG_NSH_DISABLE_CMP
CMD_MAP("cmp", cmd_cmp, 3, 3, "<path1> <path2>"),
#endif
#ifndef CONFIG_NSH_DISABLE_DIRNAME
CMD_MAP("dirname", cmd_dirname, 2, 2, "<path>"),
#endif
#ifndef CONFIG_NSH_DISABLE_DATE
CMD_MAP("date", cmd_date,
1, 4, "[-s \"MMM DD HH:MM:SS YYYY\"] [-u] [+format]"),
#endif
#ifndef CONFIG_NSH_DISABLE_DD
CMD_MAP("dd", cmd_dd, 3, 7,
"if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] "
"[skip=<sectors>] [seek=<sectors>] [verify]"),
#endif
#if defined(CONFIG_NET) && defined(CONFIG_NET_ROUTE) && !defined(CONFIG_NSH_DISABLE_DELROUTE)
CMD_MAP("delroute", cmd_delroute, 2, 3, "<target> [<netmask>]"),
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && !defined(CONFIG_NSH_DISABLE_DF)
#ifdef NSH_HAVE_CATFILE
#if defined(HAVE_DF_HUMANREADBLE) && defined(HAVE_DF_BLOCKOUTPUT)
CMD_MAP("df", cmd_df, 1, 2, "[-h]"),
#else
CMD_MAP("df", cmd_df, 1, 1, NULL),
#endif
#endif
#endif
#if defined(CONFIG_SYSLOG_DEVPATH) && !defined(CONFIG_NSH_DISABLE_DMESG)
CMD_MAP("dmesg", cmd_dmesg, 1, 2, "[-c,--clear |-C,--read-clear]"),
#endif
#ifndef CONFIG_NSH_DISABLE_ECHO
# ifndef CONFIG_DISABLE_ENVIRON
CMD_MAP("echo", cmd_echo, 1, CONFIG_NSH_MAXARGUMENTS,
"[-n] [<string|$name> [<string|$name>...]]"),
# else
CMD_MAP("echo", cmd_echo, 1, CONFIG_NSH_MAXARGUMENTS,
"[-n] [<string> [<string>...]]"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_ENV
CMD_MAP("env", cmd_env, 1, 1, NULL),
#endif
#ifndef CONFIG_NSH_DISABLE_EXEC
CMD_MAP("exec", cmd_exec, 2, 3, "<hex-address>"),
#endif
#ifndef CONFIG_NSH_DISABLE_EXIT
CMD_MAP("exit", cmd_exit, 1, 1, NULL),
#endif
#ifndef CONFIG_NSH_DISABLE_EXPR
CMD_MAP("expr", cmd_expr, 4, 4,
"<operand1> <operator> <operand2>"),
#endif
#ifndef CONFIG_NSH_DISABLE_EXPORT
CMD_MAP("export", cmd_export, 2, 3, "[<name> [<value>]]"),
#endif
#ifndef CONFIG_NSH_DISABLESCRIPT
CMD_MAP("false", cmd_false, 1, 1, NULL),
#endif
#ifdef CONFIG_FS_PROCFS
# ifndef CONFIG_NSH_DISABLE_FDINFO
CMD_MAP("fdinfo", cmd_fdinfo, 1, 2, "[pid]"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_FREE
CMD_MAP("free", cmd_free, 1, 1, NULL),
#endif
#ifdef CONFIG_DEBUG_MM
# ifndef CONFIG_NSH_DISABLE_MEMDUMP
CMD_MAP("memdump", cmd_memdump,
1, 4, "[pid/used/free/on/off]" " <minseq> <maxseq>"),
# endif
#endif
#ifdef CONFIG_NET_UDP
# ifndef CONFIG_NSH_DISABLE_GET
CMD_MAP("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
CMD_MAP("help", cmd_help, 1, 2, "[<cmd>]"),
# else
CMD_MAP("help", cmd_help, 1, 3, "[-v] [<cmd>]"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_HEXDUMP
#ifndef CONFIG_NSH_CMDOPT_HEXDUMP
CMD_MAP("hexdump", cmd_hexdump, 2, 2, "<file or device>"),
#else
CMD_MAP("hexdump", cmd_hexdump, 2, 4,
"<file or device> [skip=<bytes>] [count=<bytes>]"),
#endif
#endif
#ifdef CONFIG_NET
# ifndef CONFIG_NSH_DISABLE_IFCONFIG
CMD_MAP("ifconfig", cmd_ifconfig, 1, 12,
"[interface [mtu <len>]|[address_family] [[add|del] <ip-address>|dhcp]]"
"[dr|gw|gateway <dr-address>] [netmask <net-mask>|prefixlen <len>] "
"[dns <dns-address>] [hw <hw-mac>]"),
# endif
# ifndef CONFIG_NSH_DISABLE_IFUPDOWN
CMD_MAP("ifdown", cmd_ifdown, 2, 2, "<interface>"),
CMD_MAP("ifup", cmd_ifup, 2, 2, "<interface>"),
# endif
#endif
#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS)
CMD_MAP("insmod", cmd_insmod, 3, 3, "<file-path> <module-name>"),
#endif
#ifdef HAVE_IRQINFO
CMD_MAP("irqinfo", cmd_irqinfo, 1, 1, NULL),
#endif
#ifndef CONFIG_NSH_DISABLE_KILL
CMD_MAP("kill", cmd_kill, 2, 3, "[-<signal>] <pid>"),
#endif
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_NSH_DISABLE_PKILL)
CMD_MAP("pkill", cmd_pkill, 2, 3, "[-<signal>] <name>"),
#endif
#ifndef CONFIG_DISABLE_MOUNTPOINT
# if defined(CONFIG_DEV_LOOP) && !defined(CONFIG_NSH_DISABLE_LOSETUP)
CMD_MAP("losetup", cmd_losetup, 3, 6,
"[-d <dev-path>] | [[-o <offset>] [-r] [-b <sect-size>] "
"<dev-path> <file-path>]"),
# endif
#endif
#ifndef CONFIG_DISABLE_MOUNTPOINT
# if defined(CONFIG_SMART_DEV_LOOP) && !defined(CONFIG_NSH_DISABLE_LOSMART)
CMD_MAP("losmart", cmd_losmart, 2, 11,
"[-d <dev-path>] | [[-m <minor>] [-o <offset>] [-e <erase-size>] "
"[-s <sect-size>] [-r] <file-path>]"),
# endif
#endif
#ifndef CONFIG_DISABLE_MOUNTPOINT
# if defined(CONFIG_MTD_LOOP) && !defined(CONFIG_NSH_DISABLE_LOMTD)
CMD_MAP("lomtd", cmd_lomtd, 3, 9,
"[-d <dev-path>] | [[-o <offset>] [-e <erase-size>] "
"[-b <sect-size>] <dev-path> <file-path>]]"),
# endif
#endif
#if !defined(CONFIG_NSH_DISABLE_LN) && defined(CONFIG_PSEUDOFS_SOFTLINKS)
CMD_MAP("ln", cmd_ln, 3, 4, "[-s] <target> <link>"),
#endif
#ifndef CONFIG_NSH_DISABLE_LS
CMD_MAP("ls", cmd_ls, 1, 5, "[-lRsh] <dir-path>"),
#endif
#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS)
# if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
CMD_MAP("lsmod", cmd_lsmod, 1, 1, NULL),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_MB
CMD_MAP("mb", cmd_mb, 2, 3,
"<hex-address>[=<hex-value>] [<hex-byte-count>]"),
#endif
#if defined(CONFIG_NETUTILS_CODECS) && defined(CONFIG_CODECS_HASH_MD5)
# ifndef CONFIG_NSH_DISABLE_MD5
CMD_MAP("md5", cmd_md5, 2, 3, "[-f] <string or filepath>"),
# endif
#endif
#ifdef NSH_HAVE_DIROPTS
# ifndef CONFIG_NSH_DISABLE_MKDIR
CMD_MAP("mkdir", cmd_mkdir, 2, 3, "[-p] <path>"),
# endif
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FSUTILS_MKFATFS)
# ifndef CONFIG_NSH_DISABLE_MKFATFS
CMD_MAP("mkfatfs", cmd_mkfatfs, 2, 6,
"[-F <fatsize>] [-r <rootdirentries>] <block-driver>"),
# endif
#endif
#ifndef CONFIG_DISABLE_MOUNTPOINT
# if defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0 && \
!defined(CONFIG_NSH_DISABLE_MKFIFO)
CMD_MAP("mkfifo", cmd_mkfifo, 2, 2, "<path>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_MKRD
CMD_MAP("mkrd", cmd_mkrd, 2, 6,
"[-m <minor>] [-s <sector-size>] <nsectors>"),
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_SMARTFS) && \
defined(CONFIG_FSUTILS_MKSMARTFS)
# ifndef CONFIG_NSH_DISABLE_MKSMARTFS
# ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
CMD_MAP("mksmartfs", cmd_mksmartfs, 2, 6,
"[-s <sector-size>] [-f] <path> [<num-root-directories>]"),
# else
CMD_MAP("mksmartfs", cmd_mksmartfs,
2, 5, "[-s <sector-size>] [-f] <path>"),
# endif
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_MH
CMD_MAP("mh", cmd_mh, 2, 3,
"<hex-address>[=<hex-value>] [<hex-byte-count>]"),
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT)
# ifndef CONFIG_NSH_DISABLE_MOUNT
# if defined(NSH_HAVE_CATFILE) && defined(HAVE_MOUNT_LIST)
CMD_MAP("mount", cmd_mount, 1, 7,
"[-t <fstype> [-o <options>] [<block-device>] <mount-point>]"),
# else
CMD_MAP("mount", cmd_mount, 4, 7,
"-t <fstype> [-o <options>] [<block-device>] <mount-point>"),
# endif
# endif
#endif
#ifdef NSH_HAVE_DIROPTS
# ifndef CONFIG_NSH_DISABLE_MV
CMD_MAP("mv", cmd_mv, 3, 3, "<old-path> <new-path>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_MW
CMD_MAP("mw", cmd_mw, 2, 3,
"<hex-address>[=<hex-value>] [<hex-byte-count>]"),
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_NET) && \
defined(CONFIG_NFS)
# ifndef CONFIG_NSH_DISABLE_NFSMOUNT
CMD_MAP("nfsmount", cmd_nfsmount, 4, 5,
"<server-address> <mount-point> <remote-path> [udp]"),
# endif
#endif
#if defined(CONFIG_LIBC_NETDB) && !defined(CONFIG_NSH_DISABLE_NSLOOKUP)
CMD_MAP("nslookup", cmd_nslookup, 2, 2, "<host-name>"),
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && \
defined(CONFIG_NSH_LOGIN_PASSWD) && \
!defined(CONFIG_FSUTILS_PASSWD_READONLY)
# ifndef CONFIG_NSH_DISABLE_PASSWD
CMD_MAP("passwd", cmd_passwd, 3, 3, "<username> <password>"),
# endif
#endif
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_NSH_DISABLE_PIDOF)
CMD_MAP("pidof", cmd_pidof, 2, 2, "<name>"),
#endif
#if defined(CONFIG_PM) && !defined(CONFIG_NSH_DISABLE_PMCONFIG)
CMD_MAP("pmconfig", cmd_pmconfig, 1, 4,
"[stay|relax] [normal|idle|standby|sleep] [domain]"),
#endif
#if defined(CONFIG_BOARDCTL_POWEROFF) && !defined(CONFIG_NSH_DISABLE_POWEROFF)
CMD_MAP("poweroff", cmd_poweroff, 1, 2, NULL),
CMD_MAP("quit", cmd_poweroff, 1, 2, NULL),
#endif
#ifndef CONFIG_NSH_DISABLE_PRINTF
# ifndef CONFIG_DISABLE_ENVIRON
CMD_MAP("printf", cmd_printf, 1, CONFIG_NSH_MAXARGUMENTS,
"[\\xNN] [\\n\\r\\t] [<string|$name> [<string|$name>...]]"),
# else
CMD_MAP("printf", cmd_printf, 1, CONFIG_NSH_MAXARGUMENTS,
"[\\xNN] [\\n\\r\\t] [<string> [<string>...]]"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_PS
CMD_MAP("ps", cmd_ps, 1, 1, NULL),
#endif
#ifdef CONFIG_NET_UDP
# ifndef CONFIG_NSH_DISABLE_PUT
CMD_MAP("put", cmd_put, 4, 7,
"[-b|-n] [-f <remote-path>] -h <ip-address> <local-path>"),
# endif
#endif
#ifndef CONFIG_DISABLE_ENVIRON
# ifndef CONFIG_NSH_DISABLE_PWD
CMD_MAP("pwd", cmd_pwd, 1, 1, NULL),
# endif
#endif
#if !defined(CONFIG_NSH_DISABLE_READLINK) && defined(CONFIG_PSEUDOFS_SOFTLINKS)
CMD_MAP("readlink", cmd_readlink, 2, 2, "<link>"),
#endif
#if defined(CONFIG_BOARDCTL_RESET) && !defined(CONFIG_NSH_DISABLE_REBOOT)
CMD_MAP("reboot", cmd_reboot, 1, 2, NULL),
#endif
#if defined(CONFIG_BOARDCTL_RESET_CAUSE) && !defined(CONFIG_NSH_DISABLE_RESET_CAUSE)
CMD_MAP("resetcause", cmd_reset_cause, 1, 1, NULL),
#endif
#if defined(CONFIG_BOARDCTL_IRQ_AFFINITY) && !defined(CONFIG_NSH_DISABLE_IRQ_AFFINITY)
CMD_MAP("irqaff", cmd_irq_affinity, 3, 3,
"irqaff [IRQ Number] [Core Mask]"),
#endif
#ifdef NSH_HAVE_DIROPTS
# ifndef CONFIG_NSH_DISABLE_RM
CMD_MAP("rm", cmd_rm, 2, 3, "[-rf] <file-path>"),
# endif
#endif
#ifdef NSH_HAVE_DIROPTS
# ifndef CONFIG_NSH_DISABLE_RMDIR
CMD_MAP("rmdir", cmd_rmdir, 2, 2, "<dir-path>"),
# endif
#endif
#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS)
CMD_MAP("rmmod", cmd_rmmod, 2, 2, "<module-name>"),
#endif
#ifndef CONFIG_NSH_DISABLE_ROUTE
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
CMD_MAP("route", cmd_route, 2, 2, "ipv4|ipv6"),
#elif defined(CONFIG_NET_IPv4)
CMD_MAP("route", cmd_route, 1, 2, "[ipv4]"),
#elif defined(CONFIG_NET_IPv6)
CMD_MAP("route", cmd_route, 1, 2, "[ipv6]"),
#endif
#endif
#if defined(CONFIG_RPMSG) && !defined(CONFIG_NSH_DISABLE_RPMSG)
CMD_MAP("rpmsg", cmd_rpmsg, 2, 7,
"<panic|dump|ping> <path|all>"
" [value|times length ack sleep]"),
#endif
#if defined(CONFIG_RPTUN) && !defined(CONFIG_NSH_DISABLE_RPTUN)
CMD_MAP("rptun", cmd_rptun, 2, 7,
"<start|stop|reset|panic|dump|ping> <path|all>"
" [value|times length ack sleep]"),
#endif
#ifndef CONFIG_NSH_DISABLE_SET
#ifdef CONFIG_NSH_VARS
# if !defined(CONFIG_DISABLE_ENVIRON) && !defined(CONFIG_NSH_DISABLESCRIPT)
CMD_MAP("set", cmd_set,
1, 4, "[{+|-}{e|x|xe|ex}] [<name> <value>]"),
# elif !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_NSH_DISABLESCRIPT)
CMD_MAP("set", cmd_set, 1, 3, "[<name> <value>]"),
# elif defined(CONFIG_DISABLE_ENVIRON) && !defined(CONFIG_NSH_DISABLESCRIPT)
CMD_MAP("set", cmd_set, 1, 2, "[{+|-}{e|x|xe|ex}]"),
# endif
#else
# if !defined(CONFIG_DISABLE_ENVIRON) && !defined(CONFIG_NSH_DISABLESCRIPT)
CMD_MAP("set", cmd_set,
2, 4, "[{+|-}{e|x|xe|ex}] [<name> <value>]"),
# elif !defined(CONFIG_DISABLE_ENVIRON) && defined(CONFIG_NSH_DISABLESCRIPT)
CMD_MAP("set", cmd_set, 3, 3, "<name> <value>"),
# elif defined(CONFIG_DISABLE_ENVIRON) && !defined(CONFIG_NSH_DISABLESCRIPT)
CMD_MAP("set", cmd_set, 2, 2, "{+|-}{e|x|xe|ex}"),
# endif
#endif
#endif /* CONFIG_NSH_DISABLE_SET */
#ifndef CONFIG_NSH_DISABLE_SHUTDOWN
#if defined(CONFIG_BOARDCTL_POWEROFF) && defined(CONFIG_BOARDCTL_RESET)
CMD_MAP("shutdown", cmd_shutdown, 1, 2, "[--reboot]"),
#elif defined(CONFIG_BOARDCTL_POWEROFF)
CMD_MAP("shutdown", cmd_shutdown, 1, 1, NULL),
#elif defined(CONFIG_BOARDCTL_RESET)
CMD_MAP("shutdown", cmd_shutdown, 2, 2, "--reboot"),
#endif
#endif
#ifndef CONFIG_NSH_DISABLE_SLEEP
CMD_MAP("sleep", cmd_sleep, 2, 2, "<sec>"),
#endif
#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_SOURCE)
CMD_MAP("source", cmd_source, 2, 2, "<script-path>"),
#endif
#if defined(CONFIG_BOARDCTL_SWITCH_BOOT) && !defined(CONFIG_NSH_DISABLE_SWITCHBOOT)
CMD_MAP("swtichboot", cmd_switchboot, 2, 2, "<image path>"),
#endif
#if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST)
CMD_MAP("test", cmd_test,
3, CONFIG_NSH_MAXARGUMENTS, "<expression>"),
#endif
#ifndef CONFIG_NSH_DISABLE_TIME
CMD_MAP("time", cmd_time, 2, 2, "\"<command>\""),
#endif
#ifndef CONFIG_NSH_DISABLE_TIMEDATECTL
CMD_MAP("timedatectl", cmd_timedatectl, 1, 3, "[set-timezone TZ]"),
#endif
#ifndef CONFIG_NSH_DISABLESCRIPT
CMD_MAP("true", cmd_true, 1, 1, NULL),
#endif
#ifndef CONFIG_DISABLE_MOUNTPOINT
# ifndef CONFIG_NSH_DISABLE_TRUNCATE
CMD_MAP("truncate", cmd_truncate, 4, 4, "-s <length> <file-path>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_UNAME
# ifdef CONFIG_NET
CMD_MAP("uname", cmd_uname, 1, 7, "[-a | -imnoprsv]"),
# else
CMD_MAP("uname", cmd_uname, 1, 7, "[-a | -imoprsv]"),
# endif
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT)
# ifndef CONFIG_NSH_DISABLE_UMOUNT
CMD_MAP("umount", cmd_umount, 2, 2, "<dir-path>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_UNSET
CMD_MAP("unset", cmd_unset, 2, 2, "<name>"),
#endif
#ifndef CONFIG_NSH_DISABLE_UPTIME
CMD_MAP("uptime", cmd_uptime, 1, 2, "[-sph]"),
#endif
#if defined(CONFIG_NETUTILS_CODECS) && defined(CONFIG_CODECS_URLCODE)
# ifndef CONFIG_NSH_DISABLE_URLDECODE
CMD_MAP("urldecode", cmd_urldecode, 2, 3, "[-f] <string or filepath>"),
# endif
# ifndef CONFIG_NSH_DISABLE_URLENCODE
CMD_MAP("urlencode", cmd_urlencode, 2, 3, "[-f] <string or filepath>"),
# endif
#endif
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && \
defined(CONFIG_NSH_LOGIN_PASSWD) && \
!defined(CONFIG_FSUTILS_PASSWD_READONLY)
# ifndef CONFIG_NSH_DISABLE_USERADD
CMD_MAP("useradd", cmd_useradd, 3, 3, "<username> <password>"),
# endif
# ifndef CONFIG_NSH_DISABLE_USERDEL
CMD_MAP("userdel", cmd_userdel, 2, 2, "<username>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_USLEEP
CMD_MAP("usleep", cmd_usleep, 2, 2, "<usec>"),
#endif
#ifdef CONFIG_NET_TCP
# ifndef CONFIG_NSH_DISABLE_WGET
CMD_MAP("wget", cmd_wget, 2, 4, "[-o <local-path>] <url>"),
# endif
#endif
#ifndef CONFIG_NSH_DISABLE_XD
CMD_MAP("xd", cmd_xd, 3, 3, "<hex-address> <byte-count>"),
#endif
CMD_MAP(NULL, NULL, 1, 1, NULL)
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: help_cmdlist
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_HELP
static inline void help_cmdlist(FAR struct nsh_vtbl_s *vtbl)
{
unsigned int colwidth;
unsigned int cmdwidth;
unsigned int cmdsperline;
unsigned int ncmdrows;
unsigned int i;
unsigned int j;
unsigned int k;
unsigned int offset;
/* Extra 5 bytes for tab before newline and '\0' */
char line[HELP_LINELEN + HELP_TABSIZE + 1];
/* Pick an optimal column width */
for (k = 0, colwidth = 0; k < NUM_CMDS; k++)
{
cmdwidth = strlen(g_cmdmap[k].cmd);
if (cmdwidth > colwidth)
{
colwidth = cmdwidth;
}
}
colwidth += HELP_TABSIZE;
/* Determine the number of commands to put on one line */
if (colwidth > HELP_LINELEN)
{
cmdsperline = 1;
}
else
{
cmdsperline = HELP_LINELEN / colwidth;
}
/* Determine the total number of lines to output */
ncmdrows = (NUM_CMDS + (cmdsperline - 1)) / cmdsperline;
/* Print the command name in 'ncmdrows' rows with 'cmdsperline' commands
* on each line.
*/
for (i = 0; i < ncmdrows; i++)
{
/* Tab before a new line */
offset = HELP_TABSIZE;
memset(line, ' ', offset);
for (j = 0, k = i;
j < cmdsperline && k < NUM_CMDS;
j++, k += ncmdrows)
{
/* Copy the cmd name to line buffer */
offset += strlcpy(line + offset, g_cmdmap[k].cmd,
sizeof(line) - offset);
/* Add space between commands */
for (cmdwidth = strlen(g_cmdmap[k].cmd);
cmdwidth < colwidth;
cmdwidth++)
{
line[offset++] = ' ';
}
}
line[offset++] = '\n';
nsh_write(vtbl, line, offset);
}
}
#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\n");
#else
nsh_output(vtbl, " <cmd> [> <file>|>> <file>]\n\n");
#endif
#ifndef CONFIG_NSH_DISABLESCRIPT
#ifndef CONFIG_NSH_DISABLE_ITEF
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
#ifndef CONFIG_NSH_DISABLE_LOOPS
nsh_output(vtbl, "OR\n");
nsh_output(vtbl, " while <cmd>\n");
nsh_output(vtbl, " do\n");
nsh_output(vtbl, " [sequence of <cmd>]\n");
nsh_output(vtbl, " done\n\n");
nsh_output(vtbl, "OR\n");
nsh_output(vtbl, " until <cmd>\n");
nsh_output(vtbl, " do\n");
nsh_output(vtbl, " [sequence of <cmd>]\n");
nsh_output(vtbl, " done\n\n");
#endif
#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_error(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)
{
UNUSED(vtbl);
#ifdef CONFIG_NSH_BUILTIN_APPS
FAR const struct builtin_s *builtin;
unsigned int builtins_per_line;
unsigned int num_builtin_rows;
unsigned int builtin_width;
unsigned int num_builtins;
unsigned int column_width;
unsigned int i;
unsigned int j;
unsigned int k;
unsigned int offset;
/* Extra 5 bytes for tab before newline and '\0' */
char line[HELP_LINELEN + HELP_TABSIZE + 1];
static FAR const char *const g_builtin_prompt = "\nBuiltin Apps:\n";
/* Count the number of built-in commands and get the optimal column width */
num_builtins = 0;
column_width = 0;
for (i = 0; (builtin = builtin_for_index(i)) != NULL; i++)
{
if (builtin->main == NULL)
{
continue;
}
num_builtins++;
builtin_width = strlen(builtin->name);
if (builtin_width > column_width)
{
column_width = builtin_width;
}
}
/* Skip the printing if no available built-in commands */
if (num_builtins == 0)
{
return;
}
column_width += HELP_TABSIZE;
/* Determine the number of commands to put on one line */
if (column_width > HELP_LINELEN)
{
builtins_per_line = 1;
}
else
{
builtins_per_line = HELP_LINELEN / column_width;
}
/* Determine the total number of lines to output */
num_builtin_rows = ((num_builtins + (builtins_per_line - 1)) /
builtins_per_line);
/* List the set of available built-in commands */
nsh_write(vtbl, g_builtin_prompt, strlen(g_builtin_prompt));
for (i = 0; i < num_builtin_rows; i++)
{
offset = HELP_TABSIZE;
memset(line, ' ', offset);
for (j = 0, k = i;
j < builtins_per_line &&
(builtin = builtin_for_index(k));
j++, k += num_builtin_rows)
{
if (builtin->main == NULL)
{
continue;
}
offset += strlcpy(line + offset, builtin->name,
sizeof(line) - offset);
for (builtin_width = strlen(builtin->name);
builtin_width < column_width;
builtin_width++)
{
line[offset++] = ' ';
}
}
line[offset++] = '\n';
nsh_write(vtbl, line, offset);
}
#endif
}
#endif
/****************************************************************************
* Name: cmd_help
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_HELP
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 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,
FAR char **argv)
{
UNUSED(argc);
nsh_error(vtbl, g_fmtcmdnotfound, argv[0]);
return ERROR;
}
/****************************************************************************
* Name: cmd_true
****************************************************************************/
#ifndef CONFIG_NSH_DISABLESCRIPT
static int cmd_true(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
{
UNUSED(vtbl);
UNUSED(argc);
UNUSED(argv);
return OK;
}
#endif
/****************************************************************************
* Name: cmd_false
****************************************************************************/
#ifndef CONFIG_NSH_DISABLESCRIPT
static int cmd_false(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
{
UNUSED(vtbl);
UNUSED(argc);
UNUSED(argv);
return ERROR;
}
#endif
/****************************************************************************
* Name: cmd_exit
****************************************************************************/
#ifndef CONFIG_NSH_DISABLE_EXIT
static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
{
UNUSED(argc);
UNUSED(argv);
nsh_exit(vtbl, 0);
return OK;
}
#endif
#ifndef CONFIG_NSH_DISABLE_EXPR
static int cmd_expr(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
{
int operand1;
int operand2;
int result;
FAR char *endptr;
if (argc != 4)
{
nsh_output(vtbl, "Usage: %s <operand1> <operator> <operand2>\n",
argv[0]);
return ERROR;
}
operand1 = strtol(argv[1], &endptr, 0);
if (*endptr != '\0')
{
nsh_output(vtbl, "operand1 invalid\n");
return ERROR;
}
operand2 = strtol(argv[3], &endptr, 0);
if (*endptr != '\0')
{
nsh_output(vtbl, "operand2 invalid\n");
return ERROR;
}
switch (argv[2][0])
{
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
if (operand2 == 0)
{
nsh_output(vtbl, "operand2 invalid\n");
return ERROR;
}
result = operand1 / operand2;
break;
case '%':
if (operand2 == 0)
{
nsh_output(vtbl, "operand2 invalid\n");
return ERROR;
}
result = operand1 % operand2;
break;
default:
nsh_output(vtbl, "Unknown operator\n");
return ERROR;
}
nsh_output(vtbl, "%d\n", result);
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nsh_command
*
* Description:
* Execute the command in argv[0]
*
* Returned Value:
* -1 (ERROR) if the command was unsuccessful
* 0 (OK) if the command was successful
*
****************************************************************************/
int nsh_command(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char *argv[])
{
const struct cmdmap_s *cmdmap;
const char *cmd;
nsh_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 CONFIG_NSH_MAXARGUMENTS)
* argv[argc]: NULL terminating pointer
*/
cmd = argv[0];
/* 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_error(vtbl, g_fmtargrequired, cmd);
return ERROR;
}
else if (argc > cmdmap->maxargs)
{
/* More than the maximum number were provided */
nsh_error(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_extmatch_count
*
* Description:
* This support function is used to provide support for realine tab-
* completion logic nsh_extmatch_count() counts the number of matching
* nsh command names
*
* Input Parameters:
* name - A point to the name containing the name to be matched.
* matches - A table is size CONFIG_READLINE_MAX_EXTCMDS that can
* be used to remember matching name indices.
* namelen - The length of the name to match
*
* Returned Values:
* The number commands that match to the first namelen characters.
*
****************************************************************************/
#if defined(CONFIG_NSH_READLINE) && defined(CONFIG_READLINE_TABCOMPLETION) && \
defined(CONFIG_READLINE_HAVE_EXTMATCH)
int nsh_extmatch_count(FAR char *name, FAR int *matches, int namelen)
{
int nr_matches = 0;
int i;
for (i = 0; i < (int)NUM_CMDS; i++)
{
if (strncmp(name, g_cmdmap[i].cmd, namelen) == 0)
{
matches[nr_matches] = i;
nr_matches++;
if (nr_matches >= CONFIG_READLINE_MAX_EXTCMDS)
{
break;
}
}
}
return nr_matches;
}
#endif
/****************************************************************************
* Name: nsh_extmatch_getname
*
* Description:
* This support function is used to provide support for realine tab-
* completion logic nsh_extmatch_getname() will return the full command
* string from an index that was previously saved by nsh_exmatch_count().
*
* Input Parameters:
* index - The index of the command name to be returned.
*
* Returned Values:
* The numb
*
****************************************************************************/
#if defined(CONFIG_NSH_READLINE) && defined(CONFIG_READLINE_TABCOMPLETION) && \
defined(CONFIG_READLINE_HAVE_EXTMATCH)
FAR const char *nsh_extmatch_getname(int index)
{
DEBUGASSERT(index > 0 && index <= (int)NUM_CMDS);
return g_cmdmap[index].cmd;
}
#endif