aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2013-08-27 16:10:53 +0100
committerRon Yorston <rmy@pobox.com>2013-08-27 16:10:53 +0100
commit3fd34651ea72ea1c335d3170f234cb0517fd897f (patch)
tree36e8fc40cffd464ffda4759020777dd3ca23ca31 /libbb
parente3ac39098326de084a805d0dd31db9666b734f20 (diff)
parentd6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff)
downloadbusybox-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.src2
-rw-r--r--libbb/appletlib.c2
-rw-r--r--libbb/bb_askpass.c4
-rw-r--r--libbb/create_icmp6_socket.c38
-rw-r--r--libbb/create_icmp_socket.c36
-rw-r--r--libbb/hash_md5_sha.c6
-rw-r--r--libbb/in_ether.c58
-rw-r--r--libbb/lineedit.c82
-rw-r--r--libbb/printable.c24
-rw-r--r--libbb/time.c33
-rw-r--r--libbb/unicode.c38
-rw-r--r--libbb/xatonum.c7
-rw-r--r--libbb/xfuncs_printf.c12
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
27lib-y += copy_file.o 27lib-y += copy_file.o
28lib-y += copyfd.o 28lib-y += copyfd.o
29lib-y += crc32.o 29lib-y += crc32.o
30lib-y += create_icmp6_socket.o
31lib-y += create_icmp_socket.o
32lib-y += default_error_retval.o 30lib-y += default_error_retval.o
33lib-y += device_open.o 31lib-y += device_open.o
34lib-y += dump.o 32lib-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
14int 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
13int 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 */
16int 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
1271unsigned size_from_HISTFILESIZE(const char *hp) 1279unsigned 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 */
1335void 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
1766static void parse_and_put_prompt(const char *prmt_ptr) 1786static 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
1773static void parse_and_put_prompt(const char *prmt_ptr) 1795static 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
36void 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
40void FAST_FUNC init_unicode(void) 50void 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
59void FAST_FUNC init_unicode(void) 77void 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
967size_t FAST_FUNC unicode_strlen(const char *string) 988size_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
976size_t FAST_FUNC unicode_strwidth(const char *string) 996size_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
72const 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
542char* FAST_FUNC xmalloc_ttyname(int fd) 542char* 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
553void FAST_FUNC generate_uuid(uint8_t *buf) 551void FAST_FUNC generate_uuid(uint8_t *buf)