diff options
author | Ron Yorston <rmy@pobox.com> | 2021-01-14 13:28:49 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-01-14 13:28:49 +0000 |
commit | 89963b524d211e1aec12b72b3725be05ee95c8cf (patch) | |
tree | 48590aef62b7ee7686b7898256f29def8d9c50b9 /libbb | |
parent | 9aa5a829070392c2ac6494d0c4e674c0c2bc7dab (diff) | |
parent | 2b7c1aa92c68524559a2067609d09309d5c09adc (diff) | |
download | busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.gz busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.tar.bz2 busybox-w32-89963b524d211e1aec12b72b3725be05ee95c8cf.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/bb_do_delay.c | 59 | ||||
-rw-r--r-- | libbb/capability.c | 2 | ||||
-rw-r--r-- | libbb/copyfd.c | 5 | ||||
-rw-r--r-- | libbb/die_if_bad_username.c | 4 | ||||
-rw-r--r-- | libbb/duration.c | 2 | ||||
-rw-r--r-- | libbb/executable.c | 9 | ||||
-rw-r--r-- | libbb/hash_md5_sha.c | 22 | ||||
-rw-r--r-- | libbb/lineedit.c | 129 | ||||
-rw-r--r-- | libbb/loop.c | 139 | ||||
-rw-r--r-- | libbb/mode_string.c | 2 | ||||
-rw-r--r-- | libbb/platform.c | 4 | ||||
-rw-r--r-- | libbb/procps.c | 51 | ||||
-rw-r--r-- | libbb/pw_encrypt.c | 15 | ||||
-rw-r--r-- | libbb/pw_encrypt_des.c | 40 | ||||
-rw-r--r-- | libbb/rtc.c | 6 | ||||
-rw-r--r-- | libbb/run_shell.c | 32 | ||||
-rw-r--r-- | libbb/speed_table.c | 2 | ||||
-rw-r--r-- | libbb/time.c | 13 | ||||
-rw-r--r-- | libbb/unicode.c | 22 | ||||
-rw-r--r-- | libbb/uuencode.c | 235 | ||||
-rw-r--r-- | libbb/xatonum.c | 6 | ||||
-rw-r--r-- | libbb/xconnect.c | 20 | ||||
-rw-r--r-- | libbb/xfuncs.c | 12 | ||||
-rw-r--r-- | libbb/xfuncs_printf.c | 71 |
24 files changed, 543 insertions, 359 deletions
diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c index 65541704b..9a84fa24b 100644 --- a/libbb/bb_do_delay.c +++ b/libbb/bb_do_delay.c | |||
@@ -8,13 +8,60 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | void FAST_FUNC bb_do_delay(int seconds) | 11 | /* void FAST_FUNC bb_do_delay(unsigned seconds) { ... } - no users yet */ |
12 | |||
13 | #ifndef LOGIN_FAIL_DELAY | ||
14 | #define LOGIN_FAIL_DELAY 3 | ||
15 | #endif | ||
16 | void FAST_FUNC pause_after_failed_login(void) | ||
12 | { | 17 | { |
13 | time_t start, now; | 18 | #if 0 /* over-engineered madness */ |
19 | time_t end, diff; | ||
14 | 20 | ||
15 | start = time(NULL); | 21 | end = time(NULL) + LOGIN_FAIL_DELAY; |
22 | diff = LOGIN_FAIL_DELAY; | ||
16 | do { | 23 | do { |
17 | sleep(seconds); | 24 | sleep(diff); |
18 | now = time(NULL); | 25 | diff = end - time(NULL); |
19 | } while ((now - start) < seconds); | 26 | } while (diff > 0); |
27 | #else | ||
28 | sleep(LOGIN_FAIL_DELAY); | ||
29 | #endif | ||
30 | } | ||
31 | |||
32 | void FAST_FUNC sleep1(void) | ||
33 | { | ||
34 | sleep(1); | ||
35 | } | ||
36 | |||
37 | void FAST_FUNC msleep(unsigned ms) | ||
38 | { | ||
39 | #if 0 | ||
40 | /* 1. usleep(n) is not guaranteed by standards to accept n >= 1000000 | ||
41 | * 2. multiplication in usleep(ms * 1000) can overflow if ms > 4294967 | ||
42 | * (sleep of ~71.5 minutes) | ||
43 | * Let's play safe and loop: | ||
44 | */ | ||
45 | while (ms > 500) { | ||
46 | usleep(500000); | ||
47 | ms -= 500; | ||
48 | } | ||
49 | usleep(ms * 1000); | ||
50 | #else | ||
51 | //usleep is often implemented as a call to nanosleep. | ||
52 | //Simply do the same to implement msleep. | ||
53 | //it's marginally larger, but wakes your CPU less often: | ||
54 | //function old new delta | ||
55 | //msleep 45 52 +7 | ||
56 | struct timespec ts; | ||
57 | ts.tv_sec = ms / 1000; | ||
58 | ts.tv_nsec = (ms % 1000) * 1000000; | ||
59 | /* | ||
60 | * If a signal has non-default handler, nanosleep returns early. | ||
61 | * Our version of msleep doesn't return early | ||
62 | * if interrupted by such signals: | ||
63 | */ | ||
64 | while (nanosleep(&ts, &ts) != 0) | ||
65 | continue; | ||
66 | #endif | ||
20 | } | 67 | } |
diff --git a/libbb/capability.c b/libbb/capability.c index 23afd8eb9..e3c252a5a 100644 --- a/libbb/capability.c +++ b/libbb/capability.c | |||
@@ -17,7 +17,7 @@ extern int capget(cap_user_header_t header, const cap_user_data_t data); | |||
17 | // This way, libcap needs not be installed in build environment. | 17 | // This way, libcap needs not be installed in build environment. |
18 | #include "libbb.h" | 18 | #include "libbb.h" |
19 | 19 | ||
20 | static const char *const capabilities[] = { | 20 | static const char *const capabilities[] ALIGN_PTR = { |
21 | "chown", | 21 | "chown", |
22 | "dac_override", | 22 | "dac_override", |
23 | "dac_read_search", | 23 | "dac_read_search", |
diff --git a/libbb/copyfd.c b/libbb/copyfd.c index d41fd10f0..7f9d92ea9 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c | |||
@@ -75,10 +75,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) | |||
75 | goto use_small_buf; | 75 | goto use_small_buf; |
76 | /* We want page-aligned buffer, just in case kernel is clever | 76 | /* We want page-aligned buffer, just in case kernel is clever |
77 | * and can do page-aligned io more efficiently */ | 77 | * and can do page-aligned io more efficiently */ |
78 | buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, | 78 | buffer = mmap_anon(CONFIG_FEATURE_COPYBUF_KB * 1024); |
79 | PROT_READ | PROT_WRITE, | ||
80 | MAP_PRIVATE | MAP_ANON, | ||
81 | /* ignored: */ -1, 0); | ||
82 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; | 79 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; |
83 | if (buffer == MAP_FAILED) { | 80 | if (buffer == MAP_FAILED) { |
84 | use_small_buf: | 81 | use_small_buf: |
diff --git a/libbb/die_if_bad_username.c b/libbb/die_if_bad_username.c index e5e1160c4..d05dc74c5 100644 --- a/libbb/die_if_bad_username.c +++ b/libbb/die_if_bad_username.c | |||
@@ -8,6 +8,10 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | #ifndef LOGIN_NAME_MAX | ||
12 | #define LOGIN_NAME_MAX 256 | ||
13 | #endif | ||
14 | |||
11 | /* To avoid problems, the username should consist only of | 15 | /* To avoid problems, the username should consist only of |
12 | * letters, digits, underscores, periods, at signs and dashes, | 16 | * letters, digits, underscores, periods, at signs and dashes, |
13 | * and not start with a dash (as defined by IEEE Std 1003.1-2001). | 17 | * and not start with a dash (as defined by IEEE Std 1003.1-2001). |
diff --git a/libbb/duration.c b/libbb/duration.c index 22b209f4d..086da15fb 100644 --- a/libbb/duration.c +++ b/libbb/duration.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include "libbb.h" | 22 | #include "libbb.h" |
23 | 23 | ||
24 | static const struct suffix_mult duration_suffixes[] = { | 24 | static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = { |
25 | { "s", 1 }, | 25 | { "s", 1 }, |
26 | { "m", 60 }, | 26 | { "m", 60 }, |
27 | { "h", 60*60 }, | 27 | { "h", 60*60 }, |
diff --git a/libbb/executable.c b/libbb/executable.c index f549a7aae..bd3022b13 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -100,12 +100,3 @@ void FAST_FUNC BB_EXECVP_or_die(char **argv) | |||
100 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; | 100 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; |
101 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 101 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); |
102 | } | 102 | } |
103 | |||
104 | /* Typical idiom for applets which exec *optional* PROG [ARGS] */ | ||
105 | void FAST_FUNC exec_prog_or_SHELL(char **argv) | ||
106 | { | ||
107 | if (argv[0]) { | ||
108 | BB_EXECVP_or_die(argv); | ||
109 | } | ||
110 | run_shell(getenv("SHELL"), /*login:*/ 1, NULL); | ||
111 | } | ||
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index d8f210173..e0db8ce67 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c | |||
@@ -111,7 +111,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx) | |||
111 | They are defined in RFC 1321 as | 111 | They are defined in RFC 1321 as |
112 | T[i] = (int)(2^32 * fabs(sin(i))), i=1..64 | 112 | T[i] = (int)(2^32 * fabs(sin(i))), i=1..64 |
113 | */ | 113 | */ |
114 | static const uint32_t C_array[] = { | 114 | static const uint32_t C_array[] ALIGN4 = { |
115 | /* round 1 */ | 115 | /* round 1 */ |
116 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | 116 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, |
117 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | 117 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, |
@@ -492,7 +492,7 @@ unsigned FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) | |||
492 | 492 | ||
493 | static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) | 493 | static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) |
494 | { | 494 | { |
495 | static const uint32_t rconsts[] = { | 495 | static const uint32_t rconsts[] ALIGN4 = { |
496 | 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 | 496 | 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 |
497 | }; | 497 | }; |
498 | int i, j; | 498 | int i, j; |
@@ -567,7 +567,7 @@ typedef uint64_t sha_K_int; | |||
567 | typedef uint32_t sha_K_int; | 567 | typedef uint32_t sha_K_int; |
568 | # define K(v) (uint32_t)(v >> 32) | 568 | # define K(v) (uint32_t)(v >> 32) |
569 | #endif | 569 | #endif |
570 | static const sha_K_int sha_K[] = { | 570 | static const sha_K_int sha_K[] ALIGN8 = { |
571 | K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL), | 571 | K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL), |
572 | K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL), | 572 | K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL), |
573 | K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL), | 573 | K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL), |
@@ -760,7 +760,7 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) | |||
760 | ctx->process_block = sha1_process_block64; | 760 | ctx->process_block = sha1_process_block64; |
761 | } | 761 | } |
762 | 762 | ||
763 | static const uint32_t init256[] = { | 763 | static const uint32_t init256[] ALIGN4 = { |
764 | 0, | 764 | 0, |
765 | 0, | 765 | 0, |
766 | 0x6a09e667, | 766 | 0x6a09e667, |
@@ -773,7 +773,7 @@ static const uint32_t init256[] = { | |||
773 | 0x5be0cd19, | 773 | 0x5be0cd19, |
774 | }; | 774 | }; |
775 | #if NEED_SHA512 | 775 | #if NEED_SHA512 |
776 | static const uint32_t init512_lo[] = { | 776 | static const uint32_t init512_lo[] ALIGN4 = { |
777 | 0, | 777 | 0, |
778 | 0, | 778 | 0, |
779 | 0xf3bcc908, | 779 | 0xf3bcc908, |
@@ -1009,7 +1009,7 @@ static void sha3_process_block72(uint64_t *state) | |||
1009 | 1009 | ||
1010 | #if OPTIMIZE_SHA3_FOR_32 | 1010 | #if OPTIMIZE_SHA3_FOR_32 |
1011 | /* | 1011 | /* |
1012 | static const uint32_t IOTA_CONST_0[NROUNDS] = { | 1012 | static const uint32_t IOTA_CONST_0[NROUNDS] ALIGN4 = { |
1013 | 0x00000001UL, | 1013 | 0x00000001UL, |
1014 | 0x00000000UL, | 1014 | 0x00000000UL, |
1015 | 0x00000000UL, | 1015 | 0x00000000UL, |
@@ -1038,7 +1038,7 @@ static void sha3_process_block72(uint64_t *state) | |||
1038 | ** bits are in lsb: 0101 0000 1111 0100 1111 0001 | 1038 | ** bits are in lsb: 0101 0000 1111 0100 1111 0001 |
1039 | */ | 1039 | */ |
1040 | uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1); | 1040 | uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1); |
1041 | static const uint32_t IOTA_CONST_1[NROUNDS] = { | 1041 | static const uint32_t IOTA_CONST_1[NROUNDS] ALIGN4 = { |
1042 | 0x00000000UL, | 1042 | 0x00000000UL, |
1043 | 0x00000089UL, | 1043 | 0x00000089UL, |
1044 | 0x8000008bUL, | 1044 | 0x8000008bUL, |
@@ -1174,7 +1174,7 @@ static void sha3_process_block72(uint64_t *state) | |||
1174 | combine_halves(state); | 1174 | combine_halves(state); |
1175 | #else | 1175 | #else |
1176 | /* Native 64-bit algorithm */ | 1176 | /* Native 64-bit algorithm */ |
1177 | static const uint16_t IOTA_CONST[NROUNDS] = { | 1177 | static const uint16_t IOTA_CONST[NROUNDS] ALIGN2 = { |
1178 | /* Elements should be 64-bit, but top half is always zero | 1178 | /* Elements should be 64-bit, but top half is always zero |
1179 | * or 0x80000000. We encode 63rd bits in a separate word below. | 1179 | * or 0x80000000. We encode 63rd bits in a separate word below. |
1180 | * Same is true for 31th bits, which lets us use 16-bit table | 1180 | * Same is true for 31th bits, which lets us use 16-bit table |
@@ -1210,15 +1210,15 @@ static void sha3_process_block72(uint64_t *state) | |||
1210 | /* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */ | 1210 | /* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */ |
1211 | const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00); | 1211 | const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00); |
1212 | 1212 | ||
1213 | static const uint8_t ROT_CONST[24] = { | 1213 | static const uint8_t ROT_CONST[24] ALIGN1 = { |
1214 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, | 1214 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, |
1215 | 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, | 1215 | 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, |
1216 | }; | 1216 | }; |
1217 | static const uint8_t PI_LANE[24] = { | 1217 | static const uint8_t PI_LANE[24] ALIGN1 = { |
1218 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, | 1218 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, |
1219 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, | 1219 | 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, |
1220 | }; | 1220 | }; |
1221 | /*static const uint8_t MOD5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ | 1221 | /*static const uint8_t MOD5[10] ALIGN1 = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ |
1222 | 1222 | ||
1223 | unsigned x; | 1223 | unsigned x; |
1224 | unsigned round; | 1224 | unsigned round; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b35da1874..f3cbc512c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -57,12 +57,23 @@ | |||
57 | #if ENABLE_FEATURE_EDITING | 57 | #if ENABLE_FEATURE_EDITING |
58 | 58 | ||
59 | 59 | ||
60 | #if !ENABLE_SHELL_ASH && !ENABLE_SHELL_HUSH | ||
61 | /* so far only shells use these features */ | ||
62 | # undef ENABLE_FEATURE_EDITING_FANCY_PROMPT | ||
63 | # undef ENABLE_FEATURE_TAB_COMPLETION | ||
64 | # undef ENABLE_FEATURE_USERNAME_COMPLETION | ||
65 | # define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0 | ||
66 | # define ENABLE_FEATURE_TAB_COMPLETION 0 | ||
67 | # define ENABLE_FEATURE_USERNAME_COMPLETION 0 | ||
68 | #endif | ||
69 | |||
70 | |||
60 | #define ENABLE_USERNAME_OR_HOMEDIR \ | 71 | #define ENABLE_USERNAME_OR_HOMEDIR \ |
61 | (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) | 72 | (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) |
62 | #define IF_USERNAME_OR_HOMEDIR(...) | ||
63 | #if ENABLE_USERNAME_OR_HOMEDIR | 73 | #if ENABLE_USERNAME_OR_HOMEDIR |
64 | # undef IF_USERNAME_OR_HOMEDIR | ||
65 | # define IF_USERNAME_OR_HOMEDIR(...) __VA_ARGS__ | 74 | # define IF_USERNAME_OR_HOMEDIR(...) __VA_ARGS__ |
75 | #else | ||
76 | # define IF_USERNAME_OR_HOMEDIR(...) /*nothing*/ | ||
66 | #endif | 77 | #endif |
67 | 78 | ||
68 | 79 | ||
@@ -205,9 +216,6 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; | |||
205 | #define INIT_S() do { \ | 216 | #define INIT_S() do { \ |
206 | (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ | 217 | (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ |
207 | barrier(); \ | 218 | barrier(); \ |
208 | cmdedit_termw = 80; \ | ||
209 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \ | ||
210 | IF_FEATURE_EDITING_VI(delptr = delbuf;) \ | ||
211 | } while (0) | 219 | } while (0) |
212 | 220 | ||
213 | static void deinit_S(void) | 221 | static void deinit_S(void) |
@@ -796,16 +804,18 @@ enum { | |||
796 | FIND_FILE_ONLY = 2, | 804 | FIND_FILE_ONLY = 2, |
797 | }; | 805 | }; |
798 | 806 | ||
799 | static int path_parse(char ***p) | 807 | static unsigned path_parse(char ***p) |
800 | { | 808 | { |
801 | int npth; | 809 | unsigned npth; |
802 | const char *pth; | 810 | const char *pth; |
803 | char *tmp; | 811 | char *tmp; |
804 | char **res; | 812 | char **res; |
805 | 813 | ||
814 | # if EDITING_HAS_path_lookup | ||
806 | if (state->flags & WITH_PATH_LOOKUP) | 815 | if (state->flags & WITH_PATH_LOOKUP) |
807 | pth = state->path_lookup; | 816 | pth = state->path_lookup; |
808 | else | 817 | else |
818 | # endif | ||
809 | pth = getenv("PATH"); | 819 | pth = getenv("PATH"); |
810 | 820 | ||
811 | /* PATH="" or PATH=":"? */ | 821 | /* PATH="" or PATH=":"? */ |
@@ -824,7 +834,7 @@ static int path_parse(char ***p) | |||
824 | npth++; | 834 | npth++; |
825 | } | 835 | } |
826 | 836 | ||
827 | *p = res = xmalloc(npth * sizeof(res[0])); | 837 | *p = res = xzalloc((npth + 1) * sizeof(res[0])); |
828 | res[0] = tmp = xstrdup(pth); | 838 | res[0] = tmp = xstrdup(pth); |
829 | npth = 1; | 839 | npth = 1; |
830 | while (1) { | 840 | while (1) { |
@@ -836,6 +846,8 @@ static int path_parse(char ***p) | |||
836 | break; /* :<empty> */ | 846 | break; /* :<empty> */ |
837 | res[npth++] = tmp; | 847 | res[npth++] = tmp; |
838 | } | 848 | } |
849 | /* special case: "match subdirectories of the current directory" */ | ||
850 | /*res[npth++] = NULL; - filled by xzalloc() */ | ||
839 | return npth; | 851 | return npth; |
840 | } | 852 | } |
841 | 853 | ||
@@ -846,49 +858,49 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
846 | { | 858 | { |
847 | char *path1[1]; | 859 | char *path1[1]; |
848 | char **paths = path1; | 860 | char **paths = path1; |
849 | int npaths; | 861 | unsigned npaths; |
850 | int i; | 862 | unsigned i; |
851 | unsigned pf_len; | 863 | unsigned baselen; |
852 | const char *pfind; | 864 | const char *basecmd; |
853 | char *dirbuf = NULL; | 865 | char *dirbuf = NULL; |
854 | 866 | ||
855 | npaths = 1; | 867 | npaths = 1; |
856 | path1[0] = (char*)"."; | 868 | path1[0] = (char*)"."; |
857 | 869 | ||
858 | pfind = strrchr(command, '/'); | 870 | basecmd = strrchr(command, '/'); |
859 | #if ENABLE_PLATFORM_MINGW32 | 871 | #if ENABLE_PLATFORM_MINGW32 |
860 | if (!pfind && has_dos_drive_prefix(command) && command[2] != '\0') { | 872 | if (!basecmd && has_dos_drive_prefix(command) && command[2] != '\0') { |
861 | char buffer[PATH_MAX]; | 873 | char buffer[PATH_MAX]; |
862 | 874 | ||
863 | /* path is of form c:path with no '/' */ | 875 | /* path is of form c:path with no '/' */ |
864 | if (get_drive_cwd(command, buffer, PATH_MAX)) { | 876 | if (get_drive_cwd(command, buffer, PATH_MAX)) { |
865 | pfind = command + 2; | 877 | basecmd = command + 2; |
866 | path1[0] = dirbuf = xstrdup(buffer); | 878 | path1[0] = dirbuf = xstrdup(buffer); |
867 | } | 879 | } |
868 | } else | 880 | } else |
869 | #endif | 881 | #endif |
870 | if (!pfind) { | 882 | if (!basecmd) { |
871 | if (type == FIND_EXE_ONLY) | 883 | if (type == FIND_EXE_ONLY) |
872 | npaths = path_parse(&paths); | 884 | npaths = path_parse(&paths); |
873 | pfind = command; | 885 | basecmd = command; |
874 | } else { | 886 | } else { |
875 | /* point to 'l' in "..../last_component" */ | 887 | /* point to 'l' in "..../last_component" */ |
876 | pfind++; | 888 | basecmd++; |
877 | /* dirbuf = ".../.../.../" */ | 889 | /* dirbuf = ".../.../.../" */ |
878 | dirbuf = xstrndup(command, pfind - command); | 890 | dirbuf = xstrndup(command, basecmd - command); |
879 | # if ENABLE_FEATURE_USERNAME_COMPLETION | 891 | # if ENABLE_FEATURE_USERNAME_COMPLETION |
880 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ | 892 | if (dirbuf[0] == '~') /* ~/... or ~user/... */ |
881 | dirbuf = username_path_completion(dirbuf); | 893 | dirbuf = username_path_completion(dirbuf); |
882 | # endif | 894 | # endif |
883 | path1[0] = dirbuf; | 895 | path1[0] = dirbuf; |
884 | } | 896 | } |
885 | pf_len = strlen(pfind); | 897 | baselen = strlen(basecmd); |
886 | 898 | ||
887 | if (type == FIND_EXE_ONLY && !dirbuf) { | 899 | if (type == FIND_EXE_ONLY && !dirbuf) { |
888 | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 | 900 | # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 |
889 | const char *p = applet_names; | 901 | const char *p = applet_names; |
890 | while (*p) { | 902 | while (*p) { |
891 | if (strncmp(pfind, p, pf_len) == 0) | 903 | if (strncmp(basecmd, p, baselen) == 0) |
892 | add_match(xstrdup(p)); | 904 | add_match(xstrdup(p)); |
893 | while (*p++ != '\0') | 905 | while (*p++ != '\0') |
894 | continue; | 906 | continue; |
@@ -901,7 +913,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
901 | const char *b = state->get_exe_name(i++); | 913 | const char *b = state->get_exe_name(i++); |
902 | if (!b) | 914 | if (!b) |
903 | break; | 915 | break; |
904 | if (strncmp(pfind, b, pf_len) == 0) | 916 | if (strncmp(basecmd, b, baselen) == 0) |
905 | add_match(xstrdup(b)); | 917 | add_match(xstrdup(b)); |
906 | } | 918 | } |
907 | } | 919 | } |
@@ -913,9 +925,20 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
913 | struct dirent *next; | 925 | struct dirent *next; |
914 | struct stat st; | 926 | struct stat st; |
915 | char *found; | 927 | char *found; |
928 | #if ENABLE_PLATFORM_MINGW32 | ||
929 | char *lpath; | ||
930 | #endif | ||
931 | |||
932 | if (paths[i] == NULL) { /* path_parse()'s last component? */ | ||
933 | /* in PATH completion, current dir's subdir names | ||
934 | * can be completions (but only subdirs, not files). | ||
935 | */ | ||
936 | type = FIND_DIR_ONLY; | ||
937 | paths[i] = (char *)"."; | ||
938 | } | ||
916 | 939 | ||
917 | #if ENABLE_PLATFORM_MINGW32 | 940 | #if ENABLE_PLATFORM_MINGW32 |
918 | char *lpath = auto_string(alloc_system_drive(paths[i])); | 941 | lpath = auto_string(alloc_system_drive(paths[i])); |
919 | dir = opendir(lpath); | 942 | dir = opendir(lpath); |
920 | #else | 943 | #else |
921 | dir = opendir(paths[i]); | 944 | dir = opendir(paths[i]); |
@@ -928,10 +951,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
928 | const char *name_found = next->d_name; | 951 | const char *name_found = next->d_name; |
929 | 952 | ||
930 | /* .../<tab>: bash 3.2.0 shows dotfiles, but not . and .. */ | 953 | /* .../<tab>: bash 3.2.0 shows dotfiles, but not . and .. */ |
931 | if (!pfind[0] && DOT_OR_DOTDOT(name_found)) | 954 | if (!basecmd[0] && DOT_OR_DOTDOT(name_found)) |
932 | continue; | 955 | continue; |
933 | /* match? */ | 956 | /* match? */ |
934 | if (!is_prefixed_with(name_found, pfind)) | 957 | if (strncmp(basecmd, name_found, baselen) != 0) |
935 | continue; /* no */ | 958 | continue; /* no */ |
936 | 959 | ||
937 | #if ENABLE_PLATFORM_MINGW32 | 960 | #if ENABLE_PLATFORM_MINGW32 |
@@ -957,6 +980,9 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
957 | strcpy(found, name_found); | 980 | strcpy(found, name_found); |
958 | 981 | ||
959 | if (S_ISDIR(st.st_mode)) { | 982 | if (S_ISDIR(st.st_mode)) { |
983 | /* skip directories if searching PATH */ | ||
984 | if (type == FIND_EXE_ONLY && !dirbuf) | ||
985 | goto cont; | ||
960 | /* name is a directory, add slash */ | 986 | /* name is a directory, add slash */ |
961 | found[len] = '/'; | 987 | found[len] = '/'; |
962 | found[len + 1] = '\0'; | 988 | found[len + 1] = '\0'; |
@@ -980,7 +1006,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) | |||
980 | } | 1006 | } |
981 | free(dirbuf); | 1007 | free(dirbuf); |
982 | 1008 | ||
983 | return pf_len; | 1009 | return baselen; |
984 | } | 1010 | } |
985 | 1011 | ||
986 | /* build_match_prefix: | 1012 | /* build_match_prefix: |
@@ -1492,15 +1518,19 @@ void FAST_FUNC show_history(const line_input_t *st) | |||
1492 | printf("%4d %s\n", i, st->history[i]); | 1518 | printf("%4d %s\n", i, st->history[i]); |
1493 | } | 1519 | } |
1494 | 1520 | ||
1521 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | ||
1495 | void FAST_FUNC free_line_input_t(line_input_t *n) | 1522 | void FAST_FUNC free_line_input_t(line_input_t *n) |
1496 | { | 1523 | { |
1497 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1524 | if (n) { |
1498 | int i = n->cnt_history; | 1525 | int i = n->cnt_history; |
1499 | while (i > 0) | 1526 | while (i > 0) |
1500 | free(n->history[--i]); | 1527 | free(n->history[--i]); |
1501 | #endif | 1528 | free(n); |
1502 | free(n); | 1529 | } |
1503 | } | 1530 | } |
1531 | # else | ||
1532 | /* #defined to free() in libbb.h */ | ||
1533 | # endif | ||
1504 | 1534 | ||
1505 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1535 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY |
1506 | /* We try to ensure that concurrent additions to the history | 1536 | /* We try to ensure that concurrent additions to the history |
@@ -1581,7 +1611,7 @@ void save_history(line_input_t *st) | |||
1581 | { | 1611 | { |
1582 | FILE *fp; | 1612 | FILE *fp; |
1583 | 1613 | ||
1584 | if (!st->hist_file) | 1614 | if (!st || !st->hist_file) |
1585 | return; | 1615 | return; |
1586 | if (st->cnt_history <= st->cnt_history_in_file) | 1616 | if (st->cnt_history <= st->cnt_history_in_file) |
1587 | return; | 1617 | return; |
@@ -1971,9 +2001,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1971 | { | 2001 | { |
1972 | int prmt_size = 0; | 2002 | int prmt_size = 0; |
1973 | char *prmt_mem_ptr = xzalloc(1); | 2003 | char *prmt_mem_ptr = xzalloc(1); |
1974 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
1975 | char *cwd_buf = NULL; | 2004 | char *cwd_buf = NULL; |
1976 | # endif | ||
1977 | char flg_not_length = '['; | 2005 | char flg_not_length = '['; |
1978 | char cbuf[2]; | 2006 | char cbuf[2]; |
1979 | 2007 | ||
@@ -2040,11 +2068,9 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2040 | c = *prmt_ptr++; | 2068 | c = *prmt_ptr++; |
2041 | 2069 | ||
2042 | switch (c) { | 2070 | switch (c) { |
2043 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
2044 | case 'u': | 2071 | case 'u': |
2045 | pbuf = user_buf ? user_buf : (char*)""; | 2072 | pbuf = user_buf ? user_buf : (char*)""; |
2046 | break; | 2073 | break; |
2047 | # endif | ||
2048 | case 'H': | 2074 | case 'H': |
2049 | case 'h': | 2075 | case 'h': |
2050 | pbuf = free_me = safe_gethostname(); | 2076 | pbuf = free_me = safe_gethostname(); |
@@ -2062,7 +2088,6 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2062 | strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0'; | 2088 | strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0'; |
2063 | pbuf = timebuf; | 2089 | pbuf = timebuf; |
2064 | break; | 2090 | break; |
2065 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
2066 | case 'w': /* current dir */ | 2091 | case 'w': /* current dir */ |
2067 | case 'W': /* basename of cur dir */ | 2092 | case 'W': /* basename of cur dir */ |
2068 | if (!cwd_buf) { | 2093 | if (!cwd_buf) { |
@@ -2089,7 +2114,6 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2089 | if (cp) | 2114 | if (cp) |
2090 | pbuf = (char*)cp + 1; | 2115 | pbuf = (char*)cp + 1; |
2091 | break; | 2116 | break; |
2092 | # endif | ||
2093 | // bb_process_escape_sequence does this now: | 2117 | // bb_process_escape_sequence does this now: |
2094 | // case 'e': case 'E': /* \e \E = \033 */ | 2118 | // case 'e': case 'E': /* \e \E = \033 */ |
2095 | // c = '\033'; | 2119 | // c = '\033'; |
@@ -2130,10 +2154,17 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2130 | if (c == '\n') | 2154 | if (c == '\n') |
2131 | cmdedit_prmt_len = 0; | 2155 | cmdedit_prmt_len = 0; |
2132 | else if (flg_not_length != ']') { | 2156 | else if (flg_not_length != ']') { |
2133 | #if 0 /*ENABLE_UNICODE_SUPPORT*/ | 2157 | #if ENABLE_UNICODE_SUPPORT |
2134 | /* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */ | 2158 | if (n == 1) { |
2135 | /* FIXME */ | 2159 | /* Only count single-byte characters and the first of multi-byte characters */ |
2136 | cmdedit_prmt_len += unicode_strwidth(pbuf); | 2160 | if ((unsigned char)*pbuf < 0x80 /* single byte character */ |
2161 | || (unsigned char)*pbuf >= 0xc0 /* first of multi-byte characters */ | ||
2162 | ) { | ||
2163 | cmdedit_prmt_len += n; | ||
2164 | } | ||
2165 | } else { | ||
2166 | cmdedit_prmt_len += unicode_strwidth(pbuf); | ||
2167 | } | ||
2137 | #else | 2168 | #else |
2138 | cmdedit_prmt_len += n; | 2169 | cmdedit_prmt_len += n; |
2139 | #endif | 2170 | #endif |
@@ -2143,10 +2174,8 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2143 | free(free_me); | 2174 | free(free_me); |
2144 | } /* while */ | 2175 | } /* while */ |
2145 | 2176 | ||
2146 | # if ENABLE_USERNAME_OR_HOMEDIR | ||
2147 | if (cwd_buf != (char *)bb_msg_unknown) | 2177 | if (cwd_buf != (char *)bb_msg_unknown) |
2148 | free(cwd_buf); | 2178 | free(cwd_buf); |
2149 | # endif | ||
2150 | /* see comment (above this function) about multiline prompt redrawing */ | 2179 | /* see comment (above this function) about multiline prompt redrawing */ |
2151 | cmdedit_prompt = prompt_last_line = prmt_mem_ptr; | 2180 | cmdedit_prompt = prompt_last_line = prmt_mem_ptr; |
2152 | prmt_ptr = strrchr(cmdedit_prompt, '\n'); | 2181 | prmt_ptr = strrchr(cmdedit_prompt, '\n'); |
@@ -2154,7 +2183,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2154 | prompt_last_line = prmt_ptr + 1; | 2183 | prompt_last_line = prmt_ptr + 1; |
2155 | put_prompt(); | 2184 | put_prompt(); |
2156 | } | 2185 | } |
2157 | #endif | 2186 | #endif /* FEATURE_EDITING_FANCY_PROMPT */ |
2158 | 2187 | ||
2159 | #if ENABLE_FEATURE_EDITING_WINCH | 2188 | #if ENABLE_FEATURE_EDITING_WINCH |
2160 | static void cmdedit_setwidth(void) | 2189 | static void cmdedit_setwidth(void) |
@@ -2467,6 +2496,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2467 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; | 2496 | char read_key_buffer[KEYCODE_BUFFER_SIZE]; |
2468 | 2497 | ||
2469 | INIT_S(); | 2498 | INIT_S(); |
2499 | //command_len = 0; - done by INIT_S() | ||
2500 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | ||
2501 | cmdedit_termw = 80; | ||
2502 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) | ||
2503 | IF_FEATURE_EDITING_VI(delptr = delbuf;) | ||
2470 | 2504 | ||
2471 | #if !ENABLE_PLATFORM_MINGW32 | 2505 | #if !ENABLE_PLATFORM_MINGW32 |
2472 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 | 2506 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 |
@@ -2521,8 +2555,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2521 | #endif | 2555 | #endif |
2522 | 2556 | ||
2523 | /* prepare before init handlers */ | 2557 | /* prepare before init handlers */ |
2524 | cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | ||
2525 | command_len = 0; | ||
2526 | #if ENABLE_UNICODE_SUPPORT | 2558 | #if ENABLE_UNICODE_SUPPORT |
2527 | command_ps = xzalloc(maxsize * sizeof(command_ps[0])); | 2559 | command_ps = xzalloc(maxsize * sizeof(command_ps[0])); |
2528 | #else | 2560 | #else |
@@ -3005,6 +3037,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
3005 | * before it comes in. UGLY! | 3037 | * before it comes in. UGLY! |
3006 | */ | 3038 | */ |
3007 | usleep(20*1000); | 3039 | usleep(20*1000); |
3040 | // MAYBE? tcflush(STDIN_FILENO, TCIFLUSH); /* flushes data received but not read */ | ||
3008 | } | 3041 | } |
3009 | #endif | 3042 | #endif |
3010 | 3043 | ||
diff --git a/libbb/loop.c b/libbb/loop.c index 85b2724e5..cb8fa2442 100644 --- a/libbb/loop.c +++ b/libbb/loop.c | |||
@@ -98,9 +98,7 @@ int FAST_FUNC get_free_loop(void) | |||
98 | 98 | ||
99 | /* Returns opened fd to the loop device, <0 on error. | 99 | /* Returns opened fd to the loop device, <0 on error. |
100 | * *device is loop device to use, or if *device==NULL finds a loop device to | 100 | * *device is loop device to use, or if *device==NULL finds a loop device to |
101 | * mount it on and sets *device to a strdup of that loop device name. This | 101 | * mount it on and sets *device to a strdup of that loop device name. |
102 | * search will re-use an existing loop device already bound to that | ||
103 | * file/offset if it finds one. | ||
104 | */ | 102 | */ |
105 | int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, | 103 | int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset, |
106 | unsigned long long sizelimit, unsigned flags) | 104 | unsigned long long sizelimit, unsigned flags) |
@@ -109,9 +107,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
109 | char *try; | 107 | char *try; |
110 | bb_loop_info loopinfo; | 108 | bb_loop_info loopinfo; |
111 | struct stat statbuf; | 109 | struct stat statbuf; |
112 | int i, dfd, ffd, mode, rc; | 110 | int i, lfd, ffd, mode, rc; |
113 | |||
114 | rc = dfd = -1; | ||
115 | 111 | ||
116 | /* Open the file. Barf if this doesn't work. */ | 112 | /* Open the file. Barf if this doesn't work. */ |
117 | mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR; | 113 | mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR; |
@@ -127,24 +123,23 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
127 | 123 | ||
128 | try = *device; | 124 | try = *device; |
129 | if (!try) { | 125 | if (!try) { |
126 | get_free_loopN: | ||
130 | i = get_free_loop(); | 127 | i = get_free_loop(); |
131 | if (i == -2) { /* no /dev/loop-control */ | ||
132 | i = 0; | ||
133 | try = dev; | ||
134 | goto old_style; | ||
135 | } | ||
136 | if (i == -1) { | 128 | if (i == -1) { |
137 | close(ffd); | 129 | close(ffd); |
138 | return -1; /* no free loop devices */ | 130 | return -1; /* no free loop devices */ |
139 | } | 131 | } |
140 | try = *device = xasprintf(LOOP_FORMAT, i); | 132 | if (i >= 0) { |
141 | goto try_to_open; | 133 | try = xasprintf(LOOP_FORMAT, i); |
134 | goto open_lfd; | ||
135 | } | ||
136 | /* i == -2: no /dev/loop-control. Do an old-style search for a free device */ | ||
137 | try = dev; | ||
142 | } | 138 | } |
143 | 139 | ||
144 | old_style: | 140 | /* Find a loop device */ |
145 | /* Find a loop device. */ | 141 | /* 0xfffff is a max possible minor number in Linux circa 2010 */ |
146 | /* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */ | 142 | for (i = 0; i <= 0xfffff; i++) { |
147 | for (i = 0; rc && i < 1048576; i++) { | ||
148 | sprintf(dev, LOOP_FORMAT, i); | 143 | sprintf(dev, LOOP_FORMAT, i); |
149 | 144 | ||
150 | IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) | 145 | IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;) |
@@ -153,72 +148,86 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse | |||
153 | && errno == ENOENT | 148 | && errno == ENOENT |
154 | && try == dev | 149 | && try == dev |
155 | ) { | 150 | ) { |
156 | /* Node doesn't exist, try to create it. */ | 151 | /* Node doesn't exist, try to create it */ |
157 | if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) | 152 | if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0) |
158 | goto try_to_open; | 153 | goto open_lfd; |
159 | } | 154 | } |
160 | /* Ran out of block devices, return failure. */ | 155 | /* Ran out of block devices, return failure */ |
161 | rc = -1; | 156 | rc = -1; |
162 | break; | 157 | break; |
163 | } | 158 | } |
164 | try_to_open: | 159 | open_lfd: |
165 | /* Open the sucker and check its loopiness. */ | 160 | /* Open the sucker and check its loopiness */ |
166 | dfd = open(try, mode); | 161 | lfd = rc = open(try, mode); |
167 | if (dfd < 0 && errno == EROFS) { | 162 | if (lfd < 0 && errno == EROFS) { |
168 | mode = O_RDONLY; | 163 | mode = O_RDONLY; |
169 | dfd = open(try, mode); | 164 | lfd = rc = open(try, mode); |
170 | } | 165 | } |
171 | if (dfd < 0) { | 166 | if (lfd < 0) { |
172 | if (errno == ENXIO) { | 167 | if (errno == ENXIO) { |
173 | /* Happens if loop module is not loaded */ | 168 | /* Happens if loop module is not loaded */ |
174 | rc = -1; | 169 | /* rc is -1; */ |
175 | break; | 170 | break; |
176 | } | 171 | } |
177 | goto try_again; | 172 | goto try_next_loopN; |
178 | } | 173 | } |
179 | 174 | ||
180 | rc = ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); | 175 | rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo); |
181 | 176 | ||
182 | /* If device is free, claim it. */ | 177 | /* If device is free, try to claim it */ |
183 | if (rc && errno == ENXIO) { | 178 | if (rc && errno == ENXIO) { |
184 | /* Associate free loop device with file. */ | 179 | /* Associate free loop device with file */ |
185 | if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) { | 180 | if (ioctl(lfd, LOOP_SET_FD, ffd)) { |
186 | memset(&loopinfo, 0, sizeof(loopinfo)); | 181 | /* Ouch. Are we racing with other mount? */ |
187 | safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); | 182 | if (!*device /* yes */ |
188 | loopinfo.lo_offset = offset; | 183 | && try != dev /* tried a _kernel-offered_ loopN? */ |
189 | loopinfo.lo_sizelimit = sizelimit; | 184 | ) { |
190 | /* | 185 | free(try); |
191 | * Used by mount to set LO_FLAGS_AUTOCLEAR. | 186 | close(lfd); |
192 | * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. | 187 | //TODO: add "if (--failcount != 0) ..."? |
193 | * Note that closing LO_FLAGS_AUTOCLEARed dfd before mount | 188 | goto get_free_loopN; |
194 | * is wrong (would free the loop device!) | ||
195 | */ | ||
196 | loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); | ||
197 | rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
198 | if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) { | ||
199 | /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */ | ||
200 | /* (this code path is not tested) */ | ||
201 | loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR; | ||
202 | rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
203 | } | ||
204 | if (rc != 0) { | ||
205 | ioctl(dfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary | ||
206 | } | 189 | } |
190 | goto close_and_try_next_loopN; | ||
207 | } | 191 | } |
208 | } else { | 192 | memset(&loopinfo, 0, sizeof(loopinfo)); |
209 | rc = -1; | 193 | safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); |
210 | } | 194 | loopinfo.lo_offset = offset; |
211 | if (rc != 0) { | 195 | loopinfo.lo_sizelimit = sizelimit; |
212 | close(dfd); | 196 | /* |
197 | * Used by mount to set LO_FLAGS_AUTOCLEAR. | ||
198 | * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file. | ||
199 | * Note that closing LO_FLAGS_AUTOCLEARed lfd before mount | ||
200 | * is wrong (would free the loop device!) | ||
201 | */ | ||
202 | loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY); | ||
203 | rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
204 | if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) { | ||
205 | /* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */ | ||
206 | /* (this code path is not tested) */ | ||
207 | loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR; | ||
208 | rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo); | ||
209 | } | ||
210 | if (rc == 0) { | ||
211 | /* SUCCESS! */ | ||
212 | if (try != dev) /* tried a kernel-offered free loopN? */ | ||
213 | *device = try; /* malloced */ | ||
214 | if (!*device) /* was looping in search of free "/dev/loopN"? */ | ||
215 | *device = xstrdup(dev); | ||
216 | rc = lfd; /* return this */ | ||
217 | break; | ||
218 | } | ||
219 | /* failure, undo LOOP_SET_FD */ | ||
220 | ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary | ||
213 | } | 221 | } |
214 | try_again: | 222 | /* else: device is not free (rc == 0) or error other than ENXIO */ |
215 | if (*device) break; | 223 | close_and_try_next_loopN: |
216 | } | 224 | close(lfd); |
225 | try_next_loopN: | ||
226 | rc = -1; | ||
227 | if (*device) /* was looking for a particular "/dev/loopN"? */ | ||
228 | break; /* yes, do not try other names */ | ||
229 | } /* for() */ | ||
230 | |||
217 | close(ffd); | 231 | close(ffd); |
218 | if (rc == 0) { | ||
219 | if (!*device) | ||
220 | *device = xstrdup(dev); | ||
221 | return dfd; | ||
222 | } | ||
223 | return rc; | 232 | return rc; |
224 | } | 233 | } |
diff --git a/libbb/mode_string.c b/libbb/mode_string.c index 6c5c08acd..dc3f9f88c 100644 --- a/libbb/mode_string.c +++ b/libbb/mode_string.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #define mode_t unsigned short | 27 | #define mode_t unsigned short |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | static const mode_t mode_flags[] = { | 30 | static const mode_t mode_flags[] ALIGN4 = { |
31 | S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, | 31 | S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID, |
32 | S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, | 32 | S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID, |
33 | S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX | 33 | S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX |
diff --git a/libbb/platform.c b/libbb/platform.c index 03bbb798b..329b0237e 100644 --- a/libbb/platform.c +++ b/libbb/platform.c | |||
@@ -27,7 +27,6 @@ int FAST_FUNC usleep(unsigned usec) | |||
27 | * If a signal has non-default handler, nanosleep returns early. | 27 | * If a signal has non-default handler, nanosleep returns early. |
28 | * Our version of usleep doesn't return early | 28 | * Our version of usleep doesn't return early |
29 | * if interrupted by such signals: | 29 | * if interrupted by such signals: |
30 | * | ||
31 | */ | 30 | */ |
32 | while (nanosleep(&ts, &ts) != 0) | 31 | while (nanosleep(&ts, &ts) != 0) |
33 | continue; | 32 | continue; |
@@ -107,7 +106,8 @@ void* FAST_FUNC memrchr(const void *s, int c, size_t n) | |||
107 | /* This is now actually part of POSIX.1, but was only added in 2008 */ | 106 | /* This is now actually part of POSIX.1, but was only added in 2008 */ |
108 | char* FAST_FUNC mkdtemp(char *template) | 107 | char* FAST_FUNC mkdtemp(char *template) |
109 | { | 108 | { |
110 | if (mktemp(template) == NULL || mkdir(template, 0700) != 0) | 109 | /* NB: on error, mktemp returns an empty string, not NULL */ |
110 | if (mktemp(template)[0] == '\0' || mkdir(template, 0700) != 0) | ||
111 | return NULL; | 111 | return NULL; |
112 | return template; | 112 | return template; |
113 | } | 113 | } |
diff --git a/libbb/procps.c b/libbb/procps.c index 4f9705bc1..8c9cac125 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -21,40 +21,29 @@ typedef struct cache_t { | |||
21 | int size; | 21 | int size; |
22 | } cache_t; | 22 | } cache_t; |
23 | 23 | ||
24 | static cache_t username, groupname; | 24 | static cache_t *cache_user_group; |
25 | 25 | ||
26 | static void clear_cache(cache_t *cp) | ||
27 | { | ||
28 | free(cp->cache); | ||
29 | cp->cache = NULL; | ||
30 | cp->size = 0; | ||
31 | } | ||
32 | void FAST_FUNC clear_username_cache(void) | 26 | void FAST_FUNC clear_username_cache(void) |
33 | { | 27 | { |
34 | clear_cache(&username); | 28 | if (cache_user_group) { |
35 | clear_cache(&groupname); | 29 | free(cache_user_group[0].cache); |
36 | } | 30 | free(cache_user_group[1].cache); |
37 | 31 | free(cache_user_group); | |
38 | #if 0 /* more generic, but we don't need that yet */ | 32 | cache_user_group = NULL; |
39 | /* Returns -N-1 if not found. */ | 33 | } |
40 | /* cp->cache[N] is allocated and must be filled in this case */ | ||
41 | static int get_cached(cache_t *cp, uid_t id) | ||
42 | { | ||
43 | int i; | ||
44 | for (i = 0; i < cp->size; i++) | ||
45 | if (cp->cache[i].id == id) | ||
46 | return i; | ||
47 | i = cp->size++; | ||
48 | cp->cache = xrealloc_vector(cp->cache, 2, i); | ||
49 | cp->cache[i++].id = id; | ||
50 | return -i; | ||
51 | } | 34 | } |
52 | #endif | ||
53 | 35 | ||
54 | static char* get_cached(cache_t *cp, uid_t id, | 36 | static char* get_cached(int user_group, uid_t id, |
55 | char* FAST_FUNC x2x_utoa(uid_t id)) | 37 | char* FAST_FUNC x2x_utoa(uid_t id)) |
56 | { | 38 | { |
39 | cache_t *cp; | ||
57 | int i; | 40 | int i; |
41 | |||
42 | if (!cache_user_group) | ||
43 | cache_user_group = xzalloc(sizeof(cache_user_group[0]) * 2); | ||
44 | |||
45 | cp = &cache_user_group[user_group]; | ||
46 | |||
58 | for (i = 0; i < cp->size; i++) | 47 | for (i = 0; i < cp->size; i++) |
59 | if (cp->cache[i].id == id) | 48 | if (cp->cache[i].id == id) |
60 | return cp->cache[i].name; | 49 | return cp->cache[i].name; |
@@ -67,11 +56,11 @@ static char* get_cached(cache_t *cp, uid_t id, | |||
67 | } | 56 | } |
68 | const char* FAST_FUNC get_cached_username(uid_t uid) | 57 | const char* FAST_FUNC get_cached_username(uid_t uid) |
69 | { | 58 | { |
70 | return get_cached(&username, uid, uid2uname_utoa); | 59 | return get_cached(0, uid, uid2uname_utoa); |
71 | } | 60 | } |
72 | const char* FAST_FUNC get_cached_groupname(gid_t gid) | 61 | const char* FAST_FUNC get_cached_groupname(gid_t gid) |
73 | { | 62 | { |
74 | return get_cached(&groupname, gid, gid2group_utoa); | 63 | return get_cached(1, gid, gid2group_utoa); |
75 | } | 64 | } |
76 | 65 | ||
77 | #if !ENABLE_PLATFORM_MINGW32 | 66 | #if !ENABLE_PLATFORM_MINGW32 |
@@ -95,15 +84,15 @@ static int read_to_buf(const char *filename, void *buf) | |||
95 | 84 | ||
96 | static procps_status_t* FAST_FUNC alloc_procps_scan(void) | 85 | static procps_status_t* FAST_FUNC alloc_procps_scan(void) |
97 | { | 86 | { |
98 | unsigned n = getpagesize(); | ||
99 | procps_status_t* sp = xzalloc(sizeof(procps_status_t)); | 87 | procps_status_t* sp = xzalloc(sizeof(procps_status_t)); |
100 | sp->dir = xopendir("/proc"); | 88 | unsigned n = bb_getpagesize(); |
101 | while (1) { | 89 | while (1) { |
102 | n >>= 1; | 90 | n >>= 1; |
103 | if (!n) break; | 91 | if (!n) break; |
104 | sp->shift_pages_to_bytes++; | 92 | sp->shift_pages_to_bytes++; |
105 | } | 93 | } |
106 | sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10; | 94 | sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10; |
95 | sp->dir = xopendir("/proc"); | ||
107 | return sp; | 96 | return sp; |
108 | } | 97 | } |
109 | 98 | ||
@@ -178,6 +167,7 @@ static char *skip_fields(char *str, int count) | |||
178 | } | 167 | } |
179 | #endif | 168 | #endif |
180 | 169 | ||
170 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP | ||
181 | static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) | 171 | static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) |
182 | { | 172 | { |
183 | char *tp = is_prefixed_with(buf, prefix); | 173 | char *tp = is_prefixed_with(buf, prefix); |
@@ -187,7 +177,6 @@ static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix) | |||
187 | return tp; | 177 | return tp; |
188 | } | 178 | } |
189 | 179 | ||
190 | #if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP | ||
191 | int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, | 180 | int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, |
192 | void (*cb)(struct smaprec *, void *), void *data) | 181 | void (*cb)(struct smaprec *, void *), void *data) |
193 | { | 182 | { |
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 47c20690f..3463fd95b 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c | |||
@@ -7,7 +7,9 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | #if !ENABLE_USE_BB_CRYPT | 9 | #if !ENABLE_USE_BB_CRYPT |
10 | #include <crypt.h> | 10 | # if !defined(__FreeBSD__) |
11 | # include <crypt.h> | ||
12 | # endif | ||
11 | #endif | 13 | #endif |
12 | #include "libbb.h" | 14 | #include "libbb.h" |
13 | 15 | ||
@@ -120,6 +122,7 @@ static char *my_crypt(const char *key, const char *salt) | |||
120 | if (!des_cctx) | 122 | if (!des_cctx) |
121 | des_cctx = const_des_init(); | 123 | des_cctx = const_des_init(); |
122 | des_ctx = des_init(des_ctx, des_cctx); | 124 | des_ctx = des_init(des_ctx, des_cctx); |
125 | /* Can return NULL if salt is bad ("" or "<one_char>") */ | ||
123 | return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); | 126 | return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt); |
124 | } | 127 | } |
125 | 128 | ||
@@ -137,6 +140,8 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) | |||
137 | char *encrypted; | 140 | char *encrypted; |
138 | 141 | ||
139 | encrypted = my_crypt(clear, salt); | 142 | encrypted = my_crypt(clear, salt); |
143 | if (!encrypted) | ||
144 | bb_simple_error_msg_and_die("bad salt"); | ||
140 | 145 | ||
141 | if (cleanup) | 146 | if (cleanup) |
142 | my_crypt_cleanup(); | 147 | my_crypt_cleanup(); |
@@ -148,14 +153,16 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) | |||
148 | 153 | ||
149 | char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) | 154 | char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup) |
150 | { | 155 | { |
151 | char *s; | 156 | char *encrypted; |
152 | 157 | ||
153 | s = crypt(clear, salt); | 158 | encrypted = crypt(clear, salt); |
154 | /* | 159 | /* |
155 | * glibc used to return "" on malformed salts (for example, ""), | 160 | * glibc used to return "" on malformed salts (for example, ""), |
156 | * but since 2.17 it returns NULL. | 161 | * but since 2.17 it returns NULL. |
157 | */ | 162 | */ |
158 | return xstrdup(s ? s : ""); | 163 | if (!encrypted || !encrypted[0]) |
164 | bb_simple_error_msg_and_die("bad salt"); | ||
165 | return xstrdup(encrypted); | ||
159 | } | 166 | } |
160 | 167 | ||
161 | #endif | 168 | #endif |
diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c index 19a9ab15b..dcd3521e2 100644 --- a/libbb/pw_encrypt_des.c +++ b/libbb/pw_encrypt_des.c | |||
@@ -65,25 +65,25 @@ | |||
65 | 65 | ||
66 | 66 | ||
67 | /* A pile of data */ | 67 | /* A pile of data */ |
68 | static const uint8_t IP[64] = { | 68 | static const uint8_t IP[64] ALIGN1 = { |
69 | 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, | 69 | 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, |
70 | 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, | 70 | 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, |
71 | 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, | 71 | 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, |
72 | 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 | 72 | 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static const uint8_t key_perm[56] = { | 75 | static const uint8_t key_perm[56] ALIGN1 = { |
76 | 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, | 76 | 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, |
77 | 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, | 77 | 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, |
78 | 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, | 78 | 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, |
79 | 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 | 79 | 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static const uint8_t key_shifts[16] = { | 82 | static const uint8_t key_shifts[16] ALIGN1 = { |
83 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 | 83 | 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 |
84 | }; | 84 | }; |
85 | 85 | ||
86 | static const uint8_t comp_perm[48] = { | 86 | static const uint8_t comp_perm[48] ALIGN1 = { |
87 | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, | 87 | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, |
88 | 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, | 88 | 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, |
89 | 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, | 89 | 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, |
@@ -181,13 +181,12 @@ static const uint8_t u_sbox[8][32] = { | |||
181 | }; | 181 | }; |
182 | #endif | 182 | #endif |
183 | 183 | ||
184 | static const uint8_t pbox[32] = { | 184 | static const uint8_t pbox[32] ALIGN1 = { |
185 | 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, | 185 | 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, |
186 | 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 | 186 | 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 |
187 | }; | 187 | }; |
188 | 188 | ||
189 | static const uint32_t bits32[32] = | 189 | static const uint32_t bits32[32] ALIGN4 = { |
190 | { | ||
191 | 0x80000000, 0x40000000, 0x20000000, 0x10000000, | 190 | 0x80000000, 0x40000000, 0x20000000, 0x10000000, |
192 | 0x08000000, 0x04000000, 0x02000000, 0x01000000, | 191 | 0x08000000, 0x04000000, 0x02000000, 0x01000000, |
193 | 0x00800000, 0x00400000, 0x00200000, 0x00100000, | 192 | 0x00800000, 0x00400000, 0x00200000, 0x00100000, |
@@ -198,7 +197,7 @@ static const uint32_t bits32[32] = | |||
198 | 0x00000008, 0x00000004, 0x00000002, 0x00000001 | 197 | 0x00000008, 0x00000004, 0x00000002, 0x00000001 |
199 | }; | 198 | }; |
200 | 199 | ||
201 | static const uint8_t bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; | 200 | static const uint8_t bits8[8] ALIGN1 = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; |
202 | 201 | ||
203 | 202 | ||
204 | static int | 203 | static int |
@@ -714,11 +713,15 @@ to64_msb_first(char *s, unsigned v) | |||
714 | static char * | 713 | static char * |
715 | NOINLINE | 714 | NOINLINE |
716 | des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], | 715 | des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], |
717 | const unsigned char *key, const unsigned char *setting) | 716 | const unsigned char *key, const unsigned char *salt_str) |
718 | { | 717 | { |
719 | uint32_t salt, r0, r1, keybuf[2]; | 718 | uint32_t salt, r0, r1, keybuf[2]; |
720 | uint8_t *q; | 719 | uint8_t *q; |
721 | 720 | ||
721 | /* Bad salt? Mimic crypt() API - return NULL */ | ||
722 | if (!salt_str[0] || !salt_str[1]) | ||
723 | return NULL; | ||
724 | |||
722 | /* | 725 | /* |
723 | * Copy the key, shifting each character up by one bit | 726 | * Copy the key, shifting each character up by one bit |
724 | * and padding with zeros. | 727 | * and padding with zeros. |
@@ -733,22 +736,15 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE], | |||
733 | des_setkey(ctx, (char *)keybuf); | 736 | des_setkey(ctx, (char *)keybuf); |
734 | 737 | ||
735 | /* | 738 | /* |
736 | * setting - 2 bytes of salt | 739 | * salt_str - 2 bytes of salt |
737 | * key - up to 8 characters | 740 | * key - up to 8 characters |
738 | */ | 741 | */ |
739 | salt = (ascii_to_bin(setting[1]) << 6) | 742 | output[0] = salt_str[0]; |
740 | | ascii_to_bin(setting[0]); | 743 | output[1] = salt_str[1]; |
741 | 744 | salt = (ascii_to_bin(salt_str[1]) << 6) | |
742 | output[0] = setting[0]; | 745 | | ascii_to_bin(salt_str[0]); |
743 | /* | ||
744 | * If the encrypted password that the salt was extracted from | ||
745 | * is only 1 character long, the salt will be corrupted. We | ||
746 | * need to ensure that the output string doesn't have an extra | ||
747 | * NUL in it! | ||
748 | */ | ||
749 | output[1] = setting[1] ? setting[1] : output[0]; | ||
750 | |||
751 | setup_salt(ctx, salt); | 746 | setup_salt(ctx, salt); |
747 | |||
752 | /* Do it. */ | 748 | /* Do it. */ |
753 | do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */); | 749 | do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */); |
754 | 750 | ||
diff --git a/libbb/rtc.c b/libbb/rtc.c index c4117ba34..54b52f23a 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c | |||
@@ -7,12 +7,6 @@ | |||
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "rtc_.h" | 8 | #include "rtc_.h" |
9 | 9 | ||
10 | #if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS | ||
11 | # define ADJTIME_PATH "/var/lib/hwclock/adjtime" | ||
12 | #else | ||
13 | # define ADJTIME_PATH "/etc/adjtime" | ||
14 | #endif | ||
15 | |||
16 | int FAST_FUNC rtc_adjtime_is_utc(void) | 10 | int FAST_FUNC rtc_adjtime_is_utc(void) |
17 | { | 11 | { |
18 | int utc = 0; | 12 | int utc = 0; |
diff --git a/libbb/run_shell.c b/libbb/run_shell.c index a0420d982..c22bba87b 100644 --- a/libbb/run_shell.c +++ b/libbb/run_shell.c | |||
@@ -48,10 +48,10 @@ void FAST_FUNC set_current_security_context(security_context_t sid) | |||
48 | 48 | ||
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | /* Run SHELL, or DEFAULT_SHELL if SHELL is "" or NULL. | 51 | /* Exec SHELL, or DEFAULT_SHELL if SHELL is "" or NULL. |
52 | * If ADDITIONAL_ARGS is not NULL, pass them to the shell. | 52 | * If ADDITIONAL_ARGS is not NULL, pass them to the shell. |
53 | */ | 53 | */ |
54 | void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additional_args) | 54 | void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additional_args) |
55 | { | 55 | { |
56 | const char **args; | 56 | const char **args; |
57 | 57 | ||
@@ -59,7 +59,7 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio | |||
59 | while (args && *args) | 59 | while (args && *args) |
60 | args++; | 60 | args++; |
61 | 61 | ||
62 | args = xmalloc(sizeof(char*) * (2 + (args - additional_args))); | 62 | args = xzalloc(sizeof(args[0]) * (2 + (args - additional_args))); |
63 | 63 | ||
64 | if (!shell || !shell[0]) | 64 | if (!shell || !shell[0]) |
65 | shell = DEFAULT_SHELL; | 65 | shell = DEFAULT_SHELL; |
@@ -67,12 +67,11 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio | |||
67 | args[0] = bb_get_last_path_component_nostrip(shell); | 67 | args[0] = bb_get_last_path_component_nostrip(shell); |
68 | if (loginshell) | 68 | if (loginshell) |
69 | args[0] = xasprintf("-%s", args[0]); | 69 | args[0] = xasprintf("-%s", args[0]); |
70 | args[1] = NULL; | 70 | /*args[1] = NULL; - already is */ |
71 | if (additional_args) { | 71 | if (additional_args) { |
72 | int cnt = 1; | 72 | int cnt = 0; |
73 | for (;;) | 73 | while (*additional_args) |
74 | if ((args[cnt++] = *additional_args++) == NULL) | 74 | args[++cnt] = *additional_args++; |
75 | break; | ||
76 | } | 75 | } |
77 | 76 | ||
78 | #if ENABLE_SELINUX | 77 | #if ENABLE_SELINUX |
@@ -84,3 +83,20 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio | |||
84 | execv(shell, (char **) args); | 83 | execv(shell, (char **) args); |
85 | bb_perror_msg_and_die("can't execute '%s'", shell); | 84 | bb_perror_msg_and_die("can't execute '%s'", shell); |
86 | } | 85 | } |
86 | |||
87 | void FAST_FUNC exec_login_shell(const char *shell) | ||
88 | { | ||
89 | exec_shell(shell, 1, NULL); | ||
90 | } | ||
91 | |||
92 | /* Typical idiom for applets which exec *optional* PROG [ARGS] */ | ||
93 | void FAST_FUNC exec_prog_or_SHELL(char **argv) | ||
94 | { | ||
95 | if (argv[0]) { | ||
96 | BB_EXECVP_or_die(argv); | ||
97 | } | ||
98 | /* Both users (nsenter and unshare) do indeed exec | ||
99 | * a _login_ shell (with dash in argv[0])! | ||
100 | */ | ||
101 | exec_login_shell(getenv("SHELL")); | ||
102 | } | ||
diff --git a/libbb/speed_table.c b/libbb/speed_table.c index 967cf8de8..cf7101e64 100644 --- a/libbb/speed_table.c +++ b/libbb/speed_table.c | |||
@@ -28,7 +28,7 @@ struct speed_map { | |||
28 | }; | 28 | }; |
29 | 29 | ||
30 | /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */ | 30 | /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */ |
31 | static const struct speed_map speeds[] = { | 31 | static const struct speed_map speeds[] ALIGN4 = { |
32 | {B0, 0}, | 32 | {B0, 0}, |
33 | {B50, 50}, | 33 | {B50, 50}, |
34 | {B75, 75}, | 34 | {B75, 75}, |
diff --git a/libbb/time.c b/libbb/time.c index e66a9cba8..cf5f2e5c8 100644 --- a/libbb/time.c +++ b/libbb/time.c | |||
@@ -90,7 +90,11 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm) | |||
90 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ | 90 | ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */ |
91 | } else | 91 | } else |
92 | if (date_str[0] == '@') { | 92 | if (date_str[0] == '@') { |
93 | time_t t = bb_strtol(date_str + 1, NULL, 10); | 93 | time_t t; |
94 | if (sizeof(t) <= sizeof(long)) | ||
95 | t = bb_strtol(date_str + 1, NULL, 10); | ||
96 | else /* time_t is 64 bits but longs are smaller */ | ||
97 | t = bb_strtoll(date_str + 1, NULL, 10); | ||
94 | if (!errno) { | 98 | if (!errno) { |
95 | struct tm *lt = localtime(&t); | 99 | struct tm *lt = localtime(&t); |
96 | if (lt) { | 100 | if (lt) { |
@@ -246,7 +250,6 @@ char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) | |||
246 | 250 | ||
247 | #if ENABLE_MONOTONIC_SYSCALL | 251 | #if ENABLE_MONOTONIC_SYSCALL |
248 | 252 | ||
249 | #include <sys/syscall.h> | ||
250 | /* Old glibc (< 2.3.4) does not provide this constant. We use syscall | 253 | /* Old glibc (< 2.3.4) does not provide this constant. We use syscall |
251 | * directly so this definition is safe. */ | 254 | * directly so this definition is safe. */ |
252 | #ifndef CLOCK_MONOTONIC | 255 | #ifndef CLOCK_MONOTONIC |
@@ -288,19 +291,19 @@ unsigned FAST_FUNC monotonic_sec(void) | |||
288 | unsigned long long FAST_FUNC monotonic_ns(void) | 291 | unsigned long long FAST_FUNC monotonic_ns(void) |
289 | { | 292 | { |
290 | struct timeval tv; | 293 | struct timeval tv; |
291 | gettimeofday(&tv, NULL); | 294 | xgettimeofday(&tv); |
292 | return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; | 295 | return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; |
293 | } | 296 | } |
294 | unsigned long long FAST_FUNC monotonic_us(void) | 297 | unsigned long long FAST_FUNC monotonic_us(void) |
295 | { | 298 | { |
296 | struct timeval tv; | 299 | struct timeval tv; |
297 | gettimeofday(&tv, NULL); | 300 | xgettimeofday(&tv); |
298 | return tv.tv_sec * 1000000ULL + tv.tv_usec; | 301 | return tv.tv_sec * 1000000ULL + tv.tv_usec; |
299 | } | 302 | } |
300 | unsigned long long FAST_FUNC monotonic_ms(void) | 303 | unsigned long long FAST_FUNC monotonic_ms(void) |
301 | { | 304 | { |
302 | struct timeval tv; | 305 | struct timeval tv; |
303 | gettimeofday(&tv, NULL); | 306 | xgettimeofday(&tv); |
304 | return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; | 307 | return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; |
305 | } | 308 | } |
306 | unsigned FAST_FUNC monotonic_sec(void) | 309 | unsigned FAST_FUNC monotonic_sec(void) |
diff --git a/libbb/unicode.c b/libbb/unicode.c index 79481f159..e98cbbf35 100644 --- a/libbb/unicode.c +++ b/libbb/unicode.c | |||
@@ -25,7 +25,7 @@ uint8_t unicode_status; | |||
25 | 25 | ||
26 | void FAST_FUNC reinit_unicode(const char *LANG) | 26 | void FAST_FUNC reinit_unicode(const char *LANG) |
27 | { | 27 | { |
28 | static const char unicode_0x394[] = { 0xce, 0x94, 0 }; | 28 | static const char unicode_0x394[] ALIGN1 = { 0xce, 0x94, 0 }; |
29 | size_t width; | 29 | size_t width; |
30 | 30 | ||
31 | /* We pass "" instead of "C" because some libc's have | 31 | /* We pass "" instead of "C" because some libc's have |
@@ -306,8 +306,10 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max) | |||
306 | unsigned first, last; | 306 | unsigned first, last; |
307 | 307 | ||
308 | first = table[0] >> 2; | 308 | first = table[0] >> 2; |
309 | last = first + (table[0] & 3); | 309 | if (ucs < first) |
310 | if (ucs < first || ucs > last) | 310 | return 0; |
311 | last = (table[max] >> 2) + (table[max] & 3); | ||
312 | if (ucs > last) | ||
311 | return 0; | 313 | return 0; |
312 | 314 | ||
313 | min = 0; | 315 | min = 0; |
@@ -587,12 +589,12 @@ int FAST_FUNC wcwidth(unsigned ucs) | |||
587 | BIG_(0xFE20, 0xFE23) \ | 589 | BIG_(0xFE20, 0xFE23) \ |
588 | BIG_(0xFEFF, 0xFEFF) \ | 590 | BIG_(0xFEFF, 0xFEFF) \ |
589 | BIG_(0xFFF9, 0xFFFB) | 591 | BIG_(0xFFF9, 0xFFFB) |
590 | static const struct interval combining[] = { ARRAY }; | 592 | static const struct interval combining[] ALIGN4 = { ARRAY }; |
591 | # undef BIG_ | 593 | # undef BIG_ |
592 | # undef PAIR | 594 | # undef PAIR |
593 | # define BIG_(a,b) | 595 | # define BIG_(a,b) |
594 | # define PAIR(a,b) (a << 2) | (b-a), | 596 | # define PAIR(a,b) (a << 2) | (b-a), |
595 | static const uint16_t combining1[] = { ARRAY }; | 597 | static const uint16_t combining1[] ALIGN2 = { ARRAY }; |
596 | # undef BIG_ | 598 | # undef BIG_ |
597 | # undef PAIR | 599 | # undef PAIR |
598 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; | 600 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; |
@@ -646,7 +648,7 @@ int FAST_FUNC wcwidth(unsigned ucs) | |||
646 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 | 648 | # if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000 |
647 | if (ucs >= 0x10000) { | 649 | if (ucs >= 0x10000) { |
648 | /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ | 650 | /* Combining chars in Supplementary Multilingual Plane 0x1xxxx */ |
649 | static const struct interval combining0x10000[] = { | 651 | static const struct interval combining0x10000[] ALIGN4 = { |
650 | { 0x0A01, 0x0A03 }, { 0x0A05, 0x0A06 }, { 0x0A0C, 0x0A0F }, | 652 | { 0x0A01, 0x0A03 }, { 0x0A05, 0x0A06 }, { 0x0A0C, 0x0A0F }, |
651 | { 0x0A38, 0x0A3A }, { 0x0A3F, 0x0A3F }, { 0xD167, 0xD169 }, | 653 | { 0x0A38, 0x0A3A }, { 0x0A3F, 0x0A3F }, { 0xD167, 0xD169 }, |
652 | { 0xD173, 0xD182 }, { 0xD185, 0xD18B }, { 0xD1AA, 0xD1AD }, | 654 | { 0xD173, 0xD182 }, { 0xD185, 0xD18B }, { 0xD1AA, 0xD1AD }, |
@@ -757,12 +759,12 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc) | |||
757 | {0x10E7F, 0x10FFF}, | 759 | {0x10E7F, 0x10FFF}, |
758 | {0x1E800, 0x1EFFF} | 760 | {0x1E800, 0x1EFFF} |
759 | */ | 761 | */ |
760 | static const struct interval rtl_b[] = { ARRAY }; | 762 | static const struct interval rtl_b[] ALIGN4 = { ARRAY }; |
761 | # undef BIG_ | 763 | # undef BIG_ |
762 | # undef PAIR | 764 | # undef PAIR |
763 | # define BIG_(a,b) | 765 | # define BIG_(a,b) |
764 | # define PAIR(a,b) (a << 2) | (b-a), | 766 | # define PAIR(a,b) (a << 2) | (b-a), |
765 | static const uint16_t rtl_p[] = { ARRAY }; | 767 | static const uint16_t rtl_p[] ALIGN2 = { ARRAY }; |
766 | # undef BIG_ | 768 | # undef BIG_ |
767 | # undef PAIR | 769 | # undef PAIR |
768 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; | 770 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; |
@@ -961,12 +963,12 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc) | |||
961 | {0x1F030, 0x1F093}, | 963 | {0x1F030, 0x1F093}, |
962 | {0x1F100, 0x1F10A} | 964 | {0x1F100, 0x1F10A} |
963 | */ | 965 | */ |
964 | static const struct interval neutral_b[] = { ARRAY }; | 966 | static const struct interval neutral_b[] ALIGN4 = { ARRAY }; |
965 | # undef BIG_ | 967 | # undef BIG_ |
966 | # undef PAIR | 968 | # undef PAIR |
967 | # define BIG_(a,b) | 969 | # define BIG_(a,b) |
968 | # define PAIR(a,b) (a << 2) | (b-a), | 970 | # define PAIR(a,b) (a << 2) | (b-a), |
969 | static const uint16_t neutral_p[] = { ARRAY }; | 971 | static const uint16_t neutral_p[] ALIGN2 = { ARRAY }; |
970 | # undef BIG_ | 972 | # undef BIG_ |
971 | # undef PAIR | 973 | # undef PAIR |
972 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; | 974 | # define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1]; |
diff --git a/libbb/uuencode.c b/libbb/uuencode.c index d36b34f63..21af7a8c9 100644 --- a/libbb/uuencode.c +++ b/libbb/uuencode.c | |||
@@ -8,8 +8,18 @@ | |||
8 | */ | 8 | */ |
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | /* Conversion table. for base 64 */ | 11 | /* Conversion tables */ |
12 | const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { | 12 | #if ENABLE_BASE32 |
13 | const char bb_uuenc_tbl_base32[] ALIGN1 = { | ||
14 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | ||
15 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | ||
16 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | ||
17 | 'Y', 'Z', '2', '3', '4', '5', '6', '7', | ||
18 | /* unused: '=', */ | ||
19 | }; | ||
20 | #endif | ||
21 | /* for base 64 */ | ||
22 | const char bb_uuenc_tbl_base64[] ALIGN1 = { | ||
13 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', | 23 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', |
14 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', | 24 | 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', |
15 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', | 25 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', |
@@ -18,11 +28,9 @@ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { | |||
18 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', | 28 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', |
19 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', | 29 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', |
20 | '4', '5', '6', '7', '8', '9', '+', '/', | 30 | '4', '5', '6', '7', '8', '9', '+', '/', |
21 | '=' /* termination character */, | 31 | '=' /* termination character */ |
22 | '\0' /* needed for uudecode.c only */ | ||
23 | }; | 32 | }; |
24 | 33 | const char bb_uuenc_tbl_std[] ALIGN1 = { | |
25 | const char bb_uuenc_tbl_std[65] ALIGN1 = { | ||
26 | '`', '!', '"', '#', '$', '%', '&', '\'', | 34 | '`', '!', '"', '#', '$', '%', '&', '\'', |
27 | '(', ')', '*', '+', ',', '-', '.', '/', | 35 | '(', ')', '*', '+', ',', '-', '.', '/', |
28 | '0', '1', '2', '3', '4', '5', '6', '7', | 36 | '0', '1', '2', '3', '4', '5', '6', '7', |
@@ -30,7 +38,7 @@ const char bb_uuenc_tbl_std[65] ALIGN1 = { | |||
30 | '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', | 38 | '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', |
31 | 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', | 39 | 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', |
32 | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', | 40 | 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', |
33 | 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', | 41 | 'X', 'Y', 'Z', '[', '\\',']', '^', '_', |
34 | '`' /* termination character */ | 42 | '`' /* termination character */ |
35 | }; | 43 | }; |
36 | 44 | ||
@@ -72,86 +80,124 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl | |||
72 | } | 80 | } |
73 | 81 | ||
74 | /* | 82 | /* |
75 | * Decode base64 encoded string. Stops on '\0'. | 83 | * Decode base64 encoded string. |
76 | * | 84 | * |
77 | * Returns: pointer to the undecoded part of source. | 85 | * Returns: pointer past the last written output byte, |
86 | * the result is not NUL-terminated. | ||
87 | * (*pp_src) is advanced past the last read byte. | ||
78 | * If points to '\0', then the source was fully decoded. | 88 | * If points to '\0', then the source was fully decoded. |
79 | * (*pp_dst): advanced past the last written byte. | ||
80 | */ | 89 | */ |
81 | const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) | 90 | char* FAST_FUNC decode_base64(char *dst, const char **pp_src) |
82 | { | 91 | { |
83 | char *dst = *pp_dst; | 92 | const char *src = pp_src ? *pp_src : dst; /* for httpd.c, support NULL 2nd param */ |
84 | const char *src_tail; | 93 | unsigned ch = 0; |
94 | unsigned t; | ||
95 | int i = 0; | ||
85 | 96 | ||
86 | while (1) { | 97 | while ((t = (unsigned char)*src) != '\0') { |
87 | unsigned char six_bit[4]; | 98 | src++; |
88 | int count = 0; | ||
89 | |||
90 | /* Fetch up to four 6-bit values */ | ||
91 | src_tail = src; | ||
92 | while (count < 4) { | ||
93 | char *table_ptr; | ||
94 | int ch; | ||
95 | |||
96 | /* Get next _valid_ character. | ||
97 | * bb_uuenc_tbl_base64[] contains this string: | ||
98 | * 0 1 2 3 4 5 6 | ||
99 | * 01234567890123456789012345678901234567890123456789012345678901234 | ||
100 | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" | ||
101 | */ | ||
102 | do { | ||
103 | ch = *src; | ||
104 | if (ch == '\0') { | ||
105 | if (count == 0) { | ||
106 | /* Example: | ||
107 | * If we decode "QUJD <NUL>", we want | ||
108 | * to return ptr to NUL, not to ' ', | ||
109 | * because we did fully decode | ||
110 | * the string (to "ABC"). | ||
111 | */ | ||
112 | src_tail = src; | ||
113 | } | ||
114 | goto ret; | ||
115 | } | ||
116 | src++; | ||
117 | table_ptr = strchr(bb_uuenc_tbl_base64, ch); | ||
118 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
119 | } while (!table_ptr); | ||
120 | 99 | ||
121 | /* Convert encoded character to decimal */ | 100 | /* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */ |
122 | ch = table_ptr - bb_uuenc_tbl_base64; | 101 | if (t >= '0' && t <= '9') |
102 | t = t - '0' + 52; | ||
103 | else if (t >= 'A' && t <= 'Z') | ||
104 | t = t - 'A'; | ||
105 | else if (t >= 'a' && t <= 'z') | ||
106 | t = t - 'a' + 26; | ||
107 | else if (t == '+') | ||
108 | t = 62; | ||
109 | else if (t == '/') | ||
110 | t = 63; | ||
111 | else if (t == '=' && (i == 3 || (i == 2 && *src == '='))) | ||
112 | /* the above disallows "==AA", "A===", "AA=A" etc */ | ||
113 | t = 0x1000000; | ||
114 | else | ||
115 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
116 | continue; | ||
123 | 117 | ||
124 | /* ch is 64 if char was '=', otherwise 0..63 */ | 118 | ch = (ch << 6) | t; |
125 | if (ch == 64) | 119 | i = (i + 1) & 3; |
120 | if (i == 0) { | ||
121 | *dst++ = (char) (ch >> 16); | ||
122 | *dst++ = (char) (ch >> 8); | ||
123 | *dst++ = (char) ch; | ||
124 | if (ch & 0x1000000) { /* was last input char '='? */ | ||
125 | dst--; | ||
126 | if (ch & (0x1000000 << 6)) /* was it "=="? */ | ||
127 | dst--; | ||
126 | break; | 128 | break; |
127 | six_bit[count] = ch; | 129 | } |
128 | count++; | 130 | ch = 0; |
131 | } | ||
132 | } | ||
133 | /* i is zero here if full 4-char block was decoded */ | ||
134 | if (pp_src) | ||
135 | *pp_src = src - i; /* -i signals truncation: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */ | ||
136 | return dst; | ||
137 | } | ||
138 | |||
139 | #if ENABLE_BASE32 | ||
140 | char* FAST_FUNC decode_base32(char *dst, const char **pp_src) | ||
141 | { | ||
142 | const char *src = *pp_src; | ||
143 | uint64_t ch = 0; | ||
144 | unsigned t; | ||
145 | int i = 0; | ||
146 | |||
147 | while ((t = (unsigned char)*src) != '\0') { | ||
148 | src++; | ||
149 | |||
150 | /* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */ | ||
151 | if (t >= '2' && t <= '7') | ||
152 | t = t - '2' + 26; | ||
153 | else if (t == '=' && i > 1) | ||
154 | t = 0; | ||
155 | else { | ||
156 | t = (t | 0x20) - 'a'; | ||
157 | if (t > 25) | ||
158 | //TODO: add BASE64_FLAG_foo to die on bad char? | ||
159 | continue; | ||
129 | } | 160 | } |
130 | 161 | ||
131 | /* Transform 6-bit values to 8-bit ones. | 162 | ch = (ch << 5) | t; |
132 | * count can be < 4 when we decode the tail: | 163 | i = (i + 1) & 7; |
133 | * "eQ==" -> "y", not "y NUL NUL". | 164 | if (i == 0) { |
134 | * Note that (count > 1) is always true, | 165 | *dst++ = (char) (ch >> 32); |
135 | * "x===" encoding is not valid: | 166 | if (src[-1] == '=') /* was last input char '='? */ |
136 | * even a single zero byte encodes as "AA==". | 167 | goto tail; |
137 | * However, with current logic we come here with count == 1 | 168 | *dst++ = (char) (ch >> 24); |
138 | * when we decode "==" tail. | 169 | *dst++ = (char) (ch >> 16); |
139 | */ | 170 | *dst++ = (char) (ch >> 8); |
140 | if (count > 1) | 171 | *dst++ = (char) ch; |
141 | *dst++ = six_bit[0] << 2 | six_bit[1] >> 4; | 172 | } |
142 | if (count > 2) | 173 | } |
143 | *dst++ = six_bit[1] << 4 | six_bit[2] >> 2; | 174 | /* i is zero here if full 8-char block was decoded */ |
144 | if (count > 3) | 175 | *pp_src = src - i; |
145 | *dst++ = six_bit[2] << 6 | six_bit[3]; | 176 | return dst; |
146 | /* Note that if we decode "AA==" and ate first '=', | 177 | tail: |
147 | * we just decoded one char (count == 2) and now we'll | 178 | { |
148 | * do the loop once more to decode second '='. | 179 | const char *s = src; |
180 | while (*--s == '=') | ||
181 | i++; | ||
182 | /* Why duplicate the below code? Testcase: | ||
183 | * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d | ||
184 | * IOW, decoding of | ||
185 | * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI== | ||
186 | * ==== | ||
187 | * must correctly stitch together the tail, must not overwrite | ||
188 | * the tail before it is analyzed! (we can be decoding in-place) | ||
189 | * Else testcase fails, prints trailing extra NUL bytes. | ||
149 | */ | 190 | */ |
150 | } /* while (1) */ | 191 | *dst++ = (char) (ch >> 24); |
151 | ret: | 192 | *dst++ = (char) (ch >> 16); |
152 | *pp_dst = dst; | 193 | *dst++ = (char) (ch >> 8); |
153 | return src_tail; | 194 | *dst++ = (char) ch; |
195 | dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */ | ||
196 | } | ||
197 | *pp_src = src; | ||
198 | return dst; | ||
154 | } | 199 | } |
200 | #endif | ||
155 | 201 | ||
156 | /* | 202 | /* |
157 | * Decode base64 encoded stream. | 203 | * Decode base64 encoded stream. |
@@ -163,20 +209,22 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
163 | /* Note that EOF _can_ be passed as exit_char too */ | 209 | /* Note that EOF _can_ be passed as exit_char too */ |
164 | #define exit_char ((int)(signed char)flags) | 210 | #define exit_char ((int)(signed char)flags) |
165 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) | 211 | #define uu_style_end (flags & BASE64_FLAG_UU_STOP) |
212 | #define base32 (flags & BASE64_32) | ||
166 | 213 | ||
167 | /* uuencoded files have 61 byte lines. Use 64 byte buffer | 214 | /* uuencoded files have 61 byte lines. |
168 | * to process line at a time. | 215 | * base32/64 have 76 byte lines by default. |
216 | * Use 80 byte buffer to process one line at a time. | ||
169 | */ | 217 | */ |
170 | enum { BUFFER_SIZE = 64 }; | 218 | enum { BUFFER_SIZE = 80 }; |
171 | 219 | /* decoded data is shorter than input, can use single buffer for both */ | |
172 | char in_buf[BUFFER_SIZE + 2]; | 220 | char buf[BUFFER_SIZE + 2]; |
173 | char out_buf[BUFFER_SIZE / 4 * 3 + 2]; | ||
174 | char *out_tail; | ||
175 | const char *in_tail; | ||
176 | int term_seen = 0; | 221 | int term_seen = 0; |
177 | int in_count = 0; | 222 | int in_count = 0; |
178 | 223 | ||
179 | while (1) { | 224 | while (1) { |
225 | char *out_tail; | ||
226 | const char *in_tail; | ||
227 | |||
180 | while (in_count < BUFFER_SIZE) { | 228 | while (in_count < BUFFER_SIZE) { |
181 | int ch = fgetc(src_stream); | 229 | int ch = fgetc(src_stream); |
182 | if (ch == exit_char) { | 230 | if (ch == exit_char) { |
@@ -195,29 +243,34 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) | |||
195 | */ | 243 | */ |
196 | if (ch <= ' ') | 244 | if (ch <= ' ') |
197 | break; | 245 | break; |
198 | in_buf[in_count++] = ch; | 246 | buf[in_count++] = ch; |
199 | } | 247 | } |
200 | in_buf[in_count] = '\0'; | 248 | buf[in_count] = '\0'; |
201 | 249 | ||
202 | /* Did we encounter "====" line? */ | 250 | /* Did we encounter "====" line? */ |
203 | if (uu_style_end && strcmp(in_buf, "====") == 0) | 251 | if (uu_style_end && strcmp(buf, "====") == 0) |
204 | return; | 252 | return; |
205 | 253 | ||
206 | out_tail = out_buf; | 254 | in_tail = buf; |
207 | in_tail = decode_base64(&out_tail, in_buf); | 255 | #if ENABLE_BASE32 |
256 | if (base32) | ||
257 | out_tail = decode_base32(buf, &in_tail); | ||
258 | else | ||
259 | #endif | ||
260 | out_tail = decode_base64(buf, &in_tail); | ||
208 | 261 | ||
209 | fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); | 262 | fwrite(buf, (out_tail - buf), 1, dst_stream); |
210 | 263 | ||
211 | if (term_seen) { | 264 | if (term_seen) { |
212 | /* Did we consume ALL characters? */ | 265 | /* Did we consume ALL characters? */ |
213 | if (*in_tail == '\0') | 266 | if (*in_tail == '\0') |
214 | return; | 267 | return; |
215 | /* No */ | 268 | /* No */ |
216 | bb_simple_error_msg_and_die("truncated base64 input"); | 269 | bb_simple_error_msg_and_die("truncated input"); |
217 | } | 270 | } |
218 | 271 | ||
219 | /* It was partial decode */ | 272 | /* It was partial decode */ |
220 | in_count = strlen(in_tail); | 273 | in_count = strlen(in_tail); |
221 | memmove(in_buf, in_tail, in_count); | 274 | memmove(buf, in_tail, in_count); |
222 | } | 275 | } |
223 | } | 276 | } |
diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 7639a62aa..36b06c849 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c | |||
@@ -68,14 +68,14 @@ uint16_t FAST_FUNC xatou16(const char *numstr) | |||
68 | return xatou_range(numstr, 0, 0xffff); | 68 | return xatou_range(numstr, 0, 0xffff); |
69 | } | 69 | } |
70 | 70 | ||
71 | const struct suffix_mult bkm_suffixes[] = { | 71 | const struct suffix_mult bkm_suffixes[] ALIGN_SUFFIX = { |
72 | { "b", 512 }, | 72 | { "b", 512 }, |
73 | { "k", 1024 }, | 73 | { "k", 1024 }, |
74 | { "m", 1024*1024 }, | 74 | { "m", 1024*1024 }, |
75 | { "", 0 } | 75 | { "", 0 } |
76 | }; | 76 | }; |
77 | 77 | ||
78 | const struct suffix_mult cwbkMG_suffixes[] = { | 78 | const struct suffix_mult cwbkMG_suffixes[] ALIGN_SUFFIX = { |
79 | { "c", 1 }, | 79 | { "c", 1 }, |
80 | { "w", 2 }, | 80 | { "w", 2 }, |
81 | { "b", 512 }, | 81 | { "b", 512 }, |
@@ -96,7 +96,7 @@ const struct suffix_mult cwbkMG_suffixes[] = { | |||
96 | { "", 0 } | 96 | { "", 0 } |
97 | }; | 97 | }; |
98 | 98 | ||
99 | const struct suffix_mult kmg_i_suffixes[] = { | 99 | const struct suffix_mult kmg_i_suffixes[] ALIGN_SUFFIX = { |
100 | { "KiB", 1024 }, | 100 | { "KiB", 1024 }, |
101 | { "kiB", 1024 }, | 101 | { "kiB", 1024 }, |
102 | { "K", 1024 }, | 102 | { "K", 1024 }, |
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 38faef38e..f5c514b2c 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -428,17 +428,14 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) | |||
428 | struct sockaddr_nl sa; | 428 | struct sockaddr_nl sa; |
429 | int fd; | 429 | int fd; |
430 | 430 | ||
431 | memset(&sa, 0, sizeof(sa)); | ||
432 | sa.nl_family = AF_NETLINK; | ||
433 | sa.nl_pid = getpid(); | ||
434 | sa.nl_groups = grp; | ||
435 | fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto); | 431 | fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto); |
436 | xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); | ||
437 | close_on_exec_on(fd); | ||
438 | 432 | ||
433 | /* Set receive buffer size before binding the socket | ||
434 | * We want to have enough space before we start receiving messages. | ||
435 | */ | ||
439 | if (rcvbuf != 0) { | 436 | if (rcvbuf != 0) { |
440 | // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl | 437 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf); |
441 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf); | 438 | /* SO_RCVBUFFORCE (root only) can go above net.core.rmem_max */ |
442 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf); | 439 | setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf); |
443 | # if 0 | 440 | # if 0 |
444 | { | 441 | { |
@@ -450,6 +447,13 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) | |||
450 | # endif | 447 | # endif |
451 | } | 448 | } |
452 | 449 | ||
450 | memset(&sa, 0, sizeof(sa)); | ||
451 | sa.nl_family = AF_NETLINK; | ||
452 | sa.nl_pid = getpid(); | ||
453 | sa.nl_groups = grp; | ||
454 | xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); | ||
455 | close_on_exec_on(fd); | ||
456 | |||
453 | return fd; | 457 | return fd; |
454 | } | 458 | } |
455 | #endif | 459 | #endif |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index c92436683..ef990118e 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -421,15 +421,3 @@ int FAST_FUNC wait4pid(pid_t pid) | |||
421 | return WTERMSIG(status) + 0x180; | 421 | return WTERMSIG(status) + 0x180; |
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | |||
425 | // Useful when we do know that pid is valid, and we just want to wait | ||
426 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | ||
427 | int FAST_FUNC wait_for_exitstatus(pid_t pid) | ||
428 | { | ||
429 | int exit_status, n; | ||
430 | |||
431 | n = safe_waitpid(pid, &exit_status, 0); | ||
432 | if (n < 0) | ||
433 | bb_simple_perror_msg_and_die("waitpid"); | ||
434 | return exit_status; | ||
435 | } | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 6fdc0f6a4..4bd19d471 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -111,6 +111,29 @@ void* FAST_FUNC xmemdup(const void *s, int n) | |||
111 | return memcpy(xmalloc(n), s, n); | 111 | return memcpy(xmalloc(n), s, n); |
112 | } | 112 | } |
113 | 113 | ||
114 | #if !ENABLE_PLATFORM_MINGW32 | ||
115 | void* FAST_FUNC mmap_read(int fd, size_t size) | ||
116 | { | ||
117 | return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
118 | } | ||
119 | |||
120 | void* FAST_FUNC mmap_anon(size_t size) | ||
121 | { | ||
122 | return mmap(NULL, size, | ||
123 | PROT_READ | PROT_WRITE, | ||
124 | MAP_PRIVATE | MAP_ANONYMOUS, | ||
125 | /* ignored: */ -1, 0); | ||
126 | } | ||
127 | |||
128 | void* FAST_FUNC xmmap_anon(size_t size) | ||
129 | { | ||
130 | void *p = mmap_anon(size); | ||
131 | if (p == MAP_FAILED) | ||
132 | bb_die_memory_exhausted(); | ||
133 | return p; | ||
134 | } | ||
135 | #endif | ||
136 | |||
114 | // Die if we can't open a file and return a FILE* to it. | 137 | // Die if we can't open a file and return a FILE* to it. |
115 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. | 138 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. |
116 | FILE* FAST_FUNC xfopen(const char *path, const char *mode) | 139 | FILE* FAST_FUNC xfopen(const char *path, const char *mode) |
@@ -502,22 +525,22 @@ void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg) | |||
502 | bb_simple_perror_msg_and_die(errmsg); | 525 | bb_simple_perror_msg_and_die(errmsg); |
503 | } | 526 | } |
504 | 527 | ||
505 | #if !ENABLE_PLATFORM_MINGW32 | 528 | #if ENABLE_SELINUX |
506 | // selinux_or_die() - die if SELinux is disabled. | 529 | // selinux_or_die() - die if SELinux is disabled. |
507 | void FAST_FUNC selinux_or_die(void) | 530 | void FAST_FUNC selinux_or_die(void) |
508 | { | 531 | { |
509 | #if ENABLE_SELINUX | ||
510 | int rc = is_selinux_enabled(); | 532 | int rc = is_selinux_enabled(); |
511 | if (rc == 0) { | 533 | if (rc == 0) { |
512 | bb_simple_error_msg_and_die("SELinux is disabled"); | 534 | bb_simple_error_msg_and_die("SELinux is disabled"); |
513 | } else if (rc < 0) { | 535 | } else if (rc < 0) { |
514 | bb_simple_error_msg_and_die("is_selinux_enabled() failed"); | 536 | bb_simple_error_msg_and_die("is_selinux_enabled() failed"); |
515 | } | 537 | } |
538 | } | ||
516 | #else | 539 | #else |
517 | bb_simple_error_msg_and_die("SELinux support is disabled"); | 540 | /* not defined, other code must have no calls to it */ |
518 | #endif | 541 | #endif |
519 | } | ||
520 | 542 | ||
543 | #if !ENABLE_PLATFORM_MINGW32 | ||
521 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) | 544 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) |
522 | { | 545 | { |
523 | int ret; | 546 | int ret; |
@@ -634,14 +657,11 @@ void FAST_FUNC generate_uuid(uint8_t *buf) | |||
634 | pid_t pid; | 657 | pid_t pid; |
635 | int i; | 658 | int i; |
636 | 659 | ||
637 | i = open("/dev/urandom", O_RDONLY); | 660 | open_read_close("/dev/urandom", buf, 16); |
638 | if (i >= 0) { | ||
639 | read(i, buf, 16); | ||
640 | close(i); | ||
641 | } | ||
642 | /* Paranoia. /dev/urandom may be missing. | 661 | /* Paranoia. /dev/urandom may be missing. |
643 | * rand() is guaranteed to generate at least [0, 2^15) range, | 662 | * rand() is guaranteed to generate at least [0, 2^15) range, |
644 | * but lowest bits in some libc are not so "random". */ | 663 | * but lowest bits in some libc are not so "random". |
664 | */ | ||
645 | srand(monotonic_us()); /* pulls in printf */ | 665 | srand(monotonic_us()); /* pulls in printf */ |
646 | pid = getpid(); | 666 | pid = getpid(); |
647 | while (1) { | 667 | while (1) { |
@@ -686,3 +706,34 @@ void FAST_FUNC xvfork_parent_waits_and_exits(void) | |||
686 | /* Child continues */ | 706 | /* Child continues */ |
687 | } | 707 | } |
688 | #endif /* !ENABLE_PLATFORM_MINGW32 */ | 708 | #endif /* !ENABLE_PLATFORM_MINGW32 */ |
709 | |||
710 | // Useful when we do know that pid is valid, and we just want to wait | ||
711 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | ||
712 | int FAST_FUNC wait_for_exitstatus(pid_t pid) | ||
713 | { | ||
714 | int exit_status, n; | ||
715 | |||
716 | n = safe_waitpid(pid, &exit_status, 0); | ||
717 | if (n < 0) | ||
718 | bb_simple_perror_msg_and_die("waitpid"); | ||
719 | return exit_status; | ||
720 | } | ||
721 | |||
722 | #if !ENABLE_PLATFORM_MINGW32 | ||
723 | void FAST_FUNC xsettimeofday(const struct timeval *tv) | ||
724 | { | ||
725 | if (settimeofday(tv, NULL)) | ||
726 | bb_simple_perror_msg_and_die("settimeofday"); | ||
727 | } | ||
728 | #endif | ||
729 | |||
730 | void FAST_FUNC xgettimeofday(struct timeval *tv) | ||
731 | { | ||
732 | #if 0 | ||
733 | if (gettimeofday(tv, NULL)) | ||
734 | bb_simple_perror_msg_and_die("gettimeofday"); | ||
735 | #else | ||
736 | /* Never fails on Linux */ | ||
737 | gettimeofday(tv, NULL); | ||
738 | #endif | ||
739 | } | ||