From 40394cb1c963c35d2daa9570ba968afa981cf1fc Mon Sep 17 00:00:00 2001 From: Euan Harris Date: Thu, 3 May 2018 13:34:46 +0100 Subject: nsenter: Rename --network option to --net In nsenter from util-linux, the long version of the -n option is --net=. BusyBox's version expects --network=, so scripts and examples written for util-linux's version cause BusyBox's version to exit with the usage message. Confusingly, until commit 036585a911a5f, the usage message erroneously claimed that the long option was indeed called --net; after that commit long options are not listed at all. Signed-off-by: Euan Harris Signed-off-by: Denys Vlasenko --- util-linux/nsenter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index c6933c8d5..35439a2ab 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c @@ -112,7 +112,7 @@ static const char nsenter_longopts[] ALIGN1 = "user\0" Optional_argument "U" "ipc\0" Optional_argument "i" "uts\0" Optional_argument "u" - "network\0" Optional_argument "n" + "net\0" Optional_argument "n" "pid\0" Optional_argument "p" "mount\0" Optional_argument "m" "target\0" Required_argument "t" -- cgit v1.2.3-55-g6feb From 254e47372f77ea1070be6dbb44b5c45770115a07 Mon Sep 17 00:00:00 2001 From: Euan Harris Date: Fri, 4 May 2018 16:18:47 +0100 Subject: nsenter: fix parsing of -t, -S and -G options -t, -S and -G each take mandatory integer arguments. getopt32long()'s option string syntax for this type of argument is 'c:+', however nsenter's opt_str uses 'c+', which specifies two options 'c' and '+' which do not take arguments. This means that giving a target PID causes nsenter to exit and print the usage string: # nsenter -t1 sh nsenter: unrecognized option: 1 BusyBox v1.27.2 (2017-12-12 10:41:50 GMT) multi-call binary. ... The long form options are also broken: # nsenter --setuid=1000 --setgid=1000 sh BusyBox v1.29.0.git (2018-05-04 13:56:49 UTC) multi-call binary. ... `nsenter --target= sh` parses correctly and appears to work, but is ignored and set to 0. This doesn't raise an error unless one of the namespace arguments is also given: # ./busybox_unstripped nsenter --target=42 sh # exit # ./busybox_unstripped nsenter -n --target=42 sh BusyBox v1.29.0.git (2018-05-04 13:56:49 UTC) multi-call binary. ... This has caused problems in a couple of places: https://github.com/linuxkit/linuxkit/issues/567 https://github.com/gliderlabs/docker-alpine/issues/359 https://github.com/kontena/pharos-cluster/pull/81 Signed-off-by: Euan Harris Signed-off-by: Denys Vlasenko --- util-linux/nsenter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index 35439a2ab..ae8103a52 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c @@ -105,7 +105,7 @@ static const struct namespace_descr ns_list[] = { /* * Upstream nsenter doesn't support the short option for --preserve-credentials */ -static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t+S+G+r::w::F"; +static const char opt_str[] ALIGN1 = "U::i::u::n::p::m::""t:+S:+G:+r::w::F"; #if ENABLE_LONG_OPTS static const char nsenter_longopts[] ALIGN1 = -- cgit v1.2.3-55-g6feb From 43b9235f66aa56bb884c13443d9e7d56003b5c36 Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Mon, 14 May 2018 14:29:15 +1000 Subject: udhcp: fix use of trim() in udhcp_str2optset() trim() modifies the string in place if needed and returns a pointer to the end of the resulting string. Update udhcp_str2optset() so it no longer sets the value of 'val' to the return value of trim(). Signed-off-by: Samuel Mendoza-Jonas Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index fbf9c6878..b7c04da73 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -489,9 +489,10 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dh int length; char *val; - if (optflag->flags == OPTION_BIN) - val = trim(strtok(NULL, "")); /* do not split "'q w e'" */ - else + if (optflag->flags == OPTION_BIN) { + val = strtok(NULL, ""); /* do not split "'q w e'" */ + trim(val); + } else val = strtok(NULL, ", \t"); if (!val) break; -- cgit v1.2.3-55-g6feb From bcdec1a8b8bf9fb3ea4de96d153b203e12e035fd Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Mon, 14 May 2018 14:29:11 +1000 Subject: udhcpc6: add DHCPv6 env helper Add string_option_to_env() to easily generate environment variables for known simple options. Signed-off-by: Samuel Mendoza-Jonas Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 85d9da724..fa1568b5f 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -195,6 +195,34 @@ static char** new_env(void) return &client6_data.env_ptr[client6_data.env_idx++]; } +static char *string_option_to_env(uint8_t *option, uint8_t *option_end) +{ + const char *ptr, *name = NULL; + unsigned val_len; + int i; + + ptr = d6_option_strings; + i = 0; + while (*ptr) { + if (d6_optflags[i].code == option[1]) { + name = ptr; + goto found; + } + ptr += strlen(ptr) + 1; + i++; + } + bb_error_msg("can't find option name for 0x%x, skipping", option[1]); + return NULL; + + found: + val_len = (option[2] << 8) | option[3]; + if (val_len + &option[D6_OPT_DATA] > option_end) { + bb_error_msg("option data exceeds option length"); + return NULL; + } + return xasprintf("%s=%.*s", name, val_len, (char*)option + 4); +} + /* put all the parameters into the environment */ static void option_to_env(uint8_t *option, uint8_t *option_end) { -- cgit v1.2.3-55-g6feb From 23cbd7d5bbbf8f5fb65d1ff3a92323f2bb300f63 Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Mon, 14 May 2018 14:29:12 +1000 Subject: udhcpc6: add DHCPv6 boot options Add support for 'bootfile-url' and 'bootfile-params' as defined by RFC5970 "DHCPv6 Options for Network Boot". Signed-off-by: Samuel Mendoza-Jonas Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_common.h | 3 +++ networking/udhcp/d6_dhcpc.c | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h index e9c0397ae..d0506e2bb 100644 --- a/networking/udhcp/d6_common.h +++ b/networking/udhcp/d6_common.h @@ -128,6 +128,9 @@ struct d6_option { #define D6_OPT_TZ_POSIX 41 #define D6_OPT_TZ_NAME 42 +#define D6_OPT_BOOT_URL 59 +#define D6_OPT_BOOT_PARAM 60 + /*** Other shared functions ***/ struct client6_data_t { diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index fa1568b5f..f837bd549 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -38,6 +38,14 @@ //config: help //config: You can request POSIX timezone with "-O tz" and timezone name //config: with "-O timezone". +//config: +//config:config FEATURE_UDHCPC6_RFC5970 +//config: bool "Support RFC 5970 (Network Boot)" +//config: default y +//config: depends on UDHCPC6 +//config: help +//config: You can request bootfile-url with "-O bootfile_url" and +//config: bootfile-params with "-O bootfile_params". //applet:IF_UDHCPC6(APPLET(udhcpc6, BB_DIR_USR_BIN, BB_SUID_DROP)) @@ -70,6 +78,10 @@ static const struct dhcp_optflag d6_optflags[] = { #if ENABLE_FEATURE_UDHCPC6_RFC4833 { OPTION_STRING, D6_OPT_TZ_POSIX }, { OPTION_STRING, D6_OPT_TZ_NAME }, +#endif +#if ENABLE_FEATURE_UDHCPC6_RFC5970 + { OPTION_STRING, D6_OPT_BOOT_URL }, + { OPTION_STRING, D6_OPT_BOOT_PARAM }, #endif { 0, 0 } }; @@ -86,6 +98,11 @@ static const char d6_option_strings[] ALIGN1 = "tz" "\0" /* D6_OPT_TZ_POSIX */ "timezone" "\0" /* D6_OPT_TZ_NAME */ #endif +#if ENABLE_FEATURE_UDHCPC6_RFC5970 + "bootfile_url" "\0" /* D6_OPT_BOOT_URL */ + "bootfile_param" "\0" /* D6_OPT_BOOT_PARAM */ +#endif + "\0"; #if ENABLE_LONG_OPTS @@ -382,6 +399,14 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) *new_env() = xasprintf("tz_name=%.*s", (int)option[3], (char*)option + 4); break; #endif + case D6_OPT_BOOT_URL: + case D6_OPT_BOOT_PARAM: + { + char *tmp = string_option_to_env(option, option_end); + if (tmp) + *new_env() = tmp; + break; + } } len_m4 -= 4 + option[3]; option += 4 + option[3]; -- cgit v1.2.3-55-g6feb From 30f4d52ed17112f4fa340afe3bcaf305eeed36d9 Mon Sep 17 00:00:00 2001 From: Samuel Mendoza-Jonas Date: Mon, 14 May 2018 14:29:13 +1000 Subject: udhcpc6: add PXELINUX options Add support for the PXELINUX options 209 ("ConfigFile") and 210 ("PathPrefix") in the DHCPv6 client. See also: RFC5071, "Dynamic Host Configuration Protocol Options Used by PXELINUX". Signed-off-by: Samuel Mendoza-Jonas Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index f837bd549..85068721a 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -83,6 +83,8 @@ static const struct dhcp_optflag d6_optflags[] = { { OPTION_STRING, D6_OPT_BOOT_URL }, { OPTION_STRING, D6_OPT_BOOT_PARAM }, #endif + { OPTION_STRING, 0xd1 }, /* DHCP_PXE_CONF_FILE */ + { OPTION_STRING, 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ { 0, 0 } }; /* Must match d6_optflags[] order */ @@ -102,7 +104,8 @@ static const char d6_option_strings[] ALIGN1 = "bootfile_url" "\0" /* D6_OPT_BOOT_URL */ "bootfile_param" "\0" /* D6_OPT_BOOT_PARAM */ #endif - + "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ + "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ "\0"; #if ENABLE_LONG_OPTS @@ -401,6 +404,8 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) #endif case D6_OPT_BOOT_URL: case D6_OPT_BOOT_PARAM: + case 0xd1: /* DHCP_PXE_CONF_FILE */ + case 0xd2: /* DHCP_PXE_PATH_PREFIX */ { char *tmp = string_option_to_env(option, option_end); if (tmp) -- cgit v1.2.3-55-g6feb From 6027597fd1a1a9293818db4729625fff375bf907 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 May 2018 11:06:35 +0200 Subject: udhcpc6: set -x options in request Last foru commits: function old new delta option_to_env 621 791 +170 .rodata 168351 168505 +154 attach_option 431 506 +75 add_d6_client_options 112 167 +55 d6_option_strings 30 84 +54 udhcp_str2optset 644 660 +16 d6_optflags 12 20 +8 udhcpc6_main 2590 2596 +6 udhcpc_main 2648 2651 +3 read_optset 15 18 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 10/0 up/down: 544/0) Total: 544 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 33 ++++++++++++++++++++++++++------- networking/udhcp/common.h | 11 ++++++++++- networking/udhcp/d6_dhcpc.c | 14 ++++++++++++-- networking/udhcp/dhcpc.c | 5 ++++- networking/udhcp/dhcpd.c | 5 ++++- 5 files changed, 56 insertions(+), 12 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index b7c04da73..52ef875f0 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -379,12 +379,18 @@ int FAST_FUNC udhcp_str2nip(const char *str, void *arg) * and to parse udhcpd.conf's "opt OPTNAME OPTVAL" directives. */ /* helper: add an option to the opt_list */ +#if !ENABLE_UDHCPC6 +#define attach_option(opt_list, optflag, buffer, length, dhcpv6) \ + attach_option(opt_list, optflag, buffer, length) +#endif static NOINLINE void attach_option( struct option_set **opt_list, const struct dhcp_optflag *optflag, char *buffer, - int length) + int length, + bool dhcpv6) { + IF_NOT_UDHCPC6(bool dhcpv6 = 0;) struct option_set *existing; char *allocated = NULL; @@ -410,10 +416,21 @@ static NOINLINE void attach_option( /* make a new option */ log2("attaching option %02x to list", optflag->code); new = xmalloc(sizeof(*new)); - new->data = xmalloc(length + OPT_DATA); - new->data[OPT_CODE] = optflag->code; - new->data[OPT_LEN] = length; - memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), length); + if (!dhcpv6) { + new->data = xmalloc(length + OPT_DATA); + new->data[OPT_CODE] = optflag->code; + new->data[OPT_LEN] = length; + memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), + length); + } else { + new->data = xmalloc(length + D6_OPT_DATA); + new->data[D6_OPT_CODE] = optflag->code >> 8; + new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; + new->data[D6_OPT_LEN] = length >> 8; + new->data[D6_OPT_LEN + 1] = length & 0xff; + memcpy(new->data + D6_OPT_DATA, (allocated ? allocated : buffer), + length); + } curr = opt_list; while (*curr && (*curr)->data[OPT_CODE] < optflag->code) @@ -450,7 +467,9 @@ static NOINLINE void attach_option( free(allocated); } -int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, const struct dhcp_optflag *optflags, const char *option_strings) +int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg, + const struct dhcp_optflag *optflags, const char *option_strings, + bool dhcpv6) { struct option_set **opt_list = arg; char *opt; @@ -602,7 +621,7 @@ case_OPTION_STRING: } if (retval) - attach_option(opt_list, optflag, opt, length); + attach_option(opt_list, optflag, opt, length, dhcpv6); } while (retval && (optflag->flags & OPTION_LIST)); return retval; diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 13059f106..5f890459c 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -164,6 +164,10 @@ enum { #define OPT_CODE 0 #define OPT_LEN 1 #define OPT_DATA 2 +/* Offsets in option byte sequence for DHCPv6 */ +#define D6_OPT_CODE 0 +#define D6_OPT_LEN 2 +#define D6_OPT_DATA 4 /* Bits in "overload" option */ #define OPTION_FIELD 0 #define FILE_FIELD 1 @@ -290,10 +294,15 @@ void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; /* 2nd param is "uint32_t*" */ int FAST_FUNC udhcp_str2nip(const char *str, void *arg); /* 2nd param is "struct option_set**" */ +#if !ENABLE_UDHCPC6 +#define udhcp_str2optset(str, arg, optflags, option_strings, dhcpv6) \ + udhcp_str2optset(str, arg, optflags, option_strings) +#endif int FAST_FUNC udhcp_str2optset(const char *str, void *arg, const struct dhcp_optflag *optflags, - const char *option_strings); + const char *option_strings, + bool dhcpv6); #if ENABLE_UDHCPC || ENABLE_UDHCPD void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 85068721a..9e3ce8b1c 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -484,8 +484,10 @@ static uint8_t *init_d6_packet(struct d6_packet *packet, char type, uint32_t xid static uint8_t *add_d6_client_options(uint8_t *ptr) { + struct option_set *curr; uint8_t *start = ptr; unsigned option; + uint16_t len; ptr += 4; for (option = 1; option < 256; option++) { @@ -508,7 +510,12 @@ static uint8_t *add_d6_client_options(uint8_t *ptr) ptr = mempcpy(ptr, &opt_fqdn_req, sizeof(opt_fqdn_req)); #endif /* Add -x options if any */ - //... + curr = client_config.options; + while (curr) { + len = (curr->data[D6_OPT_LEN] << 8) | curr->data[D6_OPT_LEN + 1]; + ptr = mempcpy(ptr, curr->data, D6_OPT_DATA + len); + curr = curr->next; + } return ptr; } @@ -1215,7 +1222,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) } while (list_x) { char *optstr = xstrdup(llist_pop(&list_x)); - udhcp_str2optset(optstr, &client_config.options, d6_optflags, d6_option_strings); + udhcp_str2optset(optstr, &client_config.options, + d6_optflags, d6_option_strings, + /*dhcpv6:*/ 1 + ); free(optstr); } diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index bd9e8fdc2..c206a5825 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1337,7 +1337,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) } while (list_x) { char *optstr = xstrdup(llist_pop(&list_x)); - udhcp_str2optset(optstr, &client_config.options, dhcp_optflags, dhcp_option_strings); + udhcp_str2optset(optstr, &client_config.options, + dhcp_optflags, dhcp_option_strings, + /*dhcpv6:*/ 0 + ); free(optstr); } diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 19f94a2d7..ef59dca5c 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -362,7 +362,10 @@ static int FAST_FUNC read_staticlease(const char *const_line, void *arg) } static int FAST_FUNC read_optset(const char *line, void *arg) { - return udhcp_str2optset(line, arg, dhcp_optflags, dhcp_option_strings); + return udhcp_str2optset(line, arg, + dhcp_optflags, dhcp_option_strings, + /*dhcpv6:*/ 0 + ); } struct config_keyword { -- cgit v1.2.3-55-g6feb From 2ccd3522816291bd7e3ede3f60370d725d86e179 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 14 May 2018 11:14:58 +0200 Subject: popmaildir: placate gcc8 "warning: 'strncpy' output truncated" Signed-off-by: Denys Vlasenko --- mailutils/popmaildir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index a4aad3662..589456715 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c @@ -265,7 +265,7 @@ int popmaildir_main(int argc UNUSED_PARAM, char **argv) // atomically move message to ./new/ target = xstrdup(filename); - strncpy(target, "new", 3); + memcpy(target, "new", 3); // ... or just stop receiving on failure if (rename_or_warn(filename, target)) break; -- cgit v1.2.3-55-g6feb From a40a661d971cf75c617c83357ac0e87a45f41f4f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 20 May 2018 22:43:42 +0200 Subject: tweak /var/service example Signed-off-by: Denys Vlasenko --- examples/var_service/ifplugd_if/ifplugd_handler | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/examples/var_service/ifplugd_if/ifplugd_handler b/examples/var_service/ifplugd_if/ifplugd_handler index 4962fcf98..0749019f1 100755 --- a/examples/var_service/ifplugd_if/ifplugd_handler +++ b/examples/var_service/ifplugd_if/ifplugd_handler @@ -3,13 +3,18 @@ # $1: interface # $2: state -if test -d "/var/service/dhcp_$1"; then - if test x"$2" = x"down"; then - echo "Downing /var/service/dhcp_$1" - sv d "/var/service/dhcp_$1" - fi - if test x"$2" = x"up"; then - echo "Upping /var/service/dhcp_$1" - sv u "/var/service/dhcp_$1" - fi +if test x"$2" = x"down"; then + echo "Downing dhcp_$1" + svc -d "dhcp_$1" + echo "Downing zcip_$1" + svc -d "zcip_$1" fi +if test x"$2" = x"up"; then + echo "Upping dhcp_$1" + svc -u "dhcp_$1" + echo "Upping zcip_$1" + svc -u "zcip_$1" +fi +# Parent ifplugd exits if we exit with nonzero. +# Do not startle it: +exit 0 -- cgit v1.2.3-55-g6feb From 8c24af9dcfe0d89a660c39838eec4d20bc13efbf Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Tue, 22 May 2018 17:34:31 +0200 Subject: tar: fix interaction of delayed symlink and hardlink creation function old new delta create_or_remember_link - 106 +106 create_links_from_list - 93 +93 find_applet_by_name 124 128 +4 unzip_main 2724 2726 +2 data_extract_all 891 873 -18 create_symlinks_from_list 64 - -64 create_or_remember_symlink 94 - -94 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 2/1 up/down: 205/-176) Total: 29 bytes Signed-off-by: Harald van Dijk Signed-off-by: Denys Vlasenko --- archival/cpio.c | 2 +- archival/libarchive/data_extract_all.c | 16 +++++++--------- archival/libarchive/get_header_ar.c | 2 +- archival/libarchive/unsafe_symlink_target.c | 21 +++++++++++---------- archival/tar.c | 2 +- archival/unzip.c | 7 ++++--- include/bb_archive.h | 11 ++++++----- testsuite/tar.tests | 16 ++++++++++++++++ 8 files changed, 47 insertions(+), 30 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 308ec1b25..221667112 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -508,7 +508,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) while (get_header_cpio(archive_handle) == EXIT_SUCCESS) continue; - create_symlinks_from_list(archive_handle->symlink_placeholders); + create_links_from_list(archive_handle->link_placeholders); if (archive_handle->cpio__blocks != (off_t)-1 && !(opt & OPT_QUIET) diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 8fa69ffaf..4c95db4a6 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c @@ -122,13 +122,10 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) /* Handle hard links separately */ if (hard_link) { - res = link(hard_link, dst_name); - if (res != 0) { - /* shared message */ - bb_perror_msg("can't create %slink '%s' to '%s'", - "hard", dst_name, hard_link - ); - } + create_or_remember_link(&archive_handle->link_placeholders, + hard_link, + dst_name, + 1); /* Hardlinks have no separate mode/ownership, skip chown/chmod */ goto ret; } @@ -195,9 +192,10 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) * * Untarring bug.tar would otherwise place evil.py in '/tmp'. */ - create_or_remember_symlink(&archive_handle->symlink_placeholders, + create_or_remember_link(&archive_handle->link_placeholders, file_header->link_target, - dst_name); + dst_name, + 0); break; case S_IFSOCK: case S_IFBLK: diff --git a/archival/libarchive/get_header_ar.c b/archival/libarchive/get_header_ar.c index adcde46d5..7ce9c615c 100644 --- a/archival/libarchive/get_header_ar.c +++ b/archival/libarchive/get_header_ar.c @@ -126,7 +126,7 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) struct archive_handle_t *sa = archive_handle->dpkg__sub_archive; while (archive_handle->dpkg__action_data_subarchive(sa) == EXIT_SUCCESS) continue; - create_symlinks_from_list(sa->symlink_placeholders); + create_links_from_list(sa->link_placeholders); } else #endif archive_handle->action_data(archive_handle); diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c index 8dcafeaa1..f8dc8033d 100644 --- a/archival/libarchive/unsafe_symlink_target.c +++ b/archival/libarchive/unsafe_symlink_target.c @@ -5,13 +5,14 @@ #include "libbb.h" #include "bb_archive.h" -void FAST_FUNC create_or_remember_symlink(llist_t **symlink_placeholders, +void FAST_FUNC create_or_remember_link(llist_t **link_placeholders, const char *target, - const char *linkname) + const char *linkname, + int hard_link) { - if (target[0] == '/' || strstr(target, "..")) { - llist_add_to(symlink_placeholders, - xasprintf("%s%c%s", linkname, '\0', target) + if (hard_link || target[0] == '/' || strstr(target, "..")) { + llist_add_to_end(link_placeholders, + xasprintf("%c%s%c%s", hard_link, linkname, '\0', target) ); return; } @@ -23,17 +24,17 @@ void FAST_FUNC create_or_remember_symlink(llist_t **symlink_placeholders, } } -void FAST_FUNC create_symlinks_from_list(llist_t *list) +void FAST_FUNC create_links_from_list(llist_t *list) { while (list) { char *target; - target = list->data + strlen(list->data) + 1; - if (symlink(target, list->data)) { + target = list->data + 1 + strlen(list->data + 1) + 1; + if ((*list->data ? link : symlink) (target, list->data + 1)) { /* shared message */ bb_error_msg_and_die("can't create %slink '%s' to '%s'", - "sym", - list->data, target + *list->data ? "hard" : "sym", + list->data + 1, target ); } list = list->link; diff --git a/archival/tar.c b/archival/tar.c index a8b888fa9..ae1ccc756 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -1244,7 +1244,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) while (get_header_tar(tar_handle) == EXIT_SUCCESS) bb_got_signal = EXIT_SUCCESS; /* saw at least one header, good */ - create_symlinks_from_list(tar_handle->symlink_placeholders); + create_links_from_list(tar_handle->link_placeholders); /* Check that every file that should have been extracted was */ while (tar_handle->accept) { diff --git a/archival/unzip.c b/archival/unzip.c index 0d00d8dc9..96b7ab69b 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -372,9 +372,10 @@ static void unzip_extract_symlink(llist_t **symlink_placeholders, target[xstate.mem_output_size] = '\0'; #endif } - create_or_remember_symlink(symlink_placeholders, + create_or_remember_link(symlink_placeholders, target, - dst_fn); + dst_fn, + 0); free(target); } #endif @@ -990,7 +991,7 @@ int unzip_main(int argc, char **argv) } #if ENABLE_FEATURE_UNZIP_CDF - create_symlinks_from_list(symlink_placeholders); + create_links_from_list(symlink_placeholders); #endif if ((opts & OPT_l) && quiet <= 1) { diff --git a/include/bb_archive.h b/include/bb_archive.h index 0252488bf..2ee30f794 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -64,8 +64,8 @@ typedef struct archive_handle_t { /* Currently processed file's header */ file_header_t *file_header; - /* List of symlink placeholders */ - llist_t *symlink_placeholders; + /* List of link placeholders */ + llist_t *link_placeholders; /* Process the header component, e.g. tar -t */ void FAST_FUNC (*action_header)(const file_header_t *); @@ -203,10 +203,11 @@ void seek_by_jump(int fd, off_t amount) FAST_FUNC; void seek_by_read(int fd, off_t amount) FAST_FUNC; const char *strip_unsafe_prefix(const char *str) FAST_FUNC; -void create_or_remember_symlink(llist_t **symlink_placeholders, +void create_or_remember_link(llist_t **link_placeholders, const char *target, - const char *linkname) FAST_FUNC; -void create_symlinks_from_list(llist_t *list) FAST_FUNC; + const char *linkname, + int hard_link) FAST_FUNC; +void create_links_from_list(llist_t *list) FAST_FUNC; void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; diff --git a/testsuite/tar.tests b/testsuite/tar.tests index 1675b07b1..6c479d3fe 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -365,4 +365,20 @@ n8fYaKlioCTzL2oXYczyUUIP4u5IpwoSEwWdtoA= SKIP= cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null +mkdir tar.tempdir && cd tar.tempdir || exit 1 +testing "Symlinks and hardlinks coexist" '\ +mkdir dir +>dir/a +ln -s ../dir/a dir/b +ln dir/b dir/c +mkdir new +tar cf - dir/* | tar -C new -xvf - 2>&1 +' "\ +dir/a +dir/b +dir/c +" \ +"" "" +cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From ccb8e4bc4fb74701d0d323d61e9359d8597a4272 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 24 May 2018 15:26:28 +0200 Subject: fsck: fix incorrect handling of child exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit c4fb8c6a - fsck: do not use statics not only statics were changed but also a couple of statics-unrelated changes were made. This included the handling of the child termination status as follows: - if (WIFEXITED(status)) - status = WEXITSTATUS(status); - else if (WIFSIGNALED(status)) { + status = WEXITSTATUS(status); + if (WIFSIGNALED(status)) { This is wrong, should have used a different variable to hold exit code. Reported by Niklas Hambüchen . function old new delta wait_one 294 282 -12 Signed-off-by: Denys Vlasenko --- e2fsprogs/fsck.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index 1c285bb92..f5aa3dbe4 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -414,7 +414,7 @@ static void kill_all_if_got_signal(void) static int wait_one(int flags) { int status; - int sig; + int exitcode; struct fsck_instance *inst, *prev; pid_t pid; @@ -448,15 +448,16 @@ static int wait_one(int flags) } child_died: - status = WEXITSTATUS(status); + exitcode = WEXITSTATUS(status); if (WIFSIGNALED(status)) { + unsigned sig; sig = WTERMSIG(status); - status = EXIT_UNCORRECTED; + exitcode = EXIT_UNCORRECTED; if (sig != SIGINT) { printf("Warning: %s %s terminated " - "by signal %d\n", + "by signal %u\n", inst->prog, inst->device, sig); - status = EXIT_ERROR; + exitcode = EXIT_ERROR; } } @@ -492,12 +493,12 @@ static int wait_one(int flags) else G.instance_list = inst->next; if (G.verbose > 1) - printf("Finished with %s (exit status %d)\n", - inst->device, status); + printf("Finished with %s (exit status %u)\n", + inst->device, exitcode); G.num_running--; free_instance(inst); - return status; + return exitcode; } /* -- cgit v1.2.3-55-g6feb From 3f91e662f21083d4febf74fa89ccc50e406cbf6c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 24 May 2018 16:38:40 +0200 Subject: nc: fix the !NC_SERVER configuration The symptom is the "nc: NO OPT l!" message. Signed-off-by: Denys Vlasenko --- networking/nc_bloaty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 64098648a..42c84de45 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c @@ -791,7 +791,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv) "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk") IF_NC_EXTRA("i:o:z") "\0" - "?2:vv:ll", /* max 2 params; -v and -l are counters */ + "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */ &str_p, &str_s, &o_wait IF_NC_EXTRA(, &str_i, &str_o) , &o_verbose IF_NC_SERVER(, &cnt_l) -- cgit v1.2.3-55-g6feb From 747162109fb1c891baf6aafa1ca0410bd08d04a4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 24 May 2018 17:29:14 +0200 Subject: realpath,readlink -f: coreutils compat, closes 11021 function old new delta xmalloc_realpath_coreutils - 121 +121 Signed-off-by: Denys Vlasenko --- coreutils/readlink.c | 2 +- coreutils/realpath.c | 2 +- include/libbb.h | 1 + libbb/xreadlink.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/coreutils/readlink.c b/coreutils/readlink.c index b8e327d11..49361cea0 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -86,7 +86,7 @@ int readlink_main(int argc UNUSED_PARAM, char **argv) /* NOFORK: only one alloc is allowed; must free */ if (opt & 1) { /* -f */ - buf = xmalloc_realpath(fname); + buf = xmalloc_realpath_coreutils(fname); } else { buf = xmalloc_readlink_or_warn(fname); } diff --git a/coreutils/realpath.c b/coreutils/realpath.c index aa878fcd2..43923681c 100644 --- a/coreutils/realpath.c +++ b/coreutils/realpath.c @@ -38,7 +38,7 @@ int realpath_main(int argc UNUSED_PARAM, char **argv) do { /* NOFORK: only one alloc is allowed; must free */ - char *resolved_path = xmalloc_realpath(*argv); + char *resolved_path = xmalloc_realpath_coreutils(*argv); if (resolved_path != NULL) { puts(resolved_path); free(resolved_path); diff --git a/include/libbb.h b/include/libbb.h index a605c7f03..d4ba031df 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -485,6 +485,7 @@ DIR *xopendir(const char *path) FAST_FUNC; DIR *warn_opendir(const char *path) FAST_FUNC; char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; +char *xmalloc_realpath_coreutils(const char *path) FAST_FUNC RETURNS_MALLOC; char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; /* !RETURNS_MALLOC: it's a realloc-like function */ diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 9b62bcc43..6315033bb 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -122,3 +122,33 @@ char* FAST_FUNC xmalloc_realpath(const char *path) return xstrdup(realpath(path, buf)); #endif } + +char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) +{ + char *buf; + + errno = 0; + buf = xmalloc_realpath(path); + /* + * There is one case when "readlink -f" and + * "realpath" from coreutils succeed, + * even though file does not exist, such as: + * /tmp/file_does_not_exist + * (the directory must exist). + */ + if (!buf && errno == ENOENT) { + char *last_slash = strrchr(path, '/'); + if (last_slash) { + *last_slash++ = '\0'; + buf = xmalloc_realpath(path); + if (buf) { + unsigned len = strlen(buf); + buf = xrealloc(buf, len + strlen(last_slash) + 2); + buf[len++] = '/'; + strcpy(buf + len, last_slash); + } + } + } + + return buf; +} -- cgit v1.2.3-55-g6feb From a174c791ece5d7f2869e9efd338d91c8ea10f609 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Thu, 24 May 2018 08:30:16 -0700 Subject: udhcpc6: ignore invalid OPTION_IAADDR Signed-off-by: David Decotigny Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 9e3ce8b1c..2ff9c5669 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -287,6 +287,10 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) * | valid-lifetime | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + /* Make sure payload contains an address */ + if (option[3] < 24) + break; + sprint_nip6(ipv6str, option + 4); *new_env() = xasprintf("ipv6=%s", ipv6str); -- cgit v1.2.3-55-g6feb From 8f48fc01e9e43d16bf5860fa37252b43c76cb395 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Thu, 24 May 2018 08:30:15 -0700 Subject: udhcpc6: carry along length of packet when parsing it. This is to avoid parsing garbage past packet's actual end. Also const-ize params to a few functions. function old new delta d6_run_script_no_option - 12 +12 option_to_env 791 798 +7 d6_run_script 253 255 +2 perform_d6_release 95 93 -2 udhcpc6_main 2596 2592 -4 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/2 up/down: 21/-6) Total: 15 bytes Signed-off-by: David Decotigny Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 2ff9c5669..4dbc2b1bd 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -215,7 +215,8 @@ static char** new_env(void) return &client6_data.env_ptr[client6_data.env_idx++]; } -static char *string_option_to_env(uint8_t *option, uint8_t *option_end) +static char *string_option_to_env(const uint8_t *option, + const uint8_t *option_end) { const char *ptr, *name = NULL; unsigned val_len; @@ -244,7 +245,7 @@ static char *string_option_to_env(uint8_t *option, uint8_t *option_end) } /* put all the parameters into the environment */ -static void option_to_env(uint8_t *option, uint8_t *option_end) +static void option_to_env(const uint8_t *option, const uint8_t *option_end) { #if ENABLE_FEATURE_UDHCPC6_RFC3646 int addrs, option_offset; @@ -422,7 +423,7 @@ static void option_to_env(uint8_t *option, uint8_t *option_end) } } -static char **fill_envp(struct d6_packet *packet) +static char **fill_envp(const uint8_t *option, const uint8_t *option_end) { char **envp, **curr; @@ -431,8 +432,8 @@ static char **fill_envp(struct d6_packet *packet) *new_env() = xasprintf("interface=%s", client_config.interface); - if (packet) - option_to_env(packet->d6_options, packet->d6_options + sizeof(packet->d6_options)); + if (option) + option_to_env(option, option_end); envp = curr = client6_data.env_ptr; while (*curr) @@ -442,12 +443,13 @@ static char **fill_envp(struct d6_packet *packet) } /* Call a script with a par file and env vars */ -static void d6_run_script(struct d6_packet *packet, const char *name) +static void d6_run_script(const uint8_t *option, const uint8_t *option_end, + const char *name) { char **envp, **curr; char *argv[3]; - envp = fill_envp(packet); + envp = fill_envp(option, option_end); /* call script */ log1("executing %s %s", client_config.script, name); @@ -463,6 +465,11 @@ static void d6_run_script(struct d6_packet *packet, const char *name) free(envp); } +/* Call a script with a par file and no env var */ +static void d6_run_script_no_option(const char *name) +{ + d6_run_script(NULL, NULL, name); +} /*** Sending/receiving packets ***/ @@ -1038,7 +1045,7 @@ static void perform_renew(void) state = RENEW_REQUESTED; break; case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ - d6_run_script(NULL, "deconfig"); + d6_run_script_no_option("deconfig"); case REQUESTING: case RELEASED: change_listen_mode(LISTEN_RAW); @@ -1067,7 +1074,7 @@ static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *ou * Users requested to be notified in all cases, even if not in one * of the states above. */ - d6_run_script(NULL, "deconfig"); + d6_run_script_no_option("deconfig"); change_listen_mode(LISTEN_NONE); state = RELEASED; } @@ -1276,7 +1283,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) udhcp_sp_setup(); state = INIT_SELECTING; - d6_run_script(NULL, "deconfig"); + d6_run_script_no_option("deconfig"); change_listen_mode(LISTEN_RAW); packet_num = 0; timeout = 0; @@ -1357,7 +1364,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) continue; } leasefail: - d6_run_script(NULL, "leasefail"); + d6_run_script_no_option("leasefail"); #if BB_MMU /* -b is not supported on NOMMU */ if (opt & OPT_b) { /* background if no lease */ bb_error_msg("no lease, forking to background"); @@ -1431,7 +1438,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) } /* Timed out, enter init state */ bb_error_msg("lease lost, entering init state"); - d6_run_script(NULL, "deconfig"); + d6_run_script_no_option("deconfig"); state = INIT_SELECTING; client_config.first_secs = 0; /* make secs field count from 0 */ /*timeout = 0; - already is */ @@ -1538,9 +1545,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) if (option && (option->data[0] | option->data[1]) != 0) { /* return to init state */ bb_error_msg("received DHCP NAK (%u)", option->data[4]); - d6_run_script(&packet, "nak"); + d6_run_script(packet.d6_options, + packet_end, "nak"); if (state != REQUESTING) - d6_run_script(NULL, "deconfig"); + d6_run_script_no_option("deconfig"); change_listen_mode(LISTEN_RAW); sleep(3); /* avoid excessive network traffic */ state = INIT_SELECTING; @@ -1737,7 +1745,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) if (timeout < 0x10) timeout = 0x10; /* enter bound state */ - d6_run_script(&packet, state == REQUESTING ? "bound" : "renew"); + d6_run_script(packet.d6_options, packet_end, + (state == REQUESTING ? "bound" : "renew")); state = BOUND; change_listen_mode(LISTEN_NONE); -- cgit v1.2.3-55-g6feb From a36986bb80289c1cd8d15a557e49207c9a42946b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 25 May 2018 17:03:46 +0200 Subject: unlzma: close another SEGV possibility function old new delta unpack_lzma_stream 2669 2686 +17 Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_unlzma.c | 6 +++++- testsuite/unzip.tests | 19 ++++++++++++++++--- testsuite/unzip_bad_lzma_2.zip | Bin 0 -> 96 bytes 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 testsuite/unzip_bad_lzma_2.zip diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index 446319e7b..6886239d0 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c @@ -350,8 +350,12 @@ unpack_lzma_stream(transformer_state_t *xstate) state = state < LZMA_NUM_LIT_STATES ? 9 : 11; pos = buffer_pos - rep0; - if ((int32_t)pos < 0) + if ((int32_t)pos < 0) { pos += header.dict_size; + /* see unzip_bad_lzma_2.zip: */ + if (pos >= buffer_size) + goto bad; + } previous_byte = buffer[pos]; goto one_byte1; #else diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests index 6bcb6b3a2..af53de9df 100755 --- a/testsuite/unzip.tests +++ b/testsuite/unzip.tests @@ -14,7 +14,7 @@ # Create a scratch directory mkdir temp -cd temp || exit 90 +cd temp || exit $? # Create test file to work with. @@ -54,9 +54,22 @@ SKIP= rm -f * -optional CONFIG_FEATURE_UNZIP_LZMA -testing "unzip (archive with corrupted lzma)" "unzip -p ../unzip_bad_lzma_1.zip 2>&1; echo \$?" \ +optional FEATURE_UNZIP_LZMA +testing "unzip (archive with corrupted lzma 1)" "unzip -p ../unzip_bad_lzma_1.zip 2>&1; echo \$?" \ "unzip: removing leading '/' from member names +unzip: corrupted data +unzip: inflate error +1 +" \ +"" "" +SKIP= + +rm -f * + +optional FEATURE_UNZIP_LZMA +testing "unzip (archive with corrupted lzma 2)" "unzip -p ../unzip_bad_lzma_2.zip 2>&1; echo \$?" \ +"unzip: removing leading '/' from member names +unzip: corrupted data unzip: inflate error 1 " \ diff --git a/testsuite/unzip_bad_lzma_2.zip b/testsuite/unzip_bad_lzma_2.zip new file mode 100644 index 000000000..cdb917088 Binary files /dev/null and b/testsuite/unzip_bad_lzma_2.zip differ -- cgit v1.2.3-55-g6feb From bf7f103ffb6e2644e9c063cba723e25635c14a52 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 26 May 2018 17:42:00 +0200 Subject: whitespace fix Signed-off-by: Denys Vlasenko --- libbb/xreadlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index 6315033bb..ead30e499 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -143,7 +143,7 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) buf = xmalloc_realpath(path); if (buf) { unsigned len = strlen(buf); - buf = xrealloc(buf, len + strlen(last_slash) + 2); + buf = xrealloc(buf, len + strlen(last_slash) + 2); buf[len++] = '/'; strcpy(buf + len, last_slash); } -- cgit v1.2.3-55-g6feb From 8bc418f07eab79a9c8d26594629799f6157a9466 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 26 May 2018 18:51:18 +0200 Subject: fdisk: remove "Partition N does not end on cylinder boundary" message fdisk from util-linux 2.31 (maybe earlier) does not print this. function old new delta check_consistency 449 399 -50 Signed-off-by: Denys Vlasenko --- util-linux/fdisk.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 7275535e6..cdcba0a03 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -2004,12 +2004,6 @@ check_consistency(const struct partition *p, int partition) printf(" phys=(%u,%u,%u) ", pec, peh, pes); printf("logical=(%u,%u,%u)\n", lec, leh, les); } - -/* Ending on cylinder boundary? */ - if (peh != (g_heads - 1) || pes != g_sectors) { - printf("Partition %u does not end on cylinder boundary\n", - partition + 1); - } } static void -- cgit v1.2.3-55-g6feb From 0972c7f7a570c38edb68e1c60a45614b7a7c7d55 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 28 May 2018 14:36:26 +0200 Subject: wget: emit a message that certificate verification is not implemented function old new delta spawn_ssl_client 185 209 +24 Signed-off-by: Denys Vlasenko --- networking/wget.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 30c339244..8103aacee 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -137,6 +137,7 @@ //usage: "Retrieve files via HTTP or FTP\n" //usage: IF_FEATURE_WGET_LONG_OPTIONS( //usage: "\n --spider Only check URL existence: $? is 0 if exists" +///////: "\n --no-check-certificate Don't validate the server's certificate" //usage: ) //usage: "\n -c Continue retrieval of aborted transfer" //usage: "\n -q Quiet" @@ -271,6 +272,7 @@ enum { WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_NO_CHECK_CERT = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, }; enum { @@ -714,6 +716,9 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) int pid; char *servername, *p; + if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) + bb_error_msg("note: TLS certificate validation not implemented"); + servername = xstrdup(host); p = strrchr(servername, ':'); if (p) *p = '\0'; @@ -1402,10 +1407,9 @@ IF_DESKTOP( "tries\0" Required_argument "t") "header\0" Required_argument "\xff" "post-data\0" Required_argument "\xfe" "spider\0" No_argument "\xfd" + "no-check-certificate\0" No_argument "\xfc" /* Ignored (we always use PASV): */ IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") - /* Ignored (we don't do ssl) */ -IF_DESKTOP( "no-check-certificate\0" No_argument "\xf0") /* Ignored (we don't support caching) */ IF_DESKTOP( "no-cache\0" No_argument "\xf0") IF_DESKTOP( "no-verbose\0" No_argument "\xf0") @@ -1465,6 +1469,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") if (option_mask32 & WGET_OPT_HEADER) bb_error_msg("--header"); if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); + if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate"); exit(0); #endif argv += optind; -- cgit v1.2.3-55-g6feb From 43b17b1cd0dd3eac740e4770be77db2c9010ad04 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 31 May 2018 22:15:55 -0700 Subject: restore documentation on the build config language Kconfig-language.txt was deleted in commit 4fa499a17b52b back in 2006. Move to docs/ as suggested by Xabier Oneca: http://lists.busybox.net/pipermail/busybox/2014-May/080914.html Also update references to it everywhere. Signed-off-by: Kartik Agaram Signed-off-by: Denys Vlasenko --- Config.in | 2 +- archival/Config.src | 2 +- console-tools/Config.src | 2 +- coreutils/Config.src | 2 +- debianutils/Config.src | 2 +- docs/Kconfig-language.txt | 255 ++++++++++++++++++++++++++++++++++++++++ e2fsprogs/Config.src | 2 +- editors/Config.src | 2 +- findutils/Config.src | 2 +- init/Config.src | 2 +- klibc-utils/Config.src | 2 +- libbb/Config.src | 2 +- loginutils/Config.src | 2 +- miscutils/Config.src | 2 +- modutils/Config.src | 2 +- networking/Config.src | 2 +- networking/udhcp/Config.src | 2 +- printutils/Config.src | 2 +- procps/Config.src | 2 +- runit/Config.src | 2 +- selinux/Config.src | 2 +- shell/Config.src | 2 +- sysklogd/Config.src | 2 +- util-linux/Config.src | 2 +- util-linux/volume_id/Config.src | 2 +- 25 files changed, 279 insertions(+), 24 deletions(-) create mode 100644 docs/Kconfig-language.txt diff --git a/Config.in b/Config.in index 51ff01ef4..ae21f52ef 100644 --- a/Config.in +++ b/Config.in @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # mainmenu "Configuration" diff --git a/archival/Config.src b/archival/Config.src index 449914565..6f4f30c43 100644 --- a/archival/Config.src +++ b/archival/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Archival Utilities" diff --git a/console-tools/Config.src b/console-tools/Config.src index e6587ade4..c30caf0e1 100644 --- a/console-tools/Config.src +++ b/console-tools/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Console Utilities" diff --git a/coreutils/Config.src b/coreutils/Config.src index 7a8a3a634..1bded03a6 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Coreutils" diff --git a/debianutils/Config.src b/debianutils/Config.src index 61daeb047..17b0d8945 100644 --- a/debianutils/Config.src +++ b/debianutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Debian Utilities" diff --git a/docs/Kconfig-language.txt b/docs/Kconfig-language.txt new file mode 100644 index 000000000..0ba8932ba --- /dev/null +++ b/docs/Kconfig-language.txt @@ -0,0 +1,255 @@ +Introduction +------------ + +The configuration database is collection of configuration options +organized in a tree structure: + + +- Code maturity level options + | +- Prompt for development and/or incomplete code/drivers + +- General setup + | +- Networking support + | +- System V IPC + | +- BSD Process Accounting + | +- Sysctl support + +- Loadable module support + | +- Enable loadable module support + | +- Set version information on all module symbols + | +- Kernel module loader + +- ... + +Every entry has its own dependencies. These dependencies are used +to determine the visible of an entry. Any child entry is only +visible if its parent entry is also visible. + +Menu entries +------------ + +Most entries define a config option, all other entries help to organize +them. A single configuration option is defined like this: + +config MODVERSIONS + bool "Set version information on all module symbols" + depends MODULES + help + Usually, modules have to be recompiled whenever you switch to a new + kernel. ... + +Every line starts with a key word and can be followed by multiple +arguments. "config" starts a new config entry. The following lines +define attributes for this config option. Attributes can be the type of +the config option, input prompt, dependencies, help text and default +values. A config option can be defined multiple times with the same +name, but every definition can have only a single input prompt and the +type must not conflict. + +Menu attributes +--------------- + +A menu entry can have a number of attributes. Not all of them are +applicable everywhere (see syntax). + +- type definition: "bool"/"tristate"/"string"/"hex"/"integer" + Every config option must have a type. There are only two basic types: + tristate and string, the other types base on these two. The type + definition optionally accepts an input prompt, so these two examples + are equivalent: + + bool "Networking support" + and + bool + prompt "Networking support" + +- input prompt: "prompt" ["if" ] + Every menu entry can have at most one prompt, which is used to display + to the user. Optionally dependencies only for this prompt can be added + with "if". + +- default value: "default" ["if" ] + A config option can have any number of default values. If multiple + default values are visible, only the first defined one is active. + Default values are not limited to the menu entry, where they are + defined, this means the default can be defined somewhere else or be + overridden by an earlier definition. + The default value is only assigned to the config symbol if no other + value was set by the user (via the input prompt above). If an input + prompt is visible the default value is presented to the user and can + be overridden by him. + Optionally dependencies only for this default value can be added with + "if". + +- dependencies: "depends on"/"requires" + This defines a dependency for this menu entry. If multiple + dependencies are defined they are connected with '&&'. Dependencies + are applied to all other options within this menu entry (which also + accept "if" expression), so these two examples are equivalent: + + bool "foo" if BAR + default y if BAR + and + depends on BAR + bool "foo" + default y + +- help text: "help" + This defines a help text. The end of the help text is determined by + the level indentation, this means it ends at the first line which has + a smaller indentation than the first line of the help text. + + +Menu dependencies +----------------- + +Dependencies define the visibility of a menu entry and can also reduce +the input range of tristate symbols. The tristate logic used in the +expressions uses one more state than normal boolean logic to express the +module state. Dependency expressions have the following syntax: + + ::= (1) + '=' (2) + '!=' (3) + '(' ')' (4) + '!' (5) + '||' (6) + '&&' (7) + +Expressions are listed in decreasing order of precedence. + +(1) Convert the symbol into an expression. Boolean and tristate symbols + are simply converted into the respective expression values. All + other symbol types result in 'n'. +(2) If the values of both symbols are equal, it returns 'y', + otherwise 'n'. +(3) If the values of both symbols are equal, it returns 'n', + otherwise 'y'. +(4) Returns the value of the expression. Used to override precedence. +(5) Returns the result of (2-/expr/). +(6) Returns the result of min(/expr/, /expr/). +(7) Returns the result of max(/expr/, /expr/). + +An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 +respectively for calculations). A menu entry becomes visible when it's +expression evaluates to 'm' or 'y'. + +There are two type of symbols: constant and nonconstant symbols. +Nonconstant symbols are the most common ones and are defined with the +'config' statement. Nonconstant symbols consist entirely of alphanumeric +characters or underscores. +Constant symbols are only part of expressions. Constant symbols are +always surrounded by single or double quotes. Within the quote any +other character is allowed and the quotes can be escaped using '\'. + +Menu structure +-------------- + +The position of a menu entry in the tree is determined in two ways. First +it can be specified explicitely: + +menu "Network device support" + depends NET + +config NETDEVICES + ... + +endmenu + +All entries within the "menu" ... "endmenu" block become a submenu of +"Network device support". All subentries inherit the dependencies from +the menu entry, e.g. this means the dependency "NET" is added to the +dependency list of the config option NETDEVICES. + +The other way to generate the menu structure is done by analyzing the +dependencies. If a menu entry somehow depends on the previous entry, it +can be made a submenu of it. First the the previous (parent) symbol must +be part of the dependency list and then one of these two condititions +must be true: +- the child entry must become invisible, if the parent is set to 'n' +- the child entry must only be visible, if the parent is visible + +config MODULES + bool "Enable loadable module support" + +config MODVERSIONS + bool "Set version information on all module symbols" + depends MODULES + +comment "module support disabled" + depends !MODULES + +MODVERSIONS directly depends on MODULES, this means it's only visible if +MODULES is different from 'n'. The comment on the other hand is always +visible when MODULES it's visible (the (empty) dependency of MODULES is +also part of the comment dependencies). + + +Kconfig syntax +-------------- + +The configuration file describes a series of menu entries, where every +line starts with a keyword (except help texts). The following keywords +end a menu entry: +- config +- choice/endchoice +- comment +- menu/endmenu +- if/endif +- source +The first four also start the definition of a menu entry. + +config: + + "config" + + +This defines a config symbol and accepts any of above +attributes as options. + +choices: + + "choice" + + + "endchoice" + +This defines a choice group and accepts any of above attributes as +options. A choice can only be of type bool or tristate, while a boolean +choice only allows a single config entry to be selected, a tristate +choice also allows any number of config entries to be set to 'm'. This +can be used if multiple drivers for a single hardware exists and only a +single driver can be compiled/loaded into the kernel, but all drivers +can be compiled as modules. +A choice accepts another option "optional", which allows to set the +choice to 'n' and no entry needs to be selected. + +comment: + + "comment" + + +This defines a comment which is displayed to the user during the +configuration process and is also echoed to the output files. The only +possible options are dependencies. + +menu: + + "menu" + + + "endmenu" + +This defines a menu block, see "Menu structure" above for more +information. The only possible options are dependencies. + +if: + + "if" + + "endif" + +This defines an if block. The dependency expression is appended +to all enclosed menu entries. + +source: + + "source" + +This reads the specified configuration file. This file is always parsed. diff --git a/e2fsprogs/Config.src b/e2fsprogs/Config.src index a20d849e6..ad15f470c 100644 --- a/e2fsprogs/Config.src +++ b/e2fsprogs/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Linux Ext2 FS Progs" diff --git a/editors/Config.src b/editors/Config.src index 0920bc494..3b2e4a6c0 100644 --- a/editors/Config.src +++ b/editors/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Editors" diff --git a/findutils/Config.src b/findutils/Config.src index 9ee71a845..c28c5844e 100644 --- a/findutils/Config.src +++ b/findutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Finding Utilities" diff --git a/init/Config.src b/init/Config.src index 5767c93f0..b19b0bea1 100644 --- a/init/Config.src +++ b/init/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Init Utilities" diff --git a/klibc-utils/Config.src b/klibc-utils/Config.src index fe7cb1315..cf4552e51 100644 --- a/klibc-utils/Config.src +++ b/klibc-utils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "klibc-utils" diff --git a/libbb/Config.src b/libbb/Config.src index 16e16480b..312aa1831 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # comment "Library Tuning" diff --git a/loginutils/Config.src b/loginutils/Config.src index 680f42118..cbb09646b 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Login/Password Management Utilities" diff --git a/miscutils/Config.src b/miscutils/Config.src index 7325fb8fa..d10b00b28 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Miscellaneous Utilities" diff --git a/modutils/Config.src b/modutils/Config.src index e413702bb..188296814 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Linux Module Utilities" diff --git a/networking/Config.src b/networking/Config.src index 492c60da4..2ce5287de 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Networking Utilities" diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 50bff2e8c..e5958804b 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # config UDHCPD diff --git a/printutils/Config.src b/printutils/Config.src index e53b9d093..5f1d65f6c 100644 --- a/printutils/Config.src +++ b/printutils/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Print Utilities" diff --git a/procps/Config.src b/procps/Config.src index 515d79938..2b1b8ab11 100644 --- a/procps/Config.src +++ b/procps/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Process Utilities" diff --git a/runit/Config.src b/runit/Config.src index 8cde89680..403ec8724 100644 --- a/runit/Config.src +++ b/runit/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Runit Utilities" diff --git a/selinux/Config.src b/selinux/Config.src index 9cb755a0f..f8fcdadf9 100644 --- a/selinux/Config.src +++ b/selinux/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "SELinux Utilities" diff --git a/shell/Config.src b/shell/Config.src index 81c4ec874..959d3cb42 100644 --- a/shell/Config.src +++ b/shell/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Shells" diff --git a/sysklogd/Config.src b/sysklogd/Config.src index 684e7d414..321be0117 100644 --- a/sysklogd/Config.src +++ b/sysklogd/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "System Logging Utilities" diff --git a/util-linux/Config.src b/util-linux/Config.src index 68fcc266f..0fad3e5c0 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # menu "Linux System Utilities" diff --git a/util-linux/volume_id/Config.src b/util-linux/volume_id/Config.src index ac208c9cc..fe3b14a71 100644 --- a/util-linux/volume_id/Config.src +++ b/util-linux/volume_id/Config.src @@ -1,6 +1,6 @@ # # For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. +# see docs/Kconfig-language.txt. # config VOLUMEID -- cgit v1.2.3-55-g6feb From 6fb8bd795c3f40735ced3f51b8082f91956fd786 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Tue, 5 Jun 2018 12:48:53 -0400 Subject: Update release script to generate detached signatures and checksum files This is more usable for programmatically checking the validity of a release. Signed-off-by: Eli Schwartz Signed-off-by: Denys Vlasenko --- scripts/bb_release | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/scripts/bb_release b/scripts/bb_release index 8aa380438..2e146bf84 100755 --- a/scripts/bb_release +++ b/scripts/bb_release @@ -15,20 +15,8 @@ VERSION=`ls busybox-*.tar.gz | sed 's/busybox-\(.*\)\.tar\.gz/\1/'` zcat busybox-$VERSION.tar.gz | bzip2 > busybox-$VERSION.tar.bz2 -test -f busybox-$VERSION.tar.gz || { echo "no busybox-$VERSION.tar.gz"; exit 1; } -test -f busybox-$VERSION.tar.bz2 || { echo "no busybox-$VERSION.tar.bz2"; exit 1; } - -signit() -{ -echo "$1 released `date -r $1 -R` - -MD5: `md5sum $1` -SHA1: `sha1sum $1` - -To verify this signature, you can obtain my public key -from http://busybox.net/~vda/vda_pubkey.gpg -" | gpg --clearsign > "$1.sign" -} - -signit busybox-$VERSION.tar.gz -signit busybox-$VERSION.tar.bz2 +for releasefile in busybox-$VERSION.tar.gz busybox-$VERSION.tar.bz2; do + test -f $releasefile || { echo "no $releasefile"; exit 1; } + gpg --detach-sign $releasefile + sha256sum $releasefile > $releasefile.sha256 +done -- cgit v1.2.3-55-g6feb From 148788eb0ee96026105755cf3fd1ad3d94f49cd2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 21 Jun 2018 17:36:22 +0200 Subject: udhcpc: remove code which requires server ID to be on local network This reverts "udhcpc: paranoia when using kernel UDP mode for sending renew: server ID may be bogus". Users complain that they do have servers behind routers (with DHCP relays). function old new delta send_packet 168 166 -2 bcast_or_ucast 25 23 -2 udhcp_send_kernel_packet 301 295 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-10) Total: -10 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/common.h | 4 +--- networking/udhcp/d6_dhcpc.c | 4 +--- networking/udhcp/dhcpc.c | 10 ++-------- networking/udhcp/dhcpd.c | 4 +--- networking/udhcp/packet.c | 7 +++---- 5 files changed, 8 insertions(+), 21 deletions(-) diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 5f890459c..50ea9199b 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -317,9 +317,7 @@ int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port, - int send_flags -) FAST_FUNC; + uint32_t dest_nip, int dest_port) FAST_FUNC; void udhcp_sp_setup(void) FAST_FUNC; void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 4dbc2b1bd..ed2255ef3 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -803,15 +803,13 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st opt_ptr = add_d6_client_options(opt_ptr); bb_error_msg("sending %s", "renew"); - if (server_ipv6) { + if (server_ipv6) return d6_send_kernel_packet( &packet, (opt_ptr - (uint8_t*) &packet), our_cur_ipv6, CLIENT_PORT6, server_ipv6, SERVER_PORT6, client_config.ifindex - /* TODO? send_flags: MSG_DONTROUTE (see IPv4 code for reason why) */ ); - } return d6_mcast_from_client_config_ifindex(&packet, opt_ptr); } diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index c206a5825..c2805a009 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -693,16 +693,10 @@ static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) { - if (server) { - /* Without MSG_DONTROUTE, the packet was seen routed over - * _other interface_ if server ID is bogus (example: 1.1.1.1). - */ + if (server) return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, - server, SERVER_PORT, - /*send_flags: "to hosts only on directly connected networks" */ MSG_DONTROUTE - ); - } + server, SERVER_PORT); return raw_bcast_from_client_config_ifindex(packet, ciaddr); } diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index ef59dca5c..a8cd3f03b 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -591,9 +591,7 @@ static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt) udhcp_send_kernel_packet(dhcp_pkt, server_config.server_nip, SERVER_PORT, - dhcp_pkt->gateway_nip, SERVER_PORT, - /*send_flags:*/ 0 - ); + dhcp_pkt->gateway_nip, SERVER_PORT); } static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast) diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index fc2bb5416..ff16904f7 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -189,8 +189,7 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, /* Let the kernel do all the work for packet generation */ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, - uint32_t dest_nip, int dest_port, - int send_flags) + uint32_t dest_nip, int dest_port) { struct sockaddr_in sa; unsigned padding; @@ -227,8 +226,8 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); if (padding > DHCP_SIZE - 300) padding = DHCP_SIZE - 300; - result = send(fd, dhcp_pkt, DHCP_SIZE - padding, send_flags); - msg = "send"; + result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); + msg = "write"; ret_close: close(fd); if (result < 0) { -- cgit v1.2.3-55-g6feb From 34254f9ddece34d4df541438ec4f6a1b19929926 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 22 Jun 2018 18:59:10 +0200 Subject: install: fix "-D -t DIR1/DIR2/DIR3" creating only DIR1/DIR2, closes 11106 function old new delta install_main 758 767 +9 Signed-off-by: Denys Vlasenko --- coreutils/install.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/coreutils/install.c b/coreutils/install.c index 2e4dc257f..8270490bd 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -214,7 +214,11 @@ int install_main(int argc, char **argv) dest = last; if (opts & OPT_MKDIR_LEADING) { char *ddir = xstrdup(dest); - bb_make_directory(dirname(ddir), 0755, mkdir_flags); + /* + * -D -t DIR1/DIR2/F3 FILE: create DIR1/DIR2/F3, copy FILE there + * -D FILE DIR1/DIR2/F3: create DIR1/DIR2, copy FILE there as F3 + */ + bb_make_directory((opts & OPT_TARGET) ? ddir : dirname(ddir), 0755, mkdir_flags); /* errors are not checked. copy_file * will fail if dir is not created. */ -- cgit v1.2.3-55-g6feb From e56e091d650494e4894d24e33ab2cdb7b57dc686 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 23 Jun 2018 13:55:13 +0200 Subject: examples: update /var/service/getty for Unicode ttys Signed-off-by: Denys Vlasenko --- examples/var_service/getty_tty1/cfg | 8 +- examples/var_service/getty_tty1/login.sh | 3 +- examples/var_service/getty_tty1/ru_koi8r.keymap | 183 ------------------- examples/var_service/getty_tty1/run | 6 - .../var_service/getty_tty1/unicode_cyrillic.keymap | 200 +++++++++++++++++++++ 5 files changed, 206 insertions(+), 194 deletions(-) delete mode 100644 examples/var_service/getty_tty1/ru_koi8r.keymap create mode 100644 examples/var_service/getty_tty1/unicode_cyrillic.keymap diff --git a/examples/var_service/getty_tty1/cfg b/examples/var_service/getty_tty1/cfg index 0f63e5233..ab973f738 100755 --- a/examples/var_service/getty_tty1/cfg +++ b/examples/var_service/getty_tty1/cfg @@ -10,7 +10,7 @@ ttyname=`tty` ttybase="${ttyname%%[0123456789]*}" # strip numeric tail if test x"$ttybase" = x"/dev/vc/" -o x"$ttybase" = x"/dev/tty"; then - echo "* Activating Cyrillic KOI8-R -> CP866 font map" + echo "* Activating font map" echo -ne "\033(K" >"$ttyname" echo "* Loading screen font" @@ -18,9 +18,9 @@ if test x"$ttybase" = x"/dev/vc/" -o x"$ttybase" = x"/dev/tty"; then -C "$ttyname" \ -m "$PWD/koi8r_to_uni.trans" \ "$PWD/alt08x16+unimap.fnt" \ - || echo "! setfont failure" + || echo "setfont exit code: $?" echo "* Loading keymap" - loadkeys "$PWD/ru_koi8r.keymap" \ - || echo "! loadkeys failure" + loadkeys "$PWD/unicode_cyrillic.keymap" \ + || echo "loadkeys exit code: $?" fi diff --git a/examples/var_service/getty_tty1/login.sh b/examples/var_service/getty_tty1/login.sh index d69b6fd55..f8b53fc03 100755 --- a/examples/var_service/getty_tty1/login.sh +++ b/examples/var_service/getty_tty1/login.sh @@ -6,7 +6,8 @@ ttybase="${ttyname%%[0123456789]*}" # strip numeric tail if test "$ttybase" = "/dev/tty"; then tail="${ttyname:8}" echo "* Setting terminal device's owner to $LOGIN_UID:$LOGIN_GID" - chown "$LOGIN_UID:$LOGIN_GID" "/dev/vcs$tail" "/dev/vcsa$tail" + test -c "/dev/vcs$tail" && chown "$LOGIN_UID:$LOGIN_GID" "/dev/vcs$tail" + test -c "/dev/vcsa$tail" && chown "$LOGIN_UID:$LOGIN_GID" "/dev/vcsa$tail" fi # We can do this also, but login does it itself # chown "$LOGIN_UID:$LOGIN_GID" "$ttyname" diff --git a/examples/var_service/getty_tty1/ru_koi8r.keymap b/examples/var_service/getty_tty1/ru_koi8r.keymap deleted file mode 100644 index 6c811539c..000000000 --- a/examples/var_service/getty_tty1/ru_koi8r.keymap +++ /dev/null @@ -1,183 +0,0 @@ -keymaps 0,1, 2,3, 4,6, 8,10, 12,14 -# -# This one is for generating koi8r Russian chars -# Cyr/Lat switches: RightAlt, Shift+Ctrl, Ctrl+Shift -# (last one does not work for dark and obscure reasons 8( ) -# -# plain,shift, plain,shift, ctrl,ctrl alt,alt ctrlalt,ctrlalt -# lat-------- cyr-------- lat cyr lat cyr lat cyr -# -#Shift 1 -#AltGr (cyr) 2 -#Control 4 -#Alt 8 -#ShiftL 16 -#ShiftR 32 -#CtrlL 64 -#CtrlR 128 -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 1 = Escape Escape Escape Escape Escape Escape Meta_Escape Meta_Escape SAK SAK -keycode 2 = one exclam one exclam exclam exclam Meta_one Meta_one -keycode 3 = two at two at nul nul Meta_two Meta_two -keycode 4 = three numbersign three numbersign three three Meta_three Meta_three -keycode 5 = four dollar four dollar Control_backslash Control_backslash Meta_four Meta_four -keycode 6 = five percent five percent Control_bracketright Control_bracketright Meta_five Meta_five -keycode 7 = six asciicircum six asciicircum Control_asciicircum Control_asciicircum Meta_six Meta_six -keycode 8 = seven ampersand seven ampersand Control_underscore Control_underscore Meta_seven Meta_seven -keycode 9 = eight asterisk eight asterisk eight eight Meta_eight Meta_eight -keycode 10 = nine parenleft nine parenleft nine nine Meta_nine Meta_nine -keycode 11 = zero parenright zero parenright zero zero Meta_zero Meta_zero -keycode 12 = minus underscore minus underscore Control_underscore Control_underscore Meta_minus Meta_minus -keycode 13 = equal plus equal plus equal equal Meta_equal Meta_equal -keycode 14 = Delete Delete Delete Delete BackSpace BackSpace Meta_Delete Meta_Delete -keycode 15 = Tab Tab Tab Tab Tab Tab Meta_Tab Meta_Tab -keycode 16 = q Q 202 234 Control_q Control_q Meta_q Meta_q Meta_Control_q Meta_Control_q -keycode 17 = w W 195 227 Control_w Control_w Meta_w Meta_w Meta_Control_w Meta_Control_w -keycode 18 = e E 213 245 Control_e Control_e Meta_e Meta_e Meta_Control_e Meta_Control_e -keycode 19 = r R 203 235 Control_r Control_r Meta_r Meta_r Meta_Control_r Meta_Control_r -keycode 20 = t T 197 229 Control_t Control_t Meta_t Meta_t Meta_Control_t Meta_Control_t -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 21 = y Y 206 238 Control_y Control_y Meta_y Meta_y Meta_Control_y Meta_Control_y -keycode 22 = u U 199 231 Control_u Control_u Meta_u Meta_u Meta_Control_u Meta_Control_u -keycode 23 = i I 219 251 Control_i Control_i Meta_i Meta_i Meta_Control_i Meta_Control_i -keycode 24 = o O 221 253 Control_o Control_o Meta_o Meta_o Meta_Control_o Meta_Control_o -keycode 25 = p P 218 250 Control_p Control_p Meta_p Meta_p Meta_Control_p Meta_Control_p -keycode 26 = bracketleft braceleft 200 232 Escape Escape Meta_bracketleft Meta_bracketleft -keycode 27 = bracketright braceright 223 255 Control_bracketright Control_bracketright -keycode 28 = Return -# Shift+Ctrl - Cyrillic -keycode 29 = Control AltGr_Lock Control AltGr_Lock Control Control Control Control Control Control -keycode 30 = a A 198 230 Control_a Control_a Meta_a Meta_a Meta_Control_a Meta_Control_a -keycode 31 = s S 217 249 Control_s Control_s Meta_s Meta_s Meta_Control_s Meta_Control_s -keycode 32 = d D 215 247 Control_d Control_d Meta_d Meta_d Meta_Control_d Meta_Control_d -keycode 33 = f F 193 225 Control_f Control_f Meta_f Meta_f Meta_Control_f Meta_Control_f -keycode 34 = g G 208 240 Control_g Control_g Meta_g Meta_g Meta_Control_g Meta_Control_g -keycode 35 = h H 210 242 Control_h Control_h Meta_h Meta_h Meta_Control_h Meta_Control_h -keycode 36 = j J 207 239 Control_j Control_j Meta_j Meta_j Meta_Control_j Meta_Control_j -keycode 37 = k K 204 236 Control_k Control_k Meta_k Meta_k Meta_Control_k Meta_Control_k -keycode 38 = l L 196 228 Control_l Control_l Meta_l Meta_l Meta_Control_l Meta_Control_l -keycode 39 = semicolon colon 214 246 semicolon semicolon Meta_semicolon Meta_semicolon -keycode 40 = apostrophe quotedbl 220 252 Control_g Control_g Meta_apostrophe Meta_apostrophe -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 41 = grave asciitilde grave asciitilde nul nul Meta_grave Meta_grave -keycode 42 = Shift -keycode 43 = backslash bar backslash bar Control_backslash Control_backslash Meta_backslash Meta_backslash -keycode 44 = z Z 209 241 Control_z Control_z Meta_z Meta_z Meta_Control_z Meta_Control_z -keycode 45 = x X 222 254 Control_x Control_x Meta_x Meta_x Meta_Control_x Meta_Control_x -keycode 46 = c C 211 243 Control_c Control_c Meta_c Meta_c Meta_Control_c Meta_Control_c -keycode 47 = v V 205 237 Control_v Control_v Meta_v Meta_v Meta_Control_v Meta_Control_v -keycode 48 = b B 201 233 Control_b Control_b Meta_b Meta_b Meta_Control_b Meta_Control_b -keycode 49 = n N 212 244 Control_n Control_n Meta_n Meta_n Meta_Control_n Meta_Control_n -keycode 50 = m M 216 248 Control_m Control_m Meta_m Meta_m Meta_Control_m Meta_Control_m -keycode 51 = comma less 194 226 comma comma Meta_comma Meta_comma -keycode 52 = period greater 192 224 Compose Compose Meta_period Meta_period -keycode 53 = slash question slash question Delete Delete Meta_slash Meta_slash Meta_question Meta_question -# Ctrl+Shift - Cyrillic (not working???) -keycode 54 = Shift Shift Shift Shift AltGr_Lock AltGr_Lock Shift Shift Shift Shift -keycode 55 = KP_Multiply -keycode 56 = Alt -keycode 57 = space space space space nul nul Meta_space Meta_space -keycode 58 = Caps_Lock -keycode 59 = F1 F11 F1 F11 F1 F1 Console_1 Console_1 Console_1 Console_1 -keycode 60 = F2 F12 F2 F12 F2 F2 Console_2 Console_2 Console_2 Console_2 -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 61 = F3 F13 F3 F13 F3 F3 Console_3 Console_3 Console_3 Console_3 -keycode 62 = F4 F14 F4 F14 F4 F4 Console_4 Console_4 Console_4 Console_4 -keycode 63 = F5 F15 F5 F15 F5 F5 Console_5 Console_5 Console_5 Console_5 -keycode 64 = F6 F16 F6 F16 F6 F6 Console_6 Console_6 Console_6 Console_6 -keycode 65 = F7 F17 F7 F17 F7 F7 Console_7 Console_7 Console_7 Console_7 -keycode 66 = F8 F18 F8 F18 F8 F8 Console_8 Console_8 Console_8 Console_8 -keycode 67 = F9 F19 F9 F19 F9 F9 Console_9 Console_9 Console_9 Console_9 -keycode 68 = F10 F20 F10 F20 F10 F10 Console_10 Console_10 Console_10 Console_10 -keycode 69 = Num_Lock Bare_Num_Lock Num_Lock Bare_Num_Lock -keycode 70 = Scroll_Lock Show_Memory Scroll_Lock Show_Memory Show_State Show_State -keycode 71 = KP_7 KP_7 KP_7 KP_7 KP_7 KP_7 Ascii_7 Ascii_7 -keycode 72 = KP_8 KP_8 KP_8 KP_8 KP_8 KP_8 Ascii_8 Ascii_8 -keycode 73 = KP_9 KP_9 KP_9 KP_9 KP_9 KP_9 Ascii_9 Ascii_9 -keycode 74 = KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract KP_Subtract -keycode 75 = KP_4 KP_4 KP_4 KP_4 KP_4 KP_4 Ascii_4 Ascii_4 -keycode 76 = KP_5 KP_5 KP_5 KP_5 KP_5 KP_5 Ascii_5 Ascii_5 -keycode 77 = KP_6 KP_6 KP_6 KP_6 KP_6 KP_6 Ascii_6 Ascii_6 -keycode 78 = KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add KP_Add -keycode 79 = KP_1 KP_1 KP_1 KP_1 KP_1 KP_1 Ascii_1 Ascii_1 -keycode 80 = KP_2 KP_2 KP_2 KP_2 KP_2 KP_2 Ascii_2 Ascii_2 -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 81 = KP_3 KP_3 KP_3 KP_3 KP_3 KP_3 Ascii_3 Ascii_3 -keycode 82 = KP_0 KP_0 KP_0 KP_0 KP_0 KP_0 Ascii_0 Ascii_0 -keycode 83 = KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period KP_Period Boot Boot -keycode 84 = Last_Console -keycode 85 = -keycode 86 = less greater less greater less less Meta_less Meta_less -keycode 87 = F11 F11 F11 F11 F11 F11 Console_11 Console_11 Console_11 Console_11 -keycode 88 = F12 F12 F12 F12 F12 F12 Console_12 Console_12 Console_12 Console_12 -keycode 89 = -keycode 90 = -keycode 91 = -keycode 92 = -keycode 93 = -keycode 94 = -keycode 95 = -keycode 96 = KP_Enter -keycode 97 = Control -keycode 98 = KP_Divide -keycode 99 = Control_backslash -# Right Alt - Cyrillic -keycode 100 = AltGr_Lock -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 101 = Break -keycode 102 = Find -keycode 103 = Up -keycode 104 = Prior Scroll_Backward Prior Scroll_Backward Prior Prior Prior Prior Prior Prior -keycode 105 = Left Left Left Left Left Left Left Left Decr_Console Decr_Console -keycode 106 = Right Right Right Right Right Right Right Right Incr_Console Incr_Console -keycode 107 = Select -keycode 108 = Down -keycode 109 = Next Scroll_Forward Next Scroll_Forward Next Next Next Next Next Next -keycode 110 = Insert -keycode 111 = Remove Remove Remove Remove Remove Remove Remove Remove Boot Boot -keycode 112 = Macro -keycode 113 = F13 -keycode 114 = F14 -keycode 115 = Help -keycode 116 = Do -keycode 117 = F17 -keycode 118 = KP_MinPlus -keycode 119 = Pause -keycode 120 = -#============== plain ========= shift========== plain cyr ===== shift cyr ===== ctrl ================== ctrl cyr ============== alt =================== alt cyr =============== ctrlalt =============== ctrlalt cyr =========== -keycode 121 = -keycode 122 = -keycode 123 = -keycode 124 = -keycode 125 = -keycode 126 = -keycode 127 = - -string F1 = "\033[[A" -string F2 = "\033[[B" -string F3 = "\033[[C" -string F4 = "\033[[D" -string F5 = "\033[[E" -string F6 = "\033[17~" -string F7 = "\033[18~" -string F8 = "\033[19~" -string F9 = "\033[20~" -string F10 = "\033[21~" -string F11 = "\033[23~" -string F12 = "\033[24~" -string F13 = "\033[25~" -string F14 = "\033[26~" -string F15 = "\033[28~" -string F16 = "\033[29~" -string F17 = "\033[31~" -string F18 = "\033[32~" -string F19 = "\033[33~" -string F20 = "\033[34~" -string Find = "\033[1~" -string Insert = "\033[2~" -string Remove = "\033[3~" -string Select = "\033[4~" -string Prior = "\033[5~" -string Next = "\033[6~" -string Macro = "\033[M" -string Pause = "\033[P" diff --git a/examples/var_service/getty_tty1/run b/examples/var_service/getty_tty1/run index c7c413ba4..c5b291b4d 100755 --- a/examples/var_service/getty_tty1/run +++ b/examples/var_service/getty_tty1/run @@ -1,9 +1,5 @@ #!/bin/sh -exec >/dev/null -exec 2>&1 -exec Date: Sun, 15 Apr 2018 20:37:50 +0400 Subject: ntpd: deprecate IPTOS_LOWDELAY in favor of IPTOS_DSCP_AF21 Update QoS markers. Use DSCP AF21 for interactive traffic. DSCP is defined in RFC2474. Many modern equipment no longer support IPTOS. Signed-off-by: Codarren Velvindron Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 6cd497090..a1b8ac5b0 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -93,10 +93,10 @@ #include "libbb.h" #include -#include /* For IPTOS_LOWDELAY definition */ +#include /* For IPTOS_DSCP_AF21 definition */ #include -#ifndef IPTOS_LOWDELAY -# define IPTOS_LOWDELAY 0x10 +#ifndef IPTOS_DSCP_AF21 +# define IPTOS_DSCP_AF21 0x48 #endif @@ -910,7 +910,7 @@ send_query_to_peer(peer_t *p) #if ENABLE_FEATURE_IPV6 if (family == AF_INET) #endif - setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); + setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_DSCP_AF21); free(local_lsa); } @@ -2320,7 +2320,7 @@ static NOINLINE void ntp_init(char **argv) xfunc_die(); } socket_want_pktinfo(G_listen_fd); - setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); + setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_DSCP_AF21); } #endif /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ -- cgit v1.2.3-55-g6feb From 5cb4f9081f3f6575da052b03cb227a7a488b0a8b Mon Sep 17 00:00:00 2001 From: Ivan Abrea Date: Sun, 24 Jun 2018 20:04:57 +0200 Subject: tls: fix to handle X.509 v1 certificates correctly The syntax of public key certificates can be found in RFC 5280 section 4.1. The relevant part of the syntax is the following: TBSCertificate ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, serialNumber CertificateSerialNumber, ... remaining fields omitted ... } The version field has a default value of v1. RFC 5280 section 4.1.2.1 says the following: If only basic fields are present, the version SHOULD be 1 (the value is omitted from the certificate as the default value); however, the version MAY be 2 or 3. To help detect if the version field is present or not, the type of the version field has an explicit tag of [0]. Due to this tag, if the version field is present, its encoding will have an identifier octet that is distinct from that of the serialNumber field. ITU-T X.690 specifies how a value of such a type should be encoded with DER. There is a PDF of X.690 freely available from ITU-T. X.690 section 8.1.2 specifies the format of identifier octets which is the first component of every encoded value. Identifier octets encode the tag of a type. Bits 8 and 7 encode the tag class. Bit 6 will be 0 if the encoding is primitive and 1 if the encoding is constructed. Bits 5 to 1 encode the tag number. X.690 section 8.14 specifies what the identifier octet should be for explicitly tagged types. Section 8.14.3 says if implicit tagging is not used, then the encoding shall be constructed. The version field uses explicit tagging and not implicit tagging, so its encoding will be constructed. This means bit 6 of the identifier octet should be 1. X.690 section 8.14 and Annex A provide examples. Note from their examples that the notation for tags could look like [APPLICATION 2] where both the tag class and tag number are given. For this example, the tag class is 1 (application) and the tag number is 2. For notation like [0] where the tag class is omitted and only the tag number is given, the tag class will be context-specific. Putting this all together, the identifier octet for the DER encoding of the version field should have a tag class of 2 (context-specific), bit 6 as 1 (constructed), and a tag number of 0. Signed-off-by: Ivan Abrea Signed-off-by: Denys Vlasenko --- networking/tls.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/networking/tls.c b/networking/tls.c index 99722cfb4..c8d9e9697 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1082,6 +1082,8 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey */ uint8_t *end = der + len; + uint8_t tag_class, pc, tag_number; + int version_present; /* enter "Certificate" item: [der, end) will be only Cert */ der = enter_der_item(der, &end); @@ -1089,8 +1091,24 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) /* enter "tbsCertificate" item: [der, end) will be only tbsCert */ der = enter_der_item(der, &end); + /* + * Skip version field only if it is present. For a v1 certificate, the + * version field won't be present since v1 is the default value for the + * version field and fields with default values should be omitted (see + * RFC 5280 sections 4.1 and 4.1.2.1). If the version field is present + * it will have a tag class of 2 (context-specific), bit 6 as 1 + * (constructed), and a tag number of 0 (see ITU-T X.690 sections 8.1.2 + * and 8.14). + */ + tag_class = der[0] >> 6; /* bits 8-7 */ + pc = (der[0] & 32) >> 5; /* bit 6 */ + tag_number = der[0] & 31; /* bits 5-1 */ + version_present = tag_class == 2 && pc == 1 && tag_number == 0; + if (version_present) { + der = skip_der_item(der, end); /* version */ + } + /* skip up to subjectPublicKeyInfo */ - der = skip_der_item(der, end); /* version */ der = skip_der_item(der, end); /* serialNumber */ der = skip_der_item(der, end); /* signatureAlgo */ der = skip_der_item(der, end); /* issuer */ -- cgit v1.2.3-55-g6feb From 817a20296fd9e4e8eed095836d7dc28183794247 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 15:35:17 +0200 Subject: randomconfig fixes Signed-off-by: Denys Vlasenko --- include/bb_archive.h | 4 ++-- shell/hush.c | 2 ++ util-linux/mkfs_vfat.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/bb_archive.h b/include/bb_archive.h index 2ee30f794..d2022336b 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -116,10 +116,10 @@ typedef struct archive_handle_t { #if ENABLE_FEATURE_AR_CREATE const char *ar__name; struct archive_handle_t *ar__out; -# if ENABLE_FEATURE_AR_LONG_FILENAMES +#endif +#if ENABLE_FEATURE_AR_LONG_FILENAMES char *ar__long_names; unsigned ar__long_name_size; -# endif #endif } archive_handle_t; /* bits in ah_flags */ diff --git a/shell/hush.c b/shell/hush.c index c77700175..0b36dad80 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4577,7 +4577,9 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign # endif end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); +#if ENABLE_HUSH_INTERACTIVE G.promptmode = 1; /* PS2 */ +#endif debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); while (1) { diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index 26a919536..92f0e3b1a 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c @@ -522,7 +522,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) //STORE_LE(boot_blk->reserved2[3], 0,0,0); STORE_LE(boot_blk->vi.ext_boot_sign, 0x29); STORE_LE(boot_blk->vi.volume_id32, volume_id); - strncpy(boot_blk->vi.fs_type, "FAT32 ", sizeof(boot_blk->vi.fs_type)); + memcpy(boot_blk->vi.fs_type, "FAT32 ", sizeof(boot_blk->vi.fs_type)); strncpy(boot_blk->vi.volume_label, volume_label, sizeof(boot_blk->vi.volume_label)); memcpy(boot_blk->boot_code, boot_code, sizeof(boot_code)); STORE_LE(boot_blk->boot_sign, BOOT_SIGN); -- cgit v1.2.3-55-g6feb From 99496dc7160552824d6146ec951b2f7b03a51759 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 15:36:58 +0200 Subject: hush: variable nesting code is used also if HUSH_FUNCTIONS is not enabled Signed-off-by: Denys Vlasenko --- shell/hush.c | 104 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 0b36dad80..738a6b286 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7314,6 +7314,58 @@ static const struct built_in_command *find_builtin(const char *name) return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]); } +static void remove_nested_vars(void) +{ + struct variable *cur; + struct variable **cur_pp; + + cur_pp = &G.top_var; + while ((cur = *cur_pp) != NULL) { + if (cur->var_nest_level <= G.var_nest_level) { + cur_pp = &cur->next; + continue; + } + /* Unexport */ + if (cur->flg_export) { + debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level); + bb_unsetenv(cur->varstr); + } + /* Remove from global list */ + *cur_pp = cur->next; + /* Free */ + if (!cur->max_len) { + debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); + free(cur->varstr); + } + free(cur); + } +} + +static void enter_var_nest_level(void) +{ + G.var_nest_level++; + debug_printf_env("var_nest_level++ %u\n", G.var_nest_level); + + /* Try: f() { echo -n .; f; }; f + * struct variable::var_nest_level is uint16_t, + * thus limiting recursion to < 2^16. + * In any case, with 8 Mbyte stack SEGV happens + * not too long after 2^16 recursions anyway. + */ + if (G.var_nest_level > 0xff00) + bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level); +} + +static void leave_var_nest_level(void) +{ + G.var_nest_level--; + debug_printf_env("var_nest_level-- %u\n", G.var_nest_level); + if (HUSH_DEBUG && (int)G.var_nest_level < 0) + bb_error_msg_and_die("BUG: nesting underflow"); + + remove_nested_vars(); +} + #if ENABLE_HUSH_FUNCTIONS static struct function **find_function_slot(const char *name) { @@ -7400,58 +7452,6 @@ static void unset_func(const char *name) } # endif -static void remove_nested_vars(void) -{ - struct variable *cur; - struct variable **cur_pp; - - cur_pp = &G.top_var; - while ((cur = *cur_pp) != NULL) { - if (cur->var_nest_level <= G.var_nest_level) { - cur_pp = &cur->next; - continue; - } - /* Unexport */ - if (cur->flg_export) { - debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level); - bb_unsetenv(cur->varstr); - } - /* Remove from global list */ - *cur_pp = cur->next; - /* Free */ - if (!cur->max_len) { - debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level); - free(cur->varstr); - } - free(cur); - } -} - -static void enter_var_nest_level(void) -{ - G.var_nest_level++; - debug_printf_env("var_nest_level++ %u\n", G.var_nest_level); - - /* Try: f() { echo -n .; f; }; f - * struct variable::var_nest_level is uint16_t, - * thus limiting recursion to < 2^16. - * In any case, with 8 Mbyte stack SEGV happens - * not too long after 2^16 recursions anyway. - */ - if (G.var_nest_level > 0xff00) - bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level); -} - -static void leave_var_nest_level(void) -{ - G.var_nest_level--; - debug_printf_env("var_nest_level-- %u\n", G.var_nest_level); - if (HUSH_DEBUG && (int)G.var_nest_level < 0) - bb_error_msg_and_die("BUG: nesting underflow"); - - remove_nested_vars(); -} - # if BB_MMU #define exec_function(to_free, funcp, argv) \ exec_function(funcp, argv) -- cgit v1.2.3-55-g6feb From c96bb2c5ab2772d649c67a716615a72f4aca9cd3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 15:43:56 +0200 Subject: hush: fix for !ENABLE_HUSH_MODE_X configuration Signed-off-by: Denys Vlasenko --- shell/hush.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 738a6b286..8d4478ae5 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -8255,8 +8255,8 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe) * subshell: ( list ) [&] */ #if !ENABLE_HUSH_MODE_X -#define redirect_and_varexp_helper(old_vars_p, command, squirrel, argv_expanded) \ - redirect_and_varexp_helper(old_vars_p, command, squirrel) +#define redirect_and_varexp_helper(command, squirrel, argv_expanded) \ + redirect_and_varexp_helper(command, squirrel) #endif static int redirect_and_varexp_helper( struct command *command, -- cgit v1.2.3-55-g6feb From 8ef9effaa558fbbf7e0f3b91a3faa4074686e671 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 15:44:58 +0200 Subject: fdisk: placate warning of strncpy not copying NUL byte Signed-off-by: Denys Vlasenko --- util-linux/fdisk_sgi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c index 30def09c6..1cf0af5cc 100644 --- a/util-linux/fdisk_sgi.c +++ b/util-linux/fdisk_sgi.c @@ -425,7 +425,7 @@ create_sgiinfo(void) /* I keep SGI's habit to write the sgilabel to the second block */ sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2); sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo)); - strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8); + memcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8); } static sgiinfo *fill_sgiinfo(void); -- cgit v1.2.3-55-g6feb From d1a83234c05e0a977e33d409d3a8cd0441e9e5a1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 15:50:33 +0200 Subject: hush: fix dup_CLOEXEC() call without "avoid_fd" parameter Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index 8d4478ae5..5d907e200 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9668,7 +9668,7 @@ int hush_main(int argc, char **argv) G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254); if (G_interactive_fd < 0) { /* try to dup to any fd */ - G_interactive_fd = dup_CLOEXEC(STDIN_FILENO); + G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1); if (G_interactive_fd < 0) /* give up */ G_interactive_fd = 0; -- cgit v1.2.3-55-g6feb From 5f5119be971825e359f8dd3456f99f07546eca7f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 16:01:05 +0200 Subject: scripts/randomtest: disable CONFIG_FEATURE_MOUNT_NFS for glibc Signed-off-by: Denys Vlasenko --- scripts/randomtest | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/randomtest b/scripts/randomtest index 635978338..19f663479 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -57,6 +57,7 @@ if test x"$LIBC" = x"glibc"; then | grep -v CONFIG_FEATURE_2_4_MODULES \ | grep -v CONFIG_FEATURE_USE_BSS_TAIL \ | grep -v CONFIG_DEBUG_SANITIZE \ + | grep -v CONFIG_FEATURE_MOUNT_NFS \ >.config.new mv .config.new .config echo '# CONFIG_STATIC is not set' >>.config @@ -66,6 +67,8 @@ if test x"$LIBC" = x"glibc"; then echo '# CONFIG_FEATURE_2_4_MODULES is not set' >>.config echo '# CONFIG_FEATURE_USE_BSS_TAIL is not set' >>.config echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config + # 2018: current glibc versions no longer include rpc/rpc.h + echo '# CONFIG_FEATURE_MOUNT_NFS is not set' >>.config fi # If uclibc, build static, and remove some things -- cgit v1.2.3-55-g6feb From 185326613d2a7535aac4ea112f060d86096ac0ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 16:08:22 +0200 Subject: scripts/randomtest: disable CONFIG_FEATURE_INETD_RPC for glibc Signed-off-by: Denys Vlasenko --- scripts/randomtest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/randomtest b/scripts/randomtest index 19f663479..3434531b1 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -58,6 +58,7 @@ if test x"$LIBC" = x"glibc"; then | grep -v CONFIG_FEATURE_USE_BSS_TAIL \ | grep -v CONFIG_DEBUG_SANITIZE \ | grep -v CONFIG_FEATURE_MOUNT_NFS \ + | grep -v CONFIG_FEATURE_INETD_RPC \ >.config.new mv .config.new .config echo '# CONFIG_STATIC is not set' >>.config @@ -69,6 +70,7 @@ if test x"$LIBC" = x"glibc"; then echo '# CONFIG_DEBUG_SANITIZE is not set' >>.config # 2018: current glibc versions no longer include rpc/rpc.h echo '# CONFIG_FEATURE_MOUNT_NFS is not set' >>.config + echo '# CONFIG_FEATURE_INETD_RPC is not set' >>.config fi # If uclibc, build static, and remove some things -- cgit v1.2.3-55-g6feb From 762440b20e3b75ab30ddca55cfdc657397bb38dc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 17:22:35 +0200 Subject: scripts/randomtest: disable CONFIG_NSLOOKUP for uclibc Signed-off-by: Denys Vlasenko --- scripts/randomtest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/randomtest b/scripts/randomtest index 3434531b1..94709a99f 100755 --- a/scripts/randomtest +++ b/scripts/randomtest @@ -91,6 +91,7 @@ if test x"$LIBC" = x"uclibc"; then | grep -v CONFIG_UNSHARE \ | grep -v CONFIG_FALLOCATE \ | grep -v CONFIG_UDHCPC6 \ + | grep -v CONFIG_NSLOOKUP \ | grep -v CONFIG_ASH_INTERNAL_GLOB \ >.config.new mv .config.new .config @@ -108,6 +109,7 @@ if test x"$LIBC" = x"uclibc"; then echo '# CONFIG_UNSHARE is not set' >>.config echo '# CONFIG_FALLOCATE is not set' >>.config echo '# CONFIG_UDHCPC6 is not set' >>.config + echo '# CONFIG_NSLOOKUP is not set' >>.config echo 'CONFIG_ASH_INTERNAL_GLOB=y' >>.config fi -- cgit v1.2.3-55-g6feb From b2b14cbd4c20d4dda1599fc95680b0583533ab48 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 18:09:22 +0200 Subject: hush: fix compile problem found by randomconfig Signed-off-by: Denys Vlasenko --- shell/hush.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index 5d907e200..c3cb9382a 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2373,7 +2373,8 @@ static int unset_local_var(const char *name) } #endif -#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ || ENABLE_HUSH_GETOPTS +#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ || ENABLE_HUSH_GETOPTS \ + || (ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT) static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) { char *var = xasprintf("%s=%s", name, val); -- cgit v1.2.3-55-g6feb From 35a017c0c52bc6de761b30bc0468a6fec380ab27 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 26 Jun 2018 18:27:54 +0200 Subject: hush: unset_local_var_len is only used by unset_local_var Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index c3cb9382a..1f83267be 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2333,6 +2333,7 @@ static void set_pwd_var(unsigned flag) set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag); } +#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS static int unset_local_var_len(const char *name, int name_len) { struct variable *cur; @@ -2366,7 +2367,6 @@ static int unset_local_var_len(const char *name, int name_len) return EXIT_SUCCESS; } -#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS static int unset_local_var(const char *name) { return unset_local_var_len(name, strlen(name)); -- cgit v1.2.3-55-g6feb From 57dbe4d5ac483f928b6e80b33993c8fd6a061aa7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 09:43:38 +0200 Subject: libbb: crypt() in newer glibc requires include Signed-off-by: Denys Vlasenko --- libbb/pw_encrypt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 1edf4b6f0..86455cd0d 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c @@ -6,6 +6,7 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +#include #include "libbb.h" /* static const uint8_t ascii64[] ALIGN1 = -- cgit v1.2.3-55-g6feb From 751005020d83e3626604d93c93c0e0ea6e0ef8e5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 09:57:30 +0200 Subject: testsuite/cat.tests: fix false positive Signed-off-by: Denys Vlasenko --- testsuite/cat.tests | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testsuite/cat.tests b/testsuite/cat.tests index 404ebedeb..10970dc90 100755 --- a/testsuite/cat.tests +++ b/testsuite/cat.tests @@ -6,16 +6,20 @@ . ./testing.sh # testing "description" "command" "result" "infile" "stdin" +optional FEATURE_CATV testing 'cat -e' \ 'cat -e' \ 'foo$\n' \ '' \ 'foo\n' +SKIP= +optional FEATURE_CATV testing 'cat -v' \ 'cat -v' \ 'foo\n' \ '' \ 'foo\n' +SKIP= exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 5738823dff9f7a6906c59516d60f8a0fc83a3ad9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 10:01:49 +0200 Subject: testsuite/tar.tests: fix false positive Signed-off-by: Denys Vlasenko --- testsuite/tar.tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tar.tests b/testsuite/tar.tests index 6c479d3fe..38f03cd72 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -336,7 +336,7 @@ SKIP= cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null mkdir tar.tempdir && cd tar.tempdir || exit 1 -optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT +optional FEATURE_SEAMLESS_BZ2 FEATURE_TAR_AUTODETECT LS testing "Symlink attack: create symlink and then write through it" '\ exec 2>&1 uudecode -o input && tar xvf input; echo $? -- cgit v1.2.3-55-g6feb From a429d5d0f3cbd50be47eea9b839a3bf87d38bf3f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 10:35:45 +0200 Subject: testsuite/bzcat.tests: fix false positive Signed-off-by: Denys Vlasenko --- testsuite/bzcat.tests | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/testsuite/bzcat.tests b/testsuite/bzcat.tests index 32c1c5d7f..8210d94d4 100755 --- a/testsuite/bzcat.tests +++ b/testsuite/bzcat.tests @@ -31,9 +31,9 @@ hello_bz2() { } for ext in \ - `test x"$CONFIG_GUNZIP" = x"y" && echo gz` \ - `test x"$CONFIG_BUNZIP2" = x"y" && echo bz2` \ - `test x"$CONFIG_UNCOMPRESS" = x"y" && echo Z` + `test x"$CONFIG_GUNZIP:$CONFIG_FEATURE_SEAMLESS_GZ" = x"y:y" && echo gz` \ + `test x"$CONFIG_BUNZIP2:$CONFIG_FEATURE_SEAMLESS_BZ2" = x"y:y" && echo bz2` \ + `test x"$CONFIG_UNCOMPRESS:$CONFIG_FEATURE_SEAMLESS_Z" = x"y:y" && echo Z` do prep() { rm -f t1.$ext t2.$ext t_actual @@ -47,6 +47,8 @@ do echo "PASS: $1" else echo "FAIL: $1" + #echo "t_actual:" + #cat t_actual FAILCOUNT=$((FAILCOUNT + 1)) fi } @@ -96,6 +98,7 @@ testing "bzcat can handle compressed zero-length bzip2 files" \ # "input" file is compressed (.Z) file with "a\n" data test x"$CONFIG_UNCOMPRESS" = x"y" && \ +test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && \ testing "zcat can print many files" \ "zcat input input; echo \$?" \ "\ @@ -108,6 +111,7 @@ a # "input" file is compressed (.Z) zero byte file test x"$CONFIG_UNCOMPRESS" = x"y" && \ +test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && \ testing "zcat can handle compressed zero-length (.Z) files" \ "zcat input input; echo \$?" \ "0\n" \ -- cgit v1.2.3-55-g6feb From d8799b90f314469c10ada3008856cfdeb98b92f9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 12:54:57 +0200 Subject: testsuite/unexpand/unexpand-works-like-GNU: fix false positive Signed-off-by: Denys Vlasenko --- testsuite/unexpand/unexpand-works-like-GNU | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testsuite/unexpand/unexpand-works-like-GNU b/testsuite/unexpand/unexpand-works-like-GNU index a5258363f..111b277b5 100644 --- a/testsuite/unexpand/unexpand-works-like-GNU +++ b/testsuite/unexpand/unexpand-works-like-GNU @@ -1,3 +1,7 @@ +# coreutils 8.25 often says "input line is too long" +# on ELF executables. In this case, do not run the test: +unexpand ../../busybox >/dev/null || exit 0 + rm -f foo bar echo " y" | unexpand ../../busybox > foo echo " y" | busybox unexpand ../../busybox > bar -- cgit v1.2.3-55-g6feb From 94593799f7deab90dae163f323f76ca1a987ab03 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 13:15:10 +0200 Subject: testsuite/bzcat.tests: fix false positive take 2 Signed-off-by: Denys Vlasenko --- testsuite/bzcat.tests | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/testsuite/bzcat.tests b/testsuite/bzcat.tests index 8210d94d4..ad05dcb2c 100755 --- a/testsuite/bzcat.tests +++ b/testsuite/bzcat.tests @@ -30,10 +30,11 @@ hello_bz2() { $ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3" } +test x"$CONFIG_ZCAT" = x"y" && \ for ext in \ - `test x"$CONFIG_GUNZIP:$CONFIG_FEATURE_SEAMLESS_GZ" = x"y:y" && echo gz` \ - `test x"$CONFIG_BUNZIP2:$CONFIG_FEATURE_SEAMLESS_BZ2" = x"y:y" && echo bz2` \ - `test x"$CONFIG_UNCOMPRESS:$CONFIG_FEATURE_SEAMLESS_Z" = x"y:y" && echo Z` + `test x"$CONFIG_FEATURE_SEAMLESS_GZ" = x"y" && echo gz` \ + `test x"$CONFIG_FEATURE_SEAMLESS_BZ2" = x"y" && echo bz2` \ + `test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && echo Z` do prep() { rm -f t1.$ext t2.$ext t_actual @@ -97,7 +98,7 @@ testing "bzcat can handle compressed zero-length bzip2 files" \ ## compress algorithm # "input" file is compressed (.Z) file with "a\n" data -test x"$CONFIG_UNCOMPRESS" = x"y" && \ +test x"$CONFIG_ZCAT" = x"y" && \ test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && \ testing "zcat can print many files" \ "zcat input input; echo \$?" \ @@ -110,7 +111,7 @@ a " "" # "input" file is compressed (.Z) zero byte file -test x"$CONFIG_UNCOMPRESS" = x"y" && \ +test x"$CONFIG_ZCAT" = x"y" && \ test x"$CONFIG_FEATURE_SEAMLESS_Z" = x"y" && \ testing "zcat can handle compressed zero-length (.Z) files" \ "zcat input input; echo \$?" \ -- cgit v1.2.3-55-g6feb From 33eae2871072dc078585d7d9b03b1600b5457a5f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 14:26:21 +0200 Subject: testsuite/pidof.tests: fix false positive Signed-off-by: Denys Vlasenko --- testsuite/pidof.tests | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/pidof.tests b/testsuite/pidof.tests index 2a06d2b1c..b360a127b 100755 --- a/testsuite/pidof.tests +++ b/testsuite/pidof.tests @@ -18,9 +18,11 @@ testing "pidof (exit with success)" "pidof pidof > /dev/null; echo \$?" \ testing "pidof this" "pidof pidof.tests | grep -o -w $$" "$$\n" "" "" +test x"`cat /proc/1/comm`" = x"init" && { optional FEATURE_PIDOF_SINGLE testing "pidof -s" "pidof -s init" "1\n" "" "" SKIP= +} optional FEATURE_PIDOF_OMIT FEATURE_PIDOF_SINGLE # This test fails now because process name matching logic has changed, -- cgit v1.2.3-55-g6feb From 332a191e7fc0fd17a99d168077228fdc15549f2b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 14:35:56 +0200 Subject: testsuite/tar.tests: fix false positive Signed-off-by: Denys Vlasenko --- testsuite/tar.tests | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tar.tests b/testsuite/tar.tests index 38f03cd72..d71a34910 100755 --- a/testsuite/tar.tests +++ b/testsuite/tar.tests @@ -366,6 +366,7 @@ SKIP= cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null mkdir tar.tempdir && cd tar.tempdir || exit 1 +optional FEATURE_TAR_CREATE testing "Symlinks and hardlinks coexist" '\ mkdir dir >dir/a @@ -379,6 +380,7 @@ dir/b dir/c " \ "" "" +SKIP= cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 2f7738e4748594227c95bef86acf73436c334e2d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 14:44:35 +0200 Subject: nslookup: placate "warning: unused variable i" Signed-off-by: Denys Vlasenko --- networking/nslookup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/nslookup.c b/networking/nslookup.c index fd241a5ca..3a614b0c6 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -712,11 +712,11 @@ static void add_query(int type, const char *dname) static char *make_ptr(const char *addrstr) { unsigned char addr[16]; - int i; #if ENABLE_FEATURE_IPV6 if (inet_pton(AF_INET6, addrstr, addr)) { if (memcmp(addr, v4_mapped, 12) != 0) { + int i; char resbuf[80]; char *ptr = resbuf; for (i = 0; i < 16; i++) { -- cgit v1.2.3-55-g6feb From 39043ad25eda79e315da5148e239730ee1d8d6ca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 14:46:08 +0200 Subject: vi: placate "warning: statement with no effect" Signed-off-by: Denys Vlasenko --- editors/vi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/editors/vi.c b/editors/vi.c index cdfb27cc5..61e988ce9 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -750,7 +750,10 @@ static int query_screen_dimensions(void) return err; } #else -# define query_screen_dimensions() (0) +static ALWAYS_INLINE int query_screen_dimensions(void) +{ + return 0; +} #endif static void edit_file(char *fn) -- cgit v1.2.3-55-g6feb From 4c58f246d400d59d21eb98e8d6b334e0447ebaaa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 14:50:00 +0200 Subject: testsuite/pidof.tests: fix false positive take 2 Signed-off-by: Denys Vlasenko --- testsuite/pidof.tests | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testsuite/pidof.tests b/testsuite/pidof.tests index b360a127b..cd10de4e0 100755 --- a/testsuite/pidof.tests +++ b/testsuite/pidof.tests @@ -24,11 +24,16 @@ testing "pidof -s" "pidof -s init" "1\n" "" "" SKIP= } +test x"`cat /proc/1/comm`" = x"init" && { optional FEATURE_PIDOF_OMIT FEATURE_PIDOF_SINGLE # This test fails now because process name matching logic has changed, # but new logic is not "wrong" either... see find_pid_by_name.c comments #testing "pidof -o %PPID" "pidof -o %PPID pidof.tests | grep -o -w $$" "" "" "" testing "pidof -o %PPID NOP" "pidof -o %PPID -s init" "1\n" "" "" +SKIP= +} + +optional FEATURE_PIDOF_OMIT testing "pidof -o init" "pidof -o 1 init | grep -o -w 1" "" "" "" SKIP= -- cgit v1.2.3-55-g6feb From 8825cb6660b66c412296c2b1e10ca2f965a0a9cd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jun 2018 15:11:36 +0200 Subject: vi: placate "warning: variable orig_buf set but not used" Signed-off-by: Denys Vlasenko --- editors/vi.c | 56 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 61e988ce9..f103e0dc0 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -1070,10 +1070,13 @@ static void colon(char *buf) not_implemented(p); #else - char c, *orig_buf, *buf1, *q, *r; + char c, *buf1, *q, *r; char *fn, cmd[MAX_INPUT_LEN], args[MAX_INPUT_LEN]; int i, l, li, b, e; int useforce; +# if ENABLE_FEATURE_VI_SEARCH || ENABLE_FEATURE_ALLOW_EXEC + char *orig_buf; +# endif // :3154 // if (-e line 3154) goto it else stay put // :4,33w! foo // write a portion of buffer to file "foo" @@ -1105,8 +1108,10 @@ static void colon(char *buf) // look for optional address(es) :. :1 :1,9 :'q,'a :% buf = get_address(buf, &b, &e); +# if ENABLE_FEATURE_VI_SEARCH || ENABLE_FEATURE_ALLOW_EXEC // remember orig command line orig_buf = buf; +# endif // get the COMMAND into cmd[] buf1 = cmd; @@ -1150,7 +1155,7 @@ static void colon(char *buf) dot_skip_over_ws(); } } -#if ENABLE_FEATURE_ALLOW_EXEC +# if ENABLE_FEATURE_ALLOW_EXEC else if (cmd[0] == '!') { // run a cmd int retcode; // :!ls run the @@ -1162,7 +1167,7 @@ static void colon(char *buf) rawmode(); Hit_Return(); // let user see results } -#endif +# endif else if (cmd[0] == '=' && !cmd[1]) { // where is the address if (b < 0) { // no addr given- use defaults b = e = count_lines(text, dot); @@ -1197,7 +1202,7 @@ static void colon(char *buf) size = init_text_buffer(fn); -#if ENABLE_FEATURE_VI_YANKMARK +# if ENABLE_FEATURE_VI_YANKMARK if (Ureg >= 0 && Ureg < 28) { free(reg[Ureg]); // free orig line reg- for 'U' reg[Ureg] = NULL; @@ -1206,7 +1211,7 @@ static void colon(char *buf) free(reg[YDreg]); // free default yank/delete register reg[YDreg] = NULL; } -#endif +# endif // how many lines in text[]? li = count_lines(text, end - 1); status_line("'%s'%s" @@ -1353,16 +1358,16 @@ static void colon(char *buf) optind = -1; /* start from 0th file */ editing = 0; } -#if ENABLE_FEATURE_VI_SET +# if ENABLE_FEATURE_VI_SET } else if (strncmp(cmd, "set", i) == 0) { // set or clear features -#if ENABLE_FEATURE_VI_SETOPTS +# if ENABLE_FEATURE_VI_SETOPTS char *argp; -#endif +# endif i = 0; // offset into args // only blank is regarded as args delimiter. What about tab '\t'? if (!args[0] || strcasecmp(args, "all") == 0) { // print out values of all options -#if ENABLE_FEATURE_VI_SETOPTS +# if ENABLE_FEATURE_VI_SETOPTS status_line_bold( "%sautoindent " "%sflash " @@ -1375,10 +1380,10 @@ static void colon(char *buf) showmatch ? "" : "no", tabstop ); -#endif +# endif goto ret; } -#if ENABLE_FEATURE_VI_SETOPTS +# if ENABLE_FEATURE_VI_SETOPTS argp = args; while (*argp) { if (strncmp(argp, "no", 2) == 0) @@ -1396,16 +1401,17 @@ static void colon(char *buf) argp = skip_non_whitespace(argp); argp = skip_whitespace(argp); } -#endif /* FEATURE_VI_SETOPTS */ -#endif /* FEATURE_VI_SET */ -#if ENABLE_FEATURE_VI_SEARCH +# endif /* FEATURE_VI_SETOPTS */ +# endif /* FEATURE_VI_SET */ + +# if ENABLE_FEATURE_VI_SEARCH } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern char *F, *R, *flags; size_t len_F, len_R; int gflag; // global replace flag -#if ENABLE_FEATURE_VI_UNDO +# if ENABLE_FEATURE_VI_UNDO int dont_chain_first_item = ALLOW_UNDO; -#endif +# endif // F points to the "find" pattern // R points to the "replace" pattern @@ -1442,9 +1448,9 @@ static void colon(char *buf) // we found the "find" pattern - delete it // For undo support, the first item should not be chained text_hole_delete(found, found + len_F - 1, dont_chain_first_item); -#if ENABLE_FEATURE_VI_UNDO +# if ENABLE_FEATURE_VI_UNDO dont_chain_first_item = ALLOW_UNDO_CHAIN; -#endif +# endif // insert the "replace" patern bias = string_insert(found, R, ALLOW_UNDO_CHAIN); found += bias; @@ -1460,7 +1466,7 @@ static void colon(char *buf) } q = next_line(ls); } -#endif /* FEATURE_VI_SEARCH */ +# endif /* FEATURE_VI_SEARCH */ } else if (strncmp(cmd, "version", i) == 0) { // show software version status_line(BB_VER); } else if (strncmp(cmd, "write", i) == 0 // write text to file @@ -1475,12 +1481,12 @@ static void colon(char *buf) if (args[0]) { fn = args; } -#if ENABLE_FEATURE_VI_READONLY +# if ENABLE_FEATURE_VI_READONLY if (readonly_mode && !useforce) { status_line_bold("'%s' is read only", fn); goto ret; } -#endif +# endif //if (useforce) { // if "fn" is not write-able, chmod u+w // sprintf(syscmd, "chmod u+w %s", fn); @@ -1520,7 +1526,7 @@ static void colon(char *buf) } } } -#if ENABLE_FEATURE_VI_YANKMARK +# if ENABLE_FEATURE_VI_YANKMARK } else if (strncmp(cmd, "yank", i) == 0) { // yank lines if (b < 0) { // no addr given- use defaults q = begin_line(dot); // assume .,. for the range @@ -1530,7 +1536,7 @@ static void colon(char *buf) li = count_lines(q, r); status_line("Yank %d lines (%d chars) into [%c]", li, strlen(reg[YDreg]), what_reg()); -#endif +# endif } else { // cmd unknown not_implemented(cmd); @@ -1538,10 +1544,10 @@ static void colon(char *buf) ret: dot = bound_dot(dot); // make sure "dot" is valid return; -#if ENABLE_FEATURE_VI_SEARCH +# if ENABLE_FEATURE_VI_SEARCH colon_s_fail: status_line(":s expression missing delimiters"); -#endif +# endif #endif /* FEATURE_VI_COLON */ } -- cgit v1.2.3-55-g6feb From 335766602b2598f29a3dd854654b9ba9edb6d7cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 28 Jun 2018 14:10:00 +0200 Subject: testsuite/mount.tests: fix false positive Signed-off-by: Denys Vlasenko --- libbb/loop.c | 4 ++++ testsuite/mount.tests | 2 ++ 2 files changed, 6 insertions(+) diff --git a/libbb/loop.c b/libbb/loop.c index f0d4296ae..c78535a20 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -106,6 +106,10 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse return -errno; } +//TODO: use LOOP_CTL_GET_FREE instead of trying every loopN in sequence? a-la: +// fd = open("/dev/loop-control", O_RDWR); +// loopN = ioctl(fd, LOOP_CTL_GET_FREE); +// /* Find a loop device. */ try = *device ? *device : dev; /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ diff --git a/testsuite/mount.tests b/testsuite/mount.tests index a0bc50888..91c2e8b42 100755 --- a/testsuite/mount.tests +++ b/testsuite/mount.tests @@ -10,9 +10,11 @@ test "`id -u`" = 0 || { exit 0 } +# Without MOUNT_LOOP_CREATE, the test will fail if /dev/loopN's do not exist if test x"$CONFIG_MKFS_MINIX" != x"y" \ || test x"$CONFIG_FEATURE_MINIX2" != x"y" \ || test x"$CONFIG_FEATURE_MOUNT_LOOP" != x"y" \ +|| test x"$CONFIG_FEATURE_MOUNT_LOOP_CREATE" != x"y" \ || test x"$CONFIG_FEATURE_MOUNT_FLAGS" != x"y" \ || test x"$CONFIG_FEATURE_DEVFS" = x"y" \ ; then -- cgit v1.2.3-55-g6feb From 10a38174403c44760c1941424f4e540075e59696 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 1 Jul 2018 16:38:52 +0200 Subject: Bump version to 1.29.0 Signed-off-by: Denys Vlasenko --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9d7a0a36c..c38618bed 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 PATCHLEVEL = 29 SUBLEVEL = 0 -EXTRAVERSION = .git +EXTRAVERSION = NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From 0dbcb46af50ab273e03f3a6e4ae93912aa1f2f35 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 1 Jul 2018 17:18:47 +0200 Subject: Start 1.30.0 development cycle Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c38618bed..59ec83a6a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 -PATCHLEVEL = 29 +PATCHLEVEL = 30 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = .git NAME = Unnamed # *DOCUMENTATION* -- cgit v1.2.3-55-g6feb From 029bd187bdad5bfd7771ed356e633e8ec8044d2e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Jul 2018 16:17:07 +0200 Subject: ntpd: increase minimum G.FREQHOLD_cnt from 8 to 10 With ~0.9 initiall offsets, using 8 results in a bit too eager frequency correction. Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index a1b8ac5b0..7b800369e 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -149,6 +149,7 @@ */ #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ +#define MIN_FREQHOLD 10 /* adjust offset, but not freq in this many first adjustments */ #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ #define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ @@ -1753,7 +1754,7 @@ update_local_clock(peer_t *p) //15:19:39.114 update from: offset:+0.327022 delay:0.158384 jitter:0.108538 clock drift:-1.393ppm tc:4 //15:20:12.715 update from: offset:+0.275596 delay:0.158297 jitter:0.097292 clock drift:-1.393ppm tc:4 //15:20:45.111 update from: offset:+0.225715 delay:0.158271 jitter:0.087841 clock drift:-1.393ppm tc:4 -// If allwed to continue, it would start increasing tmx.freq now. +// If allowed to continue, it would start increasing tmx.freq now. // Instead, it was ^Ced, and started anew: //15:21:15.043 no valid datapoints, no peer selected //15:21:17.408 update from: offset:+0.175910 delay:0.158314 jitter:0.076683 clock drift:-1.393ppm tc:4 @@ -1776,9 +1777,9 @@ update_local_clock(peer_t *p) //15:31:53.473 update from: offset:+0.000007 delay:0.158142 jitter:0.010922 clock drift:+9.343ppm tc:6 //15:32:58.902 update from: offset:-0.000728 delay:0.158222 jitter:0.009454 clock drift:+9.298ppm tc:6 /* - * This expression would choose 15 in the above example. + * This expression would choose MIN_FREQHOLD + 7 in the above example. */ - G.FREQHOLD_cnt = 8 + ((unsigned)(abs(tmx.offset)) >> 16); + G.FREQHOLD_cnt = MIN_FREQHOLD + ((unsigned)(abs(tmx.offset)) >> 16); } G.FREQHOLD_cnt--; tmx.status |= STA_FREQHOLD; -- cgit v1.2.3-55-g6feb From 9634e8a7d545283c662992d4d3e4a1bcd557c055 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Jul 2018 18:31:02 +0200 Subject: wget: fix fetching of https URLs without http proxy The "fix fetching of https URLs with http proxy" commit broke the usual http-to-https redirect: $ wget http://busybox.net/downloads/busybox-1.29.0.tar.bz2 Connecting to busybox.net (140.211.167.122:80) Connecting to busybox.net (140.211.167.122:443) wget: server returned error: HTTP/1.1 400 Bad Request Fixing... Signed-off-by: Denys Vlasenko --- networking/wget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/networking/wget.c b/networking/wget.c index 8103aacee..33c93bad3 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -1335,6 +1335,7 @@ However, in real world it was observed that some web servers /* server.user remains untouched */ free(server.allocated); server.allocated = NULL; + server.protocol = target.protocol; server.host = target.host; /* strip_ipv6_scope_id(target.host); - no! */ /* we assume remote never gives us IPv6 addr with scope id */ -- cgit v1.2.3-55-g6feb From e5d5f5b9a770de5a48d1a3bd293d5d611d6624c4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Jul 2018 16:27:54 +0200 Subject: hexdump: fix short file of zero butes treated as dup function old new delta bb_dump_dump 1466 1491 +25 Signed-off-by: Denys Vlasenko --- libbb/dump.c | 14 +++++++++----- testsuite/hexdump.tests | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100755 testsuite/hexdump.tests diff --git a/libbb/dump.c b/libbb/dump.c index 5941ef902..b4b49d709 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -387,7 +387,10 @@ static unsigned char *get(priv_dumper_t *dumper) if (need == blocksize) { return NULL; } - if (dumper->pub.dump_vflag != ALL && !memcmp(dumper->get__curp, dumper->get__savp, nread)) { + if (dumper->pub.dump_vflag != ALL /* not "show all"? */ + && dumper->pub.dump_vflag != FIRST /* not first line? */ + && memcmp(dumper->get__curp, dumper->get__savp, nread) == 0 /* same data? */ + ) { if (dumper->pub.dump_vflag != DUP) { puts("*"); } @@ -399,7 +402,7 @@ static unsigned char *get(priv_dumper_t *dumper) } n = fread(dumper->get__curp + nread, sizeof(unsigned char), dumper->pub.dump_length == -1 ? need : MIN(dumper->pub.dump_length, need), stdin); - if (!n) { + if (n == 0) { if (ferror(stdin)) { bb_simple_perror_msg(dumper->argv[-1]); } @@ -411,9 +414,10 @@ static unsigned char *get(priv_dumper_t *dumper) dumper->pub.dump_length -= n; } need -= n; - if (!need) { - if (dumper->pub.dump_vflag == ALL || dumper->pub.dump_vflag == FIRST - || memcmp(dumper->get__curp, dumper->get__savp, blocksize) + if (need == 0) { + if (dumper->pub.dump_vflag == ALL /* "show all"? */ + || dumper->pub.dump_vflag == FIRST /* first line? */ + || memcmp(dumper->get__curp, dumper->get__savp, blocksize) != 0 /* not same data? */ ) { if (dumper->pub.dump_vflag == DUP || dumper->pub.dump_vflag == FIRST) { dumper->pub.dump_vflag = WAIT; diff --git a/testsuite/hexdump.tests b/testsuite/hexdump.tests new file mode 100755 index 000000000..45a0c1300 --- /dev/null +++ b/testsuite/hexdump.tests @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright 2018 by Denys Vlasenko +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh + +# testing "description" "command" "result" "infile" "stdin" +testing 'hexdump -C with four NULs' \ + 'hexdump -C' \ + "\ +00000000 00 00 00 00 |....| +00000004 +" \ + '' \ + '\0\0\0\0' + +exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From aa75a7da7f3b0bb50be82f535244137bae423fa8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Jul 2018 17:02:50 +0200 Subject: examples/var_service/: use "svc" for service commands, other tweaks Signed-off-by: Denys Vlasenko --- examples/var_service/dhcp_if/dhcp_handler | 10 +++++----- examples/var_service/dhcp_if/finish | 2 +- examples/var_service/dhcp_if_pinger/run | 16 +++++++-------- examples/var_service/fw/etc/dnsmasq_servers.conf | 2 +- examples/var_service/fw/run | 2 +- examples/var_service/ntpd/run | 25 ++++++++++++++---------- examples/var_service/zcip_if/finish | 4 ++-- examples/var_service/zcip_if/zcip_handler | 4 ++-- 8 files changed, 35 insertions(+), 30 deletions(-) diff --git a/examples/var_service/dhcp_if/dhcp_handler b/examples/var_service/dhcp_if/dhcp_handler index 3d44a6022..6a97e8543 100755 --- a/examples/var_service/dhcp_if/dhcp_handler +++ b/examples/var_service/dhcp_if/dhcp_handler @@ -52,7 +52,7 @@ if test x"$1" != x"bound" && test x"$1" != x"renew" ; then rm "$file_ntpconf" rm "$dir_ipconf/$file_ipconf" rm "$dir_ntpconf/$file_ntpconf" - sv u /var/service/fw + svc -u fw exit fi @@ -67,10 +67,10 @@ if test $? != 0; then echo "Reconfiguring fw" mkdir -p "$dir_ipconf" 2>/dev/null cp "$file_ipconf" "$dir_ipconf/$file_ipconf" - sv u /var/service/fw + svc -u fw fi -if test -d /var/service/ntpd; then +if test -d ../ntpd; then ./convert2ntpconf "$file_ntpconf" # Reconfigure ntp server addresses if needed diff --brief "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" >/dev/null 2>&1 @@ -78,7 +78,7 @@ if test -d /var/service/ntpd; then echo "Reconfiguring ntp" mkdir -p "$dir_ntpconf" 2>/dev/null cp "$file_ntpconf" "$dir_ntpconf/$file_ntpconf" - sv t /var/service/ntpd - sv u /var/service/ntpd + svc -t ntpd + svc -u ntpd fi fi diff --git a/examples/var_service/dhcp_if/finish b/examples/var_service/dhcp_if/finish index 5e7667a2d..8ce188336 100755 --- a/examples/var_service/dhcp_if/finish +++ b/examples/var_service/dhcp_if/finish @@ -14,4 +14,4 @@ rm "$file_ipconf" rm "$file_ntpconf" rm "$dir_ipconf/$file_ipconf" rm "$dir_ntpconf/$file_ntpconf" -sv u /var/service/fw +svc -u fw diff --git a/examples/var_service/dhcp_if_pinger/run b/examples/var_service/dhcp_if_pinger/run index 8aca90c1a..25341243f 100755 --- a/examples/var_service/dhcp_if_pinger/run +++ b/examples/var_service/dhcp_if_pinger/run @@ -21,9 +21,9 @@ if test -f "$0.log"; then mv "$0.log.new" "$0.log" fi -test -f "/var/service/dhcp_$if/env.out" || exec env - sleep "$ping_time" +test -f "../dhcp_$if/env.out" || exec env - sleep "$ping_time" -. "/var/service/dhcp_$if/env.out" +. "../dhcp_$if/env.out" test x"$router" != x"" || exec env - sleep "$ping_time" #msg "Pinging $router" @@ -36,12 +36,12 @@ while true; do env - sleep "$retry_time" done -test -d "/var/service/dhcp_$if" && { - msg "Restarting /var/service/dhcp_$if" - sv t "/var/service/dhcp_$if" +test -d "../dhcp_$if" && { + msg "Restarting dhcp_$if" + svc -t "dhcp_$if" } -test -d "/var/service/supplicant_$if" && { - msg "Restarting /var/service/supplicant_$if" - sv t "/var/service/supplicant_$if" +test -d "../supplicant_$if" && { + msg "Restarting supplicant_$if" + svc -t "supplicant_$if" } exec env - sleep "$ping_time" diff --git a/examples/var_service/fw/etc/dnsmasq_servers.conf b/examples/var_service/fw/etc/dnsmasq_servers.conf index 68313605f..c39fe6e43 100644 --- a/examples/var_service/fw/etc/dnsmasq_servers.conf +++ b/examples/var_service/fw/etc/dnsmasq_servers.conf @@ -35,4 +35,4 @@ $empty && echo "server=8.8.8.8" $empty && echo "server=8.8.4.4" # SIGHUP: make dnsmasq reload config -sv h dnsmasq +svc -h dnsmasq diff --git a/examples/var_service/fw/run b/examples/var_service/fw/run index 1fd71cc01..41078d0ab 100755 --- a/examples/var_service/fw/run +++ b/examples/var_service/fw/run @@ -8,7 +8,7 @@ extif="if" ext_open_tcp="22 80 88" # space-separated # Make ourself one-shot -sv o . +svc -o . # Debug #date '+%Y-%m-%d %H:%M:%S' >>"$0.log" diff --git a/examples/var_service/ntpd/run b/examples/var_service/ntpd/run index 6f2a68188..5c90aad41 100755 --- a/examples/var_service/ntpd/run +++ b/examples/var_service/ntpd/run @@ -6,12 +6,22 @@ exec 2>&1 exec /dev/null @@ -20,30 +30,25 @@ chmod -R a=rX "$rundir" rm -rf rundir 2>/dev/null ln -s "$rundir" rundir - -echo "* Checking network" -test -f /var/run/service/fw/up || exec sleep 7 -sleep 5 # to let it settle - # Grab config from dhcp cfg=-1 for f in rundir/*.ntpconf; do - test -f "$f" || continue - . "$f" + test -f "$f" || continue + . "$f" done # Select peers p_opt="" cfg=0 while test x"${ntpip[$cfg]}" != x""; do - p_opt="$p_opt -p ${ntpip[$cfg]}" - let cfg=cfg+1 + p_opt="$p_opt -p ${ntpip[$cfg]}" + let cfg=cfg+1 done test x"$p_opt" == x"" && p_opt="$default_p_opt" if test x"$p_opt" == x""; then echo "* No NTP peers configured, stopping" - sv o . + svc -o . exec sleep 1 fi diff --git a/examples/var_service/zcip_if/finish b/examples/var_service/zcip_if/finish index 95995cf5f..7955cf3b8 100755 --- a/examples/var_service/zcip_if/finish +++ b/examples/var_service/zcip_if/finish @@ -1,5 +1,5 @@ #!/bin/sh -# executed when service is taken down ("sv d .") +# executed when service is taken down service=${PWD##*/} file_ipconf="$service.ipconf" @@ -10,4 +10,4 @@ echo "Finish: deconfiguring" rm "env.out" rm "$file_ipconf" rm "$dir_ipconf/$file_ipconf" -sv u /var/service/fw +svc -u fw diff --git a/examples/var_service/zcip_if/zcip_handler b/examples/var_service/zcip_if/zcip_handler index 3c6ca788b..625450f7b 100755 --- a/examples/var_service/zcip_if/zcip_handler +++ b/examples/var_service/zcip_if/zcip_handler @@ -28,7 +28,7 @@ if test x"$1" != x"config"; then echo "Deconfiguring" rm "$file_ipconf" rm "$dir_ipconf/$file_ipconf" - sv u /var/service/fw + svc -u fw exit fi @@ -43,5 +43,5 @@ if test $? != 0; then echo "Reconfiguring fw" mkdir -p "$dir_ipconf" 2>/dev/null cp "$file_ipconf" "$dir_ipconf/$file_ipconf" - sv u /var/service/fw + svc -u fw fi -- cgit v1.2.3-55-g6feb From 14339191afc5d77205487e3365ca2569f86afd44 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Jul 2018 23:23:09 +0200 Subject: examples/var_service/: use standard logger script, viewer and pager scripts Signed-off-by: Denys Vlasenko --- examples/var_service/dhcp_if/README | 5 ----- examples/var_service/dhcp_if/log/run | 21 +------------------- examples/var_service/dhcp_if/p_log | 4 ---- examples/var_service/dhcp_if/w_log | 4 ---- examples/var_service/dhcp_if_pinger/README | 5 ----- examples/var_service/dhcpd_if/README | 5 ----- examples/var_service/dhcpd_if/log/run | 21 +------------------- examples/var_service/dhcpd_if/p_log | 4 ---- examples/var_service/dhcpd_if/w_log | 4 ---- examples/var_service/dnsmasq/log/run | 21 +------------------- examples/var_service/dnsmasq/p_log | 4 ---- examples/var_service/dnsmasq/w_log | 4 ---- examples/var_service/ftpd/README | 5 ----- examples/var_service/ftpd/log/run | 21 +------------------- examples/var_service/ftpd/p_log | 4 ---- examples/var_service/ftpd/w_log | 4 ---- examples/var_service/fw/README | 5 ----- examples/var_service/getty_tty1/README | 5 ----- examples/var_service/gpm/README | 5 ----- examples/var_service/httpd/README | 5 ----- examples/var_service/httpd/log/run | 21 +------------------- examples/var_service/httpd/p_log | 4 ---- examples/var_service/httpd/w_log | 4 ---- examples/var_service/ifplugd_if/README | 5 ----- examples/var_service/ifplugd_if/log/run | 21 +------------------- examples/var_service/ifplugd_if/p_log | 4 ---- examples/var_service/ifplugd_if/w_log | 4 ---- examples/var_service/inetd/README | 5 ----- examples/var_service/inetd/log/run | 21 +------------------- examples/var_service/inetd/p_log | 4 ---- examples/var_service/inetd/w_log | 4 ---- examples/var_service/nmeter/README | 5 ----- examples/var_service/ntpd/README | 5 ----- examples/var_service/ntpd/log/run | 21 +------------------- examples/var_service/ntpd/p_log | 4 ---- examples/var_service/ntpd/w_log | 4 ---- examples/var_service/std_service_logger | 32 ++++++++++++++++++++++++++++++ examples/var_service/supplicant_if/README | 5 ----- examples/var_service/supplicant_if/log/run | 21 +------------------- examples/var_service/supplicant_if/p_log | 4 ---- examples/var_service/supplicant_if/w_log | 4 ---- examples/var_service/sview | 19 ++++++++++++++++++ examples/var_service/svpage | 19 ++++++++++++++++++ examples/var_service/tftpd/README | 5 ----- examples/var_service/tftpd/log/run | 21 +------------------- examples/var_service/tftpd/p_log | 4 ---- examples/var_service/tftpd/w_log | 4 ---- examples/var_service/zcip_if/README | 5 ----- examples/var_service/zcip_if/log/run | 21 +------------------- examples/var_service/zcip_if/p_log | 4 ---- examples/var_service/zcip_if/w_log | 4 ---- 51 files changed, 81 insertions(+), 383 deletions(-) delete mode 100644 examples/var_service/dhcp_if/README delete mode 100755 examples/var_service/dhcp_if/p_log delete mode 100755 examples/var_service/dhcp_if/w_log delete mode 100644 examples/var_service/dhcp_if_pinger/README delete mode 100644 examples/var_service/dhcpd_if/README delete mode 100755 examples/var_service/dhcpd_if/p_log delete mode 100755 examples/var_service/dhcpd_if/w_log delete mode 100755 examples/var_service/dnsmasq/p_log delete mode 100755 examples/var_service/dnsmasq/w_log delete mode 100644 examples/var_service/ftpd/README delete mode 100755 examples/var_service/ftpd/p_log delete mode 100755 examples/var_service/ftpd/w_log delete mode 100644 examples/var_service/fw/README delete mode 100644 examples/var_service/getty_tty1/README delete mode 100644 examples/var_service/gpm/README delete mode 100644 examples/var_service/httpd/README delete mode 100755 examples/var_service/httpd/p_log delete mode 100755 examples/var_service/httpd/w_log delete mode 100644 examples/var_service/ifplugd_if/README delete mode 100755 examples/var_service/ifplugd_if/p_log delete mode 100755 examples/var_service/ifplugd_if/w_log delete mode 100644 examples/var_service/inetd/README delete mode 100755 examples/var_service/inetd/p_log delete mode 100755 examples/var_service/inetd/w_log delete mode 100644 examples/var_service/nmeter/README delete mode 100644 examples/var_service/ntpd/README delete mode 100755 examples/var_service/ntpd/p_log delete mode 100755 examples/var_service/ntpd/w_log create mode 100755 examples/var_service/std_service_logger delete mode 100644 examples/var_service/supplicant_if/README delete mode 100755 examples/var_service/supplicant_if/p_log delete mode 100755 examples/var_service/supplicant_if/w_log create mode 100755 examples/var_service/sview create mode 100755 examples/var_service/svpage delete mode 100644 examples/var_service/tftpd/README delete mode 100755 examples/var_service/tftpd/p_log delete mode 100755 examples/var_service/tftpd/w_log delete mode 100644 examples/var_service/zcip_if/README delete mode 100755 examples/var_service/zcip_if/p_log delete mode 100755 examples/var_service/zcip_if/w_log diff --git a/examples/var_service/dhcp_if/README b/examples/var_service/dhcp_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/dhcp_if/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/dhcp_if/log/run b/examples/var_service/dhcp_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/dhcp_if/log/run +++ b/examples/var_service/dhcp_if/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/dhcp_if/p_log b/examples/var_service/dhcp_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/dhcp_if/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/dhcp_if/w_log b/examples/var_service/dhcp_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/dhcp_if/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/dhcp_if_pinger/README b/examples/var_service/dhcp_if_pinger/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/dhcp_if_pinger/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/dhcpd_if/README b/examples/var_service/dhcpd_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/dhcpd_if/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/dhcpd_if/log/run b/examples/var_service/dhcpd_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/dhcpd_if/log/run +++ b/examples/var_service/dhcpd_if/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/dhcpd_if/p_log b/examples/var_service/dhcpd_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/dhcpd_if/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/dhcpd_if/w_log b/examples/var_service/dhcpd_if/w_log deleted file mode 100755 index dba76c69b..000000000 --- a/examples/var_service/dhcpd_if/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir -watch -n1 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b0-$((w-2))' diff --git a/examples/var_service/dnsmasq/log/run b/examples/var_service/dnsmasq/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/dnsmasq/log/run +++ b/examples/var_service/dnsmasq/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/dnsmasq/p_log b/examples/var_service/dnsmasq/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/dnsmasq/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/dnsmasq/w_log b/examples/var_service/dnsmasq/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/dnsmasq/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/ftpd/README b/examples/var_service/ftpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/ftpd/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/ftpd/log/run b/examples/var_service/ftpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/ftpd/log/run +++ b/examples/var_service/ftpd/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/ftpd/p_log b/examples/var_service/ftpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/ftpd/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/ftpd/w_log b/examples/var_service/ftpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/ftpd/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/fw/README b/examples/var_service/fw/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/fw/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/getty_tty1/README b/examples/var_service/getty_tty1/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/getty_tty1/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/gpm/README b/examples/var_service/gpm/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/gpm/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/httpd/README b/examples/var_service/httpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/httpd/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/httpd/log/run b/examples/var_service/httpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/httpd/log/run +++ b/examples/var_service/httpd/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/httpd/p_log b/examples/var_service/httpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/httpd/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/httpd/w_log b/examples/var_service/httpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/httpd/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/ifplugd_if/README b/examples/var_service/ifplugd_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/ifplugd_if/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/ifplugd_if/log/run b/examples/var_service/ifplugd_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/ifplugd_if/log/run +++ b/examples/var_service/ifplugd_if/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/ifplugd_if/p_log b/examples/var_service/ifplugd_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/ifplugd_if/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/ifplugd_if/w_log b/examples/var_service/ifplugd_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/ifplugd_if/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/inetd/README b/examples/var_service/inetd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/inetd/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/inetd/log/run b/examples/var_service/inetd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/inetd/log/run +++ b/examples/var_service/inetd/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/inetd/p_log b/examples/var_service/inetd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/inetd/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/inetd/w_log b/examples/var_service/inetd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/inetd/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/nmeter/README b/examples/var_service/nmeter/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/nmeter/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/ntpd/README b/examples/var_service/ntpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/ntpd/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/ntpd/log/run b/examples/var_service/ntpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/ntpd/log/run +++ b/examples/var_service/ntpd/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/ntpd/p_log b/examples/var_service/ntpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/ntpd/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/ntpd/w_log b/examples/var_service/ntpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/ntpd/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/std_service_logger b/examples/var_service/std_service_logger new file mode 100755 index 000000000..ee68ad12b --- /dev/null +++ b/examples/var_service/std_service_logger @@ -0,0 +1,32 @@ +#!/bin/sh + +user=logger + +exec >/dev/null 2>&1 + +service="${PWD%/log}" +service="${service##*/}" +logdir="/var/log/service/$service" + +mkdir -p "$logdir" +chown -R "$user": "$logdir" +chmod -R go-rwxst,u+rwX "$logdir" +# TODO: if "$logdir/config" does not exist, +# based on service's preferences, write some setup in it: +# e.g. smaller nNUM directive ("I'm not that important, +# save 2 rather than default 10 one-megabyte log files") + +# Convenience symlink in this log/ directory: +rm logdir +ln -s "$logdir" logdir + +# Make current dir accessible to logger: +chmod a+rX . + +args="" +test "$LOG_NOTIMESTAMP" || args="-tt" + +exec \ +env - PATH="$PATH" \ +chpst -u "$user" -m $((20 * 1024*1024)) \ +svlogd $args "$logdir" diff --git a/examples/var_service/supplicant_if/README b/examples/var_service/supplicant_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/supplicant_if/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/supplicant_if/log/run b/examples/var_service/supplicant_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/supplicant_if/log/run +++ b/examples/var_service/supplicant_if/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/supplicant_if/p_log b/examples/var_service/supplicant_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/supplicant_if/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/supplicant_if/w_log b/examples/var_service/supplicant_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/supplicant_if/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/sview b/examples/var_service/sview new file mode 100755 index 000000000..716c1079c --- /dev/null +++ b/examples/var_service/sview @@ -0,0 +1,19 @@ +#!/bin/sh + +test "$1" || { + echo "Syntax: ${0##*/} SERVICE" + exit 1 +} + +test x"$1" = x"${1#*/}" -a x"$1" != x"." && { + # has no slashes and is not a "." + cd "/var/service/$1" || exit $? + set -- "." +} + +test -x "$1/view" && exec "$1/view" + +cd "log/logdir" || exit $? + +h=`ttysize h` +exec tail -n $((h-1)) -F current 2>&1 diff --git a/examples/var_service/svpage b/examples/var_service/svpage new file mode 100755 index 000000000..31c3d6dd7 --- /dev/null +++ b/examples/var_service/svpage @@ -0,0 +1,19 @@ +#!/bin/sh + +test "$1" || { + echo "Syntax: ${0##*/} SERVICE" + exit 1 +} + +test x"$1" = x"${1#*/}" -a x"$1" != x"." && { + # has no slashes and is not a "." + cd "/var/service/$1" || exit $? + set -- "." +} + +test -x "$1/page" && exec "$1/page" + +cd "log/logdir" || exit $? + +test "$PAGER" || PAGER=less +cat @* current | $PAGER diff --git a/examples/var_service/tftpd/README b/examples/var_service/tftpd/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/tftpd/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/tftpd/log/run b/examples/var_service/tftpd/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/tftpd/log/run +++ b/examples/var_service/tftpd/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/tftpd/p_log b/examples/var_service/tftpd/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/tftpd/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/tftpd/w_log b/examples/var_service/tftpd/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/tftpd/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' diff --git a/examples/var_service/zcip_if/README b/examples/var_service/zcip_if/README deleted file mode 100644 index 4ddccb22d..000000000 --- a/examples/var_service/zcip_if/README +++ /dev/null @@ -1,5 +0,0 @@ -The real README file is one directory up. - -This directory's run script can have useful comments. -If it doesn't but you feel it should, please send a patch -to busybox's mailing list. diff --git a/examples/var_service/zcip_if/log/run b/examples/var_service/zcip_if/log/run index 69d74b73f..756be4e7e 100755 --- a/examples/var_service/zcip_if/log/run +++ b/examples/var_service/zcip_if/log/run @@ -1,21 +1,2 @@ #!/bin/sh - -user=logger - -logdir="/var/log/service/`(cd ..;basename $PWD)`" -mkdir -p "$logdir" 2>/dev/null -chown -R "$user": "$logdir" -chmod -R go-rwxst,u+rwX "$logdir" -rm -rf logdir -ln -s "$logdir" logdir - -# make this dir accessible to logger -chmod a+rX . - -exec >/dev/null -exec 2>&1 -exec \ -env - PATH="$PATH" \ -softlimit \ -setuidgid "$user" \ -svlogd -tt "$logdir" +exec std_service_logger diff --git a/examples/var_service/zcip_if/p_log b/examples/var_service/zcip_if/p_log deleted file mode 100755 index a2521be05..000000000 --- a/examples/var_service/zcip_if/p_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -cat @* current | $PAGER diff --git a/examples/var_service/zcip_if/w_log b/examples/var_service/zcip_if/w_log deleted file mode 100755 index aa36ef13b..000000000 --- a/examples/var_service/zcip_if/w_log +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -cd log/logdir || exit 1 -watch -n2 'w=`ttysize w`; h=`ttysize h`; tail -$((h-3)) current 2>&1 | cut -b1-$((w-2))' -- cgit v1.2.3-55-g6feb From fc267214f0957bdc5794a71ae73e38edb00e5ba2 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 3 Jul 2018 16:36:13 +1000 Subject: udhcp: add option 211, "reboot time" As defined in RFC 5071. Signed-off-by: Jeremy Kerr Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 2 ++ networking/udhcp/common.h | 1 + 2 files changed, 3 insertions(+) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 52ef875f0..77fb07cdc 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -65,6 +65,7 @@ const struct dhcp_optflag dhcp_optflags[] = { #endif { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ + { OPTION_U32 , 0xd3 }, /* DHCP_REBOOT_TIME */ { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ @@ -133,6 +134,7 @@ const char dhcp_option_strings[] ALIGN1 = #endif "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ + "reboottime" "\0" /* DHCP_REBOOT_TIME */ "ip6rd" "\0" /* DHCP_6RD */ "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ "wpad" "\0" /* DHCP_WPAD */ diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 50ea9199b..550161934 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -156,6 +156,7 @@ enum { //#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ //#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */ //#define DHCP_PXE_PATH_PREFIX 0xd2 /* RFC 5071 Configuration File */ +//#define DHCP_REBOOT_TIME 0xd3 /* RFC 5071 Reboot time */ //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ #define DHCP_END 0xff -- cgit v1.2.3-55-g6feb From 6d26744a2c78d874e6e2c8f44cacb0c7c6c11eae Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 4 Jul 2018 15:44:22 +0200 Subject: udhcp: tweak comment indentation, no code changes Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 78 +++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 77fb07cdc..e5fd74f91 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -93,51 +93,51 @@ const struct dhcp_optflag dhcp_optflags[] = { */ /* Must match dhcp_optflags[] order */ const char dhcp_option_strings[] ALIGN1 = - "subnet" "\0" /* DHCP_SUBNET */ - "timezone" "\0" /* DHCP_TIME_OFFSET */ - "router" "\0" /* DHCP_ROUTER */ -// "timesrv" "\0" /* DHCP_TIME_SERVER */ -// "namesrv" "\0" /* DHCP_NAME_SERVER */ - "dns" "\0" /* DHCP_DNS_SERVER */ -// "logsrv" "\0" /* DHCP_LOG_SERVER */ -// "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ - "lprsrv" "\0" /* DHCP_LPR_SERVER */ - "hostname" "\0" /* DHCP_HOST_NAME */ - "bootsize" "\0" /* DHCP_BOOT_SIZE */ - "domain" "\0" /* DHCP_DOMAIN_NAME */ - "swapsrv" "\0" /* DHCP_SWAP_SERVER */ - "rootpath" "\0" /* DHCP_ROOT_PATH */ - "ipttl" "\0" /* DHCP_IP_TTL */ - "mtu" "\0" /* DHCP_MTU */ - "broadcast" "\0" /* DHCP_BROADCAST */ - "routes" "\0" /* DHCP_ROUTES */ - "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ - "nissrv" "\0" /* DHCP_NIS_SERVER */ - "ntpsrv" "\0" /* DHCP_NTP_SERVER */ - "wins" "\0" /* DHCP_WINS_SERVER */ - "lease" "\0" /* DHCP_LEASE_TIME */ - "serverid" "\0" /* DHCP_SERVER_ID */ - "message" "\0" /* DHCP_ERR_MESSAGE */ - "tftp" "\0" /* DHCP_TFTP_SERVER_NAME */ - "bootfile" "\0" /* DHCP_BOOT_FILE */ -// "userclass" "\0" /* DHCP_USER_CLASS */ + "subnet" "\0" /* DHCP_SUBNET */ + "timezone" "\0" /* DHCP_TIME_OFFSET */ + "router" "\0" /* DHCP_ROUTER */ +// "timesrv" "\0" /* DHCP_TIME_SERVER */ +// "namesrv" "\0" /* DHCP_NAME_SERVER */ + "dns" "\0" /* DHCP_DNS_SERVER */ +// "logsrv" "\0" /* DHCP_LOG_SERVER */ +// "cookiesrv" "\0" /* DHCP_COOKIE_SERVER */ + "lprsrv" "\0" /* DHCP_LPR_SERVER */ + "hostname" "\0" /* DHCP_HOST_NAME */ + "bootsize" "\0" /* DHCP_BOOT_SIZE */ + "domain" "\0" /* DHCP_DOMAIN_NAME */ + "swapsrv" "\0" /* DHCP_SWAP_SERVER */ + "rootpath" "\0" /* DHCP_ROOT_PATH */ + "ipttl" "\0" /* DHCP_IP_TTL */ + "mtu" "\0" /* DHCP_MTU */ + "broadcast" "\0" /* DHCP_BROADCAST */ + "routes" "\0" /* DHCP_ROUTES */ + "nisdomain" "\0" /* DHCP_NIS_DOMAIN */ + "nissrv" "\0" /* DHCP_NIS_SERVER */ + "ntpsrv" "\0" /* DHCP_NTP_SERVER */ + "wins" "\0" /* DHCP_WINS_SERVER */ + "lease" "\0" /* DHCP_LEASE_TIME */ + "serverid" "\0" /* DHCP_SERVER_ID */ + "message" "\0" /* DHCP_ERR_MESSAGE */ + "tftp" "\0" /* DHCP_TFTP_SERVER_NAME*/ + "bootfile" "\0" /* DHCP_BOOT_FILE */ +// "userclass" "\0" /* DHCP_USER_CLASS */ #if ENABLE_FEATURE_UDHCP_RFC3397 - "search" "\0" /* DHCP_DOMAIN_SEARCH */ + "search" "\0" /* DHCP_DOMAIN_SEARCH */ // doesn't work in udhcpd.conf since OPTION_SIP_SERVERS // is not handled yet by "string->option" conversion code: - "sipsrv" "\0" /* DHCP_SIP_SERVERS */ + "sipsrv" "\0" /* DHCP_SIP_SERVERS */ #endif - "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ + "staticroutes" "\0" /* DHCP_STATIC_ROUTES */ #if ENABLE_FEATURE_UDHCP_8021Q - "vlanid" "\0" /* DHCP_VLAN_ID */ - "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ + "vlanid" "\0" /* DHCP_VLAN_ID */ + "vlanpriority" "\0" /* DHCP_VLAN_PRIORITY */ #endif - "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ - "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ - "reboottime" "\0" /* DHCP_REBOOT_TIME */ - "ip6rd" "\0" /* DHCP_6RD */ - "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ - "wpad" "\0" /* DHCP_WPAD */ + "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ + "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ + "reboottime" "\0" /* DHCP_REBOOT_TIME */ + "ip6rd" "\0" /* DHCP_6RD */ + "msstaticroutes" "\0" /* DHCP_MS_STATIC_ROUTES*/ + "wpad" "\0" /* DHCP_WPAD */ ; #endif -- cgit v1.2.3-55-g6feb From 2cd81698ee6f272202299058c134495bc8984c5f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 4 Jul 2018 16:05:48 +0200 Subject: udhcp: add decimal option values in comments, no code changes Signed-off-by: Denys Vlasenko --- networking/udhcp/common.h | 60 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 550161934..7ad603d33 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -122,9 +122,9 @@ enum { //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ //#define DHCP_LPR_SERVER 0x09 -#define DHCP_HOST_NAME 0x0c /* either client informs server or server gives name to client */ +#define DHCP_HOST_NAME 0x0c /* 12: either client informs server or server gives name to client */ //#define DHCP_BOOT_SIZE 0x0d -//#define DHCP_DOMAIN_NAME 0x0f /* server gives domain suffix */ +//#define DHCP_DOMAIN_NAME 0x0f /* 15: server gives domain suffix */ //#define DHCP_SWAP_SERVER 0x10 //#define DHCP_ROOT_PATH 0x11 //#define DHCP_IP_TTL 0x17 @@ -135,40 +135,40 @@ enum { //#define DHCP_NIS_SERVER 0x29 //#define DHCP_NTP_SERVER 0x2a //#define DHCP_WINS_SERVER 0x2c -#define DHCP_REQUESTED_IP 0x32 /* sent by client if specific IP is wanted */ -#define DHCP_LEASE_TIME 0x33 -#define DHCP_OPTION_OVERLOAD 0x34 -#define DHCP_MESSAGE_TYPE 0x35 -#define DHCP_SERVER_ID 0x36 /* by default server's IP */ -#define DHCP_PARAM_REQ 0x37 /* list of options client wants */ -//#define DHCP_ERR_MESSAGE 0x38 /* error message when sending NAK etc */ -#define DHCP_MAX_SIZE 0x39 -#define DHCP_VENDOR 0x3c /* client's vendor (a string) */ -#define DHCP_CLIENT_ID 0x3d /* by default client's MAC addr, but may be arbitrarily long */ -//#define DHCP_TFTP_SERVER_NAME 0x42 /* same as 'sname' field */ -//#define DHCP_BOOT_FILE 0x43 /* same as 'file' field */ -//#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ -#define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ -//#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ -//#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ -//#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ -//#define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ -//#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ -//#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */ -//#define DHCP_PXE_PATH_PREFIX 0xd2 /* RFC 5071 Configuration File */ -//#define DHCP_REBOOT_TIME 0xd3 /* RFC 5071 Reboot time */ -//#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ -//#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ -#define DHCP_END 0xff +#define DHCP_REQUESTED_IP 0x32 /* 50: sent by client if specific IP is wanted */ +#define DHCP_LEASE_TIME 0x33 /* 51: */ +#define DHCP_OPTION_OVERLOAD 0x34 /* 52: */ +#define DHCP_MESSAGE_TYPE 0x35 /* 53: */ +#define DHCP_SERVER_ID 0x36 /* 54: server's IP */ +#define DHCP_PARAM_REQ 0x37 /* 55: list of options client wants */ +//#define DHCP_ERR_MESSAGE 0x38 /* 56: error message when sending NAK etc */ +#define DHCP_MAX_SIZE 0x39 /* 57: */ +#define DHCP_VENDOR 0x3c /* 60: client's vendor (a string) */ +#define DHCP_CLIENT_ID 0x3d /* 61: by default client's MAC addr, but may be arbitrarily long */ +//#define DHCP_TFTP_SERVER_NAME 0x42 /* 66: same as 'sname' field */ +//#define DHCP_BOOT_FILE 0x43 /* 67: same as 'file' field */ +//#define DHCP_USER_CLASS 0x4d /* 77: RFC 3004. set of LASCII strings. "I am a printer" etc */ +#define DHCP_FQDN 0x51 /* 81: client asks to update DNS to map its FQDN to its new IP */ +//#define DHCP_DOMAIN_SEARCH 0x77 /* 119: RFC 3397. set of ASCIZ string, DNS-style compressed */ +//#define DHCP_SIP_SERVERS 0x78 /* 120: RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ +//#define DHCP_STATIC_ROUTES 0x79 /* 121: RFC 3442. (mask,ip,router) tuples */ +//#define DHCP_VLAN_ID 0x84 /* 132: 802.1P VLAN ID */ +//#define DHCP_VLAN_PRIORITY 0x85 /* 133: 802.1Q VLAN priority */ +//#define DHCP_PXE_CONF_FILE 0xd1 /* 209: RFC 5071 Configuration File */ +//#define DHCP_PXE_PATH_PREFIX 0xd2 /* 210: RFC 5071 Configuration File */ +//#define DHCP_REBOOT_TIME 0xd3 /* 211: RFC 5071 Reboot time */ +//#define DHCP_MS_STATIC_ROUTES 0xf9 /* 249: Microsoft's pre-RFC 3442 code for 0x79? */ +//#define DHCP_WPAD 0xfc /* 252: MSIE's Web Proxy Autodiscovery Protocol */ +#define DHCP_END 0xff /* 255: */ /* Offsets in option byte sequence */ #define OPT_CODE 0 #define OPT_LEN 1 #define OPT_DATA 2 /* Offsets in option byte sequence for DHCPv6 */ -#define D6_OPT_CODE 0 -#define D6_OPT_LEN 2 -#define D6_OPT_DATA 4 +#define D6_OPT_CODE 0 +#define D6_OPT_LEN 2 +#define D6_OPT_DATA 4 /* Bits in "overload" option */ #define OPTION_FIELD 0 #define FILE_FIELD 1 -- cgit v1.2.3-55-g6feb From 6f09785b7e4a6cc7a9ede623d51aa8f6dc5e9a03 Mon Sep 17 00:00:00 2001 From: "Raffaello D. Di Napoli" Date: Tue, 26 Jun 2018 19:18:02 -0400 Subject: sendmail: fix parsing of addresses in angle brackets Pointer e needs to be wound back in order to overwrite '>' with '\0'. Regression introduced in 20077c1429 Signed-off-by: Raffaello D. Di Napoli Signed-off-by: Denys Vlasenko --- mailutils/sendmail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mailutils/sendmail.c b/mailutils/sendmail.c index 4ca91fad8..0170f2870 100644 --- a/mailutils/sendmail.c +++ b/mailutils/sendmail.c @@ -173,7 +173,7 @@ static char *angle_address(char *str) char *s, *e; e = trim(str); - if (e != str && e[-1] == '>') { + if (e != str && *--e == '>') { s = strrchr(str, '<'); if (s) { *e = '\0'; -- cgit v1.2.3-55-g6feb From 4a85d56c4cda90d0c175f29eb320375d14ead507 Mon Sep 17 00:00:00 2001 From: haroon maqsood Date: Fri, 6 Jul 2018 16:17:57 +0200 Subject: nproc: implement --all --ignore=N function old new delta nproc_main 98 242 +144 packed_usage 32799 32816 +17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 161/0) Total: 161 bytes Signed-off-by: haroon maqsood Signed-off-by: Denys Vlasenko --- coreutils/nproc.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/coreutils/nproc.c b/coreutils/nproc.c index 336b176ca..0ea8d1001 100644 --- a/coreutils/nproc.c +++ b/coreutils/nproc.c @@ -14,10 +14,14 @@ //kbuild:lib-$(CONFIG_NPROC) += nproc.o //usage:#define nproc_trivial_usage -//usage: "" -//TODO: "[--all] [--ignore=N]" +//usage: ""IF_LONG_OPTS("--all --ignore=N") //usage:#define nproc_full_usage "\n\n" -//usage: "Print number of CPUs" +//usage: "Print number of available CPUs" +//usage: IF_LONG_OPTS( +//usage: "\n" +//usage: "\n --all Number of installed CPUs" +//usage: "\n --ignore=N Exclude N CPUs" +//usage: ) #include #include "libbb.h" @@ -26,13 +30,30 @@ int nproc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { unsigned long mask[1024]; - unsigned i, count = 0; - - //getopt32(argv, ""); - - //if --all, count /sys/devices/system/cpu/cpuN dirs, else: + int count = 0; +#if ENABLE_LONG_OPTS + int ignore = 0; + int opts = getopt32long(argv, "\xfe:+", + "ignore\0" Required_argument "\xfe" + "all\0" No_argument "\xff" + , &ignore + ); + if (opts & (1 << 1)) { + DIR *cpusd = opendir("/sys/devices/system/cpu"); + if (cpusd) { + struct dirent *de; + while (NULL != (de = readdir(cpusd))) { + char *cpuid = strstr(de->d_name, "cpu"); + if (cpuid && isdigit(cpuid[strlen(cpuid) - 1])) + count++; + } + closedir(cpusd); + } + } else +#endif if (sched_getaffinity(0, sizeof(mask), (void*)mask) == 0) { + int i; for (i = 0; i < ARRAY_SIZE(mask); i++) { unsigned long m = mask[i]; while (m) { @@ -42,8 +63,11 @@ int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) } } } - if (count == 0) - count++; + + IF_LONG_OPTS(count -= ignore;) + if (count <= 0) + count = 1; + printf("%u\n", count); return 0; -- cgit v1.2.3-55-g6feb From abe22cd17b182153bc883e7d9e3cb04eb2c449ff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Jul 2018 20:35:35 +0200 Subject: find: implement -quit function old new delta packed_usage 32816 32846 +30 find_main 446 464 +18 func_quit - 13 +13 parse_params 1495 1505 +10 static.params 210 216 +6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/0 up/down: 77/0) Total: 77 bytes Signed-off-by: Denys Vlasenko --- findutils/find.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/findutils/find.c b/findutils/find.c index 07321c81a..72732615b 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -182,6 +182,13 @@ //config: If the file is a directory, don't descend into it. Useful for //config: exclusion .svn and CVS directories. //config: +//config:config FEATURE_FIND_QUIT +//config: bool "Enable -quit: exit" +//config: default y +//config: depends on FIND +//config: help +//config: If this action is reached, 'find' exits. +//config: //config:config FEATURE_FIND_DELETE //config: bool "Enable -delete: delete files/dirs" //config: default y @@ -318,6 +325,9 @@ //usage: IF_FEATURE_FIND_DELETE( //usage: "\n -delete Delete current file/directory. Turns on -depth option" //usage: ) +//usage: IF_FEATURE_FIND_QUIT( +//usage: "\n -quit Exit" +//usage: ) //usage: //usage:#define find_example_usage //usage: "$ find / -name passwd\n" @@ -375,6 +385,7 @@ IF_FEATURE_FIND_SIZE( ACTS(size, char size_char; off_t size;)) IF_FEATURE_FIND_CONTEXT(ACTS(context, security_context_t context;)) IF_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;)) IF_FEATURE_FIND_PRUNE( ACTS(prune)) +IF_FEATURE_FIND_QUIT( ACTS(quit)) IF_FEATURE_FIND_DELETE( ACTS(delete)) IF_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; /* -exec ARGS */ @@ -402,6 +413,7 @@ struct globals { action ***actions; smallint need_print; smallint xdev_on; + smalluint exitstatus; recurse_flags_t recurse_flags; IF_FEATURE_FIND_EXEC_PLUS(unsigned max_argv_len;) } FIX_ALIASING; @@ -774,6 +786,12 @@ ACTF(prune) return SKIP + TRUE; } #endif +#if ENABLE_FEATURE_FIND_QUIT +ACTF(quit) +{ + exit(G.exitstatus); +} +#endif #if ENABLE_FEATURE_FIND_DELETE ACTF(delete) { @@ -954,6 +972,7 @@ static action*** parse_params(char **argv) PARM_print , IF_FEATURE_FIND_PRINT0( PARM_print0 ,) IF_FEATURE_FIND_PRUNE( PARM_prune ,) + IF_FEATURE_FIND_QUIT( PARM_quit ,) IF_FEATURE_FIND_DELETE( PARM_delete ,) IF_FEATURE_FIND_EXEC( PARM_exec ,) IF_FEATURE_FIND_PAREN( PARM_char_brace,) @@ -997,6 +1016,7 @@ static action*** parse_params(char **argv) "-print\0" IF_FEATURE_FIND_PRINT0( "-print0\0" ) IF_FEATURE_FIND_PRUNE( "-prune\0" ) + IF_FEATURE_FIND_QUIT( "-quit\0" ) IF_FEATURE_FIND_DELETE( "-delete\0" ) IF_FEATURE_FIND_EXEC( "-exec\0" ) IF_FEATURE_FIND_PAREN( "(\0" ) @@ -1152,6 +1172,12 @@ static action*** parse_params(char **argv) (void) ALLOC_ACTION(prune); } #endif +#if ENABLE_FEATURE_FIND_QUIT + else if (parm == PARM_quit) { + dbg("%d", __LINE__); + (void) ALLOC_ACTION(quit); + } +#endif #if ENABLE_FEATURE_FIND_DELETE else if (parm == PARM_delete) { dbg("%d", __LINE__); @@ -1401,7 +1427,7 @@ static action*** parse_params(char **argv) int find_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int find_main(int argc UNUSED_PARAM, char **argv) { - int i, firstopt, status = EXIT_SUCCESS; + int i, firstopt; char **past_HLP, *saved; INIT_G(); @@ -1475,10 +1501,10 @@ int find_main(int argc UNUSED_PARAM, char **argv) NULL, /* user data */ 0) /* depth */ ) { - status |= EXIT_FAILURE; + G.exitstatus |= EXIT_FAILURE; } } - IF_FEATURE_FIND_EXEC_PLUS(status |= flush_exec_plus();) - return status; + IF_FEATURE_FIND_EXEC_PLUS(G.exitstatus |= flush_exec_plus();) + return G.exitstatus; } -- cgit v1.2.3-55-g6feb From 4d0e2d5b6d563fd8adb5940a42d73a43c812378b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Jul 2018 20:49:08 +0200 Subject: tweak help texts Signed-off-by: Denys Vlasenko --- archival/cpio.c | 8 +++++--- findutils/xargs.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 221667112..01f82379e 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -64,15 +64,17 @@ //usage: "\n -p DIR Copy files to DIR" //usage: ) //usage: "\nOptions:" +//usage: IF_FEATURE_CPIO_O( +//usage: "\n -H newc Archive format" +//usage: ) //usage: "\n -d Make leading directories" //usage: "\n -m Preserve mtime" //usage: "\n -v Verbose" //usage: "\n -u Overwrite" //usage: "\n -F FILE Input (-t,-i,-p) or output (-o) file" //usage: "\n -R USER[:GRP] Set owner of created files" -//usage: IF_FEATURE_CPIO_O( -//usage: "\n -H newc Archive format" -//usage: ) +//usage: "\n -L Dereference symlinks" +//usage: "\n -0 Input is separated by NULs" /* GNU cpio 2.9 --help (abridged): diff --git a/findutils/xargs.c b/findutils/xargs.c index 1d85d50e8..c369bdaf5 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -520,7 +520,7 @@ static int xargs_ask_confirmation(void) //usage: ) //usage: "\n -r Don't run command if input is empty" //usage: IF_FEATURE_XARGS_SUPPORT_ZERO_TERM( -//usage: "\n -0 Input is separated by NUL characters" +//usage: "\n -0 Input is separated by NULs" //usage: ) //usage: IF_FEATURE_XARGS_SUPPORT_ARGS_FILE( //usage: "\n -a FILE Read from FILE instead of stdin" -- cgit v1.2.3-55-g6feb From 9be4d4fe442aa9e23675b1c0a8b1394e77998961 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Jul 2018 20:50:30 +0200 Subject: cpio: if longopts are enabled, accept --null (synonym for -0) Signed-off-by: Denys Vlasenko --- archival/cpio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/archival/cpio.c b/archival/cpio.c index 01f82379e..9cacf9de6 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -376,6 +376,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) #endif "owner\0" Required_argument "R" "verbose\0" No_argument "v" + "null\0" No_argument "0" "quiet\0" No_argument "\xff" "to-stdout\0" No_argument "\xfe" ; -- cgit v1.2.3-55-g6feb From 008e73b5728b19c7ba6e746e279c4bc8a1935f0d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 6 Jul 2018 21:04:41 +0200 Subject: find: implement -executable function old new delta func_executable - 19 +19 parse_params 1505 1519 +14 static.params 216 228 +12 packed_usage 32847 32855 +8 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/0 up/down: 53/0) Total: 53 bytes Signed-off-by: Denys Vlasenko --- findutils/find.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/findutils/find.c b/findutils/find.c index 72732615b..6407c6c5a 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -95,6 +95,11 @@ //config: Enable searching based on file type (file, //config: directory, socket, device, etc.). //config: +//config:config FEATURE_FIND_EXECUTABLE +//config: bool "Enable -executable: file is executable" +//config: default y +//config: depends on FIND +//config: //config:config FEATURE_FIND_XDEV //config: bool "Enable -xdev: 'stay in filesystem'" //config: default y @@ -272,6 +277,9 @@ //usage: IF_FEATURE_FIND_TYPE( //usage: "\n -type X File type is X (one of: f,d,l,b,c,s,p)" //usage: ) +//usage: IF_FEATURE_FIND_EXECUTABLE( +//usage: "\n -executable File is executable" +//usage: ) //usage: IF_FEATURE_FIND_PERM( //usage: "\n -perm MASK At least one mask bit (+MASK), all bits (-MASK)," //usage: "\n or exactly MASK bits are set in file's mode" @@ -375,6 +383,7 @@ IF_FEATURE_FIND_PATH( ACTS(path, const char *pattern; bool ipath;)) IF_FEATURE_FIND_REGEX( ACTS(regex, regex_t compiled_pattern;)) IF_FEATURE_FIND_PRINT0( ACTS(print0)) IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;)) +IF_FEATURE_FIND_EXECUTABLE(ACTS(executable)) IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;)) IF_FEATURE_FIND_MTIME( ACTS(mtime, char mtime_char; unsigned mtime_days;)) IF_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;)) @@ -578,6 +587,12 @@ ACTF(type) return ((statbuf->st_mode & S_IFMT) == ap->type_mask); } #endif +#if ENABLE_FEATURE_FIND_EXECUTABLE +ACTF(executable) +{ + return access(fileName, X_OK) == 0; +} +#endif #if ENABLE_FEATURE_FIND_PERM ACTF(perm) { @@ -975,6 +990,7 @@ static action*** parse_params(char **argv) IF_FEATURE_FIND_QUIT( PARM_quit ,) IF_FEATURE_FIND_DELETE( PARM_delete ,) IF_FEATURE_FIND_EXEC( PARM_exec ,) + IF_FEATURE_FIND_EXECUTABLE(PARM_executable,) IF_FEATURE_FIND_PAREN( PARM_char_brace,) /* All options/actions starting from here require argument */ PARM_name , @@ -1019,6 +1035,7 @@ static action*** parse_params(char **argv) IF_FEATURE_FIND_QUIT( "-quit\0" ) IF_FEATURE_FIND_DELETE( "-delete\0" ) IF_FEATURE_FIND_EXEC( "-exec\0" ) + IF_FEATURE_FIND_EXECUTABLE("-executable\0") IF_FEATURE_FIND_PAREN( "(\0" ) /* All options/actions starting from here require argument */ "-name\0" @@ -1288,6 +1305,11 @@ static action*** parse_params(char **argv) dbg("created:type mask:%x", ap->type_mask); } #endif +#if ENABLE_FEATURE_FIND_EXECUTABLE + else if (parm == PARM_executable) { + (void) ALLOC_ACTION(executable); + } +#endif #if ENABLE_FEATURE_FIND_PERM /* -perm BITS File's mode bits are exactly BITS (octal or symbolic). * Symbolic modes use mode 0 as a point of departure. -- cgit v1.2.3-55-g6feb From cbe8c65e590949cad25dccba90101553b77d88c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jul 2018 01:37:54 +0200 Subject: sort: add -V "sort version" function old new delta packed_usage 32855 32858 +3 get_key 500 503 +3 sort_opt_str 36 37 +1 sort_main 1037 1036 -1 compare_keys 795 783 -12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/2 up/down: 7/-13) Total: -6 bytes Signed-off-by: Denys Vlasenko --- coreutils/sort.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/coreutils/sort.c b/coreutils/sort.c index 4d741e76d..05e5c9071 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -60,6 +60,7 @@ //usage: IF_FEATURE_SORT_BIG( //usage: "\n -g General numerical sort" //usage: "\n -M Sort month" +//usage: "\n -V Sort version" //usage: "\n -t CHAR Field separator" //usage: "\n -k N[,M] Sort by Nth field" //usage: ) @@ -91,32 +92,33 @@ /* These are sort types */ enum { - FLAG_n = 1, /* Numeric sort */ - FLAG_g = 2, /* Sort using strtod() */ - FLAG_M = 4, /* Sort date */ + FLAG_n = 1 << 0, /* Numeric sort */ + FLAG_g = 1 << 1, /* Sort using strtod() */ + FLAG_M = 1 << 2, /* Sort date */ + FLAG_V = 1 << 3, /* Sort version */ /* ucsz apply to root level only, not keys. b at root level implies bb */ - FLAG_u = 8, /* Unique */ - FLAG_c = 0x10, /* Check: no output, exit(!ordered) */ - FLAG_s = 0x20, /* Stable sort, no ascii fallback at end */ - FLAG_z = 0x40, /* Input and output is NUL terminated, not \n */ + FLAG_u = 1 << 4, /* Unique */ + FLAG_c = 1 << 5, /* Check: no output, exit(!ordered) */ + FLAG_s = 1 << 6, /* Stable sort, no ascii fallback at end */ + FLAG_z = 1 << 7, /* Input and output is NUL terminated, not \n */ /* These can be applied to search keys, the previous four can't */ - FLAG_b = 0x80, /* Ignore leading blanks */ - FLAG_r = 0x100, /* Reverse */ - FLAG_d = 0x200, /* Ignore !(isalnum()|isspace()) */ - FLAG_f = 0x400, /* Force uppercase */ - FLAG_i = 0x800, /* Ignore !isprint() */ - FLAG_m = 0x1000, /* ignored: merge already sorted files; do not sort */ - FLAG_S = 0x2000, /* ignored: -S, --buffer-size=SIZE */ - FLAG_T = 0x4000, /* ignored: -T, --temporary-directory=DIR */ - FLAG_o = 0x8000, - FLAG_k = 0x10000, - FLAG_t = 0x20000, + FLAG_b = 1 << 8, /* Ignore leading blanks */ + FLAG_r = 1 << 9, /* Reverse */ + FLAG_d = 1 << 10, /* Ignore !(isalnum()|isspace()) */ + FLAG_f = 1 << 11, /* Force uppercase */ + FLAG_i = 1 << 12, /* Ignore !isprint() */ + FLAG_m = 1 << 13, /* ignored: merge already sorted files; do not sort */ + FLAG_S = 1 << 14, /* ignored: -S, --buffer-size=SIZE */ + FLAG_T = 1 << 15, /* ignored: -T, --temporary-directory=DIR */ + FLAG_o = 1 << 16, + FLAG_k = 1 << 17, + FLAG_t = 1 << 18, FLAG_bb = 0x80000000, /* Ignore trailing blanks */ FLAG_no_tie_break = 0x40000000, }; static const char sort_opt_str[] ALIGN1 = "^" - "ngMucszbrdfimS:T:o:k:*t:" + "ngMVucszbrdfimS:T:o:k:*t:" "\0" "o--o:t--t"/*-t, -o: at most one of each*/; /* * OPT_STR must not be string literal, needs to have stable address: @@ -273,10 +275,15 @@ static int compare_keys(const void *xarg, const void *yarg) y = *(char **)yarg; #endif /* Perform actual comparison */ - switch (flags & (FLAG_n | FLAG_M | FLAG_g)) { + switch (flags & (FLAG_n | FLAG_g | FLAG_M | FLAG_V)) { default: bb_error_msg_and_die("unknown sort type"); break; +#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 + case FLAG_V: + retval = strverscmp(x, y); + break; +#endif /* Ascii sort */ case 0: #if ENABLE_LOCALE_SUPPORT -- cgit v1.2.3-55-g6feb From 253f555f01fa380083a7436a569397a4e7f997b0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jul 2018 18:23:33 +0200 Subject: usage: do not print trailing space for commands which have no arguments function old new delta bb_show_usage 120 130 +10 Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 769b7881c..f155d0908 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -169,8 +169,11 @@ void FAST_FUNC bb_show_usage(void) else { full_write2_str("\nUsage: "); full_write2_str(applet_name); - full_write2_str(" "); - full_write2_str(p); + if (p[0]) { + if (p[0] != '\n') + full_write2_str(" "); + full_write2_str(p); + } full_write2_str("\n"); } if (ENABLE_FEATURE_CLEAN_UP) -- cgit v1.2.3-55-g6feb From 79fb6ac7a5acc4178b66314c573aeada1d387ed9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 13 Jul 2018 20:30:02 +0200 Subject: cp: optional --reflink support function old new delta cp_main 428 512 +84 copy_file 1676 1742 +66 Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 24 ++++++++++++++++++++++++ include/libbb.h | 3 +++ libbb/copy_file.c | 19 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/coreutils/cp.c b/coreutils/cp.c index 455bffbba..b623aaf33 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -24,6 +24,11 @@ //config: help //config: Enable long options. //config: Also add support for --parents option. +//config: +//config:config FEATURE_CP_REFLINK +//config: bool "Enable --reflink[=auto] +//config: default y +//config: depends on FEATURE_CP_LONG_OPTIONS //applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) /* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ @@ -72,10 +77,14 @@ int cp_main(int argc, char **argv) #if ENABLE_FEATURE_CP_LONG_OPTIONS /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), + OPT_reflink = 1 << (FILEUTILS_CP_OPTNUM+2), #endif }; #if ENABLE_FEATURE_CP_LONG_OPTIONS +# if ENABLE_FEATURE_CP_REFLINK + char *reflink = NULL; +# endif flags = getopt32long(argv, "^" FILEUTILS_CP_OPTSTR "\0" @@ -99,7 +108,22 @@ int cp_main(int argc, char **argv) "update\0" No_argument "u" "remove-destination\0" No_argument "\xff" "parents\0" No_argument "\xfe" +# if ENABLE_FEATURE_CP_REFLINK + "reflink\0" Optional_argument "\xfd" + , &reflink +# endif ); +# if ENABLE_FEATURE_CP_REFLINK + BUILD_BUG_ON(OPT_reflink != FILEUTILS_REFLINK); + if (flags & FILEUTILS_REFLINK) { + if (!reflink) + flags |= FILEUTILS_REFLINK_ALWAYS; + else if (strcmp(reflink, "always") == 0) + flags |= FILEUTILS_REFLINK_ALWAYS; + else if (strcmp(reflink, "auto") != 0) + bb_show_usage(); + } +# endif #else flags = getopt32(argv, "^" FILEUTILS_CP_OPTSTR diff --git a/include/libbb.h b/include/libbb.h index d4ba031df..94caba2bb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -410,6 +410,9 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ #endif FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ + /* bit 17 skipped for "cp --parents" */ + FILEUTILS_REFLINK = 1 << (18 - !ENABLE_SELINUX), /* cp --reflink=auto */ + FILEUTILS_REFLINK_ALWAYS = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink[=always] */ /* * Hole. cp may have some bits set here, * they should not affect remove_file()/copy_file() diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 1b8befd65..98bd4fe72 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -339,9 +339,28 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) freecon(con); } } +#endif +#if ENABLE_FEATURE_CP_REFLINK +# undef BTRFS_IOCTL_MAGIC +# define BTRFS_IOCTL_MAGIC 0x94 +# undef BTRFS_IOC_CLONE +# define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int) + if (flags & FILEUTILS_REFLINK) { + retval = ioctl(dst_fd, BTRFS_IOC_CLONE, src_fd); + if (retval == 0) + goto do_close; + /* reflink did not work */ + if (flags & FILEUTILS_REFLINK_ALWAYS) { + bb_perror_msg("failed to clone '%s' from '%s'", dest, source); + goto do_close; + } + /* fall through to standard copy */ + retval = 0; + } #endif if (bb_copyfd_eof(src_fd, dst_fd) == -1) retval = -1; + IF_FEATURE_CP_REFLINK(do_close:) /* Careful with writing... */ if (close(dst_fd) < 0) { bb_perror_msg("error writing to '%s'", dest); -- cgit v1.2.3-55-g6feb From 8717b14f376e38998512c022b3d2b1af6e877e5e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 13 Jul 2018 20:40:40 +0200 Subject: grep: accept and ignore --color[=anything] function old new delta grep_main 827 834 +7 Signed-off-by: Denys Vlasenko --- findutils/grep.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/findutils/grep.c b/findutils/grep.c index 88de0d4ef..3e8ea9239 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -704,10 +704,15 @@ int grep_main(int argc UNUSED_PARAM, char **argv) /* do normal option parsing */ #if ENABLE_FEATURE_GREP_CONTEXT /* -H unsets -h; -C unsets -A,-B */ - opts = getopt32(argv, - "^" OPTSTR_GREP "\0" "H-h:C-AB", + opts = getopt32long(argv, "^" + OPTSTR_GREP + "\0" + "H-h:C-AB", + "color\0" Optional_argument "\xff", &pattern_head, &fopt, &max_matches, - &lines_after, &lines_before, &Copt); + &lines_after, &lines_before, &Copt + , NULL + ); if (opts & OPT_C) { /* -C unsets prev -A and -B, but following -A or -B -- cgit v1.2.3-55-g6feb From b0441a7189c874808dcfc36567d3e878c6ec7ba3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jul 2018 18:03:56 +0200 Subject: hush: shrink code in builtin_eval function old new delta builtin_eval 126 119 -7 Signed-off-by: Denys Vlasenko --- shell/hush.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 1f83267be..9d3f06db0 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9806,41 +9806,41 @@ static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) static int FAST_FUNC builtin_eval(char **argv) { - int rcode = EXIT_SUCCESS; - argv = skip_dash_dash(argv); - if (argv[0]) { - char *str = NULL; - if (argv[1]) { - /* "The eval utility shall construct a command by - * concatenating arguments together, separating - * each with a character." - */ - char *p; - unsigned len = 0; - char **pp = argv; - do - len += strlen(*pp) + 1; - while (*++pp); - str = p = xmalloc(len); - pp = argv; - do { - p = stpcpy(p, *pp); - *p++ = ' '; - } while (*++pp); - p[-1] = '\0'; - } + if (!argv[0]) + return EXIT_SUCCESS; + if (!argv[1]) { /* bash: * eval "echo Hi; done" ("done" is syntax error): * "echo Hi" will not execute too. */ - parse_and_run_string(str ? str : argv[0]); + parse_and_run_string(argv[0]); + } else { + /* "The eval utility shall construct a command by + * concatenating arguments together, separating + * each with a character." + */ + char *str, *p; + unsigned len = 0; + char **pp = argv; + do + len += strlen(*pp) + 1; + while (*++pp); + str = p = xmalloc(len); + pp = argv; + for (;;) { + p = stpcpy(p, *pp); + pp++; + if (!*pp) + break; + *p++ = ' '; + } + parse_and_run_string(str); free(str); - rcode = G.last_exitcode; } - return rcode; + return G.last_exitcode; } static int FAST_FUNC builtin_exec(char **argv) -- cgit v1.2.3-55-g6feb From 1fbb73fc4cee44f0768fbb09fe8f41a52d47ed3e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jul 2018 00:16:16 +0200 Subject: cp: add missing quote in config snippet Signed-off-by: Denys Vlasenko --- coreutils/cp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/cp.c b/coreutils/cp.c index b623aaf33..ae60623d3 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -26,7 +26,7 @@ //config: Also add support for --parents option. //config: //config:config FEATURE_CP_REFLINK -//config: bool "Enable --reflink[=auto] +//config: bool "Enable --reflink[=auto]" //config: default y //config: depends on FEATURE_CP_LONG_OPTIONS -- cgit v1.2.3-55-g6feb From b762c784caa78877a9949224af425e52db237beb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jul 2018 14:21:38 +0200 Subject: hush: improve ${var#...}, ${var:+...} and ${var/.../...} - handle quoting dollar_altvalue1 test partially fails: word splitting of unquoted ${var:+...} is not correct function old new delta encode_then_expand_vararg - 443 +443 expand_one_var 1599 1610 +11 parse_stream 2756 2753 -3 encode_string 250 242 -8 setup_heredoc 308 298 -10 expand_and_evaluate_arith 106 96 -10 encode_then_expand_string 142 126 -16 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/5 up/down: 454/-47) Total: 407 bytes Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/dollar_altvalue1.right | 16 ++ shell/ash_test/ash-quoting/dollar_altvalue1.tests | 16 ++ shell/ash_test/ash-quoting/dollar_repl_bash1.right | 14 ++ shell/ash_test/ash-quoting/dollar_repl_bash1.tests | 12 ++ shell/ash_test/ash-quoting/squote_in_varexp.right | 4 + shell/ash_test/ash-quoting/squote_in_varexp.tests | 4 + shell/ash_test/ash-quoting/squote_in_varexp2.right | 2 + shell/ash_test/ash-quoting/squote_in_varexp2.tests | 2 + shell/ash_test/ash-z_slow/many_ifs.tests | 4 +- shell/hush.c | 200 +++++++++++++++------ .../hush_test/hush-quoting/dollar_altvalue1.right | 16 ++ .../hush_test/hush-quoting/dollar_altvalue1.tests | 16 ++ .../hush_test/hush-quoting/dollar_repl_bash1.right | 14 ++ .../hush_test/hush-quoting/dollar_repl_bash1.tests | 12 ++ .../hush_test/hush-quoting/squote_in_varexp.right | 4 + .../hush_test/hush-quoting/squote_in_varexp.tests | 4 + .../hush_test/hush-quoting/squote_in_varexp2.right | 2 + .../hush_test/hush-quoting/squote_in_varexp2.tests | 2 + shell/hush_test/hush-z_slow/many_ifs.tests | 4 +- 19 files changed, 291 insertions(+), 57 deletions(-) create mode 100644 shell/ash_test/ash-quoting/dollar_altvalue1.right create mode 100755 shell/ash_test/ash-quoting/dollar_altvalue1.tests create mode 100644 shell/ash_test/ash-quoting/dollar_repl_bash1.right create mode 100755 shell/ash_test/ash-quoting/dollar_repl_bash1.tests create mode 100644 shell/hush_test/hush-quoting/dollar_altvalue1.right create mode 100755 shell/hush_test/hush-quoting/dollar_altvalue1.tests create mode 100644 shell/hush_test/hush-quoting/dollar_repl_bash1.right create mode 100755 shell/hush_test/hush-quoting/dollar_repl_bash1.tests diff --git a/shell/ash_test/ash-quoting/dollar_altvalue1.right b/shell/ash_test/ash-quoting/dollar_altvalue1.right new file mode 100644 index 000000000..5cd495d3b --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue1.right @@ -0,0 +1,16 @@ +Unquoted b c d +|b| +|c| +|d| +Unquoted 'b c' d +|b c| +|d| +Unquoted "b c" d +|b c| +|d| +Quoted b c d +|b c d| +Quoted 'b c' d +|'b c' d| +Quoted "b c" d +|b c d| diff --git a/shell/ash_test/ash-quoting/dollar_altvalue1.tests b/shell/ash_test/ash-quoting/dollar_altvalue1.tests new file mode 100755 index 000000000..f4dc8caec --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue1.tests @@ -0,0 +1,16 @@ +f() { for i; do echo "|$i|"; done; } +x=a + +echo Unquoted b c d +f ${x:+b c d} +echo Unquoted "'b c' d" +f ${x:+'b c' d} +echo Unquoted '"b c" d' +f ${x:+"b c" d} + +echo Quoted b c d +f "${x:+b c d}" +echo Quoted "'b c' d" +f "${x:+'b c' d}" +echo Quoted '"b c" d' +f "${x:+"b c" d}" diff --git a/shell/ash_test/ash-quoting/dollar_repl_bash1.right b/shell/ash_test/ash-quoting/dollar_repl_bash1.right new file mode 100644 index 000000000..f5e9309f4 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_bash1.right @@ -0,0 +1,14 @@ +|y| +|zx| +|y| +|zx| +|y zx| +|y zx| +|y| +|zy| +|z| +|y| +|zy| +|z| +|y zy z| +|y zy z| diff --git a/shell/ash_test/ash-quoting/dollar_repl_bash1.tests b/shell/ash_test/ash-quoting/dollar_repl_bash1.tests new file mode 100755 index 000000000..912635925 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_repl_bash1.tests @@ -0,0 +1,12 @@ +f() { for i; do echo "|$i|"; done; } +v=xx + +f ${v/'x'/"y z"} +f ${v/"x"/'y z'} +f "${v/'x'/"y z"}" +f "${v/"x"/'y z'}" + +f ${v//'x'/"y z"} +f ${v//"x"/'y z'} +f "${v//'x'/"y z"}" +f "${v//"x"/'y z'}" diff --git a/shell/ash_test/ash-quoting/squote_in_varexp.right b/shell/ash_test/ash-quoting/squote_in_varexp.right index a75c0bfd6..4a457021b 100644 --- a/shell/ash_test/ash-quoting/squote_in_varexp.right +++ b/shell/ash_test/ash-quoting/squote_in_varexp.right @@ -1,5 +1,9 @@ z z +z +z +y +y y y Ok:0 diff --git a/shell/ash_test/ash-quoting/squote_in_varexp.tests b/shell/ash_test/ash-quoting/squote_in_varexp.tests index a2d05a246..4afc52107 100755 --- a/shell/ash_test/ash-quoting/squote_in_varexp.tests +++ b/shell/ash_test/ash-quoting/squote_in_varexp.tests @@ -1,6 +1,10 @@ x=yz echo ${x#'y'} echo "${x#'y'}" +echo ${x#"y"} +echo "${x#"y"}" echo ${x%'z'} echo "${x%'z'}" +echo ${x%"z"} +echo "${x%"z"}" echo Ok:$? diff --git a/shell/ash_test/ash-quoting/squote_in_varexp2.right b/shell/ash_test/ash-quoting/squote_in_varexp2.right index 9d0add3c5..d03047024 100644 --- a/shell/ash_test/ash-quoting/squote_in_varexp2.right +++ b/shell/ash_test/ash-quoting/squote_in_varexp2.right @@ -1,3 +1,5 @@ Nothing: Nothing: +Nothing: +Nothing: Ok:0 diff --git a/shell/ash_test/ash-quoting/squote_in_varexp2.tests b/shell/ash_test/ash-quoting/squote_in_varexp2.tests index 806ad12b9..2797725cc 100755 --- a/shell/ash_test/ash-quoting/squote_in_varexp2.tests +++ b/shell/ash_test/ash-quoting/squote_in_varexp2.tests @@ -1,4 +1,6 @@ x='\\\\' printf Nothing:'%s\n' ${x#'\\\\'} printf Nothing:'%s\n' "${x#'\\\\'}" +printf Nothing:'%s\n' ${x#"\\\\\\\\"} +printf Nothing:'%s\n' "${x#"\\\\\\\\"}" echo Ok:$? diff --git a/shell/ash_test/ash-z_slow/many_ifs.tests b/shell/ash_test/ash-z_slow/many_ifs.tests index 1f5b1b3a6..cf9a89874 100755 --- a/shell/ash_test/ash-z_slow/many_ifs.tests +++ b/shell/ash_test/ash-z_slow/many_ifs.tests @@ -229,8 +229,8 @@ do '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; ' ') ;; *) x=$f2$d2$f3$d3 - x=${x# } #was x=${x#' '} hush needs fixing for this to work - x=${x% } #was x=${x%' '} + x=${x#' '} + x=${x%' '} split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" ;; esac diff --git a/shell/hush.c b/shell/hush.c index 9d3f06db0..415993e71 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4888,34 +4888,15 @@ static int parse_dollar(o_string *as_string, } #if BB_MMU -# if BASH_PATTERN_SUBST -#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ - encode_string(dest, input, dquote_end, process_bkslash) -# else -/* only ${var/pattern/repl} (its pattern part) needs additional mode */ -#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ +#define encode_string(as_string, dest, input, dquote_end) \ encode_string(dest, input, dquote_end) -# endif #define as_string NULL - -#else /* !MMU */ - -# if BASH_PATTERN_SUBST -/* all parameters are needed, no macro tricks */ -# else -#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ - encode_string(as_string, dest, input, dquote_end) -# endif #endif static int encode_string(o_string *as_string, o_string *dest, struct in_str *input, - int dquote_end, - int process_bkslash) + int dquote_end) { -#if !BASH_PATTERN_SUBST - const int process_bkslash = 1; -#endif int ch; int next; @@ -4938,7 +4919,7 @@ static int encode_string(o_string *as_string, } debug_printf_parse("\" ch=%c (%d) escape=%d\n", ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); - if (process_bkslash && ch == '\\') { + if (ch == '\\') { if (next == EOF) { /* Testcase: in interactive shell a file with * echo "unterminated string\ @@ -5447,7 +5428,7 @@ static struct pipe *parse_stream(char **pstring, } if (ctx.is_assignment == NOT_ASSIGNMENT) ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; - if (!encode_string(&ctx.as_string, &ctx.word, input, '"', /*process_bkslash:*/ 1)) + if (!encode_string(&ctx.as_string, &ctx.word, input, '"')) goto parse_error; ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; continue; /* get next char */ @@ -5744,16 +5725,8 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha * Returns malloced string. * As an optimization, we return NULL if expansion is not needed. */ -#if !BASH_PATTERN_SUBST -/* only ${var/pattern/repl} (its pattern part) needs additional mode */ -#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \ - encode_then_expand_string(str) -#endif -static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash) +static char *encode_then_expand_string(const char *str) { -#if !BASH_PATTERN_SUBST - enum { do_unbackslash = 1 }; -#endif char *exp_str; struct in_str input; o_string dest = NULL_O_STRING; @@ -5771,14 +5744,135 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int * echo $(($a + `echo 1`)) $((1 + $((2)) )) */ setup_string_in_str(&input, str); - encode_string(NULL, &dest, &input, EOF, process_bkslash); + encode_string(NULL, &dest, &input, EOF); //TODO: error check (encode_string returns 0 on error)? //bb_error_msg("'%s' -> '%s'", str, dest.data); + exp_str = expand_string_to_string(dest.data, + EXP_FLAG_ESC_GLOB_CHARS, + /*unbackslash:*/ 1 + ); + //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); + o_free_unsafe(&dest); + return exp_str; +} + +#if !BASH_PATTERN_SUBST +#define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \ + encode_then_expand_vararg(str, handle_squotes) +#endif +static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash) +{ +#if !BASH_PATTERN_SUBST + const int do_unbackslash = 0; +#endif + char *exp_str; + struct in_str input; + o_string dest = NULL_O_STRING; + + if (!strchr(str, '$') + && !strchr(str, '\\') + && !strchr(str, '\'') +//todo:better code + && !strchr(str, '"') +#if ENABLE_HUSH_TICK + && !strchr(str, '`') +#endif + ) { + return NULL; + } + + /* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}. + * These can contain single- and double-quoted strings, + * and treated as if the ARG string is initially unquoted. IOW: + * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be + * a dquoted string: "${var#"zz"}"), the difference only comes later + * (word splitting and globbing of the ${var...} result). + */ + + setup_string_in_str(&input, str); + o_addchr(&dest, '\0'); + dest.length = 0; + exp_str = NULL; + + for (;;) { + int ch; + int next; + + ch = i_getch(&input); + if (ch == EOF) { + if (dest.o_expflags) { /* EXP_FLAG_ESC_GLOB_CHARS set? */ + syntax_error_unterm_ch('"'); + goto ret; /* error */ + } + break; + } + debug_printf_parse("%s: ch=%c (%d) escape=%d\n", + __func__, ch, ch, !!dest.o_expflags); + if (ch == '\'' && handle_squotes && !dest.o_expflags) { +//quoting version of add_till_single_quote() (try to merge?): + for (;;) { + ch = i_getch(&input); + if (ch == EOF) { + syntax_error_unterm_ch('\''); + goto ret; /* error */ + } + if (ch == '\'') + break; + o_addqchr(&dest, ch); + } + continue; + } + if (ch == '"') { + dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; + continue; + } + if (ch == '\\') { + ch = i_getch(&input); + if (ch == EOF) { +//example? error message? syntax_error_unterm_ch('"'); + debug_printf_parse("%s: error: \\\n", __func__); + goto ret; + } + o_addqchr(&dest, ch); + continue; + } + next = '\0'; + if (ch != '\n') { + next = i_peek(&input); + } + if (ch == '$') { + if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { + debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); + goto ret; + } + continue; + } +#if ENABLE_HUSH_TICK + if (ch == '`') { + //unsigned pos = dest->length; + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + o_addchr(&dest, 0x80 | '`'); + if (!add_till_backquote(&dest, &input, + /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */ + ) + ) { + goto ret; /* error */ + } + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); + continue; + } +#endif + o_addQchr(&dest, ch); + } /* for (;;) */ + + debug_printf_parse("encode: '%s' -> '%s'\n", str, dest.data); exp_str = expand_string_to_string(dest.data, do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0, do_unbackslash ); - //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); + ret: + debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str); o_free_unsafe(&dest); return exp_str; } @@ -5793,7 +5887,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) math_state.lookupvar = get_local_var_value; math_state.setvar = set_local_var_from_halves; //math_state.endofname = endofname; - exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); + exp_str = encode_then_expand_string(arg); res = arith(&math_state, exp_str ? exp_str : arg); free(exp_str); if (errmsg_p) @@ -5869,7 +5963,6 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha char *to_be_freed; char *p; char *var; - char first_char; char exp_op; char exp_save = exp_save; /* for compiler */ char *exp_saveptr; /* points to expansion operator */ @@ -5883,10 +5976,10 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha var = arg; exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL; arg0 = arg[0]; - first_char = arg[0] = arg0 & 0x7f; + arg[0] = (arg0 & 0x7f); exp_op = 0; - if (first_char == '#' && arg[1] /* ${#...} but not ${#} */ + if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */ && (!exp_saveptr /* and ( not(${#...}) */ || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */ ) /* NB: skipping ^^^specvar check mishandles ${#::2} */ @@ -5897,7 +5990,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha } else { /* Maybe handle parameter expansion */ if (exp_saveptr /* if 2nd char is one of expansion operators */ - && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */ + && strchr(NUMERIC_SPECVARS_STR, arg[0]) /* 1st char is special variable */ ) { /* ${?:0}, ${#[:]%0} etc */ exp_saveptr = var + 1; @@ -5966,6 +6059,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha * Word is expanded to produce a glob pattern. * Then var's value is matched to it and matching part removed. */ +//FIXME: ${x#...${...}...} +//should evaluate inner ${...} even if x is "" and no shrinking of it is possible - +//inner ${...} may have side effects! if (val && val[0]) { char *t; char *exp_exp_word; @@ -5974,20 +6070,16 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha if (exp_op == *exp_word) /* ## or %% */ exp_word++; debug_printf_expand("expand: exp_word:'%s'\n", exp_word); - /* - * process_bkslash:1 unbackslash:1 breaks this: - * a='a\\'; echo ${a%\\\\} # correct output is: a - * process_bkslash:1 unbackslash:0 breaks this: - * a='a}'; echo ${a%\}} # correct output is: a - */ - exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); + exp_exp_word = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0); if (exp_exp_word) exp_word = exp_exp_word; - debug_printf_expand("expand: exp_exp_word:'%s'\n", exp_word); - /* HACK ALERT. We depend here on the fact that + debug_printf_expand("expand: exp_word:'%s'\n", exp_word); + /* + * HACK ALERT. We depend here on the fact that * G.global_argv and results of utoa and get_local_var_value * are actually in writable memory: - * scan_and_match momentarily stores NULs there. */ + * scan_and_match momentarily stores NULs there. + */ t = (char*)val; loc = scan_and_match(t, exp_word, scan_flags); debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc); @@ -6020,7 +6112,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha * (note that a*z _pattern_ is never globbed!) */ char *pattern, *repl, *t; - pattern = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0); + pattern = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0); if (!pattern) pattern = xstrdup(exp_word); debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern); @@ -6028,7 +6120,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha exp_word = p; p = strchr(p, SPECIAL_VAR_SYMBOL); *p = '\0'; - repl = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 1); + repl = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 1); debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl); /* HACK ALERT. We depend here on the fact that * G.global_argv and results of utoa and get_local_var_value @@ -6131,7 +6223,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, (exp_save == ':') ? "true" : "false", use_word); if (use_word) { - to_be_freed = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); +//FIXME: unquoted ${x:+"b c" d} and ${x:+'b c' d} should expand to two words +//currently it expands to three. + to_be_freed = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ !(arg0 & 0x80), /*unbackslash:*/ 0); if (to_be_freed) exp_word = to_be_freed; if (exp_op == '?') { @@ -6934,7 +7028,7 @@ static void setup_heredoc(struct redir_struct *redir) expanded = NULL; if (!(redir->rd_dup & HEREDOC_QUOTED)) { - expanded = encode_then_expand_string(heredoc, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); + expanded = encode_then_expand_string(heredoc); if (expanded) heredoc = expanded; } diff --git a/shell/hush_test/hush-quoting/dollar_altvalue1.right b/shell/hush_test/hush-quoting/dollar_altvalue1.right new file mode 100644 index 000000000..5cd495d3b --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue1.right @@ -0,0 +1,16 @@ +Unquoted b c d +|b| +|c| +|d| +Unquoted 'b c' d +|b c| +|d| +Unquoted "b c" d +|b c| +|d| +Quoted b c d +|b c d| +Quoted 'b c' d +|'b c' d| +Quoted "b c" d +|b c d| diff --git a/shell/hush_test/hush-quoting/dollar_altvalue1.tests b/shell/hush_test/hush-quoting/dollar_altvalue1.tests new file mode 100755 index 000000000..f4dc8caec --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue1.tests @@ -0,0 +1,16 @@ +f() { for i; do echo "|$i|"; done; } +x=a + +echo Unquoted b c d +f ${x:+b c d} +echo Unquoted "'b c' d" +f ${x:+'b c' d} +echo Unquoted '"b c" d' +f ${x:+"b c" d} + +echo Quoted b c d +f "${x:+b c d}" +echo Quoted "'b c' d" +f "${x:+'b c' d}" +echo Quoted '"b c" d' +f "${x:+"b c" d}" diff --git a/shell/hush_test/hush-quoting/dollar_repl_bash1.right b/shell/hush_test/hush-quoting/dollar_repl_bash1.right new file mode 100644 index 000000000..f5e9309f4 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_bash1.right @@ -0,0 +1,14 @@ +|y| +|zx| +|y| +|zx| +|y zx| +|y zx| +|y| +|zy| +|z| +|y| +|zy| +|z| +|y zy z| +|y zy z| diff --git a/shell/hush_test/hush-quoting/dollar_repl_bash1.tests b/shell/hush_test/hush-quoting/dollar_repl_bash1.tests new file mode 100755 index 000000000..912635925 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_repl_bash1.tests @@ -0,0 +1,12 @@ +f() { for i; do echo "|$i|"; done; } +v=xx + +f ${v/'x'/"y z"} +f ${v/"x"/'y z'} +f "${v/'x'/"y z"}" +f "${v/"x"/'y z'}" + +f ${v//'x'/"y z"} +f ${v//"x"/'y z'} +f "${v//'x'/"y z"}" +f "${v//"x"/'y z'}" diff --git a/shell/hush_test/hush-quoting/squote_in_varexp.right b/shell/hush_test/hush-quoting/squote_in_varexp.right index a75c0bfd6..4a457021b 100644 --- a/shell/hush_test/hush-quoting/squote_in_varexp.right +++ b/shell/hush_test/hush-quoting/squote_in_varexp.right @@ -1,5 +1,9 @@ z z +z +z +y +y y y Ok:0 diff --git a/shell/hush_test/hush-quoting/squote_in_varexp.tests b/shell/hush_test/hush-quoting/squote_in_varexp.tests index a2d05a246..4afc52107 100755 --- a/shell/hush_test/hush-quoting/squote_in_varexp.tests +++ b/shell/hush_test/hush-quoting/squote_in_varexp.tests @@ -1,6 +1,10 @@ x=yz echo ${x#'y'} echo "${x#'y'}" +echo ${x#"y"} +echo "${x#"y"}" echo ${x%'z'} echo "${x%'z'}" +echo ${x%"z"} +echo "${x%"z"}" echo Ok:$? diff --git a/shell/hush_test/hush-quoting/squote_in_varexp2.right b/shell/hush_test/hush-quoting/squote_in_varexp2.right index 9d0add3c5..d03047024 100644 --- a/shell/hush_test/hush-quoting/squote_in_varexp2.right +++ b/shell/hush_test/hush-quoting/squote_in_varexp2.right @@ -1,3 +1,5 @@ Nothing: Nothing: +Nothing: +Nothing: Ok:0 diff --git a/shell/hush_test/hush-quoting/squote_in_varexp2.tests b/shell/hush_test/hush-quoting/squote_in_varexp2.tests index 806ad12b9..2797725cc 100755 --- a/shell/hush_test/hush-quoting/squote_in_varexp2.tests +++ b/shell/hush_test/hush-quoting/squote_in_varexp2.tests @@ -1,4 +1,6 @@ x='\\\\' printf Nothing:'%s\n' ${x#'\\\\'} printf Nothing:'%s\n' "${x#'\\\\'}" +printf Nothing:'%s\n' ${x#"\\\\\\\\"} +printf Nothing:'%s\n' "${x#"\\\\\\\\"}" echo Ok:$? diff --git a/shell/hush_test/hush-z_slow/many_ifs.tests b/shell/hush_test/hush-z_slow/many_ifs.tests index 1f5b1b3a6..cf9a89874 100755 --- a/shell/hush_test/hush-z_slow/many_ifs.tests +++ b/shell/hush_test/hush-z_slow/many_ifs.tests @@ -229,8 +229,8 @@ do '') split "$d0$f1$d1$f2$d2$f3$d3" "[2]($f1)($f2)" "($f1)($f2)" ;; ' ') ;; *) x=$f2$d2$f3$d3 - x=${x# } #was x=${x#' '} hush needs fixing for this to work - x=${x% } #was x=${x%' '} + x=${x#' '} + x=${x%' '} split "$d0$f1$d1$f2$d2$f3$d3" "[3]($f1)($f2)($f3)" "($f1)($x)" ;; esac -- cgit v1.2.3-55-g6feb From 0d2e0de42bab54c31ba37f1c6fd10dcdc7008ccf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jul 2018 14:33:19 +0200 Subject: hush: faster/smaller code to check for presense of multiple chars in string Go over the string only once. function old new delta encode_then_expand_string 126 105 -21 encode_then_expand_vararg 443 399 -44 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-65) Total: -65 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 415993e71..238f997da 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5730,14 +5730,17 @@ static char *encode_then_expand_string(const char *str) char *exp_str; struct in_str input; o_string dest = NULL_O_STRING; + const char *cp; - if (!strchr(str, '$') - && !strchr(str, '\\') + cp = str; + for (;;) { + if (!*cp) return NULL; /* string has no special chars */ + if (*cp == '$') break; + if (*cp == '\\') break; #if ENABLE_HUSH_TICK - && !strchr(str, '`') + if (*cp == '`') break; #endif - ) { - return NULL; + cp++; } /* We need to expand. Example: @@ -5768,17 +5771,19 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int char *exp_str; struct in_str input; o_string dest = NULL_O_STRING; + const char *cp; - if (!strchr(str, '$') - && !strchr(str, '\\') - && !strchr(str, '\'') -//todo:better code - && !strchr(str, '"') + cp = str; + for (;;) { + if (!*cp) return NULL; /* string has no special chars */ + if (*cp == '$') break; + if (*cp == '\\') break; + if (*cp == '\'') break; + if (*cp == '"') break; #if ENABLE_HUSH_TICK - && !strchr(str, '`') + if (*cp == '`') break; #endif - ) { - return NULL; + cp++; } /* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}. -- cgit v1.2.3-55-g6feb From 4c201c00a3650cdacad5fc098ca255416687fb0f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jul 2018 15:04:17 +0200 Subject: whitespace fixes Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 2 +- libbb/nuke_str.c | 2 +- shell/hush.c | 6 +++--- shell/random.c | 12 ++++++------ util-linux/unshare.c | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f155d0908..319bcc263 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -737,7 +737,7 @@ static void install_links(const char *busybox, int use_symbolic_links, * busybox.h::bb_install_loc_t, or else... */ int (*lf)(const char *, const char *); char *fpc; - const char *appname = applet_names; + const char *appname = applet_names; unsigned i; int rc; diff --git a/libbb/nuke_str.c b/libbb/nuke_str.c index 240e68004..b5385e956 100644 --- a/libbb/nuke_str.c +++ b/libbb/nuke_str.c @@ -12,7 +12,7 @@ void FAST_FUNC nuke_str(char *str) { - if (str) { + if (str) { while (*str) *str++ = 0; /* or: memset(str, 0, strlen(str)); - not as small as above */ diff --git a/shell/hush.c b/shell/hush.c index 238f997da..7da8f334c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2470,7 +2470,7 @@ static void reinit_unicode_for_hush(void) */ if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV || ENABLE_UNICODE_USING_LOCALE - ) { + ) { const char *s = get_local_var_value("LC_ALL"); if (!s) s = get_local_var_value("LC_CTYPE"); if (!s) s = get_local_var_value("LANG"); @@ -5795,8 +5795,8 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int */ setup_string_in_str(&input, str); - o_addchr(&dest, '\0'); - dest.length = 0; + o_addchr(&dest, '\0'); + dest.length = 0; exp_str = NULL; for (;;) { diff --git a/shell/random.c b/shell/random.c index 5d3620516..56c7c5a3c 100644 --- a/shell/random.c +++ b/shell/random.c @@ -46,11 +46,11 @@ next_random(random_t *rnd) * Choices for a,b,c: 10,13,10; 8,9,22; 2,7,3; 23,3,24 * (given by algorithm author) */ - enum { - a = 2, - b = 7, - c = 3, - }; + enum { + a = 2, + b = 7, + c = 3, + }; uint32_t t; @@ -154,7 +154,7 @@ int main(int argc, char **argv) write(1, buf, sizeof(buf)); } - return 0; + return 0; } #endif diff --git a/util-linux/unshare.c b/util-linux/unshare.c index 7c295da1f..fffee28a0 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c @@ -73,7 +73,7 @@ #include "libbb.h" static void mount_or_die(const char *source, const char *target, - const char *fstype, unsigned long mountflags) + const char *fstype, unsigned long mountflags) { if (mount(source, target, fstype, mountflags, NULL)) { bb_perror_msg_and_die("can't mount %s on %s (flags:0x%lx)", -- cgit v1.2.3-55-g6feb From 8b08d5a502adec2067e3ebf7f27513f75b0b95e8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jul 2018 15:48:53 +0200 Subject: hush: smaller code to set o_string to "" function old new delta encode_then_expand_vararg 399 398 -1 parse_stream 2753 2748 -5 Signed-off-by: Denys Vlasenko --- shell/hush.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 7da8f334c..534fabbd0 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4997,8 +4997,7 @@ static struct pipe *parse_stream(char **pstring, /* If very first arg is "" or '', ctx.word.data may end up NULL. * Preventing this: */ - o_addchr(&ctx.word, '\0'); - ctx.word.length = 0; + ctx.word.data = xzalloc(1); /* start as "", not as NULL */ /* We used to separate words on $IFS here. This was wrong. * $IFS is used only for word splitting when $var is expanded, @@ -5795,8 +5794,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int */ setup_string_in_str(&input, str); - o_addchr(&dest, '\0'); - dest.length = 0; + dest.data = xzalloc(1); /* start as "", not as NULL */ exp_str = NULL; for (;;) { -- cgit v1.2.3-55-g6feb From 2e71101e31b8b421cee0107c4136d68b65e3a5d8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jul 2018 16:02:25 +0200 Subject: hush: fix 'x=; echo ${x:-"$@"}' producing 'BUG in varexp2' message function old new delta expand_string_to_string 126 128 +2 Signed-off-by: Denys Vlasenko --- shell/hush.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 534fabbd0..da10a09a8 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6529,13 +6529,20 @@ static char *expand_string_to_string(const char *str, int EXP_flags, int do_unba argv[0] = (char*)str; argv[1] = NULL; list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD); - if (HUSH_DEBUG) - if (!list[0] || list[1]) - bb_error_msg_and_die("BUG in varexp2"); - /* actually, just move string 2*sizeof(char*) bytes back */ - overlapping_strcpy((char*)list, list[0]); - if (do_unbackslash) - unbackslash((char*)list); + if (!list[0]) { + /* Example where it happens: + * x=; echo ${x:-"$@"} + */ + ((char*)list)[0] = '\0'; + } else { + if (HUSH_DEBUG) + if (list[1]) + bb_error_msg_and_die("BUG in varexp2"); + /* actually, just move string 2*sizeof(char*) bytes back */ + overlapping_strcpy((char*)list, list[0]); + if (do_unbackslash) + unbackslash((char*)list); + } debug_printf_expand("string_to_string=>'%s'\n", (char*)list); return (char*)list; } -- cgit v1.2.3-55-g6feb From e36a5894bd24a28b3529998bb7d0f87d7f5eb61b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jul 2018 16:12:23 +0200 Subject: hush: reduce indentation, no code changes Signed-off-by: Denys Vlasenko --- shell/hush.c | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index da10a09a8..92c79b8b6 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2423,35 +2423,33 @@ static void set_vars_and_save_old(char **strings) char *eq; eq = strchr(*s, '='); - if (eq) { - var_pp = get_ptr_to_local_var(*s, eq - *s); - if (var_pp) { - var_p = *var_pp; - if (var_p->flg_read_only) { - char **p; - bb_error_msg("%s: readonly variable", *s); - /* - * "VAR=V BLTIN" unsets VARs after BLTIN completes. - * If VAR is readonly, leaving it in the list - * after asssignment error (msg above) - * causes doubled error message later, on unset. - */ - debug_printf_env("removing/freeing '%s' element\n", *s); - free(*s); - p = s; - do { *p = p[1]; p++; } while (*p); - goto next; - } - /* below, set_local_var() with nest level will - * "shadow" (remove) this variable from - * global linked list. - */ - } - debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level); - set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT); - } else if (HUSH_DEBUG) { + if (HUSH_DEBUG && !eq) bb_error_msg_and_die("BUG in varexp4"); + var_pp = get_ptr_to_local_var(*s, eq - *s); + if (var_pp) { + var_p = *var_pp; + if (var_p->flg_read_only) { + char **p; + bb_error_msg("%s: readonly variable", *s); + /* + * "VAR=V BLTIN" unsets VARs after BLTIN completes. + * If VAR is readonly, leaving it in the list + * after asssignment error (msg above) + * causes doubled error message later, on unset. + */ + debug_printf_env("removing/freeing '%s' element\n", *s); + free(*s); + p = s; + do { *p = p[1]; p++; } while (*p); + goto next; + } + /* below, set_local_var() with nest level will + * "shadow" (remove) this variable from + * global linked list. + */ } + debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level); + set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT); s++; next: ; } -- cgit v1.2.3-55-g6feb From 116b50a5c1ea9d80d60641f2df2b61473b57fe47 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jul 2018 11:16:53 +0200 Subject: hush: make expand_vars_to_list() a bit more sane function old new delta append_str_maybe_ifs_split - 64 +64 expand_vars_to_list 1167 1139 -28 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 64/-28) Total: 36 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 60 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 92c79b8b6..b738d2fd8 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5955,6 +5955,24 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c } #endif /* BASH_PATTERN_SUBST */ +static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n, + int first_ch, const char *val) +{ + if (!(first_ch & 0x80)) { /* unquoted $VAR */ + debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, + !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); + if (val && val[0]) + n = expand_on_ifs(ended_in_ifs, output, n, val); + } else { /* quoted "$VAR" */ + output->has_quoted_part = 1; + debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, + !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); + if (val && val[0]) + o_addQstr(output, val); + } + return n; +} + /* Helper: * Handles varname... construct. */ @@ -6290,11 +6308,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { char first_ch; - char *to_be_freed = NULL; const char *val = NULL; -#if ENABLE_HUSH_TICK - o_string subst_result = NULL_O_STRING; -#endif #if ENABLE_FEATURE_SH_MATH char arith_buf[sizeof(arith_t)*3 + 2]; #endif @@ -6382,7 +6396,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) val = SPECIAL_VAR_SYMBOL_STR; break; #if ENABLE_HUSH_TICK - case '`': /* `cmd */ + case '`': { /* `cmd */ + o_string subst_result = NULL_O_STRING; + *p = '\0'; /* replace trailing */ arg++; /* Can't just stuff it into output o_string, @@ -6392,8 +6408,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) G.last_exitcode = process_command_subs(&subst_result, arg); G.expand_exitcode = G.last_exitcode; debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); - val = subst_result.data; - goto store_val; + n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, subst_result.data); + o_free_unsafe(&subst_result); + goto restore; + } #endif #if ENABLE_FEATURE_SH_MATH case '+': { /* +cmd */ @@ -6409,37 +6427,23 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) break; } #endif - default: + default: { + char *to_be_freed; val = expand_one_var(&to_be_freed, arg, &p); - IF_HUSH_TICK(store_val:) - if (!(first_ch & 0x80)) { /* unquoted $VAR */ - debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, - !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); - if (val && val[0]) { - n = expand_on_ifs(&ended_in_ifs, output, n, val); - val = NULL; - } - } else { /* quoted $VAR, val will be appended below */ - output->has_quoted_part = 1; - debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, - !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); - } - break; + n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, val); + free(to_be_freed); + goto restore; + } /* default: */ } /* switch (char after ) */ if (val && val[0]) { o_addQstr(output, val); } - free(to_be_freed); - + restore: /* Restore NULL'ed SPECIAL_VAR_SYMBOL. * Do the check to avoid writing to a const string. */ if (*p != SPECIAL_VAR_SYMBOL) *p = SPECIAL_VAR_SYMBOL; - -#if ENABLE_HUSH_TICK - o_free(&subst_result); -#endif arg = ++p; } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ -- cgit v1.2.3-55-g6feb From 8a6a4615048d51af0e765e893211073faa7951cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jul 2018 12:14:47 +0200 Subject: hush: propagate (output,n) parameters into expand_one_var() This is necessary since expand_one_var() for ${var:+ARG} must create more than one output word, and thus can't simply return a char*. function old new delta expand_one_var 1610 1643 +33 expand_vars_to_list 1139 1125 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 33/-14) Total: 19 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index b738d2fd8..ea259f53c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5976,7 +5976,8 @@ static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n /* Helper: * Handles varname... construct. */ -static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp) +static NOINLINE int expand_one_var(o_string *output, + int *ended_in_ifs, int n, int first_ch, char *arg, char **pp) { const char *val; char *to_be_freed; @@ -6038,9 +6039,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha /* Look up the variable in question */ if (isdigit(var[0])) { /* parse_dollar should have vetted var for us */ - int n = xatoi_positive(var); - if (n < G.global_argc) - val = G.global_argv[n]; + int nn = xatoi_positive(var); + if (nn < G.global_argc) + val = G.global_argv[nn]; /* else val remains NULL: $N with too big N */ } else { switch (var[0]) { @@ -6236,6 +6237,34 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha * Colon forms (${var:-word}, ${var:=word} etc) do the same, * but also treat null var as if it is unset. */ +/* + * Word-splitting and squote behavior of bash: + * $ f() { for i; do echo "|$i|"; done; }; + * + * $ x=; f ${x:?'x y' z} + * bash: x: x y z + * $ x=; f "${x:?'x y' z}" + * bash: x: x y z # dash prints: dash: x: 'x y' z + * + * $ x=; f ${x:='x y' z} + * |x| + * |y| + * |z| + * $ x=; f "${x:='x y' z}" + * |'x y' z| + * + * $ x=x; f ${x:+'x y' z} + * |x y| + * |z| + * $ x=x; f "${x:+'x y' z}" + * |'x y' z| + * + * $ x=; f ${x:-'x y' z} + * |x y| + * |z| + * $ x=; f "${x:-'x y' z}" + * |'x y' z| + */ int use_word = (!val || ((exp_save == ':') && !val[0])); if (exp_op == '+') use_word = !use_word; @@ -6244,7 +6273,10 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha if (use_word) { //FIXME: unquoted ${x:+"b c" d} and ${x:+'b c' d} should expand to two words //currently it expands to three. - to_be_freed = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ !(arg0 & 0x80), /*unbackslash:*/ 0); + to_be_freed = encode_then_expand_vararg(exp_word, + /*handle_squotes:*/ !(arg0 & 0x80), + /*unbackslash:*/ 0 + ); if (to_be_freed) exp_word = to_be_freed; if (exp_op == '?') { @@ -6258,6 +6290,11 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ ); //TODO: how interactive bash aborts expansion mid-command? +//It aborts the entire line: +// $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO +// bash: x: x y z +// $ +// ("echo YO" is not executed, neither the f function call) } else { val = exp_word; } @@ -6280,10 +6317,12 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha } /* if (exp_op) */ arg[0] = arg0; - *pp = p; - *to_be_freed_pp = to_be_freed; - return val; + + n = append_str_maybe_ifs_split(output, ended_in_ifs, n, first_ch, val); + + free(to_be_freed); + return n; } /* Expand all variable references in given string, adding words to list[] @@ -6427,13 +6466,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) break; } #endif - default: { - char *to_be_freed; - val = expand_one_var(&to_be_freed, arg, &p); - n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, val); - free(to_be_freed); + default: + n = expand_one_var(output, &ended_in_ifs, n, first_ch, arg, &p); goto restore; - } /* default: */ } /* switch (char after ) */ if (val && val[0]) { -- cgit v1.2.3-55-g6feb From 168579a34c6fc6c2f2cd20256367ceb61f50bf68 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jul 2018 13:45:54 +0200 Subject: hush: store "ended_in_ifs" flag in o_string This simplifies function parameter passing. function old new delta expand_one_var 1643 1639 -4 append_str_maybe_ifs_split 64 52 -12 expand_vars_to_list 1125 1112 -13 expand_on_ifs 361 345 -16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-45) Total: -45 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index ea259f53c..2d4e3fa66 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -534,6 +534,7 @@ typedef struct o_string { * possibly empty one: word"", wo''rd etc. */ smallint has_quoted_part; smallint has_empty_slot; + smallint ended_in_ifs; } o_string; enum { EXP_FLAG_SINGLEWORD = 0x80, /* must be 0x80 */ @@ -5643,10 +5644,10 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len /* Store given string, finalizing the word and starting new one whenever * we encounter IFS char(s). This is used for expanding variable values. * End-of-string does NOT finalize word: think about 'echo -$VAR-'. - * Return in *ended_with_ifs: + * Return in output->ended_in_ifs: * 1 - ended with IFS char, else 0 (this includes case of empty str). */ -static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str) +static int expand_on_ifs(o_string *output, int n, const char *str) { int last_is_ifs = 0; @@ -5709,8 +5710,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha } } - if (ended_with_ifs) - *ended_with_ifs = last_is_ifs; + output->ended_in_ifs = last_is_ifs; debug_print_list("expand_on_ifs[1]", output, n); return n; } @@ -5955,14 +5955,14 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c } #endif /* BASH_PATTERN_SUBST */ -static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n, +static int append_str_maybe_ifs_split(o_string *output, int n, int first_ch, const char *val) { if (!(first_ch & 0x80)) { /* unquoted $VAR */ debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); if (val && val[0]) - n = expand_on_ifs(ended_in_ifs, output, n, val); + n = expand_on_ifs(output, n, val); } else { /* quoted "$VAR" */ output->has_quoted_part = 1; debug_printf_expand("quoted '%s', output->o_escape:%d\n", val, @@ -5977,7 +5977,7 @@ static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n * Handles varname... construct. */ static NOINLINE int expand_one_var(o_string *output, - int *ended_in_ifs, int n, int first_ch, char *arg, char **pp) + int n, int first_ch, char *arg, char **pp) { const char *val; char *to_be_freed; @@ -6242,9 +6242,9 @@ static NOINLINE int expand_one_var(o_string *output, * $ f() { for i; do echo "|$i|"; done; }; * * $ x=; f ${x:?'x y' z} - * bash: x: x y z + * bash: x: x y z #BUG: does not abort, ${} results in empty expansion * $ x=; f "${x:?'x y' z}" - * bash: x: x y z # dash prints: dash: x: 'x y' z + * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in "" * * $ x=; f ${x:='x y' z} * |x| @@ -6290,7 +6290,7 @@ static NOINLINE int expand_one_var(o_string *output, /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ ); //TODO: how interactive bash aborts expansion mid-command? -//It aborts the entire line: +//It aborts the entire line, returns to prompt: // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO // bash: x: x y z // $ @@ -6319,7 +6319,7 @@ static NOINLINE int expand_one_var(o_string *output, arg[0] = arg0; *pp = p; - n = append_str_maybe_ifs_split(output, ended_in_ifs, n, first_ch, val); + n = append_str_maybe_ifs_split(output, n, first_ch, val); free(to_be_freed); return n; @@ -6336,9 +6336,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) * expansion of right-hand side of assignment == 1-element expand. */ char cant_be_null = 0; /* only bit 0x80 matters */ - int ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ char *p; + output->ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ + debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); debug_print_list("expand_vars_to_list", output, n); @@ -6352,10 +6353,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) char arith_buf[sizeof(arith_t)*3 + 2]; #endif - if (ended_in_ifs) { + if (output->ended_in_ifs) { o_addchr(output, '\0'); n = o_save_ptr(output, n); - ended_in_ifs = 0; + output->ended_in_ifs = 0; } o_addblock(output, arg, p - arg); @@ -6386,7 +6387,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */ if (!(first_ch & 0x80)) { /* unquoted $* or $@ */ while (G.global_argv[i]) { - n = expand_on_ifs(NULL, output, n, G.global_argv[i]); + n = expand_on_ifs(output, n, G.global_argv[i]); debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1); if (G.global_argv[i++][0] && G.global_argv[i]) { /* this argv[] is not empty and not last: @@ -6447,7 +6448,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) G.last_exitcode = process_command_subs(&subst_result, arg); G.expand_exitcode = G.last_exitcode; debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); - n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, subst_result.data); + n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data); o_free_unsafe(&subst_result); goto restore; } @@ -6467,7 +6468,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) } #endif default: - n = expand_one_var(output, &ended_in_ifs, n, first_ch, arg, &p); + n = expand_one_var(output, n, first_ch, arg, &p); goto restore; } /* switch (char after ) */ @@ -6483,7 +6484,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ if (arg[0]) { - if (ended_in_ifs) { + if (output->ended_in_ifs) { o_addchr(output, '\0'); n = o_save_ptr(output, n); } -- cgit v1.2.3-55-g6feb From 18e8b6129298c02f7b5ccc17fee6bccc01a8968f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 14:24:56 +0200 Subject: hush: remove pointless "next" var, simplify expand_vars_to_list() function old new delta o_addstr - 26 +26 expand_vars_to_list 1112 1117 +5 encode_then_expand_vararg 398 382 -16 parse_dollar 779 762 -17 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/2 up/down: 31/-33) Total: -2 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 2d4e3fa66..fca67dc17 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -475,6 +475,7 @@ #endif #define SPECIAL_VAR_SYMBOL_STR "\3" +#define SPECIAL_VAR_SYMBOL_CHR '\3' #define SPECIAL_VAR_SYMBOL 3 /* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */ #define SPECIAL_VAR_QUOTED_SVS 1 @@ -5797,7 +5798,6 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int for (;;) { int ch; - int next; ch = i_getch(&input); if (ch == EOF) { @@ -5837,10 +5837,6 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int o_addqchr(&dest, ch); continue; } - next = '\0'; - if (ch != '\n') { - next = i_peek(&input); - } if (ch == '$') { if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) { debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); @@ -5956,7 +5952,7 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c #endif /* BASH_PATTERN_SUBST */ static int append_str_maybe_ifs_split(o_string *output, int n, - int first_ch, const char *val) + int first_ch, const char *val) { if (!(first_ch & 0x80)) { /* unquoted $VAR */ debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val, @@ -6348,7 +6344,6 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { char first_ch; - const char *val = NULL; #if ENABLE_FEATURE_SH_MATH char arith_buf[sizeof(arith_t)*3 + 2]; #endif @@ -6424,19 +6419,23 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) } break; } - case SPECIAL_VAR_SYMBOL: /* */ + case SPECIAL_VAR_SYMBOL: { + /* */ /* "Empty variable", used to make "" etc to not disappear */ output->has_quoted_part = 1; - arg++; cant_be_null = 0x80; + arg++; break; + } case SPECIAL_VAR_QUOTED_SVS: /* */ + /* "^C variable", represents literal ^C char (possible in scripts) */ + o_addchr(output, SPECIAL_VAR_SYMBOL_CHR); arg++; - val = SPECIAL_VAR_SYMBOL_STR; break; #if ENABLE_HUSH_TICK - case '`': { /* `cmd */ + case '`': { + /* `cmd */ o_string subst_result = NULL_O_STRING; *p = '\0'; /* replace trailing */ @@ -6450,11 +6449,12 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data); o_free_unsafe(&subst_result); - goto restore; + break; } #endif #if ENABLE_FEATURE_SH_MATH - case '+': { /* +cmd */ + case '+': { + /* +arith */ arith_t res; arg++; /* skip '+' */ @@ -6463,19 +6463,16 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) res = expand_and_evaluate_arith(arg, NULL); debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res); sprintf(arith_buf, ARITH_FMT, res); - val = arith_buf; + o_addstr(output, arith_buf); break; } #endif default: + /* varname[ops] */ n = expand_one_var(output, n, first_ch, arg, &p); - goto restore; + break; } /* switch (char after ) */ - if (val && val[0]) { - o_addQstr(output, val); - } - restore: /* Restore NULL'ed SPECIAL_VAR_SYMBOL. * Do the check to avoid writing to a const string. */ if (*p != SPECIAL_VAR_SYMBOL) -- cgit v1.2.3-55-g6feb From 57235beb696a7dbdb48751b9721c4c025127ae96 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 14:45:12 +0200 Subject: hush: expand_vars_to_list() should not assume it starts new word function old new delta expand_variables 112 115 +3 expand_vars_to_list 1117 1108 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 3/-9) Total: -6 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index fca67dc17..b8af1b088 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -3343,7 +3343,6 @@ static char **o_finalize_list(o_string *o, int n) char **list; int string_start; - n = o_save_ptr(o, n); /* force growth for list[n] if necessary */ if (DEBUG_EXPAND) debug_print_list("finalized", o, n); debug_printf_expand("finalized n:%d\n", n); @@ -6334,12 +6333,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) char cant_be_null = 0; /* only bit 0x80 matters */ char *p; - output->ended_in_ifs = 0; /* did last unquoted expansion end with IFS chars? */ - debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg, !!(output->o_expflags & EXP_FLAG_SINGLEWORD)); - debug_print_list("expand_vars_to_list", output, n); - n = o_save_ptr(output, n); debug_print_list("expand_vars_to_list[0]", output, n); while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) { @@ -6512,9 +6507,16 @@ static char **expand_variables(char **argv, unsigned expflags) output.o_expflags = expflags; n = 0; - while (*argv) { - n = expand_vars_to_list(&output, n, *argv); - argv++; + for (;;) { + /* go to next list[n] */ + output.ended_in_ifs = 0; + n = o_save_ptr(&output, n); + + if (!*argv) + break; + + /* expand argv[i] */ + n = expand_vars_to_list(&output, n, *argv++); } debug_print_list("expand_variables", &output, n); -- cgit v1.2.3-55-g6feb From 294eb4612cd668521faa48711297196f00af61d9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 16:18:59 +0200 Subject: hush: fix word splitting in ${v:+ARG} - dollar_altvalue1 test ash might be a bit buggy, need to investigate dollar_altvalue9 test function old new delta expand_one_var 1639 2236 +597 expand_variables 112 128 +16 expand_vars_to_list 1117 1097 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 613/-20) Total: 593 bytes Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/dollar_altvalue9.right | 24 ++ shell/ash_test/ash-quoting/dollar_altvalue9.tests | 17 ++ shell/hush.c | 263 ++++++++++++++++----- .../hush_test/hush-quoting/dollar_altvalue9.right | 24 ++ .../hush_test/hush-quoting/dollar_altvalue9.tests | 17 ++ 5 files changed, 284 insertions(+), 61 deletions(-) create mode 100644 shell/ash_test/ash-quoting/dollar_altvalue9.right create mode 100755 shell/ash_test/ash-quoting/dollar_altvalue9.tests create mode 100644 shell/hush_test/hush-quoting/dollar_altvalue9.right create mode 100755 shell/hush_test/hush-quoting/dollar_altvalue9.tests diff --git a/shell/ash_test/ash-quoting/dollar_altvalue9.right b/shell/ash_test/ash-quoting/dollar_altvalue9.right new file mode 100644 index 000000000..fc6c2697c --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue9.right @@ -0,0 +1,24 @@ +Unquoted 1: +|a| +|x y| +|1| +|2| +|1 2| +|A| +|B| +|C D| +|zb| +Quoted 1: +|a 'x y' 1 2 '' 1 2 A B C D zb| +Unquoted 2: +|ax y| +|1| +|2| +|1 2| +|A| +|B| +|C D| +|z| +|b| +Quoted 2: +|a 'x y' 1 2 '' 1 2 A B C D z b| diff --git a/shell/ash_test/ash-quoting/dollar_altvalue9.tests b/shell/ash_test/ash-quoting/dollar_altvalue9.tests new file mode 100755 index 000000000..27a6f4f3c --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue9.tests @@ -0,0 +1,17 @@ +f() { for i; do echo "|$i|"; done; } + +echo Unquoted 1: +x='1 2'; f a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b +echo Quoted 1: +x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b" + +echo Unquoted 2: +x='1 2'; f a${x:+'x y' $x '' "$x" `echo A B` "`echo C D`" z }b +echo Quoted 2: +x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z }b" + +#echo Unquoted 3: +#e= +#x='1 2'; f a${x:+'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b +#echo Quoted 3: +#x='1 2'; f "a${x:+ 'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b" diff --git a/shell/hush.c b/shell/hush.c index b8af1b088..fc77b89fc 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5873,6 +5873,138 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int return exp_str; } +static int expand_vars_to_list(o_string *output, int n, char *arg); + +static int encode_then_append_var_plusminus(o_string *output, int n, + const char *str, int dquoted) +{ + struct in_str input; + o_string dest = NULL_O_STRING; + +#if 0 //todo? + const char *cp; + cp = str; + for (;;) { + if (!*cp) return NULL; /* string has no special chars */ + if (*cp == '$') break; + if (*cp == '\\') break; + if (*cp == '\'') break; + if (*cp == '"') break; +#if ENABLE_HUSH_TICK + if (*cp == '`') break; +#endif + cp++; + } +#endif + + /* Expanding ARG in ${var+ARG}, ${var-ARG} */ + + setup_string_in_str(&input, str); + + for (;;) { + int ch; + + ch = i_getch(&input); + debug_printf_parse("%s: ch=%c (%d) escape=%x\n", + __func__, ch, ch, dest.o_expflags); + + if (!dest.o_expflags) { + if (ch == EOF) + break; + if (!dquoted && strchr(G.ifs, ch)) { + /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word. + * do not assume we are at the start of the word (PREFIX above). + */ + if (dest.data) { + n = expand_vars_to_list(output, n, dest.data); + o_free(&dest); + o_addchr(output, '\0'); + n = o_save_ptr(output, n); /* create next word */ + } else + if (output->length != o_get_last_ptr(output, n) + || output->has_quoted_part + ) { + /* For these cases: + * f() { for i; do echo "|$i|"; done; }; x=x + * f a${x:+ }b # 1st condition + * |a| + * |b| + * f ""${x:+ }b # 2nd condition + * || + * |b| + */ + o_addchr(output, '\0'); + n = o_save_ptr(output, n); /* create next word */ + } + continue; + } + if (!dquoted && ch == '\'') { +//quoting version of add_till_single_quote() (try to merge?): + for (;;) { + ch = i_getch(&input); + if (ch == EOF) { + syntax_error_unterm_ch('\''); + goto ret; /* error */ + } + if (ch == '\'') + break; + o_addqchr(&dest, ch); + } + continue; + } + } + if (ch == EOF) { + syntax_error_unterm_ch('"'); + goto ret; /* error */ + } + if (ch == '"') { + dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; + continue; + } + if (ch == '\\') { + ch = i_getch(&input); + if (ch == EOF) { +//example? error message? syntax_error_unterm_ch('"'); + debug_printf_parse("%s: error: \\\n", __func__); + goto ret; + } + o_addqchr(&dest, ch); + continue; + } + if (ch == '$') { + if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ (dest.o_expflags || dquoted) ? 0x80 : 0)) { + debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__); + goto ret; + } + continue; + } +#if ENABLE_HUSH_TICK + if (ch == '`') { + //unsigned pos = dest->length; + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + o_addchr(&dest, (dest.o_expflags || dquoted) ? 0x80 | '`' : '`'); + if (!add_till_backquote(&dest, &input, + /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */ + ) + ) { + goto ret; /* error */ + } + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); + continue; + } +#endif + o_addQchr(&dest, ch); + } /* for (;;) */ + + if (dest.data) { + n = expand_vars_to_list(output, n, dest.data); + } + ret: + o_free_unsafe(&dest); + return n; +} + #if ENABLE_FEATURE_SH_MATH static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) { @@ -6231,78 +6363,86 @@ static NOINLINE int expand_one_var(o_string *output, * * Colon forms (${var:-word}, ${var:=word} etc) do the same, * but also treat null var as if it is unset. + * + * Word-splitting and single quote behavior: + * + * $ f() { for i; do echo "|$i|"; done; }; + * + * $ x=; f ${x:?'x y' z} + * bash: x: x y z #BUG: does not abort, ${} results in empty expansion + * $ x=; f "${x:?'x y' z}" + * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in "" + * + * $ x=; f ${x:='x y' z} + * |x| + * |y| + * |z| + * $ x=; f "${x:='x y' z}" + * |'x y' z| + * + * $ x=x; f ${x:+'x y' z}| + * |x y| + * |z| + * $ x=x; f "${x:+'x y' z}" + * |'x y' z| + * + * $ x=; f ${x:-'x y' z} + * |x y| + * |z| + * $ x=; f "${x:-'x y' z}" + * |'x y' z| */ -/* - * Word-splitting and squote behavior of bash: - * $ f() { for i; do echo "|$i|"; done; }; - * - * $ x=; f ${x:?'x y' z} - * bash: x: x y z #BUG: does not abort, ${} results in empty expansion - * $ x=; f "${x:?'x y' z}" - * bash: x: x y z # dash prints: dash: x: 'x y' z #BUG: does not abort, ${} results in "" - * - * $ x=; f ${x:='x y' z} - * |x| - * |y| - * |z| - * $ x=; f "${x:='x y' z}" - * |'x y' z| - * - * $ x=x; f ${x:+'x y' z} - * |x y| - * |z| - * $ x=x; f "${x:+'x y' z}" - * |'x y' z| - * - * $ x=; f ${x:-'x y' z} - * |x y| - * |z| - * $ x=; f "${x:-'x y' z}" - * |'x y' z| - */ int use_word = (!val || ((exp_save == ':') && !val[0])); if (exp_op == '+') use_word = !use_word; debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, (exp_save == ':') ? "true" : "false", use_word); if (use_word) { -//FIXME: unquoted ${x:+"b c" d} and ${x:+'b c' d} should expand to two words -//currently it expands to three. - to_be_freed = encode_then_expand_vararg(exp_word, - /*handle_squotes:*/ !(arg0 & 0x80), - /*unbackslash:*/ 0 - ); - if (to_be_freed) - exp_word = to_be_freed; - if (exp_op == '?') { - /* mimic bash message */ - msg_and_die_if_script("%s: %s", - var, - exp_word[0] - ? exp_word - : "parameter null or not set" - /* ash has more specific messages, a-la: */ - /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ + if (exp_op == '+' || exp_op == '-') { + /* ${var+word} - use alternative value */ + /* ${var-word} - use default value */ + n = encode_then_append_var_plusminus(output, n, exp_word, + /*dquoted:*/ (arg0 & 0x80) ); + val = NULL; + } else { + /* ${var?word} - indicate error if unset */ + /* ${var=word} - assign and use default value */ + to_be_freed = encode_then_expand_vararg(exp_word, + /*handle_squotes:*/ !(arg0 & 0x80), + /*unbackslash:*/ 0 + ); + if (to_be_freed) + exp_word = to_be_freed; + if (exp_op == '?') { + /* mimic bash message */ + msg_and_die_if_script("%s: %s", + var, + exp_word[0] + ? exp_word + : "parameter null or not set" + /* ash has more specific messages, a-la: */ + /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/ + ); //TODO: how interactive bash aborts expansion mid-command? //It aborts the entire line, returns to prompt: // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO // bash: x: x y z // $ // ("echo YO" is not executed, neither the f function call) - } else { - val = exp_word; - } - - if (exp_op == '=') { - /* ${var=[word]} or ${var:=[word]} */ - if (isdigit(var[0]) || var[0] == '#') { - /* mimic bash message */ - msg_and_die_if_script("$%s: cannot assign in this way", var); - val = NULL; } else { - char *new_var = xasprintf("%s=%s", var, val); - set_local_var(new_var, /*flag:*/ 0); + val = exp_word; + } + if (exp_op == '=') { + /* ${var=[word]} or ${var:=[word]} */ + if (isdigit(var[0]) || var[0] == '#') { + /* mimic bash message */ + msg_and_die_if_script("$%s: cannot assign in this way", var); + val = NULL; + } else { + char *new_var = xasprintf("%s=%s", var, val); + set_local_var(new_var, /*flag:*/ 0); + } } } } @@ -6482,8 +6622,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) } debug_print_list("expand_vars_to_list[a]", output, n); /* this part is literal, and it was already pre-quoted - * if needed (much earlier), do not use o_addQstr here! */ - o_addstr_with_NUL(output, arg); + * if needed (much earlier), do not use o_addQstr here! + */ + o_addstr(output, arg); debug_print_list("expand_vars_to_list[b]", output, n); } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ && !(cant_be_null & 0x80) /* and all vars were not quoted. */ @@ -6491,8 +6632,6 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) n--; /* allow to reuse list[n] later without re-growth */ output->has_empty_slot = 1; - } else { - o_addchr(output, '\0'); } return n; @@ -6517,6 +6656,8 @@ static char **expand_variables(char **argv, unsigned expflags) /* expand argv[i] */ n = expand_vars_to_list(&output, n, *argv++); + /* if (!output->has_empty_slot) -- need this?? */ + o_addchr(&output, '\0'); } debug_print_list("expand_variables", &output, n); diff --git a/shell/hush_test/hush-quoting/dollar_altvalue9.right b/shell/hush_test/hush-quoting/dollar_altvalue9.right new file mode 100644 index 000000000..fc6c2697c --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue9.right @@ -0,0 +1,24 @@ +Unquoted 1: +|a| +|x y| +|1| +|2| +|1 2| +|A| +|B| +|C D| +|zb| +Quoted 1: +|a 'x y' 1 2 '' 1 2 A B C D zb| +Unquoted 2: +|ax y| +|1| +|2| +|1 2| +|A| +|B| +|C D| +|z| +|b| +Quoted 2: +|a 'x y' 1 2 '' 1 2 A B C D z b| diff --git a/shell/hush_test/hush-quoting/dollar_altvalue9.tests b/shell/hush_test/hush-quoting/dollar_altvalue9.tests new file mode 100755 index 000000000..27a6f4f3c --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue9.tests @@ -0,0 +1,17 @@ +f() { for i; do echo "|$i|"; done; } + +echo Unquoted 1: +x='1 2'; f a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b +echo Quoted 1: +x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z}b" + +echo Unquoted 2: +x='1 2'; f a${x:+'x y' $x '' "$x" `echo A B` "`echo C D`" z }b +echo Quoted 2: +x='1 2'; f "a${x:+ 'x y' $x '' "$x" `echo A B` "`echo C D`" z }b" + +#echo Unquoted 3: +#e= +#x='1 2'; f a${x:+'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b +#echo Quoted 3: +#x='1 2'; f "a${x:+ 'x y' $x '' "$x" $e $e "$e" $e `echo A B` "`echo C D`" z }b" -- cgit v1.2.3-55-g6feb From 83e434d5b56baccf617ebcc8a752959f7c4aacfc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 17:36:06 +0200 Subject: hush: fix handling of '' in ${var:+ARG} This wasn't an ash bug in dollar_altvalue9, it was hush bug (and bash!) function old new delta expand_one_var 2236 2254 +18 expand_vars_to_list 1097 1103 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 24/0) Total: 24 bytes Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/dollar_altvalue2.right | 69 ++++++++++++++++++++++ shell/ash_test/ash-quoting/dollar_altvalue2.tests | 33 +++++++++++ shell/ash_test/ash-quoting/dollar_altvalue9.right | 2 + shell/hush.c | 12 +++- .../hush_test/hush-quoting/dollar_altvalue2.right | 69 ++++++++++++++++++++++ .../hush_test/hush-quoting/dollar_altvalue2.tests | 33 +++++++++++ .../hush_test/hush-quoting/dollar_altvalue9.right | 2 + 7 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 shell/ash_test/ash-quoting/dollar_altvalue2.right create mode 100755 shell/ash_test/ash-quoting/dollar_altvalue2.tests create mode 100644 shell/hush_test/hush-quoting/dollar_altvalue2.right create mode 100755 shell/hush_test/hush-quoting/dollar_altvalue2.tests diff --git a/shell/ash_test/ash-quoting/dollar_altvalue2.right b/shell/ash_test/ash-quoting/dollar_altvalue2.right new file mode 100644 index 000000000..7cf37e379 --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue2.right @@ -0,0 +1,69 @@ +Unquoted '': +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +|| +end + +Unquoted "": +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +|| +end + +Quoted '': +start: +|''| +end +start: +|'' | +end +start: +| ''| +end +start: +| '' | +end +start: +|'' ''| +end + +Quoted "": +start: +|| +end +start: +| | +end +start: +| | +end +start: +| | +end +start: +| | +end diff --git a/shell/ash_test/ash-quoting/dollar_altvalue2.tests b/shell/ash_test/ash-quoting/dollar_altvalue2.tests new file mode 100755 index 000000000..3377eb27f --- /dev/null +++ b/shell/ash_test/ash-quoting/dollar_altvalue2.tests @@ -0,0 +1,33 @@ +f() { echo start:; for i; do echo "|$i|"; done; echo end; } +x=a + +echo "Unquoted '':" +f ${x:+''} +f ${x:+'' } +f ${x:+ ''} +f ${x:+ '' } +f ${x:+'' ''} + +echo +echo 'Unquoted "":' +f ${x:+""} +f ${x:+"" } +f ${x:+ ""} +f ${x:+ "" } +f ${x:+"" ""} + +echo +echo "Quoted '':" +f "${x:+''}" +f "${x:+'' }" +f "${x:+ ''}" +f "${x:+ '' }" +f "${x:+'' ''}" + +echo +echo 'Quoted "":' +f "${x:+""}" +f "${x:+"" }" +f "${x:+ ""}" +f "${x:+ "" }" +f "${x:+"" ""}" diff --git a/shell/ash_test/ash-quoting/dollar_altvalue9.right b/shell/ash_test/ash-quoting/dollar_altvalue9.right index fc6c2697c..39342fe7c 100644 --- a/shell/ash_test/ash-quoting/dollar_altvalue9.right +++ b/shell/ash_test/ash-quoting/dollar_altvalue9.right @@ -3,6 +3,7 @@ Unquoted 1: |x y| |1| |2| +|| |1 2| |A| |B| @@ -14,6 +15,7 @@ Unquoted 2: |ax y| |1| |2| +|| |1 2| |A| |B| diff --git a/shell/hush.c b/shell/hush.c index fc77b89fc..559595d2e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -475,7 +475,6 @@ #endif #define SPECIAL_VAR_SYMBOL_STR "\3" -#define SPECIAL_VAR_SYMBOL_CHR '\3' #define SPECIAL_VAR_SYMBOL 3 /* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */ #define SPECIAL_VAR_QUOTED_SVS 1 @@ -5950,6 +5949,8 @@ static int encode_then_append_var_plusminus(o_string *output, int n, break; o_addqchr(&dest, ch); } + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + o_addchr(&dest, SPECIAL_VAR_SYMBOL); continue; } } @@ -5959,6 +5960,10 @@ static int encode_then_append_var_plusminus(o_string *output, int n, } if (ch == '"') { dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; + if (dest.o_expflags) { + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + o_addchr(&dest, SPECIAL_VAR_SYMBOL); + } continue; } if (ch == '\\') { @@ -6565,7 +6570,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) case SPECIAL_VAR_QUOTED_SVS: /* */ /* "^C variable", represents literal ^C char (possible in scripts) */ - o_addchr(output, SPECIAL_VAR_SYMBOL_CHR); + o_addchr(output, SPECIAL_VAR_SYMBOL); arg++; break; #if ENABLE_HUSH_TICK @@ -6627,7 +6632,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) o_addstr(output, arg); debug_print_list("expand_vars_to_list[b]", output, n); } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ - && !(cant_be_null & 0x80) /* and all vars were not quoted. */ + && !(cant_be_null & 0x80) /* and all vars were not quoted */ + && !output->has_quoted_part ) { n--; /* allow to reuse list[n] later without re-growth */ diff --git a/shell/hush_test/hush-quoting/dollar_altvalue2.right b/shell/hush_test/hush-quoting/dollar_altvalue2.right new file mode 100644 index 000000000..7cf37e379 --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue2.right @@ -0,0 +1,69 @@ +Unquoted '': +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +|| +end + +Unquoted "": +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +end +start: +|| +|| +end + +Quoted '': +start: +|''| +end +start: +|'' | +end +start: +| ''| +end +start: +| '' | +end +start: +|'' ''| +end + +Quoted "": +start: +|| +end +start: +| | +end +start: +| | +end +start: +| | +end +start: +| | +end diff --git a/shell/hush_test/hush-quoting/dollar_altvalue2.tests b/shell/hush_test/hush-quoting/dollar_altvalue2.tests new file mode 100755 index 000000000..3377eb27f --- /dev/null +++ b/shell/hush_test/hush-quoting/dollar_altvalue2.tests @@ -0,0 +1,33 @@ +f() { echo start:; for i; do echo "|$i|"; done; echo end; } +x=a + +echo "Unquoted '':" +f ${x:+''} +f ${x:+'' } +f ${x:+ ''} +f ${x:+ '' } +f ${x:+'' ''} + +echo +echo 'Unquoted "":' +f ${x:+""} +f ${x:+"" } +f ${x:+ ""} +f ${x:+ "" } +f ${x:+"" ""} + +echo +echo "Quoted '':" +f "${x:+''}" +f "${x:+'' }" +f "${x:+ ''}" +f "${x:+ '' }" +f "${x:+'' ''}" + +echo +echo 'Quoted "":' +f "${x:+""}" +f "${x:+"" }" +f "${x:+ ""}" +f "${x:+ "" }" +f "${x:+"" ""}" diff --git a/shell/hush_test/hush-quoting/dollar_altvalue9.right b/shell/hush_test/hush-quoting/dollar_altvalue9.right index fc6c2697c..39342fe7c 100644 --- a/shell/hush_test/hush-quoting/dollar_altvalue9.right +++ b/shell/hush_test/hush-quoting/dollar_altvalue9.right @@ -3,6 +3,7 @@ Unquoted 1: |x y| |1| |2| +|| |1 2| |A| |B| @@ -14,6 +15,7 @@ Unquoted 2: |ax y| |1| |2| +|| |1 2| |A| |B| -- cgit v1.2.3-55-g6feb From 1856740ec0b4ffd8f780c3cc1ef9b38c9fc1eead Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 17:51:31 +0200 Subject: hush: better names for o_free_unsafe() / o_free(), no logic changes o_free() made o_string NULL-initialized, o_free_unsafe() did not bother reinitializing (expected caller to not need it). Signed-off-by: Denys Vlasenko --- shell/hush.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 559595d2e..2da288c15 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2797,13 +2797,13 @@ static void o_reset_to_empty_unquoted(o_string *o) o->data[0] = '\0'; } -static void o_free(o_string *o) +static void o_free_and_set_NULL(o_string *o) { free(o->data); memset(o, 0, sizeof(*o)); } -static ALWAYS_INLINE void o_free_unsafe(o_string *o) +static ALWAYS_INLINE void o_free(o_string *o) { free(o->data); } @@ -3852,7 +3852,7 @@ static const struct reserved_combo* reserved_word(struct parse_context *ctx) int len = old->as_string.length; /* Concatenate halves */ o_addstr(&old->as_string, ctx->as_string.data); - o_free_unsafe(&ctx->as_string); + o_free(&ctx->as_string); /* Find where leading keyword starts in first half */ str = old->as_string.data + len; if (str > old->as_string.data) @@ -4263,7 +4263,7 @@ static char *fetch_till_str(o_string *as_string, } } if (ch == EOF) { - o_free_unsafe(&heredoc); + o_free(&heredoc); return NULL; } o_addchr(&heredoc, ch); @@ -5033,7 +5033,7 @@ static struct pipe *parse_stream(char **pstring, if (done_word(&ctx)) { goto parse_error; } - o_free(&ctx.word); + o_free_and_set_NULL(&ctx.word); done_pipe(&ctx, PIPE_SEQ); pi = ctx.list_head; /* If we got nothing... */ @@ -5050,7 +5050,7 @@ static struct pipe *parse_stream(char **pstring, if (pstring) *pstring = ctx.as_string.data; else - o_free_unsafe(&ctx.as_string); + o_free(&ctx.as_string); #endif debug_leave(); debug_printf_parse("parse_stream return %p\n", pi); @@ -5284,13 +5284,13 @@ static struct pipe *parse_stream(char **pstring, if (!HAS_KEYWORDS IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0)) ) { - o_free(&ctx.word); + o_free_and_set_NULL(&ctx.word); #if !BB_MMU debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data); if (pstring) *pstring = ctx.as_string.data; else - o_free_unsafe(&ctx.as_string); + o_free(&ctx.as_string); #endif if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) { /* Example: bare "{ }", "()" */ @@ -5568,7 +5568,7 @@ static struct pipe *parse_stream(char **pstring, free_pipe_list(pctx->list_head); debug_printf_clean("freed list %p\n", pctx->list_head); #if !BB_MMU - o_free_unsafe(&pctx->as_string); + o_free(&pctx->as_string); #endif IF_HAS_KEYWORDS(p2 = pctx->stack;) if (pctx != &ctx) { @@ -5577,7 +5577,7 @@ static struct pipe *parse_stream(char **pstring, IF_HAS_KEYWORDS(pctx = p2;) } while (HAS_KEYWORDS && pctx); - o_free(&ctx.word); + o_free_and_set_NULL(&ctx.word); #if !BB_MMU if (pstring) *pstring = NULL; @@ -5751,7 +5751,7 @@ static char *encode_then_expand_string(const char *str) /*unbackslash:*/ 1 ); //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); - o_free_unsafe(&dest); + o_free(&dest); return exp_str; } @@ -5868,7 +5868,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int ); ret: debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str); - o_free_unsafe(&dest); + o_free(&dest); return exp_str; } @@ -5916,7 +5916,7 @@ static int encode_then_append_var_plusminus(o_string *output, int n, */ if (dest.data) { n = expand_vars_to_list(output, n, dest.data); - o_free(&dest); + o_free_and_set_NULL(&dest); o_addchr(output, '\0'); n = o_save_ptr(output, n); /* create next word */ } else @@ -6006,7 +6006,7 @@ static int encode_then_append_var_plusminus(o_string *output, int n, n = expand_vars_to_list(output, n, dest.data); } ret: - o_free_unsafe(&dest); + o_free(&dest); return n; } @@ -6588,7 +6588,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) G.expand_exitcode = G.last_exitcode; debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data); - o_free_unsafe(&subst_result); + o_free(&subst_result); break; } #endif @@ -6631,7 +6631,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) */ o_addstr(output, arg); debug_print_list("expand_vars_to_list[b]", output, n); - } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ + } else + if (output->length == o_get_last_ptr(output, n) /* expansion is empty */ && !(cant_be_null & 0x80) /* and all vars were not quoted */ && !output->has_quoted_part ) { -- cgit v1.2.3-55-g6feb From 4c3c8a1a61e33a8c55991a260ba73d6a75d74810 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 19:11:09 +0200 Subject: hush: tidy up code after previous commits Signed-off-by: Denys Vlasenko --- shell/hush.c | 91 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 2da288c15..dddba5e30 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4471,7 +4471,6 @@ static int parse_group(struct parse_context *ctx, #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS /* Subroutines for copying $(...) and `...` things */ -static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); /* '...' */ static int add_till_single_quote(o_string *dest, struct in_str *input) { @@ -4486,7 +4485,21 @@ static int add_till_single_quote(o_string *dest, struct in_str *input) o_addchr(dest, ch); } } +static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input) +{ + while (1) { + int ch = i_getch(input); + if (ch == EOF) { + syntax_error_unterm_ch('\''); + return 0; + } + if (ch == '\'') + return 1; + o_addqchr(dest, ch); + } +} /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ +static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); static int add_till_double_quote(o_string *dest, struct in_str *input) { while (1) { @@ -5599,6 +5612,7 @@ static char *expand_string_to_string(const char *str, int EXP_flags, int do_unba #if ENABLE_HUSH_TICK static int process_command_subs(o_string *dest, const char *s); #endif +static int expand_vars_to_list(o_string *output, int n, char *arg); /* expand_strvec_to_strvec() takes a list of strings, expands * all variable references within and returns a pointer to @@ -5755,6 +5769,13 @@ static char *encode_then_expand_string(const char *str) return exp_str; } +/* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}. + * These can contain single- and double-quoted strings, + * and treated as if the ARG string is initially unquoted. IOW: + * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be + * a dquoted string: "${var#"zz"}"), the difference only comes later + * (word splitting and globbing of the ${var...} result). + */ #if !BASH_PATTERN_SUBST #define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \ encode_then_expand_vararg(str, handle_squotes) @@ -5782,14 +5803,6 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int cp++; } - /* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}. - * These can contain single- and double-quoted strings, - * and treated as if the ARG string is initially unquoted. IOW: - * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be - * a dquoted string: "${var#"zz"}"), the difference only comes later - * (word splitting and globbing of the ${var...} result). - */ - setup_string_in_str(&input, str); dest.data = xzalloc(1); /* start as "", not as NULL */ exp_str = NULL; @@ -5798,28 +5811,21 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int int ch; ch = i_getch(&input); - if (ch == EOF) { - if (dest.o_expflags) { /* EXP_FLAG_ESC_GLOB_CHARS set? */ - syntax_error_unterm_ch('"'); - goto ret; /* error */ - } - break; - } debug_printf_parse("%s: ch=%c (%d) escape=%d\n", __func__, ch, ch, !!dest.o_expflags); - if (ch == '\'' && handle_squotes && !dest.o_expflags) { -//quoting version of add_till_single_quote() (try to merge?): - for (;;) { - ch = i_getch(&input); - if (ch == EOF) { - syntax_error_unterm_ch('\''); + + if (!dest.o_expflags) { + if (ch == EOF) + break; + if (handle_squotes && ch == '\'') { + if (!add_till_single_quote_dquoted(&dest, &input)) goto ret; /* error */ - } - if (ch == '\'') - break; - o_addqchr(&dest, ch); + continue; } - continue; + } + if (ch == EOF) { + syntax_error_unterm_ch('"'); + goto ret; /* error */ } if (ch == '"') { dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS; @@ -5872,8 +5878,8 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int return exp_str; } -static int expand_vars_to_list(o_string *output, int n, char *arg); - +/* Expanding ARG in ${var+ARG}, ${var-ARG} + */ static int encode_then_append_var_plusminus(o_string *output, int n, const char *str, int dquoted) { @@ -5896,8 +5902,6 @@ static int encode_then_append_var_plusminus(o_string *output, int n, } #endif - /* Expanding ARG in ${var+ARG}, ${var-ARG} */ - setup_string_in_str(&input, str); for (;;) { @@ -5938,17 +5942,8 @@ static int encode_then_append_var_plusminus(o_string *output, int n, continue; } if (!dquoted && ch == '\'') { -//quoting version of add_till_single_quote() (try to merge?): - for (;;) { - ch = i_getch(&input); - if (ch == EOF) { - syntax_error_unterm_ch('\''); - goto ret; /* error */ - } - if (ch == '\'') - break; - o_addqchr(&dest, ch); - } + if (!add_till_single_quote_dquoted(&dest, &input)) + goto ret; /* error */ o_addchr(&dest, SPECIAL_VAR_SYMBOL); o_addchr(&dest, SPECIAL_VAR_SYMBOL); continue; @@ -6105,11 +6100,10 @@ static int append_str_maybe_ifs_split(o_string *output, int n, return n; } -/* Helper: - * Handles varname... construct. +/* Handle varname... construct. */ -static NOINLINE int expand_one_var(o_string *output, - int n, int first_ch, char *arg, char **pp) +static NOINLINE int expand_one_var(o_string *output, int n, + int first_ch, char *arg, char **pp) { const char *val; char *to_be_freed; @@ -6385,7 +6379,7 @@ static NOINLINE int expand_one_var(o_string *output, * $ x=; f "${x:='x y' z}" * |'x y' z| * - * $ x=x; f ${x:+'x y' z}| + * $ x=x; f ${x:+'x y' z} * |x y| * |z| * $ x=x; f "${x:+'x y' z}" @@ -6620,7 +6614,8 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) arg = ++p; } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */ - if (arg[0]) { + if (*arg) { + /* handle trailing string */ if (output->ended_in_ifs) { o_addchr(output, '\0'); n = o_save_ptr(output, n); -- cgit v1.2.3-55-g6feb From f36caa4071bbb5bb6d098ced8116accc65370dd8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jul 2018 19:29:41 +0200 Subject: hush: never glob result of dquoted "${v:+/bin/c*}" Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-glob/glob_altvalue1.right | 7 +++++++ shell/ash_test/ash-glob/glob_altvalue1.tests | 13 +++++++++++++ shell/hush.c | 14 +++++++++++++- shell/hush_test/hush-glob/glob_altvalue1.right | 7 +++++++ shell/hush_test/hush-glob/glob_altvalue1.tests | 13 +++++++++++++ 5 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 shell/ash_test/ash-glob/glob_altvalue1.right create mode 100755 shell/ash_test/ash-glob/glob_altvalue1.tests create mode 100644 shell/hush_test/hush-glob/glob_altvalue1.right create mode 100755 shell/hush_test/hush-glob/glob_altvalue1.tests diff --git a/shell/ash_test/ash-glob/glob_altvalue1.right b/shell/ash_test/ash-glob/glob_altvalue1.right new file mode 100644 index 000000000..bd3592229 --- /dev/null +++ b/shell/ash_test/ash-glob/glob_altvalue1.right @@ -0,0 +1,7 @@ +1u: glob_altvalue1.tests +2u: glob_altvalue1.t* +3u: glob_altvalue1.t* +4u: glob_altvalue1.t* +1q: glob_altvalue1.t* +2q: 'glob_altvalue1.t*' +3q: glob_altvalue1.t* diff --git a/shell/ash_test/ash-glob/glob_altvalue1.tests b/shell/ash_test/ash-glob/glob_altvalue1.tests new file mode 100755 index 000000000..5483d63e6 --- /dev/null +++ b/shell/ash_test/ash-glob/glob_altvalue1.tests @@ -0,0 +1,13 @@ +x=x + +echo 1u: ${x:+glob_altvalue1.t*} +echo 2u: ${x:+'glob_altvalue1.t*'} +echo 3u: ${x:+"glob_altvalue1.t*"} +echo 4u: ${x:+glob_altvalue1.t\*} +##echo 5u: ${x:+"glob_altvalue1.t\*"} + +echo 1q: "${x:+glob_altvalue1.t*}" +echo 2q: "${x:+'glob_altvalue1.t*'}" +echo 3q: "${x:+"glob_altvalue1.t*"}" +##echo 4q: "${x:+glob_altvalue1.t\*}" +##echo 5q: "${x:+"glob_altvalue1.t\*"}" diff --git a/shell/hush.c b/shell/hush.c index dddba5e30..4fdd15900 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5994,7 +5994,19 @@ static int encode_then_append_var_plusminus(o_string *output, int n, continue; } #endif - o_addQchr(&dest, ch); + if (dquoted) { + /* Always glob-protect if in dquotes: + * x=x; echo "${x:+/bin/c*}" - prints: /bin/c* + * x=x; echo "${x:+"/bin/c*"}" - prints: /bin/c* + */ + o_addqchr(&dest, ch); + } else { + /* Glob-protect only if char is quoted: + * x=x; echo ${x:+/bin/c*} - prints many filenames + * x=x; echo ${x:+"/bin/c*"} - prints: /bin/c* + */ + o_addQchr(&dest, ch); + } } /* for (;;) */ if (dest.data) { diff --git a/shell/hush_test/hush-glob/glob_altvalue1.right b/shell/hush_test/hush-glob/glob_altvalue1.right new file mode 100644 index 000000000..bd3592229 --- /dev/null +++ b/shell/hush_test/hush-glob/glob_altvalue1.right @@ -0,0 +1,7 @@ +1u: glob_altvalue1.tests +2u: glob_altvalue1.t* +3u: glob_altvalue1.t* +4u: glob_altvalue1.t* +1q: glob_altvalue1.t* +2q: 'glob_altvalue1.t*' +3q: glob_altvalue1.t* diff --git a/shell/hush_test/hush-glob/glob_altvalue1.tests b/shell/hush_test/hush-glob/glob_altvalue1.tests new file mode 100755 index 000000000..5483d63e6 --- /dev/null +++ b/shell/hush_test/hush-glob/glob_altvalue1.tests @@ -0,0 +1,13 @@ +x=x + +echo 1u: ${x:+glob_altvalue1.t*} +echo 2u: ${x:+'glob_altvalue1.t*'} +echo 3u: ${x:+"glob_altvalue1.t*"} +echo 4u: ${x:+glob_altvalue1.t\*} +##echo 5u: ${x:+"glob_altvalue1.t\*"} + +echo 1q: "${x:+glob_altvalue1.t*}" +echo 2q: "${x:+'glob_altvalue1.t*'}" +echo 3q: "${x:+"glob_altvalue1.t*"}" +##echo 4q: "${x:+glob_altvalue1.t\*}" +##echo 5q: "${x:+"glob_altvalue1.t\*"}" -- cgit v1.2.3-55-g6feb From ca2f831ead327d98ab3374acb3b07ad7632ea02d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jul 2018 14:21:07 +0200 Subject: hexedit: fixes for redraw and down movement causing SEGV on attempt to access "Go to:" command was not updating row position, making next "down" movements for one screenful print empty lines instead of showing the contents. If the file is whole pages long, "down" movement at EOF was advancing position +16 bytes, mapping the next portion (entirely past the end of the file), then finding out that the new position is beyond the EOF, rolling it back -16 bytes... ending up with this postion pointing *before* the mapped portion. Any next access (e.g. "move right" key) SEGVs. function old new delta hexedit_main 1170 1184 +14 Signed-off-by: Denys Vlasenko --- miscutils/hexedit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 95c930d12..298eb8149 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c @@ -153,7 +153,8 @@ static void redraw(unsigned cursor) i++; } - printf(ESC"[%u;%uH", 1 + cursor / 16, 1 + pos + (cursor & 0xf) * 3); + G.row = cursor / 16; + printf(ESC"[%u;%uH", 1 + G.row, 1 + pos + (cursor & 0xf) * 3); } static void redraw_cur_line(void) @@ -367,6 +368,8 @@ int hexedit_main(int argc UNUSED_PARAM, char **argv) if (G.current_byte > G.eof_byte) { /* _after_ eof - don't allow this */ G.current_byte -= 16; + if (G.current_byte < G.baseaddr) + move_mapping_lower(); break; } } -- cgit v1.2.3-55-g6feb From d73cdbf84c9c7d509baf69eb3256dcaf733f4d93 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jul 2018 15:43:57 +0200 Subject: hush: fix handling of heredocs starting with empty lines function old new delta parse_stream 2748 2759 +11 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-heredoc/heredoc_empty3.right | 2 ++ shell/ash_test/ash-heredoc/heredoc_empty3.tests | 4 ++++ shell/hush.c | 8 ++++++++ shell/hush_test/hush-heredoc/heredoc_empty3.right | 2 ++ shell/hush_test/hush-heredoc/heredoc_empty3.tests | 4 ++++ 5 files changed, 20 insertions(+) create mode 100644 shell/ash_test/ash-heredoc/heredoc_empty3.right create mode 100755 shell/ash_test/ash-heredoc/heredoc_empty3.tests create mode 100644 shell/hush_test/hush-heredoc/heredoc_empty3.right create mode 100755 shell/hush_test/hush-heredoc/heredoc_empty3.tests diff --git a/shell/ash_test/ash-heredoc/heredoc_empty3.right b/shell/ash_test/ash-heredoc/heredoc_empty3.right new file mode 100644 index 000000000..0b54a9c93 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_empty3.right @@ -0,0 +1,2 @@ + +Ok diff --git a/shell/ash_test/ash-heredoc/heredoc_empty3.tests b/shell/ash_test/ash-heredoc/heredoc_empty3.tests new file mode 100755 index 000000000..828c2dd89 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_empty3.tests @@ -0,0 +1,4 @@ +cat < Date: Mon, 23 Jul 2018 16:31:21 +0200 Subject: hush: fix heredoc handling in the "cmd <" case function old new delta parse_stream 2759 2787 +28 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-heredoc/heredocA.right | 1 + shell/ash_test/ash-heredoc/heredocA.tests | 4 +++ shell/hush.c | 54 ++++++++++++++++------------- shell/hush_test/hush-heredoc/heredoc9.right | 1 + shell/hush_test/hush-heredoc/heredoc9.tests | 9 +++++ shell/hush_test/hush-heredoc/heredocA.right | 1 + shell/hush_test/hush-heredoc/heredocA.tests | 4 +++ 7 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 shell/ash_test/ash-heredoc/heredocA.right create mode 100755 shell/ash_test/ash-heredoc/heredocA.tests create mode 100644 shell/hush_test/hush-heredoc/heredoc9.right create mode 100755 shell/hush_test/hush-heredoc/heredoc9.tests create mode 100644 shell/hush_test/hush-heredoc/heredocA.right create mode 100755 shell/hush_test/hush-heredoc/heredocA.tests diff --git a/shell/ash_test/ash-heredoc/heredocA.right b/shell/ash_test/ash-heredoc/heredocA.right new file mode 100644 index 000000000..7326d9603 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocA.right @@ -0,0 +1 @@ +Ok diff --git a/shell/ash_test/ash-heredoc/heredocA.tests b/shell/ash_test/ash-heredoc/heredocA.tests new file mode 100755 index 000000000..440aaf906 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocA.tests @@ -0,0 +1,4 @@ +{ cat <cmds; - debug_printf_parse("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n", + debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n", pi->num_cmds, - cmd->argv ? cmd->argv[0] : "NONE"); + cmd->argv ? cmd->argv[0] : "NONE" + ); for (i = 0; i < pi->num_cmds; i++) { struct redir_struct *redir = cmd->redirects; - debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n", + debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n", i, cmd->argv ? cmd->argv[0] : "NONE"); while (redir) { if (redir->rd_type == REDIRECT_HEREDOC) { @@ -4325,11 +4331,9 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ } pi = pi->next; } -#if 0 /* Should be 0. If it isn't, it's a parse error */ - if (heredoc_cnt) + if (HUSH_DEBUG && heredoc_cnt) bb_error_msg_and_die("heredoc BUG 2"); -#endif return 0; } @@ -5200,7 +5204,9 @@ static struct pipe *parse_stream(char **pstring, * "case ... in word) ..." */ if (IS_NULL_CMD(ctx.command) - && ctx.word.length == 0 && !ctx.word.has_quoted_part + && ctx.word.length == 0 + && !ctx.word.has_quoted_part + && heredoc_cnt == 0 ) { /* This newline can be ignored. But... * Without check #1, interactive shell @@ -5228,7 +5234,7 @@ static struct pipe *parse_stream(char **pstring, } /* Treat newline as a command separator. */ done_pipe(&ctx, PIPE_SEQ); - debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt); + debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt); if (heredoc_cnt) { if (fetch_heredocs(heredoc_cnt, &ctx, input)) { goto parse_error; @@ -5362,7 +5368,7 @@ static struct pipe *parse_stream(char **pstring, if (next == '<') { redir_style = REDIRECT_HEREDOC; heredoc_cnt++; - debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt); + debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt); ch = i_getch(input); nommu_addchr(&ctx.as_string, ch); } else if (next == '>') { diff --git a/shell/hush_test/hush-heredoc/heredoc9.right b/shell/hush_test/hush-heredoc/heredoc9.right new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc9.right @@ -0,0 +1 @@ +hello diff --git a/shell/hush_test/hush-heredoc/heredoc9.tests b/shell/hush_test/hush-heredoc/heredoc9.tests new file mode 100755 index 000000000..96c227cc1 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc9.tests @@ -0,0 +1,9 @@ +echo hello >greeting +cat </dev/null +rm greeting diff --git a/shell/hush_test/hush-heredoc/heredocA.right b/shell/hush_test/hush-heredoc/heredocA.right new file mode 100644 index 000000000..7326d9603 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocA.right @@ -0,0 +1 @@ +Ok diff --git a/shell/hush_test/hush-heredoc/heredocA.tests b/shell/hush_test/hush-heredoc/heredocA.tests new file mode 100755 index 000000000..440aaf906 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocA.tests @@ -0,0 +1,4 @@ +{ cat < Date: Tue, 24 Jul 2018 13:03:03 +0200 Subject: hush: fix handling of heredocs not enclosed in groups where they are "declared" function old new delta fetch_heredocs - 479 +479 parse_and_run_stream 146 148 +2 parse_stream 2787 2296 -491 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 481/-491) Total: -10 bytes Signed-off-by: Denys Vlasenko --- .../ash-heredoc/heredoc_after_compound1.right | 2 + .../ash-heredoc/heredoc_after_compound1.tests | 3 + shell/hush.c | 104 ++++++++++++--------- .../hush-heredoc/heredoc_after_compound1.right | 2 + .../hush-heredoc/heredoc_after_compound1.tests | 3 + .../hush-heredoc/heredoc_var_expand1.right | 4 + .../hush-heredoc/heredoc_var_expand1.tests | 11 +++ 7 files changed, 84 insertions(+), 45 deletions(-) create mode 100644 shell/ash_test/ash-heredoc/heredoc_after_compound1.right create mode 100755 shell/ash_test/ash-heredoc/heredoc_after_compound1.tests create mode 100644 shell/hush_test/hush-heredoc/heredoc_after_compound1.right create mode 100755 shell/hush_test/hush-heredoc/heredoc_after_compound1.tests create mode 100644 shell/hush_test/hush-heredoc/heredoc_var_expand1.right create mode 100755 shell/hush_test/hush-heredoc/heredoc_var_expand1.tests diff --git a/shell/ash_test/ash-heredoc/heredoc_after_compound1.right b/shell/ash_test/ash-heredoc/heredoc_after_compound1.right new file mode 100644 index 000000000..9052f7d1f --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_after_compound1.right @@ -0,0 +1,2 @@ +Ok1 +Ok2 diff --git a/shell/ash_test/ash-heredoc/heredoc_after_compound1.tests b/shell/ash_test/ash-heredoc/heredoc_after_compound1.tests new file mode 100755 index 000000000..e7cfb5be1 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_after_compound1.tests @@ -0,0 +1,3 @@ +{ cat <redirects) + fdprintf(2, " {redir}"); fdprintf(2, "\n"); prn++; } @@ -4292,10 +4294,12 @@ static char *fetch_till_str(o_string *as_string, /* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs * and load them all. There should be exactly heredoc_cnt of them. */ -static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input) +#if BB_MMU +#define fetch_heredocs(as_string, pi, heredoc_cnt, input) \ + fetch_heredocs(pi, heredoc_cnt, input) +#endif +static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input) { - struct pipe *pi = ctx->list_head; - while (pi && heredoc_cnt) { int i; struct command *cmd = pi->cmds; @@ -4315,11 +4319,11 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ redir->rd_type = REDIRECT_HEREDOC2; /* redir->rd_dup is (ab)used to indicate <<- */ - p = fetch_till_str(&ctx->as_string, input, + p = fetch_till_str(as_string, input, redir->rd_filename, redir->rd_dup); if (!p) { syntax_error("unexpected EOF in here document"); - return 1; + return -1; } free(redir->rd_filename); redir->rd_filename = p; @@ -4327,29 +4331,36 @@ static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_ } redir = redir->next; } + if (cmd->group) { + //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt); + heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input); + //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt); + if (heredoc_cnt < 0) + return heredoc_cnt; /* error */ + } cmd++; } pi = pi->next; } - /* Should be 0. If it isn't, it's a parse error */ - if (HUSH_DEBUG && heredoc_cnt) - bb_error_msg_and_die("heredoc BUG 2"); - return 0; + return heredoc_cnt; } static int run_list(struct pipe *pi); #if BB_MMU -#define parse_stream(pstring, input, end_trigger) \ - parse_stream(input, end_trigger) +#define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \ + parse_stream(heredoc_cnt_ptr, input, end_trigger) #endif static struct pipe *parse_stream(char **pstring, + int *heredoc_cnt_ptr, struct in_str *input, int end_trigger); - +/* Returns number of heredocs not yet consumed, + * or -1 on error. + */ static int parse_group(struct parse_context *ctx, - struct in_str *input, int ch) + struct in_str *input, int ch) { /* ctx->word contains characters seen prior to ( or {. * Typically it's empty, but for function defs, @@ -4360,6 +4371,7 @@ static int parse_group(struct parse_context *ctx, char *as_string = NULL; #endif struct pipe *pipe_list; + int heredoc_cnt = 0; int endch; struct command *command = ctx->command; @@ -4368,12 +4380,12 @@ static int parse_group(struct parse_context *ctx, if (ch == '(' && !ctx->word.has_quoted_part) { if (ctx->word.length) if (done_word(ctx)) - return 1; + return -1; if (!command->argv) goto skip; /* (... */ if (command->argv[1]) { /* word word ... (... */ syntax_error_unexpected_ch('('); - return 1; + return -1; } /* it is "word(..." or "word (..." */ do @@ -4381,7 +4393,7 @@ static int parse_group(struct parse_context *ctx, while (ch == ' ' || ch == '\t'); if (ch != ')') { syntax_error_unexpected_ch(ch); - return 1; + return -1; } nommu_addchr(&ctx->as_string, ch); do @@ -4389,7 +4401,7 @@ static int parse_group(struct parse_context *ctx, while (ch == ' ' || ch == '\t' || ch == '\n'); if (ch != '{' && ch != '(') { syntax_error_unexpected_ch(ch); - return 1; + return -1; } nommu_addchr(&ctx->as_string, ch); command->cmd_type = CMD_FUNCDEF; @@ -4403,9 +4415,9 @@ static int parse_group(struct parse_context *ctx, || ctx->word.has_quoted_part /* ""{... */ ) { syntax_error(NULL); - debug_printf_parse("parse_group return 1: " + debug_printf_parse("parse_group return -1: " "syntax error, groups and arglists don't mix\n"); - return 1; + return -1; } #endif @@ -4423,7 +4435,7 @@ static int parse_group(struct parse_context *ctx, && ch != '(' /* but "{(..." is allowed (without whitespace) */ ) { syntax_error_unexpected_ch(ch); - return 1; + return -1; } if (ch != '(') { ch = i_getch(input); @@ -4431,7 +4443,9 @@ static int parse_group(struct parse_context *ctx, } } - pipe_list = parse_stream(&as_string, input, endch); + debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt); + pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch); + debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt); #if !BB_MMU if (as_string) o_addstr(&ctx->as_string, as_string); @@ -4442,9 +4456,9 @@ static int parse_group(struct parse_context *ctx, /* parse_stream already emitted error msg */ if (!BB_MMU) free(as_string); - debug_printf_parse("parse_group return 1: " + debug_printf_parse("parse_group return -1: " "parse_stream returned %p\n", pipe_list); - return 1; + return -1; } #if !BB_MMU as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ @@ -4475,8 +4489,8 @@ static int parse_group(struct parse_context *ctx, command->group = pipe_list; - debug_printf_parse("parse_group return 0\n"); - return 0; + debug_printf_parse("parse_group return %d\n", heredoc_cnt); + return heredoc_cnt; /* command remains "open", available for possible redirects */ #undef as_string } @@ -5002,6 +5016,7 @@ static int encode_string(o_string *as_string, * or return ERR_PTR. */ static struct pipe *parse_stream(char **pstring, + int *heredoc_cnt_ptr, struct in_str *input, int end_trigger) { @@ -5077,7 +5092,11 @@ static struct pipe *parse_stream(char **pstring, else o_free(&ctx.as_string); #endif + // heredoc_cnt must be 0 here anyway + //if (heredoc_cnt_ptr) + // *heredoc_cnt_ptr = heredoc_cnt; debug_leave(); + debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt); debug_printf_parse("parse_stream return %p\n", pi); return pi; } @@ -5236,10 +5255,9 @@ static struct pipe *parse_stream(char **pstring, done_pipe(&ctx, PIPE_SEQ); debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt); if (heredoc_cnt) { - if (fetch_heredocs(heredoc_cnt, &ctx, input)) { + heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input); + if (heredoc_cnt != 0) goto parse_error; - } - heredoc_cnt = 0; } ctx.is_assignment = MAYBE_ASSIGNMENT; debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]); @@ -5288,19 +5306,6 @@ static struct pipe *parse_stream(char **pstring, ) #endif ) { - if (heredoc_cnt) { - /* This is technically valid: - * { cat < Date: Tue, 24 Jul 2018 14:03:18 +0200 Subject: hush: handle backslash-newline in heredoc terminators function old new delta fetch_heredocs 479 527 +48 (ash fails this test) Signed-off-by: Denys Vlasenko --- .../ash-heredoc/heredoc_bkslash_newline2.right | 1 + .../ash-heredoc/heredoc_bkslash_newline2.tests | 4 ++++ shell/hush.c | 20 ++++++++++++++++++-- .../hush-heredoc/heredoc_bkslash_newline2.right | 1 + .../hush-heredoc/heredoc_bkslash_newline2.tests | 4 ++++ 5 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right create mode 100755 shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests create mode 100644 shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right create mode 100755 shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.right @@ -0,0 +1 @@ +Ok1 diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests new file mode 100755 index 000000000..1d2a26504 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline2.tests @@ -0,0 +1,4 @@ +cat < (not a line cont.) */ - prev = 0; /* not \ */ + prev = 0; /* not '\' */ else prev = ch; } diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right new file mode 100644 index 000000000..3d79316d7 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.right @@ -0,0 +1 @@ +Ok1 diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests new file mode 100755 index 000000000..1d2a26504 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline2.tests @@ -0,0 +1,4 @@ +cat < Date: Tue, 24 Jul 2018 16:54:41 +0200 Subject: hush: fix nested redirects colliding with script fds This necessitates switch from libc FILE api to a simple homegrown replacement. The change which fixes the bug here is the deleting of restore_redirected_FILEs(); line. It was prematurely moving (restoring) script fd#3. The fix is: we don't even _want_ to restore scrit fds, we are perfectly fine with them being moved. The only reason we tried to restore them is that FILE api did not allow moving of FILE->fd. function old new delta refill_HFILE_and_getc - 93 +93 hfopen - 90 +90 hfclose - 66 +66 pseudo_exec_argv 591 597 +6 hush_main 1089 1095 +6 builtin_source 209 214 +5 save_fd_on_redirect 197 200 +3 setup_redirects 320 321 +1 fgetc_interactive 235 236 +1 i_peek_and_eat_bkslash_nl 99 97 -2 expand_vars_to_list 1103 1100 -3 restore_redirects 99 52 -47 fclose_and_forget 57 - -57 remember_FILE 63 - -63 ------------------------------------------------------------------------------ (add/remove: 3/2 grow/shrink: 6/3 up/down: 271/-172) Total: 99 bytes Signed-off-by: Denys Vlasenko --- libbb/xfuncs_printf.c | 1 + shell/ash_test/ash-heredoc/heredocB.right | 3 + shell/ash_test/ash-heredoc/heredocB.tests | 12 ++ shell/ash_test/ash-redir/redir_script.tests | 4 + shell/hush.c | 234 +++++++++++++++----------- shell/hush_test/hush-heredoc/heredocB.right | 3 + shell/hush_test/hush-heredoc/heredocB.tests | 12 ++ shell/hush_test/hush-redir/redir_script.tests | 4 + 8 files changed, 175 insertions(+), 98 deletions(-) create mode 100644 shell/ash_test/ash-heredoc/heredocB.right create mode 100755 shell/ash_test/ash-heredoc/heredocB.tests create mode 100644 shell/hush_test/hush-heredoc/heredocB.right create mode 100755 shell/hush_test/hush-heredoc/heredocB.tests diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 7247c915b..6cc60f6c0 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c @@ -222,6 +222,7 @@ void FAST_FUNC xdup2(int from, int to) { if (dup2(from, to) != to) bb_perror_msg_and_die("can't duplicate file descriptor"); + // " %d to %d", from, to); } // "Renumber" opened fd diff --git a/shell/ash_test/ash-heredoc/heredocB.right b/shell/ash_test/ash-heredoc/heredocB.right new file mode 100644 index 000000000..43ba0b4f9 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocB.right @@ -0,0 +1,3 @@ +one - alpha +two - beta +three - gamma diff --git a/shell/ash_test/ash-heredoc/heredocB.tests b/shell/ash_test/ash-heredoc/heredocB.tests new file mode 100755 index 000000000..45ea4687f --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredocB.tests @@ -0,0 +1,12 @@ +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done <&- 3>&-" && \ test x"$fds" = x" 11>&- 3>&-" \ && { echo "Ok: script fd is not closed"; exit 0; } +# or we see that fd 3 moved to fd 10: +test x"$fds1" = x" 3>&- 4>&-" && \ +test x"$fds" = x" 10>&- 3>&-" \ +&& { echo "Ok: script fd is not closed"; exit 0; } echo "Bug: script fd is closed" echo "fds1:$fds1" diff --git a/shell/hush.c b/shell/hush.c index c26484b49..7a1513c24 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -357,6 +357,9 @@ #else # define CLEAR_RANDOM_T(rnd) ((void)0) #endif +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif #ifndef F_DUPFD_CLOEXEC # define F_DUPFD_CLOEXEC F_DUPFD #endif @@ -556,11 +559,27 @@ static const char *const assignment_flag[] = { }; #endif +/* We almost can use standard FILE api, but we need an ability to move + * its fd when redirects coincide with it. No api exists for that + * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902). + * HFILE is our internal alternative. Only supports reading. + * Since we now can, we incorporate linked list of all opened HFILEs + * into the struct (used to be a separate mini-list). + */ +typedef struct HFILE { + char *cur; + char *end; + struct HFILE *next_hfile; + int is_stdin; + int fd; + char buf[1024]; +} HFILE; + typedef struct in_str { const char *p; int peek_buf[2]; int last_char; - FILE *file; + HFILE *file; } in_str; /* The descrip member of this structure is only used to make @@ -814,14 +833,6 @@ enum { NUM_OPT_O }; - -struct FILE_list { - struct FILE_list *next; - FILE *fp; - int fd; -}; - - /* "Globals" within this file */ /* Sorted roughly by size (smaller offsets == smaller code) */ struct globals { @@ -954,7 +965,7 @@ struct globals { unsigned lineno; char *lineno_var; #endif - struct FILE_list *FILE_list; + HFILE *HFILE_list; /* Which signals have non-DFL handler (even with no traps set)? * Set at the start to: * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS) @@ -1563,83 +1574,115 @@ static int xdup_CLOEXEC_and_close(int fd, int avoid_fd) } -/* Manipulating the list of open FILEs */ -static FILE *remember_FILE(FILE *fp) +/* Manipulating HFILEs */ +static HFILE *hfopen(const char *name) { - if (fp) { - struct FILE_list *n = xmalloc(sizeof(*n)); - n->next = G.FILE_list; - G.FILE_list = n; - n->fp = fp; - n->fd = fileno(fp); - close_on_exec_on(n->fd); + HFILE *fp; + int fd; + + fd = STDIN_FILENO; + if (name) { + fd = open(name, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return NULL; + if (O_CLOEXEC == 0) /* ancient libc */ + close_on_exec_on(fd); } + + fp = xmalloc(sizeof(*fp)); + fp->is_stdin = (name == NULL); + fp->fd = fd; + fp->cur = fp->end = fp->buf; + fp->next_hfile = G.HFILE_list; + G.HFILE_list = fp; return fp; } -static void fclose_and_forget(FILE *fp) +static void hfclose(HFILE *fp) { - struct FILE_list **pp = &G.FILE_list; + HFILE **pp = &G.HFILE_list; while (*pp) { - struct FILE_list *cur = *pp; - if (cur->fp == fp) { - *pp = cur->next; - free(cur); + HFILE *cur = *pp; + if (cur == fp) { + *pp = cur->next_hfile; break; } - pp = &cur->next; + pp = &cur->next_hfile; } - fclose(fp); + if (fp->fd >= 0) + close(fp->fd); + free(fp); } -static int save_FILEs_on_redirect(int fd, int avoid_fd) +static int refill_HFILE_and_getc(HFILE *fp) { - struct FILE_list *fl = G.FILE_list; + int n; + + if (fp->fd < 0) { + /* Already saw EOF */ + return EOF; + } + /* Try to buffer more input */ + fp->cur = fp->buf; + n = safe_read(fp->fd, fp->buf, sizeof(fp->buf)); + if (n < 0) { + bb_perror_msg("read error"); + n = 0; + } + fp->end = fp->buf + n; + if (n == 0) { + /* EOF/error */ + close(fp->fd); + fp->fd = -1; + return EOF; + } + return (unsigned char)(*fp->cur++); +} +/* Inlined for common case of non-empty buffer. + */ +static ALWAYS_INLINE int hfgetc(HFILE *fp) +{ + if (fp->cur < fp->end) + return (unsigned char)(*fp->cur++); + /* Buffer empty */ + return refill_HFILE_and_getc(fp); +} +static int move_HFILEs_on_redirect(int fd, int avoid_fd) +{ + HFILE *fl = G.HFILE_list; while (fl) { if (fd == fl->fd) { /* We use it only on script files, they are all CLOEXEC */ fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd); debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd); - return 1; - } - fl = fl->next; - } - return 0; -} -static void restore_redirected_FILEs(void) -{ - struct FILE_list *fl = G.FILE_list; - while (fl) { - int should_be = fileno(fl->fp); - if (fl->fd != should_be) { - debug_printf_redir("restoring script fd from %d to %d\n", fl->fd, should_be); - xmove_fd(fl->fd, should_be); - fl->fd = should_be; + return 1; /* "found and moved" */ } - fl = fl->next; + fl = fl->next_hfile; } + return 0; /* "not in the list" */ } #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU -static void close_all_FILE_list(void) +static void close_all_HFILE_list(void) { - struct FILE_list *fl = G.FILE_list; + HFILE *fl = G.HFILE_list; while (fl) { - /* fclose would also free FILE object. + /* hfclose would also free HFILE object. * It is disastrous if we share memory with a vforked parent. * I'm not sure we never come here after vfork. * Therefore just close fd, nothing more. */ - /*fclose(fl->fp); - unsafe */ - close(fl->fd); - fl = fl->next; + /*hfclose(fl); - unsafe */ + if (fl->fd >= 0) + close(fl->fd); + fl = fl->next_hfile; } } #endif -static int fd_in_FILEs(int fd) +static int fd_in_HFILEs(int fd) { - struct FILE_list *fl = G.FILE_list; + HFILE *fl = G.HFILE_list; while (fl) { if (fl->fd == fd) return 1; - fl = fl->next; + fl = fl->next_hfile; } return 0; } @@ -2580,7 +2623,7 @@ static int get_user_input(struct in_str *i) } fflush_all(); //FIXME: here ^C or SIGINT will have effect only after - r = fgetc(i->file); + r = hfgetc(i->file); /* In !ENABLE_FEATURE_EDITING we don't use read_line_input, * no ^C masking happens during fgetc, no special code for ^C: * it generates SIGINT as usual. @@ -2600,22 +2643,22 @@ static int fgetc_interactive(struct in_str *i) { int ch; /* If it's interactive stdin, get new line. */ - if (G_interactive_fd && i->file == stdin) { + if (G_interactive_fd && i->file->is_stdin) { /* Returns first char (or EOF), the rest is in i->p[] */ ch = get_user_input(i); G.promptmode = 1; /* PS2 */ debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode); } else { /* Not stdin: script file, sourced file, etc */ - do ch = fgetc(i->file); while (ch == '\0'); + do ch = hfgetc(i->file); while (ch == '\0'); } return ch; } #else -static inline int fgetc_interactive(struct in_str *i) +static ALWAYS_INLINE int fgetc_interactive(struct in_str *i) { int ch; - do ch = fgetc(i->file); while (ch == '\0'); + do ch = hfgetc(i->file); while (ch == '\0'); return ch; } #endif /* INTERACTIVE */ @@ -2730,7 +2773,7 @@ static int i_peek2(struct in_str *i) ch = i->peek_buf[1]; if (ch == 0) { /* We did not read it yet, get it now */ - do ch = fgetc(i->file); while (ch == '\0'); + do ch = hfgetc(i->file); while (ch == '\0'); i->peek_buf[1] = ch; } @@ -2774,10 +2817,10 @@ static int i_peek_and_eat_bkslash_nl(struct in_str *input) } } -static void setup_file_in_str(struct in_str *i, FILE *f) +static void setup_file_in_str(struct in_str *i, HFILE *fp) { memset(i, 0, sizeof(*i)); - i->file = f; + i->file = fp; /* i->p = NULL; */ } @@ -7106,19 +7149,19 @@ static void parse_and_run_string(const char *s) //IF_HUSH_LINENO_VAR(G.lineno = sv;) } -static void parse_and_run_file(FILE *f) +static void parse_and_run_file(HFILE *fp) { struct in_str input; IF_HUSH_LINENO_VAR(unsigned sv = G.lineno;) IF_HUSH_LINENO_VAR(G.lineno = 1;) - setup_file_in_str(&input, f); + setup_file_in_str(&input, fp); parse_and_run_stream(&input, ';'); IF_HUSH_LINENO_VAR(G.lineno = sv;) } #if ENABLE_HUSH_TICK -static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) +static int generate_stream_from_string(const char *s, pid_t *pid_p) { pid_t pid; int channel[2]; @@ -7220,7 +7263,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) free(to_free); # endif close(channel[1]); - return remember_FILE(xfdopen_for_read(channel[0])); + return channel[0]; } /* Return code is exit status of the process that is run. */ @@ -7230,7 +7273,7 @@ static int process_command_subs(o_string *dest, const char *s) pid_t pid; int status, ch, eol_cnt; - fp = generate_stream_from_string(s, &pid); + fp = xfdopen_for_read(generate_stream_from_string(s, &pid)); /* Now send results of command back into original context */ eol_cnt = 0; @@ -7249,7 +7292,7 @@ static int process_command_subs(o_string *dest, const char *s) } debug_printf("done reading from `cmd` pipe, closing it\n"); - fclose_and_forget(fp); + fclose(fp); /* We need to extract exitcode. Test case * "true; echo `sleep 1; false` $?" * should print 1 */ @@ -7427,20 +7470,17 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp) return 1; /* "we closed fd" */ } #endif + /* If this one of script's fds? */ + if (move_HFILEs_on_redirect(fd, avoid_fd)) + return 1; /* yes. "we closed fd" (actually moved it) */ + /* Are we called from setup_redirects(squirrel==NULL)? Two cases: - * (1) Redirect in a forked child. No need to save FILEs' fds, - * we aren't going to use them anymore, ok to trash. - * (2) "exec 3>FILE". Bummer. We can save script FILEs' fds, - * but how are we doing to restore them? - * "fileno(fd) = new_fd" can't be done. + * (1) Redirect in a forked child. + * (2) "exec 3>FILE". */ if (!sqp) return 0; - /* If this one of script's fds? */ - if (save_FILEs_on_redirect(fd, avoid_fd)) - return 1; /* yes. "we closed fd" */ - /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */ *sqp = add_squirrel(*sqp, fd, avoid_fd); return 0; /* "we did not close fd" */ @@ -7465,8 +7505,6 @@ static void restore_redirects(struct squirrel *sq) } /* If moved, G.interactive_fd stays on new fd, not restoring it */ - - restore_redirected_FILEs(); } #if ENABLE_FEATURE_SH_STANDALONE && BB_MMU @@ -7474,7 +7512,7 @@ static void close_saved_fds_and_FILE_fds(void) { if (G_interactive_fd) close(G_interactive_fd); - close_all_FILE_list(); + close_all_HFILE_list(); } #endif @@ -7487,7 +7525,7 @@ static int internally_opened_fd(int fd, struct squirrel *sq) return 1; #endif /* If this one of script's fds? */ - if (fd_in_FILEs(fd)) + if (fd_in_HFILEs(fd)) return 1; if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) { @@ -7512,7 +7550,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp); /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ * of the heredoc */ - debug_printf_parse("set heredoc '%s'\n", + debug_printf_redir("set heredoc '%s'\n", redir->rd_filename); setup_heredoc(redir); continue; @@ -7524,8 +7562,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) int mode; if (redir->rd_filename == NULL) { - /* - * Examples: + /* Examples: * "cmd >" (no filename) * "cmd > " (which is never interactive (unless -i?)) * sources $BASH_ENV here (without scanning $PATH). @@ -9902,13 +9938,15 @@ int hush_main(int argc, char **argv) G.global_argv++; debug_printf("running script '%s'\n", G.global_argv[0]); xfunc_error_retval = 127; /* for "hush /does/not/exist" case */ - input = xfopen_for_read(G.global_argv[0]); + input = hfopen(G.global_argv[0]); + if (!input) { + bb_simple_perror_msg_and_die(G.global_argv[0]); + } xfunc_error_retval = 1; - remember_FILE(input); install_special_sighandlers(); parse_and_run_file(input); #if ENABLE_FEATURE_CLEAN_UP - fclose_and_forget(input); + hfclose(input); #endif goto final_return; } @@ -10038,7 +10076,7 @@ int hush_main(int argc, char **argv) ); } - parse_and_run_file(stdin); + parse_and_run_file(hfopen(NULL)); /* stdin */ final_return: hush_exit(G.last_exitcode); @@ -10849,7 +10887,7 @@ Test that VAR is a valid variable name? static int FAST_FUNC builtin_source(char **argv) { char *arg_path, *filename; - FILE *input; + HFILE *input; save_arg_t sv; char *args_need_save; #if ENABLE_HUSH_FUNCTIONS @@ -10873,10 +10911,10 @@ static int FAST_FUNC builtin_source(char **argv) return EXIT_FAILURE; } } - input = remember_FILE(fopen_or_warn(filename, "r")); + input = hfopen(filename); free(arg_path); if (!input) { - /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ + bb_perror_msg("%s", filename); /* POSIX: non-interactive shell should abort here, * not merely fail. So far no one complained :) */ @@ -10895,7 +10933,7 @@ static int FAST_FUNC builtin_source(char **argv) /* "false; . ./empty_line; echo Zero:$?" should print 0 */ G.last_exitcode = 0; parse_and_run_file(input); - fclose_and_forget(input); + hfclose(input); if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ restore_G_args(&sv, argv); diff --git a/shell/hush_test/hush-heredoc/heredocB.right b/shell/hush_test/hush-heredoc/heredocB.right new file mode 100644 index 000000000..43ba0b4f9 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocB.right @@ -0,0 +1,3 @@ +one - alpha +two - beta +three - gamma diff --git a/shell/hush_test/hush-heredoc/heredocB.tests b/shell/hush_test/hush-heredoc/heredocB.tests new file mode 100755 index 000000000..45ea4687f --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredocB.tests @@ -0,0 +1,12 @@ +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done <&- 3>&-" && \ test x"$fds" = x" 11>&- 3>&-" \ && { echo "Ok: script fd is not closed"; exit 0; } +# or we see that fd 3 moved to fd 10: +test x"$fds1" = x" 3>&- 4>&-" && \ +test x"$fds" = x" 10>&- 3>&-" \ +&& { echo "Ok: script fd is not closed"; exit 0; } echo "Bug: script fd is closed" echo "fds1:$fds1" -- cgit v1.2.3-55-g6feb From 63c42afaa43d42def05dfbca1f4e10c7314b1f77 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jul 2018 17:08:04 +0200 Subject: hush: add "heredoc.tests" from ash, tweak ash "is a function" message Signed-off-by: Denys Vlasenko --- shell/ash.c | 3 +- shell/ash_test/ash-heredoc/heredoc.right | 2 +- shell/hush_test/hush-heredoc/heredoc.right | 20 ++++++ shell/hush_test/hush-heredoc/heredoc.tests | 97 ++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 shell/hush_test/hush-heredoc/heredoc.right create mode 100755 shell/hush_test/hush-heredoc/heredoc.tests diff --git a/shell/ash.c b/shell/ash.c index 051cc671f..03fbbee53 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8512,7 +8512,8 @@ describe_command(char *command, const char *path, int describe_command_verbose) case CMDFUNCTION: if (describe_command_verbose) { - out1str(" is a shell function"); + /*out1str(" is a shell function");*/ + out1str(" is a function"); /* bash says this */ } else { out1str(command); } diff --git a/shell/ash_test/ash-heredoc/heredoc.right b/shell/ash_test/ash-heredoc/heredoc.right index baf115166..85d36dae9 100644 --- a/shell/ash_test/ash-heredoc/heredoc.right +++ b/shell/ash_test/ash-heredoc/heredoc.right @@ -16,6 +16,6 @@ tab 3 abc def ghi jkl mno -fff is a shell function +fff is a function hi there diff --git a/shell/hush_test/hush-heredoc/heredoc.right b/shell/hush_test/hush-heredoc/heredoc.right new file mode 100644 index 000000000..9b9e2aae9 --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc.right @@ -0,0 +1,20 @@ +there +one - alpha +two - beta +three - gamma +hi\ +there$a +stuff +hi\ +there +EO\ +F +hi +hi +tab 1 +tab 2 +tab 3 +abc +def ghi +jkl mno +fff is a function diff --git a/shell/hush_test/hush-heredoc/heredoc.tests b/shell/hush_test/hush-heredoc/heredoc.tests new file mode 100755 index 000000000..39345c51b --- /dev/null +++ b/shell/hush_test/hush-heredoc/heredoc.tests @@ -0,0 +1,97 @@ +# check order and content of multiple here docs + +cat << EOF1 << EOF2 +hi +EOF1 +there +EOF2 + +while read line1; do + read line2 <&3 + echo $line1 - $line2 +done < /tmp/bash-zzz << EOF +abc +EOF +cat >> /tmp/bash-zzz << EOF +def ghi +jkl mno +EOF +cat /tmp/bash-zzz +rm -f /tmp/bash-zzz + +# make sure command printing puts the here-document as the last redirection +# on the line, and the function export code preserves syntactic correctness +fff() +{ + ed /tmp/foo </dev/null +/^name/d +w +q +ENDOFINPUT +aa=1 +} + +type fff +#ash# export -f fff +#ash# ${THIS_SH} -c 'type fff' + +#hush# bash warns: "here-document at line N delimited by end-of-file", +#hush# ash allows it, +#hush# hush errors out for now: +#hush# # check that end of file delimits a here-document +#hush# # THIS MUST BE LAST! +#hush# +#hush# cat << EOF +#hush# hi +#hush# there -- cgit v1.2.3-55-g6feb From 945e9b05c910d3b946a5d5a396c5a7e075513e6e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jul 2018 18:01:22 +0200 Subject: hush: fix/explain corner cases of redirection colliding with script fd function old new delta save_fd_on_redirect 200 208 +8 run_pipe 1870 1873 +3 setup_redirects 321 322 +1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 12/0) Total: 12 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 7a1513c24..e3c6e2de9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -7470,16 +7470,54 @@ static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp) return 1; /* "we closed fd" */ } #endif + /* Are we called from setup_redirects(squirrel==NULL) + * in redirect in a [v]forked child? + */ + if (sqp == NULL) { + /* No need to move script fds. + * For NOMMU case, it's actively wrong: we'd change ->fd + * fields in memory for the parent, but parent's fds + * aren't be moved, it would use wrong fd! + * Reproducer: "cmd 3>FILE" in script. + * If we would call move_HFILEs_on_redirect(), child would: + * fcntl64(3, F_DUPFD_CLOEXEC, 10) = 10 + * close(3) = 0 + * and change ->fd to 10 if fd#3 is a script fd. WRONG. + */ + //bb_error_msg("sqp == NULL: [v]forked child"); + return 0; + } + /* If this one of script's fds? */ if (move_HFILEs_on_redirect(fd, avoid_fd)) return 1; /* yes. "we closed fd" (actually moved it) */ - /* Are we called from setup_redirects(squirrel==NULL)? Two cases: - * (1) Redirect in a forked child. - * (2) "exec 3>FILE". + /* Are we called for "exec 3>FILE"? Came through + * redirect_and_varexp_helper(squirrel=ERR_PTR) -> setup_redirects(ERR_PTR) + * This case used to fail for this script: + * exec 3>FILE + * echo Ok + * ...100000 more lines... + * echo Ok + * as follows: + * read(3, "exec 3>FILE\necho Ok\necho Ok"..., 1024) = 1024 + * open("FILE", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4 + * dup2(4, 3) = 3 + * ^^^^^^^^ oops, we lost fd#3 opened to our script! + * close(4) = 0 + * write(1, "Ok\n", 3) = 3 + * ... = 3 + * write(1, "Ok\n", 3) = 3 + * read(3, 0x94fbc08, 1024) = -1 EBADF (Bad file descriptor) + * ^^^^^^^^ oops, wrong fd!!! + * With this case separate from sqp == NULL and *after* move_HFILEs, + * it now works: */ - if (!sqp) + if (sqp == ERR_PTR) { + /* Don't preserve redirected fds: exec is _meant_ to change these */ + //bb_error_msg("sqp == ERR_PTR: exec >FILE"); return 0; + } /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */ *sqp = add_squirrel(*sqp, fd, avoid_fd); @@ -7618,7 +7656,7 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp) */ } else { /* if newfd is a script fd or saved fd, simulate EBADF */ - if (internally_opened_fd(newfd, sqp ? *sqp : NULL)) { + if (internally_opened_fd(newfd, sqp && sqp != ERR_PTR ? *sqp : NULL)) { //errno = EBADF; //bb_perror_msg_and_die("can't duplicate file descriptor"); newfd = -1; /* same effect as code above */ @@ -8633,8 +8671,8 @@ static int checkjobs_and_fg_shell(struct pipe *fg_pipe) * subshell: ( list ) [&] */ #if !ENABLE_HUSH_MODE_X -#define redirect_and_varexp_helper(command, squirrel, argv_expanded) \ - redirect_and_varexp_helper(command, squirrel) +#define redirect_and_varexp_helper(command, sqp, argv_expanded) \ + redirect_and_varexp_helper(command, sqp) #endif static int redirect_and_varexp_helper( struct command *command, @@ -8651,10 +8689,6 @@ static int redirect_and_varexp_helper( /* this takes ownership of new_env[i] elements, and frees new_env: */ set_vars_and_save_old(new_env); - /* setup_redirects acts on file descriptors, not FILEs. - * This is perfect for work that comes after exec(). - * Is it really safe for inline use? Experimentally, - * things seem to work. */ return setup_redirects(command, sqp); } static NOINLINE int run_pipe(struct pipe *pi) @@ -8855,7 +8889,10 @@ static NOINLINE int run_pipe(struct pipe *pi) */ enter_var_nest_level(); G.shadowed_vars_pp = &old_vars; - rcode = redirect_and_varexp_helper(command, /*squirrel:*/ NULL, argv_expanded); + rcode = redirect_and_varexp_helper(command, + /*squirrel:*/ ERR_PTR, + argv_expanded + ); G.shadowed_vars_pp = sv_shadowed; /* rcode=1 can be if redir file can't be opened */ -- cgit v1.2.3-55-g6feb From 81de30de05beebabfa72f2a01ec4f33e9a1923e3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jul 2018 21:12:58 +0200 Subject: gzip: unbreak FEATURE_GZIP_LEVELS, closes 11171 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index c5a1fe9b4..74d5d685f 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -333,12 +333,6 @@ struct globals { /* DECLARE(Pos, head, 1<