[PATCH v2 1/2] ash: implement -d DELIM option for `read`
Johannes Schindelin
johannes.schindelin at gmx.de
Tue Aug 8 14:46:39 UTC 2017
The POSIX standard only requires the `read` builtin to handle `-r`:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html
However, Bash introduced the option `-d <DELIM>` to override IFS for
just one invocation, and it is quite useful.
It is also super easy to implement in BusyBox' ash, so let's do that.
The motivation: This option is used by Git's test suite.
function old new delta
.rodata 163505 163587 +82
shell_builtin_read 1244 1289 +45
readcmd 233 259 +26
builtin_read 258 263 +5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 158/0) Total: 158 bytes
Signed-off-by: Johannes Schindelin <johannes.schindelin at gmx.de>
---
shell/ash.c | 19 ++++++++++++++++---
shell/hush.c | 3 ++-
shell/shell_common.c | 10 +++++++---
shell/shell_common.h | 3 ++-
4 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/shell/ash.c b/shell/ash.c
index 6dc1cfef7..4b0896573 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -189,6 +189,8 @@
#define BASH_HOSTNAME_VAR ENABLE_ASH_BASH_COMPAT
#define BASH_SHLVL_VAR ENABLE_ASH_BASH_COMPAT
#define BASH_XTRACEFD ENABLE_ASH_BASH_COMPAT
+#define BASH_READ_D ENABLE_ASH_BASH_COMPAT
+#define IF_BASH_READ_D IF_ASH_BASH_COMPAT
#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
/* Bionic at least up to version 24 has no glob() */
@@ -13402,10 +13404,10 @@ letcmd(int argc UNUSED_PARAM, char **argv)
* -p PROMPT Display PROMPT on stderr (if input is from tty)
* -t SECONDS Timeout after SECONDS (tty or pipe only)
* -u FD Read from given FD instead of fd 0
+ * -d DELIM End on DELIM char, not newline
* This uses unbuffered input, which may be avoidable in some cases.
* TODO: bash also has:
* -a ARRAY Read into array[0],[1],etc
- * -d DELIM End on DELIM char, not newline
* -e Use line editing (tty only)
*/
static int FAST_FUNC
@@ -13415,11 +13417,12 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
char *opt_p = NULL;
char *opt_t = NULL;
char *opt_u = NULL;
+ IF_BASH_READ_D(char *opt_d = NULL;)
int read_flags = 0;
const char *r;
int i;
- while ((i = nextopt("p:u:rt:n:s")) != '\0') {
+ while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
switch (i) {
case 'p':
opt_p = optionarg;
@@ -13439,6 +13442,11 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
case 'u':
opt_u = optionarg;
break;
+#if BASH_READ_D
+ case 'd':
+ opt_d = optionarg;
+ break;
+#endif
default:
break;
}
@@ -13456,7 +13464,12 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
opt_n,
opt_p,
opt_t,
- opt_u
+ opt_u,
+#if BASH_READ_D
+ opt_d
+#else
+ NULL
+#endif
);
INT_ON;
diff --git a/shell/hush.c b/shell/hush.c
index 8dc531657..d4e647fc0 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -9454,7 +9454,8 @@ static int FAST_FUNC builtin_read(char **argv)
opt_n,
opt_p,
opt_t,
- opt_u
+ opt_u,
+ NULL
);
if ((uintptr_t)r == 1 && errno == EINTR) {
diff --git a/shell/shell_common.c b/shell/shell_common.c
index a9f8d8413..2db8ea3e2 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -54,7 +54,8 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
const char *opt_n,
const char *opt_p,
const char *opt_t,
- const char *opt_u
+ const char *opt_u,
+ const char *opt_d
)
{
struct pollfd pfd[1];
@@ -237,14 +238,17 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
continue;
}
}
- if (c == '\n')
+ if (opt_d) {
+ if (c == *opt_d)
+ break;
+ } else if (c == '\n')
break;
/* $IFS splitting. NOT done if we run "read"
* without variable names (bash compat).
* Thus, "read" and "read REPLY" are not the same.
*/
- if (argv[0]) {
+ if (!opt_d && argv[0]) {
/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */
const char *is_ifs = strchr(ifs, c);
if (startword && is_ifs) {
diff --git a/shell/shell_common.h b/shell/shell_common.h
index a82535c86..1b79bffca 100644
--- a/shell/shell_common.h
+++ b/shell/shell_common.h
@@ -42,7 +42,8 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
const char *opt_n,
const char *opt_p,
const char *opt_t,
- const char *opt_u
+ const char *opt_u,
+ const char *opt_d
);
int FAST_FUNC
--
2.14.0.windows.1.2.g0f3342804fc
More information about the busybox
mailing list