From 4bd70463c7e7511aea9de58876f0beacbcec1779 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 12 Jun 2023 10:19:29 +0200 Subject: libbb: pass "" rather than NULL as format string in _nomsg functions function old new delta bb_perror_nomsg_and_die 9 10 +1 bb_perror_nomsg 9 10 +1 bb_verror_msg 480 469 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 2/-11) Total: -9 bytes Signed-off-by: Denys Vlasenko --- libbb/perror_nomsg.c | 12 ++---------- libbb/perror_nomsg_and_die.c | 12 ++---------- libbb/verror_msg.c | 6 ------ 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/libbb/perror_nomsg.c b/libbb/perror_nomsg.c index a2a11cc8e..670ccbc0c 100644 --- a/libbb/perror_nomsg.c +++ b/libbb/perror_nomsg.c @@ -6,17 +6,9 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +#include "libbb.h" -/* gcc warns about a null format string, therefore we provide - * modified definition without "attribute (format)" - * instead of including libbb.h */ -//#include "libbb.h" -#include "platform.h" -extern void bb_perror_msg(const char *s, ...) FAST_FUNC; - -/* suppress gcc "no previous prototype" warning */ -void FAST_FUNC bb_perror_nomsg(void); void FAST_FUNC bb_perror_nomsg(void) { - bb_perror_msg(0); + bb_simple_perror_msg(""); } diff --git a/libbb/perror_nomsg_and_die.c b/libbb/perror_nomsg_and_die.c index 543ff5178..4151e0246 100644 --- a/libbb/perror_nomsg_and_die.c +++ b/libbb/perror_nomsg_and_die.c @@ -6,17 +6,9 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +#include "libbb.h" -/* gcc warns about a null format string, therefore we provide - * modified definition without "attribute (format)" - * instead of including libbb.h */ -//#include "libbb.h" -#include "platform.h" -extern void bb_perror_msg_and_die(const char *s, ...) FAST_FUNC; - -/* suppress gcc "no previous prototype" warning */ -void FAST_FUNC bb_perror_nomsg_and_die(void); void FAST_FUNC bb_perror_nomsg_and_die(void) { - bb_perror_msg_and_die(0); + bb_simple_perror_msg_and_die(""); } diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 71512aee2..74b608f4c 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -26,9 +26,6 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) if (!logmode) return; - if (!s) /* nomsg[_and_die] uses NULL fmt */ - s = ""; /* some libc don't like printf(NULL) */ - applet_len = strlen(applet_name) + 2; /* "applet: " */ strerr_len = strerr ? strlen(strerr) : 0; msgeol_len = strlen(msg_eol); @@ -116,9 +113,6 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) if (!logmode) return; - if (!s) /* nomsg[_and_die] uses NULL fmt */ - s = ""; /* some libc don't like printf(NULL) */ - /* Prevent "derefing type-punned ptr will break aliasing rules" */ used = vasprintf((char**)(void*)msgptr, s, p); if (used < 0) -- cgit v1.2.3-55-g6feb From 8f0e4c42c630126daafd834175b86d2b28f5b798 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 12 Jun 2023 13:12:23 +0200 Subject: udhcpd: optional BOOTP support from Adam Goldman This patch makes udhcpd respond correctly to queries from BOOTP clients. It contains the following changes: The end field, or DHCP_END option, is required in DHCP requests but optional in BOOTP requests. However, we still send an end field in all replies, because some BOOTP clients expect one in replies even if they didn't send one in the request. Requests without a DHCP_MESSAGE_TYPE are recognized as BOOTP requests and handled appropriately, instead of being discarded. We still require an RFC 1048 options field, but we allow it to be empty. Since a BOOTP client will keep using the assigned IP forever, we only send a BOOTP reply if a static lease exists for that client. BOOTP replies shouldn't contain DHCP_* options, so we omit them if there was no DHCP_MESSAGE_TYPE in the request. Options other than DHCP_* options are still sent. The options field of a BOOTP reply must be exactly 64 bytes. If we construct a reply with more than 64 bytes of options, we give up and log an error instead of sending it. udhcp_send_raw_packet already pads the options field to 64 bytes if it is too short. This implementation has been tested against an HP PA-RISC client. function old new delta .rodata 105247 105321 +74 udhcpd_main 1520 1591 +71 send_offer 419 470 +51 init_packet 81 97 +16 udhcp_init_header 75 88 +13 udhcp_scan_options 192 203 +11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 6/0 up/down: 236/0) Total: 236 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/Config.src | 7 +++++++ networking/udhcp/common.c | 10 ++++++++- networking/udhcp/common.h | 14 ++++++++++--- networking/udhcp/dhcpc.c | 2 +- networking/udhcp/dhcpd.c | 49 ++++++++++++++++++++++++++++++++++++++------- networking/udhcp/packet.c | 9 ++++++--- 6 files changed, 76 insertions(+), 15 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 7ba7f48fc..d9c501c18 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -10,6 +10,13 @@ config UDHCPD udhcpd is a DHCP server geared primarily toward embedded systems, while striving to be fully functional and RFC compliant. +config FEATURE_UDHCPD_BOOTP + bool "Answer to BOOTP requests as well" + default y + depends on UDHCPD + help + Support old BOOTP protocol too. + config FEATURE_UDHCPD_BASE_IP_ON_MAC bool "Select IP address based on client MAC" default n diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index ae818db05..ad580f38d 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -252,6 +252,14 @@ uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_sc /* option bytes: [code][len][data1][data2]..[dataLEN] */ while (1) { if (scan_state->rem <= 0) { + if (ENABLE_FEATURE_UDHCPD_BOOTP && scan_state->rem == 0) { + /* DHCP requires END option to be present. + * We are here if packet fails this condition + * (options[] are zero-padded to the end). + * Assume BOOTP packet without further checks. + */ + break; /* return NULL */ + } complain: bb_simple_error_msg("bad packet, malformed option field"); return NULL; @@ -278,7 +286,7 @@ uint8_t* FAST_FUNC udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_sc scan_state->rem = sizeof(packet->sname); continue; } - break; + break; /* return NULL */ } if (scan_state->rem <= OPT_LEN) /* [len] byte exists? */ diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 49a0b593d..3ef371a7c 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -20,8 +20,11 @@ extern const uint8_t MAC_BCAST_ADDR[6] ALIGN2; /* six all-ones */ /*** DHCP packet ***/ +#define RFC1048_MAGIC 0x63825363 +/* RFC 1048 still uses BOOTP's small buffer (4 byte cookie + 60 the rest) */ +#define RFC1048_OPTIONS_BUFSIZE 60 + /* DHCP protocol. See RFC 2131 */ -#define DHCP_MAGIC 0x63825363 #define DHCP_OPTIONS_BUFSIZE 308 #define BOOTREQUEST 1 #define BOOTREPLY 2 @@ -57,8 +60,10 @@ struct dhcp_packet { * such as 'unix' or 'gateway'; this means 'boot the named program * configured for my machine'" */ - /* BOOTP fields end here, BOOTP says optional uint8_t vend[64] follows */ - uint32_t cookie; /* DHCP magic bytes: 99,130,83,99 decimal */ + /* BOOTP fields end here, BOOTP says optional uint8_t vend[64] follows. */ + /* RFC 1048 defined this cookie value and options 0-12 and 255. */ + /* DHCP extended it and required option 255 (END) to be always present. */ + uint32_t cookie; /* RFC 1048 magic bytes: 99,130,83,99 decimal */ uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; }; #define DHCP_PKT_SNAME_LEN 64 @@ -200,6 +205,9 @@ struct dhcp_scan_state { #define SNAME_FIELD 2 /* DHCP_MESSAGE_TYPE values */ +#if ENABLE_FEATURE_UDHCPD_BOOTP +#define MSGTYPE_BOOTP 0 /* there was no TYPE option in client's packet, assuming BOOTP */ +#endif #define DHCPDISCOVER 1 /* client -> server */ #define DHCPOFFER 2 /* client <- server */ #define DHCPREQUEST 3 /* client -> server */ diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index c757fb37c..200a2fb8a 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -971,7 +971,7 @@ static NOINLINE int d4_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) } skip_udp_sum_check: - if (packet.data.cookie != htonl(DHCP_MAGIC)) { + if (packet.data.cookie != htonl(RFC1048_MAGIC)) { log1s("packet with bad magic, ignoring"); return -2; } diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 66750e2e6..2904119e5 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -649,7 +649,8 @@ static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacke packet->flags = oldpacket->flags; packet->gateway_nip = oldpacket->gateway_nip; packet->ciaddr = oldpacket->ciaddr; - udhcp_add_simple_option(packet, DHCP_SERVER_ID, server_data.server_nip); + IF_FEATURE_UDHCPD_BOOTP(if (type != MSGTYPE_BOOTP)) + udhcp_add_simple_option(packet, DHCP_SERVER_ID, server_data.server_nip); } /* Fill options field, siaddr_nip, and sname and boot_file fields. @@ -725,7 +726,12 @@ static uint32_t select_lease_time(struct dhcp_packet *packet) /* We got a DHCP DISCOVER. Send an OFFER. */ /* NOINLINE: limit stack usage in caller */ -static NOINLINE void send_offer(struct dhcp_packet *oldpacket, +#if !ENABLE_FEATURE_UDHCPD_BOOTP +#define send_offer(is_dhcp_client, ...) \ + send_offer(__VA_ARGS__) +#endif +static NOINLINE void send_offer(void *is_dhcp_client, + struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease, uint32_t requested_nip, @@ -734,7 +740,12 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, struct dhcp_packet packet; uint32_t lease_time_sec; +#if ENABLE_FEATURE_UDHCPD_BOOTP + init_packet(&packet, oldpacket, is_dhcp_client ? DHCPOFFER : MSGTYPE_BOOTP); +#else + enum { is_dhcp_client = 1 }; init_packet(&packet, oldpacket, DHCPOFFER); +#endif /* If it is a static lease, use its IP */ packet.yiaddr = static_lease_nip; @@ -784,9 +795,16 @@ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, } } - lease_time_sec = select_lease_time(oldpacket); - udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); + if (is_dhcp_client) { + lease_time_sec = select_lease_time(oldpacket); + udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); + } +/* TODO: pass "is_dhcp_client" to add_server_options(), avoid adding confusing options to BOOTP clients? */ add_server_options(&packet); + if (!is_dhcp_client && udhcp_end_option(packet.options) >= RFC1048_OPTIONS_BUFSIZE) { + bb_simple_error_msg("BOOTP reply too large, not sending"); + return; + } /* send_packet emits error message itself if it detects failure */ send_packet_verbose(&packet, "sending OFFER to %s"); @@ -1050,8 +1068,12 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) continue; } msg_type = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); - if (!msg_type || msg_type[0] < DHCP_MINTYPE || msg_type[0] > DHCP_MAXTYPE) { - bb_info_msg("no or bad message type option%s", ", ignoring packet"); + if ( + IF_FEATURE_UDHCPD_BOOTP( msg_type && ) + IF_NOT_FEATURE_UDHCPD_BOOTP( !msg_type || ) + (msg_type[0] < DHCP_MINTYPE || msg_type[0] > DHCP_MAXTYPE) + ) { + bb_info_msg("bad message type option%s", ", ignoring packet"); continue; } @@ -1086,12 +1108,25 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) move_from_unaligned32(requested_nip, requested_ip_opt); } +#if ENABLE_FEATURE_UDHCPD_BOOTP + /* Handle old BOOTP clients */ + if (!msg_type) { + log1("received %s", "BOOTP BOOTREQUEST"); + if (!static_lease_nip) { + bb_info_msg("no static lease for BOOTP client%s", ", ignoring packet"); + continue; + } + send_offer(msg_type, &packet, static_lease_nip, lease, requested_nip, arpping_ms); + continue; + } +#endif + switch (msg_type[0]) { case DHCPDISCOVER: log1("received %s", "DISCOVER"); - send_offer(&packet, static_lease_nip, lease, requested_nip, arpping_ms); + send_offer(msg_type, &packet, static_lease_nip, lease, requested_nip, arpping_ms); break; case DHCPREQUEST: diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 529978189..f9dc11d01 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -18,6 +18,8 @@ void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) memset(packet, 0, sizeof(*packet)); packet->op = BOOTREQUEST; /* if client to a server */ switch (type) { + IF_FEATURE_UDHCPD_BOOTP(case MSGTYPE_BOOTP:) + /* reply to a BOOTP (not DHCP) client */ case DHCPOFFER: case DHCPACK: case DHCPNAK: @@ -25,10 +27,11 @@ void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) } packet->htype = 1; /* ethernet */ packet->hlen = 6; - packet->cookie = htonl(DHCP_MAGIC); + packet->cookie = htonl(RFC1048_MAGIC); if (DHCP_END != 0) packet->options[0] = DHCP_END; - udhcp_add_simple_option(packet, DHCP_MESSAGE_TYPE, type); + IF_FEATURE_UDHCPD_BOOTP(if (type != MSGTYPE_BOOTP)) + udhcp_add_simple_option(packet, DHCP_MESSAGE_TYPE, type); } #endif @@ -90,7 +93,7 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) } if (bytes < offsetof(struct dhcp_packet, options) - || packet->cookie != htonl(DHCP_MAGIC) + || packet->cookie != htonl(RFC1048_MAGIC) ) { bb_simple_info_msg("packet with bad magic, ignoring"); return -2; -- cgit v1.2.3-55-g6feb From bab8828b0dad1d51d6b34e38249f0641ca64b1e9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 12 Jun 2023 16:37:19 +0200 Subject: hush: fix expansion of space in "a=${a:+$a }c" construct function old new delta encode_then_append_var_plusminus 554 552 -2 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-quoting/space_in_varexp1.right | 2 ++ shell/ash_test/ash-quoting/space_in_varexp1.tests | 6 ++++++ shell/hush.c | 2 +- shell/hush_test/hush-quoting/space_in_varexp1.right | 2 ++ shell/hush_test/hush-quoting/space_in_varexp1.tests | 6 ++++++ 5 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 shell/ash_test/ash-quoting/space_in_varexp1.right create mode 100755 shell/ash_test/ash-quoting/space_in_varexp1.tests create mode 100644 shell/hush_test/hush-quoting/space_in_varexp1.right create mode 100755 shell/hush_test/hush-quoting/space_in_varexp1.tests diff --git a/shell/ash_test/ash-quoting/space_in_varexp1.right b/shell/ash_test/ash-quoting/space_in_varexp1.right new file mode 100644 index 000000000..a617a91c3 --- /dev/null +++ b/shell/ash_test/ash-quoting/space_in_varexp1.right @@ -0,0 +1,2 @@ +1:'b c' +2:'b c' diff --git a/shell/ash_test/ash-quoting/space_in_varexp1.tests b/shell/ash_test/ash-quoting/space_in_varexp1.tests new file mode 100755 index 000000000..1589587d1 --- /dev/null +++ b/shell/ash_test/ash-quoting/space_in_varexp1.tests @@ -0,0 +1,6 @@ +a=b +a=${a:+$a }c +echo "1:'$a'" +a=b +a="${a:+$a }c" +echo "2:'$a'" diff --git a/shell/hush.c b/shell/hush.c index cdaa67a3b..dbc4aecab 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6398,7 +6398,7 @@ static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n, if (!dest.o_expflags) { if (ch == EOF) break; - if (!dquoted && strchr(G.ifs, ch)) { + if (!dquoted && !(output->o_expflags & EXP_FLAG_SINGLEWORD) && 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). */ diff --git a/shell/hush_test/hush-quoting/space_in_varexp1.right b/shell/hush_test/hush-quoting/space_in_varexp1.right new file mode 100644 index 000000000..a617a91c3 --- /dev/null +++ b/shell/hush_test/hush-quoting/space_in_varexp1.right @@ -0,0 +1,2 @@ +1:'b c' +2:'b c' diff --git a/shell/hush_test/hush-quoting/space_in_varexp1.tests b/shell/hush_test/hush-quoting/space_in_varexp1.tests new file mode 100755 index 000000000..1589587d1 --- /dev/null +++ b/shell/hush_test/hush-quoting/space_in_varexp1.tests @@ -0,0 +1,6 @@ +a=b +a=${a:+$a }c +echo "1:'$a'" +a=b +a="${a:+$a }c" +echo "2:'$a'" -- cgit v1.2.3-55-g6feb From d417193cf37ca1005830d7e16f5fa7e1d8a44209 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 12 Jun 2023 17:48:47 +0200 Subject: shell: avoid segfault on ${0::0/0~09J}. Closes 15216 function old new delta evaluate_string 1011 1053 +42 Signed-off-by: Denys Vlasenko --- shell/math.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/shell/math.c b/shell/math.c index 76d22c9bd..727c29467 100644 --- a/shell/math.c +++ b/shell/math.c @@ -577,6 +577,28 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) # endif #endif +//TODO: much better estimation than expr_len/2? Such as: +//static unsigned estimate_nums_and_names(const char *expr) +//{ +// unsigned count = 0; +// while (*(expr = skip_whitespace(expr)) != '\0') { +// const char *p; +// if (isdigit(*expr)) { +// while (isdigit(*++expr)) +// continue; +// count++; +// continue; +// } +// p = endofname(expr); +// if (p != expr) { +// expr = p; +// count++; +// continue; +// } +// } +// return count; +//} + static arith_t evaluate_string(arith_state_t *math_state, const char *expr) { @@ -584,10 +606,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) const char *errmsg; const char *start_expr = expr = skip_whitespace(expr); unsigned expr_len = strlen(expr) + 2; - /* Stack of integers */ - /* The proof that there can be no more than strlen(startbuf)/2+1 - * integers in any given correct or incorrect expression - * is left as an exercise to the reader. */ + /* Stack of integers/names */ + /* There can be no more than strlen(startbuf)/2+1 + * integers/names in any given correct or incorrect expression. + * (modulo "09v09v09v09v09v" case, + * but we have code to detect that early) + */ var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); var_or_num_t *numstackptr = numstack; /* Stack of operator tokens */ @@ -652,6 +676,13 @@ evaluate_string(arith_state_t *math_state, const char *expr) numstackptr->var = NULL; errno = 0; numstackptr->val = strto_arith_t(expr, (char**) &expr); + /* A number can't be followed by another number, or a variable name. + * We'd catch this later anyway, but this would require numstack[] + * to be twice as deep to handle strings where _every_ char is + * a new number or name. Example: 09v09v09v09v09v09v09v09v09v + */ + if (isalnum(*expr) || *expr == '_') + goto err; //bb_error_msg("val:%lld", numstackptr->val); if (errno) numstackptr->val = 0; /* bash compat */ -- cgit v1.2.3-55-g6feb From a4f30f3c70550ee6ceea6768864bfb2e3a99a887 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Jun 2023 13:55:13 +0200 Subject: shell/math: reduce stack usage function old new delta arith_apply 1123 1134 +11 arith_lookup_val 140 145 +5 evaluate_string 1053 1047 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 16/-6) Total: 10 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 66 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/shell/math.c b/shell/math.c index 727c29467..af8e691fe 100644 --- a/shell/math.c +++ b/shell/math.c @@ -236,14 +236,19 @@ typedef struct { * then '?' selects one of them based on its left side. */ arith_t second_val; - char second_val_present; - /* If NULL then it's just a number, else it's a named variable */ - char *var; +#define SECOND_VAL_VALID ((char*)(intptr_t)-1) + /* If NULL then it's just a number, if SECOND_VAL_VALID, + * it's a result of "expr : expr", else it's a named variable. + * (We use SECOND_VAL_VALID instead of a bit flag to keep + * var_or_num_t smaller, we allocate a lot of them on stack). + */ + char *var_name; } var_or_num_t; + typedef struct remembered_name { struct remembered_name *next; - const char *var; + const char *var_name; } remembered_name; @@ -253,17 +258,17 @@ evaluate_string(arith_state_t *math_state, const char *expr); static const char* arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) { - if (t->var) { - const char *p = math_state->lookupvar(t->var); + if (t->var_name && t->var_name != SECOND_VAL_VALID) { + const char *p = math_state->lookupvar(t->var_name); if (p) { remembered_name *cur; - remembered_name cur_save; + remembered_name remember; /* did we already see this name? * testcase: a=b; b=a; echo $((a)) */ for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { - if (strcmp(cur->var, t->var) == 0) { + if (strcmp(cur->var_name, t->var_name) == 0) { /* Yes */ return "expression recursion loop detected"; } @@ -271,9 +276,9 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) /* push current var name */ cur = math_state->list_of_recursed_names; - cur_save.var = t->var; - cur_save.next = cur; - math_state->list_of_recursed_names = &cur_save; + remember.var_name = t->var_name; + remember.next = cur; + math_state->list_of_recursed_names = &remember; /* recursively evaluate p as expression */ t->val = evaluate_string(math_state, p); @@ -286,7 +291,7 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) /* treat undefined var as 0 */ t->val = 0; } - return 0; + return NULL; } /* "Applying" a token means performing it on the top elements on the integer @@ -303,7 +308,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ /* There is no operator that can work without arguments */ if (NUMPTR == numstack) - goto err; + goto syntax_err; top_of_stack = NUMPTR - 1; @@ -326,15 +331,15 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ else if (op != TOK_UPLUS) { /* Binary operators */ arith_t right_side_val; - char bad_second_val; + int bad_second_val; /* Binary operators need two arguments */ if (top_of_stack == numstack) - goto err; + goto syntax_err; /* ...and they pop one */ NUMPTR = top_of_stack; /* this decrements NUMPTR */ - bad_second_val = top_of_stack->second_val_present; + bad_second_val = (top_of_stack->var_name == SECOND_VAL_VALID); if (op == TOK_CONDITIONAL) { /* ? operation */ /* Make next if (...) protect against * $((expr1 ? expr2)) - that is, missing ": expr" */ @@ -363,8 +368,10 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ /* Protect against $((expr : expr)) */ return "malformed ?: operator"; } - top_of_stack->second_val_present = op; + top_of_stack->val = rez; top_of_stack->second_val = right_side_val; + top_of_stack->var_name = SECOND_VAL_VALID; + return NULL; } else if (op == TOK_BOR || op == TOK_OR_ASSIGN) rez |= right_side_val; @@ -439,13 +446,13 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (is_assign_op(op)) { char buf[sizeof(arith_t)*3 + 2]; - if (top_of_stack->var == NULL) { + if (!top_of_stack->var_name || top_of_stack->var_name == SECOND_VAL_VALID) { /* Hmm, 1=2 ? */ - goto err; + goto syntax_err; } /* Save to shell variable */ sprintf(buf, ARITH_FMT, rez); - math_state->setvar(top_of_stack->var, buf); + math_state->setvar(top_of_stack->var_name, buf); /* After saving, make previous value for v++ or v-- */ if (op == TOK_POST_INC) rez--; @@ -455,9 +462,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ top_of_stack->val = rez; /* Erase var name, it is just a number now */ - top_of_stack->var = NULL; + top_of_stack->var_name = NULL; return NULL; - err: + syntax_err: return "arithmetic syntax error"; #undef NUMPTR } @@ -660,12 +667,11 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (p != expr) { /* Name */ size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ - numstackptr->var = alloca(var_name_size); - safe_strncpy(numstackptr->var, expr, var_name_size); + numstackptr->var_name = alloca(var_name_size); + safe_strncpy(numstackptr->var_name, expr, var_name_size); //bb_error_msg("var:'%s'", numstackptr->var); expr = p; num: - numstackptr->second_val_present = 0; numstackptr++; lasttok = TOK_NUM; continue; @@ -673,7 +679,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (isdigit(*expr)) { /* Number */ - numstackptr->var = NULL; + numstackptr->var_name = NULL; errno = 0; numstackptr->val = strto_arith_t(expr, (char**) &expr); /* A number can't be followed by another number, or a variable name. @@ -702,7 +708,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) if ((expr[0] == '+' || expr[0] == '-') && (expr[1] == expr[0]) ) { - if (numstackptr == numstack || !numstackptr[-1].var) { /* not a VAR++ */ + if (numstackptr == numstack || !numstackptr[-1].var_name) { /* not a VAR++ */ char next = skip_whitespace(expr + 2)[0]; if (!(isalpha(next) || next == '_')) { /* not a ++VAR */ //bb_error_msg("special %c%c", expr[0], expr[0]); @@ -795,14 +801,14 @@ evaluate_string(arith_state_t *math_state, const char *expr) //bb_error_msg("op == TOK_RPAREN"); if (prev_op == TOK_LPAREN) { //bb_error_msg("prev_op == TOK_LPAREN"); -//bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var); - if (numstackptr[-1].var) { +//bb_error_msg(" %p %p numstackptr[-1].var_name:'%s'", numstack, numstackptr-1, numstackptr[-1].var_name); + if (numstackptr[-1].var_name && numstackptr[-1].var_name != SECOND_VAL_VALID) { /* Expression is (var), lookup now */ errmsg = arith_lookup_val(math_state, &numstackptr[-1]); if (errmsg) goto err_with_custom_msg; /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ - numstackptr[-1].var = NULL; + numstackptr[-1].var_name = NULL; } /* Any operator directly after a * close paren should consider itself binary */ -- cgit v1.2.3-55-g6feb From 8ccb3f7b1375862f8ef82cd9d225da986b80f054 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Jun 2023 15:17:14 +0200 Subject: shell: add a few yet-failing arithmentic tests Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-assign-in-varexp.right | 3 +++ shell/ash_test/ash-arith/arith-assign-in-varexp.tests | 8 ++++++++ shell/ash_test/ash-arith/arith-comma1.right | 3 +++ shell/ash_test/ash-arith/arith-comma1.tests | 6 ++++++ shell/ash_test/ash-arith/arith-precedence1.right | 1 + shell/ash_test/ash-arith/arith-precedence1.tests | 2 ++ shell/ash_test/ash-arith/arith-ternary1.right | 5 +++++ shell/ash_test/ash-arith/arith-ternary1.tests | 12 ++++++++++++ shell/ash_test/ash-arith/arith-ternary2.right | 1 + shell/ash_test/ash-arith/arith-ternary2.tests | 2 ++ 10 files changed, 43 insertions(+) create mode 100644 shell/ash_test/ash-arith/arith-assign-in-varexp.right create mode 100755 shell/ash_test/ash-arith/arith-assign-in-varexp.tests create mode 100644 shell/ash_test/ash-arith/arith-comma1.right create mode 100755 shell/ash_test/ash-arith/arith-comma1.tests create mode 100644 shell/ash_test/ash-arith/arith-precedence1.right create mode 100755 shell/ash_test/ash-arith/arith-precedence1.tests create mode 100644 shell/ash_test/ash-arith/arith-ternary1.right create mode 100755 shell/ash_test/ash-arith/arith-ternary1.tests create mode 100644 shell/ash_test/ash-arith/arith-ternary2.right create mode 100755 shell/ash_test/ash-arith/arith-ternary2.tests diff --git a/shell/ash_test/ash-arith/arith-assign-in-varexp.right b/shell/ash_test/ash-arith/arith-assign-in-varexp.right new file mode 100644 index 000000000..06ac80a64 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-assign-in-varexp.right @@ -0,0 +1,3 @@ +20:20 +a=b=10 +b=10 diff --git a/shell/ash_test/ash-arith/arith-assign-in-varexp.tests b/shell/ash_test/ash-arith/arith-assign-in-varexp.tests new file mode 100755 index 000000000..920aaa779 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-assign-in-varexp.tests @@ -0,0 +1,8 @@ +exec 2>&1 +a='b=10' +b=3 +# The variables should evaluate left-to-right, +# thus b is set to 10 _before_ addition +echo 20:$((a + b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/ash_test/ash-arith/arith-comma1.right b/shell/ash_test/ash-arith/arith-comma1.right new file mode 100644 index 000000000..be1264cc0 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-comma1.right @@ -0,0 +1,3 @@ +10:10 +a=b=10 +b=10 diff --git a/shell/ash_test/ash-arith/arith-comma1.tests b/shell/ash_test/ash-arith/arith-comma1.tests new file mode 100755 index 000000000..f86304303 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-comma1.tests @@ -0,0 +1,6 @@ +exec 2>&1 +a='b=10' +b=3 +echo 10:$((a,b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/ash_test/ash-arith/arith-precedence1.right b/shell/ash_test/ash-arith/arith-precedence1.right new file mode 100644 index 000000000..7f407b5d2 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-precedence1.right @@ -0,0 +1 @@ +4:4 diff --git a/shell/ash_test/ash-arith/arith-precedence1.tests b/shell/ash_test/ash-arith/arith-precedence1.tests new file mode 100755 index 000000000..964ae4ee2 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-precedence1.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 4:"$((0 ? 1,2 : 3,4))" diff --git a/shell/ash_test/ash-arith/arith-ternary1.right b/shell/ash_test/ash-arith/arith-ternary1.right new file mode 100644 index 000000000..c968f1181 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary1.right @@ -0,0 +1,5 @@ +42:42 +a=0 +6:6 +a=b=+err+ +b=6 diff --git a/shell/ash_test/ash-arith/arith-ternary1.tests b/shell/ash_test/ash-arith/arith-ternary1.tests new file mode 100755 index 000000000..5a54e34b6 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary1.tests @@ -0,0 +1,12 @@ +exec 2>&1 +a=0 +# The not-taken branch should not evaluate +echo 42:$((1 ? 42 : (a+=2))) +echo "a=$a" + +a='b=+err+' +b=5 +# The not-taken branch should not even parse variables +echo 6:$((0 ? a : ++b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/ash_test/ash-arith/arith-ternary2.right b/shell/ash_test/ash-arith/arith-ternary2.right new file mode 100644 index 000000000..aa54bd925 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary2.right @@ -0,0 +1 @@ +5:5 diff --git a/shell/ash_test/ash-arith/arith-ternary2.tests b/shell/ash_test/ash-arith/arith-ternary2.tests new file mode 100755 index 000000000..eefc8e7ce --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary2.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 5:$((1?2?3?4?5:6:7:8:9)) -- cgit v1.2.3-55-g6feb From c1d7507a4d36bbeba88b09e8f0269fe81e1cb33f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Jun 2023 16:15:18 +0200 Subject: shell/math: fix one name check, other minor cleanups Signed-off-by: Denys Vlasenko --- shell/math.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/shell/math.c b/shell/math.c index af8e691fe..57eb56952 100644 --- a/shell/math.c +++ b/shell/math.c @@ -245,6 +245,9 @@ typedef struct { char *var_name; } var_or_num_t; +#define VALID_NAME(name) ((name) && (name) != SECOND_VAL_VALID) +#define NOT_NAME(name) (!(name) || (name) == SECOND_VAL_VALID) + typedef struct remembered_name { struct remembered_name *next; @@ -258,7 +261,7 @@ evaluate_string(arith_state_t *math_state, const char *expr); static const char* arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) { - if (t->var_name && t->var_name != SECOND_VAL_VALID) { + if (VALID_NAME(t->var_name)) { const char *p = math_state->lookupvar(t->var_name); if (p) { remembered_name *cur; @@ -275,16 +278,15 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) } /* push current var name */ - cur = math_state->list_of_recursed_names; remember.var_name = t->var_name; - remember.next = cur; + remember.next = math_state->list_of_recursed_names; math_state->list_of_recursed_names = &remember; /* recursively evaluate p as expression */ t->val = evaluate_string(math_state, p); /* pop current var name */ - math_state->list_of_recursed_names = cur; + math_state->list_of_recursed_names = remember.next; return math_state->errmsg; } @@ -446,7 +448,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (is_assign_op(op)) { char buf[sizeof(arith_t)*3 + 2]; - if (!top_of_stack->var_name || top_of_stack->var_name == SECOND_VAL_VALID) { + if (NOT_NAME(top_of_stack->var_name)) { /* Hmm, 1=2 ? */ goto syntax_err; } @@ -708,9 +710,11 @@ evaluate_string(arith_state_t *math_state, const char *expr) if ((expr[0] == '+' || expr[0] == '-') && (expr[1] == expr[0]) ) { - if (numstackptr == numstack || !numstackptr[-1].var_name) { /* not a VAR++ */ + if (numstackptr == numstack || NOT_NAME(numstackptr[-1].var_name)) { + /* not a VAR++ */ char next = skip_whitespace(expr + 2)[0]; - if (!(isalpha(next) || next == '_')) { /* not a ++VAR */ + if (!(isalpha(next) || next == '_')) { + /* not a ++VAR */ //bb_error_msg("special %c%c", expr[0], expr[0]); op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); expr++; @@ -802,7 +806,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (prev_op == TOK_LPAREN) { //bb_error_msg("prev_op == TOK_LPAREN"); //bb_error_msg(" %p %p numstackptr[-1].var_name:'%s'", numstack, numstackptr-1, numstackptr[-1].var_name); - if (numstackptr[-1].var_name && numstackptr[-1].var_name != SECOND_VAL_VALID) { + if (VALID_NAME(numstackptr[-1].var_name)) { /* Expression is (var), lookup now */ errmsg = arith_lookup_val(math_state, &numstackptr[-1]); if (errmsg) -- cgit v1.2.3-55-g6feb From 02378ce20c6d2df062357b6d60fc440609d203be Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Jun 2023 16:16:37 +0200 Subject: syslogd: decrease stack usage, ~50 bytes function old new delta syslogd_init - 1007 +1007 syslogd_main 1619 636 -983 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 1007/-983) Total: 24 bytes Signed-off-by: Denys Vlasenko --- sysklogd/syslogd.c | 156 +++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 75 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 6ddfd771a..20034e969 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -1002,20 +1002,63 @@ static int try_to_resolve_remote(remoteHost_t *rh) } #endif -static void do_syslogd(void) NORETURN; -static void do_syslogd(void) +/* By doing init in a separate function we decrease stack usage + * in main loop. + */ +static int NOINLINE syslogd_init(char **argv) { + int opts; + char OPTION_DECL; #if ENABLE_FEATURE_REMOTE_LOG - llist_t *item; + llist_t *remoteAddrList = NULL; #endif -#if ENABLE_FEATURE_SYSLOGD_DUP - int last_sz = -1; - char *last_buf; - char *recvbuf = G.recvbuf; -#else -#define recvbuf (G.recvbuf) + + /* No non-option params */ + opts = getopt32(argv, "^"OPTION_STR"\0""=0", OPTION_PARAM); +#if ENABLE_FEATURE_REMOTE_LOG + while (remoteAddrList) { + remoteHost_t *rh = xzalloc(sizeof(*rh)); + rh->remoteHostname = llist_pop(&remoteAddrList); + rh->remoteFD = -1; + rh->last_dns_resolve = monotonic_sec() - DNS_WAIT_SEC - 1; + llist_add_to(&G.remoteHosts, rh); + } #endif +#ifdef SYSLOGD_MARK + if (opts & OPT_mark) // -m + G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60; +#endif + //if (opts & OPT_nofork) // -n + //if (opts & OPT_outfile) // -O + if (opts & OPT_loglevel) // -l + G.logLevel = xatou_range(opt_l, 1, 8); + //if (opts & OPT_small) // -S +#if ENABLE_FEATURE_ROTATE_LOGFILE + if (opts & OPT_filesize) // -s + G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; + if (opts & OPT_rotatecnt) // -b + G.logFileRotate = xatou_range(opt_b, 0, 99); +#endif +#if ENABLE_FEATURE_IPC_SYSLOG + if (opt_C) // -Cn + G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; +#endif + /* If they have not specified remote logging, then log locally */ + if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R + option_mask32 |= OPT_locallog; +#if ENABLE_FEATURE_SYSLOGD_CFG + parse_syslogdcfg(opt_f); +#endif + + /* Store away localhost's name before the fork */ + G.hostname = safe_gethostname(); + *strchrnul(G.hostname, '.') = '\0'; + + if (!(opts & OPT_nofork)) { + bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); + } + /* Set up signal handlers (so that they interrupt read()) */ signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); @@ -1027,15 +1070,39 @@ static void do_syslogd(void) #endif xmove_fd(create_socket(), STDIN_FILENO); - if (option_mask32 & OPT_circularlog) + if (opts & OPT_circularlog) ipcsyslog_init(); - if (option_mask32 & OPT_kmsg) + if (opts & OPT_kmsg) kmsg_init(); + return opts; +} + +int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int syslogd_main(int argc UNUSED_PARAM, char **argv) +{ + int opts; +#if ENABLE_FEATURE_REMOTE_LOG + llist_t *item; +#endif +#if ENABLE_FEATURE_SYSLOGD_DUP + int last_sz = -1; + char *last_buf; + char *recvbuf; +#else +#define recvbuf (G.recvbuf) +#endif + + INIT_G(); + opts = syslogd_init(argv); + timestamp_and_log_internal("syslogd started: BusyBox v" BB_VER); write_pidfile_std_path_and_ext("syslogd"); +#if ENABLE_FEATURE_SYSLOGD_DUP + recvbuf = G.recvbuf; +#endif while (!bb_got_signal) { ssize_t sz; @@ -1070,7 +1137,7 @@ static void do_syslogd(void) sz--; } #if ENABLE_FEATURE_SYSLOGD_DUP - if ((option_mask32 & OPT_dup) && (sz == last_sz)) + if ((opts & OPT_dup) && (sz == last_sz)) if (memcmp(last_buf, recvbuf, sz) == 0) continue; last_sz = sz; @@ -1111,7 +1178,7 @@ static void do_syslogd(void) } } #endif - if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) { + if (!ENABLE_FEATURE_REMOTE_LOG || (opts & OPT_locallog)) { recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */ split_escape_and_log(recvbuf, sz); } @@ -1120,73 +1187,12 @@ static void do_syslogd(void) timestamp_and_log_internal("syslogd exiting"); remove_pidfile_std_path_and_ext("syslogd"); ipcsyslog_cleanup(); - if (option_mask32 & OPT_kmsg) + if (opts & OPT_kmsg) kmsg_cleanup(); kill_myself_with_sig(bb_got_signal); #undef recvbuf } -int syslogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int syslogd_main(int argc UNUSED_PARAM, char **argv) -{ - int opts; - char OPTION_DECL; -#if ENABLE_FEATURE_REMOTE_LOG - llist_t *remoteAddrList = NULL; -#endif - - INIT_G(); - - /* No non-option params */ - opts = getopt32(argv, "^"OPTION_STR"\0""=0", OPTION_PARAM); -#if ENABLE_FEATURE_REMOTE_LOG - while (remoteAddrList) { - remoteHost_t *rh = xzalloc(sizeof(*rh)); - rh->remoteHostname = llist_pop(&remoteAddrList); - rh->remoteFD = -1; - rh->last_dns_resolve = monotonic_sec() - DNS_WAIT_SEC - 1; - llist_add_to(&G.remoteHosts, rh); - } -#endif - -#ifdef SYSLOGD_MARK - if (opts & OPT_mark) // -m - G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60; -#endif - //if (opts & OPT_nofork) // -n - //if (opts & OPT_outfile) // -O - if (opts & OPT_loglevel) // -l - G.logLevel = xatou_range(opt_l, 1, 8); - //if (opts & OPT_small) // -S -#if ENABLE_FEATURE_ROTATE_LOGFILE - if (opts & OPT_filesize) // -s - G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; - if (opts & OPT_rotatecnt) // -b - G.logFileRotate = xatou_range(opt_b, 0, 99); -#endif -#if ENABLE_FEATURE_IPC_SYSLOG - if (opt_C) // -Cn - G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; -#endif - /* If they have not specified remote logging, then log locally */ - if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R - option_mask32 |= OPT_locallog; -#if ENABLE_FEATURE_SYSLOGD_CFG - parse_syslogdcfg(opt_f); -#endif - - /* Store away localhost's name before the fork */ - G.hostname = safe_gethostname(); - *strchrnul(G.hostname, '.') = '\0'; - - if (!(opts & OPT_nofork)) { - bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); - } - - do_syslogd(); - /* return EXIT_SUCCESS; */ -} - /* Clean up. Needed because we are included from syslogd_and_logger.c */ #undef DEBUG #undef SYSLOGD_MARK -- cgit v1.2.3-55-g6feb From 373f64eef3cc121d7531522ef654feb0a8068d5a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Jun 2023 16:25:13 +0200 Subject: syslogd: daemonize _after_ init (so that init errors are visible, if they occur) Signed-off-by: Denys Vlasenko --- sysklogd/syslogd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 20034e969..7711e467b 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -1055,6 +1055,14 @@ static int NOINLINE syslogd_init(char **argv) G.hostname = safe_gethostname(); *strchrnul(G.hostname, '.') = '\0'; + xmove_fd(create_socket(), STDIN_FILENO); + + if (opts & OPT_circularlog) + ipcsyslog_init(); + + if (opts & OPT_kmsg) + kmsg_init(); + if (!(opts & OPT_nofork)) { bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); } @@ -1068,14 +1076,6 @@ static int NOINLINE syslogd_init(char **argv) signal(SIGALRM, do_mark); alarm(G.markInterval); #endif - xmove_fd(create_socket(), STDIN_FILENO); - - if (opts & OPT_circularlog) - ipcsyslog_init(); - - if (opts & OPT_kmsg) - kmsg_init(); - return opts; } -- cgit v1.2.3-55-g6feb From 8acbf31708779e7ad559775c9db4ebd7a962be33 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Jun 2023 18:27:19 +0200 Subject: shell/math: document ternary ?: op's weirdness, add code comments Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-precedence1.right | 3 + shell/ash_test/ash-arith/arith-precedence1.tests | 13 ++++ shell/math.c | 77 +++++++++++++++--------- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/shell/ash_test/ash-arith/arith-precedence1.right b/shell/ash_test/ash-arith/arith-precedence1.right index 7f407b5d2..3f9320a13 100644 --- a/shell/ash_test/ash-arith/arith-precedence1.right +++ b/shell/ash_test/ash-arith/arith-precedence1.right @@ -1 +1,4 @@ 4:4 +4:4 +4:4 +4:4 diff --git a/shell/ash_test/ash-arith/arith-precedence1.tests b/shell/ash_test/ash-arith/arith-precedence1.tests index 964ae4ee2..bfef05292 100755 --- a/shell/ash_test/ash-arith/arith-precedence1.tests +++ b/shell/ash_test/ash-arith/arith-precedence1.tests @@ -1,2 +1,15 @@ exec 2>&1 +# bash documentation says that precedence order is: +# ... +# expr ? expr1 : expr2 +# = *= /= %= += -= <<= >>= &= ^= |= +# exprA , exprB +# but in practice, the rules for expr1 and expr2 are different: +# assignments and commas in expr1 have higher precedence than :?, +# but in expr2 they haven't: +# "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4" +# "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error) +echo 4:$((0 ? 1,2 : 3,4)) +echo 4:$((1 ? 1,2 : 3,4)) echo 4:"$((0 ? 1,2 : 3,4))" +echo 4:"$((1 ? 1,2 : 3,4))" diff --git a/shell/math.c b/shell/math.c index 57eb56952..d5f3ce361 100644 --- a/shell/math.c +++ b/shell/math.c @@ -116,6 +116,12 @@ #include "libbb.h" #include "math.h" +#if 1 +# define dbg(...) ((void)0) +#else +# define dbg(...) bb_error_msg(__VA_ARGS__) +#endif + typedef unsigned char operator; /* An operator's token id is a bit of a bitfield. The lower 5 bits are the @@ -151,6 +157,17 @@ typedef unsigned char operator; #define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0) /* Ternary conditional operator is right associative too */ +// FIXME: +// bash documentation says that precedence order is: +// ... +// expr ? expr1 : expr2 +// = *= /= %= += -= <<= >>= &= ^= |= +// exprA , exprB +// but in practice, the rules for expr1 and expr2 are different: +// assignments and commas in expr1 have higher precedence than ?:, +// but in expr2 they haven't: +// "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4" +// "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error) #define TOK_CONDITIONAL tok_decl(4,0) #define TOK_CONDITIONAL_SEP tok_decl(4,1) @@ -246,7 +263,7 @@ typedef struct { } var_or_num_t; #define VALID_NAME(name) ((name) && (name) != SECOND_VAL_VALID) -#define NOT_NAME(name) (!(name) || (name) == SECOND_VAL_VALID) +#define NOT_NAME(name) (!(name) || (name) == SECOND_VAL_VALID) typedef struct remembered_name { @@ -624,11 +641,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); var_or_num_t *numstackptr = numstack; /* Stack of operator tokens */ - operator *const stack = alloca(expr_len * sizeof(stack[0])); - operator *stackptr = stack; + operator *const opstack = alloca(expr_len * sizeof(opstack[0])); + operator *opstackptr = opstack; /* Start with a left paren */ - *stackptr++ = lasttok = TOK_LPAREN; + dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); + *opstackptr++ = lasttok = TOK_LPAREN; errmsg = NULL; while (1) { @@ -655,11 +673,11 @@ evaluate_string(arith_state_t *math_state, const char *expr) * and let the loop process it */ expr = ptr_to_rparen; //bb_error_msg("expr=')'"); - continue; + goto tok_find; } /* At this point, we're done with the expression */ if (numstackptr != numstack + 1) { - /* ...but if there isn't, it's bad */ + /* if there is not exactly one result, it's bad */ goto err; } goto ret; @@ -671,9 +689,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ numstackptr->var_name = alloca(var_name_size); safe_strncpy(numstackptr->var_name, expr, var_name_size); -//bb_error_msg("var:'%s'", numstackptr->var); + dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); expr = p; - num: + push_num: numstackptr++; lasttok = TOK_NUM; continue; @@ -684,6 +702,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) numstackptr->var_name = NULL; errno = 0; numstackptr->val = strto_arith_t(expr, (char**) &expr); + dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); /* A number can't be followed by another number, or a variable name. * We'd catch this later anyway, but this would require numstack[] * to be twice as deep to handle strings where _every_ char is @@ -691,10 +710,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) */ if (isalnum(*expr) || *expr == '_') goto err; -//bb_error_msg("val:%lld", numstackptr->val); if (errno) numstackptr->val = 0; /* bash compat */ - goto num; + goto push_num; } /* Should be an operator */ @@ -715,14 +733,13 @@ evaluate_string(arith_state_t *math_state, const char *expr) char next = skip_whitespace(expr + 2)[0]; if (!(isalpha(next) || next == '_')) { /* not a ++VAR */ - //bb_error_msg("special %c%c", expr[0], expr[0]); op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); expr++; goto tok_found1; } } } - + tok_find: p = op_tokens; while (1) { /* Compare expr to current op_tokens[] element */ @@ -799,13 +816,10 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* The algorithm employed here is simple: while we don't * hit an open paren nor the bottom of the stack, pop * tokens and apply them */ - while (stackptr != stack) { - operator prev_op = *--stackptr; + while (opstackptr != opstack) { + operator prev_op = *--opstackptr; if (op == TOK_RPAREN) { -//bb_error_msg("op == TOK_RPAREN"); if (prev_op == TOK_LPAREN) { -//bb_error_msg("prev_op == TOK_LPAREN"); -//bb_error_msg(" %p %p numstackptr[-1].var_name:'%s'", numstack, numstackptr-1, numstackptr[-1].var_name); if (VALID_NAME(numstackptr[-1].var_name)) { /* Expression is (var), lookup now */ errmsg = arith_lookup_val(math_state, &numstackptr[-1]); @@ -819,31 +833,38 @@ evaluate_string(arith_state_t *math_state, const char *expr) lasttok = TOK_NUM; goto next; } -//bb_error_msg("prev_op != TOK_LPAREN"); + /* Not (y), but ...x~y): fall through to evaluate x~y */ } else { operator prev_prec = PREC(prev_op); -//bb_error_msg("op != TOK_RPAREN"); fix_assignment_prec(prec); fix_assignment_prec(prev_prec); if (prev_prec < prec || (prev_prec == prec && is_right_associative(prec)) ) { - stackptr++; - break; + /* ...x~y@: push @ on opstack */ + opstackptr++; /* undo removal of ~ op */ + goto push_op; } + /* ...x~y@: evaluate x~y, replace it on stack with result. Then repeat */ } -//bb_error_msg("arith_apply(prev_op:%02x)", prev_op); + dbg("arith_apply(prev_op:%02x, numstack:%d)", prev_op, (int)(numstackptr - numstack)); errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); if (errmsg) goto err_with_custom_msg; - } - if (op == TOK_RPAREN) +dbg(" numstack:%d val:%lld %lld %p", (int)(numstackptr - numstack), + numstackptr[-1].val, + numstackptr[-1].var_name == SECOND_VAL_VALID ? numstackptr[-1].second_val : 0, + numstackptr[-1].var_name +); + } /* while (opstack not empty) */ + if (op == TOK_RPAREN) /* unpaired RPAREN? */ goto err; } - - /* Push this operator to the stack and remember it */ -//bb_error_msg("push op:%02x", op); - *stackptr++ = lasttok = op; + /* else: LPAREN or UNARY: push it on opstack */ + push_op: + /* Push this operator to opstack */ + dbg("(%d) op:%02x", (int)(opstackptr - opstack), op); + *opstackptr++ = lasttok = op; next: ; } /* while (1) */ -- cgit v1.2.3-55-g6feb From a02450ff0bfa45618e72fc7103ea3a8f0e7fff80 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Jun 2023 01:05:40 +0200 Subject: shell/math: remove a redundant check function old new delta arith_apply 1134 1087 -47 Signed-off-by: Denys Vlasenko --- shell/math.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/math.c b/shell/math.c index d5f3ce361..9ca7c6bb1 100644 --- a/shell/math.c +++ b/shell/math.c @@ -435,10 +435,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ c *= rez; rez = c; } - else if (right_side_val == 0) - return "divide by zero"; - else if (op == TOK_DIV || op == TOK_DIV_ASSIGN - || op == TOK_REM || op == TOK_REM_ASSIGN) { + else /*if (op == TOK_DIV || op == TOK_DIV_ASSIGN + || op == TOK_REM || op == TOK_REM_ASSIGN) - always true */ + { + if (right_side_val == 0) + return "divide by zero"; /* * bash 4.2.45 x86 64bit: SEGV on 'echo $((2**63 / -1))' * @@ -456,9 +457,8 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ } if (op == TOK_DIV || op == TOK_DIV_ASSIGN) rez /= right_side_val; - else { + else rez %= right_side_val; - } } } -- cgit v1.2.3-55-g6feb From 46dccd2ec0eafd850b2168d4dfe4e74949fd3424 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Jun 2023 11:05:48 +0200 Subject: shell/math: fix nested ?: and do not parse variables in not-taken branch Fixes arith-ternary1.tests and arith-ternary_nested.tests function old new delta evaluate_string 1043 1101 +58 arith_apply 1087 1137 +50 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 108/0) Total: 108 bytes Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-ternary1.right | 3 - shell/ash_test/ash-arith/arith-ternary1.tests | 7 -- shell/ash_test/ash-arith/arith-ternary2.right | 4 +- shell/ash_test/ash-arith/arith-ternary2.tests | 7 +- .../ash_test/ash-arith/arith-ternary_nested.right | 1 + .../ash_test/ash-arith/arith-ternary_nested.tests | 2 + shell/math.c | 80 +++++++++++++--------- 7 files changed, 61 insertions(+), 43 deletions(-) create mode 100644 shell/ash_test/ash-arith/arith-ternary_nested.right create mode 100755 shell/ash_test/ash-arith/arith-ternary_nested.tests diff --git a/shell/ash_test/ash-arith/arith-ternary1.right b/shell/ash_test/ash-arith/arith-ternary1.right index c968f1181..6b751d7b8 100644 --- a/shell/ash_test/ash-arith/arith-ternary1.right +++ b/shell/ash_test/ash-arith/arith-ternary1.right @@ -1,5 +1,2 @@ 42:42 a=0 -6:6 -a=b=+err+ -b=6 diff --git a/shell/ash_test/ash-arith/arith-ternary1.tests b/shell/ash_test/ash-arith/arith-ternary1.tests index 5a54e34b6..3532ce54d 100755 --- a/shell/ash_test/ash-arith/arith-ternary1.tests +++ b/shell/ash_test/ash-arith/arith-ternary1.tests @@ -3,10 +3,3 @@ a=0 # The not-taken branch should not evaluate echo 42:$((1 ? 42 : (a+=2))) echo "a=$a" - -a='b=+err+' -b=5 -# The not-taken branch should not even parse variables -echo 6:$((0 ? a : ++b)) -echo "a=$a" -echo "b=$b" diff --git a/shell/ash_test/ash-arith/arith-ternary2.right b/shell/ash_test/ash-arith/arith-ternary2.right index aa54bd925..a549b1b5c 100644 --- a/shell/ash_test/ash-arith/arith-ternary2.right +++ b/shell/ash_test/ash-arith/arith-ternary2.right @@ -1 +1,3 @@ -5:5 +6:6 +a=b=+err+ +b=6 diff --git a/shell/ash_test/ash-arith/arith-ternary2.tests b/shell/ash_test/ash-arith/arith-ternary2.tests index eefc8e7ce..cb3163932 100755 --- a/shell/ash_test/ash-arith/arith-ternary2.tests +++ b/shell/ash_test/ash-arith/arith-ternary2.tests @@ -1,2 +1,7 @@ exec 2>&1 -echo 5:$((1?2?3?4?5:6:7:8:9)) +a='b=+err+' +b=5 +# The not-taken branch should not parse variables +echo 6:$((0 ? a : ++b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/ash_test/ash-arith/arith-ternary_nested.right b/shell/ash_test/ash-arith/arith-ternary_nested.right new file mode 100644 index 000000000..aa54bd925 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested.right @@ -0,0 +1 @@ +5:5 diff --git a/shell/ash_test/ash-arith/arith-ternary_nested.tests b/shell/ash_test/ash-arith/arith-ternary_nested.tests new file mode 100755 index 000000000..eefc8e7ce --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 5:$((1?2?3?4?5:6:7:8:9)) diff --git a/shell/math.c b/shell/math.c index 9ca7c6bb1..2b7a3494f 100644 --- a/shell/math.c +++ b/shell/math.c @@ -331,6 +331,28 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ top_of_stack = NUMPTR - 1; + if (op == TOK_CONDITIONAL_SEP) { + /* "expr1 ? expr2 : expr3" operation */ + var_or_num_t *expr1 = &top_of_stack[-2]; + if (expr1 < numstack) { + return "malformed ?: operator"; + } + err = arith_lookup_val(math_state, expr1); + if (err) + return err; + if (expr1->val != 0) /* select expr2 or expr3 */ + top_of_stack--; + err = arith_lookup_val(math_state, top_of_stack); + if (err) + return err; + NUMPTR = expr1 + 1; + expr1->val = top_of_stack->val; + expr1->var_name = NULL; + return NULL; + } + if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */ + return "malformed ?: operator"; + /* Resolve name to value, if needed */ err = arith_lookup_val(math_state, top_of_stack); if (err) @@ -350,25 +372,12 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ else if (op != TOK_UPLUS) { /* Binary operators */ arith_t right_side_val; - int bad_second_val; /* Binary operators need two arguments */ if (top_of_stack == numstack) goto syntax_err; /* ...and they pop one */ NUMPTR = top_of_stack; /* this decrements NUMPTR */ - - bad_second_val = (top_of_stack->var_name == SECOND_VAL_VALID); - if (op == TOK_CONDITIONAL) { /* ? operation */ - /* Make next if (...) protect against - * $((expr1 ? expr2)) - that is, missing ": expr" */ - bad_second_val = !bad_second_val; - } - if (bad_second_val) { - /* Protect against $((expr expr1 : expr2)) */ - return "malformed ?: operator"; - } - top_of_stack--; /* now points to left side */ if (op != TOK_ASSIGN) { @@ -380,19 +389,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ right_side_val = rez; rez = top_of_stack->val; - if (op == TOK_CONDITIONAL) /* ? operation */ - rez = (rez ? right_side_val : top_of_stack[1].second_val); - else if (op == TOK_CONDITIONAL_SEP) { /* : operation */ - if (top_of_stack == numstack) { - /* Protect against $((expr : expr)) */ - return "malformed ?: operator"; - } - top_of_stack->val = rez; - top_of_stack->second_val = right_side_val; - top_of_stack->var_name = SECOND_VAL_VALID; - return NULL; - } - else if (op == TOK_BOR || op == TOK_OR_ASSIGN) + if (op == TOK_BOR || op == TOK_OR_ASSIGN) rez |= right_side_val; else if (op == TOK_OR) rez = right_side_val || rez; @@ -833,7 +830,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) lasttok = TOK_NUM; goto next; } - /* Not (y), but ...x~y): fall through to evaluate x~y */ + /* Not (y), but ...x~y). Fall through to evaluate x~y */ } else { operator prev_prec = PREC(prev_op); fix_assignment_prec(prec); @@ -841,11 +838,17 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (prev_prec < prec || (prev_prec == prec && is_right_associative(prec)) ) { - /* ...x~y@: push @ on opstack */ - opstackptr++; /* undo removal of ~ op */ - goto push_op; + /* Unless a?b?c:d:... and we are at the second : */ + if (op != TOK_CONDITIONAL_SEP + || prev_op != TOK_CONDITIONAL_SEP + ) { + /* ...x~y@: push @ on opstack */ + opstackptr++; /* undo removal of ~ op */ + goto push_op; + } + /* else: a?b?c:d:. Evaluate b?c:d, replace it on stack with result. Then repeat */ } - /* ...x~y@: evaluate x~y, replace it on stack with result. Then repeat */ + /* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */ } dbg("arith_apply(prev_op:%02x, numstack:%d)", prev_op, (int)(numstackptr - numstack)); errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); @@ -856,6 +859,21 @@ dbg(" numstack:%d val:%lld %lld %p", (int)(numstackptr - numstack), numstackptr[-1].var_name == SECOND_VAL_VALID ? numstackptr[-1].second_val : 0, numstackptr[-1].var_name ); + /* For ternary ?: we need to remove ? from opstack too, not just : */ + if (prev_op == TOK_CONDITIONAL_SEP) { + // This is caught in arith_apply() + //if (opstackptr == opstack) { + // /* Example: $((2:3)) */ + // errmsg = "where is your ? in ?:"; + // goto err_with_custom_msg; + //} + opstackptr--; + if (*opstackptr != TOK_CONDITIONAL) { + /* Example: $((1,2:3)) */ + errmsg = "malformed ?: operator"; + goto err_with_custom_msg; + } + } } /* while (opstack not empty) */ if (op == TOK_RPAREN) /* unpaired RPAREN? */ goto err; -- cgit v1.2.3-55-g6feb From 5febdb122357dbe39e236c9e93d06dab328edb45 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Jun 2023 11:10:45 +0200 Subject: shell/math: remove now-unused second_val function old new delta arith_apply 1137 1134 -3 evaluate_string 1101 1095 -6 arith_lookup_val 150 143 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-16) Total: -16 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/shell/math.c b/shell/math.c index 2b7a3494f..fa22bc400 100644 --- a/shell/math.c +++ b/shell/math.c @@ -246,24 +246,11 @@ is_right_associative(operator prec) typedef struct { arith_t val; - /* We acquire second_val only when "expr1 : expr2" part - * of ternary ?: op is evaluated. - * We treat ?: as two binary ops: (expr ? (expr1 : expr2)). - * ':' produces a new value which has two parts, val and second_val; - * then '?' selects one of them based on its left side. - */ - arith_t second_val; -#define SECOND_VAL_VALID ((char*)(intptr_t)-1) - /* If NULL then it's just a number, if SECOND_VAL_VALID, - * it's a result of "expr : expr", else it's a named variable. - * (We use SECOND_VAL_VALID instead of a bit flag to keep - * var_or_num_t smaller, we allocate a lot of them on stack). - */ char *var_name; } var_or_num_t; -#define VALID_NAME(name) ((name) && (name) != SECOND_VAL_VALID) -#define NOT_NAME(name) (!(name) || (name) == SECOND_VAL_VALID) +#define VALID_NAME(name) (name) +#define NOT_NAME(name) (!(name)) typedef struct remembered_name { @@ -854,11 +841,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); if (errmsg) goto err_with_custom_msg; -dbg(" numstack:%d val:%lld %lld %p", (int)(numstackptr - numstack), - numstackptr[-1].val, - numstackptr[-1].var_name == SECOND_VAL_VALID ? numstackptr[-1].second_val : 0, - numstackptr[-1].var_name -); +dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[-1].val, numstackptr[-1].var_name); /* For ternary ?: we need to remove ? from opstack too, not just : */ if (prev_op == TOK_CONDITIONAL_SEP) { // This is caught in arith_apply() -- cgit v1.2.3-55-g6feb From 3df885abe340c5feaed212536139ee24d60e40a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Jun 2023 11:33:59 +0200 Subject: shell/math: fix the order of variable resolution in binops function old new delta arith_apply 1134 1143 +9 Signed-off-by: Denys Vlasenko --- .../hush-arith/arith-assign-in-varexp.right | 3 +++ .../hush-arith/arith-assign-in-varexp.tests | 8 +++++++ shell/hush_test/hush-arith/arith-comma1.right | 3 +++ shell/hush_test/hush-arith/arith-comma1.tests | 6 +++++ shell/hush_test/hush-arith/arith-ternary2.right | 3 +++ shell/hush_test/hush-arith/arith-ternary2.tests | 7 ++++++ .../hush-arith/arith-ternary_nested.right | 1 + .../hush-arith/arith-ternary_nested.tests | 2 ++ shell/math.c | 27 ++++++++++++---------- 9 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 shell/hush_test/hush-arith/arith-assign-in-varexp.right create mode 100755 shell/hush_test/hush-arith/arith-assign-in-varexp.tests create mode 100644 shell/hush_test/hush-arith/arith-comma1.right create mode 100755 shell/hush_test/hush-arith/arith-comma1.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary2.right create mode 100755 shell/hush_test/hush-arith/arith-ternary2.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary_nested.right create mode 100755 shell/hush_test/hush-arith/arith-ternary_nested.tests diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp.right b/shell/hush_test/hush-arith/arith-assign-in-varexp.right new file mode 100644 index 000000000..06ac80a64 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-assign-in-varexp.right @@ -0,0 +1,3 @@ +20:20 +a=b=10 +b=10 diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp.tests b/shell/hush_test/hush-arith/arith-assign-in-varexp.tests new file mode 100755 index 000000000..920aaa779 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-assign-in-varexp.tests @@ -0,0 +1,8 @@ +exec 2>&1 +a='b=10' +b=3 +# The variables should evaluate left-to-right, +# thus b is set to 10 _before_ addition +echo 20:$((a + b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/hush_test/hush-arith/arith-comma1.right b/shell/hush_test/hush-arith/arith-comma1.right new file mode 100644 index 000000000..be1264cc0 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-comma1.right @@ -0,0 +1,3 @@ +10:10 +a=b=10 +b=10 diff --git a/shell/hush_test/hush-arith/arith-comma1.tests b/shell/hush_test/hush-arith/arith-comma1.tests new file mode 100755 index 000000000..f86304303 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-comma1.tests @@ -0,0 +1,6 @@ +exec 2>&1 +a='b=10' +b=3 +echo 10:$((a,b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/hush_test/hush-arith/arith-ternary2.right b/shell/hush_test/hush-arith/arith-ternary2.right new file mode 100644 index 000000000..a549b1b5c --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.right @@ -0,0 +1,3 @@ +6:6 +a=b=+err+ +b=6 diff --git a/shell/hush_test/hush-arith/arith-ternary2.tests b/shell/hush_test/hush-arith/arith-ternary2.tests new file mode 100755 index 000000000..cb3163932 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.tests @@ -0,0 +1,7 @@ +exec 2>&1 +a='b=+err+' +b=5 +# The not-taken branch should not parse variables +echo 6:$((0 ? a : ++b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/hush_test/hush-arith/arith-ternary_nested.right b/shell/hush_test/hush-arith/arith-ternary_nested.right new file mode 100644 index 000000000..aa54bd925 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested.right @@ -0,0 +1 @@ +5:5 diff --git a/shell/hush_test/hush-arith/arith-ternary_nested.tests b/shell/hush_test/hush-arith/arith-ternary_nested.tests new file mode 100755 index 000000000..eefc8e7ce --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 5:$((1?2?3?4?5:6:7:8:9)) diff --git a/shell/math.c b/shell/math.c index fa22bc400..077aba848 100644 --- a/shell/math.c +++ b/shell/math.c @@ -340,7 +340,20 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */ return "malformed ?: operator"; - /* Resolve name to value, if needed */ + if (PREC(op) < UNARYPREC) { + /* In binops a ~ b, variables are resolved left-to-right, + * resolve top_of_stack[-1] _before_ resolving top_of_stack[0] + */ + if (top_of_stack == numstack) /* need two arguments */ + goto syntax_err; + /* Unless it is =, resolve top_of_stack[-1] name to value */ + if (op != TOK_ASSIGN) { + err = arith_lookup_val(math_state, top_of_stack - 1); + if (err) + return err; + } + } + /* Resolve top_of_stack[0] name to value */ err = arith_lookup_val(math_state, top_of_stack); if (err) return err; @@ -360,20 +373,10 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ /* Binary operators */ arith_t right_side_val; - /* Binary operators need two arguments */ - if (top_of_stack == numstack) - goto syntax_err; - /* ...and they pop one */ + /* Pop numstack */ NUMPTR = top_of_stack; /* this decrements NUMPTR */ top_of_stack--; /* now points to left side */ - if (op != TOK_ASSIGN) { - /* Resolve left side value (unless the op is '=') */ - err = arith_lookup_val(math_state, top_of_stack); - if (err) - return err; - } - right_side_val = rez; rez = top_of_stack->val; if (op == TOK_BOR || op == TOK_OR_ASSIGN) -- cgit v1.2.3-55-g6feb From 66139330fc09384f2ce95e60ea1f5268badbafc9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Jun 2023 13:59:11 +0200 Subject: shell/math: trivial code shrink function old new delta arith_apply 1143 1132 -11 Signed-off-by: Denys Vlasenko --- shell/math.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/shell/math.c b/shell/math.c index 077aba848..c1bf324f8 100644 --- a/shell/math.c +++ b/shell/math.c @@ -321,9 +321,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (op == TOK_CONDITIONAL_SEP) { /* "expr1 ? expr2 : expr3" operation */ var_or_num_t *expr1 = &top_of_stack[-2]; - if (expr1 < numstack) { + NUMPTR = expr1 + 1; + if (expr1 < numstack) /* Example: $((2:3)) */ return "malformed ?: operator"; - } err = arith_lookup_val(math_state, expr1); if (err) return err; @@ -332,7 +332,6 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ err = arith_lookup_val(math_state, top_of_stack); if (err) return err; - NUMPTR = expr1 + 1; expr1->val = top_of_stack->val; expr1->var_name = NULL; return NULL; @@ -343,7 +342,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (PREC(op) < UNARYPREC) { /* In binops a ~ b, variables are resolved left-to-right, * resolve top_of_stack[-1] _before_ resolving top_of_stack[0] - */ + */ if (top_of_stack == numstack) /* need two arguments */ goto syntax_err; /* Unless it is =, resolve top_of_stack[-1] name to value */ -- cgit v1.2.3-55-g6feb From 2ff01bb699d80cb7d24a93e812cc91c54be5cc20 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Jun 2023 15:19:02 +0200 Subject: shell: sync ash/hush test scripts Signed-off-by: Denys Vlasenko --- shell/ash_test/run-all | 21 +++++++++++++++++---- shell/hush_test/run-all | 12 ++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/shell/ash_test/run-all b/shell/ash_test/run-all index 96703ef12..066327dc0 100755 --- a/shell/ash_test/run-all +++ b/shell/ash_test/run-all @@ -47,6 +47,7 @@ do_test() # $1 but with / replaced by # so that it can be used as filename part noslash=`echo "$1" | sed 's:/:#:g'` ( + tret=0 cd "$1" || { echo "cannot cd $1!"; exit 1; } for x in run-*; do test -f "$x" || continue @@ -69,13 +70,25 @@ do_test() test -f "$name.right" || continue # echo Running test: "$x" echo -n "$1/$x:" - { + ( "$THIS_SH" "./$x" 2>&1 | \ - grep -va "^ash: using fallback suid method$" >"$name.xx" + grep -va "^ash: using fallback suid method$" >"$name.xx" + r=$? + # filter C library differences + sed -i \ + -e "/: invalid option /s:'::g" \ + "$name.xx" + test $r -eq 77 && rm -f "$TOPDIR/$noslash-$x.fail" && exit 77 diff -u "$name.xx" "$name.right" >"$TOPDIR/$noslash-$x.fail" \ && rm -f "$name.xx" "$TOPDIR/$noslash-$x.fail" - } && echo " ok" || echo " fail" + ) + case $? in + 0) echo " ok";; + 77) echo " skip (feature disabled)";; + *) echo " fail ($?)"; tret=1;; + esac done + exit $tret ) } @@ -103,4 +116,4 @@ else done fi -exit ${ret} +exit $ret diff --git a/shell/hush_test/run-all b/shell/hush_test/run-all index 3fbc7c531..7345fee43 100755 --- a/shell/hush_test/run-all +++ b/shell/hush_test/run-all @@ -29,7 +29,7 @@ fi eval $(sed -e '/^#/d' -e '/^$/d' -e 's:^:export :' .config) -PATH="`pwd`:$PATH" # for hush and recho/zecho/printenv +PATH="`pwd`:$PATH" # for hush export PATH THIS_SH="`pwd`/hush" @@ -67,7 +67,8 @@ do_test() # echo Running test: "$x" echo -n "$1/$x:" ( - "$THIS_SH" "./$x" >"$name.xx" 2>&1 + "$THIS_SH" "./$x" 2>&1 | \ + grep -va "^hush: using fallback suid method$" >"$name.xx" r=$? # filter C library differences sed -i \ @@ -83,7 +84,7 @@ do_test() *) echo " fail ($?)"; tret=1;; esac done - exit ${tret} + exit $tret ) } @@ -95,6 +96,9 @@ ret=0 if [ $# -lt 1 ]; then # All sub directories modules=`ls -d hush-*` + # If you want to test hush against ash testsuite + # (have to copy ash_test dir to current dir first): + #modules=`ls -d hush-* ash_test/ash-*` for module in $modules; do do_test $module || ret=1 @@ -108,4 +112,4 @@ else done fi -exit ${ret} +exit $ret -- cgit v1.2.3-55-g6feb From 3829d8b6758439251fc3e34dcedf5910d039b07d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 09:19:48 +0200 Subject: shell/math: simpler insertion of "fake" last RPAREN Skip one pass through token table, since we know the result. function old new delta evaluate_string 1095 1097 +2 Signed-off-by: Denys Vlasenko --- shell/math.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/math.c b/shell/math.c index c1bf324f8..748c3b3ad 100644 --- a/shell/math.c +++ b/shell/math.c @@ -518,7 +518,7 @@ static const char op_tokens[] ALIGN1 = { '(', 0, TOK_LPAREN, 0 }; -#define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7]) +#define END_POINTER (&op_tokens[sizeof(op_tokens)-1]) #if ENABLE_FEATURE_SH_MATH_BASE static arith_t strto_arith_t(const char *nptr, char **endptr) @@ -653,13 +653,13 @@ evaluate_string(arith_state_t *math_state, const char *expr) * are to be applied in order. At the end, there should be a final * result on the integer stack */ - if (expr != ptr_to_rparen + 1) { + if (expr != END_POINTER) { /* If we haven't done so already, * append a closing right paren * and let the loop process it */ - expr = ptr_to_rparen; -//bb_error_msg("expr=')'"); - goto tok_find; + expr = END_POINTER; + op = TOK_RPAREN; + goto tok_found1; } /* At this point, we're done with the expression */ if (numstackptr != numstack + 1) { @@ -725,7 +725,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) } } } - tok_find: + p = op_tokens; while (1) { /* Compare expr to current op_tokens[] element */ @@ -792,7 +792,6 @@ evaluate_string(arith_state_t *math_state, const char *expr) * "applied" in this way. */ prec = PREC(op); -//bb_error_msg("prec:%02x", prec); if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { /* not left paren or unary */ if (lasttok != TOK_NUM) { -- cgit v1.2.3-55-g6feb From 5f56a0388271d2de6cf31af1041bdcb3d11029fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 10:07:12 +0200 Subject: shell/math: fix parsing of ?: and explain why it's parsed that way This fixes arith-precedence1.tests. This breaks arith-ternary2.tests again (we now evaluate variables on not-taken branches). We need a better logic here anyway: not only bare variables should not evaluate when not-taken: 1 ? eval_me : do_not_eval but any (arbitrarily complex) expressions shouldn't evaluate as well! 1 ? var_is_set=1 : ((var_is_not_set=2,var2*=4)) function old new delta evaluate_string 1097 1148 +51 Signed-off-by: Denys Vlasenko --- .../ash_test/ash-arith/arith-ternary_nested1.right | 1 + .../ash_test/ash-arith/arith-ternary_nested1.tests | 2 + shell/ash_test/ash-arith/arith.right | 2 +- shell/hush_test/hush-arith/arith-precedence1.right | 4 ++ shell/hush_test/hush-arith/arith-precedence1.tests | 15 +++++++ shell/hush_test/hush-arith/arith-ternary2.right | 3 -- shell/hush_test/hush-arith/arith-ternary2.tests | 7 ---- .../hush-arith/arith-ternary_nested1.right | 1 + .../hush-arith/arith-ternary_nested1.tests | 2 + shell/hush_test/hush-arith/arith.right | 2 +- shell/math.c | 48 +++++++++++++++------- 11 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 shell/ash_test/ash-arith/arith-ternary_nested1.right create mode 100755 shell/ash_test/ash-arith/arith-ternary_nested1.tests create mode 100644 shell/hush_test/hush-arith/arith-precedence1.right create mode 100755 shell/hush_test/hush-arith/arith-precedence1.tests delete mode 100644 shell/hush_test/hush-arith/arith-ternary2.right delete mode 100755 shell/hush_test/hush-arith/arith-ternary2.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary_nested1.right create mode 100755 shell/hush_test/hush-arith/arith-ternary_nested1.tests diff --git a/shell/ash_test/ash-arith/arith-ternary_nested1.right b/shell/ash_test/ash-arith/arith-ternary_nested1.right new file mode 100644 index 000000000..d80319695 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested1.right @@ -0,0 +1 @@ +3:3 diff --git a/shell/ash_test/ash-arith/arith-ternary_nested1.tests b/shell/ash_test/ash-arith/arith-ternary_nested1.tests new file mode 100755 index 000000000..469584bea --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested1.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 3:$((1?(2?(3):4):5)) diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 61fcab55e..8bc78b8d1 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -92,7 +92,7 @@ ghi ./arith.tests: line 190: arithmetic syntax error 16 16 ./arith.tests: line 195: arithmetic syntax error -./arith.tests: line 196: malformed ?: operator +./arith.tests: line 196: arithmetic syntax error ./arith.tests: line 197: arithmetic syntax error 9 9 ./arith.tests: line 204: arithmetic syntax error diff --git a/shell/hush_test/hush-arith/arith-precedence1.right b/shell/hush_test/hush-arith/arith-precedence1.right new file mode 100644 index 000000000..3f9320a13 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-precedence1.right @@ -0,0 +1,4 @@ +4:4 +4:4 +4:4 +4:4 diff --git a/shell/hush_test/hush-arith/arith-precedence1.tests b/shell/hush_test/hush-arith/arith-precedence1.tests new file mode 100755 index 000000000..bfef05292 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-precedence1.tests @@ -0,0 +1,15 @@ +exec 2>&1 +# bash documentation says that precedence order is: +# ... +# expr ? expr1 : expr2 +# = *= /= %= += -= <<= >>= &= ^= |= +# exprA , exprB +# but in practice, the rules for expr1 and expr2 are different: +# assignments and commas in expr1 have higher precedence than :?, +# but in expr2 they haven't: +# "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4" +# "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error) +echo 4:$((0 ? 1,2 : 3,4)) +echo 4:$((1 ? 1,2 : 3,4)) +echo 4:"$((0 ? 1,2 : 3,4))" +echo 4:"$((1 ? 1,2 : 3,4))" diff --git a/shell/hush_test/hush-arith/arith-ternary2.right b/shell/hush_test/hush-arith/arith-ternary2.right deleted file mode 100644 index a549b1b5c..000000000 --- a/shell/hush_test/hush-arith/arith-ternary2.right +++ /dev/null @@ -1,3 +0,0 @@ -6:6 -a=b=+err+ -b=6 diff --git a/shell/hush_test/hush-arith/arith-ternary2.tests b/shell/hush_test/hush-arith/arith-ternary2.tests deleted file mode 100755 index cb3163932..000000000 --- a/shell/hush_test/hush-arith/arith-ternary2.tests +++ /dev/null @@ -1,7 +0,0 @@ -exec 2>&1 -a='b=+err+' -b=5 -# The not-taken branch should not parse variables -echo 6:$((0 ? a : ++b)) -echo "a=$a" -echo "b=$b" diff --git a/shell/hush_test/hush-arith/arith-ternary_nested1.right b/shell/hush_test/hush-arith/arith-ternary_nested1.right new file mode 100644 index 000000000..d80319695 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested1.right @@ -0,0 +1 @@ +3:3 diff --git a/shell/hush_test/hush-arith/arith-ternary_nested1.tests b/shell/hush_test/hush-arith/arith-ternary_nested1.tests new file mode 100755 index 000000000..469584bea --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested1.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 3:$((1?(2?(3):4):5)) diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index a8612295e..df8154f97 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -94,7 +94,7 @@ ghi hush: arithmetic syntax error 16 16 hush: arithmetic syntax error -hush: malformed ?: operator +hush: arithmetic syntax error hush: arithmetic syntax error 9 9 hush: arithmetic syntax error diff --git a/shell/math.c b/shell/math.c index 748c3b3ad..f6aa02ac2 100644 --- a/shell/math.c +++ b/shell/math.c @@ -157,17 +157,17 @@ typedef unsigned char operator; #define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0) /* Ternary conditional operator is right associative too */ -// FIXME: -// bash documentation says that precedence order is: -// ... -// expr ? expr1 : expr2 -// = *= /= %= += -= <<= >>= &= ^= |= -// exprA , exprB -// but in practice, the rules for expr1 and expr2 are different: -// assignments and commas in expr1 have higher precedence than ?:, -// but in expr2 they haven't: -// "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4" -// "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error) +/* + * bash documentation says that precedence order is: + * ... + * expr ? expr1 : expr2 + * = *= /= %= += -= <<= >>= &= ^= |= + * exprA , exprB + * What it omits is that expr1 is parsed as if parenthesized + * (this matches the rules of ?: in C language): + * "v ? 1,2 : 3,4" is parsed as "(v ? (1,2) : 3),4" + * "v ? a=2 : b=4" is parsed as "(v ? (a=1) : b)=4" (thus, this is a syntax error) + */ #define TOK_CONDITIONAL tok_decl(4,0) #define TOK_CONDITIONAL_SEP tok_decl(4,1) @@ -629,6 +629,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* Stack of operator tokens */ operator *const opstack = alloca(expr_len * sizeof(opstack[0])); operator *opstackptr = opstack; + operator insert_op = 0xff; /* Start with a left paren */ dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); @@ -751,11 +752,24 @@ evaluate_string(arith_state_t *math_state, const char *expr) goto err; } } + /* NB: expr now points past the operator */ tok_found: op = p[1]; /* fetch TOK_foo value */ - tok_found1: - /* NB: expr now points past the operator */ + /* Special rule for "? EXPR :" + * "EXPR in the middle of ? : is parsed as if parenthesized" + * (this quirk originates in C grammar, I think). + */ + if (op == TOK_CONDITIONAL) { + insert_op = TOK_LPAREN; + dbg("insert_op=%02x", insert_op); + } + if (op == TOK_CONDITIONAL_SEP) { + insert_op = op; + op = TOK_RPAREN; + dbg("insert_op=%02x op=%02x", insert_op, op); + } + tok_found1: /* post grammar: a++ reduce to num */ if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC) lasttok = TOK_NUM; @@ -865,9 +879,15 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ /* else: LPAREN or UNARY: push it on opstack */ push_op: /* Push this operator to opstack */ - dbg("(%d) op:%02x", (int)(opstackptr - opstack), op); + dbg("(%d) op:%02x insert_op:%02x", (int)(opstackptr - opstack), op, insert_op); *opstackptr++ = lasttok = op; next: ; + if (insert_op != 0xff) { + op = insert_op; + insert_op = 0xff; + dbg("inserting %02x", op); + goto tok_found1; + } } /* while (1) */ err: -- cgit v1.2.3-55-g6feb From 61a4959251667751e424e600c6cb75de39d6b1c3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 11:19:15 +0200 Subject: shell/math: remove special code to handle a?b?c:d:e, it works without it now The "hack" to virtually parenthesize ? EXPR : made this unnecessary. The expression is effectively a?(b?(c):d):e and thus b?c:d is evaluated before continuing with the second : function old new delta evaluate_string 1148 1132 -16 Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-ternary_nested2.right | 1 + shell/ash_test/ash-arith/arith-ternary_nested2.tests | 2 ++ shell/hush_test/hush-arith/arith-ternary_nested2.right | 1 + shell/hush_test/hush-arith/arith-ternary_nested2.tests | 2 ++ shell/math.c | 12 +++--------- 5 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 shell/ash_test/ash-arith/arith-ternary_nested2.right create mode 100755 shell/ash_test/ash-arith/arith-ternary_nested2.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary_nested2.right create mode 100755 shell/hush_test/hush-arith/arith-ternary_nested2.tests diff --git a/shell/ash_test/ash-arith/arith-ternary_nested2.right b/shell/ash_test/ash-arith/arith-ternary_nested2.right new file mode 100644 index 000000000..d80319695 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested2.right @@ -0,0 +1 @@ +3:3 diff --git a/shell/ash_test/ash-arith/arith-ternary_nested2.tests b/shell/ash_test/ash-arith/arith-ternary_nested2.tests new file mode 100755 index 000000000..e8b8a9e1a --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested2.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 3:$((0?1:2?3:4?5:6?7:8)) diff --git a/shell/hush_test/hush-arith/arith-ternary_nested2.right b/shell/hush_test/hush-arith/arith-ternary_nested2.right new file mode 100644 index 000000000..d80319695 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested2.right @@ -0,0 +1 @@ +3:3 diff --git a/shell/hush_test/hush-arith/arith-ternary_nested2.tests b/shell/hush_test/hush-arith/arith-ternary_nested2.tests new file mode 100755 index 000000000..e8b8a9e1a --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested2.tests @@ -0,0 +1,2 @@ +exec 2>&1 +echo 3:$((0?1:2?3:4?5:6?7:8)) diff --git a/shell/math.c b/shell/math.c index f6aa02ac2..8d0c9dea7 100644 --- a/shell/math.c +++ b/shell/math.c @@ -840,15 +840,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (prev_prec < prec || (prev_prec == prec && is_right_associative(prec)) ) { - /* Unless a?b?c:d:... and we are at the second : */ - if (op != TOK_CONDITIONAL_SEP - || prev_op != TOK_CONDITIONAL_SEP - ) { - /* ...x~y@: push @ on opstack */ - opstackptr++; /* undo removal of ~ op */ - goto push_op; - } - /* else: a?b?c:d:. Evaluate b?c:d, replace it on stack with result. Then repeat */ + /* ...x~y@: push @ on opstack */ + opstackptr++; /* undo removal of ~ op */ + goto push_op; } /* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */ } -- cgit v1.2.3-55-g6feb From 648f506949ded749e28186d0092b6e42085c897b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 11:55:56 +0200 Subject: libbb: code shrink: introduce and use [_]exit_FAILURE() function old new delta exit_FAILURE - 7 +7 _exit_FAILURE - 7 +7 run 198 199 +1 restore_state_and_exit 114 115 +1 xbsd_write_bootstrap 399 397 -2 vfork_compressor 209 207 -2 sig_handler 12 10 -2 serial_ctl 154 152 -2 parse_args 1169 1167 -2 onintr 21 19 -2 make_new_session 493 491 -2 login_main 988 986 -2 gotsig 35 33 -2 do_iplink 1315 1313 -2 addgroup_main 397 395 -2 inetd_main 1911 1908 -3 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 2/12 up/down: 16/-25) Total: -9 bytes Signed-off-by: Denys Vlasenko --- applets/individual.c | 2 +- archival/tar.c | 2 +- console-tools/resize.c | 2 +- findutils/xargs.c | 2 +- include/libbb.h | 2 ++ init/init.c | 2 +- libbb/xfuncs.c | 10 ++++++++++ loginutils/addgroup.c | 2 +- loginutils/login.c | 10 +++++----- miscutils/devfsd.c | 6 +++--- miscutils/setserial.c | 2 +- networking/inetd.c | 4 ++-- networking/libiproute/iplink.c | 2 +- networking/libiproute/iptunnel.c | 2 +- networking/ping.c | 2 +- networking/slattach.c | 2 +- networking/telnetd.c | 2 +- procps/powertop.c | 2 +- selinux/setfiles.c | 2 +- util-linux/fdisk_osf.c | 5 +++-- util-linux/more.c | 2 +- 21 files changed, 40 insertions(+), 27 deletions(-) diff --git a/applets/individual.c b/applets/individual.c index e94f26c93..2f743d906 100644 --- a/applets/individual.c +++ b/applets/individual.c @@ -20,5 +20,5 @@ int main(int argc, char **argv) void bb_show_usage(void) { fputs_stdout(APPLET_full_usage "\n"); - exit(EXIT_FAILURE); + exit_FAILURE(); } diff --git a/archival/tar.c b/archival/tar.c index 9de37592e..d6ca6c1e0 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -621,7 +621,7 @@ static void NOINLINE vfork_compressor(int tar_fd, const char *gzip) execlp(gzip, gzip, "-f", (char *)0); vfork_exec_errno = errno; - _exit(EXIT_FAILURE); + _exit_FAILURE(); } /* parent */ diff --git a/console-tools/resize.c b/console-tools/resize.c index 056e33750..95e0c7bf9 100644 --- a/console-tools/resize.c +++ b/console-tools/resize.c @@ -45,7 +45,7 @@ static void onintr(int sig UNUSED_PARAM) { tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p); - _exit(EXIT_FAILURE); + _exit_FAILURE(); } int resize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; diff --git a/findutils/xargs.c b/findutils/xargs.c index 067ef41c5..c6000e066 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -800,7 +800,7 @@ void bb_show_usage(void) { fprintf(stderr, "Usage: %s [-p] [-r] [-t] -[x] [-n max_arg] [-s max_chars]\n", applet_name); - exit(EXIT_FAILURE); + exit_FAILURE(); } int main(int argc, char **argv) diff --git a/include/libbb.h b/include/libbb.h index 6191debb1..18336da23 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1281,6 +1281,8 @@ void set_task_comm(const char *comm) FAST_FUNC; #endif void exit_SUCCESS(void) NORETURN FAST_FUNC; void _exit_SUCCESS(void) NORETURN FAST_FUNC; +void exit_FAILURE(void) NORETURN FAST_FUNC; +void _exit_FAILURE(void) NORETURN FAST_FUNC; /* Helpers for daemonization. * diff --git a/init/init.c b/init/init.c index 1e1ce833d..2ee1e4cde 100644 --- a/init/init.c +++ b/init/init.c @@ -500,7 +500,7 @@ static pid_t run(const struct init_action *a) /* Open the new terminal device */ if (!open_stdio_to_tty(a->terminal)) - _exit(EXIT_FAILURE); + _exit_FAILURE(); /* NB: on NOMMU we can't wait for input in child, so * "askfirst" will work the same as "respawn". */ diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 465e5366c..b03af8542 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -433,3 +433,13 @@ void FAST_FUNC _exit_SUCCESS(void) { _exit(EXIT_SUCCESS); } + +void FAST_FUNC exit_FAILURE(void) +{ + exit(EXIT_FAILURE); +} + +void FAST_FUNC _exit_FAILURE(void) +{ + _exit(EXIT_FAILURE); +} diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 2a83c8a15..71d3a8db9 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -102,7 +102,7 @@ static void new_group(char *group, gid_t gid) /* add entry to group */ p = xasprintf("x:%u:", (unsigned) gr.gr_gid); if (update_passwd(bb_path_group_file, group, p, NULL) < 0) - exit(EXIT_FAILURE); + exit_FAILURE(); if (ENABLE_FEATURE_CLEAN_UP) free(p); #if ENABLE_FEATURE_SHADOWPASSWDS diff --git a/loginutils/login.c b/loginutils/login.c index 332238181..b02be2176 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -173,7 +173,7 @@ static void die_if_nologin(void) fflush_all(); /* Users say that they do need this prior to exit: */ tcdrain(STDOUT_FILENO); - exit(EXIT_FAILURE); + exit_FAILURE(); } #else # define die_if_nologin() ((void)0) @@ -265,19 +265,19 @@ static void get_username_or_die(char *buf, int size_buf) do { c = getchar(); if (c == EOF) - exit(EXIT_FAILURE); + exit_FAILURE(); if (c == '\n') { if (!--cntdown) - exit(EXIT_FAILURE); + exit_FAILURE(); goto prompt; } } while (isspace(c)); /* maybe isblank? */ *buf++ = c; if (!fgets(buf, size_buf-2, stdin)) - exit(EXIT_FAILURE); + exit_FAILURE(); if (!strchr(buf, '\n')) - exit(EXIT_FAILURE); + exit_FAILURE(); while ((unsigned char)*buf > ' ') buf++; *buf = '\0'; diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 297693f8c..36b491595 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c @@ -354,10 +354,10 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found"; #define simple_info_logger(p, msg) #define msg_logger(p, fmt, args...) #define simple_msg_logger(p, msg) -#define msg_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) -#define simple_msg_logger_and_die(p, msg) exit(EXIT_FAILURE) +#define msg_logger_and_die(p, fmt, args...) exit_FAILURE() +#define simple_msg_logger_and_die(p, msg) exit_FAILURE() #define error_logger(p, fmt, args...) -#define error_logger_and_die(p, fmt, args...) exit(EXIT_FAILURE) +#define error_logger_and_die(p, fmt, args...) exit_FAILURE() #endif static void safe_memcpy(char *dest, const char *src, int len) diff --git a/miscutils/setserial.c b/miscutils/setserial.c index 2006861e2..175c788fc 100644 --- a/miscutils/setserial.c +++ b/miscutils/setserial.c @@ -535,7 +535,7 @@ static int serial_ctl(int fd, int ops, struct serial_struct *serinfo) bb_simple_perror_msg(err); if (ops & CTL_NODIE) goto nodie; - exit(EXIT_FAILURE); + exit_FAILURE(); } static void print_flag(const char **prefix, const char *flag) diff --git a/networking/inetd.c b/networking/inetd.c index fb2fbe323..e63edcd9d 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -1449,7 +1449,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) else sep->se_builtin->bi_dgram_fn(ctrl, sep); if (pid) /* we did fork */ - _exit(EXIT_FAILURE); + _exit_FAILURE(); maybe_close(accepted_fd); continue; /* -> check next fd in fd set */ } @@ -1530,7 +1530,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) /* eat packet in udp case */ if (sep->se_socktype != SOCK_STREAM) recv(0, line, LINE_SIZE, MSG_DONTWAIT); - _exit(EXIT_FAILURE); + _exit_FAILURE(); } /* for (sep = servtab...) */ } /* for (;;) */ } diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c index 68d199044..9eb0b4f5f 100644 --- a/networking/libiproute/iplink.c +++ b/networking/libiproute/iplink.c @@ -215,7 +215,7 @@ static void parse_address(char *dev, int hatype, int halen, char *lla, struct if alen = hatype == 1/*ARPHRD_ETHER*/ ? 14/*ETH_HLEN*/ : 19/*INFINIBAND_HLEN*/; alen = ll_addr_a2n((unsigned char *)(ifr->ifr_hwaddr.sa_data), alen, lla); if (alen < 0) - exit(EXIT_FAILURE); + exit_FAILURE(); if (alen != halen) { bb_error_msg_and_die("wrong address (%s) length: expected %d bytes", lla, halen); } diff --git a/networking/libiproute/iptunnel.c b/networking/libiproute/iptunnel.c index c9fa632f3..1ec81c635 100644 --- a/networking/libiproute/iptunnel.c +++ b/networking/libiproute/iptunnel.c @@ -319,7 +319,7 @@ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p) struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (do_get_ioctl(*argv, &old_p)) - exit(EXIT_FAILURE); + exit_FAILURE(); *p = old_p; } } diff --git a/networking/ping.c b/networking/ping.c index 9805695a1..b7e6955a9 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -247,7 +247,7 @@ struct globals { static void noresp(int ign UNUSED_PARAM) { printf("No response from %s\n", G.hostname); - exit(EXIT_FAILURE); + exit_FAILURE(); } static void ping4(len_and_sockaddr *lsa) diff --git a/networking/slattach.c b/networking/slattach.c index 6d2a252fc..16b4c9158 100644 --- a/networking/slattach.c +++ b/networking/slattach.c @@ -80,7 +80,7 @@ static void restore_state_and_exit(int exitcode) /* Restore line status */ if (tcsetattr_serial_or_warn(&G.saved_state)) - exit(EXIT_FAILURE); + exit_FAILURE(); if (ENABLE_FEATURE_CLEAN_UP) close(serial_fd); diff --git a/networking/telnetd.c b/networking/telnetd.c index 0805e464f..fb90e7f11 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -571,7 +571,7 @@ make_new_session( BB_EXECVP(G.loginpath, (char **)login_argv); /* _exit is safer with vfork, and we shouldn't send message * to remote clients anyway */ - _exit(EXIT_FAILURE); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/ + _exit_FAILURE(); /*bb_perror_msg_and_die("execv %s", G.loginpath);*/ } #if ENABLE_FEATURE_TELNETD_STANDALONE diff --git a/procps/powertop.c b/procps/powertop.c index 18ddaa3ec..8d5d9295d 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -109,7 +109,7 @@ static void reset_term(void) static void sig_handler(int signo UNUSED_PARAM) { reset_term(); - _exit(EXIT_FAILURE); + _exit_FAILURE(); } #endif diff --git a/selinux/setfiles.c b/selinux/setfiles.c index a617b95d8..70e68a666 100644 --- a/selinux/setfiles.c +++ b/selinux/setfiles.c @@ -687,7 +687,7 @@ int setfiles_main(int argc UNUSED_PARAM, char **argv) bb_simple_perror_msg_and_die(argv[0]); } if (nerr) - exit(EXIT_FAILURE); + exit_FAILURE(); argv++; } diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index 6c66c130d..049f0b169 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c @@ -746,11 +746,12 @@ xbsd_write_bootstrap(void) return; e = d + sizeof(struct xbsd_disklabel); - for (p = d; p < e; p++) + for (p = d; p < e; p++) { if (*p) { printf("Bootstrap overlaps with disk label!\n"); - exit(EXIT_FAILURE); + exit_FAILURE(); } + } memmove(d, &dl, sizeof(struct xbsd_disklabel)); diff --git a/util-linux/more.c b/util-linux/more.c index a830dcbc1..352a3b6cf 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -65,7 +65,7 @@ static void gotsig(int sig UNUSED_PARAM) * therefore it is safe in signal handler */ bb_putchar_stderr('\n'); tcsetattr_tty_TCSANOW(&G.initial_settings); - _exit(EXIT_FAILURE); + _exit_FAILURE(); } #define CONVERTED_TAB_SIZE 8 -- cgit v1.2.3-55-g6feb From 22cb0d573a5cabd24fa648f1a13c22acf661a4a3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 12:44:43 +0200 Subject: shell: document another arithmetic discrepancy with bash Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-assign-in-varexp1.right | 2 ++ shell/ash_test/ash-arith/arith-assign-in-varexp1.tests | 9 +++++++++ 2 files changed, 11 insertions(+) create mode 100644 shell/ash_test/ash-arith/arith-assign-in-varexp1.right create mode 100755 shell/ash_test/ash-arith/arith-assign-in-varexp1.tests diff --git a/shell/ash_test/ash-arith/arith-assign-in-varexp1.right b/shell/ash_test/ash-arith/arith-assign-in-varexp1.right new file mode 100644 index 000000000..1feb307d2 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-assign-in-varexp1.right @@ -0,0 +1,2 @@ +7:7 +x=3 diff --git a/shell/ash_test/ash-arith/arith-assign-in-varexp1.tests b/shell/ash_test/ash-arith/arith-assign-in-varexp1.tests new file mode 100755 index 000000000..fc8ac9d97 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-assign-in-varexp1.tests @@ -0,0 +1,9 @@ +exec 2>&1 +a='x=1' +b='x=2' +c='x=3' +# The variables should evaluate immediately when they encountered, +# not when they go into an operation. Here, order of evaluation +# of names to numbers should be a,b,c - not b,c,a: +echo 7:$((a+b*c)) +echo "x=$x" -- cgit v1.2.3-55-g6feb From ea6dcbe2839fb21049baadd0d5da903ae11661ec Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 13:56:12 +0200 Subject: shell/math: fix order of expansion of variables to numbers This fixes arith-assign-in-varexp1.tests function old new delta evaluate_string 1132 1258 +126 arith_lookup_val 143 - -143 arith_apply 1132 977 -155 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 126/-298) Total: -172 bytes Signed-off-by: Denys Vlasenko --- .../hush-arith/arith-assign-in-varexp1.right | 2 + .../hush-arith/arith-assign-in-varexp1.tests | 9 ++++ shell/math.c | 49 +++++++--------------- 3 files changed, 26 insertions(+), 34 deletions(-) create mode 100644 shell/hush_test/hush-arith/arith-assign-in-varexp1.right create mode 100755 shell/hush_test/hush-arith/arith-assign-in-varexp1.tests diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp1.right b/shell/hush_test/hush-arith/arith-assign-in-varexp1.right new file mode 100644 index 000000000..1feb307d2 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-assign-in-varexp1.right @@ -0,0 +1,2 @@ +7:7 +x=3 diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp1.tests b/shell/hush_test/hush-arith/arith-assign-in-varexp1.tests new file mode 100755 index 000000000..fc8ac9d97 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-assign-in-varexp1.tests @@ -0,0 +1,9 @@ +exec 2>&1 +a='x=1' +b='x=2' +c='x=3' +# The variables should evaluate immediately when they encountered, +# not when they go into an operation. Here, order of evaluation +# of names to numbers should be a,b,c - not b,c,a: +echo 7:$((a+b*c)) +echo "x=$x" diff --git a/shell/math.c b/shell/math.c index 8d0c9dea7..7e2bf5ea5 100644 --- a/shell/math.c +++ b/shell/math.c @@ -310,7 +310,6 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ var_or_num_t *top_of_stack; arith_t rez; - const char *err; /* There is no operator that can work without arguments */ if (NUMPTR == numstack) @@ -324,14 +323,8 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ NUMPTR = expr1 + 1; if (expr1 < numstack) /* Example: $((2:3)) */ return "malformed ?: operator"; - err = arith_lookup_val(math_state, expr1); - if (err) - return err; if (expr1->val != 0) /* select expr2 or expr3 */ top_of_stack--; - err = arith_lookup_val(math_state, top_of_stack); - if (err) - return err; expr1->val = top_of_stack->val; expr1->var_name = NULL; return NULL; @@ -339,24 +332,6 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */ return "malformed ?: operator"; - if (PREC(op) < UNARYPREC) { - /* In binops a ~ b, variables are resolved left-to-right, - * resolve top_of_stack[-1] _before_ resolving top_of_stack[0] - */ - if (top_of_stack == numstack) /* need two arguments */ - goto syntax_err; - /* Unless it is =, resolve top_of_stack[-1] name to value */ - if (op != TOK_ASSIGN) { - err = arith_lookup_val(math_state, top_of_stack - 1); - if (err) - return err; - } - } - /* Resolve top_of_stack[0] name to value */ - err = arith_lookup_val(math_state, top_of_stack); - if (err) - return err; - rez = top_of_stack->val; if (op == TOK_UMINUS) rez = -rez; @@ -372,6 +347,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ /* Binary operators */ arith_t right_side_val; + if (top_of_stack == numstack) /* have two arguments? */ + goto syntax_err; /* no */ + /* Pop numstack */ NUMPTR = top_of_stack; /* this decrements NUMPTR */ top_of_stack--; /* now points to left side */ @@ -677,7 +655,16 @@ evaluate_string(arith_state_t *math_state, const char *expr) numstackptr->var_name = alloca(var_name_size); safe_strncpy(numstackptr->var_name, expr, var_name_size); dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); - expr = p; + expr = skip_whitespace(p); + /* If it is not followed by "=" operator... */ + if (expr[0] != '=' /* not "=..." */ + || expr[1] == '=' /* or "==..." */ + ) { + /* Evaluate variable to value */ + errmsg = arith_lookup_val(math_state, numstackptr); + if (errmsg) + goto err_with_custom_msg; + } push_num: numstackptr++; lasttok = TOK_NUM; @@ -819,14 +806,8 @@ evaluate_string(arith_state_t *math_state, const char *expr) operator prev_op = *--opstackptr; if (op == TOK_RPAREN) { if (prev_op == TOK_LPAREN) { - if (VALID_NAME(numstackptr[-1].var_name)) { - /* Expression is (var), lookup now */ - errmsg = arith_lookup_val(math_state, &numstackptr[-1]); - if (errmsg) - goto err_with_custom_msg; - /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ - numstackptr[-1].var_name = NULL; - } + /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ + numstackptr[-1].var_name = NULL; /* Any operator directly after a * close paren should consider itself binary */ lasttok = TOK_NUM; -- cgit v1.2.3-55-g6feb From 38f423cc9c6419f86e8ab602f195a9035a879001 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 16:46:31 +0200 Subject: shell/math: explain the logic, small tweak to make code smaller function old new delta evaluate_string 1258 1257 -1 Signed-off-by: Denys Vlasenko --- shell/math.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/shell/math.c b/shell/math.c index 7e2bf5ea5..4623c979e 100644 --- a/shell/math.c +++ b/shell/math.c @@ -133,7 +133,10 @@ typedef unsigned char operator; #define tok_decl(prec,id) (((id)<<5) | (prec)) #define PREC(op) ((op) & 0x1F) +#define PREC_LPAREN 0 #define TOK_LPAREN tok_decl(0,0) +/* Precedence value of RPAREN is used only to distinguish it from LPAREN */ +#define TOK_RPAREN tok_decl(1,1) #define TOK_COMMA tok_decl(1,0) @@ -223,7 +226,6 @@ typedef unsigned char operator; #define SPEC_PREC (UNARYPREC+4) #define TOK_NUM tok_decl(SPEC_PREC, 0) -#define TOK_RPAREN tok_decl(SPEC_PREC, 1) static int is_assign_op(operator op) @@ -789,19 +791,32 @@ evaluate_string(arith_state_t *math_state, const char *expr) * stack until we find an operator with a lesser priority than the * one we have just extracted. If op is right-associative, * then stop "applying" on the equal priority too. - * Left paren is given the lowest priority so it will never be - * "applied" in this way. + * Left paren will never be "applied" in this way. */ prec = PREC(op); - if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { - /* not left paren or unary */ + if (prec != PREC_LPAREN && prec < UNARYPREC) { + /* binary, ternary or RPAREN */ if (lasttok != TOK_NUM) { - /* binary op must be preceded by a num */ + /* must be preceded by a num */ goto err; } - /* The algorithm employed here is simple: while we don't - * hit an open paren nor the bottom of the stack, pop - * tokens and apply them */ + /* if op is RPAREN: + * while opstack is not empty: + * pop prev_op + * if prev_op is LPAREN (finished evaluating (EXPR)): + * goto N + * evaluate prev_op on top of numstack + * BUG (unpaired RPAREN) + * else (op is not RPAREN): + * while opstack is not empty: + * pop prev_op + * if can't evaluate prev_op (it is lower precedence than op): + * push prev_op back + * goto P + * evaluate prev_op on top of numstack + * P: push op + * N: loop to parse the rest of string + */ while (opstackptr != opstack) { operator prev_op = *--opstackptr; if (op == TOK_RPAREN) { @@ -821,7 +836,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (prev_prec < prec || (prev_prec == prec && is_right_associative(prec)) ) { - /* ...x~y@: push @ on opstack */ + /* ...x~y@. push @ on opstack */ opstackptr++; /* undo removal of ~ op */ goto push_op; } -- cgit v1.2.3-55-g6feb From f8263528cd44ac5dc95778556c6fd3feea14742e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jun 2023 17:16:46 +0200 Subject: shell/math: simplify handling of unary plus function old new delta evaluate_string 1257 1271 +14 arith_apply 977 968 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 14/-9) Total: 5 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/shell/math.c b/shell/math.c index 4623c979e..a398bcb98 100644 --- a/shell/math.c +++ b/shell/math.c @@ -345,7 +345,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ rez++; else if (op == TOK_POST_DEC || op == TOK_PRE_DEC) rez--; - else if (op != TOK_UPLUS) { + else /*if (op != TOK_UPLUS) - always true, we drop TOK_UPLUS earlier */ { /* Binary operators */ arith_t right_side_val; @@ -770,8 +770,10 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (lasttok != TOK_NUM) { switch (op) { case TOK_ADD: - op = TOK_UPLUS; - break; + //op = TOK_UPLUS; + //break; + /* Unary plus does nothing, do not even push it to opstack */ + continue; case TOK_SUB: op = TOK_UMINUS; break; -- cgit v1.2.3-55-g6feb From e1279858394a6079be6816cbedaa3f10e74057cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 16 Jun 2023 19:43:53 +0200 Subject: shell/math: fix ?: to not evaluate not-taken branches This fixes ash-arith-arith-ternary1/2.tests function old new delta evaluate_string 1271 1432 +161 arith_apply 968 1000 +32 arith 22 36 +14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 207/0) Total: 207 bytes Signed-off-by: Denys Vlasenko --- .../ash_test/ash-arith/arith-ternary-assign.right | 1 + .../ash_test/ash-arith/arith-ternary-assign.tests | 3 + shell/ash_test/ash-arith/arith-ternary-comma.right | 1 + shell/ash_test/ash-arith/arith-ternary-comma.tests | 3 + .../ash_test/ash-arith/arith-ternary-preincr.right | 1 + .../ash_test/ash-arith/arith-ternary-preincr.tests | 3 + shell/ash_test/ash-arith/arith-ternary3.right | 1 + shell/ash_test/ash-arith/arith-ternary3.tests | 4 + .../ash_test/ash-arith/arith-ternary_nested3.right | 2 + .../ash_test/ash-arith/arith-ternary_nested3.tests | 6 ++ .../hush-arith/arith-ternary-assign.right | 1 + .../hush-arith/arith-ternary-assign.tests | 3 + .../hush_test/hush-arith/arith-ternary-comma.right | 1 + .../hush_test/hush-arith/arith-ternary-comma.tests | 3 + .../hush-arith/arith-ternary-preincr.right | 1 + .../hush-arith/arith-ternary-preincr.tests | 3 + shell/hush_test/hush-arith/arith-ternary1.right | 2 + shell/hush_test/hush-arith/arith-ternary1.tests | 5 ++ shell/hush_test/hush-arith/arith-ternary2.right | 3 + shell/hush_test/hush-arith/arith-ternary2.tests | 7 ++ shell/hush_test/hush-arith/arith-ternary3.right | 1 + shell/hush_test/hush-arith/arith-ternary3.tests | 4 + .../hush-arith/arith-ternary_nested3.right | 2 + .../hush-arith/arith-ternary_nested3.tests | 6 ++ shell/math.c | 85 ++++++++++++++++------ shell/math.h | 3 +- 26 files changed, 131 insertions(+), 24 deletions(-) create mode 100644 shell/ash_test/ash-arith/arith-ternary-assign.right create mode 100755 shell/ash_test/ash-arith/arith-ternary-assign.tests create mode 100644 shell/ash_test/ash-arith/arith-ternary-comma.right create mode 100755 shell/ash_test/ash-arith/arith-ternary-comma.tests create mode 100644 shell/ash_test/ash-arith/arith-ternary-preincr.right create mode 100755 shell/ash_test/ash-arith/arith-ternary-preincr.tests create mode 100644 shell/ash_test/ash-arith/arith-ternary3.right create mode 100755 shell/ash_test/ash-arith/arith-ternary3.tests create mode 100644 shell/ash_test/ash-arith/arith-ternary_nested3.right create mode 100755 shell/ash_test/ash-arith/arith-ternary_nested3.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary-assign.right create mode 100755 shell/hush_test/hush-arith/arith-ternary-assign.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary-comma.right create mode 100755 shell/hush_test/hush-arith/arith-ternary-comma.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary-preincr.right create mode 100755 shell/hush_test/hush-arith/arith-ternary-preincr.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary1.right create mode 100755 shell/hush_test/hush-arith/arith-ternary1.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary2.right create mode 100755 shell/hush_test/hush-arith/arith-ternary2.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary3.right create mode 100755 shell/hush_test/hush-arith/arith-ternary3.tests create mode 100644 shell/hush_test/hush-arith/arith-ternary_nested3.right create mode 100755 shell/hush_test/hush-arith/arith-ternary_nested3.tests diff --git a/shell/ash_test/ash-arith/arith-ternary-assign.right b/shell/ash_test/ash-arith/arith-ternary-assign.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-assign.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/ash_test/ash-arith/arith-ternary-assign.tests b/shell/ash_test/ash-arith/arith-ternary-assign.tests new file mode 100755 index 000000000..fa18fe7b9 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-assign.tests @@ -0,0 +1,3 @@ +exec 2>&1 +a='@' +echo 42:$((a=1?42:3,a)) diff --git a/shell/ash_test/ash-arith/arith-ternary-comma.right b/shell/ash_test/ash-arith/arith-ternary-comma.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-comma.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/ash_test/ash-arith/arith-ternary-comma.tests b/shell/ash_test/ash-arith/arith-ternary-comma.tests new file mode 100755 index 000000000..5e05b58c4 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-comma.tests @@ -0,0 +1,3 @@ +exec 2>&1 +x='@' +echo 42:$((1?4:x,20*2+2)) diff --git a/shell/ash_test/ash-arith/arith-ternary-preincr.right b/shell/ash_test/ash-arith/arith-ternary-preincr.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-preincr.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/ash_test/ash-arith/arith-ternary-preincr.tests b/shell/ash_test/ash-arith/arith-ternary-preincr.tests new file mode 100755 index 000000000..3985c7079 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary-preincr.tests @@ -0,0 +1,3 @@ +exec 2>&1 +x='@' +echo 42:$((1?42:++x)) diff --git a/shell/ash_test/ash-arith/arith-ternary3.right b/shell/ash_test/ash-arith/arith-ternary3.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary3.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/ash_test/ash-arith/arith-ternary3.tests b/shell/ash_test/ash-arith/arith-ternary3.tests new file mode 100755 index 000000000..0bf9f3002 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary3.tests @@ -0,0 +1,4 @@ +exec 2>&1 +# "EXPR ?..." should check _evaluated_ EXPR, +# not its last value +echo 42:$((1 < 1 ? -1 : 1 > 1 ? 1 : 42)) diff --git a/shell/ash_test/ash-arith/arith-ternary_nested3.right b/shell/ash_test/ash-arith/arith-ternary_nested3.right new file mode 100644 index 000000000..1a34fde65 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested3.right @@ -0,0 +1,2 @@ +42:42 +a=2:2 diff --git a/shell/ash_test/ash-arith/arith-ternary_nested3.tests b/shell/ash_test/ash-arith/arith-ternary_nested3.tests new file mode 100755 index 000000000..b69dcc6e9 --- /dev/null +++ b/shell/ash_test/ash-arith/arith-ternary_nested3.tests @@ -0,0 +1,6 @@ +exec 2>&1 +x='@' +a=2 +# After processing nested ?:, outermost ?: should still rememeber to NOT evaluate a*=2 +echo 42:$((1?0?41:42:(a*=2))) +echo "a=2:$a" diff --git a/shell/hush_test/hush-arith/arith-ternary-assign.right b/shell/hush_test/hush-arith/arith-ternary-assign.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-assign.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/hush_test/hush-arith/arith-ternary-assign.tests b/shell/hush_test/hush-arith/arith-ternary-assign.tests new file mode 100755 index 000000000..fa18fe7b9 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-assign.tests @@ -0,0 +1,3 @@ +exec 2>&1 +a='@' +echo 42:$((a=1?42:3,a)) diff --git a/shell/hush_test/hush-arith/arith-ternary-comma.right b/shell/hush_test/hush-arith/arith-ternary-comma.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-comma.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/hush_test/hush-arith/arith-ternary-comma.tests b/shell/hush_test/hush-arith/arith-ternary-comma.tests new file mode 100755 index 000000000..5e05b58c4 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-comma.tests @@ -0,0 +1,3 @@ +exec 2>&1 +x='@' +echo 42:$((1?4:x,20*2+2)) diff --git a/shell/hush_test/hush-arith/arith-ternary-preincr.right b/shell/hush_test/hush-arith/arith-ternary-preincr.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-preincr.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/hush_test/hush-arith/arith-ternary-preincr.tests b/shell/hush_test/hush-arith/arith-ternary-preincr.tests new file mode 100755 index 000000000..3985c7079 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary-preincr.tests @@ -0,0 +1,3 @@ +exec 2>&1 +x='@' +echo 42:$((1?42:++x)) diff --git a/shell/hush_test/hush-arith/arith-ternary1.right b/shell/hush_test/hush-arith/arith-ternary1.right new file mode 100644 index 000000000..6b751d7b8 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary1.right @@ -0,0 +1,2 @@ +42:42 +a=0 diff --git a/shell/hush_test/hush-arith/arith-ternary1.tests b/shell/hush_test/hush-arith/arith-ternary1.tests new file mode 100755 index 000000000..3532ce54d --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary1.tests @@ -0,0 +1,5 @@ +exec 2>&1 +a=0 +# The not-taken branch should not evaluate +echo 42:$((1 ? 42 : (a+=2))) +echo "a=$a" diff --git a/shell/hush_test/hush-arith/arith-ternary2.right b/shell/hush_test/hush-arith/arith-ternary2.right new file mode 100644 index 000000000..a549b1b5c --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.right @@ -0,0 +1,3 @@ +6:6 +a=b=+err+ +b=6 diff --git a/shell/hush_test/hush-arith/arith-ternary2.tests b/shell/hush_test/hush-arith/arith-ternary2.tests new file mode 100755 index 000000000..cb3163932 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary2.tests @@ -0,0 +1,7 @@ +exec 2>&1 +a='b=+err+' +b=5 +# The not-taken branch should not parse variables +echo 6:$((0 ? a : ++b)) +echo "a=$a" +echo "b=$b" diff --git a/shell/hush_test/hush-arith/arith-ternary3.right b/shell/hush_test/hush-arith/arith-ternary3.right new file mode 100644 index 000000000..6644d86bf --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary3.right @@ -0,0 +1 @@ +42:42 diff --git a/shell/hush_test/hush-arith/arith-ternary3.tests b/shell/hush_test/hush-arith/arith-ternary3.tests new file mode 100755 index 000000000..0bf9f3002 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary3.tests @@ -0,0 +1,4 @@ +exec 2>&1 +# "EXPR ?..." should check _evaluated_ EXPR, +# not its last value +echo 42:$((1 < 1 ? -1 : 1 > 1 ? 1 : 42)) diff --git a/shell/hush_test/hush-arith/arith-ternary_nested3.right b/shell/hush_test/hush-arith/arith-ternary_nested3.right new file mode 100644 index 000000000..1a34fde65 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested3.right @@ -0,0 +1,2 @@ +42:42 +a=2:2 diff --git a/shell/hush_test/hush-arith/arith-ternary_nested3.tests b/shell/hush_test/hush-arith/arith-ternary_nested3.tests new file mode 100755 index 000000000..b69dcc6e9 --- /dev/null +++ b/shell/hush_test/hush-arith/arith-ternary_nested3.tests @@ -0,0 +1,6 @@ +exec 2>&1 +x='@' +a=2 +# After processing nested ?:, outermost ?: should still rememeber to NOT evaluate a*=2 +echo 42:$((1?0?41:42:(a*=2))) +echo "a=2:$a" diff --git a/shell/math.c b/shell/math.c index a398bcb98..b1aabef9d 100644 --- a/shell/math.c +++ b/shell/math.c @@ -356,6 +356,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ NUMPTR = top_of_stack; /* this decrements NUMPTR */ top_of_stack--; /* now points to left side */ + if (math_state->evaluation_disabled) { + dbg("binary op %02x skipped", op); + goto ret_NULL; + } + right_side_val = rez; rez = top_of_stack->val; if (op == TOK_BOR || op == TOK_OR_ASSIGN) @@ -428,6 +433,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ } } + if (math_state->evaluation_disabled) { + dbg("unary op %02x skipped", op); + goto ret_NULL; + } + if (is_assign_op(op)) { char buf[sizeof(arith_t)*3 + 2]; @@ -446,6 +456,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ } top_of_stack->val = rez; + ret_NULL: /* Erase var name, it is just a number now */ top_of_stack->var_name = NULL; return NULL; @@ -594,8 +605,10 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) static arith_t evaluate_string(arith_state_t *math_state, const char *expr) { +#define EVAL_DISABLED ((unsigned long long)math_state->evaluation_disabled) +#define TOP_BIT_ULL ((unsigned long long)LLONG_MAX + 1) operator lasttok; - const char *errmsg; + const char *errmsg = NULL; const char *start_expr = expr = skip_whitespace(expr); unsigned expr_len = strlen(expr) + 2; /* Stack of integers/names */ @@ -614,7 +627,6 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* Start with a left paren */ dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); *opstackptr++ = lasttok = TOK_LPAREN; - errmsg = NULL; while (1) { const char *p; @@ -653,19 +665,26 @@ evaluate_string(arith_state_t *math_state, const char *expr) p = endofname(expr); if (p != expr) { /* Name */ - size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ - numstackptr->var_name = alloca(var_name_size); - safe_strncpy(numstackptr->var_name, expr, var_name_size); - dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); - expr = skip_whitespace(p); - /* If it is not followed by "=" operator... */ - if (expr[0] != '=' /* not "=..." */ - || expr[1] == '=' /* or "==..." */ - ) { - /* Evaluate variable to value */ - errmsg = arith_lookup_val(math_state, numstackptr); - if (errmsg) - goto err_with_custom_msg; + if (!math_state->evaluation_disabled) { + size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ + numstackptr->var_name = alloca(var_name_size); + safe_strncpy(numstackptr->var_name, expr, var_name_size); + dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); + expr = skip_whitespace(p); + /* If it is not followed by "=" operator... */ + if (expr[0] != '=' /* not "=..." */ + || expr[1] == '=' /* or "==..." */ + ) { + /* Evaluate variable to value */ + errmsg = arith_lookup_val(math_state, numstackptr); + if (errmsg) + goto err_with_custom_msg; + } + } else { + dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); + numstackptr->var_name = NULL; + numstackptr->val = 0; //paranoia, probably not needed + expr = p; } push_num: numstackptr++; @@ -814,10 +833,11 @@ evaluate_string(arith_state_t *math_state, const char *expr) * pop prev_op * if can't evaluate prev_op (it is lower precedence than op): * push prev_op back - * goto P + * goto C * evaluate prev_op on top of numstack - * P: push op - * N: loop to parse the rest of string + * C:if op is "?": check result, set disable flag if needed + * push op + * N:loop to parse the rest of string */ while (opstackptr != opstack) { operator prev_op = *--opstackptr; @@ -840,7 +860,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) ) { /* ...x~y@. push @ on opstack */ opstackptr++; /* undo removal of ~ op */ - goto push_op; + goto check_cond; } /* else: ...x~y@. Evaluate x~y, replace it on stack with result. Then repeat */ } @@ -863,21 +883,41 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ errmsg = "malformed ?: operator"; goto err_with_custom_msg; } + /* Example: a=1?2:3,a. We just executed ":". + * Prevent assignment from being still disabled. + */ + math_state->evaluation_disabled >>= 1; + dbg("':' executed: evaluation_disabled=%llx (restored)", EVAL_DISABLED); } } /* while (opstack not empty) */ if (op == TOK_RPAREN) /* unpaired RPAREN? */ goto err; - } + check_cond: + if (op == TOK_CONDITIONAL) { + /* We know the value of EXPR in "EXPR ? ..." + * Should we stop evaluating now? */ + if (math_state->evaluation_disabled & TOP_BIT_ULL) + goto err; /* >63 levels of ?: nesting not supported */ + math_state->evaluation_disabled <<= 1; + if (numstackptr[-1].val == 0) + math_state->evaluation_disabled |= 1; + dbg("'?' entered: evaluation_disabled=%llx", EVAL_DISABLED); + } + } /* if */ /* else: LPAREN or UNARY: push it on opstack */ - push_op: + /* Push this operator to opstack */ dbg("(%d) op:%02x insert_op:%02x", (int)(opstackptr - opstack), op, insert_op); *opstackptr++ = lasttok = op; - next: ; + next: if (insert_op != 0xff) { op = insert_op; insert_op = 0xff; dbg("inserting %02x", op); + if (op == TOK_CONDITIONAL_SEP) { + math_state->evaluation_disabled ^= 1; + dbg("':' entered: evaluation_disabled=%llx (negated)", EVAL_DISABLED); + } goto tok_found1; } } /* while (1) */ @@ -896,6 +936,7 @@ arith(arith_state_t *math_state, const char *expr) { math_state->errmsg = NULL; math_state->list_of_recursed_names = NULL; + math_state->evaluation_disabled = 0; return evaluate_string(math_state, expr); } diff --git a/shell/math.h b/shell/math.h index 41ef6e8df..452ddaddd 100644 --- a/shell/math.h +++ b/shell/math.h @@ -73,13 +73,12 @@ typedef long arith_t; typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); -//typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); typedef struct arith_state_t { const char *errmsg; arith_var_lookup_t lookupvar; arith_var_set_t setvar; -// arith_var_endofname_t endofname; + uint64_t evaluation_disabled; void *list_of_recursed_names; } arith_state_t; -- cgit v1.2.3-55-g6feb From 550696d492c7389927d3f335bed11aa4decbcae6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 16 Jun 2023 20:47:43 +0200 Subject: shell/math: tweka comments Signed-off-by: Denys Vlasenko --- shell/math.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/shell/math.c b/shell/math.c index b1aabef9d..2959e57ea 100644 --- a/shell/math.c +++ b/shell/math.c @@ -46,7 +46,6 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - /* This is my infix parser/evaluator. It is optimized for size, intended * as a replacement for yacc-based parsers. However, it may well be faster * than a comparable parser written in yacc. The supported operators are @@ -61,7 +60,6 @@ * to the stack instead of adding them to a queue to end up with an * expression). */ - /* * Aug 24, 2001 Manuel Novoa III * @@ -245,7 +243,6 @@ is_right_associative(operator prec) || prec == PREC(TOK_CONDITIONAL); } - typedef struct { arith_t val; char *var_name; @@ -254,13 +251,11 @@ typedef struct { #define VALID_NAME(name) (name) #define NOT_NAME(name) (!(name)) - typedef struct remembered_name { struct remembered_name *next; const char *var_name; } remembered_name; - static arith_t evaluate_string(arith_state_t *math_state, const char *expr); @@ -278,7 +273,7 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) */ for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { if (strcmp(cur->var_name, t->var_name) == 0) { - /* Yes */ + /* yes */ return "expression recursion loop detected"; } } @@ -500,7 +495,6 @@ static const char op_tokens[] ALIGN1 = { '+', 0, TOK_ADD, '-', 0, TOK_SUB, '^', 0, TOK_BXOR, - /* uniq */ '~', 0, TOK_BNOT, ',', 0, TOK_COMMA, '?', 0, TOK_CONDITIONAL, @@ -869,14 +863,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (errmsg) goto err_with_custom_msg; dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[-1].val, numstackptr[-1].var_name); - /* For ternary ?: we need to remove ? from opstack too, not just : */ if (prev_op == TOK_CONDITIONAL_SEP) { - // This is caught in arith_apply() - //if (opstackptr == opstack) { - // /* Example: $((2:3)) */ - // errmsg = "where is your ? in ?:"; - // goto err_with_custom_msg; - //} + /* We just executed ":" */ + /* Remove "?" from opstack too, not just ":" */ opstackptr--; if (*opstackptr != TOK_CONDITIONAL) { /* Example: $((1,2:3)) */ @@ -890,12 +879,14 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ dbg("':' executed: evaluation_disabled=%llx (restored)", EVAL_DISABLED); } } /* while (opstack not empty) */ + if (op == TOK_RPAREN) /* unpaired RPAREN? */ goto err; check_cond: if (op == TOK_CONDITIONAL) { - /* We know the value of EXPR in "EXPR ? ..." - * Should we stop evaluating now? */ + /* We just now evaluated EXPR before "?". + * Should we disable evaluation now? + */ if (math_state->evaluation_disabled & TOP_BIT_ULL) goto err; /* >63 levels of ?: nesting not supported */ math_state->evaluation_disabled <<= 1; @@ -915,6 +906,7 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ insert_op = 0xff; dbg("inserting %02x", op); if (op == TOK_CONDITIONAL_SEP) { + /* The next token is ":". Toggle "do not evaluate" bit */ math_state->evaluation_disabled ^= 1; dbg("':' entered: evaluation_disabled=%llx (negated)", EVAL_DISABLED); } -- cgit v1.2.3-55-g6feb From d6f98f214b3bd242f7404b68a4f9d777114fffa3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 00:28:49 +0200 Subject: shell/math: code shrink function old new delta evaluate_string 1432 1414 -18 Signed-off-by: Denys Vlasenko --- shell/math.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/math.c b/shell/math.c index 2959e57ea..56f866bf2 100644 --- a/shell/math.c +++ b/shell/math.c @@ -889,9 +889,9 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ */ if (math_state->evaluation_disabled & TOP_BIT_ULL) goto err; /* >63 levels of ?: nesting not supported */ - math_state->evaluation_disabled <<= 1; - if (numstackptr[-1].val == 0) - math_state->evaluation_disabled |= 1; + math_state->evaluation_disabled = + (math_state->evaluation_disabled << 1) + | (numstackptr[-1].val == 0); dbg("'?' entered: evaluation_disabled=%llx", EVAL_DISABLED); } } /* if */ -- cgit v1.2.3-55-g6feb From 6221832bc15d9037360e3bdc9405df08ed801cc1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 10:40:29 +0200 Subject: shell/math.h: update comments, rearrange struct members for smaller code function old new delta arith_apply 1000 998 -2 evaluate_string 1414 1406 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-10) Total: -10 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 2 +- shell/math.h | 26 ++++---------------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/shell/math.c b/shell/math.c index 56f866bf2..6196a6ad9 100644 --- a/shell/math.c +++ b/shell/math.c @@ -926,9 +926,9 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ arith_t FAST_FUNC arith(arith_state_t *math_state, const char *expr) { + math_state->evaluation_disabled = 0; math_state->errmsg = NULL; math_state->list_of_recursed_names = NULL; - math_state->evaluation_disabled = 0; return evaluate_string(math_state, expr); } diff --git a/shell/math.h b/shell/math.h index 452ddaddd..9812184f1 100644 --- a/shell/math.h +++ b/shell/math.h @@ -6,7 +6,6 @@ * * See math.c for internal documentation. */ - /* The math library has just one function: * * arith_t arith(arith_state_t *state, const char *expr); @@ -22,7 +21,6 @@ * "1 + 2 + 3" * you would obviously get back 6. */ - /* To add support to a shell, you need to implement three functions: * * lookupvar() - look up and return the value of a variable @@ -36,28 +34,12 @@ * setvar() - set a variable to some value * * If the arithmetic expansion does something like: - * $(( i = 1)) + * $((i = 1)) * then the math code will make a call like so: - * setvar("i", "1", 0); + * setvar("i", "1"); * The storage for the first two parameters are not allocated, so your * shell implementation will most likely need to strdup() them to save. - * - * endofname() - return the end of a variable name from input - * - * The arithmetic code does not know about variable naming conventions. - * So when it is given an experession, it knows something is not numeric, - * but it is up to the shell to dictate what is a valid identifiers. - * So when it encounters something like: - * $(( some_var + 123 )) - * It will make a call like so: - * end = endofname("some_var + 123"); - * So the shell needs to scan the input string and return a pointer to the - * first non-identifier string. In this case, it should return the input - * pointer with an offset pointing to the first space. The typical - * implementation will return the offset of first char that does not match - * the regex (in C locale): ^[a-zA-Z_][a-zA-Z_0-9]* */ - #ifndef SHELL_MATH_H #define SHELL_MATH_H 1 @@ -75,11 +57,11 @@ typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); typedef struct arith_state_t { + uint64_t evaluation_disabled; const char *errmsg; + void *list_of_recursed_names; arith_var_lookup_t lookupvar; arith_var_set_t setvar; - uint64_t evaluation_disabled; - void *list_of_recursed_names; } arith_state_t; arith_t FAST_FUNC arith(arith_state_t *state, const char *expr); -- cgit v1.2.3-55-g6feb From 19a74a54ded98b28c672d38b79ea9f313f2d89db Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 11:03:02 +0200 Subject: shell/math: change ?: nesting code to not have 63 level nesting limitation function old new delta evaluate_string 1406 1432 +26 arith 36 29 -7 arith_apply 998 990 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 26/-15) Total: 11 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 33 ++++++++++++++++++++------------- shell/math.h | 2 +- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/shell/math.c b/shell/math.c index 6196a6ad9..3e339a5ec 100644 --- a/shell/math.c +++ b/shell/math.c @@ -599,8 +599,6 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) static arith_t evaluate_string(arith_state_t *math_state, const char *expr) { -#define EVAL_DISABLED ((unsigned long long)math_state->evaluation_disabled) -#define TOP_BIT_ULL ((unsigned long long)LLONG_MAX + 1) operator lasttok; const char *errmsg = NULL; const char *start_expr = expr = skip_whitespace(expr); @@ -617,6 +615,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) operator *const opstack = alloca(expr_len * sizeof(opstack[0])); operator *opstackptr = opstack; operator insert_op = 0xff; + unsigned ternary_level = 0; /* Start with a left paren */ dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); @@ -875,8 +874,11 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ /* Example: a=1?2:3,a. We just executed ":". * Prevent assignment from being still disabled. */ - math_state->evaluation_disabled >>= 1; - dbg("':' executed: evaluation_disabled=%llx (restored)", EVAL_DISABLED); + if (ternary_level == math_state->evaluation_disabled) { + math_state->evaluation_disabled = 0; + dbg("':' executed: evaluation_disabled=CLEAR"); + } + ternary_level--; } } /* while (opstack not empty) */ @@ -887,12 +889,11 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ /* We just now evaluated EXPR before "?". * Should we disable evaluation now? */ - if (math_state->evaluation_disabled & TOP_BIT_ULL) - goto err; /* >63 levels of ?: nesting not supported */ - math_state->evaluation_disabled = - (math_state->evaluation_disabled << 1) - | (numstackptr[-1].val == 0); - dbg("'?' entered: evaluation_disabled=%llx", EVAL_DISABLED); + ternary_level++; + if (numstackptr[-1].val == 0 && !math_state->evaluation_disabled) { + math_state->evaluation_disabled = ternary_level; + dbg("'?' entered: evaluation_disabled=%u", math_state->evaluation_disabled); + } } } /* if */ /* else: LPAREN or UNARY: push it on opstack */ @@ -906,9 +907,15 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ insert_op = 0xff; dbg("inserting %02x", op); if (op == TOK_CONDITIONAL_SEP) { - /* The next token is ":". Toggle "do not evaluate" bit */ - math_state->evaluation_disabled ^= 1; - dbg("':' entered: evaluation_disabled=%llx (negated)", EVAL_DISABLED); + /* The next token is ":". Toggle "do not evaluate" state */ + if (!math_state->evaluation_disabled) { + math_state->evaluation_disabled = ternary_level; + dbg("':' entered: evaluation_disabled=%u", math_state->evaluation_disabled); + } else if (ternary_level == math_state->evaluation_disabled) { + math_state->evaluation_disabled = 0; + dbg("':' entered: evaluation_disabled=CLEAR"); + } /* else: ternary_level > nonzero evaluation_disabled: we are in nested ?:, in its disabled branch */ + /* do nothing */ } goto tok_found1; } diff --git a/shell/math.h b/shell/math.h index 9812184f1..439031828 100644 --- a/shell/math.h +++ b/shell/math.h @@ -57,7 +57,7 @@ typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); typedef struct arith_state_t { - uint64_t evaluation_disabled; + unsigned evaluation_disabled; const char *errmsg; void *list_of_recursed_names; arith_var_lookup_t lookupvar; -- cgit v1.2.3-55-g6feb From 822590f5e29c613dd1401ba4309c0684426fc4f4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 19:20:31 +0200 Subject: shell/math: eliminate some redundant stores on return code path function old new delta evaluate_string 1432 1412 -20 Signed-off-by: Denys Vlasenko --- shell/math.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/shell/math.c b/shell/math.c index 3e339a5ec..4b56d1397 100644 --- a/shell/math.c +++ b/shell/math.c @@ -303,21 +303,21 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) static NOINLINE const char* arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_or_num_t **numstackptr) { -#define NUMPTR (*numstackptr) +#define NUMSTACKPTR (*numstackptr) var_or_num_t *top_of_stack; arith_t rez; /* There is no operator that can work without arguments */ - if (NUMPTR == numstack) + if (NUMSTACKPTR == numstack) goto syntax_err; - top_of_stack = NUMPTR - 1; + top_of_stack = NUMSTACKPTR - 1; if (op == TOK_CONDITIONAL_SEP) { /* "expr1 ? expr2 : expr3" operation */ var_or_num_t *expr1 = &top_of_stack[-2]; - NUMPTR = expr1 + 1; + NUMSTACKPTR = expr1 + 1; if (expr1 < numstack) /* Example: $((2:3)) */ return "malformed ?: operator"; if (expr1->val != 0) /* select expr2 or expr3 */ @@ -348,12 +348,17 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ goto syntax_err; /* no */ /* Pop numstack */ - NUMPTR = top_of_stack; /* this decrements NUMPTR */ + NUMSTACKPTR = top_of_stack; /* this decrements NUMSTACKPTR */ top_of_stack--; /* now points to left side */ if (math_state->evaluation_disabled) { dbg("binary op %02x skipped", op); goto ret_NULL; + /* bash 5.2.12 does not execute "2/0" in disabled + * branches of ?: (and thus does not complain), + * but complains about negative exp: "2**-1". + * I don't think we need to emulate that. + */ } right_side_val = rez; @@ -457,7 +462,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ return NULL; syntax_err: return "arithmetic syntax error"; -#undef NUMPTR +#undef NUMSTACKPTR } /* longest must be first */ @@ -630,8 +635,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (*expr == '\0') { if (expr == start_expr) { /* Null expression */ - numstack->val = 0; - goto ret; + return 0; } /* This is only reached after all tokens have been extracted from the @@ -650,9 +654,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* At this point, we're done with the expression */ if (numstackptr != numstack + 1) { /* if there is not exactly one result, it's bad */ - goto err; + goto syntax_err; } - goto ret; + return numstack->val; } p = endofname(expr); @@ -697,7 +701,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) * a new number or name. Example: 09v09v09v09v09v09v09v09v09v */ if (isalnum(*expr) || *expr == '_') - goto err; + goto syntax_err; if (errno) numstackptr->val = 0; /* bash compat */ goto push_num; @@ -750,7 +754,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (*p == '\0') { /* No next element, operator not found */ //math_state->syntax_error_at = expr; - goto err; + goto syntax_err; } } /* NB: expr now points past the operator */ @@ -812,7 +816,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* binary, ternary or RPAREN */ if (lasttok != TOK_NUM) { /* must be preceded by a num */ - goto err; + goto syntax_err; } /* if op is RPAREN: * while opstack is not empty: @@ -883,7 +887,7 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ } /* while (opstack not empty) */ if (op == TOK_RPAREN) /* unpaired RPAREN? */ - goto err; + goto syntax_err; check_cond: if (op == TOK_CONDITIONAL) { /* We just now evaluated EXPR before "?". @@ -914,20 +918,19 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ } else if (ternary_level == math_state->evaluation_disabled) { math_state->evaluation_disabled = 0; dbg("':' entered: evaluation_disabled=CLEAR"); - } /* else: ternary_level > nonzero evaluation_disabled: we are in nested ?:, in its disabled branch */ - /* do nothing */ + } /* else: ternary_level > evaluation_disabled && evaluation_disabled != 0 */ + /* We are in nested "?:" while in outer "?:" disabled branch */ + /* do_nothing */ } goto tok_found1; } } /* while (1) */ - err: + syntax_err: errmsg = "arithmetic syntax error"; err_with_custom_msg: - numstack->val = -1; - ret: math_state->errmsg = errmsg; - return numstack->val; + return -1; } arith_t FAST_FUNC -- cgit v1.2.3-55-g6feb From 2ca9c45953cdb5a1bd6144c6eed5a8f14c551122 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 19:52:20 +0200 Subject: shell/read: do not allow empty variable name Signed-off-by: Denys Vlasenko --- shell/shell_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/shell_common.c b/shell/shell_common.c index 13163acdf..1eca101b9 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -57,7 +57,7 @@ shell_builtin_read(struct builtin_read_params *params) argv = params->argv; pp = argv; while (*pp) { - if (endofname(*pp)[0] != '\0') { + if (!*pp[0] || endofname(*pp)[0] != '\0') { /* Mimic bash message */ bb_error_msg("read: '%s': bad variable name", *pp); return (const char *)(uintptr_t)1; -- cgit v1.2.3-55-g6feb From d0441222db80c6fc0c47fa014106d38e25bfada7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 20:45:02 +0200 Subject: ash: code shrink function old new delta setvar 166 164 -2 Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 51b627fcc..dde36dd7c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2506,7 +2506,7 @@ setvar(const char *name, const char *val, int flags) p = mempcpy(nameeq, name, namelen); if (val) { *p++ = '='; - memcpy(p, val, vallen); + strcpy(p, val); } vp = setvareq(nameeq, flags | VNOSAVE); INT_ON; -- cgit v1.2.3-55-g6feb From 96769486e20fd5f1142cae0db2cbacef31dc75e9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 21:02:37 +0200 Subject: shell: move varcmp() to shell_common.h and use it in hush function old new delta unset_local_var - 112 +112 findvar 31 35 +4 set_vars_and_save_old 144 141 -3 helper_export_local 235 230 -5 set_local_var 425 416 -9 handle_changed_special_names 38 27 -11 builtin_unset 154 141 -13 builtin_getopts 404 391 -13 get_local_var_value 281 260 -21 get_ptr_to_local_var 71 45 -26 unset_local_var_len 139 - -139 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/8 up/down: 116/-240) Total: -124 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 24 ------------------------ shell/hush.c | 42 ++++++++++++++++-------------------------- shell/shell_common.c | 19 +++++++++++++++++++ shell/shell_common.h | 2 ++ 4 files changed, 37 insertions(+), 50 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index dde36dd7c..96d2433d3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2259,30 +2259,6 @@ getoptsreset(const char *value) } #endif -/* - * Compares two strings up to the first = or '\0'. The first - * string must be terminated by '='; the second may be terminated by - * either '=' or '\0'. - */ -static int -varcmp(const char *p, const char *q) -{ - int c, d; - - while ((c = *p) == (d = *q)) { - if (c == '\0' || c == '=') - goto out; - p++; - q++; - } - if (c == '=') - c = '\0'; - if (d == '=') - d = '\0'; - out: - return c - d; -} - /* * Find the appropriate entry in the hash table from the name. */ diff --git a/shell/hush.c b/shell/hush.c index dbc4aecab..426182924 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2255,14 +2255,14 @@ static const char *get_cwd(int force) /* * Shell and environment variable support */ -static struct variable **get_ptr_to_local_var(const char *name, unsigned len) +static struct variable **get_ptr_to_local_var(const char *name) { struct variable **pp; struct variable *cur; pp = &G.top_var; while ((cur = *pp) != NULL) { - if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=') + if (varcmp(cur->varstr, name) == 0) return pp; pp = &cur->next; } @@ -2272,21 +2272,20 @@ static struct variable **get_ptr_to_local_var(const char *name, unsigned len) static const char* FAST_FUNC get_local_var_value(const char *name) { struct variable **vpp; - unsigned len = strlen(name); if (G.expanded_assignments) { char **cpp = G.expanded_assignments; while (*cpp) { char *cp = *cpp; - if (strncmp(cp, name, len) == 0 && cp[len] == '=') - return cp + len + 1; + if (varcmp(cp, name) == 0) + return strchr(cp, '=') + 1; cpp++; } } - vpp = get_ptr_to_local_var(name, len); + vpp = get_ptr_to_local_var(name); if (vpp) - return (*vpp)->varstr + len + 1; + return strchr((*vpp)->varstr, '=') + 1; if (strcmp(name, "PPID") == 0) return utoa(G.root_ppid); @@ -2319,13 +2318,11 @@ static const char* FAST_FUNC get_local_var_value(const char *name) } #if ENABLE_HUSH_GETOPTS -static void handle_changed_special_names(const char *name, unsigned name_len) +static void handle_changed_special_names(const char *name) { - if (name_len == 6) { - if (strncmp(name, "OPTIND", 6) == 0) { - G.getopt_count = 0; - return; - } + if (varcmp(name, "OPTIND") == 0) { + G.getopt_count = 0; + return; } } #else @@ -2476,7 +2473,7 @@ static int set_local_var(char *str, unsigned flags) } free(free_me); - handle_changed_special_names(cur->varstr, name_len - 1); + handle_changed_special_names(cur->varstr); return retval; } @@ -2499,16 +2496,14 @@ static void set_pwd_var(unsigned flag) } #if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS -static int unset_local_var_len(const char *name, int name_len) +static int unset_local_var(const char *name) { struct variable *cur; struct variable **cur_pp; cur_pp = &G.top_var; while ((cur = *cur_pp) != NULL) { - if (strncmp(cur->varstr, name, name_len) == 0 - && cur->varstr[name_len] == '=' - ) { + if (varcmp(cur->varstr, name) == 0) { if (cur->flg_read_only) { bb_error_msg("%s: readonly variable", name); return EXIT_FAILURE; @@ -2527,15 +2522,10 @@ static int unset_local_var_len(const char *name, int name_len) } /* Handle "unset LINENO" et al even if did not find the variable to unset */ - handle_changed_special_names(name, name_len); + handle_changed_special_names(name); return EXIT_SUCCESS; } - -static int unset_local_var(const char *name) -{ - return unset_local_var_len(name, strlen(name)); -} #endif @@ -2581,7 +2571,7 @@ static void set_vars_and_save_old(char **strings) eq = strchr(*s, '='); if (HUSH_DEBUG && !eq) bb_simple_error_msg_and_die("BUG in varexp4"); - var_pp = get_ptr_to_local_var(*s, eq - *s); + var_pp = get_ptr_to_local_var(*s); if (var_pp) { var_p = *var_pp; if (var_p->flg_read_only) { @@ -11215,7 +11205,7 @@ static int helper_export_local(char **argv, unsigned flags) if (*name_end == '\0') { struct variable *var, **vpp; - vpp = get_ptr_to_local_var(name, name_end - name); + vpp = get_ptr_to_local_var(name); var = vpp ? *vpp : NULL; if (flags & SETFLAG_UNEXPORT) { diff --git a/shell/shell_common.c b/shell/shell_common.c index 1eca101b9..e5c2cefb3 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -22,6 +22,25 @@ const char defifsvar[] ALIGN1 = "IFS= \t\n"; const char defoptindvar[] ALIGN1 = "OPTIND=1"; +/* Compare two strings up to the first '=' or '\0'. */ +int FAST_FUNC varcmp(const char *p, const char *q) +{ + int c, d; + + while ((c = *p) == (d = *q)) { + if (c == '\0' || c == '=') + goto out; + p++; + q++; + } + if (c == '=') + c = '\0'; + if (d == '=') + d = '\0'; + out: + return c - d; +} + /* read builtin */ /* Needs to be interruptible: shell must handle traps and shell-special signals diff --git a/shell/shell_common.h b/shell/shell_common.h index 7b478f1df..fab676e4a 100644 --- a/shell/shell_common.h +++ b/shell/shell_common.h @@ -26,6 +26,8 @@ extern const char defifsvar[] ALIGN1; /* "IFS= \t\n" */ extern const char defoptindvar[] ALIGN1; /* "OPTIND=1" */ +int FAST_FUNC varcmp(const char *p, const char *q); + /* Builtins */ struct builtin_read_params { -- cgit v1.2.3-55-g6feb From 182e5a4d000cdb5808830b1f02c59d40c6e61150 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 17 Jun 2023 22:43:46 +0200 Subject: shell/math: decrease stack usage function old new delta evaluate_string 1412 1467 +55 Signed-off-by: Denys Vlasenko --- shell/math.c | 62 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/shell/math.c b/shell/math.c index 4b56d1397..f6fed805c 100644 --- a/shell/math.c +++ b/shell/math.c @@ -579,48 +579,40 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) # endif #endif -//TODO: much better estimation than expr_len/2? Such as: -//static unsigned estimate_nums_and_names(const char *expr) -//{ -// unsigned count = 0; -// while (*(expr = skip_whitespace(expr)) != '\0') { -// const char *p; -// if (isdigit(*expr)) { -// while (isdigit(*++expr)) -// continue; -// count++; -// continue; -// } -// p = endofname(expr); -// if (p != expr) { -// expr = p; -// count++; -// continue; -// } -// } -// return count; -//} - static arith_t evaluate_string(arith_state_t *math_state, const char *expr) { - operator lasttok; - const char *errmsg = NULL; - const char *start_expr = expr = skip_whitespace(expr); - unsigned expr_len = strlen(expr) + 2; /* Stack of integers/names */ - /* There can be no more than strlen(startbuf)/2+1 - * integers/names in any given correct or incorrect expression. - * (modulo "09v09v09v09v09v" case, - * but we have code to detect that early) - */ - var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0])); - var_or_num_t *numstackptr = numstack; + var_or_num_t *numstack, *numstackptr; /* Stack of operator tokens */ - operator *const opstack = alloca(expr_len * sizeof(opstack[0])); - operator *opstackptr = opstack; + operator *opstack, *opstackptr; + operator lasttok; operator insert_op = 0xff; unsigned ternary_level = 0; + const char *errmsg; + const char *start_expr = expr = skip_whitespace(expr); + + { + unsigned expr_len = strlen(expr) + 2; + /* If LOTS of whitespace, do not blow up the estimation */ + const char *p = expr; + while (*p) { + /* in a run of whitespace, count only 1st char */ + if (isspace(*p)) { + while (p++, isspace(*p)) + expr_len--; + } else { + p++; + } + } + /* There can be no more than expr_len/2 + * integers/names in any given correct or incorrect expression. + * (modulo "09v09v09v09v09v" case, + * but we have code to detect that early) + */ + numstackptr = numstack = alloca((expr_len / 2) * sizeof(numstack[0])); + opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); + } /* Start with a left paren */ dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); -- cgit v1.2.3-55-g6feb From c72c5552edecb8a2f97cd7e2d9a09a3059986cca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 00:47:55 +0200 Subject: shell/math: decrease stack usage by not allocating copies of variable names We risk exhaust stack with alloca() with old code. function old new delta arith_apply 990 1023 +33 evaluate_string 1467 1494 +27 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 60/0) Total: 60 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 83 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/shell/math.c b/shell/math.c index f6fed805c..4c1b1b762 100644 --- a/shell/math.c +++ b/shell/math.c @@ -245,7 +245,7 @@ is_right_associative(operator prec) typedef struct { arith_t val; - char *var_name; + const char *var_name; } var_or_num_t; #define VALID_NAME(name) (name) @@ -256,44 +256,58 @@ typedef struct remembered_name { const char *var_name; } remembered_name; +static ALWAYS_INLINE int isalnum_(int c) +{ + return (isalnum(c) || c == '_'); +} + static arith_t evaluate_string(arith_state_t *math_state, const char *expr); static const char* arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) { - if (VALID_NAME(t->var_name)) { - const char *p = math_state->lookupvar(t->var_name); - if (p) { - remembered_name *cur; - remembered_name remember; - - /* did we already see this name? - * testcase: a=b; b=a; echo $((a)) - */ - for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { - if (strcmp(cur->var_name, t->var_name) == 0) { - /* yes */ - return "expression recursion loop detected"; - } + const char *name = t->var_name; + char c; + const char *p; + char *e = (char*)endofname(name); + + c = *e; + *e = '\0'; + p = math_state->lookupvar(name); + *e = c; + if (p) { + size_t len = e - name; + remembered_name *cur; + remembered_name remember; + + /* did we already see this name? + * testcase: a=b; b=a; echo $((a)) + */ + for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { + if (strncmp(cur->var_name, name, len) == 0 + && !isalnum_(cur->var_name[len]) + ) { + /* yes */ + return "expression recursion loop detected"; } + } - /* push current var name */ - remember.var_name = t->var_name; - remember.next = math_state->list_of_recursed_names; - math_state->list_of_recursed_names = &remember; + /* push current var name */ + remember.var_name = name; + remember.next = math_state->list_of_recursed_names; + math_state->list_of_recursed_names = &remember; - /* recursively evaluate p as expression */ - t->val = evaluate_string(math_state, p); + /* recursively evaluate p as expression */ + t->val = evaluate_string(math_state, p); - /* pop current var name */ - math_state->list_of_recursed_names = remember.next; + /* pop current var name */ + math_state->list_of_recursed_names = remember.next; - return math_state->errmsg; - } - /* treat undefined var as 0 */ - t->val = 0; + return math_state->errmsg; } + /* treat undefined var as 0 */ + t->val = 0; return NULL; } @@ -447,7 +461,13 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ } /* Save to shell variable */ sprintf(buf, ARITH_FMT, rez); - math_state->setvar(top_of_stack->var_name, buf); + { + char *e = (char*)endofname(top_of_stack->var_name); + char c = *e; + *e = '\0'; + math_state->setvar(top_of_stack->var_name, buf); + *e = c; + } /* After saving, make previous value for v++ or v-- */ if (op == TOK_POST_INC) rez--; @@ -610,6 +630,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) * (modulo "09v09v09v09v09v" case, * but we have code to detect that early) */ + dbg("expr:'%s' expr_len:%u", expr, expr_len); numstackptr = numstack = alloca((expr_len / 2) * sizeof(numstack[0])); opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); } @@ -655,10 +676,8 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (p != expr) { /* Name */ if (!math_state->evaluation_disabled) { - size_t var_name_size = (p - expr) + 1; /* +1 for NUL */ - numstackptr->var_name = alloca(var_name_size); - safe_strncpy(numstackptr->var_name, expr, var_name_size); - dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name); + numstackptr->var_name = expr; + dbg("[%d] var:'%.*s'", (int)(numstackptr - numstack), (int)(p - expr), expr); expr = skip_whitespace(p); /* If it is not followed by "=" operator... */ if (expr[0] != '=' /* not "=..." */ -- cgit v1.2.3-55-g6feb From 2d06c83b87e8c8330ef82bbdf4314112400877f7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 18:31:55 +0200 Subject: shell/math: code shrink function old new delta evaluate_string 1489 1486 -3 Signed-off-by: Denys Vlasenko --- shell/math.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/shell/math.c b/shell/math.c index 4c1b1b762..fee325307 100644 --- a/shell/math.c +++ b/shell/math.c @@ -264,10 +264,9 @@ static ALWAYS_INLINE int isalnum_(int c) static arith_t evaluate_string(arith_state_t *math_state, const char *expr); -static const char* -arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) +static arith_t +arith_lookup_val(arith_state_t *math_state, const char *name) { - const char *name = t->var_name; char c; const char *p; char *e = (char*)endofname(name); @@ -277,6 +276,7 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) p = math_state->lookupvar(name); *e = c; if (p) { + arith_t val; size_t len = e - name; remembered_name *cur; remembered_name remember; @@ -289,7 +289,8 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) && !isalnum_(cur->var_name[len]) ) { /* yes */ - return "expression recursion loop detected"; + math_state->errmsg = "expression recursion loop detected"; + return -1; } } @@ -299,16 +300,16 @@ arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) math_state->list_of_recursed_names = &remember; /* recursively evaluate p as expression */ - t->val = evaluate_string(math_state, p); + /* this sets math_state->errmsg on error */ + val = evaluate_string(math_state, p); /* pop current var name */ math_state->list_of_recursed_names = remember.next; - return math_state->errmsg; + return val; } /* treat undefined var as 0 */ - t->val = 0; - return NULL; + return 0; } /* "Applying" a token means performing it on the top elements on the integer @@ -684,9 +685,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) || expr[1] == '=' /* or "==..." */ ) { /* Evaluate variable to value */ - errmsg = arith_lookup_val(math_state, numstackptr); - if (errmsg) - goto err_with_custom_msg; + numstackptr->val = arith_lookup_val(math_state, numstackptr->var_name); + if (math_state->errmsg) + return numstackptr->val; /* -1 */ } } else { dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); -- cgit v1.2.3-55-g6feb From b61fd8ec5a2e3b728c05a72b603fb4255b1022da Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 18:49:00 +0200 Subject: shell: typo fix in tests Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-ternary_nested3.tests | 2 +- shell/hush_test/hush-arith/arith-ternary_nested3.tests | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/ash_test/ash-arith/arith-ternary_nested3.tests b/shell/ash_test/ash-arith/arith-ternary_nested3.tests index b69dcc6e9..6f753867e 100755 --- a/shell/ash_test/ash-arith/arith-ternary_nested3.tests +++ b/shell/ash_test/ash-arith/arith-ternary_nested3.tests @@ -1,6 +1,6 @@ exec 2>&1 x='@' a=2 -# After processing nested ?:, outermost ?: should still rememeber to NOT evaluate a*=2 +# After processing nested ?:, outermost ?: should still remember to NOT evaluate a*=2 echo 42:$((1?0?41:42:(a*=2))) echo "a=2:$a" diff --git a/shell/hush_test/hush-arith/arith-ternary_nested3.tests b/shell/hush_test/hush-arith/arith-ternary_nested3.tests index b69dcc6e9..6f753867e 100755 --- a/shell/hush_test/hush-arith/arith-ternary_nested3.tests +++ b/shell/hush_test/hush-arith/arith-ternary_nested3.tests @@ -1,6 +1,6 @@ exec 2>&1 x='@' a=2 -# After processing nested ?:, outermost ?: should still rememeber to NOT evaluate a*=2 +# After processing nested ?:, outermost ?: should still remember to NOT evaluate a*=2 echo 42:$((1?0?41:42:(a*=2))) echo "a=2:$a" -- cgit v1.2.3-55-g6feb From 8309c9159f7d8ee8b0f6f4b401750c5a03a4b0b9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 18:58:22 +0200 Subject: shell/math: eliminate redundant endofname() function old new delta evaluate_string 1486 1498 +12 Signed-off-by: Denys Vlasenko --- shell/math.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/shell/math.c b/shell/math.c index fee325307..cb702b7f4 100644 --- a/shell/math.c +++ b/shell/math.c @@ -265,19 +265,18 @@ static arith_t evaluate_string(arith_state_t *math_state, const char *expr); static arith_t -arith_lookup_val(arith_state_t *math_state, const char *name) +arith_lookup_val(arith_state_t *math_state, const char *name, char *endname) { char c; const char *p; - char *e = (char*)endofname(name); - c = *e; - *e = '\0'; + c = *endname; + *endname = '\0'; p = math_state->lookupvar(name); - *e = c; + *endname = c; if (p) { arith_t val; - size_t len = e - name; + size_t len = endname - name; remembered_name *cur; remembered_name remember; @@ -685,9 +684,10 @@ evaluate_string(arith_state_t *math_state, const char *expr) || expr[1] == '=' /* or "==..." */ ) { /* Evaluate variable to value */ - numstackptr->val = arith_lookup_val(math_state, numstackptr->var_name); + arith_t val = arith_lookup_val(math_state, numstackptr->var_name, (char*)p); if (math_state->errmsg) - return numstackptr->val; /* -1 */ + return val; /* -1 */ + numstackptr->val = val; } } else { dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); -- cgit v1.2.3-55-g6feb From 7701b526a720c4a84839174fe6b084d831ac90c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 19:13:22 +0200 Subject: shell/math: code shrink function old new delta evaluate_string 1498 1491 -7 Signed-off-by: Denys Vlasenko --- shell/math.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/shell/math.c b/shell/math.c index cb702b7f4..6784eeeb0 100644 --- a/shell/math.c +++ b/shell/math.c @@ -363,7 +363,6 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ /* Pop numstack */ NUMSTACKPTR = top_of_stack; /* this decrements NUMSTACKPTR */ - top_of_stack--; /* now points to left side */ if (math_state->evaluation_disabled) { dbg("binary op %02x skipped", op); @@ -375,6 +374,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ */ } + top_of_stack--; /* now points to left side */ right_side_val = rez; rez = top_of_stack->val; if (op == TOK_BOR || op == TOK_OR_ASSIGN) @@ -703,9 +703,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) if (isdigit(*expr)) { /* Number */ + char *end; numstackptr->var_name = NULL; errno = 0; - numstackptr->val = strto_arith_t(expr, (char**) &expr); + end = (char*) expr; /* separate variable to go on stack */ + numstackptr->val = strto_arith_t(expr, &end); + expr = end; dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); /* A number can't be followed by another number, or a variable name. * We'd catch this later anyway, but this would require numstack[] -- cgit v1.2.3-55-g6feb From 10cce8ae35654585a09d6e839dd502f04b81599d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 19:30:22 +0200 Subject: shell/math: explain why we use separate &end Signed-off-by: Denys Vlasenko --- shell/math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/math.c b/shell/math.c index 6784eeeb0..0b30e089d 100644 --- a/shell/math.c +++ b/shell/math.c @@ -706,7 +706,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) char *end; numstackptr->var_name = NULL; errno = 0; - end = (char*) expr; /* separate variable to go on stack */ + /* code is smaller compared to using &expr here: */ numstackptr->val = strto_arith_t(expr, &end); expr = end; dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); -- cgit v1.2.3-55-g6feb From 79b90cbece5d69c4d370347c347f3d17bd1156c6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Jun 2023 20:13:22 +0200 Subject: shell/math: add note on ERANGE function old new delta evaluate_string 1488 1478 -10 Signed-off-by: Denys Vlasenko --- shell/math.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/shell/math.c b/shell/math.c index 0b30e089d..e5447e767 100644 --- a/shell/math.c +++ b/shell/math.c @@ -667,6 +667,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* At this point, we're done with the expression */ if (numstackptr != numstack + 1) { /* if there is not exactly one result, it's bad */ + /* Example: $((1 2)) */ goto syntax_err; } return numstack->val; @@ -691,9 +692,10 @@ evaluate_string(arith_state_t *math_state, const char *expr) } } else { dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); - numstackptr->var_name = NULL; - numstackptr->val = 0; //paranoia, probably not needed expr = p; + numstackptr->var_name = NULL; + push_num0: + numstackptr->val = 0; } push_num: numstackptr++; @@ -717,8 +719,13 @@ evaluate_string(arith_state_t *math_state, const char *expr) */ if (isalnum(*expr) || *expr == '_') goto syntax_err; - if (errno) - numstackptr->val = 0; /* bash compat */ + if (errno) { +// TODO: bash 5.2.15 does not catch ERANGE (some older version did?). +// $((99999999999999999999)) is 7766279631452241919 (the 64-bit truncated value). +// Our BASE# code does this as well: try $((10#99999999999999999999)), +// but the "ordinary" code path with strtoull() does not do this. + goto push_num0; /* bash compat */ + } goto push_num; } -- cgit v1.2.3-55-g6feb From a165098922ddbfbca3579538f50b44002ab0fae7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Jun 2023 09:44:04 +0200 Subject: shell/math: fix comments about jammed-together num+num corner cases function old new delta evaluate_string 1478 1470 -8 Signed-off-by: Denys Vlasenko --- shell/math.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/shell/math.c b/shell/math.c index e5447e767..d9986335a 100644 --- a/shell/math.c +++ b/shell/math.c @@ -613,7 +613,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) const char *start_expr = expr = skip_whitespace(expr); { - unsigned expr_len = strlen(expr) + 2; + unsigned expr_len = strlen(expr); /* If LOTS of whitespace, do not blow up the estimation */ const char *p = expr; while (*p) { @@ -625,14 +625,21 @@ evaluate_string(arith_state_t *math_state, const char *expr) p++; } } - /* There can be no more than expr_len/2 + dbg("expr:'%s' expr_len:%u", expr, expr_len); + /* expr_len deep opstack is needed. Think "------------7". + * Only "?" operator temporarily needs two opstack slots + * (IOW: more than one slot), but its second slot (LPAREN) + * is popped off when ":" is reached. + */ + opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); + /* There can be no more than (expr_len/2 + 1) * integers/names in any given correct or incorrect expression. - * (modulo "09v09v09v09v09v" case, + * (modulo "09", "0v" cases where 2 chars are 2 ints/names, * but we have code to detect that early) */ - dbg("expr:'%s' expr_len:%u", expr, expr_len); - numstackptr = numstack = alloca((expr_len / 2) * sizeof(numstack[0])); - opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); + expr_len = (expr_len / 2) + + 1 /* "1+2" has two nums, 2 = len/2+1, NOT len/2 */; + numstackptr = numstack = alloca(expr_len * sizeof(numstack[0])); } /* Start with a left paren */ @@ -714,8 +721,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); /* A number can't be followed by another number, or a variable name. * We'd catch this later anyway, but this would require numstack[] - * to be twice as deep to handle strings where _every_ char is - * a new number or name. Example: 09v09v09v09v09v09v09v09v09v + * to be ~twice as deep to handle strings where _every_ char is + * a new number or name. + * Examples: "09" is two numbers, "0v" is number and name. */ if (isalnum(*expr) || *expr == '_') goto syntax_err; -- cgit v1.2.3-55-g6feb From db0e886735112110183fe3e4f1dea7c0f31a36c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Jun 2023 10:22:15 +0200 Subject: shell/math: $((1?)) has one-too-small opstack, fix this Signed-off-by: Denys Vlasenko --- shell/math.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/math.c b/shell/math.c index d9986335a..0cf963731 100644 --- a/shell/math.c +++ b/shell/math.c @@ -114,7 +114,7 @@ #include "libbb.h" #include "math.h" -#if 1 +#if 0 # define dbg(...) ((void)0) #else # define dbg(...) bb_error_msg(__VA_ARGS__) @@ -631,6 +631,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) * (IOW: more than one slot), but its second slot (LPAREN) * is popped off when ":" is reached. */ + expr_len++; /* +1 for 1st LPAREN. See what $((1?)) pushes to opstack */ opstackptr = opstack = alloca(expr_len * sizeof(opstack[0])); /* There can be no more than (expr_len/2 + 1) * integers/names in any given correct or incorrect expression. -- cgit v1.2.3-55-g6feb From 019dd31150526b7dd9dd0addfc38f08bcf7ec551 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Jun 2023 10:23:46 +0200 Subject: shell/math: disable debug again Signed-off-by: Denys Vlasenko --- shell/math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/math.c b/shell/math.c index 0cf963731..ac758639f 100644 --- a/shell/math.c +++ b/shell/math.c @@ -114,7 +114,7 @@ #include "libbb.h" #include "math.h" -#if 0 +#if 1 # define dbg(...) ((void)0) #else # define dbg(...) bb_error_msg(__VA_ARGS__) -- cgit v1.2.3-55-g6feb From c1c267fd36b0fcac8c8871232eecc1e360173990 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Jun 2023 17:42:05 +0200 Subject: shell/math: bash-compatible handling of too large numbers function old new delta parse_with_base - 170 +170 evaluate_string 1477 1309 -168 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 170/-168) Total: 2 bytes Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-arith/arith-bignum1.right | 13 ++++ shell/ash_test/ash-arith/arith-bignum1.tests | 17 ++++++ shell/ash_test/ash-arith/arith.right | 3 +- shell/ash_test/ash-arith/arith.tests | 6 +- shell/hush_test/hush-arith/arith-bignum1.right | 13 ++++ shell/hush_test/hush-arith/arith-bignum1.tests | 17 ++++++ shell/hush_test/hush-arith/arith.right | 3 +- shell/hush_test/hush-arith/arith.tests | 6 +- shell/math.c | 84 +++++++++++++++----------- 9 files changed, 118 insertions(+), 44 deletions(-) create mode 100644 shell/ash_test/ash-arith/arith-bignum1.right create mode 100755 shell/ash_test/ash-arith/arith-bignum1.tests create mode 100644 shell/hush_test/hush-arith/arith-bignum1.right create mode 100755 shell/hush_test/hush-arith/arith-bignum1.tests diff --git a/shell/ash_test/ash-arith/arith-bignum1.right b/shell/ash_test/ash-arith/arith-bignum1.right new file mode 100644 index 000000000..42a8016ec --- /dev/null +++ b/shell/ash_test/ash-arith/arith-bignum1.right @@ -0,0 +1,13 @@ +18 digits: 999999999999999999 +19 digits: -8446744073709551617 +20 digits: 7766279631452241919 +18 digits- -999999999999999999 +19 digits- 8446744073709551617 +20 digits- -7766279631452241919 +Hex base#: +16 digits: 9876543210abcedf +17 digits: 876543210abcedfc +18 digits: 76543210abcedfcc +16 digits: 6789abcdef543121 +17 digits: 789abcdef5431204 +18 digits: 89abcdef54312034 diff --git a/shell/ash_test/ash-arith/arith-bignum1.tests b/shell/ash_test/ash-arith/arith-bignum1.tests new file mode 100755 index 000000000..ef8f928bc --- /dev/null +++ b/shell/ash_test/ash-arith/arith-bignum1.tests @@ -0,0 +1,17 @@ +exec 2>&1 +# If the number does not fit in 64 bits, bash uses truncated 64-bit value +# (essentially, it does not check for overflow in "n = n * base + digit" +# calculation). +echo 18 digits: $((999999999999999999)) +echo 19 digits: $((9999999999999999999)) +echo 20 digits: $((99999999999999999999)) +echo 18 digits- $((-999999999999999999)) +echo 19 digits- $((-9999999999999999999)) +echo 20 digits- $((-99999999999999999999)) +echo "Hex base#:" +printf '16 digits: %016x\n' $((16#9876543210abcedf)) +printf '17 digits: %016x\n' $((16#9876543210abcedfc)) +printf '18 digits: %016x\n' $((16#9876543210abcedfcc)) +printf '16 digits: %016x\n' $((-16#9876543210abcedf)) +printf '17 digits: %016x\n' $((-16#9876543210abcedfc)) +printf '18 digits: %016x\n' $((-16#9876543210abcedfcc)) diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right index 8bc78b8d1..b2c3f56d8 100644 --- a/shell/ash_test/ash-arith/arith.right +++ b/shell/ash_test/ash-arith/arith.right @@ -80,8 +80,9 @@ other bases 62 62 63 63 missing number after base -0 0 +./arith.tests: line 161: arithmetic syntax error ./arith.tests: line 162: arithmetic syntax error +./arith.tests: line 163: arithmetic syntax error ./arith.tests: line 164: divide by zero ./arith.tests: let: line 165: arithmetic syntax error ./arith.tests: line 166: arithmetic syntax error diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests index b9cb8ba4c..42cd7fdbf 100755 --- a/shell/ash_test/ash-arith/arith.tests +++ b/shell/ash_test/ash-arith/arith.tests @@ -155,12 +155,12 @@ echo 63 $(( 64#_ )) #ash# # weird bases (error) #ash# echo $(( 3425#56 )) -echo missing number after base -echo 0 $(( 2# )) # these should generate errors +echo missing number after base +( echo $(( 2# )) ) ( echo $(( 7 = 43 )) ) -#ash# echo $(( 2#44 )) +( echo $(( 2#44 )) ) ( echo $(( 44 / 0 )) ) ( let 'jv += $iv' ) ( echo $(( jv += \$iv )) ) diff --git a/shell/hush_test/hush-arith/arith-bignum1.right b/shell/hush_test/hush-arith/arith-bignum1.right new file mode 100644 index 000000000..42a8016ec --- /dev/null +++ b/shell/hush_test/hush-arith/arith-bignum1.right @@ -0,0 +1,13 @@ +18 digits: 999999999999999999 +19 digits: -8446744073709551617 +20 digits: 7766279631452241919 +18 digits- -999999999999999999 +19 digits- 8446744073709551617 +20 digits- -7766279631452241919 +Hex base#: +16 digits: 9876543210abcedf +17 digits: 876543210abcedfc +18 digits: 76543210abcedfcc +16 digits: 6789abcdef543121 +17 digits: 789abcdef5431204 +18 digits: 89abcdef54312034 diff --git a/shell/hush_test/hush-arith/arith-bignum1.tests b/shell/hush_test/hush-arith/arith-bignum1.tests new file mode 100755 index 000000000..ef8f928bc --- /dev/null +++ b/shell/hush_test/hush-arith/arith-bignum1.tests @@ -0,0 +1,17 @@ +exec 2>&1 +# If the number does not fit in 64 bits, bash uses truncated 64-bit value +# (essentially, it does not check for overflow in "n = n * base + digit" +# calculation). +echo 18 digits: $((999999999999999999)) +echo 19 digits: $((9999999999999999999)) +echo 20 digits: $((99999999999999999999)) +echo 18 digits- $((-999999999999999999)) +echo 19 digits- $((-9999999999999999999)) +echo 20 digits- $((-99999999999999999999)) +echo "Hex base#:" +printf '16 digits: %016x\n' $((16#9876543210abcedf)) +printf '17 digits: %016x\n' $((16#9876543210abcedfc)) +printf '18 digits: %016x\n' $((16#9876543210abcedfcc)) +printf '16 digits: %016x\n' $((-16#9876543210abcedf)) +printf '17 digits: %016x\n' $((-16#9876543210abcedfc)) +printf '18 digits: %016x\n' $((-16#9876543210abcedfcc)) diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right index df8154f97..d3a978611 100644 --- a/shell/hush_test/hush-arith/arith.right +++ b/shell/hush_test/hush-arith/arith.right @@ -82,7 +82,8 @@ other bases 62 62 63 63 missing number after base -0 0 +hush: arithmetic syntax error +hush: arithmetic syntax error hush: arithmetic syntax error hush: divide by zero hush: can't execute 'let': No such file or directory diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests index 6b707486c..9f0399816 100755 --- a/shell/hush_test/hush-arith/arith.tests +++ b/shell/hush_test/hush-arith/arith.tests @@ -159,12 +159,12 @@ echo 63 $(( 64#_ )) #ash# # weird bases (error) #ash# echo $(( 3425#56 )) -echo missing number after base -echo 0 $(( 2# )) # these should generate errors +echo missing number after base +( echo $(( 2# )) ) ( echo $(( 7 = 43 )) ) -#ash# echo $(( 2#44 )) +( echo $(( 2#44 )) ) ( echo $(( 44 / 0 )) ) ( let 'jv += $iv' ) ( echo $(( jv += \$iv )) ) diff --git a/shell/math.c b/shell/math.c index ac758639f..fbf5c587e 100644 --- a/shell/math.c +++ b/shell/math.c @@ -531,29 +531,11 @@ static const char op_tokens[] ALIGN1 = { #define END_POINTER (&op_tokens[sizeof(op_tokens)-1]) #if ENABLE_FEATURE_SH_MATH_BASE -static arith_t strto_arith_t(const char *nptr, char **endptr) +static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) { - unsigned base; - arith_t n; - -# if ENABLE_FEATURE_SH_MATH_64 - n = strtoull(nptr, endptr, 0); -# else - n = strtoul(nptr, endptr, 0); -# endif - if (**endptr != '#' - || (*nptr < '1' || *nptr > '9') - || (n < 2 || n > 64) - ) { - return n; - } + arith_t n = 0; + const char *start = nptr; - /* It's "N#nnnn" or "NN#nnnn" syntax, NN can't start with 0, - * NN is in 2..64 range. - */ - base = (unsigned)n; - n = 0; - nptr = *endptr + 1; for (;;) { unsigned digit = (unsigned)*nptr - '0'; if (digit >= 10 /* not 0..9 */ @@ -582,15 +564,52 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) n = n * base + digit; nptr++; } - /* Note: we do not set errno on bad chars, we just set a pointer - * to the first invalid char. For example, this allows - * "N#" (empty "nnnn" part): 64#+1 is a valid expression, - * it means 64# + 1, whereas 64#~... is not, since ~ is not a valid - * operator. - */ *endptr = (char*)nptr; + /* "64#" and "64#+1" used to be valid expressions, but bash 5.2.15 + * no longer allow such, detect this: + */ +// NB: bash allows $((0x)), this is probably a bug... + if (nptr == start) + *endptr = NULL; /* there weren't any digits, bad */ return n; } + +static arith_t strto_arith_t(const char *nptr, char **endptr) +{ +/* NB: we do not use strtoull here to be bash-compatible: + * $((99999999999999999999)) is 7766279631452241919 + * (the 64-bit truncated value). + */ + unsigned base; + + /* nptr[0] is '0'..'9' here */ + + base = nptr[0] - '0'; + if (base == 0) { /* nptr[0] is '0' */ + base = 8; + if ((nptr[1] | 0x20) == 'x') { + base = 16; + nptr += 2; + } +// NB: bash allows $((0x)), this is probably a bug... + return parse_with_base(nptr, endptr, base); + } + + if (nptr[1] == '#') { + if (base > 1) + return parse_with_base(nptr + 2, endptr, base); + /* else: bash says "invalid arithmetic base" */ + } + + if (isdigit(nptr[1]) && nptr[2] == '#') { + base = 10 * base + (nptr[1] - '0'); + if (base >= 2 && base <= 64) + return parse_with_base(nptr + 3, endptr, base); + /* else: bash says "invalid arithmetic base" */ + } + + return parse_with_base(nptr, endptr, 10); +} #else /* !ENABLE_FEATURE_SH_MATH_BASE */ # if ENABLE_FEATURE_SH_MATH_64 # define strto_arith_t(nptr, endptr) strtoull(nptr, endptr, 0) @@ -702,7 +721,6 @@ evaluate_string(arith_state_t *math_state, const char *expr) dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); expr = p; numstackptr->var_name = NULL; - push_num0: numstackptr->val = 0; } push_num: @@ -715,11 +733,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) /* Number */ char *end; numstackptr->var_name = NULL; - errno = 0; /* code is smaller compared to using &expr here: */ numstackptr->val = strto_arith_t(expr, &end); expr = end; dbg("[%d] val:%lld", (int)(numstackptr - numstack), numstackptr->val); + if (!expr) /* example: $((10#)) */ + goto syntax_err; /* A number can't be followed by another number, or a variable name. * We'd catch this later anyway, but this would require numstack[] * to be ~twice as deep to handle strings where _every_ char is @@ -728,13 +747,6 @@ evaluate_string(arith_state_t *math_state, const char *expr) */ if (isalnum(*expr) || *expr == '_') goto syntax_err; - if (errno) { -// TODO: bash 5.2.15 does not catch ERANGE (some older version did?). -// $((99999999999999999999)) is 7766279631452241919 (the 64-bit truncated value). -// Our BASE# code does this as well: try $((10#99999999999999999999)), -// but the "ordinary" code path with strtoull() does not do this. - goto push_num0; /* bash compat */ - } goto push_num; } -- cgit v1.2.3-55-g6feb From 5d8f8570c0c4220bfadb6d24d4fbc3e722d44802 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Jun 2023 09:59:56 +0200 Subject: shell/math: rename TOK_NUM to TOK_VALUE, improve comments Signed-off-by: Denys Vlasenko --- shell/math.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/shell/math.c b/shell/math.c index fbf5c587e..0426e2daa 100644 --- a/shell/math.c +++ b/shell/math.c @@ -94,7 +94,6 @@ * * Merge in Aaron's comments previously posted to the busybox list, * modified slightly to take account of my changes to the code. - * */ /* * (C) 2003 Vladimir Oleynik @@ -212,18 +211,18 @@ typedef unsigned char operator; #define TOK_UPLUS tok_decl(UNARYPREC+1,1) #define PREC_PRE (UNARYPREC+2) - #define TOK_PRE_INC tok_decl(PREC_PRE, 0) #define TOK_PRE_DEC tok_decl(PREC_PRE, 1) #define PREC_POST (UNARYPREC+3) - #define TOK_POST_INC tok_decl(PREC_POST, 0) #define TOK_POST_DEC tok_decl(PREC_POST, 1) -#define SPEC_PREC (UNARYPREC+4) - -#define TOK_NUM tok_decl(SPEC_PREC, 0) +/* TOK_VALUE marks a number, name, name++/name--, or (EXPR): + * IOW: something which can be used as the left side of a binary op. + * Since it's never pushed to opstack, its precedence does not matter. + */ +#define TOK_VALUE tok_decl(PREC_POST, 2) static int is_assign_op(operator op) @@ -625,7 +624,9 @@ evaluate_string(arith_state_t *math_state, const char *expr) var_or_num_t *numstack, *numstackptr; /* Stack of operator tokens */ operator *opstack, *opstackptr; + /* To detect whether we are after a "value": */ operator lasttok; + /* To insert implicit () in ?: ternary op: */ operator insert_op = 0xff; unsigned ternary_level = 0; const char *errmsg; @@ -720,12 +721,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) } else { dbg("[%d] var:IGNORED", (int)(numstackptr - numstack)); expr = p; - numstackptr->var_name = NULL; - numstackptr->val = 0; + numstackptr->var_name = NULL; /* not needed, paranoia */ + numstackptr->val = 0; /* not needed, paranoia */ } - push_num: + push_value: numstackptr++; - lasttok = TOK_NUM; + lasttok = TOK_VALUE; continue; } @@ -747,7 +748,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) */ if (isalnum(*expr) || *expr == '_') goto syntax_err; - goto push_num; + goto push_value; } /* Should be an operator */ @@ -818,15 +819,14 @@ evaluate_string(arith_state_t *math_state, const char *expr) dbg("insert_op=%02x op=%02x", insert_op, op); } tok_found1: - /* post grammar: a++ reduce to num */ - if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC) - lasttok = TOK_NUM; + /* NAME++ is a "value" (something suitable for a binop) */ + if (PREC(lasttok) == PREC_POST) + lasttok = TOK_VALUE; /* Plus and minus are binary (not unary) _only_ if the last - * token was a number, or a right paren (which pretends to be - * a number, since it evaluates to one). Think about it. - * It makes sense. */ - if (lasttok != TOK_NUM) { + * token was a "value". Think about it. It makes sense. + */ + if (lasttok != TOK_VALUE) { switch (op) { case TOK_ADD: //op = TOK_UPLUS; @@ -857,8 +857,8 @@ evaluate_string(arith_state_t *math_state, const char *expr) prec = PREC(op); if (prec != PREC_LPAREN && prec < UNARYPREC) { /* binary, ternary or RPAREN */ - if (lasttok != TOK_NUM) { - /* must be preceded by a num */ + if (lasttok != TOK_VALUE) { + /* must be preceded by a num (example?) */ goto syntax_err; } /* if op is RPAREN: @@ -883,11 +883,12 @@ evaluate_string(arith_state_t *math_state, const char *expr) operator prev_op = *--opstackptr; if (op == TOK_RPAREN) { if (prev_op == TOK_LPAREN) { - /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */ + /* Erase var name: for example, (VAR) = 1 is not valid */ numstackptr[-1].var_name = NULL; - /* Any operator directly after a - * close paren should consider itself binary */ - lasttok = TOK_NUM; + /* (EXPR) is a "value": next operator directly after + * close paren should be considered binary + */ + lasttok = TOK_VALUE; goto next; } /* Not (y), but ...x~y). Fall through to evaluate x~y */ -- cgit v1.2.3-55-g6feb From e619a25a551ac6a5f215005166371074a9e2816f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Jun 2023 11:08:40 +0200 Subject: shell/math: improve comments Signed-off-by: Denys Vlasenko --- shell/math.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/math.c b/shell/math.c index 0426e2daa..9e81d604c 100644 --- a/shell/math.c +++ b/shell/math.c @@ -856,9 +856,11 @@ evaluate_string(arith_state_t *math_state, const char *expr) */ prec = PREC(op); if (prec != PREC_LPAREN && prec < UNARYPREC) { - /* binary, ternary or RPAREN */ + /* Binary, ternary or RPAREN */ if (lasttok != TOK_VALUE) { - /* must be preceded by a num (example?) */ + /* Must be preceded by a value. + * $((2 2 + * 3)) would be accepted without this. + */ goto syntax_err; } /* if op is RPAREN: -- cgit v1.2.3-55-g6feb From 800207b90a4f5f78cbe65a0f4b3ecd3b93abbd7d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 28 Jun 2023 14:18:35 +0200 Subject: shell/math: code shrink function old new delta arith_apply 1015 1023 +8 evaluate_string 1309 1295 -14 .rodata 105344 105321 -23 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 8/-37) Total: -29 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/shell/math.c b/shell/math.c index 9e81d604c..e15b014aa 100644 --- a/shell/math.c +++ b/shell/math.c @@ -141,6 +141,7 @@ typedef unsigned char operator; * but there are 11 of them, which doesn't fit into 3 bits for unique id. * Abusing another precedence level: */ +#define PREC_ASSIGN1 2 #define TOK_ASSIGN tok_decl(2,0) #define TOK_AND_ASSIGN tok_decl(2,1) #define TOK_OR_ASSIGN tok_decl(2,2) @@ -150,11 +151,12 @@ typedef unsigned char operator; #define TOK_LSHIFT_ASSIGN tok_decl(2,6) #define TOK_RSHIFT_ASSIGN tok_decl(2,7) +#define PREC_ASSIGN2 3 #define TOK_MUL_ASSIGN tok_decl(3,0) #define TOK_DIV_ASSIGN tok_decl(3,1) #define TOK_REM_ASSIGN tok_decl(3,2) -#define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0) +#define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0) /* Ternary conditional operator is right associative too */ /* @@ -211,25 +213,25 @@ typedef unsigned char operator; #define TOK_UPLUS tok_decl(UNARYPREC+1,1) #define PREC_PRE (UNARYPREC+2) -#define TOK_PRE_INC tok_decl(PREC_PRE, 0) -#define TOK_PRE_DEC tok_decl(PREC_PRE, 1) +#define TOK_PRE_INC tok_decl(PREC_PRE,0) +#define TOK_PRE_DEC tok_decl(PREC_PRE,1) #define PREC_POST (UNARYPREC+3) -#define TOK_POST_INC tok_decl(PREC_POST, 0) -#define TOK_POST_DEC tok_decl(PREC_POST, 1) +#define TOK_POST_INC tok_decl(PREC_POST,0) +#define TOK_POST_DEC tok_decl(PREC_POST,1) /* TOK_VALUE marks a number, name, name++/name--, or (EXPR): * IOW: something which can be used as the left side of a binary op. * Since it's never pushed to opstack, its precedence does not matter. */ -#define TOK_VALUE tok_decl(PREC_POST, 2) +#define TOK_VALUE tok_decl(PREC_POST,2) static int is_assign_op(operator op) { operator prec = PREC(op); - fix_assignment_prec(prec); - return prec == PREC(TOK_ASSIGN) + return prec == PREC_ASSIGN1 + || prec == PREC_ASSIGN2 || prec == PREC_PRE || prec == PREC_POST; } -- cgit v1.2.3-55-g6feb From 6a0ba673820cb6880e2f93f739de7d16d45d2b26 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Jun 2023 11:01:50 +0200 Subject: shell/math: code shrink function old new delta arith_apply 1023 996 -27 Signed-off-by: Denys Vlasenko --- shell/math.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/shell/math.c b/shell/math.c index e15b014aa..5b996703e 100644 --- a/shell/math.c +++ b/shell/math.c @@ -313,8 +313,10 @@ arith_lookup_val(arith_state_t *math_state, const char *name, char *endname) } /* "Applying" a token means performing it on the top elements on the integer - * stack. For an unary operator it will only change the top element, but a - * binary operator will pop two arguments and push the result */ + * stack. For an unary operator it will only change the top element, + * a binary operator will pop two arguments and push the result, + * the ternary ?: op will pop three arguments and push the result. + */ static NOINLINE const char* arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_or_num_t **numstackptr) { @@ -337,9 +339,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ return "malformed ?: operator"; if (expr1->val != 0) /* select expr2 or expr3 */ top_of_stack--; - expr1->val = top_of_stack->val; - expr1->var_name = NULL; - return NULL; + rez = top_of_stack->val; + top_of_stack = expr1; + goto ret_rez; } if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */ return "malformed ?: operator"; @@ -469,13 +471,13 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ math_state->setvar(top_of_stack->var_name, buf); *e = c; } - /* After saving, make previous value for v++ or v-- */ - if (op == TOK_POST_INC) - rez--; - if (op == TOK_POST_DEC) - rez++; + /* VAR++ or VAR--? */ + if (PREC(op) == PREC_POST) { + /* Do not store new value to stack (keep old value) */ + goto ret_NULL; + } } - + ret_rez: top_of_stack->val = rez; ret_NULL: /* Erase var name, it is just a number now */ -- cgit v1.2.3-55-g6feb From 38f769ab4e5f6cd2ffab88300ddaddef3aac3345 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 30 Jun 2023 19:16:41 +0200 Subject: shell/math: code shrink function old new delta arith_apply 999 996 -3 evaluate_string 1295 1291 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-7) Total: -7 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/shell/math.c b/shell/math.c index 5b996703e..beb89d140 100644 --- a/shell/math.c +++ b/shell/math.c @@ -369,7 +369,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (math_state->evaluation_disabled) { dbg("binary op %02x skipped", op); - goto ret_NULL; + return NULL; /* bash 5.2.12 does not execute "2/0" in disabled * branches of ?: (and thus does not complain), * but complains about negative exp: "2**-1". @@ -452,7 +452,7 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (math_state->evaluation_disabled) { dbg("unary op %02x skipped", op); - goto ret_NULL; + return NULL; } if (is_assign_op(op)) { @@ -598,15 +598,18 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) return parse_with_base(nptr, endptr, base); } + /* base is 1..9 here */ + if (nptr[1] == '#') { if (base > 1) return parse_with_base(nptr + 2, endptr, base); - /* else: bash says "invalid arithmetic base" */ + /* else: "1#NN", bash says "invalid arithmetic base" */ } if (isdigit(nptr[1]) && nptr[2] == '#') { base = 10 * base + (nptr[1] - '0'); - if (base >= 2 && base <= 64) + /* base is at least 10 here */ + if (base <= 64) return parse_with_base(nptr + 3, endptr, base); /* else: bash says "invalid arithmetic base" */ } -- cgit v1.2.3-55-g6feb From 045924ed7d3c887cce1c6a22a0b4e0b692719154 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Jul 2023 17:58:20 +0200 Subject: shell/math: do not accept $((36#@)) function old new delta parse_with_base 170 174 +4 arith_apply 996 991 -5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 4/-5) Total: -1 bytes Signed-off-by: Denys Vlasenko --- shell/math.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/shell/math.c b/shell/math.c index beb89d140..b06d1ae3c 100644 --- a/shell/math.c +++ b/shell/math.c @@ -128,7 +128,8 @@ typedef unsigned char operator; * Consider * and / */ #define tok_decl(prec,id) (((id)<<5) | (prec)) -#define PREC(op) ((op) & 0x1F) +#define ID_SHIFT 5 +#define PREC(op) ((op) & 0x1f) #define PREC_LPAREN 0 #define TOK_LPAREN tok_decl(0,0) @@ -146,14 +147,16 @@ typedef unsigned char operator; #define TOK_AND_ASSIGN tok_decl(2,1) #define TOK_OR_ASSIGN tok_decl(2,2) #define TOK_XOR_ASSIGN tok_decl(2,3) -#define TOK_PLUS_ASSIGN tok_decl(2,4) -#define TOK_MINUS_ASSIGN tok_decl(2,5) +#define TOK_ADD_ASSIGN tok_decl(2,4) +#define TOK_SUB_ASSIGN tok_decl(2,5) #define TOK_LSHIFT_ASSIGN tok_decl(2,6) #define TOK_RSHIFT_ASSIGN tok_decl(2,7) #define PREC_ASSIGN2 3 #define TOK_MUL_ASSIGN tok_decl(3,0) -#define TOK_DIV_ASSIGN tok_decl(3,1) +/* "/" and "/=" ops have the same id bits */ +#define DIV_ID1 1 +#define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1) #define TOK_REM_ASSIGN tok_decl(3,2) #define fix_assignment_prec(prec) do { prec -= (prec == 3); } while (0) @@ -198,7 +201,7 @@ typedef unsigned char operator; #define TOK_SUB tok_decl(13,1) #define TOK_MUL tok_decl(14,0) -#define TOK_DIV tok_decl(14,1) +#define TOK_DIV tok_decl(14,DIV_ID1) #define TOK_REM tok_decl(14,2) /* Exponent is right associative */ @@ -408,9 +411,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ rez = (rez <= right_side_val); else if (op == TOK_MUL || op == TOK_MUL_ASSIGN) rez *= right_side_val; - else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN) + else if (op == TOK_ADD || op == TOK_ADD_ASSIGN) rez += right_side_val; - else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN) + else if (op == TOK_SUB || op == TOK_SUB_ASSIGN) rez -= right_side_val; else if (op == TOK_ASSIGN || op == TOK_COMMA) rez = right_side_val; @@ -439,11 +442,11 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ * Make sure to at least not SEGV here: */ if (right_side_val == -1 - && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */ + && (rez << 1) == 0 /* MAX_NEGATIVE_INT or 0 */ ) { right_side_val = 1; } - if (op == TOK_DIV || op == TOK_DIV_ASSIGN) + if (op & (DIV_ID1 << ID_SHIFT)) /* DIV or DIV_ASSIGN? */ rez /= right_side_val; else rez %= right_side_val; @@ -505,8 +508,8 @@ static const char op_tokens[] ALIGN1 = { '*','=', 0, TOK_MUL_ASSIGN, '/','=', 0, TOK_DIV_ASSIGN, '%','=', 0, TOK_REM_ASSIGN, - '+','=', 0, TOK_PLUS_ASSIGN, - '-','=', 0, TOK_MINUS_ASSIGN, + '+','=', 0, TOK_ADD_ASSIGN, + '-','=', 0, TOK_SUB_ASSIGN, '-','-', 0, TOK_POST_DEC, '^','=', 0, TOK_XOR_ASSIGN, '+','+', 0, TOK_POST_INC, @@ -542,12 +545,15 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) for (;;) { unsigned digit = (unsigned)*nptr - '0'; if (digit >= 10 /* not 0..9 */ - && digit <= 'z' - '0' /* needed to reject e.g. $((64#~)) */ + && digit <= 'z' - '0' /* reject e.g. $((64#~)) */ ) { - /* in bases up to 36, case does not matter for a-z */ + /* current char is one of :;<=>?@A..Z[\]^_`a..z */ + + /* in bases up to 36, case does not matter for a-z, + * map A..Z and a..z to 10..35: */ digit = (unsigned)(*nptr | 0x20) - ('a' - 10); if (base > 36 && *nptr <= '_') { - /* otherwise, A-Z,@,_ are 36-61,62,63 */ + /* base > 36: A-Z,@,_ are 36-61,62,63 */ if (*nptr == '_') digit = 63; else if (*nptr == '@') @@ -558,8 +564,8 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) break; /* error: one of [\]^ */ } //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit); - //if (digit < 10) - example where we need this? - // break; + if (digit < 10) /* reject e.g. $((36#@)) */ + break; } if (digit >= base) break; -- cgit v1.2.3-55-g6feb From cc9543fed1f916f62a63cfbe9eaefba3df8e22cb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 2 Jul 2023 19:32:12 +0200 Subject: shell/math: avoid $((3**999999999999999999)) to take years function old new delta arith_apply 991 1030 +39 Signed-off-by: Denys Vlasenko --- shell/math.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/shell/math.c b/shell/math.c index b06d1ae3c..e90a38f05 100644 --- a/shell/math.c +++ b/shell/math.c @@ -155,7 +155,7 @@ typedef unsigned char operator; #define PREC_ASSIGN2 3 #define TOK_MUL_ASSIGN tok_decl(3,0) /* "/" and "/=" ops have the same id bits */ -#define DIV_ID1 1 +#define DIV_ID1 1 #define TOK_DIV_ASSIGN tok_decl(3,DIV_ID1) #define TOK_REM_ASSIGN tok_decl(3,2) @@ -422,8 +422,19 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ if (right_side_val < 0) return "exponent less than 0"; c = 1; - while (--right_side_val >= 0) + while (right_side_val != 0) { + if ((right_side_val & 1) == 0) { + /* this if() block is not necessary for correctness, + * but otherwise echo $((3**999999999999999999)) + * takes a VERY LONG time + * (and it's not interruptible by ^C) + */ + rez *= rez; + right_side_val >>= 1; + } c *= rez; + right_side_val--; + } rez = c; } else /*if (op == TOK_DIV || op == TOK_DIV_ASSIGN @@ -550,7 +561,7 @@ static arith_t parse_with_base(const char *nptr, char **endptr, unsigned base) /* current char is one of :;<=>?@A..Z[\]^_`a..z */ /* in bases up to 36, case does not matter for a-z, - * map A..Z and a..z to 10..35: */ + * map @A..Z and `a..z to 9..35: */ digit = (unsigned)(*nptr | 0x20) - ('a' - 10); if (base > 36 && *nptr <= '_') { /* base > 36: A-Z,@,_ are 36-61,62,63 */ -- cgit v1.2.3-55-g6feb From e5692e2342c68092ee3d4d895ea847cf7d13fa57 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 3 Jul 2023 14:30:59 +0200 Subject: hush: quote values in "readonly" output function old new delta builtin_readonly 61 107 +46 builtin_export 140 145 +5 .rodata 105321 105304 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 51/-17) Total: 34 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 426182924..ec4f3a2f2 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -11307,8 +11307,8 @@ static int FAST_FUNC builtin_export(char **argv) if (!p) /* wtf? take next variable */ continue; - /* export var= */ - printf("export %.*s", (int)(p - s) + 1, s); + /* "export VAR=" */ + printf("%s %.*s", "export", (int)(p - s) + 1, s); print_escaped(p + 1); putchar('\n'); # endif @@ -11352,8 +11352,15 @@ static int FAST_FUNC builtin_readonly(char **argv) struct variable *e; for (e = G.top_var; e; e = e->next) { if (e->flg_read_only) { -//TODO: quote value: readonly VAR='VAL' - printf("readonly %s\n", e->varstr); + const char *s = e->varstr; + const char *p = strchr(s, '='); + + if (!p) /* wtf? take next variable */ + continue; + /* "readonly VAR=" */ + printf("%s %.*s", "readonly", (int)(p - s) + 1, s); + print_escaped(p + 1); + putchar('\n'); } } return EXIT_SUCCESS; -- cgit v1.2.3-55-g6feb From 07a95cfcabb0706a22599b4440b495b6cfa8123e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Jul 2023 14:35:41 +0200 Subject: ash: disable check for "good" function name, bash does not check this function old new delta .rodata 105304 105261 -43 parse_command 1696 1633 -63 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-106) Total: -106 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 17 +++++++++-------- shell/hush.c | 7 ++++++- shell/hush_test/hush-vars/readonly0.right | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 96d2433d3..e91566994 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12123,18 +12123,19 @@ simplecmd(void) if (args && app == &args->narg.next && !vars && !redir ) { - struct builtincmd *bcmd; - const char *name; +// struct builtincmd *bcmd; +// const char *name; /* We have a function */ if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP) raise_error_unexpected_syntax(TRP); - name = n->narg.text; - if (!goodname(name) - || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd)) - ) { - raise_error_syntax("bad function name"); - } +//bash allows functions named "123", "..", "return"! +// name = n->narg.text; +// if (!goodname(name) +// || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd)) +// ) { +// raise_error_syntax("bad function name"); +// } n->type = NDEFUN; checkkwd = CHKNL | CHKKWD | CHKALIAS; n->ndefun.text = n->narg.text; diff --git a/shell/hush.c b/shell/hush.c index ec4f3a2f2..1b7e546fa 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4306,7 +4306,7 @@ static int done_word(struct parse_context *ctx) || endofname(command->argv[0])[0] != '\0' ) { /* bash says just "not a valid identifier" */ - syntax_error("bad variable name in for"); + syntax_error("bad for loop variable"); return 1; } /* Force FOR to have just one word (variable name) */ @@ -4683,6 +4683,11 @@ static int parse_group(struct parse_context *ctx, syntax_error_unexpected_ch(ch); return -1; } +//bash allows functions named "123", "..", "return"! +// if (endofname(command->argv[0])[0] != '\0') { +// syntax_error("bad function name"); +// return -1; +// } nommu_addchr(&ctx->as_string, ch); command->cmd_type = CMD_FUNCDEF; goto skip; diff --git a/shell/hush_test/hush-vars/readonly0.right b/shell/hush_test/hush-vars/readonly0.right index 8b750eb5f..7599698d2 100644 --- a/shell/hush_test/hush-vars/readonly0.right +++ b/shell/hush_test/hush-vars/readonly0.right @@ -1,5 +1,5 @@ -readonly a=A -readonly b=B +readonly a='A' +readonly b='B' Ok:0 hush: a=A: readonly variable -- cgit v1.2.3-55-g6feb From e41e481fd5716fc9b2e2fdf2670d72c727ecb37f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 8 Jul 2023 17:57:42 +0200 Subject: hush: fix a compile failure 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 1b7e546fa..2f55b92ea 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -11173,7 +11173,7 @@ static int FAST_FUNC builtin_umask(char **argv) } #endif -#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP +#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY || ENABLE_HUSH_SET || ENABLE_HUSH_TRAP static void print_escaped(const char *s) { //TODO? bash "set" does not quote variables which contain only alnums and "%+,-./:=@_~", -- cgit v1.2.3-55-g6feb From 6ce1dc2e91398145633ceaff7a6fecc786826277 Mon Sep 17 00:00:00 2001 From: Yousong Zhou Date: Sun, 12 Feb 2023 12:30:20 +0800 Subject: libiproute: fix filtering ip6 route by table id Otherwise - "ip -6 route show" shows routes from all tables - "ip -6 route show table 200" shows nothing function old new delta print_route 1962 1941 -21 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-21) Total: -21 bytes Signed-off-by: Yousong Zhou Signed-off-by: Denys Vlasenko --- networking/libiproute/iproute.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/networking/libiproute/iproute.c b/networking/libiproute/iproute.c index 5a972f8b2..cd77f642f 100644 --- a/networking/libiproute/iproute.c +++ b/networking/libiproute/iproute.c @@ -111,15 +111,7 @@ static int FAST_FUNC print_route(const struct sockaddr_nl *who UNUSED_PARAM, if (r->rtm_flags & RTM_F_CLONED) { return 0; } - if (G_filter.tb == RT_TABLE_LOCAL) { - if (r->rtm_type != RTN_LOCAL) { - return 0; - } - } else if (G_filter.tb == RT_TABLE_MAIN) { - if (r->rtm_type == RTN_LOCAL) { - return 0; - } - } else { + if (G_filter.tb != tid) { return 0; } } -- cgit v1.2.3-55-g6feb From 5e0411a7fb510b9aecda0a850c76bdd62c50efa4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Jul 2023 10:52:41 +0200 Subject: ash: disable sleep as builtin, closes 15619 Has a few annoying problems: * sleepcmd() -> sleep_main(), the parsing of bad arguments exits the shell. * sleep_for_duration() in sleep_main() has to be interruptible for ^C traps to work, which may be a problem for other users of sleep_for_duration(). * BUT, if sleep_for_duration() is interruptible, then SIGCHLD interrupts it as well (try "/bin/sleep 1 & sleep 10"). * sleep_main() must not allocate anything as ^C in ash longjmp's. (currently, allocations are only on error paths, in message printing). Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ shell/ash.c | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 18336da23..640fa3988 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1513,6 +1513,8 @@ int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE); /* If shell needs them, they exist even if not enabled as applets */ int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); int sleep_main(int argc, char **argv) IF_SLEEP(MAIN_EXTERNALLY_VISIBLE); +/* See disabled "config ASH_SLEEP" in ash.c */ +#define ENABLE_ASH_SLEEP 0 int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); int test_main(int argc, char **argv) #if ENABLE_TEST || ENABLE_TEST1 || ENABLE_TEST2 diff --git a/shell/ash.c b/shell/ash.c index e91566994..e154cc6cc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -134,11 +134,23 @@ //config: default y //config: depends on SHELL_ASH //config: -//config:config ASH_SLEEP -//config: bool "sleep builtin" -//config: default y -//config: depends on SHELL_ASH -//config: +// +////config:config ASH_SLEEP +////config: bool "sleep builtin" +////config: default y +////config: depends on SHELL_ASH +////config: +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//Disabled for now. Has a few annoying problems: +// * sleepcmd() -> sleep_main(), the parsing of bad arguments exits the shell. +// * sleep_for_duration() in sleep_main() has to be interruptible for +// ^C traps to work, which may be a problem for other users +// of sleep_for_duration(). +// * BUT, if sleep_for_duration() is interruptible, then SIGCHLD interrupts it +// as well (try "/bin/sleep 1 & sleep 10"). +// * sleep_main() must not allocate anything as ^C in ash longjmp's. +// (currently, allocations are only on error paths, in message printing). +// //config:config ASH_HELP //config: bool "help builtin" //config: default y -- cgit v1.2.3-55-g6feb From ae351311da0d4e6642f746ae4a9c9a60f83e1e25 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Jul 2023 11:13:51 +0200 Subject: ash: remove "volatile" specifier from suppress_int function old new delta aliascmd 274 278 +4 signal_handler 81 80 -1 static.redirectsafe 144 141 -3 unwindlocalvars 219 215 -4 trapcmd 333 329 -4 setvar 164 160 -4 setpwd 167 163 -4 setinputfile 216 212 -4 setcmd 76 72 -4 readcmd 221 217 -4 raise_exception 26 22 -4 out2str 37 33 -4 out1str 32 28 -4 freejob 89 85 -4 forkchild 616 612 -4 fg_bgcmd 298 294 -4 expandarg 949 945 -4 evaltree 753 749 -4 evalsubshell 173 169 -4 evalpipe 346 342 -4 evalfun 408 404 -4 cdcmd 699 695 -4 ash_main 1240 1236 -4 __pgetc 589 585 -4 unaliascmd 152 147 -5 unalias 51 46 -5 umaskcmd 253 248 -5 stalloc 97 92 -5 shiftcmd 144 139 -5 setinputstring 73 68 -5 redirect 1068 1063 -5 recordregion 81 76 -5 pushstring 160 155 -5 popstring 120 115 -5 popstackmark 69 64 -5 popredir 123 118 -5 popfile 110 105 -5 out1fmt 45 40 -5 newline_and_flush 39 34 -5 ifsfree 66 61 -5 growstackblock 146 141 -5 freestrings 95 90 -5 fmtstr 59 54 -5 flush_stdout_stderr 23 18 -5 dowait 577 572 -5 delete_cmd_entry 52 47 -5 clearcmdentry 98 93 -5 ash_arith 79 74 -5 argstr 1404 1399 -5 evalcommand 1523 1515 -8 removerecordregions 219 209 -10 mklocal 284 274 -10 find_command 893 883 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/52 up/down: 4/-251) Total: -247 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index e154cc6cc..1764b43c9 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -424,7 +424,11 @@ struct globals_misc { struct jmploc *exception_handler; - volatile int suppress_int; /* counter */ + /*volatile*/ int suppress_int; /* counter */ + /* ^^^^^^^ removed "volatile" since gcc would turn suppress_int++ into ridiculouls + * 3-insn sequence otherwise. + * We don't change suppress_int asyncronously (in a signal handler), but we do read it async. + */ volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */ volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */ volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */ @@ -717,7 +721,8 @@ int_on(void) { barrier(); if (--suppress_int == 0 && pending_int) - raise_interrupt(); + raise_interrupt(); /* does not return */ + barrier(); } #if DEBUG_INTONOFF # define INT_ON do { \ @@ -733,7 +738,8 @@ force_int_on(void) barrier(); suppress_int = 0; if (pending_int) - raise_interrupt(); + raise_interrupt(); /* does not return */ + barrier(); } #define FORCE_INT_ON force_int_on() @@ -743,7 +749,8 @@ force_int_on(void) barrier(); \ suppress_int = (v); \ if (suppress_int == 0 && pending_int) \ - raise_interrupt(); \ + raise_interrupt(); /* does not return */ \ + barrier(); \ } while (0) -- cgit v1.2.3-55-g6feb From a9047e09807f11bcd62f69c481ce19b2663f8862 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Jul 2023 12:02:34 +0200 Subject: ash: tweak comments, no code changes Signed-off-by: Denys Vlasenko --- shell/ash.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 1764b43c9..8bdeb44ae 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -425,9 +425,10 @@ struct globals_misc { struct jmploc *exception_handler; /*volatile*/ int suppress_int; /* counter */ - /* ^^^^^^^ removed "volatile" since gcc would turn suppress_int++ into ridiculouls - * 3-insn sequence otherwise. - * We don't change suppress_int asyncronously (in a signal handler), but we do read it async. + /* ^^^^^^^ removed "volatile" since on x86, gcc turns suppress_int++ + * into ridiculous 3-insn sequence otherwise. + * We don't change suppress_int asyncronously (in a signal handler), + * but we do read it async. */ volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */ volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */ @@ -9438,7 +9439,7 @@ evaltree(union node *n, int flags) } if (flags & EV_EXIT) { exexit: - raise_exception(EXEND); + raise_exception(EXEND); /* does not return */ } popstackmark(&smark); @@ -10466,7 +10467,7 @@ evalcommand(union node *cmd, int flags) /* We have a redirection error. */ if (spclbltin > 0) - raise_exception(EXERROR); + raise_exception(EXERROR); /* does not return */ goto out; } @@ -14571,7 +14572,7 @@ procargs(char **argv) optlist[i] = 2; if (options(&login_sh)) { /* it already printed err message */ - raise_exception(EXERROR); + raise_exception(EXERROR); /* does not return */ } xargv = argptr; xminusc = minusc; -- cgit v1.2.3-55-g6feb From 5353df91cba7b397b9407701681708d0a1518df6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Jul 2023 17:25:21 +0200 Subject: Update applet size estimates Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 8 ++++---- archival/dpkg_deb.c | 2 +- archival/lzop.c | 2 +- console-tools/chvt.c | 2 +- console-tools/clear.c | 2 +- console-tools/deallocvt.c | 2 +- console-tools/dumpkmap.c | 2 +- console-tools/fgconsole.c | 2 +- console-tools/kbd_mode.c | 2 +- console-tools/loadfont.c | 2 +- console-tools/loadkmap.c | 2 +- console-tools/openvt.c | 2 +- console-tools/reset.c | 2 +- console-tools/resize.c | 2 +- console-tools/setconsole.c | 2 +- console-tools/setkeycodes.c | 2 +- console-tools/setlogcons.c | 2 +- console-tools/showkey.c | 2 +- coreutils/basename.c | 2 +- coreutils/cat.c | 2 +- coreutils/chroot.c | 2 +- coreutils/cksum.c | 4 ++-- coreutils/comm.c | 2 +- coreutils/cut.c | 2 +- coreutils/date.c | 2 +- coreutils/dd.c | 2 +- coreutils/df.c | 2 +- coreutils/dirname.c | 2 +- coreutils/dos2unix.c | 4 ++-- coreutils/du.c | 2 +- coreutils/echo.c | 2 +- coreutils/env.c | 2 +- coreutils/expand.c | 4 ++-- coreutils/expr.c | 2 +- coreutils/factor.c | 2 +- coreutils/false.c | 2 +- coreutils/fold.c | 2 +- coreutils/head.c | 2 +- coreutils/hostid.c | 2 +- coreutils/id.c | 4 ++-- coreutils/link.c | 2 +- coreutils/ln.c | 2 +- coreutils/logname.c | 2 +- coreutils/md5_sha1_sum.c | 10 +++++----- coreutils/mkdir.c | 2 +- coreutils/mkfifo.c | 2 +- coreutils/mknod.c | 2 +- coreutils/mktemp.c | 2 +- coreutils/nice.c | 2 +- coreutils/nl.c | 2 +- coreutils/nohup.c | 2 +- coreutils/nproc.c | 2 +- coreutils/paste.c | 2 +- coreutils/printenv.c | 2 +- coreutils/printf.c | 2 +- coreutils/pwd.c | 2 +- coreutils/readlink.c | 2 +- coreutils/realpath.c | 2 +- coreutils/rm.c | 2 +- coreutils/rmdir.c | 2 +- coreutils/seq.c | 2 +- coreutils/shred.c | 2 +- coreutils/shuf.c | 2 +- coreutils/sleep.c | 2 +- coreutils/sort.c | 2 +- coreutils/split.c | 2 +- coreutils/stty.c | 2 +- coreutils/sum.c | 2 +- coreutils/sync.c | 4 ++-- coreutils/tac.c | 2 +- coreutils/tail.c | 2 +- coreutils/tee.c | 2 +- coreutils/test.c | 2 +- coreutils/timeout.c | 2 +- coreutils/touch.c | 2 +- coreutils/tr.c | 2 +- coreutils/true.c | 2 +- coreutils/truncate.c | 2 +- coreutils/tsort.c | 2 +- coreutils/tty.c | 2 +- coreutils/uname.c | 4 ++-- coreutils/uniq.c | 2 +- coreutils/unlink.c | 2 +- coreutils/usleep.c | 2 +- coreutils/uudecode.c | 6 +++--- coreutils/uuencode.c | 2 +- coreutils/wc.c | 2 +- coreutils/who.c | 6 +++--- coreutils/whoami.c | 2 +- coreutils/yes.c | 2 +- debianutils/pipe_progress.c | 2 +- debianutils/run_parts.c | 2 +- debianutils/which.c | 2 +- e2fsprogs/chattr.c | 2 +- e2fsprogs/fsck.c | 2 +- e2fsprogs/lsattr.c | 2 +- editors/awk.c | 2 +- editors/cmp.c | 2 +- editors/ed.c | 2 +- editors/patch.c | 2 +- editors/patch_toybox.c | 2 +- editors/vi.c | 2 +- findutils/find.c | 2 +- findutils/grep.c | 6 +++--- findutils/xargs.c | 2 +- init/halt.c | 6 +++--- klibc-utils/resume.c | 2 +- klibc-utils/run-init.c | 2 +- loginutils/add-remove-shell.c | 4 ++-- loginutils/addgroup.c | 2 +- loginutils/chpasswd.c | 2 +- loginutils/cryptpw.c | 4 ++-- loginutils/deluser.c | 4 ++-- loginutils/getty.c | 2 +- loginutils/login.c | 2 +- loginutils/passwd.c | 2 +- loginutils/sulogin.c | 2 +- loginutils/vlock.c | 2 +- mailutils/makemime.c | 2 +- mailutils/popmaildir.c | 2 +- mailutils/reformime.c | 2 +- miscutils/adjtimex.c | 2 +- miscutils/ascii.c | 2 +- miscutils/bc.c | 4 ++-- miscutils/beep.c | 2 +- miscutils/chat.c | 2 +- miscutils/crond.c | 2 +- miscutils/devmem.c | 2 +- miscutils/hexedit.c | 2 +- miscutils/i2c_tools.c | 10 +++++----- miscutils/lsscsi.c | 2 +- miscutils/makedevs.c | 2 +- miscutils/microcom.c | 2 +- miscutils/mt.c | 2 +- miscutils/nandwrite.c | 4 ++-- miscutils/partprobe.c | 2 +- miscutils/raidautorun.c | 2 +- miscutils/readahead.c | 2 +- miscutils/runlevel.c | 2 +- miscutils/rx.c | 2 +- miscutils/seedrng.c | 2 +- miscutils/setfattr.c | 2 +- miscutils/setserial.c | 2 +- miscutils/strings.c | 2 +- miscutils/time.c | 2 +- miscutils/tree.c | 2 +- miscutils/ts.c | 2 +- miscutils/ttysize.c | 2 +- miscutils/ubi_tools.c | 12 ++++++------ miscutils/ubirename.c | 2 +- miscutils/volname.c | 2 +- miscutils/watchdog.c | 2 +- modutils/lsmod.c | 2 +- modutils/modprobe.c | 2 +- modutils/rmmod.c | 2 +- networking/arping.c | 2 +- networking/brctl.c | 2 +- networking/dnsd.c | 2 +- networking/ether-wake.c | 2 +- networking/ftpgetput.c | 4 ++-- networking/hostname.c | 4 ++-- networking/ifplugd.c | 2 +- networking/ip.c | 6 +++--- networking/ipcalc.c | 2 +- networking/isrv_identd.c | 2 +- networking/nameif.c | 2 +- networking/nbd-client.c | 2 +- networking/nslookup.c | 2 +- networking/ntpd.c | 2 +- networking/pscan.c | 2 +- networking/route.c | 2 +- networking/slattach.c | 2 +- networking/ssl_client.c | 2 +- networking/telnetd.c | 2 +- networking/traceroute.c | 2 +- networking/tunctl.c | 2 +- networking/udhcp/Config.src | 4 ++-- networking/vconfig.c | 2 +- networking/wget.c | 2 +- networking/whois.c | 2 +- networking/zcip.c | 2 +- printutils/lpd.c | 2 +- printutils/lpr.c | 4 ++-- procps/free.c | 2 +- procps/fuser.c | 2 +- procps/iostat.c | 2 +- procps/kill.c | 6 +++--- procps/lsof.c | 2 +- procps/mpstat.c | 2 +- procps/nmeter.c | 2 +- procps/pgrep.c | 4 ++-- procps/pidof.c | 2 +- procps/pmap.c | 2 +- procps/powertop.c | 2 +- procps/ps.c | 2 +- procps/pstree.c | 2 +- procps/pwdx.c | 2 +- procps/smemcap.c | 2 +- procps/sysctl.c | 2 +- procps/uptime.c | 2 +- procps/watch.c | 2 +- runit/chpst.c | 10 +++++----- runit/runsv.c | 2 +- runit/runsvdir.c | 2 +- runit/sv.c | 6 +++--- shell/ash.c | 2 +- shell/cttyhack.c | 2 +- shell/hush.c | 2 +- sysklogd/klogd.c | 2 +- sysklogd/logger.c | 2 +- sysklogd/logread.c | 2 +- sysklogd/syslogd.c | 2 +- util-linux/acpid.c | 2 +- util-linux/blkdiscard.c | 2 +- util-linux/blockdev.c | 2 +- util-linux/cal.c | 2 +- util-linux/chrt.c | 2 +- util-linux/dmesg.c | 2 +- util-linux/eject.c | 2 +- util-linux/fallocate.c | 2 +- util-linux/fatattr.c | 2 +- util-linux/fbset.c | 2 +- util-linux/fdformat.c | 2 +- util-linux/fdisk.c | 2 +- util-linux/findfs.c | 2 +- util-linux/flock.c | 2 +- util-linux/freeramdisk.c | 4 ++-- util-linux/fsfreeze.c | 2 +- util-linux/fstrim.c | 2 +- util-linux/getopt.c | 2 +- util-linux/hexdump.c | 4 ++-- util-linux/hexdump_xxd.c | 2 +- util-linux/hwclock.c | 2 +- util-linux/ionice.c | 2 +- util-linux/ipcrm.c | 2 +- util-linux/ipcs.c | 2 +- util-linux/last.c | 2 +- util-linux/losetup.c | 2 +- util-linux/lspci.c | 2 +- util-linux/lsusb.c | 2 +- util-linux/mdev.c | 2 +- util-linux/mesg.c | 2 +- util-linux/mkfs_vfat.c | 4 ++-- util-linux/mkswap.c | 2 +- util-linux/more.c | 2 +- util-linux/mount.c | 2 +- util-linux/mountpoint.c | 2 +- util-linux/nsenter.c | 2 +- util-linux/pivot_root.c | 2 +- util-linux/rdate.c | 2 +- util-linux/rdev.c | 2 +- util-linux/readprofile.c | 2 +- util-linux/renice.c | 2 +- util-linux/rev.c | 2 +- util-linux/rtcwake.c | 2 +- util-linux/script.c | 2 +- util-linux/scriptreplay.c | 2 +- util-linux/setarch.c | 6 +++--- util-linux/setpriv.c | 2 +- util-linux/setsid.c | 2 +- util-linux/switch_root.c | 2 +- util-linux/taskset.c | 2 +- util-linux/uevent.c | 2 +- util-linux/unshare.c | 2 +- util-linux/wall.c | 2 +- 265 files changed, 320 insertions(+), 320 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 0ac059c19..b7944a62a 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -415,7 +415,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //usage: "Decompress to stdout" //config:config BUNZIP2 -//config: bool "bunzip2 (8.7 kb)" +//config: bool "bunzip2 (9.1 kb)" //config: default y //config: select FEATURE_BZIP2_DECOMPRESS //config: help @@ -429,7 +429,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //config: should probably say N here. //config: //config:config BZCAT -//config: bool "bzcat (8.7 kb)" +//config: bool "bzcat (9 kb)" //config: default y //config: select FEATURE_BZIP2_DECOMPRESS //config: help @@ -485,7 +485,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //usage: "Decompress to stdout" //config:config UNLZMA -//config: bool "unlzma (7.5 kb)" +//config: bool "unlzma (7.8 kb)" //config: default y //config: help //config: unlzma is a compression utility using the Lempel-Ziv-Markov chain @@ -494,7 +494,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //config: compressors. //config: //config:config LZCAT -//config: bool "lzcat (7.5 kb)" +//config: bool "lzcat (7.8 kb)" //config: default y //config: help //config: Alias to "unlzma -c". diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index a5a80439d..dda931169 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c @@ -5,7 +5,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DPKG_DEB -//config: bool "dpkg-deb (30 kb)" +//config: bool "dpkg-deb (29 kb)" //config: default y //config: select FEATURE_SEAMLESS_GZ //config: help diff --git a/archival/lzop.c b/archival/lzop.c index 74df8ff03..bdcc6d548 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -25,7 +25,7 @@ "Minimalized" for busybox by Alain Knaff */ //config:config LZOP -//config: bool "lzop (12 kb)" +//config: bool "lzop (13 kb)" //config: default y //config: help //config: Lzop compression/decompresion. diff --git a/console-tools/chvt.c b/console-tools/chvt.c index 7c2814d1c..2444e1f9d 100644 --- a/console-tools/chvt.c +++ b/console-tools/chvt.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHVT -//config: bool "chvt (2 kb)" +//config: bool "chvt (2.2 kb)" //config: default y //config: help //config: This program is used to change to another terminal. diff --git a/console-tools/clear.c b/console-tools/clear.c index 09ef1ea68..e1bf2c313 100644 --- a/console-tools/clear.c +++ b/console-tools/clear.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CLEAR -//config: bool "clear (tiny)" +//config: bool "clear (371 bytes)" //config: default y //config: help //config: This program clears the terminal screen. diff --git a/console-tools/deallocvt.c b/console-tools/deallocvt.c index 6cd54653c..f03ad079b 100644 --- a/console-tools/deallocvt.c +++ b/console-tools/deallocvt.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DEALLOCVT -//config: bool "deallocvt (1.9 kb)" +//config: bool "deallocvt (2.2 kb)" //config: default y //config: help //config: This program deallocates unused virtual consoles. diff --git a/console-tools/dumpkmap.c b/console-tools/dumpkmap.c index 3d8de6bed..957d16529 100644 --- a/console-tools/dumpkmap.c +++ b/console-tools/dumpkmap.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DUMPKMAP -//config: bool "dumpkmap (1.6 kb)" +//config: bool "dumpkmap (1.9 kb)" //config: default y //config: help //config: This program dumps the kernel's keyboard translation table to diff --git a/console-tools/fgconsole.c b/console-tools/fgconsole.c index 9bfb68017..b6dbc472b 100644 --- a/console-tools/fgconsole.c +++ b/console-tools/fgconsole.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FGCONSOLE -//config: bool "fgconsole (1.5 kb)" +//config: bool "fgconsole (1.8 kb)" //config: default y //config: help //config: This program prints active (foreground) console number. diff --git a/console-tools/kbd_mode.c b/console-tools/kbd_mode.c index b0b963ee0..1ec25757d 100644 --- a/console-tools/kbd_mode.c +++ b/console-tools/kbd_mode.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config KBD_MODE -//config: bool "kbd_mode (4.1 kb)" +//config: bool "kbd_mode (4.3 kb)" //config: default y //config: help //config: This program reports and sets keyboard mode. diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c index 81a0e6aa8..cec5e19cd 100644 --- a/console-tools/loadfont.c +++ b/console-tools/loadfont.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LOADFONT -//config: bool "loadfont (5.2 kb)" +//config: bool "loadfont (5.4 kb)" //config: default y //config: help //config: This program loads a console font from standard input. diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c index c038e2d22..22e918dbf 100644 --- a/console-tools/loadkmap.c +++ b/console-tools/loadkmap.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOADKMAP -//config: bool "loadkmap (1.8 kb)" +//config: bool "loadkmap (2.1 kb)" //config: default y //config: help //config: This program loads a keyboard translation table from diff --git a/console-tools/openvt.c b/console-tools/openvt.c index db2f073b2..c35617eb8 100644 --- a/console-tools/openvt.c +++ b/console-tools/openvt.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config OPENVT -//config: bool "openvt (7.2 kb)" +//config: bool "openvt (7.4 kb)" //config: default y //config: help //config: This program is used to start a command on an unused diff --git a/console-tools/reset.c b/console-tools/reset.c index cc04e4fcc..655a5ef7a 100644 --- a/console-tools/reset.c +++ b/console-tools/reset.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RESET -//config: bool "reset (345 bytes)" +//config: bool "reset (676 bytes)" //config: default y //config: help //config: This program is used to reset the terminal screen, if it diff --git a/console-tools/resize.c b/console-tools/resize.c index 95e0c7bf9..6fa7ce9ea 100644 --- a/console-tools/resize.c +++ b/console-tools/resize.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RESIZE -//config: bool "resize (903 bytes)" +//config: bool "resize (1.2 kb)" //config: default y //config: help //config: This program is used to (re)set the width and height of your current diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c index 461a98c6a..4e625890a 100644 --- a/console-tools/setconsole.c +++ b/console-tools/setconsole.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETCONSOLE -//config: bool "setconsole (3.6 kb)" +//config: bool "setconsole (3.8 kb)" //config: default y //config: help //config: Redirect writes to /dev/console to another device, diff --git a/console-tools/setkeycodes.c b/console-tools/setkeycodes.c index 5de18b8ea..03accec2f 100644 --- a/console-tools/setkeycodes.c +++ b/console-tools/setkeycodes.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETKEYCODES -//config: bool "setkeycodes (2.1 kb)" +//config: bool "setkeycodes (2.4 kb)" //config: default y //config: help //config: This program loads entries into the kernel's scancode-to-keycode diff --git a/console-tools/setlogcons.c b/console-tools/setlogcons.c index e9c2f516e..a94c0035a 100644 --- a/console-tools/setlogcons.c +++ b/console-tools/setlogcons.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETLOGCONS -//config: bool "setlogcons (1.8 kb)" +//config: bool "setlogcons (2 kb)" //config: default y //config: help //config: This program redirects the output console of kernel messages. diff --git a/console-tools/showkey.c b/console-tools/showkey.c index 84eb38a0a..87532a8ac 100644 --- a/console-tools/showkey.c +++ b/console-tools/showkey.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SHOWKEY -//config: bool "showkey (4.7 kb)" +//config: bool "showkey (4.9 kb)" //config: default y //config: help //config: Shows keys pressed. diff --git a/coreutils/basename.c b/coreutils/basename.c index 0b721c03c..bf7bd62e0 100644 --- a/coreutils/basename.c +++ b/coreutils/basename.c @@ -14,7 +14,7 @@ * 3) Save some space by using strcmp(). Calling strncmp() here was silly. */ //config:config BASENAME -//config: bool "basename (438 bytes)" +//config: bool "basename (3.7 kb)" //config: default y //config: help //config: basename is used to strip the directory and suffix from filenames, diff --git a/coreutils/cat.c b/coreutils/cat.c index 4b3414941..558869b2a 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config CAT -//config: bool "cat (5.6 kb)" +//config: bool "cat (5.8 kb)" //config: default y //config: help //config: cat is used to concatenate files and print them to the standard diff --git a/coreutils/chroot.c b/coreutils/chroot.c index 78751df84..0b45aa80c 100644 --- a/coreutils/chroot.c +++ b/coreutils/chroot.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHROOT -//config: bool "chroot (3.7 kb)" +//config: bool "chroot (4 kb)" //config: default y //config: help //config: chroot is used to change the root directory and run a command. diff --git a/coreutils/cksum.c b/coreutils/cksum.c index 83b7e3238..badc63a6a 100644 --- a/coreutils/cksum.c +++ b/coreutils/cksum.c @@ -7,11 +7,11 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CKSUM -//config: bool "cksum (4.1 kb)" +//config: bool "cksum (4.3 kb)" //config: default y //config: //config:config CRC32 -//config: bool "crc32 (4.1 kb)" +//config: bool "crc32 (4.2 kb)" //config: default y // APPLET_NOEXEC:name main location suid_type help diff --git a/coreutils/comm.c b/coreutils/comm.c index c59fccdd1..6cbdceaa9 100644 --- a/coreutils/comm.c +++ b/coreutils/comm.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config COMM -//config: bool "comm (4.2 kb)" +//config: bool "comm (4.4 kb)" //config: default y //config: help //config: comm is used to compare two files line by line and return diff --git a/coreutils/cut.c b/coreutils/cut.c index 55bdd9386..25b16d1a8 100644 --- a/coreutils/cut.c +++ b/coreutils/cut.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CUT -//config: bool "cut (5.8 kb)" +//config: bool "cut (6.7 kb)" //config: default y //config: help //config: cut is used to print selected parts of lines from diff --git a/coreutils/date.c b/coreutils/date.c index abcc37c33..3a89b6caf 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -19,7 +19,7 @@ much as possible, missed out a lot of bounds checking */ //config:config DATE -//config: bool "date (7 kb)" +//config: bool "date (7.2 kb)" //config: default y //config: help //config: date is used to set the system date or display the diff --git a/coreutils/dd.c b/coreutils/dd.c index 3e034eb1e..c032ebe1b 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DD -//config: bool "dd (7.5 kb)" +//config: bool "dd (8.3 kb)" //config: default y //config: help //config: dd copies a file (from standard input to standard output, diff --git a/coreutils/df.c b/coreutils/df.c index 176aa079f..76e9cefbf 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -18,7 +18,7 @@ * Implement -P and -B; better coreutils compat; cleanup */ //config:config DF -//config: bool "df (6.8 kb)" +//config: bool "df (7.1 kb)" //config: default y //config: help //config: df reports the amount of disk space used and available diff --git a/coreutils/dirname.c b/coreutils/dirname.c index 5aad121b5..71e1e2b7b 100644 --- a/coreutils/dirname.c +++ b/coreutils/dirname.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DIRNAME -//config: bool "dirname (329 bytes)" +//config: bool "dirname (611 bytes)" //config: default y //config: help //config: dirname is used to strip a non-directory suffix from diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c index 4039ed38c..c227cd50c 100644 --- a/coreutils/dos2unix.c +++ b/coreutils/dos2unix.c @@ -12,14 +12,14 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DOS2UNIX -//config: bool "dos2unix (5.2 kb)" +//config: bool "dos2unix (5.5 kb)" //config: default y //config: help //config: dos2unix is used to convert a text file from DOS format to //config: UNIX format, and vice versa. //config: //config:config UNIX2DOS -//config: bool "unix2dos (5.2 kb)" +//config: bool "unix2dos (5.5 kb)" //config: default y //config: help //config: unix2dos is used to convert a text file from UNIX format to diff --git a/coreutils/du.c b/coreutils/du.c index 832dd7594..4652b6300 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -19,7 +19,7 @@ * 4) Fixed busybox bug #1284 involving long overflow with human_readable. */ //config:config DU -//config: bool "du (6.3 kb)" +//config: bool "du (6.5 kb)" //config: default y //config: help //config: du is used to report the amount of disk space used diff --git a/coreutils/echo.c b/coreutils/echo.c index 44b2eb5d0..2a48d4a90 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -19,7 +19,7 @@ * The previous version did not allow 4-digit octals. */ //config:config ECHO -//config: bool "echo (1.8 kb)" +//config: bool "echo (2 kb)" //config: default y //config: help //config: echo prints a specified string to stdout. diff --git a/coreutils/env.c b/coreutils/env.c index 6eafd06ef..e9d3e883e 100644 --- a/coreutils/env.c +++ b/coreutils/env.c @@ -24,7 +24,7 @@ * - use xfunc_error_retval */ //config:config ENV -//config: bool "env (4 kb)" +//config: bool "env (4.3 kb)" //config: default y //config: help //config: env is used to set an environment variable and run diff --git a/coreutils/expand.c b/coreutils/expand.c index c5e1de6f5..47693e144 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -21,13 +21,13 @@ * Caveat: this versions of expand and unexpand don't accept tab lists. */ //config:config EXPAND -//config: bool "expand (5.1 kb)" +//config: bool "expand (5.3 kb)" //config: default y //config: help //config: By default, convert all tabs to spaces. //config: //config:config UNEXPAND -//config: bool "unexpand (5.3 kb)" +//config: bool "unexpand (5.5 kb)" //config: default y //config: help //config: By default, convert only leading sequences of blanks to tabs. diff --git a/coreutils/expr.c b/coreutils/expr.c index 760b081f9..47ebe2fca 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c @@ -23,7 +23,7 @@ * provided they all associate ((x op x) op x). */ //config:config EXPR -//config: bool "expr (6.6 kb)" +//config: bool "expr (6.8 kb)" //config: default y //config: help //config: expr is used to calculate numbers and print the result diff --git a/coreutils/factor.c b/coreutils/factor.c index 46dd2a0d7..90e9ed761 100644 --- a/coreutils/factor.c +++ b/coreutils/factor.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FACTOR -//config: bool "factor (2.7 kb)" +//config: bool "factor (3.2 kb)" //config: default y //config: help //config: factor factorizes integers diff --git a/coreutils/false.c b/coreutils/false.c index e3903efd0..ee175a9a2 100644 --- a/coreutils/false.c +++ b/coreutils/false.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FALSE -//config: bool "false (tiny)" +//config: bool "false (314 bytes)" //config: default y //config: help //config: false returns an exit code of FALSE (1). diff --git a/coreutils/fold.c b/coreutils/fold.c index 98c3b1491..2839c8c68 100644 --- a/coreutils/fold.c +++ b/coreutils/fold.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FOLD -//config: bool "fold (4.6 kb)" +//config: bool "fold (4.8 kb)" //config: default y //config: help //config: Wrap text to fit a specific width. diff --git a/coreutils/head.c b/coreutils/head.c index c7537a20e..ec83a284a 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HEAD -//config: bool "head (3.8 kb)" +//config: bool "head (4 kb)" //config: default y //config: help //config: head is used to print the first specified number of lines diff --git a/coreutils/hostid.c b/coreutils/hostid.c index 038809452..0dd18ffd9 100644 --- a/coreutils/hostid.c +++ b/coreutils/hostid.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HOSTID -//config: bool "hostid (286 bytes)" +//config: bool "hostid (566 bytes)" //config: default y //config: help //config: hostid prints the numeric identifier (in hexadecimal) for diff --git a/coreutils/id.c b/coreutils/id.c index 18bda3c55..a4f178bda 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -13,13 +13,13 @@ * Added -G option Tito Ragusa (C) 2008 for SUSv3. */ //config:config ID -//config: bool "id (7 kb)" +//config: bool "id (7.1 kb)" //config: default y //config: help //config: id displays the current user and group ID names. //config: //config:config GROUPS -//config: bool "groups (6.7 kb)" +//config: bool "groups (6.8 kb)" //config: default y //config: help //config: Print the group names associated with current user id. diff --git a/coreutils/link.c b/coreutils/link.c index 23e0cfdd0..cb994da45 100644 --- a/coreutils/link.c +++ b/coreutils/link.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LINK -//config: bool "link (3.2 kb)" +//config: bool "link (3.5 kb)" //config: default y //config: help //config: link creates hard links between files. diff --git a/coreutils/ln.c b/coreutils/ln.c index 2dcf79c07..34eec398a 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LN -//config: bool "ln (4.9 kb)" +//config: bool "ln (5.1 kb)" //config: default y //config: help //config: ln is used to create hard or soft links between files. diff --git a/coreutils/logname.c b/coreutils/logname.c index 06bbe1b0e..17c073a53 100644 --- a/coreutils/logname.c +++ b/coreutils/logname.c @@ -16,7 +16,7 @@ * a diagnostic message and an error return. */ //config:config LOGNAME -//config: bool "logname (1.1 kb)" +//config: bool "logname (1.4 kb)" //config: default y //config: help //config: logname is used to print the current user's login name. diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index b4bdc262c..f6a21237d 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -6,31 +6,31 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MD5SUM -//config: bool "md5sum (6.5 kb)" +//config: bool "md5sum (6.7 kb)" //config: default y //config: help //config: Compute and check MD5 message digest //config: //config:config SHA1SUM -//config: bool "sha1sum (5.9 kb)" +//config: bool "sha1sum (6.7 kb)" //config: default y //config: help //config: Compute and check SHA1 message digest //config: //config:config SHA256SUM -//config: bool "sha256sum (7 kb)" +//config: bool "sha256sum (8.2 kb)" //config: default y //config: help //config: Compute and check SHA256 message digest //config: //config:config SHA512SUM -//config: bool "sha512sum (7.4 kb)" +//config: bool "sha512sum (7.3 kb)" //config: default y //config: help //config: Compute and check SHA512 message digest //config: //config:config SHA3SUM -//config: bool "sha3sum (6.1 kb)" +//config: bool "sha3sum (6.3 kb)" //config: default y //config: help //config: Compute and check SHA3 message digest diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index d5e0f512b..e074c3561 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -14,7 +14,7 @@ /* Nov 28, 2006 Yoshinori Sato : Add SELinux Support. */ //config:config MKDIR -//config: bool "mkdir (4.5 kb)" +//config: bool "mkdir (4.7 kb)" //config: default y //config: help //config: mkdir is used to create directories with the specified names. diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c index e9d420ed8..f48a8e5db 100644 --- a/coreutils/mkfifo.c +++ b/coreutils/mkfifo.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MKFIFO -//config: bool "mkfifo (3.8 kb)" +//config: bool "mkfifo (4 kb)" //config: default y //config: help //config: mkfifo is used to create FIFOs (named pipes). diff --git a/coreutils/mknod.c b/coreutils/mknod.c index b10fe4fc3..e390a7203 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MKNOD -//config: bool "mknod (4.5 kb)" +//config: bool "mknod (4.6 kb)" //config: default y //config: help //config: mknod is used to create FIFOs or block/character special diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c index 33e2720de..91b2be6d3 100644 --- a/coreutils/mktemp.c +++ b/coreutils/mktemp.c @@ -29,7 +29,7 @@ * -p; else /tmp [deprecated] */ //config:config MKTEMP -//config: bool "mktemp (4.2 kb)" +//config: bool "mktemp (4.5 kb)" //config: default y //config: help //config: mktemp is used to create unique temporary files diff --git a/coreutils/nice.c b/coreutils/nice.c index e70da5d2b..0648593ee 100644 --- a/coreutils/nice.c +++ b/coreutils/nice.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config NICE -//config: bool "nice (2.1 kb)" +//config: bool "nice (2.3 kb)" //config: default y //config: help //config: nice runs a program with modified scheduling priority. diff --git a/coreutils/nl.c b/coreutils/nl.c index d06673881..12120f7a0 100644 --- a/coreutils/nl.c +++ b/coreutils/nl.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config NL -//config: bool "nl (4.6 kb)" +//config: bool "nl (4.9 kb)" //config: default y //config: help //config: nl is used to number lines of files. diff --git a/coreutils/nohup.c b/coreutils/nohup.c index ae136e085..69d8daff9 100644 --- a/coreutils/nohup.c +++ b/coreutils/nohup.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config NOHUP -//config: bool "nohup (2 kb)" +//config: bool "nohup (2.2 kb)" //config: default y //config: help //config: run a command immune to hangups, with output to a non-tty. diff --git a/coreutils/nproc.c b/coreutils/nproc.c index bb9bc56c5..f1d11fa5a 100644 --- a/coreutils/nproc.c +++ b/coreutils/nproc.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see LICENSE in this source tree */ //config:config NPROC -//config: bool "nproc (3.7 kb)" +//config: bool "nproc (3.9 kb)" //config: default y //config: help //config: Print number of CPUs diff --git a/coreutils/paste.c b/coreutils/paste.c index 7def4de11..3e5f20158 100644 --- a/coreutils/paste.c +++ b/coreutils/paste.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PASTE -//config: bool "paste (4.9 kb)" +//config: bool "paste (5.1 kb)" //config: default y //config: help //config: paste is used to paste lines of different files together diff --git a/coreutils/printenv.c b/coreutils/printenv.c index 5e195deaa..0ca9e6114 100644 --- a/coreutils/printenv.c +++ b/coreutils/printenv.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PRINTENV -//config: bool "printenv (1.3 kb)" +//config: bool "printenv (1.6 kb)" //config: default y //config: help //config: printenv is used to print all or part of environment. diff --git a/coreutils/printf.c b/coreutils/printf.c index b89df67f9..7763d7c46 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -38,7 +38,7 @@ /* 19990508 Busy Boxed! Dave Cinege */ //config:config PRINTF -//config: bool "printf (3.8 kb)" +//config: bool "printf (4.1 kb)" //config: default y //config: help //config: printf is used to format and print specified strings. diff --git a/coreutils/pwd.c b/coreutils/pwd.c index 4c42284f4..e62461719 100644 --- a/coreutils/pwd.c +++ b/coreutils/pwd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PWD -//config: bool "pwd (3.7 kb)" +//config: bool "pwd (4 kb)" //config: default y //config: help //config: pwd is used to print the current directory. diff --git a/coreutils/readlink.c b/coreutils/readlink.c index e17fc3b1e..9200f4ae0 100644 --- a/coreutils/readlink.c +++ b/coreutils/readlink.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config READLINK -//config: bool "readlink (4 kb)" +//config: bool "readlink (4.8 kb)" //config: default y //config: help //config: This program reads a symbolic link and returns the name diff --git a/coreutils/realpath.c b/coreutils/realpath.c index aeeef601c..22820a789 100644 --- a/coreutils/realpath.c +++ b/coreutils/realpath.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config REALPATH -//config: bool "realpath (1.6 kb)" +//config: bool "realpath (2.5 kb)" //config: default y //config: help //config: Return the canonicalized absolute pathname. diff --git a/coreutils/rm.c b/coreutils/rm.c index d000129d9..93e01a340 100644 --- a/coreutils/rm.c +++ b/coreutils/rm.c @@ -11,7 +11,7 @@ * Size reduction. */ //config:config RM -//config: bool "rm (5.4 kb)" +//config: bool "rm (5.5 kb)" //config: default y //config: help //config: rm is used to remove files or directories. diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index addf41188..96753e009 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RMDIR -//config: bool "rmdir (3.5 kb)" +//config: bool "rmdir (3.8 kb)" //config: default y //config: help //config: rmdir is used to remove empty directories. diff --git a/coreutils/seq.c b/coreutils/seq.c index 77a8aba8a..094f74e87 100644 --- a/coreutils/seq.c +++ b/coreutils/seq.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SEQ -//config: bool "seq (3.8 kb)" +//config: bool "seq (4 kb)" //config: default y //config: help //config: print a sequence of numbers diff --git a/coreutils/shred.c b/coreutils/shred.c index 04bf87229..7c0be612a 100644 --- a/coreutils/shred.c +++ b/coreutils/shred.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SHRED -//config: bool "shred (4.9 kb)" +//config: bool "shred (5.5 kb)" //config: default y //config: help //config: Overwrite a file to hide its contents, and optionally delete it diff --git a/coreutils/shuf.c b/coreutils/shuf.c index 466969745..0d23382a2 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SHUF -//config: bool "shuf (5.4 kb)" +//config: bool "shuf (6 kb)" //config: default y //config: help //config: Generate random permutations diff --git a/coreutils/sleep.c b/coreutils/sleep.c index a0cee5a4a..6edff59cc 100644 --- a/coreutils/sleep.c +++ b/coreutils/sleep.c @@ -13,7 +13,7 @@ * time suffixes for seconds, minutes, hours, and days. */ //config:config SLEEP -//config: bool "sleep (2 kb)" +//config: bool "sleep (2.4 kb)" //config: default y //config: help //config: sleep is used to pause for a specified number of seconds. diff --git a/coreutils/sort.c b/coreutils/sort.c index 01b7c44e5..2e952f81c 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -12,7 +12,7 @@ * http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html */ //config:config SORT -//config: bool "sort (7.7 kb)" +//config: bool "sort (8.1 kb)" //config: default y //config: help //config: sort is used to sort lines of text in specified files. diff --git a/coreutils/split.c b/coreutils/split.c index 3fcfd95f2..b6d1b9a7b 100644 --- a/coreutils/split.c +++ b/coreutils/split.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SPLIT -//config: bool "split (5 kb)" +//config: bool "split (5.2 kb)" //config: default y //config: help //config: Split a file into pieces. diff --git a/coreutils/stty.c b/coreutils/stty.c index ba2b78317..c88ef07f4 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c @@ -10,7 +10,7 @@ * Special for busybox ported by Vladimir Oleynik 2001 */ //config:config STTY -//config: bool "stty (8.9 kb)" +//config: bool "stty (9.2 kb)" //config: default y //config: help //config: stty is used to change and print terminal line settings. diff --git a/coreutils/sum.c b/coreutils/sum.c index 16ec44540..78e69acc6 100644 --- a/coreutils/sum.c +++ b/coreutils/sum.c @@ -13,7 +13,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SUM -//config: bool "sum (4 kb)" +//config: bool "sum (4.2 kb)" //config: default y //config: help //config: checksum and count the blocks in a file diff --git a/coreutils/sync.c b/coreutils/sync.c index ea328a54c..b6a4a4b70 100644 --- a/coreutils/sync.c +++ b/coreutils/sync.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SYNC -//config: bool "sync (3.8 kb)" +//config: bool "sync (4 kb)" //config: default y //config: help //config: sync is used to flush filesystem buffers. @@ -113,7 +113,7 @@ int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FSYNC -//config: bool "fsync (3.6 kb)" +//config: bool "fsync (3.8 kb)" //config: default y //config: help //config: fsync is used to flush file-related cached blocks to disk. diff --git a/coreutils/tac.c b/coreutils/tac.c index 25e85f6f3..6d3ea9c19 100644 --- a/coreutils/tac.c +++ b/coreutils/tac.c @@ -13,7 +13,7 @@ * http://www.uclibc.org/lists/busybox/2003-July/008813.html */ //config:config TAC -//config: bool "tac (3.9 kb)" +//config: bool "tac (4.1 kb)" //config: default y //config: help //config: tac is used to concatenate and print files in reverse. diff --git a/coreutils/tail.c b/coreutils/tail.c index 6201eb023..4680295b9 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -19,7 +19,7 @@ * 7) lseek attempted when count==0 even if arg was +0 (from top) */ //config:config TAIL -//config: bool "tail (6.8 kb)" +//config: bool "tail (7.2 kb)" //config: default y //config: help //config: tail is used to print the last specified number of lines diff --git a/coreutils/tee.c b/coreutils/tee.c index e67296d43..603fd3ad4 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TEE -//config: bool "tee (4.2 kb)" +//config: bool "tee (4.4 kb)" //config: default y //config: help //config: tee is used to read from standard input and write diff --git a/coreutils/test.c b/coreutils/test.c index 1d1e6d18b..008d90b25 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -20,7 +20,7 @@ * "This program is in the Public Domain." */ //config:config TEST -//config: bool "test (4.1 kb)" +//config: bool "test (4.4 kb)" //config: default y //config: help //config: test is used to check file types and compare values, diff --git a/coreutils/timeout.c b/coreutils/timeout.c index 06108f315..18aa9ebeb 100644 --- a/coreutils/timeout.c +++ b/coreutils/timeout.c @@ -28,7 +28,7 @@ * rewrite 14-11-2008 vda */ //config:config TIMEOUT -//config: bool "timeout (6 kb)" +//config: bool "timeout (6.5 kb)" //config: default y //config: help //config: Runs a program and watches it. If it does not terminate in diff --git a/coreutils/touch.c b/coreutils/touch.c index 7e13a27be..8fde70e12 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c @@ -13,7 +13,7 @@ * Also, exiting on a failure was a bug. All args should be processed. */ //config:config TOUCH -//config: bool "touch (5.9 kb)" +//config: bool "touch (6.1 kb)" //config: default y //config: help //config: touch is used to create or change the access and/or diff --git a/coreutils/tr.c b/coreutils/tr.c index 7fe7f89d5..8d779d8ea 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c @@ -19,7 +19,7 @@ * TODO: graph, print */ //config:config TR -//config: bool "tr (5.1 kb)" +//config: bool "tr (5.3 kb)" //config: default y //config: help //config: tr is used to squeeze, and/or delete characters from standard diff --git a/coreutils/true.c b/coreutils/true.c index 400388c34..02e533a0a 100644 --- a/coreutils/true.c +++ b/coreutils/true.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TRUE -//config: bool "true (tiny)" +//config: bool "true (311 bytes)" //config: default y //config: help //config: true returns an exit code of TRUE (0). diff --git a/coreutils/truncate.c b/coreutils/truncate.c index e26c3e3e1..8826e6b4c 100644 --- a/coreutils/truncate.c +++ b/coreutils/truncate.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TRUNCATE -//config: bool "truncate (4.2 kb)" +//config: bool "truncate (4.4 kb)" //config: default y //config: help //config: truncate truncates files to a given size. If a file does diff --git a/coreutils/tsort.c b/coreutils/tsort.c index dedb65b15..a451ed2ff 100644 --- a/coreutils/tsort.c +++ b/coreutils/tsort.c @@ -5,7 +5,7 @@ * public domain -- David Leonard, 2022 */ //config:config TSORT -//config: bool "tsort (0.7 kb)" +//config: bool "tsort (2.6 kb)" //config: default y //config: help //config: tsort performs a topological sort. diff --git a/coreutils/tty.c b/coreutils/tty.c index e448c27ec..8f9a82b0e 100644 --- a/coreutils/tty.c +++ b/coreutils/tty.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TTY -//config: bool "tty (3.6 kb)" +//config: bool "tty (3.9 kb)" //config: default y //config: help //config: tty is used to print the name of the current terminal to diff --git a/coreutils/uname.c b/coreutils/uname.c index 6c0bdf096..e1e7a7660 100644 --- a/coreutils/uname.c +++ b/coreutils/uname.c @@ -44,7 +44,7 @@ * Fix handling of -a to not print "unknown", add -o and -i support. */ //config:config UNAME -//config: bool "uname (3.9 kb)" +//config: bool "uname (4.2 kb)" //config: default y //config: help //config: uname is used to print system information. @@ -59,7 +59,7 @@ //config: //can't use "ARCH" for this applet, all hell breaks loose in build system :) //config:config BB_ARCH -//config: bool "arch (1.1 kb)" +//config: bool "arch (1.4 kb)" //config: default y //config: help //config: Same as uname -m. diff --git a/coreutils/uniq.c b/coreutils/uniq.c index 06c57f750..2c112dadb 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config UNIQ -//config: bool "uniq (4.9 kb)" +//config: bool "uniq (5.1 kb)" //config: default y //config: help //config: uniq is used to remove duplicate lines from a sorted file. diff --git a/coreutils/unlink.c b/coreutils/unlink.c index 24be81da6..61b108a84 100644 --- a/coreutils/unlink.c +++ b/coreutils/unlink.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see LICENSE in this source tree */ //config:config UNLINK -//config: bool "unlink (3.2 kb)" +//config: bool "unlink (3.5 kb)" //config: default y //config: help //config: unlink deletes a file by calling unlink() diff --git a/coreutils/usleep.c b/coreutils/usleep.c index 51a015c44..bb619405b 100644 --- a/coreutils/usleep.c +++ b/coreutils/usleep.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config USLEEP -//config: bool "usleep (1.3 kb)" +//config: bool "usleep (1.6 kb)" //config: default y //config: help //config: usleep is used to pause for a specified number of microseconds. diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 63a8d4d48..59768f87e 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -11,7 +11,7 @@ * "end" line */ //config:config UUDECODE -//config: bool "uudecode (5.8 kb)" +//config: bool "uudecode (5.9 kb)" //config: default y //config: help //config: uudecode is used to decode a uuencoded file. @@ -178,13 +178,13 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) #endif //config:config BASE32 -//config: bool "base32 (4.9 kb)" +//config: bool "base32 (5.5 kb)" //config: default y //config: help //config: Base32 encode and decode //config:config BASE64 -//config: bool "base64 (4.9 kb)" +//config: bool "base64 (5.3 kb)" //config: default y //config: help //config: Base64 encode and decode diff --git a/coreutils/uuencode.c b/coreutils/uuencode.c index f096e3122..97ff39ee3 100644 --- a/coreutils/uuencode.c +++ b/coreutils/uuencode.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config UUENCODE -//config: bool "uuencode (4.4 kb)" +//config: bool "uuencode (4.7 kb)" //config: default y //config: help //config: uuencode is used to uuencode a file. diff --git a/coreutils/wc.c b/coreutils/wc.c index d5238d3fc..de75aba72 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -33,7 +33,7 @@ * for which 'wc -c' should output '0'. */ //config:config WC -//config: bool "wc (4.5 kb)" +//config: bool "wc (4.7 kb)" //config: default y //config: help //config: wc is used to print the number of bytes, words, and lines, diff --git a/coreutils/who.c b/coreutils/who.c index 3725d77f5..6f96f7243 100644 --- a/coreutils/who.c +++ b/coreutils/who.c @@ -15,7 +15,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WHO -//config: bool "who (3.9 kb)" +//config: bool "who (5.6 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help @@ -23,14 +23,14 @@ //config: // procps-ng has this variation of "who": //config:config W -//config: bool "w (3.8 kb)" +//config: bool "w (5.5 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help //config: Print users currently logged on. //config: //config:config USERS -//config: bool "users (3.4 kb)" +//config: bool "users (3.6 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help diff --git a/coreutils/whoami.c b/coreutils/whoami.c index 49b5dd368..7e94d51fb 100644 --- a/coreutils/whoami.c +++ b/coreutils/whoami.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WHOAMI -//config: bool "whoami (3.2 kb)" +//config: bool "whoami (3.5 kb)" //config: default y //config: help //config: whoami is used to print the username of the current diff --git a/coreutils/yes.c b/coreutils/yes.c index 161db82c0..e04ad3ac0 100644 --- a/coreutils/yes.c +++ b/coreutils/yes.c @@ -11,7 +11,7 @@ * Size reductions and removed redundant applet name prefix from error messages. */ //config:config YES -//config: bool "yes (1.2 kb)" +//config: bool "yes (1.5 kb)" //config: default y //config: help //config: yes is used to repeatedly output a specific string, or diff --git a/debianutils/pipe_progress.c b/debianutils/pipe_progress.c index ab7e2528f..acd7402d7 100644 --- a/debianutils/pipe_progress.c +++ b/debianutils/pipe_progress.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PIPE_PROGRESS -//config: bool "pipe_progress (275 bytes)" +//config: bool "pipe_progress (576 bytes)" //config: default y //config: help //config: Display a dot to indicate pipe activity. diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index f528c88ff..780df3e96 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c @@ -23,7 +23,7 @@ * broken compatibility because the BusyBox policy doesn't allow them. */ //config:config RUN_PARTS -//config: bool "run-parts (6.1 kb)" +//config: bool "run-parts (6.2 kb)" //config: default y //config: help //config: run-parts is a utility designed to run all the scripts in a directory. diff --git a/debianutils/which.c b/debianutils/which.c index 23692dc6f..1f547919f 100644 --- a/debianutils/which.c +++ b/debianutils/which.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WHICH -//config: bool "which (3.8 kb)" +//config: bool "which (4 kb)" //config: default y //config: help //config: which is used to find programs in your PATH and diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index f436cd91e..5dec3253b 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c @@ -10,7 +10,7 @@ * Public License */ //config:config CHATTR -//config: bool "chattr (3.8 kb)" +//config: bool "chattr (4.1 kb)" //config: default y //config: help //config: chattr changes the file attributes on a second extended file system. diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index 028f8a803..fd4ea737c 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -34,7 +34,7 @@ * It doesn't guess filesystem types from on-disk format. */ //config:config FSCK -//config: bool "fsck (7.4 kb)" +//config: bool "fsck (7.6 kb)" //config: default y //config: help //config: fsck is used to check and optionally repair one or more filesystems. diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index c9f353ce5..f678f72fb 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c @@ -10,7 +10,7 @@ * Public License */ //config:config LSATTR -//config: bool "lsattr (5.5 kb)" +//config: bool "lsattr (5.7 kb)" //config: default y //config: help //config: lsattr lists the file attributes on a second extended file system. diff --git a/editors/awk.c b/editors/awk.c index 171f0a7ea..efdff2778 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config AWK -//config: bool "awk (23 kb)" +//config: bool "awk (24 kb)" //config: default y //config: help //config: Awk is used as a pattern scanning and processing language. diff --git a/editors/cmp.c b/editors/cmp.c index b89e519ad..54f347508 100644 --- a/editors/cmp.c +++ b/editors/cmp.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CMP -//config: bool "cmp (4.9 kb)" +//config: bool "cmp (5.3 kb)" //config: default y //config: help //config: cmp is used to compare two files and returns the result diff --git a/editors/ed.c b/editors/ed.c index 4a84f7433..8ec23d07f 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -7,7 +7,7 @@ * The "ed" built-in command (much simplified) */ //config:config ED -//config: bool "ed (21 kb)" +//config: bool "ed (16 kb)" //config: default y //config: help //config: The original 1970's Unix text editor, from the days of teletypes. diff --git a/editors/patch.c b/editors/patch.c index f90d6854d..5a768b23f 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -21,7 +21,7 @@ * [file] which file to patch */ //config:config PATCH -//config: bool "patch (9.4 kb)" +//config: bool "patch (9.6 kb)" //config: default y //config: help //config: Apply a unified diff formatted patch. diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c index 5478ece7d..c0631d8cd 100644 --- a/editors/patch_toybox.c +++ b/editors/patch_toybox.c @@ -26,7 +26,7 @@ USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN)) config PATCH - bool "patch (9.4 kb)" + bool "patch (9.6 kb)" default y help usage: patch [-i file] [-p depth] [-Ru] diff --git a/editors/vi.c b/editors/vi.c index 2645afe87..3cc3d2a0b 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -18,7 +18,7 @@ // An "ex" line oriented mode- maybe using "cmdedit" //config:config VI -//config: bool "vi (23 kb)" +//config: bool "vi (26 kb)" //config: default y //config: help //config: 'vi' is a text editor. More specifically, it is the One True diff --git a/findutils/find.c b/findutils/find.c index 136ca0d21..31c996988 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -51,7 +51,7 @@ * diff -u /tmp/std_find /tmp/bb_find && echo Identical */ //config:config FIND -//config: bool "find (14 kb)" +//config: bool "find (16 kb)" //config: default y //config: help //config: find is used to search your system to find specified files. diff --git a/findutils/grep.c b/findutils/grep.c index 0b72812f1..f6d0a73f4 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -18,19 +18,19 @@ * (C) 2006 Jac Goudsmit added -o option */ //config:config GREP -//config: bool "grep (8.6 kb)" +//config: bool "grep (8.9 kb)" //config: default y //config: help //config: grep is used to search files for a specified pattern. //config: //config:config EGREP -//config: bool "egrep (7.8 kb)" +//config: bool "egrep (8 kb)" //config: default y //config: help //config: Alias to "grep -E". //config: //config:config FGREP -//config: bool "fgrep (7.8 kb)" +//config: bool "fgrep (8 kb)" //config: default y //config: help //config: Alias to "grep -F". diff --git a/findutils/xargs.c b/findutils/xargs.c index c6000e066..890c37534 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -15,7 +15,7 @@ * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html */ //config:config XARGS -//config: bool "xargs (7.2 kb)" +//config: bool "xargs (7.6 kb)" //config: default y //config: help //config: xargs is used to execute a specified command for diff --git a/init/halt.c b/init/halt.c index fe3cb9e75..7aea8cfec 100644 --- a/init/halt.c +++ b/init/halt.c @@ -7,19 +7,19 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config HALT -//config: bool "halt (4 kb)" +//config: bool "halt (4.3 kb)" //config: default y //config: help //config: Stop all processes and halt the system. //config: //config:config POWEROFF -//config: bool "poweroff (4 kb)" +//config: bool "poweroff (4.3 kb)" //config: default y //config: help //config: Stop all processes and power off the system. //config: //config:config REBOOT -//config: bool "reboot (4 kb)" +//config: bool "reboot (4.3 kb)" //config: default y //config: help //config: Stop all processes and reboot the system. diff --git a/klibc-utils/resume.c b/klibc-utils/resume.c index 8c4ab26c4..7b9d18b5d 100644 --- a/klibc-utils/resume.c +++ b/klibc-utils/resume.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RESUME -//config: bool "resume (3.2 kb)" +//config: bool "resume (3.6 kb)" //config: default y //config: help //config: Resume from saved "suspend-to-disk" image diff --git a/klibc-utils/run-init.c b/klibc-utils/run-init.c index 73c677bab..5eadd9fc0 100644 --- a/klibc-utils/run-init.c +++ b/klibc-utils/run-init.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RUN_INIT -//config: bool "run-init (7.7 kb)" +//config: bool "run-init (8 kb)" //config: default y //config: help //config: The run-init utility is used from initramfs to select a new diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c index b09555aae..2470050e7 100644 --- a/loginutils/add-remove-shell.c +++ b/loginutils/add-remove-shell.c @@ -8,13 +8,13 @@ * for details. */ //config:config ADD_SHELL -//config: bool "add-shell (3.1 kb)" +//config: bool "add-shell (3.3 kb)" //config: default y if DESKTOP //config: help //config: Add shells to /etc/shells. //config: //config:config REMOVE_SHELL -//config: bool "remove-shell (3 kb)" +//config: bool "remove-shell (3.3 kb)" //config: default y if DESKTOP //config: help //config: Remove shells from /etc/shells. diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 71d3a8db9..2b5ac7550 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config ADDGROUP -//config: bool "addgroup (8.6 kb)" +//config: bool "addgroup (8.8 kb)" //config: default y //config: select LONG_OPTS //config: help diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c index a032abbed..65530b614 100644 --- a/loginutils/chpasswd.c +++ b/loginutils/chpasswd.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHPASSWD -//config: bool "chpasswd (18 kb)" +//config: bool "chpasswd (19 kb)" //config: default y //config: help //config: Reads a file of user name and password pairs from standard input diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index 2109e2eb5..1c338540f 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -10,14 +10,14 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config CRYPTPW -//config: bool "cryptpw (14 kb)" +//config: bool "cryptpw (15 kb)" //config: default y //config: help //config: Encrypts the given password with the crypt(3) libc function //config: using the given salt. //config: //config:config MKPASSWD -//config: bool "mkpasswd (15 kb)" +//config: bool "mkpasswd (16 kb)" //config: default y //config: help //config: Encrypts the given password with the crypt(3) libc function diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 8e7df737c..a82ffc317 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -9,13 +9,13 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config DELUSER -//config: bool "deluser (9.1 kb)" +//config: bool "deluser (9.3 kb)" //config: default y //config: help //config: Utility for deleting a user account. //config: //config:config DELGROUP -//config: bool "delgroup (6.4 kb)" +//config: bool "delgroup (6.6 kb)" //config: default y //config: help //config: Utility for deleting a group account. diff --git a/loginutils/getty.c b/loginutils/getty.c index cd6378d80..4581cc9f7 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -22,7 +22,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config GETTY -//config: bool "getty (10 kb)" +//config: bool "getty (11 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/loginutils/login.c b/loginutils/login.c index b02be2176..301be4a34 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -3,7 +3,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOGIN -//config: bool "login (24 kb)" +//config: bool "login (25 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/loginutils/passwd.c b/loginutils/passwd.c index acc942275..1e8449627 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -3,7 +3,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PASSWD -//config: bool "passwd (21 kb)" +//config: bool "passwd (22 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c index 681022acb..9c927ed79 100644 --- a/loginutils/sulogin.c +++ b/loginutils/sulogin.c @@ -5,7 +5,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SULOGIN -//config: bool "sulogin (17 kb)" +//config: bool "sulogin (18 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 720835c4b..11bf58ca0 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c @@ -16,7 +16,7 @@ * It now works with md5, sha1, etc passwords. */ //config:config VLOCK -//config: bool "vlock (17 kb)" +//config: bool "vlock (18 kb)" //config: default y //config: help //config: Build the "vlock" applet which allows you to lock (virtual) terminals. diff --git a/mailutils/makemime.c b/mailutils/makemime.c index 1ff2012d5..f4c1b2bd8 100644 --- a/mailutils/makemime.c +++ b/mailutils/makemime.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MAKEMIME -//config: bool "makemime (5.4 kb)" +//config: bool "makemime (5.6 kb)" //config: default y //config: help //config: Create MIME-formatted messages. diff --git a/mailutils/popmaildir.c b/mailutils/popmaildir.c index 1f2db2892..52d5d342e 100644 --- a/mailutils/popmaildir.c +++ b/mailutils/popmaildir.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config POPMAILDIR -//config: bool "popmaildir (10 kb)" +//config: bool "popmaildir (11 kb)" //config: default y //config: help //config: Simple yet powerful POP3 mail popper. Delivers content diff --git a/mailutils/reformime.c b/mailutils/reformime.c index a1d3f4e8b..850dfb9cc 100644 --- a/mailutils/reformime.c +++ b/mailutils/reformime.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config REFORMIME -//config: bool "reformime (7.5 kb)" +//config: bool "reformime (7.6 kb)" //config: default y //config: help //config: Parse MIME-formatted messages. diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c index 209d1d560..fb478c0c9 100644 --- a/miscutils/adjtimex.c +++ b/miscutils/adjtimex.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config ADJTIMEX -//config: bool "adjtimex (4.7 kb)" +//config: bool "adjtimex (4.9 kb)" //config: default y //config: help //config: Adjtimex reads and optionally sets adjustment parameters for diff --git a/miscutils/ascii.c b/miscutils/ascii.c index 98c11fa51..7bcb950fd 100644 --- a/miscutils/ascii.c +++ b/miscutils/ascii.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config ASCII -//config: bool "ascii" +//config: bool "ascii (784 bytes)" //config: default y //config: help //config: Print ascii table. diff --git a/miscutils/bc.c b/miscutils/bc.c index c629c4763..28bc40c8b 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c @@ -14,7 +14,7 @@ #define SANITY_CHECKS 1 //config:config BC -//config: bool "bc (45 kb)" +//config: bool "bc (38 kb)" //config: default y //config: select FEATURE_DC_BIG //config: help @@ -38,7 +38,7 @@ //config: 5) "read()" accepts expressions, not only numeric literals. //config: //config:config DC -//config: bool "dc (36 kb)" +//config: bool "dc (29 kb)" //config: default y //config: help //config: dc is a reverse-polish notation command-line calculator which diff --git a/miscutils/beep.c b/miscutils/beep.c index 7c60aed08..724a666c8 100644 --- a/miscutils/beep.c +++ b/miscutils/beep.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config BEEP -//config: bool "beep (2.4 kb)" +//config: bool "beep (2.7 kb)" //config: default y //config: help //config: The beep applets beeps in a given freq/Hz. diff --git a/miscutils/chat.c b/miscutils/chat.c index 83aac37de..7daf7a6f6 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config CHAT -//config: bool "chat (6.3 kb)" +//config: bool "chat (6.7 kb)" //config: default y //config: help //config: Simple chat utility. diff --git a/miscutils/crond.c b/miscutils/crond.c index bd43c6b68..3bbb5ac83 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CROND -//config: bool "crond (14 kb)" +//config: bool "crond (15 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/miscutils/devmem.c b/miscutils/devmem.c index f21621bd6..015b18f71 100644 --- a/miscutils/devmem.c +++ b/miscutils/devmem.c @@ -4,7 +4,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config DEVMEM -//config: bool "devmem (2.5 kb)" +//config: bool "devmem (2.7 kb)" //config: default y //config: help //config: devmem is a small program that reads and writes from physical diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c index 15ad78377..41f26b938 100644 --- a/miscutils/hexedit.c +++ b/miscutils/hexedit.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config HEXEDIT -//config: bool "hexedit (21 kb)" +//config: bool "hexedit (15 kb)" //config: default y //config: help //config: Edit file in hexadecimal. diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index da26f5e19..a70573ebe 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -9,31 +9,31 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config I2CGET -//config: bool "i2cget (5.5 kb)" +//config: bool "i2cget (5.7 kb)" //config: default y //config: help //config: Read from I2C/SMBus chip registers. //config: //config:config I2CSET -//config: bool "i2cset (6.7 kb)" +//config: bool "i2cset (6.9 kb)" //config: default y //config: help //config: Set I2C registers. //config: //config:config I2CDUMP -//config: bool "i2cdump (7.1 kb)" +//config: bool "i2cdump (7.2 kb)" //config: default y //config: help //config: Examine I2C registers. //config: //config:config I2CDETECT -//config: bool "i2cdetect (7.1 kb)" +//config: bool "i2cdetect (7.3 kb)" //config: default y //config: help //config: Detect I2C chips. //config: //config:config I2CTRANSFER -//config: bool "i2ctransfer (4.0 kb)" +//config: bool "i2ctransfer (5.5 kb)" //config: default y //config: help //config: Send user-defined I2C messages in one transfer. diff --git a/miscutils/lsscsi.c b/miscutils/lsscsi.c index 8f7eda761..9f677ba28 100644 --- a/miscutils/lsscsi.c +++ b/miscutils/lsscsi.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSSCSI -//config: bool "lsscsi (2.5 kb)" +//config: bool "lsscsi (2.9 kb)" //config: default y //config: help //config: lsscsi is a utility for displaying information about SCSI buses in the diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c index 93c550042..48be91875 100644 --- a/miscutils/makedevs.c +++ b/miscutils/makedevs.c @@ -7,7 +7,7 @@ * known bugs: can't deal with alpha ranges */ //config:config MAKEDEVS -//config: bool "makedevs (9.2 kb)" +//config: bool "makedevs (9.4 kb)" //config: default y //config: help //config: 'makedevs' is a utility used to create a batch of devices with diff --git a/miscutils/microcom.c b/miscutils/microcom.c index 97b46342f..99db207bf 100644 --- a/miscutils/microcom.c +++ b/miscutils/microcom.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MICROCOM -//config: bool "microcom (5.7 kb)" +//config: bool "microcom (5.9 kb)" //config: default y //config: help //config: The poor man's minicom utility for chatting with serial port devices. diff --git a/miscutils/mt.c b/miscutils/mt.c index 52d5476a1..c781ef545 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c @@ -3,7 +3,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MT -//config: bool "mt (2.5 kb)" +//config: bool "mt (2.7 kb)" //config: default y //config: help //config: mt is used to control tape devices. You can use the mt utility diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index 52bf49434..6ac92aa1f 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -8,13 +8,13 @@ * TODO: add support for large (>4GB) MTD devices */ //config:config NANDWRITE -//config: bool "nandwrite (4.8 kb)" +//config: bool "nandwrite (5 kb)" //config: default y //config: help //config: Write to the specified MTD device, with bad blocks awareness //config: //config:config NANDDUMP -//config: bool "nanddump (5.2 kb)" +//config: bool "nanddump (5.4 kb)" //config: default y //config: help //config: Dump the content of raw NAND chip diff --git a/miscutils/partprobe.c b/miscutils/partprobe.c index 0fb1927b7..b21c6241b 100644 --- a/miscutils/partprobe.c +++ b/miscutils/partprobe.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PARTPROBE -//config: bool "partprobe (3.5 kb)" +//config: bool "partprobe (3.7 kb)" //config: default y //config: help //config: Ask kernel to rescan partition table. diff --git a/miscutils/raidautorun.c b/miscutils/raidautorun.c index 905862cf7..8e70b5a51 100644 --- a/miscutils/raidautorun.c +++ b/miscutils/raidautorun.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RAIDAUTORUN -//config: bool "raidautorun (1.3 kb)" +//config: bool "raidautorun (1.6 kb)" //config: default y //config: help //config: raidautorun tells the kernel md driver to diff --git a/miscutils/readahead.c b/miscutils/readahead.c index d2bed2092..a9e672617 100644 --- a/miscutils/readahead.c +++ b/miscutils/readahead.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config READAHEAD -//config: bool "readahead (1.5 kb)" +//config: bool "readahead (1.7 kb)" //config: default y //config: depends on LFS //config: help diff --git a/miscutils/runlevel.c b/miscutils/runlevel.c index 2f1581ead..7b96a5472 100644 --- a/miscutils/runlevel.c +++ b/miscutils/runlevel.c @@ -12,7 +12,7 @@ * initially busyboxified by Bernhard Reutner-Fischer */ //config:config RUNLEVEL -//config: bool "runlevel (559 bytes)" +//config: bool "runlevel (837 bytes)" //config: default y //config: depends on FEATURE_UTMP //config: help diff --git a/miscutils/rx.c b/miscutils/rx.c index d8b041480..3052bdef7 100644 --- a/miscutils/rx.c +++ b/miscutils/rx.c @@ -15,7 +15,7 @@ * This was originally written for blob and then adapted for busybox. */ //config:config RX -//config: bool "rx (2.9 kb)" +//config: bool "rx (3.2 kb)" //config: default y //config: help //config: Receive files using the Xmodem protocol. diff --git a/miscutils/seedrng.c b/miscutils/seedrng.c index 3bf6e2ea7..7a2331cb1 100644 --- a/miscutils/seedrng.c +++ b/miscutils/seedrng.c @@ -20,7 +20,7 @@ * This is based on code from . */ //config:config SEEDRNG -//config: bool "seedrng (1.3 kb)" +//config: bool "seedrng (9.1 kb)" //config: default y //config: help //config: Seed the kernel RNG from seed files, meant to be called diff --git a/miscutils/setfattr.c b/miscutils/setfattr.c index 9792c2660..10d1840c9 100644 --- a/miscutils/setfattr.c +++ b/miscutils/setfattr.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SETFATTR -//config: bool "setfattr (3.7 kb)" +//config: bool "setfattr (3.9 kb)" //config: default y //config: help //config: Set/delete extended attributes on files diff --git a/miscutils/setserial.c b/miscutils/setserial.c index 175c788fc..5fb93d226 100644 --- a/miscutils/setserial.c +++ b/miscutils/setserial.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETSERIAL -//config: bool "setserial (6.9 kb)" +//config: bool "setserial (7.1 kb)" //config: default y //config: help //config: Retrieve or set Linux serial port. diff --git a/miscutils/strings.c b/miscutils/strings.c index b01884968..036df5c5d 100644 --- a/miscutils/strings.c +++ b/miscutils/strings.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config STRINGS -//config: bool "strings (4.6 kb)" +//config: bool "strings (4.8 kb)" //config: default y //config: help //config: strings prints the printable character sequences for each file diff --git a/miscutils/time.c b/miscutils/time.c index c4bcbcbc9..5a8fa4c0b 100644 --- a/miscutils/time.c +++ b/miscutils/time.c @@ -10,7 +10,7 @@ * Heavily modified for busybox by Erik Andersen */ //config:config TIME -//config: bool "time (6.8 kb)" +//config: bool "time (8.1 kb)" //config: default y //config: help //config: The time command runs the specified program with the given arguments. diff --git a/miscutils/tree.c b/miscutils/tree.c index fa55696c6..0b142c85c 100644 --- a/miscutils/tree.c +++ b/miscutils/tree.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TREE -//config: bool "tree (0.6 kb)" +//config: bool "tree (2.5 kb)" //config: default y //config: help //config: List files and directories in a tree structure. diff --git a/miscutils/ts.c b/miscutils/ts.c index c7e477cc5..c5c1879df 100644 --- a/miscutils/ts.c +++ b/miscutils/ts.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TS -//config: bool "ts (450 bytes)" +//config: bool "ts (4.4 kb)" //config: default y //applet:IF_TS(APPLET(ts, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/miscutils/ttysize.c b/miscutils/ttysize.c index d635b29ce..e95936637 100644 --- a/miscutils/ttysize.c +++ b/miscutils/ttysize.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TTYSIZE -//config: bool "ttysize (432 bytes)" +//config: bool "ttysize (718 bytes)" //config: default y //config: help //config: A replacement for "stty size". Unlike stty, can report only width, diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index 6d49f61d9..8de444eb2 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c @@ -4,37 +4,37 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UBIATTACH -//config: bool "ubiattach (4.2 kb)" +//config: bool "ubiattach (4.5 kb)" //config: default y //config: help //config: Attach MTD device to an UBI device. //config: //config:config UBIDETACH -//config: bool "ubidetach (4.1 kb)" +//config: bool "ubidetach (4.3 kb)" //config: default y //config: help //config: Detach MTD device from an UBI device. //config: //config:config UBIMKVOL -//config: bool "ubimkvol (5.3 kb)" +//config: bool "ubimkvol (5.5 kb)" //config: default y //config: help //config: Create a UBI volume. //config: //config:config UBIRMVOL -//config: bool "ubirmvol (4.9 kb)" +//config: bool "ubirmvol (5.1 kb)" //config: default y //config: help //config: Delete a UBI volume. //config: //config:config UBIRSVOL -//config: bool "ubirsvol (4.2 kb)" +//config: bool "ubirsvol (4.4 kb)" //config: default y //config: help //config: Resize a UBI volume. //config: //config:config UBIUPDATEVOL -//config: bool "ubiupdatevol (5.2 kb)" +//config: bool "ubiupdatevol (5.6 kb)" //config: default y //config: help //config: Update a UBI volume. diff --git a/miscutils/ubirename.c b/miscutils/ubirename.c index 06a0adacf..af94354f3 100644 --- a/miscutils/ubirename.c +++ b/miscutils/ubirename.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UBIRENAME -//config: bool "ubirename (2.4 kb)" +//config: bool "ubirename (2.7 kb)" //config: default y //config: help //config: Utility to rename UBI volumes diff --git a/miscutils/volname.c b/miscutils/volname.c index 027d01272..fbf87322d 100644 --- a/miscutils/volname.c +++ b/miscutils/volname.c @@ -28,7 +28,7 @@ * Matthew Stoltenberg */ //config:config VOLNAME -//config: bool "volname (1.6 kb)" +//config: bool "volname (1.9 kb)" //config: default y //config: help //config: Prints a CD-ROM volume name. diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 9f5a4b849..db1d27b48 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WATCHDOG -//config: bool "watchdog (5.3 kb)" +//config: bool "watchdog (5.7 kb)" //config: default y //config: help //config: The watchdog utility is used with hardware or software watchdog diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 2beb12362..d9df5ad81 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSMOD -//config: bool "lsmod (1.9 kb)" +//config: bool "lsmod (2.1 kb)" //config: default y //config: help //config: lsmod is used to display a list of loaded modules. diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 235706fd5..543f53e99 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MODPROBE -//config: bool "modprobe (28 kb)" +//config: bool "modprobe (27 kb)" //config: default y //config: help //config: Handle the loading of modules, and their dependencies on a high diff --git a/modutils/rmmod.c b/modutils/rmmod.c index 2b3c39153..fe86a6766 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RMMOD -//config: bool "rmmod (3.3 kb)" +//config: bool "rmmod (3.5 kb)" //config: default y //config: help //config: rmmod is used to unload specified modules from the kernel. diff --git a/networking/arping.c b/networking/arping.c index 86f0221ed..967f1ac04 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -6,7 +6,7 @@ * Busybox port: Nick Fedchik */ //config:config ARPING -//config: bool "arping (9 kb)" +//config: bool "arping (9.1 kb)" //config: default y //config: help //config: Ping hosts by ARP packets. diff --git a/networking/brctl.c b/networking/brctl.c index 956bd91f3..7b0270b51 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config BRCTL -//config: bool "brctl (4.7 kb)" +//config: bool "brctl (9.9 kb)" //config: default y //config: help //config: Manage ethernet bridges. diff --git a/networking/dnsd.c b/networking/dnsd.c index a0f320c6c..a11d83f49 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c @@ -17,7 +17,7 @@ * the first porting of oao' scdns to busybox also. */ //config:config DNSD -//config: bool "dnsd (9.8 kb)" +//config: bool "dnsd (10 kb)" //config: default y //config: help //config: Small and static DNS server daemon. diff --git a/networking/ether-wake.c b/networking/ether-wake.c index 36e90acfb..68df19361 100644 --- a/networking/ether-wake.c +++ b/networking/ether-wake.c @@ -64,7 +64,7 @@ * filter. That configuration consumes more power. */ //config:config ETHER_WAKE -//config: bool "ether-wake (4.9 kb)" +//config: bool "ether-wake (5.2 kb)" //config: default y //config: help //config: Send a magic packet to wake up sleeping machines. diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 4c92f34a1..1172850ce 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -13,13 +13,13 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FTPGET -//config: bool "ftpget (7.8 kb)" +//config: bool "ftpget (7.9 kb)" //config: default y //config: help //config: Retrieve a remote file via FTP. //config: //config:config FTPPUT -//config: bool "ftpput (7.5 kb)" +//config: bool "ftpput (7.6 kb)" //config: default y //config: help //config: Store a remote file via FTP. diff --git a/networking/hostname.c b/networking/hostname.c index 549103485..36cb70866 100644 --- a/networking/hostname.c +++ b/networking/hostname.c @@ -10,13 +10,13 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HOSTNAME -//config: bool "hostname (5.5 kb)" +//config: bool "hostname (5.8 kb)" //config: default y //config: help //config: Show or set the system's host name. //config: //config:config DNSDOMAINNAME -//config: bool "dnsdomainname (3.6 kb)" +//config: bool "dnsdomainname (3.8 kb)" //config: default y //config: help //config: Alias to "hostname -d". diff --git a/networking/ifplugd.c b/networking/ifplugd.c index 0b55bf4e5..a776d4121 100644 --- a/networking/ifplugd.c +++ b/networking/ifplugd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IFPLUGD -//config: bool "ifplugd (10 kb)" +//config: bool "ifplugd (11 kb)" //config: default y //config: help //config: Network interface plug detection daemon. diff --git a/networking/ip.c b/networking/ip.c index 7c3208699..36126b747 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -19,7 +19,7 @@ //config: trying to be portable, it's better to use "ip CMD" forms. //config: //config:config IPADDR -//config: bool "ipaddr (14 kb)" +//config: bool "ipaddr (15 kb)" //config: default y //config: select FEATURE_IP_ADDRESS //config: help @@ -40,7 +40,7 @@ //config: Short form of "ip route" //config: //config:config IPTUNNEL -//config: bool "iptunnel (9.6 kb)" +//config: bool "iptunnel (9.8 kb)" //config: default y //config: select FEATURE_IP_TUNNEL //config: help @@ -54,7 +54,7 @@ //config: Short form of "ip rule" //config: //config:config IPNEIGH -//config: bool "ipneigh (8.3 kb)" +//config: bool "ipneigh (8.6 kb)" //config: default y //config: select FEATURE_IP_NEIGH //config: help diff --git a/networking/ipcalc.c b/networking/ipcalc.c index e82e35dd5..92e7b289d 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c @@ -12,7 +12,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IPCALC -//config: bool "ipcalc (4.4 kb)" +//config: bool "ipcalc (4.6 kb)" //config: default y //config: help //config: ipcalc takes an IP address and netmask and calculates the diff --git a/networking/isrv_identd.c b/networking/isrv_identd.c index f564d604a..a92afc7e1 100644 --- a/networking/isrv_identd.c +++ b/networking/isrv_identd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FAKEIDENTD -//config: bool "fakeidentd (8.7 kb)" +//config: bool "fakeidentd (9 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/networking/nameif.c b/networking/nameif.c index 66e042688..461745c70 100644 --- a/networking/nameif.c +++ b/networking/nameif.c @@ -10,7 +10,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config NAMEIF -//config: bool "nameif (6.6 kb)" +//config: bool "nameif (6.9 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/networking/nbd-client.c b/networking/nbd-client.c index 755b42ccd..556fa8c97 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config NBDCLIENT -//config: bool "nbd-client (6 kb)" +//config: bool "nbd-client (6.3 kb)" //config: default y //config: help //config: Network block device client diff --git a/networking/nslookup.c b/networking/nslookup.c index 249083e24..b67d354f7 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -1,7 +1,7 @@ /* vi: set sw=4 ts=4: */ //config:config NSLOOKUP -//config: bool "nslookup (9.7 kb)" +//config: bool "nslookup (10 kb)" //config: default y //config: help //config: nslookup is a tool to query Internet name servers. diff --git a/networking/ntpd.c b/networking/ntpd.c index c7519b8fb..93bd3189d 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -41,7 +41,7 @@ *********************************************************************** */ //config:config NTPD -//config: bool "ntpd (22 kb)" +//config: bool "ntpd (23 kb)" //config: default y //config: help //config: The NTP client/server daemon. diff --git a/networking/pscan.c b/networking/pscan.c index 816178bbc..13785deca 100644 --- a/networking/pscan.c +++ b/networking/pscan.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PSCAN -//config: bool "pscan (6 kb)" +//config: bool "pscan (6.2 kb)" //config: default y //config: help //config: Simple network port scanner. diff --git a/networking/route.c b/networking/route.c index 26146f8e9..6e2d30cfd 100644 --- a/networking/route.c +++ b/networking/route.c @@ -25,7 +25,7 @@ * remove ridiculous amounts of bloat. */ //config:config ROUTE -//config: bool "route (8.7 kb)" +//config: bool "route (9 kb)" //config: default y //config: help //config: Route displays or manipulates the kernel's IP routing tables. diff --git a/networking/slattach.c b/networking/slattach.c index 16b4c9158..2f5cd15ab 100644 --- a/networking/slattach.c +++ b/networking/slattach.c @@ -13,7 +13,7 @@ * - The -F options allows disabling of RTS/CTS flow control. */ //config:config SLATTACH -//config: bool "slattach (6.2 kb)" +//config: bool "slattach (6.3 kb)" //config: default y //config: help //config: slattach configures serial line as SLIP network interface. diff --git a/networking/ssl_client.c b/networking/ssl_client.c index 397aad297..582fb0e71 100644 --- a/networking/ssl_client.c +++ b/networking/ssl_client.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SSL_CLIENT -//config: bool "ssl_client (25 kb)" +//config: bool "ssl_client (28 kb)" //config: default y //config: select TLS //config: help diff --git a/networking/telnetd.c b/networking/telnetd.c index fb90e7f11..bfeea1400 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -21,7 +21,7 @@ * Set process group corrections, initial busybox port */ //config:config TELNETD -//config: bool "telnetd (12 kb)" +//config: bool "telnetd (13 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/networking/traceroute.c b/networking/traceroute.c index 4bbe1ab8e..767f537ce 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -216,7 +216,7 @@ //config: Utility to trace the route of IP packets. //config: //config:config TRACEROUTE6 -//config: bool "traceroute6 (13 kb)" +//config: bool "traceroute6 (12 kb)" //config: default y //config: depends on FEATURE_IPV6 //config: help diff --git a/networking/tunctl.c b/networking/tunctl.c index 28571ae7f..c17302eac 100644 --- a/networking/tunctl.c +++ b/networking/tunctl.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TUNCTL -//config: bool "tunctl (6.2 kb)" +//config: bool "tunctl (6.4 kb)" //config: default y //config: help //config: tunctl creates or deletes tun devices. diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index d9c501c18..4b9259eb8 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -50,7 +50,7 @@ config DHCPD_LEASES_FILE of the file. Normally it is safe to leave it untouched. config DUMPLEASES - bool "dumpleases (5.1 kb)" + bool "dumpleases (5.3 kb)" default y help dumpleases displays the leases written out by the udhcpd. @@ -58,7 +58,7 @@ config DUMPLEASES by the absolute time that it expires in seconds from epoch. config DHCPRELAY - bool "dhcprelay (5.2 kb)" + bool "dhcprelay (5.5 kb)" default y help dhcprelay listens for DHCP requests on one or more interfaces diff --git a/networking/vconfig.c b/networking/vconfig.c index 7e805be9c..77fbe3a40 100644 --- a/networking/vconfig.c +++ b/networking/vconfig.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config VCONFIG -//config: bool "vconfig (2.3 kb)" +//config: bool "vconfig (2.6 kb)" //config: default y //config: help //config: Creates, removes, and configures VLAN interfaces diff --git a/networking/wget.c b/networking/wget.c index 9ec0e67b9..199ddd4da 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -9,7 +9,7 @@ * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. */ //config:config WGET -//config: bool "wget (38 kb)" +//config: bool "wget (41 kb)" //config: default y //config: help //config: wget is a utility for non-interactive download of files from HTTP diff --git a/networking/whois.c b/networking/whois.c index caa71ac51..3a1dbd45d 100644 --- a/networking/whois.c +++ b/networking/whois.c @@ -10,7 +10,7 @@ * Add proxy support */ //config:config WHOIS -//config: bool "whois (6.3 kb)" +//config: bool "whois (6.5 kb)" //config: default y //config: help //config: whois is a client for the whois directory service diff --git a/networking/zcip.c b/networking/zcip.c index 311dfbe4c..137d46e13 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -14,7 +14,7 @@ * certainly be used. Its naming is built over multicast DNS. */ //config:config ZCIP -//config: bool "zcip (8.4 kb)" +//config: bool "zcip (8.7 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/printutils/lpd.c b/printutils/lpd.c index 34e5ea209..c67d54708 100644 --- a/printutils/lpd.c +++ b/printutils/lpd.c @@ -70,7 +70,7 @@ * mv -f ./"$DATAFILE" save/ */ //config:config LPD -//config: bool "lpd (5.5 kb)" +//config: bool "lpd (5.7 kb)" //config: default y //config: help //config: lpd is a print spooling daemon. diff --git a/printutils/lpr.c b/printutils/lpr.c index d40d0a67c..25b0f7235 100644 --- a/printutils/lpr.c +++ b/printutils/lpr.c @@ -12,13 +12,13 @@ * See RFC 1179 for protocol description. */ //config:config LPR -//config: bool "lpr (9.9 kb)" +//config: bool "lpr (10 kb)" //config: default y //config: help //config: lpr sends files (or standard input) to a print spooling daemon. //config: //config:config LPQ -//config: bool "lpq (9.9 kb)" +//config: bool "lpq (10 kb)" //config: default y //config: help //config: lpq is a print spool queue examination and manipulation program. diff --git a/procps/free.c b/procps/free.c index 0b68e1b88..d0c849b79 100644 --- a/procps/free.c +++ b/procps/free.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FREE -//config: bool "free (3.1 kb)" +//config: bool "free (3.8 kb)" //config: default y //config: help //config: free displays the total amount of free and used physical and swap diff --git a/procps/fuser.c b/procps/fuser.c index 191746751..f72552f1b 100644 --- a/procps/fuser.c +++ b/procps/fuser.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FUSER -//config: bool "fuser (7 kb)" +//config: bool "fuser (7.3 kb)" //config: default y //config: help //config: fuser lists all PIDs (Process IDs) that currently have a given diff --git a/procps/iostat.c b/procps/iostat.c index 1c6fb87ba..d3157757f 100644 --- a/procps/iostat.c +++ b/procps/iostat.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config IOSTAT -//config: bool "iostat (7.6 kb)" +//config: bool "iostat (8 kb)" //config: default y //config: help //config: Report CPU and I/O statistics diff --git a/procps/kill.c b/procps/kill.c index 208efebde..d4be18dd8 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config KILL -//config: bool "kill (3.1 kb)" +//config: bool "kill (3.4 kb)" //config: default y //config: help //config: The command kill sends the specified signal to the specified @@ -16,7 +16,7 @@ //config: signal is sent. //config: //config:config KILLALL -//config: bool "killall (5.6 kb)" +//config: bool "killall (5.9 kb)" //config: default y //config: help //config: killall sends a signal to all processes running any of the @@ -24,7 +24,7 @@ //config: sent. //config: //config:config KILLALL5 -//config: bool "killall5 (5.3 kb)" +//config: bool "killall5 (5.6 kb)" //config: default y //config: help //config: The SystemV killall command. killall5 sends a signal diff --git a/procps/lsof.c b/procps/lsof.c index 9cb8d066c..57e385c3f 100644 --- a/procps/lsof.c +++ b/procps/lsof.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LSOF -//config: bool "lsof (3.4 kb)" +//config: bool "lsof (3.7 kb)" //config: default y //config: help //config: Show open files in the format of: diff --git a/procps/mpstat.c b/procps/mpstat.c index c78c1f0a0..795b4ccb7 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MPSTAT -//config: bool "mpstat (9.8 kb)" +//config: bool "mpstat (10 kb)" //config: default y //config: help //config: Per-processor statistics diff --git a/procps/nmeter.c b/procps/nmeter.c index 4197174ba..dca07eac6 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -6,7 +6,7 @@ * Contact me: vda.linux@googlemail.com */ //config:config NMETER -//config: bool "nmeter (11 kb)" +//config: bool "nmeter (12 kb)" //config: default y //config: help //config: Prints selected system stats continuously, one line per update. diff --git a/procps/pgrep.c b/procps/pgrep.c index 82e00322f..04ae92a67 100644 --- a/procps/pgrep.c +++ b/procps/pgrep.c @@ -7,13 +7,13 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config PGREP -//config: bool "pgrep (6.5 kb)" +//config: bool "pgrep (6.8 kb)" //config: default y //config: help //config: Look for processes by name. //config: //config:config PKILL -//config: bool "pkill (7.5 kb)" +//config: bool "pkill (7.8 kb)" //config: default y //config: help //config: Send signals to processes by name. diff --git a/procps/pidof.c b/procps/pidof.c index b81709a81..507a011a2 100644 --- a/procps/pidof.c +++ b/procps/pidof.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PIDOF -//config: bool "pidof (6.3 kb)" +//config: bool "pidof (6.5 kb)" //config: default y //config: help //config: Pidof finds the process id's (pids) of the named programs. It prints diff --git a/procps/pmap.c b/procps/pmap.c index 408cbfce7..49f7688d9 100644 --- a/procps/pmap.c +++ b/procps/pmap.c @@ -8,7 +8,7 @@ * for details. */ //config:config PMAP -//config: bool "pmap (6 kb)" +//config: bool "pmap (6.2 kb)" //config: default y //config: help //config: Display processes' memory mappings. diff --git a/procps/powertop.c b/procps/powertop.c index 8d5d9295d..147b7a3ef 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config POWERTOP -//config: bool "powertop (9.6 kb)" +//config: bool "powertop (9.9 kb)" //config: default y //config: help //config: Analyze power consumption on Intel-based laptops diff --git a/procps/ps.c b/procps/ps.c index 03b9c418c..5b521aebd 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PS -//config: bool "ps (11 kb)" +//config: bool "ps (12 kb)" //config: default y //config: help //config: ps gives a snapshot of the current processes. diff --git a/procps/pstree.c b/procps/pstree.c index 67b711168..bf6ceed5a 100644 --- a/procps/pstree.c +++ b/procps/pstree.c @@ -10,7 +10,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PSTREE -//config: bool "pstree (9.3 kb)" +//config: bool "pstree (9.4 kb)" //config: default y //config: help //config: Display a tree of processes. diff --git a/procps/pwdx.c b/procps/pwdx.c index 24ba25d90..9257347bb 100644 --- a/procps/pwdx.c +++ b/procps/pwdx.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PWDX -//config: bool "pwdx (3.7 kb)" +//config: bool "pwdx (3.9 kb)" //config: default y //config: help //config: Report current working directory of a process diff --git a/procps/smemcap.c b/procps/smemcap.c index 2f1897dae..a2231788b 100644 --- a/procps/smemcap.c +++ b/procps/smemcap.c @@ -8,7 +8,7 @@ herein by reference. */ //config:config SMEMCAP -//config: bool "smemcap (2.5 kb)" +//config: bool "smemcap (3 kb)" //config: default y //config: help //config: smemcap is a tool for capturing process data for smem, diff --git a/procps/sysctl.c b/procps/sysctl.c index 40afa0c90..84c5be4f7 100644 --- a/procps/sysctl.c +++ b/procps/sysctl.c @@ -11,7 +11,7 @@ * v1.01.1 - busybox applet aware by */ //config:config BB_SYSCTL -//config: bool "sysctl (7.4 kb)" +//config: bool "sysctl (7.9 kb)" //config: default y //config: help //config: Configure kernel parameters at runtime. diff --git a/procps/uptime.c b/procps/uptime.c index 4fd0c9d2d..aec7bd7d1 100644 --- a/procps/uptime.c +++ b/procps/uptime.c @@ -12,7 +12,7 @@ * Added FEATURE_UPTIME_UTMP_SUPPORT flag. */ //config:config UPTIME -//config: bool "uptime (3.7 kb)" +//config: bool "uptime (4 kb)" //config: default y //config: help //config: uptime gives a one line display of the current time, how long diff --git a/procps/watch.c b/procps/watch.c index 1190b29df..05b72723c 100644 --- a/procps/watch.c +++ b/procps/watch.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WATCH -//config: bool "watch (4.4 kb)" +//config: bool "watch (5.2 kb)" //config: default y //config: help //config: watch is used to execute a program periodically, showing diff --git a/runit/chpst.c b/runit/chpst.c index af777568f..2be1a5775 100644 --- a/runit/chpst.c +++ b/runit/chpst.c @@ -28,33 +28,33 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ //config:config CHPST -//config: bool "chpst (9 kb)" +//config: bool "chpst (9.2 kb)" //config: default y //config: help //config: chpst changes the process state according to the given options, and //config: execs specified program. //config: //config:config SETUIDGID -//config: bool "setuidgid (4 kb)" +//config: bool "setuidgid (4.2 kb)" //config: default y //config: help //config: Sets soft resource limits as specified by options //config: //config:config ENVUIDGID -//config: bool "envuidgid (3.9 kb)" +//config: bool "envuidgid (4.1 kb)" //config: default y //config: help //config: Sets $UID to account's uid and $GID to account's gid //config: //config:config ENVDIR -//config: bool "envdir (2.5 kb)" +//config: bool "envdir (2.9 kb)" //config: default y //config: help //config: Sets various environment variables as specified by files //config: in the given directory //config: //config:config SOFTLIMIT -//config: bool "softlimit (4.5 kb)" +//config: bool "softlimit (4.7 kb)" //config: default y //config: help //config: Sets soft resource limits as specified by options diff --git a/runit/runsv.c b/runit/runsv.c index 6ad6bf46e..20a445319 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ //config:config RUNSV -//config: bool "runsv (7.8 kb)" +//config: bool "runsv (8.2 kb)" //config: default y //config: help //config: runsv starts and monitors a service and optionally an appendant log diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 55dd47e0d..d6629dedd 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Busyboxed by Denys Vlasenko */ //config:config RUNSVDIR -//config: bool "runsvdir (6.3 kb)" +//config: bool "runsvdir (6.6 kb)" //config: default y //config: help //config: runsvdir starts a runsv process for each subdirectory, or symlink to diff --git a/runit/sv.c b/runit/sv.c index 5c249ff95..1eca1e854 100644 --- a/runit/sv.c +++ b/runit/sv.c @@ -154,7 +154,7 @@ Exit Codes /* Busyboxed by Denys Vlasenko */ //config:config SV -//config: bool "sv (8.5 kb)" +//config: bool "sv (8.7 kb)" //config: default y //config: help //config: sv reports the current status and controls the state of services @@ -169,14 +169,14 @@ Exit Codes //config: Defaults to "/var/service" //config: //config:config SVC -//config: bool "svc (8.4 kb)" +//config: bool "svc (8.7 kb)" //config: default y //config: help //config: svc controls the state of services monitored by the runsv supervisor. //config: It is compatible with daemontools command with the same name. //config: //config:config SVOK -//config: bool "svok (1.5 kb)" +//config: bool "svok (1.8 kb)" //config: default y //config: help //config: svok checks whether runsv supervisor is running. diff --git a/shell/ash.c b/shell/ash.c index 8bdeb44ae..e1d93da73 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -20,7 +20,7 @@ //config: depends on !NOMMU //config: //config:config ASH -//config: bool "ash (78 kb)" +//config: bool "ash (80 kb)" //config: default y //config: depends on !NOMMU //config: select SHELL_ASH diff --git a/shell/cttyhack.c b/shell/cttyhack.c index b9ee59bd0..62dfb2bc2 100644 --- a/shell/cttyhack.c +++ b/shell/cttyhack.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config CTTYHACK -//config: bool "cttyhack (2.4 kb)" +//config: bool "cttyhack (2.7 kb)" //config: default y //config: help //config: One common problem reported on the mailing list is the "can't diff --git a/shell/hush.c b/shell/hush.c index 2f55b92ea..8e632e0af 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -91,7 +91,7 @@ * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*" */ //config:config HUSH -//config: bool "hush (68 kb)" +//config: bool "hush (70 kb)" //config: default y //config: select SHELL_HUSH //config: help diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c index df0edee0a..d4f2c0c8f 100644 --- a/sysklogd/klogd.c +++ b/sysklogd/klogd.c @@ -17,7 +17,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config KLOGD -//config: bool "klogd (5.7 kb)" +//config: bool "klogd (6.2 kb)" //config: default y //config: help //config: klogd is a utility which intercepts and logs all diff --git a/sysklogd/logger.c b/sysklogd/logger.c index 04b2c8e3b..b99e8af74 100644 --- a/sysklogd/logger.c +++ b/sysklogd/logger.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOGGER -//config: bool "logger (6.3 kb)" +//config: bool "logger (6.5 kb)" //config: default y //config: select FEATURE_SYSLOG //config: help diff --git a/sysklogd/logread.c b/sysklogd/logread.c index e6cfcf4a7..632346d28 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c @@ -9,7 +9,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOGREAD -//config: bool "logread (4.8 kb)" +//config: bool "logread (5 kb)" //config: default y //WRONG: it should be compilable without SYSLOG=y: //WRONG: depends on FEATURE_IPC_SYSLOG diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 7711e467b..83b5c0cf6 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -13,7 +13,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SYSLOGD -//config: bool "syslogd (13 kb)" +//config: bool "syslogd (14 kb)" //config: default y //config: help //config: The syslogd utility is used to record logs of all the diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 00613f8e3..5c0bb1768 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config ACPID -//config: bool "acpid (9 kb)" +//config: bool "acpid (9.3 kb)" //config: default y //config: help //config: acpid listens to ACPI events coming either in textual form from diff --git a/util-linux/blkdiscard.c b/util-linux/blkdiscard.c index 7ac8045f9..70fd34af3 100644 --- a/util-linux/blkdiscard.c +++ b/util-linux/blkdiscard.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config BLKDISCARD -//config: bool "blkdiscard (4.3 kb)" +//config: bool "blkdiscard (4.6 kb)" //config: default y //config: help //config: blkdiscard discards sectors on a given device. diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c index 3b550220a..d47e43e55 100644 --- a/util-linux/blockdev.c +++ b/util-linux/blockdev.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config BLOCKDEV -//config: bool "blockdev (2.3 kb)" +//config: bool "blockdev (2.6 kb)" //config: default y //config: help //config: Performs some ioctls with block devices. diff --git a/util-linux/cal.c b/util-linux/cal.c index 522ab3476..0577c3899 100644 --- a/util-linux/cal.c +++ b/util-linux/cal.c @@ -11,7 +11,7 @@ * Major size reduction... over 50% (>1.5k) on i386. */ //config:config CAL -//config: bool "cal (5.8 kb)" +//config: bool "cal (6.1 kb)" //config: default y //config: help //config: cal is used to display a monthly calendar. diff --git a/util-linux/chrt.c b/util-linux/chrt.c index be96fa426..51d08584e 100644 --- a/util-linux/chrt.c +++ b/util-linux/chrt.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config CHRT -//config: bool "chrt (4.7 kb)" +//config: bool "chrt (5.1 kb)" //config: default y //config: help //config: Manipulate real-time attributes of a process. diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c index 6670b84de..5d8f01a64 100644 --- a/util-linux/dmesg.c +++ b/util-linux/dmesg.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config DMESG -//config: bool "dmesg (3.7 kb)" +//config: bool "dmesg (3.9 kb)" //config: default y //config: help //config: dmesg is used to examine or control the kernel ring buffer. When the diff --git a/util-linux/eject.c b/util-linux/eject.c index 29b0a86bd..b9813262b 100644 --- a/util-linux/eject.c +++ b/util-linux/eject.c @@ -13,7 +13,7 @@ * Most of the dirty work blatantly ripped off from cat.c =) */ //config:config EJECT -//config: bool "eject (4 kb)" +//config: bool "eject (4.3 kb)" //config: default y //config: help //config: Used to eject cdroms. (defaults to /dev/cdrom) diff --git a/util-linux/fallocate.c b/util-linux/fallocate.c index 3935e7c9b..d5c25894d 100644 --- a/util-linux/fallocate.c +++ b/util-linux/fallocate.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FALLOCATE -//config: bool "fallocate (4.1 kb)" +//config: bool "fallocate (4.3 kb)" //config: default y //config: help //config: Preallocate space for files. diff --git a/util-linux/fatattr.c b/util-linux/fatattr.c index afd70c45d..d8ea4553d 100644 --- a/util-linux/fatattr.c +++ b/util-linux/fatattr.c @@ -9,7 +9,7 @@ * Public License */ //config:config FATATTR -//config: bool "fatattr (1.9 kb)" +//config: bool "fatattr (2.2 kb)" //config: default y //config: help //config: fatattr lists or changes the file attributes on a fat file system. diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 768ab80eb..7e88c8313 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -12,7 +12,7 @@ * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) */ //config:config FBSET -//config: bool "fbset (5.9 kb)" +//config: bool "fbset (6.2 kb)" //config: default y //config: help //config: fbset is used to show or change the settings of a Linux frame buffer diff --git a/util-linux/fdformat.c b/util-linux/fdformat.c index f0466fdbd..0f8743020 100644 --- a/util-linux/fdformat.c +++ b/util-linux/fdformat.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FDFORMAT -//config: bool "fdformat (4.4 kb)" +//config: bool "fdformat (4.7 kb)" //config: default y //config: help //config: fdformat is used to low-level format a floppy disk. diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 20e7d56fa..96e2abffe 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FDISK -//config: bool "fdisk (37 kb)" +//config: bool "fdisk (31 kb)" //config: default y //config: help //config: The fdisk utility is used to divide hard disks into one or more diff --git a/util-linux/findfs.c b/util-linux/findfs.c index f5621a1fa..ec0375dfb 100644 --- a/util-linux/findfs.c +++ b/util-linux/findfs.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FINDFS -//config: bool "findfs (12 kb)" +//config: bool "findfs (11 kb)" //config: default y //config: select VOLUMEID //config: help diff --git a/util-linux/flock.c b/util-linux/flock.c index 1ed752a80..ee88be5b7 100644 --- a/util-linux/flock.c +++ b/util-linux/flock.c @@ -4,7 +4,7 @@ * This is free software, licensed under the GNU General Public License v2. */ //config:config FLOCK -//config: bool "flock (6.3 kb)" +//config: bool "flock (6.5 kb)" //config: default y //config: help //config: Manage locks from shell scripts diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c index 309169d25..88f50c51a 100644 --- a/util-linux/freeramdisk.c +++ b/util-linux/freeramdisk.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FDFLUSH -//config: bool "fdflush (1.3 kb)" +//config: bool "fdflush (1.6 kb)" //config: default y //config: help //config: fdflush is only needed when changing media on slightly-broken @@ -21,7 +21,7 @@ //config: leave this disabled. //config: //config:config FREERAMDISK -//config: bool "freeramdisk (1.3 kb)" +//config: bool "freeramdisk (1.6 kb)" //config: default y //config: help //config: Linux allows you to create ramdisks. This utility allows you to diff --git a/util-linux/fsfreeze.c b/util-linux/fsfreeze.c index 6e2ff0a54..66b6fd06f 100644 --- a/util-linux/fsfreeze.c +++ b/util-linux/fsfreeze.c @@ -5,7 +5,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config FSFREEZE -//config: bool "fsfreeze (3.5 kb)" +//config: bool "fsfreeze (3.7 kb)" //config: default y //config: select LONG_OPTS //config: help diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index 6d673002f..c28e67270 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config FSTRIM -//config: bool "fstrim (4.4 kb)" +//config: bool "fstrim (4.6 kb)" //config: default y //config: help //config: Discard unused blocks on a mounted filesystem. diff --git a/util-linux/getopt.c b/util-linux/getopt.c index 4148586d3..213bfab0b 100644 --- a/util-linux/getopt.c +++ b/util-linux/getopt.c @@ -29,7 +29,7 @@ * Replaced our_malloc with xmalloc and our_realloc with xrealloc */ //config:config GETOPT -//config: bool "getopt (5.8 kb)" +//config: bool "getopt (6 kb)" //config: default y //config: help //config: The getopt utility is used to break up (parse) options in command diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index be4c1964f..c46ffeca7 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -9,14 +9,14 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HEXDUMP -//config: bool "hexdump (8.6 kb)" +//config: bool "hexdump (8.7 kb)" //config: default y //config: help //config: The hexdump utility is used to display binary data in a readable //config: way that is comparable to the output from most hex editors. //config: //config:config HD -//config: bool "hd (7.8 kb)" +//config: bool "hd (8.3 kb)" //config: default y //config: help //config: hd is an alias to hexdump -C. diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 636cbfeec..1e8ecb6e6 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config XXD -//config: bool "xxd (8.9 kb)" +//config: bool "xxd (11 kb)" //config: default y //config: help //config: The xxd utility is used to display binary data in a readable diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 723b09589..a0b7b52bd 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config HWCLOCK -//config: bool "hwclock (5.8 kb)" +//config: bool "hwclock (5.9 kb)" //config: default y //config: help //config: The hwclock utility is used to read and set the hardware clock diff --git a/util-linux/ionice.c b/util-linux/ionice.c index 82bd309d1..b768c8322 100644 --- a/util-linux/ionice.c +++ b/util-linux/ionice.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IONICE -//config: bool "ionice (3.8 kb)" +//config: bool "ionice (4 kb)" //config: default y //config: help //config: Set/set program io scheduling class and priority diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c index 3d3ad0b56..126221c83 100644 --- a/util-linux/ipcrm.c +++ b/util-linux/ipcrm.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IPCRM -//config: bool "ipcrm (3.2 kb)" +//config: bool "ipcrm (3.5 kb)" //config: default y //config: help //config: The ipcrm utility allows the removal of System V interprocess diff --git a/util-linux/ipcs.c b/util-linux/ipcs.c index 5973cbf57..f0e5c5a7f 100644 --- a/util-linux/ipcs.c +++ b/util-linux/ipcs.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config IPCS -//config: bool "ipcs (11 kb)" +//config: bool "ipcs (12 kb)" //config: default y //config: help //config: The ipcs utility is used to provide information on the currently diff --git a/util-linux/last.c b/util-linux/last.c index 63751ca45..7530d013d 100644 --- a/util-linux/last.c +++ b/util-linux/last.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config LAST -//config: bool "last (6.1 kb)" +//config: bool "last (7.4 kb)" //config: default y //config: depends on FEATURE_WTMP //config: help diff --git a/util-linux/losetup.c b/util-linux/losetup.c index 24f7a2349..9b43d20b3 100644 --- a/util-linux/losetup.c +++ b/util-linux/losetup.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LOSETUP -//config: bool "losetup (5.5 kb)" +//config: bool "losetup (6.2 kb)" //config: default y //config: help //config: losetup is used to associate or detach a loop device with a regular diff --git a/util-linux/lspci.c b/util-linux/lspci.c index c22cbcc1e..b38b46be3 100644 --- a/util-linux/lspci.c +++ b/util-linux/lspci.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSPCI -//config: bool "lspci (6.3 kb)" +//config: bool "lspci (6.4 kb)" //config: default y //config: help //config: lspci is a utility for displaying information about PCI buses in the diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c index 9abb748ce..262c70a1b 100644 --- a/util-linux/lsusb.c +++ b/util-linux/lsusb.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config LSUSB -//config: bool "lsusb (4.2 kb)" +//config: bool "lsusb (4.4 kb)" //config: default y //config: help //config: lsusb is a utility for displaying information about USB buses in the diff --git a/util-linux/mdev.c b/util-linux/mdev.c index ebdc0c254..e98d46743 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MDEV -//config: bool "mdev (17 kb)" +//config: bool "mdev (20 kb)" //config: default y //config: help //config: mdev is a mini-udev implementation for dynamically creating device diff --git a/util-linux/mesg.c b/util-linux/mesg.c index 8c032555b..9461dbc5e 100644 --- a/util-linux/mesg.c +++ b/util-linux/mesg.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MESG -//config: bool "mesg (1.4 kb)" +//config: bool "mesg (1.8 kb)" //config: default y //config: help //config: Mesg controls access to your terminal by others. It is typically diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index d2db78e1d..7ae4fd520 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c @@ -8,13 +8,13 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MKDOSFS -//config: bool "mkdosfs (7.2 kb)" +//config: bool "mkdosfs (7.6 kb)" //config: default y //config: help //config: Utility to create FAT32 filesystems. //config: //config:config MKFS_VFAT -//config: bool "mkfs.vfat (7.2 kb)" +//config: bool "mkfs.vfat (7.6 kb)" //config: default y //config: help //config: Alias to "mkdosfs". diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 8fe5d0293..f80457a31 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config MKSWAP -//config: bool "mkswap (6.3 kb)" +//config: bool "mkswap (6.6 kb)" //config: default y //config: help //config: The mkswap utility is used to configure a file or disk partition as diff --git a/util-linux/more.c b/util-linux/more.c index 352a3b6cf..bffe6ee5e 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -14,7 +14,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config MORE -//config: bool "more (7 kb)" +//config: bool "more (7.2 kb)" //config: default y //config: help //config: more is a simple utility which allows you to read text one screen diff --git a/util-linux/mount.c b/util-linux/mount.c index 4e65b6b46..d0f0ae1ad 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -18,7 +18,7 @@ // //config:config MOUNT -//config: bool "mount (23 kb)" +//config: bool "mount (24 kb)" //config: default y //config: help //config: All files and filesystems in Unix are arranged into one big directory diff --git a/util-linux/mountpoint.c b/util-linux/mountpoint.c index 28b1e7a54..87f4cc60d 100644 --- a/util-linux/mountpoint.c +++ b/util-linux/mountpoint.c @@ -9,7 +9,7 @@ * Based on sysvinit's mountpoint */ //config:config MOUNTPOINT -//config: bool "mountpoint (4.9 kb)" +//config: bool "mountpoint (5.1 kb)" //config: default y //config: help //config: mountpoint checks if the directory is a mountpoint. diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index 1aa045b35..9a250e43c 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config NSENTER -//config: bool "nsenter (6.5 kb)" +//config: bool "nsenter (6.8 kb)" //config: default y //config: help //config: Run program with namespaces of other processes. diff --git a/util-linux/pivot_root.c b/util-linux/pivot_root.c index ecc891100..b65e914cf 100644 --- a/util-linux/pivot_root.c +++ b/util-linux/pivot_root.c @@ -9,7 +9,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config PIVOT_ROOT -//config: bool "pivot_root (1.1 kb)" +//config: bool "pivot_root (1.4 kb)" //config: default y //config: help //config: The pivot_root utility swaps the mount points for the root filesystem diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 9b80141c9..fd45081d8 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c @@ -8,7 +8,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config RDATE -//config: bool "rdate (5.6 kb)" +//config: bool "rdate (5.9 kb)" //config: default y //config: help //config: The rdate utility allows you to synchronize the date and time of your diff --git a/util-linux/rdev.c b/util-linux/rdev.c index d6b515ebc..7e8c8cd8a 100644 --- a/util-linux/rdev.c +++ b/util-linux/rdev.c @@ -8,7 +8,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config RDEV -//config: bool "rdev (1.8 kb)" +//config: bool "rdev (2.1 kb)" //config: default y //config: help //config: Print the device node associated with the filesystem mounted at '/'. diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c index f11c62292..a7e4dcb73 100644 --- a/util-linux/readprofile.c +++ b/util-linux/readprofile.c @@ -32,7 +32,7 @@ * Paul Mundt . */ //config:config READPROFILE -//config: bool "readprofile (7.1 kb)" +//config: bool "readprofile (7.5 kb)" //config: default y //config: help //config: This allows you to parse /proc/profile for basic profiling. diff --git a/util-linux/renice.c b/util-linux/renice.c index fc72550f4..53f197cce 100644 --- a/util-linux/renice.c +++ b/util-linux/renice.c @@ -18,7 +18,7 @@ * following IDs (if any). Multiple switches are allowed. */ //config:config RENICE -//config: bool "renice (4.2 kb)" +//config: bool "renice (4.4 kb)" //config: default y //config: help //config: Renice alters the scheduling priority of one or more running diff --git a/util-linux/rev.c b/util-linux/rev.c index 63b005c67..12df2b9ff 100644 --- a/util-linux/rev.c +++ b/util-linux/rev.c @@ -6,7 +6,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config REV -//config: bool "rev (4.4 kb)" +//config: bool "rev (4.6 kb)" //config: default y //config: help //config: Reverse lines of a file or files. diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index eac16077d..a8dfab064 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -23,7 +23,7 @@ * That flag should not be needed on systems with adjtime support. */ //config:config RTCWAKE -//config: bool "rtcwake (6.8 kb)" +//config: bool "rtcwake (7.5 kb)" //config: default y //config: help //config: Enter a system sleep state until specified wakeup time. diff --git a/util-linux/script.c b/util-linux/script.c index 963435335..58b844e77 100644 --- a/util-linux/script.c +++ b/util-linux/script.c @@ -11,7 +11,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SCRIPT -//config: bool "script (8.6 kb)" +//config: bool "script (8.8 kb)" //config: default y //config: help //config: The script makes typescript of terminal session. diff --git a/util-linux/scriptreplay.c b/util-linux/scriptreplay.c index 3c032eec5..e3083ab93 100644 --- a/util-linux/scriptreplay.c +++ b/util-linux/scriptreplay.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SCRIPTREPLAY -//config: bool "scriptreplay (2.4 kb)" +//config: bool "scriptreplay (2.6 kb)" //config: default y //config: help //config: This program replays a typescript, using timing information diff --git a/util-linux/setarch.c b/util-linux/setarch.c index cf8ef0064..68b7c663c 100644 --- a/util-linux/setarch.c +++ b/util-linux/setarch.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETARCH -//config: bool "setarch (3.6 kb)" +//config: bool "setarch (3.8 kb)" //config: default y //config: help //config: The linux32 utility is used to create a 32bit environment for the @@ -16,13 +16,13 @@ //config: (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...). //config: //config:config LINUX32 -//config: bool "linux32 (3.3 kb)" +//config: bool "linux32 (3.6 kb)" //config: default y //config: help //config: Alias to "setarch linux32". //config: //config:config LINUX64 -//config: bool "linux64 (3.3 kb)" +//config: bool "linux64 (3.5 kb)" //config: default y //config: help //config: Alias to "setarch linux64". diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c index 6904cf019..ee038516d 100644 --- a/util-linux/setpriv.c +++ b/util-linux/setpriv.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config SETPRIV -//config: bool "setpriv (6.6 kb)" +//config: bool "setpriv (6.9 kb)" //config: default y //config: select LONG_OPTS //config: help diff --git a/util-linux/setsid.c b/util-linux/setsid.c index cdad8c1d3..24b02a509 100644 --- a/util-linux/setsid.c +++ b/util-linux/setsid.c @@ -14,7 +14,7 @@ * - busyboxed */ //config:config SETSID -//config: bool "setsid (3.6 kb)" +//config: bool "setsid (3.8 kb)" //config: default y //config: help //config: setsid runs a program in a new session diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c index 901c0b8db..14139736e 100644 --- a/util-linux/switch_root.c +++ b/util-linux/switch_root.c @@ -7,7 +7,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config SWITCH_ROOT -//config: bool "switch_root (5.5 kb)" +//config: bool "switch_root (5.7 kb)" //config: default y //config: help //config: The switch_root utility is used from initramfs to select a new diff --git a/util-linux/taskset.c b/util-linux/taskset.c index 8b410f369..55c915e8d 100644 --- a/util-linux/taskset.c +++ b/util-linux/taskset.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config TASKSET -//config: bool "taskset (4.2 kb)" +//config: bool "taskset (5.6 kb)" //config: default y //config: help //config: Retrieve or set a processes's CPU affinity. diff --git a/util-linux/uevent.c b/util-linux/uevent.c index db11746d0..2193eb0f2 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config UEVENT -//config: bool "uevent (3.1 kb)" +//config: bool "uevent (3.5 kb)" //config: default y //config: help //config: uevent is a netlink listener for kernel uevent notifications diff --git a/util-linux/unshare.c b/util-linux/unshare.c index 06b938074..a9f56f388 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c @@ -7,7 +7,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config UNSHARE -//config: bool "unshare (7.2 kb)" +//config: bool "unshare (7.3 kb)" //config: default y //config: depends on !NOMMU //config: select LONG_OPTS diff --git a/util-linux/wall.c b/util-linux/wall.c index 23fb87517..72205cbae 100644 --- a/util-linux/wall.c +++ b/util-linux/wall.c @@ -6,7 +6,7 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ //config:config WALL -//config: bool "wall (2.6 kb)" +//config: bool "wall (2.9 kb)" //config: default y //config: depends on FEATURE_UTMP //config: help -- cgit v1.2.3-55-g6feb From 69d33db445964727b053068cfaa4d417767f8960 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Jul 2023 17:27:26 +0200 Subject: i2ctransfer: fix build warning Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index a70573ebe..5f41a72ec 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -107,6 +107,7 @@ static ALWAYS_INLINE void *itoptr(int i) return (void*)(intptr_t)i; } +#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CDETECT static int32_t i2c_smbus_access(int fd, char read_write, uint8_t cmd, int size, union i2c_smbus_data *data) { @@ -120,7 +121,6 @@ static int32_t i2c_smbus_access(int fd, char read_write, uint8_t cmd, return ioctl(fd, I2C_SMBUS, &args); } -#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CDETECT static int32_t i2c_smbus_read_byte(int fd) { union i2c_smbus_data data; -- cgit v1.2.3-55-g6feb From 9fc5933b100694174071c7c4697c70095799bfd0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 10 Jul 2023 17:27:54 +0200 Subject: ntpd: fix a warning on 32-bit arch build Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 93bd3189d..dcbdb8e60 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1632,7 +1632,7 @@ update_local_clock(peer_t *p) if (adjtimex(&tmx) < 0) bb_simple_perror_msg_and_die("adjtimex"); bb_error_msg("p adjtimex freq:%ld offset:%+ld status:0x%x tc:%ld", - tmx.freq, tmx.offset, tmx.status, tmx.constant); + (long)tmx.freq, (long)tmx.offset, tmx.status, (long)tmx.constant); } memset(&tmx, 0, sizeof(tmx)); @@ -1747,7 +1747,7 @@ update_local_clock(peer_t *p) * Not sure why. Perhaps it is normal. */ VERB4 bb_error_msg("adjtimex:%d freq:%ld offset:%+ld status:0x%x", - rc, tmx.freq, tmx.offset, tmx.status); + rc, (long)tmx.freq, (long)tmx.offset, tmx.status); G.kernel_freq_drift = tmx.freq / 65536; VERB2 bb_error_msg("update from:%s offset:%+f delay:%f jitter:%f clock drift:%+.3fppm tc:%d", p->p_dotted, -- cgit v1.2.3-55-g6feb From d70256a5c719439cc6fab6a4571c1bb46178e4c7 Mon Sep 17 00:00:00 2001 From: Andrej Picej Date: Tue, 11 Jul 2023 10:42:49 +0200 Subject: hwclock: add get/set parameters option In kernel 5.16 special ioctls were introduced to get/set RTC parameters. Add option to get/set parameters into busybox version of hwclock. Implementation is similar to the one already used in linux-utils hwclock tool. Example of parameter get use: $ hwclock -g 2 The RTC parameter 0x2 is set to 0x2. $ hwclock --param-get bsm The RTC parameter 0x2 is set to 0x2. Example of parameter set use: $ hwclock -p 2=1 The RTC parameter 0x2 will be set to 0x1. $ hwclock -p bsm=2 The RTC parameter 0x2 will be set to 0x2. function old new delta hwclock_main 298 576 +278 .rodata 105231 105400 +169 packed_usage 34541 34576 +35 static.hwclock_longopts 60 84 +24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 506/0) Total: 506 bytes Signed-off-by: Andrej Picej Signed-off-by: Denys Vlasenko --- include/rtc_.h | 18 +++++++++++ util-linux/hwclock.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/include/rtc_.h b/include/rtc_.h index 24ff5363f..782966090 100644 --- a/include/rtc_.h +++ b/include/rtc_.h @@ -46,6 +46,17 @@ struct linux_rtc_wkalrm { struct linux_rtc_time time; /* time the alarm is set to */ }; +struct rtc_param { + uint64_t param; + union { + uint64_t uvalue; + int64_t svalue; + uint64_t ptr; + }; + uint32_t index; + uint32_t __pad; +}; + /* * ioctl calls that are permitted to the /dev/rtc interface, if * any of the RTC drivers are enabled. @@ -71,12 +82,19 @@ struct linux_rtc_wkalrm { #define RTC_WKALM_SET _IOW('p', 0x0f, struct linux_rtc_wkalrm)/* Set wakeup alarm*/ #define RTC_WKALM_RD _IOR('p', 0x10, struct linux_rtc_wkalrm)/* Get wakeup alarm*/ +#define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param) /* Get parameter */ +#define RTC_PARAM_SET _IOW('p', 0x14, struct rtc_param) /* Set parameter */ + /* interrupt flags */ #define RTC_IRQF 0x80 /* any of the following is active */ #define RTC_PF 0x40 #define RTC_AF 0x20 #define RTC_UF 0x10 +#define RTC_PARAM_FEATURES 0 +#define RTC_PARAM_CORRECTION 1 +#define RTC_PARAM_BACKUP_SWITCH_MODE 2 + POP_SAVED_FUNCTION_VISIBILITY #endif diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index a0b7b52bd..d78bfe374 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -320,6 +320,70 @@ static void from_sys_clock(const char **pp_rtcname, int utc) close(rtc); } +static uint64_t resolve_rtc_param_alias(const char *alias) +{ + int n; + + BUILD_BUG_ON(RTC_PARAM_FEATURES != 0 + || RTC_PARAM_CORRECTION != 1 + || RTC_PARAM_BACKUP_SWITCH_MODE != 2 + ); + n = index_in_strings( + "features" "\0" + "correction" "\0" + "bsm" "\0" + , alias); + if (n >= 0) + return n; + return xstrtoull(alias, 0); +} + +static void get_rtc_param(const char **pp_rtcname, const char *rtc_param) +{ + int rtc; + struct rtc_param param; + + param.param = resolve_rtc_param_alias(rtc_param); + + rtc = rtc_xopen(pp_rtcname, O_RDONLY); + + xioctl(rtc, RTC_PARAM_GET, ¶m); + + printf("The RTC parameter 0x%llx is set to 0x%llx.\n", + (unsigned long long) param.param, (unsigned long long) param.uvalue); + + if (ENABLE_FEATURE_CLEAN_UP) + close(rtc); +} + +static void set_rtc_param(const char **pp_rtcname, char *rtc_param) +{ + int rtc; + struct rtc_param param; + char *eq; + + /* handle param name */ + eq = strchr(rtc_param, '='); + if (!eq) + bb_error_msg_and_die("expected ="); + *eq = '\0'; + param.param = resolve_rtc_param_alias(rtc_param); + *eq = '='; + + /* handle param value */ + param.uvalue = xstrtoull(eq + 1, 0); + + rtc = rtc_xopen(pp_rtcname, O_WRONLY); + + printf("The RTC parameter 0x%llx will be set to 0x%llx.\n", + (unsigned long long) param.param, (unsigned long long) param.uvalue); + + xioctl(rtc, RTC_PARAM_SET, ¶m); + + if (ENABLE_FEATURE_CLEAN_UP) + close(rtc); +} + // hwclock from util-linux 2.36.1 // hwclock [function] [option...] //Functions: @@ -346,10 +410,10 @@ static void from_sys_clock(const char **pp_rtcname, int utc) //usage:#define hwclock_trivial_usage //usage: IF_LONG_OPTS( -//usage: "[-swul] [--systz] [-f DEV]" +//usage: "[-swul] [--systz] [--param-get PARAM] [--param-set PARAM=VAL] [-f DEV]" //usage: ) //usage: IF_NOT_LONG_OPTS( -//usage: "[-swult] [-f DEV]" +//usage: "[-swult] [-g PARAM] [-p PARAM=VAL] [-f DEV]" //usage: ) //usage:#define hwclock_full_usage "\n\n" //usage: "Show or set hardware clock (RTC)\n" @@ -360,6 +424,8 @@ static void from_sys_clock(const char **pp_rtcname, int utc) //usage: IF_LONG_OPTS( //usage: "\n --systz Set in-kernel timezone, correct system time" //usage: "\n if RTC is kept in local time" +//usage: "\n --param-get PARAM Get RTC parameter" +//usage: "\n --param-set PARAM=VAL Set RTC parameter" //usage: ) //usage: "\n -f DEV Use specified device (e.g. /dev/rtc2)" //usage: "\n -u Assume RTC is kept in UTC" @@ -375,11 +441,14 @@ static void from_sys_clock(const char **pp_rtcname, int utc) #define HWCLOCK_OPT_SYSTOHC 0x10 #define HWCLOCK_OPT_SYSTZ 0x20 #define HWCLOCK_OPT_RTCFILE 0x40 +#define HWCLOCK_OPT_PARAM_GET 0x80 +#define HWCLOCK_OPT_PARAM_SET 0x100 int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int hwclock_main(int argc UNUSED_PARAM, char **argv) { const char *rtcname = NULL; + char *param; unsigned opt; int utc; #if ENABLE_LONG_OPTS @@ -391,14 +460,18 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) "systohc\0" No_argument "w" "systz\0" No_argument "t" /* short opt is non-standard */ "rtc\0" Required_argument "f" + "param-get\0" Required_argument "g" /* short opt is non-standard */ + "param-set\0" Required_argument "p" /* short opt is non-standard */ ; #endif opt = getopt32long(argv, - "^""lurswtf:v" /* -v is accepted and ignored */ + "^""lurswtf:g:p:v" /* -v is accepted and ignored */ "\0" - "r--wst:w--rst:s--wrt:t--rsw:l--u:u--l", + "r--wstgp:w--rstgp:s--wrtgp:t--rswgp:g--rswtp:p--rswtg:l--u:u--l", hwclock_longopts, - &rtcname + &rtcname, + ¶m, + ¶m ); /* If -u or -l wasn't given, check if we are using utc */ @@ -413,6 +486,10 @@ int hwclock_main(int argc UNUSED_PARAM, char **argv) from_sys_clock(&rtcname, utc); else if (opt & HWCLOCK_OPT_SYSTZ) set_kernel_timezone_and_clock(utc, NULL); + else if (opt & HWCLOCK_OPT_PARAM_GET) + get_rtc_param(&rtcname, param); + else if (opt & HWCLOCK_OPT_PARAM_SET) + set_rtc_param(&rtcname, param); else /* default HWCLOCK_OPT_SHOW */ show_clock(&rtcname, utc); -- cgit v1.2.3-55-g6feb