From 1062391365981a09069f96509937b7f1181b7484 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 19 Sep 2012 16:55:08 +0200 Subject: ifupdown: use -x hostname:NAME with udhcpc The -H NAME is deprecated in udhcpc. See commit 2017d48c0d70bef8768efb42909e605ea8eb5a21 Signed-off-by: Natanael Copa Signed-off-by: Denys Vlasenko --- networking/ifupdown.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/ifupdown.c b/networking/ifupdown.c index d477ff6d1..766dfabbd 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -535,7 +535,7 @@ static const struct dhcp_client_t ext_dhcp_clients[] = { "pump -i %iface% -k", }, { "udhcpc", - "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %client%]]" + "udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -x hostname:%hostname%]][[ -c %client%]]" "[[ -s %script%]][[ %udhcpc_opts%]]", "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", }, @@ -575,7 +575,7 @@ static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) return 0; # endif return execute("udhcpc " UDHCPC_CMD_OPTIONS " -p /var/run/udhcpc.%iface%.pid " - "-i %iface%[[ -H %hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]", + "-i %iface%[[ -x hostname:%hostname%]][[ -c %client%]][[ -s %script%]][[ %udhcpc_opts%]]", ifd, exec); } # else -- cgit v1.2.3-55-g6feb From 99f025a4999ee9d44db17d8abfbde7813bf99de1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 27 Oct 2015 17:15:00 +0100 Subject: i2cdetect: fix address skipping in auto mode If the bus doesn't support SMBus Quick Write or Receive Byte commands and we're running in auto mode all addresses will be skipped resulting in an empty table being printed. This is caused by not restoring the auto mode after it's been changed for certain address ranges - we need an additional variable to hold the temporary state. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index d77e6bacf..c5baaa78e 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1200,7 +1200,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) opt_F = (1 << 4), opt_l = (1 << 5); const char *const optstr = "yaqrFl"; - int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status; + int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status, cmd; unsigned first = 0x03, last = 0x77, opts; unsigned long funcs; @@ -1273,19 +1273,20 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) for(j = 0; j < 16; j++) { fflush_all(); + cmd = mode; if (mode == I2CDETECT_MODE_AUTO) { if ((i+j >= 0x30 && i+j <= 0x37) || (i+j >= 0x50 && i+j <= 0x5F)) - mode = I2CDETECT_MODE_READ; + cmd = I2CDETECT_MODE_READ; else - mode = I2CDETECT_MODE_QUICK; + cmd = I2CDETECT_MODE_QUICK; } /* Skip unwanted addresses. */ if (i+j < first || i+j > last - || (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) - || (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK))) + || (cmd == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) + || (cmd == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK))) { printf(" "); continue; @@ -1302,7 +1303,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) "can't set address to 0x%02x", i + j); } - switch (mode) { + switch (cmd) { case I2CDETECT_MODE_READ: /* * This is known to lock SMBus on various -- cgit v1.2.3-55-g6feb From fc8eb056ea8b81798467f8306629a7ea1feffe50 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 27 Oct 2015 17:15:01 +0100 Subject: i2cdetect: coding style: add a space after 'for' Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index c5baaa78e..907d738fd 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1270,7 +1270,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"); for (i = 0; i < 128; i += 16) { printf("%02x: ", i); - for(j = 0; j < 16; j++) { + for (j = 0; j < 16; j++) { fflush_all(); cmd = mode; -- cgit v1.2.3-55-g6feb From 1cde5f79d4c077cd6a2a8998a9180dfcc2800852 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 27 Oct 2015 17:15:02 +0100 Subject: i2cdump: don't read block data in non-block modes We currently read data twice in byte mode. Add a check to avoid calling i2c_smbus_read_i2c_block_data() if we're not in I2C or SMBus block mode. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 907d738fd..094bf9e38 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -971,7 +971,8 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) /* All but word data. */ if (mode != I2C_SMBUS_WORD_DATA || even) { - blen = read_block_data(fd, mode, block); + if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) + blen = read_block_data(fd, mode, block); if (mode == I2C_SMBUS_BYTE) { res = i2c_smbus_write_byte(fd, first); -- cgit v1.2.3-55-g6feb From 1fe75b8ef10933d047f7ab6060d4710a39611e92 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 27 Oct 2015 17:15:03 +0100 Subject: i2cdump: use I2C block mode for the 'i' mode parameter Currently we're calling i2c_smbus_read_block_data() for both 'i' and 's' mode parameters. If the bus doesn't support SMBus block mode, then the i2c access ioctl() fails. Make i2cdump behave compatibly with upstream version by calling i2c_smbus_read_i2c_block_data() for I2C block. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 094bf9e38..6d221e9fc 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -723,7 +723,7 @@ static int read_block_data(int buf_fd, int mode, int *block) uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS]; int res, blen = 0, tmp, i; - if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) { + if (mode == I2C_SMBUS_BLOCK_DATA) { res = i2c_smbus_read_block_data(buf_fd, 0, cblock); blen = res; } else { -- cgit v1.2.3-55-g6feb From 74bb9d5e63b0928ceac57fedd4a2d383129ade7d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 27 Oct 2015 17:15:04 +0100 Subject: i2cdump: bail-out if block read fails We should bail-out if i2c_smbus_read_block_data() or i2c_smbus_read_i2c_block_data() return 0 or less. Add the missing check for the former and fix the existing for the latter. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 6d221e9fc..7be489036 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -724,16 +724,16 @@ static int read_block_data(int buf_fd, int mode, int *block) int res, blen = 0, tmp, i; if (mode == I2C_SMBUS_BLOCK_DATA) { - res = i2c_smbus_read_block_data(buf_fd, 0, cblock); - blen = res; + blen = i2c_smbus_read_block_data(buf_fd, 0, cblock); + if (blen <= 0) + goto fail; } else { for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) { tmp = i2c_smbus_read_i2c_block_data( buf_fd, res, I2C_SMBUS_BLOCK_MAX, cblock + res); - if (tmp < 0) { - bb_error_msg_and_die("block read failed"); - } + if (tmp <= 0) + goto fail; } if (res >= I2CDUMP_NUM_REGS) @@ -748,6 +748,9 @@ static int read_block_data(int buf_fd, int mode, int *block) } return blen; + + fail: + bb_error_msg_and_die("block read failed"); } /* Dump all but word data. */ -- cgit v1.2.3-55-g6feb From 5ed6989d805535804fcd05ddc777fbae48d21f3a Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 27 Oct 2015 17:15:05 +0100 Subject: i2cdump: display the numeric value for block read ioctl() errors This makes busybox i2cdump compatible with the upstream version, which also displays the numeric error value in case of a block read failure. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 7be489036..e19d851fe 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -732,8 +732,10 @@ static int read_block_data(int buf_fd, int mode, int *block) tmp = i2c_smbus_read_i2c_block_data( buf_fd, res, I2C_SMBUS_BLOCK_MAX, cblock + res); - if (tmp <= 0) + if (tmp <= 0) { + blen = tmp; goto fail; + } } if (res >= I2CDUMP_NUM_REGS) @@ -750,7 +752,7 @@ static int read_block_data(int buf_fd, int mode, int *block) return blen; fail: - bb_error_msg_and_die("block read failed"); + bb_error_msg_and_die("block read failed: %d", blen); } /* Dump all but word data. */ -- cgit v1.2.3-55-g6feb From 2cf459141373d7ade0ba8cf5de83d4ef12b7dc97 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 1 Nov 2015 20:57:34 +0100 Subject: i2c_tools: suppress "'blen' may be used uninitialized in this function" Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index e19d851fe..aa1c7c5cc 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -909,7 +909,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) unsigned first = 0x00, last = 0xff, opts; int *block = (int *)bb_common_bufsiz1; char *opt_r_str, *dash; - int fd, res, blen; + int fd, res; opt_complementary = "-2:?3"; /* from 2 to 3 args */ opts = getopt32(argv, optstr, &opt_r_str); @@ -976,6 +976,8 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) /* All but word data. */ if (mode != I2C_SMBUS_WORD_DATA || even) { + int blen = 0; + if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) blen = read_block_data(fd, mode, block); -- cgit v1.2.3-55-g6feb From 85405c80a28509f2f36c0d4fda8693aac7652d9b Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 3 Nov 2015 09:37:40 +0000 Subject: ash: copy function tests from hush testsuite Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/func1.right | 6 ++++++ shell/ash_test/ash-misc/func1.tests | 16 ++++++++++++++++ shell/ash_test/ash-misc/func2.right | 5 +++++ shell/ash_test/ash-misc/func2.tests | 9 +++++++++ shell/ash_test/ash-misc/func3.right | 4 ++++ shell/ash_test/ash-misc/func3.tests | 8 ++++++++ shell/ash_test/ash-misc/func4.right | 2 ++ shell/ash_test/ash-misc/func4.tests | 7 +++++++ shell/ash_test/ash-misc/func5.right | 6 ++++++ shell/ash_test/ash-misc/func5.tests | 13 +++++++++++++ shell/ash_test/ash-misc/func_args1.right | 5 +++++ shell/ash_test/ash-misc/func_args1.tests | 9 +++++++++ shell/ash_test/ash-misc/func_local1.right | 3 +++ shell/ash_test/ash-misc/func_local1.tests | 5 +++++ shell/ash_test/ash-misc/func_local2.right | 14 ++++++++++++++ shell/ash_test/ash-misc/func_local2.tests | 7 +++++++ 16 files changed, 119 insertions(+) create mode 100644 shell/ash_test/ash-misc/func1.right create mode 100755 shell/ash_test/ash-misc/func1.tests create mode 100644 shell/ash_test/ash-misc/func2.right create mode 100755 shell/ash_test/ash-misc/func2.tests create mode 100644 shell/ash_test/ash-misc/func3.right create mode 100755 shell/ash_test/ash-misc/func3.tests create mode 100644 shell/ash_test/ash-misc/func4.right create mode 100755 shell/ash_test/ash-misc/func4.tests create mode 100644 shell/ash_test/ash-misc/func5.right create mode 100755 shell/ash_test/ash-misc/func5.tests create mode 100644 shell/ash_test/ash-misc/func_args1.right create mode 100755 shell/ash_test/ash-misc/func_args1.tests create mode 100644 shell/ash_test/ash-misc/func_local1.right create mode 100755 shell/ash_test/ash-misc/func_local1.tests create mode 100644 shell/ash_test/ash-misc/func_local2.right create mode 100755 shell/ash_test/ash-misc/func_local2.tests diff --git a/shell/ash_test/ash-misc/func1.right b/shell/ash_test/ash-misc/func1.right new file mode 100644 index 000000000..e21665aaf --- /dev/null +++ b/shell/ash_test/ash-misc/func1.right @@ -0,0 +1,6 @@ +Hello +Zero: 0 +One: 1 Param1: World +Zero: 0 Param1: Restored +Multi line function +One: 1 diff --git a/shell/ash_test/ash-misc/func1.tests b/shell/ash_test/ash-misc/func1.tests new file mode 100755 index 000000000..ffb269fad --- /dev/null +++ b/shell/ash_test/ash-misc/func1.tests @@ -0,0 +1,16 @@ +f() { echo Hello; } +g () { echo One: $# Param1: $1; } +h ( ) +{ + echo -n 'Multi ' && echo -n 'line ' + echo function + false +} + +f +echo Zero: $? +set -- Restored +{ g World; } +echo Zero: $? Param1: $1 +( h ) +echo One: $? diff --git a/shell/ash_test/ash-misc/func2.right b/shell/ash_test/ash-misc/func2.right new file mode 100644 index 000000000..f2a041da7 --- /dev/null +++ b/shell/ash_test/ash-misc/func2.right @@ -0,0 +1,5 @@ +First 0 +Second 0 +First 1 +Second 1 +Done diff --git a/shell/ash_test/ash-misc/func2.tests b/shell/ash_test/ash-misc/func2.tests new file mode 100755 index 000000000..763203f15 --- /dev/null +++ b/shell/ash_test/ash-misc/func2.tests @@ -0,0 +1,9 @@ +i=0 +while test $i != 2; do + f() { echo First $i; } + f + f() { echo Second $i; } + f + : $((i++)) +done +echo Done diff --git a/shell/ash_test/ash-misc/func3.right b/shell/ash_test/ash-misc/func3.right new file mode 100644 index 000000000..b6d73459a --- /dev/null +++ b/shell/ash_test/ash-misc/func3.right @@ -0,0 +1,4 @@ +One:1 +Zero:0 +One:1 +Five:5 diff --git a/shell/ash_test/ash-misc/func3.tests b/shell/ash_test/ash-misc/func3.tests new file mode 100755 index 000000000..fa6f26a23 --- /dev/null +++ b/shell/ash_test/ash-misc/func3.tests @@ -0,0 +1,8 @@ +f() { false; return; echo BAD; }; +{ f; echo One:$?; }; echo Zero:$? + +f() { false; return; }; +f; echo One:$? + +f() { return 5; }; +f; echo Five:$? diff --git a/shell/ash_test/ash-misc/func4.right b/shell/ash_test/ash-misc/func4.right new file mode 100644 index 000000000..0c87e316a --- /dev/null +++ b/shell/ash_test/ash-misc/func4.right @@ -0,0 +1,2 @@ +24 +Done diff --git a/shell/ash_test/ash-misc/func4.tests b/shell/ash_test/ash-misc/func4.tests new file mode 100755 index 000000000..74c1b9a46 --- /dev/null +++ b/shell/ash_test/ash-misc/func4.tests @@ -0,0 +1,7 @@ +func() { + eval "echo \"\${val_${1}}\"" +} + +val_x=24 +(func x) +echo Done diff --git a/shell/ash_test/ash-misc/func5.right b/shell/ash_test/ash-misc/func5.right new file mode 100644 index 000000000..2c9d316b3 --- /dev/null +++ b/shell/ash_test/ash-misc/func5.right @@ -0,0 +1,6 @@ +1 +2 +3 +1 +2 +3 diff --git a/shell/ash_test/ash-misc/func5.tests b/shell/ash_test/ash-misc/func5.tests new file mode 100755 index 000000000..e967208cc --- /dev/null +++ b/shell/ash_test/ash-misc/func5.tests @@ -0,0 +1,13 @@ +f() { echo $1; } +f 1 + +f() ( echo $1; ) +f 2 + +f() ( echo $1 ) +f 3 + +f() for i in 1 2 3; do + echo $i +done +f diff --git a/shell/ash_test/ash-misc/func_args1.right b/shell/ash_test/ash-misc/func_args1.right new file mode 100644 index 000000000..2dfb9629b --- /dev/null +++ b/shell/ash_test/ash-misc/func_args1.right @@ -0,0 +1,5 @@ +params: a b c +'f 1 2 3' called +params: a b c +'f 1 2 3' called +params: a b c diff --git a/shell/ash_test/ash-misc/func_args1.tests b/shell/ash_test/ash-misc/func_args1.tests new file mode 100755 index 000000000..7970795a9 --- /dev/null +++ b/shell/ash_test/ash-misc/func_args1.tests @@ -0,0 +1,9 @@ + +f() { echo "'f $1 $2 $3' called"; } + +set -- a b c +echo "params: $1 $2 $3" +f 1 2 3 +echo "params: $1 $2 $3" +true | f 1 2 3 +echo "params: $1 $2 $3" diff --git a/shell/ash_test/ash-misc/func_local1.right b/shell/ash_test/ash-misc/func_local1.right new file mode 100644 index 000000000..312178366 --- /dev/null +++ b/shell/ash_test/ash-misc/func_local1.right @@ -0,0 +1,3 @@ +z=a +z=z +Done diff --git a/shell/ash_test/ash-misc/func_local1.tests b/shell/ash_test/ash-misc/func_local1.tests new file mode 100755 index 000000000..1d594e20c --- /dev/null +++ b/shell/ash_test/ash-misc/func_local1.tests @@ -0,0 +1,5 @@ +export z=z +f() { local z=a; env | grep ^z; } +f +env | grep ^z +echo Done diff --git a/shell/ash_test/ash-misc/func_local2.right b/shell/ash_test/ash-misc/func_local2.right new file mode 100644 index 000000000..fe9343ac8 --- /dev/null +++ b/shell/ash_test/ash-misc/func_local2.right @@ -0,0 +1,14 @@ +1 +2 +1 +2 +1 +1 +2 +2 +3 +2 +2 +3 +1 +Done diff --git a/shell/ash_test/ash-misc/func_local2.tests b/shell/ash_test/ash-misc/func_local2.tests new file mode 100755 index 000000000..1a9ae559d --- /dev/null +++ b/shell/ash_test/ash-misc/func_local2.tests @@ -0,0 +1,7 @@ +x=1 +f() { echo $x; local x=$((x+1)); echo $x; } +g() { f; echo $x; f; local x=$((x+1)); f; echo $x; f; } +f +g +echo $x +echo Done -- cgit v1.2.3-55-g6feb From bc9bee01f35d6c716c087e82dae5f439de90914b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 4 Nov 2015 14:50:19 +0100 Subject: hush-misc/func_args1.tests: remove "UNFIXED BUG", it does not fail Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/func_args1.tests | 1 - shell/hush_test/hush-misc/func_args1.tests | 2 -- 2 files changed, 3 deletions(-) diff --git a/shell/ash_test/ash-misc/func_args1.tests b/shell/ash_test/ash-misc/func_args1.tests index 7970795a9..d394c637f 100755 --- a/shell/ash_test/ash-misc/func_args1.tests +++ b/shell/ash_test/ash-misc/func_args1.tests @@ -1,4 +1,3 @@ - f() { echo "'f $1 $2 $3' called"; } set -- a b c diff --git a/shell/hush_test/hush-misc/func_args1.tests b/shell/hush_test/hush-misc/func_args1.tests index 157921fb1..d394c637f 100755 --- a/shell/hush_test/hush-misc/func_args1.tests +++ b/shell/hush_test/hush-misc/func_args1.tests @@ -1,5 +1,3 @@ -# UNFIXED BUG - f() { echo "'f $1 $2 $3' called"; } set -- a b c -- cgit v1.2.3-55-g6feb From 95ebcf79ff6f8ad21ceacb7bac665fb86c078d84 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 3 Nov 2015 09:42:23 +0000 Subject: ash: add support for bash 'function' keyword Where the POSIX shell allows functions to be defined as: name () compound-command [ redirections ] bash adds the alternative syntax: function name [()] compound-command [ redirections ] Implement this in ash's bash compatibility mode. Most compound commands work (for/while/until/if/case/[[]]/{}); one exception is: function f (echo "no way!") The other two variants work: f() (echo "ok") function f() (echo "also ok") function old new delta parse_command 1555 1744 +189 tokname_array 232 240 +8 .rodata 155612 155566 -46 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 197/-46) Total: 151 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 101 +++++++++++++++++++++---------- shell/ash_test/ash-misc/func_bash1.right | 12 ++++ shell/ash_test/ash-misc/func_bash1.tests | 28 +++++++++ 3 files changed, 110 insertions(+), 31 deletions(-) create mode 100644 shell/ash_test/ash-misc/func_bash1.right create mode 100755 shell/ash_test/ash-misc/func_bash1.tests diff --git a/shell/ash.c b/shell/ash.c index 84502636a..e7a867f52 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7726,36 +7726,40 @@ changepath(const char *new) clearcmdentry(firstchange); builtinloc = idx_bltin; } - -#define TEOF 0 -#define TNL 1 -#define TREDIR 2 -#define TWORD 3 -#define TSEMI 4 -#define TBACKGND 5 -#define TAND 6 -#define TOR 7 -#define TPIPE 8 -#define TLP 9 -#define TRP 10 -#define TENDCASE 11 -#define TENDBQUOTE 12 -#define TNOT 13 -#define TCASE 14 -#define TDO 15 -#define TDONE 16 -#define TELIF 17 -#define TELSE 18 -#define TESAC 19 -#define TFI 20 -#define TFOR 21 -#define TIF 22 -#define TIN 23 -#define TTHEN 24 -#define TUNTIL 25 -#define TWHILE 26 -#define TBEGIN 27 -#define TEND 28 +enum { + TEOF, + TNL, + TREDIR, + TWORD, + TSEMI, + TBACKGND, + TAND, + TOR, + TPIPE, + TLP, + TRP, + TENDCASE, + TENDBQUOTE, + TNOT, + TCASE, + TDO, + TDONE, + TELIF, + TELSE, + TESAC, + TFI, + TFOR, +#if ENABLE_ASH_BASH_COMPAT + TFUNCTION, +#endif + TIF, + TIN, + TTHEN, + TUNTIL, + TWHILE, + TBEGIN, + TEND +}; typedef smallint token_id_t; /* first char is indicating which tokens mark the end of a list */ @@ -7784,6 +7788,9 @@ static const char *const tokname_array[] = { "\1esac", "\1fi", "\0for", +#if ENABLE_ASH_BASH_COMPAT + "\0function", +#endif "\0if", "\0in", "\1then", @@ -10762,6 +10769,7 @@ simplecmd(void) int savecheckkwd; #if ENABLE_ASH_BASH_COMPAT smallint double_brackets_flag = 0; + smallint function_flag = 0; #endif args = NULL; @@ -10778,6 +10786,11 @@ simplecmd(void) t = readtoken(); switch (t) { #if ENABLE_ASH_BASH_COMPAT + case TFUNCTION: + if (peektoken() != TWORD) + raise_error_unexpected_syntax(TWORD); + function_flag = 1; + break; case TAND: /* "&&" */ case TOR: /* "||" */ if (!double_brackets_flag) { @@ -10806,6 +10819,29 @@ simplecmd(void) app = &n->narg.next; savecheckkwd = 0; } +#if ENABLE_ASH_BASH_COMPAT + if (function_flag) { + checkkwd = CHKNL | CHKKWD; + switch (peektoken()) { + case TBEGIN: + case TIF: + case TCASE: + case TUNTIL: + case TWHILE: + case TFOR: + goto do_func; + case TLP: + function_flag = 0; + break; + case TWORD: + if (strcmp("[[", wordtext) == 0) + goto do_func; + /* fall through */ + default: + raise_error_unexpected_syntax(-1); + } + } +#endif break; case TREDIR: *rpp = n = redirnode; @@ -10813,6 +10849,7 @@ simplecmd(void) parsefname(); /* read name of redirection file */ break; case TLP: + IF_ASH_BASH_COMPAT(do_func:) if (args && app == &args->narg.next && !vars && !redir ) { @@ -10820,7 +10857,7 @@ simplecmd(void) const char *name; /* We have a function */ - if (readtoken() != TRP) + if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP) raise_error_unexpected_syntax(TRP); name = n->narg.text; if (!goodname(name) @@ -10833,6 +10870,7 @@ simplecmd(void) n->narg.next = parse_command(); return n; } + IF_ASH_BASH_COMPAT(function_flag = 0;) /* fall through */ default: tokpushback = 1; @@ -11013,6 +11051,7 @@ parse_command(void) n1 = list(0); t = TEND; break; + IF_ASH_BASH_COMPAT(case TFUNCTION:) case TWORD: case TREDIR: tokpushback = 1; diff --git a/shell/ash_test/ash-misc/func_bash1.right b/shell/ash_test/ash-misc/func_bash1.right new file mode 100644 index 000000000..41bf8828c --- /dev/null +++ b/shell/ash_test/ash-misc/func_bash1.right @@ -0,0 +1,12 @@ +1 +2 +3 +1 +2 +3 +1 +2 +3 +1 +2 +3 diff --git a/shell/ash_test/ash-misc/func_bash1.tests b/shell/ash_test/ash-misc/func_bash1.tests new file mode 100755 index 000000000..2cc0970e8 --- /dev/null +++ b/shell/ash_test/ash-misc/func_bash1.tests @@ -0,0 +1,28 @@ +function f() { echo $1; } +f 1 + +function f() ( echo $1; ) +f 2 + +function f() ( echo $1 ) +f 3 + +function f() for i in 1 2 3; do + echo $i +done +f + +function f { echo $1; } +f 1 + +# the next two don't work +#function f ( echo $1; ) +f 2 + +#function f ( echo $1 ) +f 3 + +function f for i in 1 2 3; do + echo $i +done +f -- cgit v1.2.3-55-g6feb From 34adecc2b049f6941c5e075ffb58fe2183823da3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 4 Nov 2015 19:39:54 +0100 Subject: TODO file: remove mpstat, iostat, powertop - we have them now Signed-off-by: Denys Vlasenko --- TODO | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO b/TODO index dcf48c2c2..8904b2135 100644 --- a/TODO +++ b/TODO @@ -258,5 +258,3 @@ vdprintf() -> similar sized functionality * more support for advanced linux 2.6.x features, see: iotop most likely there is more - -* even more support for statistics: mpstat, iostat, powertop.... -- cgit v1.2.3-55-g6feb From 48dc80bbba994eee24ed94ae4532a1cce76d7cb7 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Thu, 5 Nov 2015 18:54:55 +0100 Subject: modutils: merge module_entry and module_info to common MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This merges the in-memory module info structures of modprobe and depmod. This allows sharing hashing by modulename code improving depmod runtime with almost factor of 2x. function old new delta get_or_add_modentry - 17 +17 do_modprobe 590 601 +11 moddb_get_or_create - 10 +10 load_modules_dep 195 205 +10 moddb_get - 7 +7 add_probe 81 78 -3 modprobe_main 721 714 -7 depmod_main 553 543 -10 config_file_action 434 421 -13 helper_get_module 160 144 -16 parse_module 343 320 -23 order_dep_list 105 82 -23 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 2/7 up/down: 55/-95) Total: -40 bytes Signed-off-by: Timo Teräs Signed-off-by: Denys Vlasenko --- modutils/depmod.c | 86 ++++++++++++++++------------------------------------- modutils/modprobe.c | 66 +++++----------------------------------- modutils/modutils.c | 51 +++++++++++++++++++++++++++++++ modutils/modutils.h | 30 +++++++++++++++++++ 4 files changed, 113 insertions(+), 120 deletions(-) diff --git a/modutils/depmod.c b/modutils/depmod.c index 9713aef92..e5f0e3d2b 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -21,21 +21,13 @@ * for each depends, look through our list of full paths and emit if found */ -typedef struct module_info { - struct module_info *next; - char *name, *modname; - llist_t *dependencies; - llist_t *aliases; - llist_t *symbols; - struct module_info *dnext, *dprev; -} module_info; - static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, void *data, int depth UNUSED_PARAM) { - module_info **first = (module_info **) data; + module_db *modules = data; char *image, *ptr; - module_info *info; + module_entry *e; + /* Arbitrary. Was sb->st_size, but that breaks .gz etc */ size_t len = (64*1024*1024 - 4096); @@ -43,17 +35,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA return TRUE; image = xmalloc_open_zipped_read_close(fname, &len); - info = xzalloc(sizeof(*info)); - info->next = *first; - *first = info; + e = moddb_get_or_create(modules, bb_get_last_path_component_nostrip(fname)); + e->name = xstrdup(fname + 2); /* skip "./" */ - info->dnext = info->dprev = info; - info->name = xstrdup(fname + 2); /* skip "./" */ - info->modname = filename2modname( - bb_get_last_path_component_nostrip(fname), - NULL - ); for (ptr = image; ptr < image + len - 10; ptr++) { if (is_prefixed_with(ptr, "depends=")) { char *u; @@ -62,11 +47,11 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA for (u = ptr; *u; u++) if (*u == '-') *u = '_'; - ptr += string_to_llist(ptr, &info->dependencies, ","); + ptr += string_to_llist(ptr, &e->deps, ","); } else if (ENABLE_FEATURE_MODUTILS_ALIAS && is_prefixed_with(ptr, "alias=") ) { - llist_add_to(&info->aliases, xstrdup(ptr + 6)); + llist_add_to(&e->aliases, xstrdup(ptr + 6)); ptr += strlen(ptr); } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS && is_prefixed_with(ptr, "__ksymtab_") @@ -77,7 +62,7 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA ) { continue; } - llist_add_to(&info->symbols, xstrdup(ptr)); + llist_add_to(&e->symbols, xstrdup(ptr)); ptr += strlen(ptr); } } @@ -86,24 +71,13 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA return TRUE; } -static module_info *find_module(module_info *modules, const char *modname) -{ - module_info *m; - - for (m = modules; m != NULL; m = m->next) - if (strcmp(m->modname, modname) == 0) - return m; - return NULL; -} - -static void order_dep_list(module_info *modules, module_info *start, - llist_t *add) +static void order_dep_list(module_db *modules, module_entry *start, llist_t *add) { - module_info *m; + module_entry *m; llist_t *n; for (n = add; n != NULL; n = n->link) { - m = find_module(modules, n->data); + m = moddb_get(modules, n->data); if (m == NULL) continue; @@ -118,7 +92,7 @@ static void order_dep_list(module_info *modules, module_info *start, start->dprev = m; /* recurse */ - order_dep_list(modules, start, m->dependencies); + order_dep_list(modules, start, m->deps); } } @@ -184,10 +158,12 @@ enum { int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int depmod_main(int argc UNUSED_PARAM, char **argv) { - module_info *modules, *m, *dep; + module_db modules; + module_entry *m, *dep; const char *moddir_base = "/"; char *moddir, *version; struct utsname uts; + unsigned i; int tmp; getopt32(argv, "aAb:eF:nruqC:", &moddir_base, NULL, NULL); @@ -211,7 +187,7 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) free(moddir); /* Scan modules */ - modules = NULL; + memset(&modules, 0, sizeof(modules)); if (*argv) { do { parse_module(*argv, /*sb (unused):*/ NULL, &modules, 0); @@ -224,10 +200,11 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) /* Generate dependency and alias files */ if (!(option_mask32 & OPT_n)) xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout); - for (m = modules; m != NULL; m = m->next) { + + moddb_foreach_module(&modules, m, i) { printf("%s:", m->name); - order_dep_list(modules, m, m->dependencies); + order_dep_list(&modules, m, m->deps); while (m->dnext != m) { dep = m->dnext; printf(" %s", dep->name); @@ -243,10 +220,7 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_MODUTILS_ALIAS if (!(option_mask32 & OPT_n)) xfreopen_write("modules.alias", stdout); - for (m = modules; m != NULL; m = m->next) { - char modname[MODULE_NAME_LEN]; - const char *fname = bb_basename(m->name); - filename2modname(fname, modname); + moddb_foreach_module(&modules, m, i) { while (m->aliases) { /* * Last word used to be a basename @@ -256,34 +230,24 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) */ printf("alias %s %s\n", (char*)llist_pop(&m->aliases), - modname); + m->modname); } } #endif #if ENABLE_FEATURE_MODUTILS_SYMBOLS if (!(option_mask32 & OPT_n)) xfreopen_write("modules.symbols", stdout); - for (m = modules; m != NULL; m = m->next) { - char modname[MODULE_NAME_LEN]; - const char *fname = bb_basename(m->name); - filename2modname(fname, modname); + moddb_foreach_module(&modules, m, i) { while (m->symbols) { printf("alias symbol:%s %s\n", (char*)llist_pop(&m->symbols), - modname); + m->modname); } } #endif - if (ENABLE_FEATURE_CLEAN_UP) { - while (modules) { - module_info *old = modules; - modules = modules->next; - free(old->name); - free(old->modname); - free(old); - } - } + if (ENABLE_FEATURE_CLEAN_UP) + moddb_free(&modules); return EXIT_SUCCESS; } diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 05bf02cf8..ec490b74d 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -150,19 +150,6 @@ static const char modprobe_longopts[] ALIGN1 = #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 #define MODULE_FLAG_BLACKLISTED 0x0008 -struct module_entry { /* I'll call it ME. */ - unsigned flags; - char *modname; /* stripped of /path/, .ext and s/-/_/g */ - const char *probed_name; /* verbatim as seen on cmdline */ - char *options; /* options from config files */ - llist_t *realnames; /* strings. if this module is an alias, */ - /* real module name is one of these. */ -//Can there really be more than one? Example from real kernel? - llist_t *deps; /* strings. modules we depend on */ -}; - -#define DB_HASH_SIZE 256 - struct globals { llist_t *probes; /* MEs of module(s) requested on cmdline */ char *cmdline_mopts; /* module options from cmdline */ @@ -170,7 +157,7 @@ struct globals { /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ smallint need_symbols; struct utsname uts; - llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */ + module_db db; } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ @@ -195,51 +182,9 @@ static char *gather_options_str(char *opts, const char *append) return opts; } -/* These three functions called many times, optimizing for speed. - * Users reported minute-long delays when they runn iptables repeatedly - * (iptables use modprobe to install needed kernel modules). - */ -static struct module_entry *helper_get_module(const char *module, int create) -{ - char modname[MODULE_NAME_LEN]; - struct module_entry *e; - llist_t *l; - unsigned i; - unsigned hash; - - filename2modname(module, modname); - - hash = 0; - for (i = 0; modname[i]; i++) - hash = ((hash << 5) + hash) + modname[i]; - hash %= DB_HASH_SIZE; - - for (l = G.db[hash]; l; l = l->link) { - e = (struct module_entry *) l->data; - if (strcmp(e->modname, modname) == 0) - return e; - } - if (!create) - return NULL; - - e = xzalloc(sizeof(*e)); - e->modname = xstrdup(modname); - llist_add_to(&G.db[hash], e); - - return e; -} -static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module) +static struct module_entry *get_or_add_modentry(const char *module) { - return helper_get_module(module, 1); -} -/* So far this function always gets a module pathname, never an alias name. - * The crucial difference is that pathname needs dirname stripping, - * while alias name must NOT do it! - * Testcase where dirname stripping is likely to go wrong: "modprobe devname:snd/timer" - */ -static ALWAYS_INLINE struct module_entry *get_modentry(const char *pathname) -{ - return helper_get_module(bb_get_last_path_component_nostrip(pathname), 0); + return moddb_get_or_create(&G.db, module); } static void add_probe(const char *name) @@ -536,7 +481,7 @@ static void load_modules_dep(void) continue; *colon = '\0'; - m = get_modentry(tokens[0]); + m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0])); if (m == NULL) continue; @@ -697,5 +642,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } while (me->realnames != NULL); } + if (ENABLE_FEATURE_CLEAN_UP) + moddb_free(&G.db); + return (rc != 0); } diff --git a/modutils/modutils.c b/modutils/modutils.c index ef4134af5..8e9eef72d 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -16,6 +16,57 @@ extern int delete_module(const char *module, unsigned int flags); # define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) #endif +static module_entry *helper_get_module(module_db *db, const char *module, int create) +{ + char modname[MODULE_NAME_LEN]; + struct module_entry *e; + unsigned i, hash; + + filename2modname(module, modname); + + hash = 0; + for (i = 0; modname[i]; i++) + hash = ((hash << 5) + hash) + modname[i]; + hash %= MODULE_HASH_SIZE; + + for (e = db->buckets[hash]; e; e = e->next) + if (strcmp(e->modname, modname) == 0) + return e; + if (!create) + return NULL; + + e = xzalloc(sizeof(*e)); + e->modname = xstrdup(modname); + e->next = db->buckets[hash]; + db->buckets[hash] = e; + e->dnext = e->dprev = e; + + return e; +} +module_entry* FAST_FUNC moddb_get(module_db *db, const char *module) +{ + return helper_get_module(db, module, 0); +} +module_entry* FAST_FUNC moddb_get_or_create(module_db *db, const char *module) +{ + return helper_get_module(db, module, 1); +} + +void FAST_FUNC moddb_free(module_db *db) +{ + module_entry *e, *n; + unsigned i; + + for (i = 0; i < MODULE_HASH_SIZE; i++) { + for (e = db->buckets[i]; e; e = n) { + n = e->next; + free(e->name); + free(e->modname); + free(e); + } + } +} + void FAST_FUNC replace(char *s, char what, char with) { while (*s) { diff --git a/modutils/modutils.h b/modutils/modutils.h index 5f059c716..2cbd1448a 100644 --- a/modutils/modutils.h +++ b/modutils/modutils.h @@ -16,6 +16,36 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN /* linux/include/linux/module.h has 64, but this is also used * internally for the maximum alias name length, which can be quite long */ #define MODULE_NAME_LEN 256 +#define MODULE_HASH_SIZE 256 + +typedef struct module_entry { + struct module_entry *next; + char *name, *modname; + llist_t *deps; + IF_MODPROBE( + llist_t *realnames; + unsigned flags; + const char *probed_name; /* verbatim as seen on cmdline */ + char *options; /* options from config files */ + ) + IF_DEPMOD( + llist_t *aliases; + llist_t *symbols; + struct module_entry *dnext, *dprev; + ) +} module_entry; + +typedef struct module_db { + module_entry *buckets[MODULE_HASH_SIZE]; +} module_db; + +#define moddb_foreach_module(db, module, index) \ + for ((index) = 0; (index) < MODULE_HASH_SIZE; (index)++) \ + for (module = (db)->buckets[index]; module; module = module->next) + +module_entry *moddb_get(module_db *db, const char *s) FAST_FUNC; +module_entry *moddb_get_or_create(module_db *db, const char *s) FAST_FUNC; +void moddb_free(module_db *db) FAST_FUNC; void replace(char *s, char what, char with) FAST_FUNC; char *replace_underscores(char *s) FAST_FUNC; -- cgit v1.2.3-55-g6feb From 196e400441652946b9c7ad7bc2d78c73885f2359 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Nov 2015 15:50:28 +0100 Subject: modutils: fix build error with !DEPMOD Signed-off-by: Denys Vlasenko --- modutils/modutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modutils/modutils.c b/modutils/modutils.c index 8e9eef72d..0a056731d 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -39,7 +39,7 @@ static module_entry *helper_get_module(module_db *db, const char *module, int cr e->modname = xstrdup(modname); e->next = db->buckets[hash]; db->buckets[hash] = e; - e->dnext = e->dprev = e; + IF_DEPMOD(e->dnext = e->dprev = e;) return e; } -- cgit v1.2.3-55-g6feb