1 // SPDX-License-Identifier: GPL-2.0+
3 * This file defines the compilation unit for the new hush shell version. The
4 * actual implementation from upstream BusyBox can be found in
5 * `cli_hush_upstream.c` which is included at the end of this file.
7 * This "wrapper" technique is used to keep the changes to the upstream version
8 * as minmal as possible. Instead, all defines and redefines necessary are done
9 * here, outside the upstream sources. This will hopefully make upgrades to
10 * newer revisions much easier.
12 * Copyright (c) 2021, Harald Seiler, DENX Software Engineering, hws@denx.de
15 #include <common.h> /* readline */
17 #include <malloc.h> /* malloc, free, realloc*/
18 #include <linux/ctype.h> /* isalpha, isdigit */
20 #include <bootretry.h>
23 #include <command.h> /* find_cmd */
24 #include <asm/global_data.h>
27 * BusyBox Version: UPDATE THIS WHEN PULLING NEW UPSTREAM REVISION!
29 #define BB_VER "1.34.0.git37460f5daff9"
32 * Define hush features by the names used upstream.
34 #define ENABLE_HUSH_INTERACTIVE 1
35 #define ENABLE_FEATURE_EDITING 1
36 #define ENABLE_HUSH_IF 1
37 #define ENABLE_HUSH_LOOPS 1
38 /* No MMU in U-Boot */
40 #define USE_FOR_NOMMU(...) __VA_ARGS__
41 #define USE_FOR_MMU(...)
44 * Size-saving "small" ints (arch-dependent)
46 #if CONFIG_IS_ENABLED(X86) || CONFIG_IS_ENABLED(X86_64) || CONFIG_IS_ENABLED(MIPS)
47 /* add other arches which benefit from this... */
48 typedef signed char smallint;
49 typedef unsigned char smalluint;
51 /* for arches where byte accesses generate larger code: */
53 typedef unsigned smalluint;
57 * Alignment defines used by BusyBox.
59 #define ALIGN1 __attribute__((aligned(1)))
60 #define ALIGN2 __attribute__((aligned(2)))
61 #define ALIGN4 __attribute__((aligned(4)))
62 #define ALIGN8 __attribute__((aligned(8)))
63 #define ALIGN_PTR __attribute__((aligned(sizeof(void*))))
66 * Miscellaneous compiler/platform defines.
68 #define FAST_FUNC /* not used in U-Boot */
69 #define UNUSED_PARAM __always_unused
70 #define ALWAYS_INLINE __always_inline
71 #define NOINLINE noinline
74 * Defines to provide equivalents to what libc/BusyBox defines.
77 #define EXIT_SUCCESS 0
78 #define EXIT_FAILURE 1
81 * Stubs to provide libc/BusyBox functions based on U-Boot equivalents where it
84 #define utoa simple_itoa
86 static void __noreturn xfunc_die(void)
91 #define bb_error_msg_and_die(format, ...) do { \
92 panic("HUSH: " format, __VA_ARGS__); \
95 #define bb_simple_error_msg_and_die(msg) do { \
96 panic_str("HUSH: " msg); \
99 /* fdprintf() is used for debug output. */
100 static int __maybe_unused fdprintf(int fd, const char *format, ...)
107 va_start(args, format);
108 i = vprintf(format, args);
114 static void bb_verror_msg(const char *s, va_list p, const char* strerr)
116 /* TODO: what to do with strerr arg? */
120 static void bb_error_msg(const char *s, ...)
125 bb_verror_msg(s, p, NULL);
129 static void bb_simple_error_msg(const char *s)
131 bb_error_msg("%s", s);
134 static void *xmalloc(size_t size)
137 if (!(p = malloc(size)))
138 panic("out of memory");
142 static void *xzalloc(size_t size)
144 void *p = xmalloc(size);
149 static void *xrealloc(void *ptr, size_t size)
152 if (!(p = realloc(ptr, size)))
153 panic("out of memory");
157 static void *xmemdup(const void *s, int n)
159 return memcpy(xmalloc(n), s, n);
162 #define xstrdup strdup
163 #define xstrndup strndup
165 static void *mempcpy(void *dest, const void *src, size_t len)
167 return memcpy(dest, src, len) + len;
170 /* Like strcpy but can copy overlapping strings. */
171 static void overlapping_strcpy(char *dst, const char *src)
174 * Cheap optimization for dst == src case -
175 * better to have it here than in many callers.
178 while ((*dst = *src) != '\0') {
185 static char* skip_whitespace(const char *s)
188 * In POSIX/C locale (the only locale we care about: do we REALLY want
189 * to allow Unicode whitespace in, say, .conf files? nuts!)
190 * isspace is only these chars: "\t\n\v\f\r" and space.
191 * "\t\n\v\f\r" happen to have ASCII codes 9,10,11,12,13.
194 while (*s == ' ' || (unsigned char)(*s - 9) <= (13 - 9))
200 static char* skip_non_whitespace(const char *s)
202 while (*s != '\0' && *s != ' ' && (unsigned char)(*s - 9) > (13 - 9))
208 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
209 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
211 static const char* endofname(const char *name)
216 if (!is_in_name(*name))
223 * list_size() - returns the number of elements in char ** before NULL.
225 * Argument must contain NULL to signalize its end.
227 * @list The list to count the number of element.
228 * @return The number of element in list.
230 static size_t list_size(char **list)
234 for (size = 0; list[size] != NULL; size++);
240 static int u_boot_cli_readline(struct in_str *i);
243 static int u_boot_cli_readline(struct in_str *i);
246 * BusyBox globals which are needed for hush.
248 static uint8_t xfunc_error_retval;
250 static const char defifsvar[] __aligned(1) = "IFS= \t\n";
251 #define defifs (defifsvar + 4)
253 /* This define is used to check if exit command was called. */
254 #define EXIT_RET_CODE -2
257 * This define is used for changes that need be done directly in the upstream
258 * sources still. Ideally, its use should be minimized as much as possible.
264 * +-- Include of the upstream sources --+ *
267 #include "cli_hush_upstream.c"
270 * +-- Include of the upstream sources --+ *
274 int u_boot_hush_start_modern(void)
280 static int u_boot_cli_readline(struct in_str *i)
283 char __maybe_unused *ps_prompt = NULL;
286 prompt = CONFIG_SYS_PROMPT;
287 #ifdef CONFIG_SYS_PROMPT_HUSH_PS2
289 prompt = CONFIG_SYS_PROMPT_HUSH_PS2;
291 /* TODO: default value? */
292 #error "SYS_PROMPT_HUSH_PS2 is not defined!"
295 if (CONFIG_IS_ENABLED(CMDLINE_PS_SUPPORT)) {
297 ps_prompt = env_get("PS1");
299 ps_prompt = env_get("PS2");
305 return cli_readline(prompt);