diff options
author | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
commit | 3fd34651ea72ea1c335d3170f234cb0517fd897f (patch) | |
tree | 36e8fc40cffd464ffda4759020777dd3ca23ca31 /libbb | |
parent | e3ac39098326de084a805d0dd31db9666b734f20 (diff) | |
parent | d6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff) | |
download | busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.gz busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.bz2 busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Kbuild.src | 2 | ||||
-rw-r--r-- | libbb/appletlib.c | 2 | ||||
-rw-r--r-- | libbb/bb_askpass.c | 4 | ||||
-rw-r--r-- | libbb/create_icmp6_socket.c | 38 | ||||
-rw-r--r-- | libbb/create_icmp_socket.c | 36 | ||||
-rw-r--r-- | libbb/hash_md5_sha.c | 6 | ||||
-rw-r--r-- | libbb/in_ether.c | 58 | ||||
-rw-r--r-- | libbb/lineedit.c | 82 | ||||
-rw-r--r-- | libbb/printable.c | 24 | ||||
-rw-r--r-- | libbb/time.c | 33 | ||||
-rw-r--r-- | libbb/unicode.c | 38 | ||||
-rw-r--r-- | libbb/xatonum.c | 7 | ||||
-rw-r--r-- | libbb/xfuncs_printf.c | 12 |
13 files changed, 216 insertions, 126 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index ad81ce46b..db79ff62b 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -27,8 +27,6 @@ lib-y += concat_subpath_file.o | |||
27 | lib-y += copy_file.o | 27 | lib-y += copy_file.o |
28 | lib-y += copyfd.o | 28 | lib-y += copyfd.o |
29 | lib-y += crc32.o | 29 | lib-y += crc32.o |
30 | lib-y += create_icmp6_socket.o | ||
31 | lib-y += create_icmp_socket.o | ||
32 | lib-y += default_error_retval.o | 30 | lib-y += default_error_retval.o |
33 | lib-y += device_open.o | 31 | lib-y += device_open.o |
34 | lib-y += dump.o | 32 | lib-y += dump.o |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f0df4e080..44161a219 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "busybox.h" | 29 | #include "busybox.h" |
30 | 30 | ||
31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ | 31 | #if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ |
32 | || defined(__APPLE__) \ | 32 | || defined(__APPLE__) \ |
33 | ) | 33 | ) |
34 | # include <malloc.h> /* for mallopt */ | 34 | # include <malloc.h> /* for mallopt */ |
35 | #endif | 35 | #endif |
diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index fe2b50677..77c1bcd95 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c | |||
@@ -65,7 +65,9 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) | |||
65 | i = 0; | 65 | i = 0; |
66 | while (1) { | 66 | while (1) { |
67 | int r = read(fd, &ret[i], 1); | 67 | int r = read(fd, &ret[i], 1); |
68 | if (r < 0) { | 68 | if ((i == 0 && r == 0) /* EOF (^D) with no password */ |
69 | || r < 0 | ||
70 | ) { | ||
69 | /* read is interrupted by timeout or ^C */ | 71 | /* read is interrupted by timeout or ^C */ |
70 | ret = NULL; | 72 | ret = NULL; |
71 | break; | 73 | break; |
diff --git a/libbb/create_icmp6_socket.c b/libbb/create_icmp6_socket.c deleted file mode 100644 index 368c69028..000000000 --- a/libbb/create_icmp6_socket.c +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * create raw socket for icmp (IPv6 version) protocol | ||
6 | * and drop root privileges if running setuid | ||
7 | * | ||
8 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
9 | */ | ||
10 | |||
11 | #include "libbb.h" | ||
12 | |||
13 | #if ENABLE_FEATURE_IPV6 | ||
14 | int FAST_FUNC create_icmp6_socket(void) | ||
15 | { | ||
16 | int sock; | ||
17 | #if 0 | ||
18 | struct protoent *proto; | ||
19 | proto = getprotobyname("ipv6-icmp"); | ||
20 | /* if getprotobyname failed, just silently force | ||
21 | * proto->p_proto to have the correct value for "ipv6-icmp" */ | ||
22 | sock = socket(AF_INET6, SOCK_RAW, | ||
23 | (proto ? proto->p_proto : IPPROTO_ICMPV6)); | ||
24 | #else | ||
25 | sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); | ||
26 | #endif | ||
27 | if (sock < 0) { | ||
28 | if (errno == EPERM) | ||
29 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | ||
30 | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); | ||
31 | } | ||
32 | |||
33 | /* drop root privs if running setuid */ | ||
34 | xsetuid(getuid()); | ||
35 | |||
36 | return sock; | ||
37 | } | ||
38 | #endif | ||
diff --git a/libbb/create_icmp_socket.c b/libbb/create_icmp_socket.c deleted file mode 100644 index 585626983..000000000 --- a/libbb/create_icmp_socket.c +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * create raw socket for icmp protocol | ||
6 | * and drop root privileges if running setuid | ||
7 | * | ||
8 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
9 | */ | ||
10 | |||
11 | #include "libbb.h" | ||
12 | |||
13 | int FAST_FUNC create_icmp_socket(void) | ||
14 | { | ||
15 | int sock; | ||
16 | #if 0 | ||
17 | struct protoent *proto; | ||
18 | proto = getprotobyname("icmp"); | ||
19 | /* if getprotobyname failed, just silently force | ||
20 | * proto->p_proto to have the correct value for "icmp" */ | ||
21 | sock = socket(AF_INET, SOCK_RAW, | ||
22 | (proto ? proto->p_proto : 1)); /* 1 == ICMP */ | ||
23 | #else | ||
24 | sock = socket(AF_INET, SOCK_RAW, 1); /* 1 == ICMP */ | ||
25 | #endif | ||
26 | if (sock < 0) { | ||
27 | if (errno == EPERM) | ||
28 | bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); | ||
29 | bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); | ||
30 | } | ||
31 | |||
32 | /* drop root privs if running setuid */ | ||
33 | xsetuid(getuid()); | ||
34 | |||
35 | return sock; | ||
36 | } | ||
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index b4d955e5a..3f743ac75 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c | |||
@@ -84,7 +84,7 @@ static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed) | |||
84 | if (swap_needed) | 84 | if (swap_needed) |
85 | t = bb_bswap_64(t); | 85 | t = bb_bswap_64(t); |
86 | /* wbuffer is suitably aligned for this */ | 86 | /* wbuffer is suitably aligned for this */ |
87 | *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; | 87 | *(bb__aliased_uint64_t *) (&ctx->wbuffer[64 - 8]) = t; |
88 | } | 88 | } |
89 | ctx->process_block(ctx); | 89 | ctx->process_block(ctx); |
90 | if (remaining >= 8) | 90 | if (remaining >= 8) |
@@ -883,10 +883,10 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) | |||
883 | uint64_t t; | 883 | uint64_t t; |
884 | t = ctx->total64[0] << 3; | 884 | t = ctx->total64[0] << 3; |
885 | t = SWAP_BE64(t); | 885 | t = SWAP_BE64(t); |
886 | *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t; | 886 | *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 8]) = t; |
887 | t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61); | 887 | t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61); |
888 | t = SWAP_BE64(t); | 888 | t = SWAP_BE64(t); |
889 | *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t; | 889 | *(bb__aliased_uint64_t *) (&ctx->wbuffer[128 - 16]) = t; |
890 | } | 890 | } |
891 | sha512_process_block128(ctx); | 891 | sha512_process_block128(ctx); |
892 | if (remaining >= 16) | 892 | if (remaining >= 16) |
diff --git a/libbb/in_ether.c b/libbb/in_ether.c new file mode 100644 index 000000000..dadadbafe --- /dev/null +++ b/libbb/in_ether.c | |||
@@ -0,0 +1,58 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | */ | ||
5 | |||
6 | //kbuild:lib-$(CONFIG_IFCONFIG) += in_ether.o | ||
7 | //kbuild:lib-$(CONFIG_IFENSLAVE) += in_ether.o | ||
8 | |||
9 | #include "libbb.h" | ||
10 | #include <net/if_arp.h> | ||
11 | #include <net/ethernet.h> | ||
12 | |||
13 | /* Convert Ethernet address from "XX[:]XX[:]XX[:]XX[:]XX[:]XX" to sockaddr. | ||
14 | * Return nonzero on error. | ||
15 | */ | ||
16 | int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap) | ||
17 | { | ||
18 | char *ptr; | ||
19 | int i, j; | ||
20 | unsigned char val; | ||
21 | unsigned char c; | ||
22 | |||
23 | sap->sa_family = ARPHRD_ETHER; | ||
24 | ptr = (char *) sap->sa_data; | ||
25 | |||
26 | i = ETH_ALEN; | ||
27 | goto first; | ||
28 | do { | ||
29 | /* We might get a semicolon here */ | ||
30 | if (*bufp == ':') | ||
31 | bufp++; | ||
32 | first: | ||
33 | j = val = 0; | ||
34 | do { | ||
35 | c = *bufp; | ||
36 | if (((unsigned char)(c - '0')) <= 9) { | ||
37 | c -= '0'; | ||
38 | } else if ((unsigned char)((c|0x20) - 'a') <= 5) { | ||
39 | c = (unsigned char)((c|0x20) - 'a') + 10; | ||
40 | } else { | ||
41 | if (j && (c == ':' || c == '\0')) | ||
42 | /* One-digit byte: __:X:__ */ | ||
43 | break; | ||
44 | return -1; | ||
45 | } | ||
46 | ++bufp; | ||
47 | val <<= 4; | ||
48 | val += c; | ||
49 | j ^= 1; | ||
50 | } while (j); | ||
51 | |||
52 | *ptr++ = val; | ||
53 | |||
54 | } while (--i); | ||
55 | |||
56 | /* Error if we aren't at end of string */ | ||
57 | return *bufp; | ||
58 | } | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 7f64a9691..20d75cf56 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -38,6 +38,14 @@ | |||
38 | * and the \] escape to signal the end of such a sequence. Example: | 38 | * and the \] escape to signal the end of such a sequence. Example: |
39 | * | 39 | * |
40 | * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] ' | 40 | * PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] ' |
41 | * | ||
42 | * Unicode in PS1 is not fully supported: prompt length calulation is wrong, | ||
43 | * resulting in line wrap problems with long (multi-line) input. | ||
44 | * | ||
45 | * Multi-line PS1 (e.g. PS1="\n[\w]\n$ ") has problems with history | ||
46 | * browsing: up/down arrows result in scrolling. | ||
47 | * It stems from simplistic "cmdedit_y = cmdedit_prmt_len / cmdedit_termw" | ||
48 | * calculation of how many lines the prompt takes. | ||
41 | */ | 49 | */ |
42 | #include "libbb.h" | 50 | #include "libbb.h" |
43 | #include "unicode.h" | 51 | #include "unicode.h" |
@@ -1268,7 +1276,7 @@ line_input_t* FAST_FUNC new_line_input_t(int flags) | |||
1268 | 1276 | ||
1269 | #if MAX_HISTORY > 0 | 1277 | #if MAX_HISTORY > 0 |
1270 | 1278 | ||
1271 | unsigned size_from_HISTFILESIZE(const char *hp) | 1279 | unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp) |
1272 | { | 1280 | { |
1273 | int size = MAX_HISTORY; | 1281 | int size = MAX_HISTORY; |
1274 | if (hp) { | 1282 | if (hp) { |
@@ -1323,6 +1331,17 @@ static int get_next_history(void) | |||
1323 | return 0; | 1331 | return 0; |
1324 | } | 1332 | } |
1325 | 1333 | ||
1334 | /* Lists command history. Used by shell 'history' builtins */ | ||
1335 | void FAST_FUNC show_history(const line_input_t *st) | ||
1336 | { | ||
1337 | int i; | ||
1338 | |||
1339 | if (!st) | ||
1340 | return; | ||
1341 | for (i = 0; i < st->cnt_history; i++) | ||
1342 | printf("%4d %s\n", i, st->history[i]); | ||
1343 | } | ||
1344 | |||
1326 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1345 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY |
1327 | /* We try to ensure that concurrent additions to the history | 1346 | /* We try to ensure that concurrent additions to the history |
1328 | * do not overwrite each other. | 1347 | * do not overwrite each other. |
@@ -1762,34 +1781,36 @@ static void ask_terminal(void) | |||
1762 | #define ask_terminal() ((void)0) | 1781 | #define ask_terminal() ((void)0) |
1763 | #endif | 1782 | #endif |
1764 | 1783 | ||
1784 | /* Called just once at read_line_input() init time */ | ||
1765 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1785 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
1766 | static void parse_and_put_prompt(const char *prmt_ptr) | 1786 | static void parse_and_put_prompt(const char *prmt_ptr) |
1767 | { | 1787 | { |
1788 | const char *p; | ||
1768 | cmdedit_prompt = prmt_ptr; | 1789 | cmdedit_prompt = prmt_ptr; |
1769 | cmdedit_prmt_len = strlen(prmt_ptr); | 1790 | p = strrchr(prmt_ptr, '\n'); |
1791 | cmdedit_prmt_len = unicode_strwidth(p ? p+1 : prmt_ptr); | ||
1770 | put_prompt(); | 1792 | put_prompt(); |
1771 | } | 1793 | } |
1772 | #else | 1794 | #else |
1773 | static void parse_and_put_prompt(const char *prmt_ptr) | 1795 | static void parse_and_put_prompt(const char *prmt_ptr) |
1774 | { | 1796 | { |
1775 | int prmt_len = 0; | 1797 | int prmt_size = 0; |
1776 | size_t cur_prmt_len = 0; | ||
1777 | char flg_not_length = '['; | ||
1778 | char *prmt_mem_ptr = xzalloc(1); | 1798 | char *prmt_mem_ptr = xzalloc(1); |
1779 | # if ENABLE_USERNAME_OR_HOMEDIR | 1799 | # if ENABLE_USERNAME_OR_HOMEDIR |
1780 | char *cwd_buf = NULL; | 1800 | char *cwd_buf = NULL; |
1781 | # endif | 1801 | # endif |
1782 | char timebuf[sizeof("HH:MM:SS")]; | 1802 | char flg_not_length = '['; |
1783 | char cbuf[2]; | 1803 | char cbuf[2]; |
1784 | char c; | ||
1785 | char *pbuf; | ||
1786 | 1804 | ||
1787 | cmdedit_prmt_len = 0; | 1805 | /*cmdedit_prmt_len = 0; - already is */ |
1788 | 1806 | ||
1789 | cbuf[1] = '\0'; /* never changes */ | 1807 | cbuf[1] = '\0'; /* never changes */ |
1790 | 1808 | ||
1791 | while (*prmt_ptr) { | 1809 | while (*prmt_ptr) { |
1810 | char timebuf[sizeof("HH:MM:SS")]; | ||
1792 | char *free_me = NULL; | 1811 | char *free_me = NULL; |
1812 | char *pbuf; | ||
1813 | char c; | ||
1793 | 1814 | ||
1794 | pbuf = cbuf; | 1815 | pbuf = cbuf; |
1795 | c = *prmt_ptr++; | 1816 | c = *prmt_ptr++; |
@@ -1922,7 +1943,8 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1922 | } | 1943 | } |
1923 | case '[': case ']': | 1944 | case '[': case ']': |
1924 | if (c == flg_not_length) { | 1945 | if (c == flg_not_length) { |
1925 | flg_not_length = (flg_not_length == '[' ? ']' : '['); | 1946 | /* Toggle '['/']' hex 5b/5d */ |
1947 | flg_not_length ^= 6; | ||
1926 | continue; | 1948 | continue; |
1927 | } | 1949 | } |
1928 | break; | 1950 | break; |
@@ -1930,11 +1952,22 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1930 | } /* if */ | 1952 | } /* if */ |
1931 | } /* if */ | 1953 | } /* if */ |
1932 | cbuf[0] = c; | 1954 | cbuf[0] = c; |
1933 | cur_prmt_len = strlen(pbuf); | 1955 | { |
1934 | prmt_len += cur_prmt_len; | 1956 | int n = strlen(pbuf); |
1935 | if (flg_not_length != ']') | 1957 | prmt_size += n; |
1936 | cmdedit_prmt_len += cur_prmt_len; | 1958 | if (c == '\n') |
1937 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); | 1959 | cmdedit_prmt_len = 0; |
1960 | else if (flg_not_length != ']') { | ||
1961 | #if 0 /*ENABLE_UNICODE_SUPPORT*/ | ||
1962 | /* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */ | ||
1963 | /* FIXME */ | ||
1964 | cmdedit_prmt_len += unicode_strwidth(pbuf); | ||
1965 | #else | ||
1966 | cmdedit_prmt_len += n; | ||
1967 | #endif | ||
1968 | } | ||
1969 | } | ||
1970 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); | ||
1938 | free(free_me); | 1971 | free(free_me); |
1939 | } /* while */ | 1972 | } /* while */ |
1940 | 1973 | ||
@@ -2003,7 +2036,15 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) | |||
2003 | S.sent_ESC_br6n = 0; | 2036 | S.sent_ESC_br6n = 0; |
2004 | if (cursor == 0) { /* otherwise it may be bogus */ | 2037 | if (cursor == 0) { /* otherwise it may be bogus */ |
2005 | int col = ((ic >> 32) & 0x7fff) - 1; | 2038 | int col = ((ic >> 32) & 0x7fff) - 1; |
2006 | if (col > cmdedit_prmt_len) { | 2039 | /* |
2040 | * Is col > cmdedit_prmt_len? | ||
2041 | * If yes (terminal says cursor is farther to the right | ||
2042 | * of where we think it should be), | ||
2043 | * the prompt wasn't printed starting at col 1, | ||
2044 | * there was additional text before it. | ||
2045 | */ | ||
2046 | if ((int)(col - cmdedit_prmt_len) > 0) { | ||
2047 | /* Fix our understanding of current x position */ | ||
2007 | cmdedit_x += (col - cmdedit_prmt_len); | 2048 | cmdedit_x += (col - cmdedit_prmt_len); |
2008 | while (cmdedit_x >= cmdedit_termw) { | 2049 | while (cmdedit_x >= cmdedit_termw) { |
2009 | cmdedit_x -= cmdedit_termw; | 2050 | cmdedit_x -= cmdedit_termw; |
@@ -2094,6 +2135,7 @@ static int32_t reverse_i_search(void) | |||
2094 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; | 2135 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; |
2095 | const char *matched_history_line; | 2136 | const char *matched_history_line; |
2096 | const char *saved_prompt; | 2137 | const char *saved_prompt; |
2138 | unsigned saved_prmt_len; | ||
2097 | int32_t ic; | 2139 | int32_t ic; |
2098 | 2140 | ||
2099 | matched_history_line = NULL; | 2141 | matched_history_line = NULL; |
@@ -2102,6 +2144,7 @@ static int32_t reverse_i_search(void) | |||
2102 | 2144 | ||
2103 | /* Save and replace the prompt */ | 2145 | /* Save and replace the prompt */ |
2104 | saved_prompt = cmdedit_prompt; | 2146 | saved_prompt = cmdedit_prompt; |
2147 | saved_prmt_len = cmdedit_prmt_len; | ||
2105 | goto set_prompt; | 2148 | goto set_prompt; |
2106 | 2149 | ||
2107 | while (1) { | 2150 | while (1) { |
@@ -2177,7 +2220,7 @@ static int32_t reverse_i_search(void) | |||
2177 | free((char*)cmdedit_prompt); | 2220 | free((char*)cmdedit_prompt); |
2178 | set_prompt: | 2221 | set_prompt: |
2179 | cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf); | 2222 | cmdedit_prompt = xasprintf("(reverse-i-search)'%s': ", match_buf); |
2180 | cmdedit_prmt_len = strlen(cmdedit_prompt); | 2223 | cmdedit_prmt_len = unicode_strwidth(cmdedit_prompt); |
2181 | goto do_redraw; | 2224 | goto do_redraw; |
2182 | } | 2225 | } |
2183 | } | 2226 | } |
@@ -2199,7 +2242,7 @@ static int32_t reverse_i_search(void) | |||
2199 | 2242 | ||
2200 | free((char*)cmdedit_prompt); | 2243 | free((char*)cmdedit_prompt); |
2201 | cmdedit_prompt = saved_prompt; | 2244 | cmdedit_prompt = saved_prompt; |
2202 | cmdedit_prmt_len = strlen(cmdedit_prompt); | 2245 | cmdedit_prmt_len = saved_prmt_len; |
2203 | redraw(cmdedit_y, command_len - cursor); | 2246 | redraw(cmdedit_y, command_len - cursor); |
2204 | 2247 | ||
2205 | return ic; | 2248 | return ic; |
@@ -2774,8 +2817,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2774 | free(command_ps); | 2817 | free(command_ps); |
2775 | #endif | 2818 | #endif |
2776 | 2819 | ||
2777 | if (command_len > 0) | 2820 | if (command_len > 0) { |
2778 | remember_in_history(command); | 2821 | remember_in_history(command); |
2822 | } | ||
2779 | 2823 | ||
2780 | if (break_out > 0) { | 2824 | if (break_out > 0) { |
2781 | command[command_len++] = '\n'; | 2825 | command[command_len++] = '\n'; |
diff --git a/libbb/printable.c b/libbb/printable.c index f6ada4904..9a423431e 100644 --- a/libbb/printable.c +++ b/libbb/printable.c | |||
@@ -32,3 +32,27 @@ void FAST_FUNC fputc_printable(int ch, FILE *file) | |||
32 | } | 32 | } |
33 | fputc(ch, file); | 33 | fputc(ch, file); |
34 | } | 34 | } |
35 | |||
36 | void FAST_FUNC visible(unsigned ch, char *buf, int flags) | ||
37 | { | ||
38 | if (ch == '\t' && !(flags & VISIBLE_SHOW_TABS)) { | ||
39 | goto raw; | ||
40 | } | ||
41 | if (ch == '\n') { | ||
42 | if (flags & VISIBLE_ENDLINE) | ||
43 | *buf++ = '$'; | ||
44 | } else { | ||
45 | if (ch >= 128) { | ||
46 | ch -= 128; | ||
47 | *buf++ = 'M'; | ||
48 | *buf++ = '-'; | ||
49 | } | ||
50 | if (ch < 32 || ch == 127) { | ||
51 | *buf++ = '^'; | ||
52 | ch ^= 0x40; | ||
53 | } | ||
54 | } | ||
55 | raw: | ||
56 | *buf++ = ch; | ||
57 | *buf = '\0'; | ||
58 | } | ||
diff --git a/libbb/time.c b/libbb/time.c index 57e14b66c..ea2f72e3b 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -23,14 +23,16 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
23 | if (sscanf(date_str, "%u:%u%c", | 23 | if (sscanf(date_str, "%u:%u%c", |
24 | &ptm->tm_hour, | 24 | &ptm->tm_hour, |
25 | &ptm->tm_min, | 25 | &ptm->tm_min, |
26 | &end) >= 2) { | 26 | &end) >= 2 |
27 | ) { | ||
27 | /* no adjustments needed */ | 28 | /* no adjustments needed */ |
28 | } else | 29 | } else |
29 | /* mm.dd-HH:MM */ | 30 | /* mm.dd-HH:MM */ |
30 | if (sscanf(date_str, "%u.%u-%u:%u%c", | 31 | if (sscanf(date_str, "%u.%u-%u:%u%c", |
31 | &ptm->tm_mon, &ptm->tm_mday, | 32 | &ptm->tm_mon, &ptm->tm_mday, |
32 | &ptm->tm_hour, &ptm->tm_min, | 33 | &ptm->tm_hour, &ptm->tm_min, |
33 | &end) >= 4) { | 34 | &end) >= 4 |
35 | ) { | ||
34 | /* Adjust month from 1-12 to 0-11 */ | 36 | /* Adjust month from 1-12 to 0-11 */ |
35 | ptm->tm_mon -= 1; | 37 | ptm->tm_mon -= 1; |
36 | } else | 38 | } else |
@@ -38,15 +40,13 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
38 | if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year, | 40 | if (sscanf(date_str, "%u.%u.%u-%u:%u%c", &ptm->tm_year, |
39 | &ptm->tm_mon, &ptm->tm_mday, | 41 | &ptm->tm_mon, &ptm->tm_mday, |
40 | &ptm->tm_hour, &ptm->tm_min, | 42 | &ptm->tm_hour, &ptm->tm_min, |
41 | &end) >= 5) { | 43 | &end) >= 5 |
42 | ptm->tm_year -= 1900; /* Adjust years */ | ||
43 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | ||
44 | } else | ||
45 | /* yyyy-mm-dd HH:MM */ | 44 | /* yyyy-mm-dd HH:MM */ |
46 | if (sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year, | 45 | || sscanf(date_str, "%u-%u-%u %u:%u%c", &ptm->tm_year, |
47 | &ptm->tm_mon, &ptm->tm_mday, | 46 | &ptm->tm_mon, &ptm->tm_mday, |
48 | &ptm->tm_hour, &ptm->tm_min, | 47 | &ptm->tm_hour, &ptm->tm_min, |
49 | &end) >= 5) { | 48 | &end) >= 5 |
49 | ) { | ||
50 | ptm->tm_year -= 1900; /* Adjust years */ | 50 | ptm->tm_year -= 1900; /* Adjust years */ |
51 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | 51 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
52 | } else | 52 | } else |
@@ -58,7 +58,6 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
58 | return; /* don't fall through to end == ":" check */ | 58 | return; /* don't fall through to end == ":" check */ |
59 | } else | 59 | } else |
60 | #endif | 60 | #endif |
61 | //TODO: coreutils 6.9 also accepts "yyyy-mm-dd HH" (no minutes) | ||
62 | { | 61 | { |
63 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); | 62 | bb_error_msg_and_die(bb_msg_invalid_date, date_str); |
64 | } | 63 | } |
@@ -68,7 +67,21 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
68 | end = '\0'; | 67 | end = '\0'; |
69 | /* else end != NUL and we error out */ | 68 | /* else end != NUL and we error out */ |
70 | } | 69 | } |
71 | } else if (date_str[0] == '@') { | 70 | } else |
71 | /* yyyy-mm-dd HH */ | ||
72 | if (sscanf(date_str, "%u-%u-%u %u%c", &ptm->tm_year, | ||
73 | &ptm->tm_mon, &ptm->tm_mday, | ||
74 | &ptm->tm_hour, | ||
75 | &end) >= 4 | ||
76 | /* yyyy-mm-dd */ | ||
77 | || sscanf(date_str, "%u-%u-%u%c", &ptm->tm_year, | ||
78 | &ptm->tm_mon, &ptm->tm_mday, | ||
79 | &end) >= 3 | ||
80 | ) { | ||
81 | ptm->tm_year -= 1900; /* Adjust years */ | ||
82 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | ||
83 | } else | ||
84 | if (date_str[0] == '@') { | ||
72 | time_t t = bb_strtol(date_str + 1, NULL, 10); | 85 | time_t t = bb_strtol(date_str + 1, NULL, 10); |
73 | if (!errno) { | 86 | if (!errno) { |
74 | struct tm *lt = localtime(&t); | 87 | struct tm *lt = localtime(&t); |
diff --git a/libbb/unicode.c b/libbb/unicode.c index 99dc1dfa6..9c4da50d3 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
@@ -28,19 +28,37 @@ void FAST_FUNC reinit_unicode(const char *LANG) | |||
28 | static const char unicode_0x394[] = { 0xce, 0x94, 0 }; | 28 | static const char unicode_0x394[] = { 0xce, 0x94, 0 }; |
29 | size_t width; | 29 | size_t width; |
30 | 30 | ||
31 | /* We pass "" instead of "C" because some libc's have | ||
32 | * non-ASCII default locale for setlocale("") call | ||
33 | * (this allows users of such libc to have Unicoded | ||
34 | * system without having to mess with env). | ||
35 | * | ||
36 | * We set LC_CTYPE because (a) we may be called with $LC_CTYPE | ||
37 | * value in LANG, not with $LC_ALL, (b) internationalized | ||
38 | * LC_NUMERIC and LC_TIME are more PITA than benefit | ||
39 | * (for one, some utilities have hard time with comma | ||
40 | * used as a fractional separator). | ||
41 | */ | ||
31 | //TODO: avoid repeated calls by caching last string? | 42 | //TODO: avoid repeated calls by caching last string? |
32 | setlocale(LC_ALL, (LANG && LANG[0]) ? LANG : "C"); | 43 | setlocale(LC_CTYPE, LANG ? LANG : ""); |
33 | 44 | ||
34 | /* In unicode, this is a one character string */ | 45 | /* In unicode, this is a one character string */ |
35 | // can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused | 46 | width = unicode_strlen(unicode_0x394); |
36 | width = mbstowcs(NULL, unicode_0x394, INT_MAX); | ||
37 | unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF); | 47 | unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF); |
38 | } | 48 | } |
39 | 49 | ||
40 | void FAST_FUNC init_unicode(void) | 50 | void FAST_FUNC init_unicode(void) |
41 | { | 51 | { |
42 | if (unicode_status == UNICODE_UNKNOWN) | 52 | /* Some people set only $LC_CTYPE, not $LC_ALL, because they want |
43 | reinit_unicode(getenv("LANG")); | 53 | * only Unicode to be activated on their system, not the whole |
54 | * shebang of wrong decimal points, strange date formats and so on. | ||
55 | */ | ||
56 | if (unicode_status == UNICODE_UNKNOWN) { | ||
57 | char *s = getenv("LC_ALL"); | ||
58 | if (!s) s = getenv("LC_CTYPE"); | ||
59 | if (!s) s = getenv("LANG"); | ||
60 | reinit_unicode(s); | ||
61 | } | ||
44 | } | 62 | } |
45 | 63 | ||
46 | #else | 64 | #else |
@@ -58,8 +76,12 @@ void FAST_FUNC reinit_unicode(const char *LANG) | |||
58 | 76 | ||
59 | void FAST_FUNC init_unicode(void) | 77 | void FAST_FUNC init_unicode(void) |
60 | { | 78 | { |
61 | if (unicode_status == UNICODE_UNKNOWN) | 79 | if (unicode_status == UNICODE_UNKNOWN) { |
62 | reinit_unicode(getenv("LANG")); | 80 | char *s = getenv("LC_ALL"); |
81 | if (!s) s = getenv("LC_CTYPE"); | ||
82 | if (!s) s = getenv("LANG"); | ||
83 | reinit_unicode(s); | ||
84 | } | ||
63 | } | 85 | } |
64 | # endif | 86 | # endif |
65 | 87 | ||
@@ -963,7 +985,6 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) | |||
963 | 985 | ||
964 | /* The rest is mostly same for libc and for "homegrown" support */ | 986 | /* The rest is mostly same for libc and for "homegrown" support */ |
965 | 987 | ||
966 | #if 0 // UNUSED | ||
967 | size_t FAST_FUNC unicode_strlen(const char *string) | 988 | size_t FAST_FUNC unicode_strlen(const char *string) |
968 | { | 989 | { |
969 | size_t width = mbstowcs(NULL, string, INT_MAX); | 990 | size_t width = mbstowcs(NULL, string, INT_MAX); |
@@ -971,7 +992,6 @@ size_t FAST_FUNC unicode_strlen(const char *string) | |||
971 | return strlen(string); | 992 | return strlen(string); |
972 | return width; | 993 | return width; |
973 | } | 994 | } |
974 | #endif | ||
975 | 995 | ||
976 | size_t FAST_FUNC unicode_strwidth(const char *string) | 996 | size_t FAST_FUNC unicode_strwidth(const char *string) |
977 | { | 997 | { |
diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 62bbe53e7..6f4e023bb 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c | |||
@@ -68,3 +68,10 @@ uint16_t FAST_FUNC xatou16(const char *numstr) | |||
68 | { | 68 | { |
69 | return xatou_range(numstr, 0, 0xffff); | 69 | return xatou_range(numstr, 0, 0xffff); |
70 | } | 70 | } |
71 | |||
72 | const struct suffix_mult bkm_suffixes[] = { | ||
73 | { "b", 512 }, | ||
74 | { "k", 1024 }, | ||
75 | { "m", 1024*1024 }, | ||
76 | { "", 0 } | ||
77 | }; | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 05aa07ce8..a70683241 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -541,13 +541,11 @@ int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp) | |||
541 | 541 | ||
542 | char* FAST_FUNC xmalloc_ttyname(int fd) | 542 | char* FAST_FUNC xmalloc_ttyname(int fd) |
543 | { | 543 | { |
544 | char *buf = xzalloc(128); | 544 | char buf[128]; |
545 | int r = ttyname_r(fd, buf, 127); | 545 | int r = ttyname_r(fd, buf, sizeof(buf) - 1); |
546 | if (r) { | 546 | if (r) |
547 | free(buf); | 547 | return NULL; |
548 | buf = NULL; | 548 | return xstrdup(buf); |
549 | } | ||
550 | return buf; | ||
551 | } | 549 | } |
552 | 550 | ||
553 | void FAST_FUNC generate_uuid(uint8_t *buf) | 551 | void FAST_FUNC generate_uuid(uint8_t *buf) |