u-boot/common/cli_hush_modern.c

324 lines
6.8 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0+
/*
* This file defines the compilation unit for the new hush shell version. The
* actual implementation from upstream BusyBox can be found in
* `cli_hush_upstream.c` which is included at the end of this file.
*
* This "wrapper" technique is used to keep the changes to the upstream version
* as minmal as possible. Instead, all defines and redefines necessary are done
* here, outside the upstream sources. This will hopefully make upgrades to
* newer revisions much easier.
*
* Copyright (c) 2021, Harald Seiler, DENX Software Engineering, hws@denx.de
*/
#include <env.h>
#include <malloc.h> /* malloc, free, realloc*/
#include <linux/ctype.h> /* isalpha, isdigit */
#include <console.h>
#include <bootretry.h>
#include <cli.h>
#include <cli_hush.h>
#include <command.h> /* find_cmd */
#include <asm/global_data.h>
/*
* BusyBox Version: UPDATE THIS WHEN PULLING NEW UPSTREAM REVISION!
*/
cli: modern_hush: Add upstream commits up to 2nd October 2023. This commit adds the following hush busybox upstream commits: 791b222dd55d ("sleep: fix "sleep -- ARGS"") 5353df91cba7 ("Update applet size estimates") e41e481fd571 ("hush: fix a compile failure") 07a95cfcabb0 ("ash: disable check for "good" function name, bash does not check this") e5692e2342c6 ("hush: quote values in "readonly" output") 96769486e20f ("shell: move varcmp() to shell_common.h and use it in hush") bab8828b0dad ("hush: fix expansion of space in "a=${a:+$a }c" construct") b5be8da350b5 ("hush: make "false" built-in") 6824298ab4d3 ("hush: fix ELIF cmd1;cmd2 THEN ... not executing cmd2, closes 15571") 3a7f00eadcf4 ("hush: add comment about abort on syntax error %{^}") acae889dd972 ("ash,hush: tab completion of functions and aliases") 90b607d79a13 ("hush: quote variable values printed by "set" (match ash behavior)") 6748e6494c22 ("hush (NOMMU): fix LINENO in execed children") fd5fb2d2b596 ("hush: speed up "big heredoc" code") 1409432d072e ("hush: add TODO comment") 93ae7464e6e4 ("hush: restore SIGHUP handling, this time explain why we do what we do") 1fdb33bd07e5 ("hush: restore tty pgrp on SIGHUP") 6101b6d3eaa0 ("hush: remove special handling of SIGHUP") 93e0898c663a ("shell: fix SIGWINCH and SIGCHLD (in hush) interrupting line input, closes 15256") 969e00816835 ("hush: code shrink") 27be0e8cfeb6 ("shell: fix compile failures in some configs") 7d1c7d833785 ("ash,hush: use HOME for tab completion and prompts") 21afddefd258 ("hush: fix "error: invalid preprocessing directive ##"") e53c7dbafc78 ("hush: fix set -n to act immediately, not just after run_list()") 574b9c446da1 ("hush: fix var_LINENO3.tests failure") 49bcf9f40cff ("hush: speed up ${x//\*/|} too") 53b2fdcdba4c ("*: add NOINLINEs where code noticeably shrinks") 7c3e96d4b3d4 ("shell: use more compact SHELL_ASH / HUSH config defines. no code changes") 62f1eed1e191 ("hush: in a comment, document what -i might be doing") aaf3d5ba74c5 ("shell: tweak --help") db5546ca1018 ("libbb: code shrink: introduce and use [_]exit_SUCCESS()") 931c55f9e2b4 ("libbb: invert the meaning of SETUP_ENV_NO_CHDIR -> SETUP_ENV_CHDIR") 12566e7f9b5e ("ash,hush: fix handling of SIGINT while waiting for interactive input") 987be932ed3c ("*: slap on a few ALIGN_PTR where appropriate") Signed-off-by: Francis Laniel <francis.laniel@amarulasolutions.com>
2023-12-22 21:02:42 +00:00
#define BB_VER "1.35.0.git7d1c7d833785"
/*
* Define hush features by the names used upstream.
*/
#define ENABLE_HUSH_INTERACTIVE 1
#define ENABLE_FEATURE_EDITING 1
#define ENABLE_HUSH_IF 1
#define ENABLE_HUSH_LOOPS 1
/* No MMU in U-Boot */
#define BB_MMU 0
#define USE_FOR_NOMMU(...) __VA_ARGS__
#define USE_FOR_MMU(...)
/*
* Size-saving "small" ints (arch-dependent)
*/
#if CONFIG_IS_ENABLED(X86) || CONFIG_IS_ENABLED(X86_64) || CONFIG_IS_ENABLED(MIPS)
/* add other arches which benefit from this... */
typedef signed char smallint;
typedef unsigned char smalluint;
#else
/* for arches where byte accesses generate larger code: */
typedef int smallint;
typedef unsigned smalluint;
#endif
/*
* Alignment defines used by BusyBox.
*/
#define ALIGN1 __attribute__((aligned(1)))
#define ALIGN2 __attribute__((aligned(2)))
#define ALIGN4 __attribute__((aligned(4)))
#define ALIGN8 __attribute__((aligned(8)))
#define ALIGN_PTR __attribute__((aligned(sizeof(void*))))
/*
* Miscellaneous compiler/platform defines.
*/
#define FAST_FUNC /* not used in U-Boot */
#define UNUSED_PARAM __always_unused
#define ALWAYS_INLINE __always_inline
#define NOINLINE noinline
/*
* Defines to provide equivalents to what libc/BusyBox defines.
*/
#define EOF (-1)
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
/*
* Stubs to provide libc/BusyBox functions based on U-Boot equivalents where it
* makes sense.
*/
#define utoa simple_itoa
static void __noreturn xfunc_die(void)
{
panic("HUSH died!");
}
#define bb_error_msg_and_die(format, ...) do { \
panic("HUSH: " format, __VA_ARGS__); \
} while (0);
#define bb_simple_error_msg_and_die(msg) do { \
panic_str("HUSH: " msg); \
} while (0);
/* fdprintf() is used for debug output. */
static int __maybe_unused fdprintf(int fd, const char *format, ...)
{
va_list args;
uint i;
assert(fd == 2);
va_start(args, format);
i = vprintf(format, args);
va_end(args);
return i;
}
static void bb_verror_msg(const char *s, va_list p, const char* strerr)
{
/* TODO: what to do with strerr arg? */
vprintf(s, p);
}
static void bb_error_msg(const char *s, ...)
{
va_list p;
va_start(p, s);
bb_verror_msg(s, p, NULL);
va_end(p);
}
static void bb_simple_error_msg(const char *s)
{
bb_error_msg("%s", s);
}
static void *xmalloc(size_t size)
{
void *p = NULL;
if (!(p = malloc(size)))
panic("out of memory");
return p;
}
static void *xzalloc(size_t size)
{
void *p = xmalloc(size);
memset(p, 0, size);
return p;
}
static void *xrealloc(void *ptr, size_t size)
{
void *p = NULL;
if (!(p = realloc(ptr, size)))
panic("out of memory");
return p;
}
static void *xmemdup(const void *s, int n)
{
return memcpy(xmalloc(n), s, n);
}
#define xstrdup strdup
#define xstrndup strndup
static void *mempcpy(void *dest, const void *src, size_t len)
{
return memcpy(dest, src, len) + len;
}
/* Like strcpy but can copy overlapping strings. */
static void overlapping_strcpy(char *dst, const char *src)
{
/*
* Cheap optimization for dst == src case -
* better to have it here than in many callers.
*/
if (dst != src) {
while ((*dst = *src) != '\0') {
dst++;
src++;
}
}
}
static char* skip_whitespace(const char *s)
{
/*
* In POSIX/C locale (the only locale we care about: do we REALLY want
* to allow Unicode whitespace in, say, .conf files? nuts!)
* isspace is only these chars: "\t\n\v\f\r" and space.
* "\t\n\v\f\r" happen to have ASCII codes 9,10,11,12,13.
* Use that.
*/
while (*s == ' ' || (unsigned char)(*s - 9) <= (13 - 9))
s++;
return (char *) s;
}
static char* skip_non_whitespace(const char *s)
{
while (*s != '\0' && *s != ' ' && (unsigned char)(*s - 9) > (13 - 9))
s++;
return (char *) s;
}
#define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
#define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
static const char* endofname(const char *name)
{
if (!is_name(*name))
return name;
while (*++name) {
if (!is_in_name(*name))
break;
}
return name;
}
/**
* list_size() - returns the number of elements in char ** before NULL.
*
* Argument must contain NULL to signalize its end.
*
* @list The list to count the number of element.
* @return The number of element in list.
*/
static size_t list_size(char **list)
{
size_t size;
for (size = 0; list[size] != NULL; size++);
return size;
}
cli: modern_hush: Add upstream commits up to 2nd October 2023. This commit adds the following hush busybox upstream commits: 791b222dd55d ("sleep: fix "sleep -- ARGS"") 5353df91cba7 ("Update applet size estimates") e41e481fd571 ("hush: fix a compile failure") 07a95cfcabb0 ("ash: disable check for "good" function name, bash does not check this") e5692e2342c6 ("hush: quote values in "readonly" output") 96769486e20f ("shell: move varcmp() to shell_common.h and use it in hush") bab8828b0dad ("hush: fix expansion of space in "a=${a:+$a }c" construct") b5be8da350b5 ("hush: make "false" built-in") 6824298ab4d3 ("hush: fix ELIF cmd1;cmd2 THEN ... not executing cmd2, closes 15571") 3a7f00eadcf4 ("hush: add comment about abort on syntax error %{^}") acae889dd972 ("ash,hush: tab completion of functions and aliases") 90b607d79a13 ("hush: quote variable values printed by "set" (match ash behavior)") 6748e6494c22 ("hush (NOMMU): fix LINENO in execed children") fd5fb2d2b596 ("hush: speed up "big heredoc" code") 1409432d072e ("hush: add TODO comment") 93ae7464e6e4 ("hush: restore SIGHUP handling, this time explain why we do what we do") 1fdb33bd07e5 ("hush: restore tty pgrp on SIGHUP") 6101b6d3eaa0 ("hush: remove special handling of SIGHUP") 93e0898c663a ("shell: fix SIGWINCH and SIGCHLD (in hush) interrupting line input, closes 15256") 969e00816835 ("hush: code shrink") 27be0e8cfeb6 ("shell: fix compile failures in some configs") 7d1c7d833785 ("ash,hush: use HOME for tab completion and prompts") 21afddefd258 ("hush: fix "error: invalid preprocessing directive ##"") e53c7dbafc78 ("hush: fix set -n to act immediately, not just after run_list()") 574b9c446da1 ("hush: fix var_LINENO3.tests failure") 49bcf9f40cff ("hush: speed up ${x//\*/|} too") 53b2fdcdba4c ("*: add NOINLINEs where code noticeably shrinks") 7c3e96d4b3d4 ("shell: use more compact SHELL_ASH / HUSH config defines. no code changes") 62f1eed1e191 ("hush: in a comment, document what -i might be doing") aaf3d5ba74c5 ("shell: tweak --help") db5546ca1018 ("libbb: code shrink: introduce and use [_]exit_SUCCESS()") 931c55f9e2b4 ("libbb: invert the meaning of SETUP_ENV_NO_CHDIR -> SETUP_ENV_CHDIR") 12566e7f9b5e ("ash,hush: fix handling of SIGINT while waiting for interactive input") 987be932ed3c ("*: slap on a few ALIGN_PTR where appropriate") Signed-off-by: Francis Laniel <francis.laniel@amarulasolutions.com>
2023-12-22 21:02:42 +00:00
static int varcmp(const char *p, const char *q)
{
int c, d;
while ((c = *p) == (d = *q)) {
if (c == '\0' || c == '=')
goto out;
p++;
q++;
}
if (c == '=')
c = '\0';
if (d == '=')
d = '\0';
out:
return c - d;
}
struct in_str;
static int u_boot_cli_readline(struct in_str *i);
struct in_str;
static int u_boot_cli_readline(struct in_str *i);
/*
* BusyBox globals which are needed for hush.
*/
static uint8_t xfunc_error_retval;
static const char defifsvar[] __aligned(1) = "IFS= \t\n";
#define defifs (defifsvar + 4)
/* This define is used to check if exit command was called. */
#define EXIT_RET_CODE -2
/*
* This define is used for changes that need be done directly in the upstream
* sources still. Ideally, its use should be minimized as much as possible.
*/
#define __U_BOOT__
/*
*
* +-- Include of the upstream sources --+ *
* V V
*/
#include "cli_hush_upstream.c"
/*
* A A
* +-- Include of the upstream sources --+ *
*
*/
int u_boot_hush_start_modern(void)
{
INIT_G();
return 0;
}
static int u_boot_cli_readline(struct in_str *i)
{
char *prompt;
char __maybe_unused *ps_prompt = NULL;
if (!G.promptmode)
prompt = CONFIG_SYS_PROMPT;
#ifdef CONFIG_SYS_PROMPT_HUSH_PS2
else
prompt = CONFIG_SYS_PROMPT_HUSH_PS2;
#else
/* TODO: default value? */
#error "SYS_PROMPT_HUSH_PS2 is not defined!"
#endif
if (CONFIG_IS_ENABLED(CMDLINE_PS_SUPPORT)) {
if (!G.promptmode)
ps_prompt = env_get("PS1");
else
ps_prompt = env_get("PS2");
if (ps_prompt)
prompt = ps_prompt;
}
return cli_readline(prompt);
}