diff options
author | Ron Yorston <rmy@pobox.com> | 2016-10-19 17:01:55 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2016-10-19 17:01:55 +0100 |
commit | 075814c60a316cfd088c88f26f75ab21b5850b98 (patch) | |
tree | f6e33ac693630827deb309faa5fa4931588db57d /libbb | |
parent | 977d65c1bbc57f5cdd0c8bfd67c8b5bb1cd390dd (diff) | |
parent | f37e1155aabde6bd95d267a8aec347cedccb8bc3 (diff) | |
download | busybox-w32-075814c60a316cfd088c88f26f75ab21b5850b98.tar.gz busybox-w32-075814c60a316cfd088c88f26f75ab21b5850b98.tar.bz2 busybox-w32-075814c60a316cfd088c88f26f75ab21b5850b98.zip |
Merge branch busybox (up to "ash: comment out free(p) just before...")
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/appletlib.c | 12 | ||||
-rw-r--r-- | libbb/copy_file.c | 16 | ||||
-rw-r--r-- | libbb/dump.c | 51 | ||||
-rw-r--r-- | libbb/hash_md5_sha.c | 55 | ||||
-rw-r--r-- | libbb/lineedit.c | 22 | ||||
-rw-r--r-- | libbb/login.c | 40 | ||||
-rw-r--r-- | libbb/speed_table.c | 81 | ||||
-rw-r--r-- | libbb/udp_io.c | 10 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 5 | ||||
-rw-r--r-- | libbb/xconnect.c | 7 | ||||
-rw-r--r-- | libbb/xfuncs_printf.c | 12 |
11 files changed, 238 insertions, 73 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 28adf2740..4aa40454f 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -930,7 +930,9 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) | |||
930 | } | 930 | } |
931 | if (ENABLE_FEATURE_SUID) | 931 | if (ENABLE_FEATURE_SUID) |
932 | check_suid(applet_no); | 932 | check_suid(applet_no); |
933 | exit(applet_main[applet_no](argc, argv)); | 933 | xfunc_error_retval = applet_main[applet_no](argc, argv); |
934 | /* Note: applet_main() may also not return (die on a xfunc or such) */ | ||
935 | xfunc_die(); | ||
934 | } | 936 | } |
935 | # endif /* NUM_APPLETS > 0 */ | 937 | # endif /* NUM_APPLETS > 0 */ |
936 | 938 | ||
@@ -993,6 +995,14 @@ int main(int argc UNUSED_PARAM, char **argv) | |||
993 | */ | 995 | */ |
994 | mallopt(M_MMAP_THRESHOLD, 32 * 1024 - 256); | 996 | mallopt(M_MMAP_THRESHOLD, 32 * 1024 - 256); |
995 | #endif | 997 | #endif |
998 | #if 0 /*def M_TOP_PAD*/ | ||
999 | /* When the program break is increased, then M_TOP_PAD bytes are added | ||
1000 | * to the sbrk(2) request. When the heap is trimmed because of free(3), | ||
1001 | * this much free space is preserved at the top of the heap. | ||
1002 | * glibc default seems to be way too big: 128k, but need to verify. | ||
1003 | */ | ||
1004 | mallopt(M_TOP_PAD, 8 * 1024); | ||
1005 | #endif | ||
996 | 1006 | ||
997 | #if !BB_MMU | 1007 | #if !BB_MMU |
998 | /* NOMMU re-exec trick sets high-order bit in first byte of name */ | 1008 | /* NOMMU re-exec trick sets high-order bit in first byte of name */ |
diff --git a/libbb/copy_file.c b/libbb/copy_file.c index c52297376..cb6d12359 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c | |||
@@ -299,11 +299,16 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
299 | if (!S_ISREG(source_stat.st_mode)) | 299 | if (!S_ISREG(source_stat.st_mode)) |
300 | new_mode = 0666; | 300 | new_mode = 0666; |
301 | 301 | ||
302 | // POSIX way is a security problem versus (sym)link attacks | 302 | if (ENABLE_FEATURE_NON_POSIX_CP || (flags & FILEUTILS_INTERACTIVE)) { |
303 | if (!ENABLE_FEATURE_NON_POSIX_CP) { | 303 | /* |
304 | dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); | 304 | * O_CREAT|O_EXCL: require that file did not exist before creation |
305 | } else { /* safe way: */ | 305 | */ |
306 | dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); | 306 | dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); |
307 | } else { /* POSIX, and not "cp -i" */ | ||
308 | /* | ||
309 | * O_CREAT|O_TRUNC: create, or truncate (security problem versus (sym)link attacks) | ||
310 | */ | ||
311 | dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); | ||
307 | } | 312 | } |
308 | if (dst_fd == -1) { | 313 | if (dst_fd == -1) { |
309 | ovr = ask_and_unlink(dest, flags); | 314 | ovr = ask_and_unlink(dest, flags); |
@@ -378,7 +383,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
378 | } | 383 | } |
379 | /* _Not_ jumping to preserve_mode_ugid_time: | 384 | /* _Not_ jumping to preserve_mode_ugid_time: |
380 | * symlinks don't have those */ | 385 | * symlinks don't have those */ |
381 | return 0; | 386 | goto verb_and_exit; |
382 | } | 387 | } |
383 | if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) | 388 | if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) |
384 | || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) | 389 | || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) |
@@ -413,6 +418,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
413 | bb_perror_msg("can't preserve %s of '%s'", "permissions", dest); | 418 | bb_perror_msg("can't preserve %s of '%s'", "permissions", dest); |
414 | } | 419 | } |
415 | 420 | ||
421 | verb_and_exit: | ||
416 | if (flags & FILEUTILS_VERBOSE) { | 422 | if (flags & FILEUTILS_VERBOSE) { |
417 | printf("'%s' -> '%s'\n", source, dest); | 423 | printf("'%s' -> '%s'\n", source, dest); |
418 | } | 424 | } |
diff --git a/libbb/dump.c b/libbb/dump.c index 566881a78..154be5d80 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -157,7 +157,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) | |||
157 | /* | 157 | /* |
158 | * figure out the byte count for each conversion; | 158 | * figure out the byte count for each conversion; |
159 | * rewrite the format as necessary, set up blank- | 159 | * rewrite the format as necessary, set up blank- |
160 | * pbb_dump_adding for end of data. | 160 | * padding for end of data. |
161 | */ | 161 | */ |
162 | if (*p1 == 'c') { | 162 | if (*p1 == 'c') { |
163 | pr->flags = F_CHAR; | 163 | pr->flags = F_CHAR; |
@@ -466,14 +466,14 @@ static void bpad(PR *pr) | |||
466 | } | 466 | } |
467 | 467 | ||
468 | static const char conv_str[] ALIGN1 = | 468 | static const char conv_str[] ALIGN1 = |
469 | "\0\\0\0" | 469 | "\0" "\\""0""\0" |
470 | "\007\\a\0" /* \a */ | 470 | "\007""\\""a""\0" /* \a */ |
471 | "\b\\b\0" | 471 | "\b" "\\""b""\0" |
472 | "\f\\b\0" | 472 | "\f" "\\""f""\0" |
473 | "\n\\n\0" | 473 | "\n" "\\""n""\0" |
474 | "\r\\r\0" | 474 | "\r" "\\""r""\0" |
475 | "\t\\t\0" | 475 | "\t" "\\""t""\0" |
476 | "\v\\v\0" | 476 | "\v" "\\""v""\0" |
477 | ; | 477 | ; |
478 | 478 | ||
479 | 479 | ||
@@ -485,7 +485,7 @@ static void conv_c(PR *pr, unsigned char *p) | |||
485 | do { | 485 | do { |
486 | if (*p == *str) { | 486 | if (*p == *str) { |
487 | ++str; | 487 | ++str; |
488 | goto strpr; | 488 | goto strpr; /* map e.g. '\n' to "\\n" */ |
489 | } | 489 | } |
490 | str += 4; | 490 | str += 4; |
491 | } while (*str); | 491 | } while (*str); |
@@ -702,8 +702,6 @@ int FAST_FUNC bb_dump_dump(dumper_t *pub_dumper, char **argv) | |||
702 | void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) | 702 | void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) |
703 | { | 703 | { |
704 | const char *p; | 704 | const char *p; |
705 | char *p1; | ||
706 | char *p2; | ||
707 | FS *tfs; | 705 | FS *tfs; |
708 | FU *tfu, **nextfupp; | 706 | FU *tfu, **nextfupp; |
709 | const char *savep; | 707 | const char *savep; |
@@ -779,29 +777,42 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) | |||
779 | } | 777 | } |
780 | } | 778 | } |
781 | tfu->fmt = xstrndup(savep, p - savep); | 779 | tfu->fmt = xstrndup(savep, p - savep); |
782 | /* escape(tfu->fmt); */ | ||
783 | |||
784 | p1 = tfu->fmt; | ||
785 | 780 | ||
786 | /* alphabetic escape sequences have to be done in place */ | 781 | /* alphabetic escape sequences have to be done in place */ |
782 | strcpy_and_process_escape_sequences(tfu->fmt, tfu->fmt); | ||
783 | /* unknown mappings are not changed: "\z" -> '\\' 'z' */ | ||
784 | /* trailing backslash, if any, is preserved */ | ||
785 | #if 0 | ||
786 | char *p1; | ||
787 | char *p2; | ||
788 | p1 = tfu->fmt; | ||
787 | for (p2 = p1;; ++p1, ++p2) { | 789 | for (p2 = p1;; ++p1, ++p2) { |
788 | if (*p1 == '\0') { | 790 | *p2 = *p1; |
789 | *p2 = *p1; | 791 | if (*p1 == '\0') |
790 | break; | 792 | break; |
791 | } | 793 | |
792 | if (*p1 == '\\') { | 794 | if (*p1 == '\\') { |
793 | const char *cs = conv_str + 4; | 795 | const char *cs; |
794 | ++p1; | 796 | |
797 | p1++; | ||
795 | *p2 = *p1; | 798 | *p2 = *p1; |
799 | if (*p1 == '\0') { | ||
800 | /* "...\" trailing backslash. Eaten. */ | ||
801 | break; | ||
802 | } | ||
803 | cs = conv_str + 4; /* skip NUL element */ | ||
796 | do { | 804 | do { |
805 | /* map e.g. "\n" -> '\n' */ | ||
797 | if (*p1 == cs[2]) { | 806 | if (*p1 == cs[2]) { |
798 | *p2 = cs[0]; | 807 | *p2 = cs[0]; |
799 | break; | 808 | break; |
800 | } | 809 | } |
801 | cs += 4; | 810 | cs += 4; |
802 | } while (*cs); | 811 | } while (*cs); |
812 | /* unknown mappings remove bkslash: "\z" -> 'z' */ | ||
803 | } | 813 | } |
804 | } | 814 | } |
815 | #endif | ||
805 | 816 | ||
806 | p++; | 817 | p++; |
807 | } | 818 | } |
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index d08c6b2f7..7e7d8da2f 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c | |||
@@ -941,10 +941,6 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) | |||
941 | # define OPTIMIZE_SHA3_FOR_32 1 | 941 | # define OPTIMIZE_SHA3_FOR_32 1 |
942 | #endif | 942 | #endif |
943 | 943 | ||
944 | enum { | ||
945 | SHA3_IBLK_BYTES = 72, /* 576 bits / 8 */ | ||
946 | }; | ||
947 | |||
948 | #if OPTIMIZE_SHA3_FOR_32 | 944 | #if OPTIMIZE_SHA3_FOR_32 |
949 | /* This splits every 64-bit word into a pair of 32-bit words, | 945 | /* This splits every 64-bit word into a pair of 32-bit words, |
950 | * even bits go into first word, odd bits go to second one. | 946 | * even bits go into first word, odd bits go to second one. |
@@ -1352,6 +1348,8 @@ static void sha3_process_block72(uint64_t *state) | |||
1352 | void FAST_FUNC sha3_begin(sha3_ctx_t *ctx) | 1348 | void FAST_FUNC sha3_begin(sha3_ctx_t *ctx) |
1353 | { | 1349 | { |
1354 | memset(ctx, 0, sizeof(*ctx)); | 1350 | memset(ctx, 0, sizeof(*ctx)); |
1351 | /* SHA3-512, user can override */ | ||
1352 | ctx->input_block_bytes = (1600 - 512*2) / 8; /* 72 bytes */ | ||
1355 | } | 1353 | } |
1356 | 1354 | ||
1357 | void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) | 1355 | void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) |
@@ -1361,7 +1359,7 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) | |||
1361 | unsigned bufpos = ctx->bytes_queued; | 1359 | unsigned bufpos = ctx->bytes_queued; |
1362 | 1360 | ||
1363 | while (1) { | 1361 | while (1) { |
1364 | unsigned remaining = SHA3_IBLK_BYTES - bufpos; | 1362 | unsigned remaining = ctx->input_block_bytes - bufpos; |
1365 | if (remaining > len) | 1363 | if (remaining > len) |
1366 | remaining = len; | 1364 | remaining = len; |
1367 | len -= remaining; | 1365 | len -= remaining; |
@@ -1373,38 +1371,41 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) | |||
1373 | remaining--; | 1371 | remaining--; |
1374 | } | 1372 | } |
1375 | /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ | 1373 | /* Clever way to do "if (bufpos != N) break; ... ; bufpos = 0;" */ |
1376 | bufpos -= SHA3_IBLK_BYTES; | 1374 | bufpos -= ctx->input_block_bytes; |
1377 | if (bufpos != 0) | 1375 | if (bufpos != 0) |
1378 | break; | 1376 | break; |
1379 | /* Buffer is filled up, process it */ | 1377 | /* Buffer is filled up, process it */ |
1380 | sha3_process_block72(ctx->state); | 1378 | sha3_process_block72(ctx->state); |
1381 | /*bufpos = 0; - already is */ | 1379 | /*bufpos = 0; - already is */ |
1382 | } | 1380 | } |
1383 | ctx->bytes_queued = bufpos + SHA3_IBLK_BYTES; | 1381 | ctx->bytes_queued = bufpos + ctx->input_block_bytes; |
1384 | #else | 1382 | #else |
1385 | /* +50 bytes code size, but a bit faster because of long-sized XORs */ | 1383 | /* +50 bytes code size, but a bit faster because of long-sized XORs */ |
1386 | const uint8_t *data = buffer; | 1384 | const uint8_t *data = buffer; |
1387 | unsigned bufpos = ctx->bytes_queued; | 1385 | unsigned bufpos = ctx->bytes_queued; |
1386 | unsigned iblk_bytes = ctx->input_block_bytes; | ||
1388 | 1387 | ||
1389 | /* If already data in queue, continue queuing first */ | 1388 | /* If already data in queue, continue queuing first */ |
1390 | while (len != 0 && bufpos != 0) { | 1389 | if (bufpos != 0) { |
1391 | uint8_t *buf = (uint8_t*)ctx->state; | 1390 | while (len != 0) { |
1392 | buf[bufpos] ^= *data++; | 1391 | uint8_t *buf = (uint8_t*)ctx->state; |
1393 | len--; | 1392 | buf[bufpos] ^= *data++; |
1394 | bufpos++; | 1393 | len--; |
1395 | if (bufpos == SHA3_IBLK_BYTES) { | 1394 | bufpos++; |
1396 | bufpos = 0; | 1395 | if (bufpos == iblk_bytes) { |
1397 | goto do_block; | 1396 | bufpos = 0; |
1397 | goto do_block; | ||
1398 | } | ||
1398 | } | 1399 | } |
1399 | } | 1400 | } |
1400 | 1401 | ||
1401 | /* Absorb complete blocks */ | 1402 | /* Absorb complete blocks */ |
1402 | while (len >= SHA3_IBLK_BYTES) { | 1403 | while (len >= iblk_bytes) { |
1403 | /* XOR data onto beginning of state[]. | 1404 | /* XOR data onto beginning of state[]. |
1404 | * We try to be efficient - operate one word at a time, not byte. | 1405 | * We try to be efficient - operate one word at a time, not byte. |
1405 | * Careful wrt unaligned access: can't just use "*(long*)data"! | 1406 | * Careful wrt unaligned access: can't just use "*(long*)data"! |
1406 | */ | 1407 | */ |
1407 | unsigned count = SHA3_IBLK_BYTES / sizeof(long); | 1408 | unsigned count = iblk_bytes / sizeof(long); |
1408 | long *buf = (long*)ctx->state; | 1409 | long *buf = (long*)ctx->state; |
1409 | do { | 1410 | do { |
1410 | long v; | 1411 | long v; |
@@ -1412,7 +1413,7 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) | |||
1412 | *buf++ ^= v; | 1413 | *buf++ ^= v; |
1413 | data += sizeof(long); | 1414 | data += sizeof(long); |
1414 | } while (--count); | 1415 | } while (--count); |
1415 | len -= SHA3_IBLK_BYTES; | 1416 | len -= iblk_bytes; |
1416 | do_block: | 1417 | do_block: |
1417 | sha3_process_block72(ctx->state); | 1418 | sha3_process_block72(ctx->state); |
1418 | } | 1419 | } |
@@ -1433,8 +1434,22 @@ void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) | |||
1433 | { | 1434 | { |
1434 | /* Padding */ | 1435 | /* Padding */ |
1435 | uint8_t *buf = (uint8_t*)ctx->state; | 1436 | uint8_t *buf = (uint8_t*)ctx->state; |
1436 | buf[ctx->bytes_queued] ^= 1; | 1437 | /* |
1437 | buf[SHA3_IBLK_BYTES - 1] ^= 0x80; | 1438 | * Keccak block padding is: add 1 bit after last bit of input, |
1439 | * then add zero bits until the end of block, and add the last 1 bit | ||
1440 | * (the last bit in the block) - the "10*1" pattern. | ||
1441 | * SHA3 standard appends additional two bits, 01, before that padding: | ||
1442 | * | ||
1443 | * SHA3-224(M) = KECCAK[448](M||01, 224) | ||
1444 | * SHA3-256(M) = KECCAK[512](M||01, 256) | ||
1445 | * SHA3-384(M) = KECCAK[768](M||01, 384) | ||
1446 | * SHA3-512(M) = KECCAK[1024](M||01, 512) | ||
1447 | * (M is the input, || is bit concatenation) | ||
1448 | * | ||
1449 | * The 6 below contains 01 "SHA3" bits and the first 1 "Keccak" bit: | ||
1450 | */ | ||
1451 | buf[ctx->bytes_queued] ^= 6; /* bit pattern 00000110 */ | ||
1452 | buf[ctx->input_block_bytes - 1] ^= 0x80; | ||
1438 | 1453 | ||
1439 | sha3_process_block72(ctx->state); | 1454 | sha3_process_block72(ctx->state); |
1440 | 1455 | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 2566abd38..34eb16e6b 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -81,7 +81,9 @@ | |||
81 | # define CHAR_T wchar_t | 81 | # define CHAR_T wchar_t |
82 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } | 82 | static bool BB_isspace(CHAR_T c) { return ((unsigned)c < 256 && isspace(c)); } |
83 | # if ENABLE_FEATURE_EDITING_VI | 83 | # if ENABLE_FEATURE_EDITING_VI |
84 | static bool BB_isalnum(CHAR_T c) { return ((unsigned)c < 256 && isalnum(c)); } | 84 | static bool BB_isalnum_or_underscore(CHAR_T c) { |
85 | return ((unsigned)c < 256 && isalnum(c)) || c == '_'; | ||
86 | } | ||
85 | # endif | 87 | # endif |
86 | static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } | 88 | static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } |
87 | # undef isspace | 89 | # undef isspace |
@@ -96,7 +98,11 @@ static bool BB_ispunct(CHAR_T c) { return ((unsigned)c < 256 && ispunct(c)); } | |||
96 | # define BB_NUL '\0' | 98 | # define BB_NUL '\0' |
97 | # define CHAR_T char | 99 | # define CHAR_T char |
98 | # define BB_isspace(c) isspace(c) | 100 | # define BB_isspace(c) isspace(c) |
99 | # define BB_isalnum(c) isalnum(c) | 101 | # if ENABLE_FEATURE_EDITING_VI |
102 | static bool BB_isalnum_or_underscore(CHAR_T c) { | ||
103 | return ((unsigned)c < 256 && isalnum(c)) || c == '_'; | ||
104 | } | ||
105 | # endif | ||
100 | # define BB_ispunct(c) ispunct(c) | 106 | # define BB_ispunct(c) ispunct(c) |
101 | #endif | 107 | #endif |
102 | #if ENABLE_UNICODE_PRESERVE_BROKEN | 108 | #if ENABLE_UNICODE_PRESERVE_BROKEN |
@@ -1647,9 +1653,9 @@ vi_word_motion(int eat) | |||
1647 | { | 1653 | { |
1648 | CHAR_T *command = command_ps; | 1654 | CHAR_T *command = command_ps; |
1649 | 1655 | ||
1650 | if (BB_isalnum(command[cursor]) || command[cursor] == '_') { | 1656 | if (BB_isalnum_or_underscore(command[cursor])) { |
1651 | while (cursor < command_len | 1657 | while (cursor < command_len |
1652 | && (BB_isalnum(command[cursor+1]) || command[cursor+1] == '_') | 1658 | && (BB_isalnum_or_underscore(command[cursor+1])) |
1653 | ) { | 1659 | ) { |
1654 | input_forward(); | 1660 | input_forward(); |
1655 | } | 1661 | } |
@@ -1691,9 +1697,9 @@ vi_end_motion(void) | |||
1691 | input_forward(); | 1697 | input_forward(); |
1692 | if (cursor >= command_len-1) | 1698 | if (cursor >= command_len-1) |
1693 | return; | 1699 | return; |
1694 | if (BB_isalnum(command[cursor]) || command[cursor] == '_') { | 1700 | if (BB_isalnum_or_underscore(command[cursor])) { |
1695 | while (cursor < command_len-1 | 1701 | while (cursor < command_len-1 |
1696 | && (BB_isalnum(command[cursor+1]) || command[cursor+1] == '_') | 1702 | && (BB_isalnum_or_underscore(command[cursor+1])) |
1697 | ) { | 1703 | ) { |
1698 | input_forward(); | 1704 | input_forward(); |
1699 | } | 1705 | } |
@@ -1726,9 +1732,9 @@ vi_back_motion(void) | |||
1726 | input_backward(1); | 1732 | input_backward(1); |
1727 | if (cursor <= 0) | 1733 | if (cursor <= 0) |
1728 | return; | 1734 | return; |
1729 | if (BB_isalnum(command[cursor]) || command[cursor] == '_') { | 1735 | if (BB_isalnum_or_underscore(command[cursor])) { |
1730 | while (cursor > 0 | 1736 | while (cursor > 0 |
1731 | && (BB_isalnum(command[cursor-1]) || command[cursor-1] == '_') | 1737 | && (BB_isalnum_or_underscore(command[cursor-1])) |
1732 | ) { | 1738 | ) { |
1733 | input_backward(1); | 1739 | input_backward(1); |
1734 | } | 1740 | } |
diff --git a/libbb/login.c b/libbb/login.c index 8f080b775..5a7acfcf0 100644 --- a/libbb/login.c +++ b/libbb/login.c | |||
@@ -45,6 +45,45 @@ void FAST_FUNC print_login_issue(const char *issue_file, const char *tty) | |||
45 | if (c == '\\' || c == '%') { | 45 | if (c == '\\' || c == '%') { |
46 | c = fgetc(fp); | 46 | c = fgetc(fp); |
47 | switch (c) { | 47 | switch (c) { |
48 | //From getty manpage (* - supported by us) | ||
49 | //======================================== | ||
50 | //4 or 4{interface} | ||
51 | // Insert the IPv4 address of the network interface (example: \4{eth0}). | ||
52 | // If the interface argument is not specified, then select the first | ||
53 | // fully configured (UP, non-LOOPBACK, RUNNING) interface. | ||
54 | //6 or 6{interface} -- The same as \4 but for IPv6. | ||
55 | //b -- Insert the baudrate of the current line. | ||
56 | //*d -- Insert the current date. | ||
57 | //*t -- Insert the current time. | ||
58 | //e or e{name} | ||
59 | // Translate the human-readable name to an escape sequence and insert it | ||
60 | // (for example: \e{red}Alert text.\e{reset}). If the name argument | ||
61 | // is not specified, then insert \033. The currently supported names are: | ||
62 | // black, blink, blue, bold, brown, cyan, darkgray, gray, green, halfbright, | ||
63 | // lightblue, lightcyan, lightgray, lightgreen, lightmagenta, lightred, | ||
64 | // magenta, red, reset, reverse, and yellow. Unknown names are ignored. | ||
65 | //*s | ||
66 | // Insert the system name (the name of the operating system - `uname -s`) | ||
67 | //*S or S{VARIABLE} | ||
68 | // Insert the VARIABLE data from /etc/os-release. | ||
69 | // If the VARIABLE argument is not specified, use PRETTY_NAME. | ||
70 | // If PRETTY_NAME is not in /etc/os-release, \S is the same as \s. | ||
71 | //*l -- Insert the name of the current tty line. | ||
72 | //*m -- Insert the architecture identifier of the machine: `uname -m`. | ||
73 | //*n -- Insert the nodename of the machine: `uname -n`. | ||
74 | //*o -- Insert the NIS domainname of the machine. Same as `hostname -d'. | ||
75 | //*O -- Insert the DNS domainname of the machine. | ||
76 | //*r -- Insert the release number of the OS: `uname -r`. | ||
77 | //u -- Insert the number of current users logged in. | ||
78 | //U -- Insert the string "1 user" or "N users" (current users logged in). | ||
79 | //*v -- Insert the version of the OS, e.g. the build-date etc: `uname -v`. | ||
80 | //We also implement: | ||
81 | //*D -- same as \O "DNS domainname" | ||
82 | //*h -- same as \n "nodename" | ||
83 | |||
84 | case 'S': | ||
85 | /* minimal implementation, not reading /etc/os-release */ | ||
86 | /*FALLTHROUGH*/ | ||
48 | case 's': | 87 | case 's': |
49 | outbuf = uts.sysname; | 88 | outbuf = uts.sysname; |
50 | break; | 89 | break; |
@@ -65,6 +104,7 @@ void FAST_FUNC print_login_issue(const char *issue_file, const char *tty) | |||
65 | #if defined(__linux__) | 104 | #if defined(__linux__) |
66 | case 'D': | 105 | case 'D': |
67 | case 'o': | 106 | case 'o': |
107 | case 'O': | ||
68 | outbuf = uts.domainname; | 108 | outbuf = uts.domainname; |
69 | break; | 109 | break; |
70 | #endif | 110 | #endif |
diff --git a/libbb/speed_table.c b/libbb/speed_table.c index 174d531b2..11ced01d0 100644 --- a/libbb/speed_table.c +++ b/libbb/speed_table.c | |||
@@ -10,7 +10,16 @@ | |||
10 | #include "libbb.h" | 10 | #include "libbb.h" |
11 | 11 | ||
12 | struct speed_map { | 12 | struct speed_map { |
13 | #if defined __FreeBSD__ | 13 | #if defined __FreeBSD__ \ |
14 | || (defined B115200 && B115200 > 0xffff) \ | ||
15 | || (defined B230400 && B230400 > 0xffff) \ | ||
16 | || (defined B460800 && B460800 > 0xffff) \ | ||
17 | || (defined B921600 && B921600 > 0xffff) \ | ||
18 | || (defined B1152000 && B1152000 > 0xffff) \ | ||
19 | || (defined B1000000 && B1000000 > 0xffff) \ | ||
20 | || (defined B2000000 && B2000000 > 0xffff) \ | ||
21 | || (defined B3000000 && B3000000 > 0xffff) \ | ||
22 | || (defined B4000000 && B4000000 > 0xffff) | ||
14 | /* On FreeBSD, B<num> constants don't fit into a short */ | 23 | /* On FreeBSD, B<num> constants don't fit into a short */ |
15 | unsigned speed; | 24 | unsigned speed; |
16 | #else | 25 | #else |
@@ -19,6 +28,7 @@ struct speed_map { | |||
19 | unsigned short value; | 28 | unsigned short value; |
20 | }; | 29 | }; |
21 | 30 | ||
31 | /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */ | ||
22 | static const struct speed_map speeds[] = { | 32 | static const struct speed_map speeds[] = { |
23 | {B0, 0}, | 33 | {B0, 0}, |
24 | {B50, 50}, | 34 | {B50, 50}, |
@@ -37,30 +47,79 @@ static const struct speed_map speeds[] = { | |||
37 | #ifdef B19200 | 47 | #ifdef B19200 |
38 | {B19200, 19200}, | 48 | {B19200, 19200}, |
39 | #elif defined(EXTA) | 49 | #elif defined(EXTA) |
40 | {EXTA, 19200}, | 50 | {EXTA, 19200}, |
41 | #endif | 51 | #endif |
52 | /* 19200 = 0x4b00 */ | ||
53 | /* 38400 = 0x9600, this value would use bit#15 if not "/200" encoded: */ | ||
42 | #ifdef B38400 | 54 | #ifdef B38400 |
43 | {B38400, 38400/256 + 0x8000U}, | 55 | {B38400, 38400/200 + 0x8000u}, |
44 | #elif defined(EXTB) | 56 | #elif defined(EXTB) |
45 | {EXTB, 38400/256 + 0x8000U}, | 57 | {EXTB, 38400/200 + 0x8000u}, |
46 | #endif | 58 | #endif |
47 | #ifdef B57600 | 59 | #ifdef B57600 |
48 | {B57600, 57600/256 + 0x8000U}, | 60 | {B57600, 57600/200 + 0x8000u}, |
49 | #endif | 61 | #endif |
50 | #ifdef B115200 | 62 | #ifdef B115200 |
51 | {B115200, 115200/256 + 0x8000U}, | 63 | {B115200, 115200/200 + 0x8000u}, |
52 | #endif | 64 | #endif |
53 | #ifdef B230400 | 65 | #ifdef B230400 |
54 | {B230400, 230400/256 + 0x8000U}, | 66 | {B230400, 230400/200 + 0x8000u}, |
55 | #endif | 67 | #endif |
56 | #ifdef B460800 | 68 | #ifdef B460800 |
57 | {B460800, 460800/256 + 0x8000U}, | 69 | {B460800, 460800/200 + 0x8000u}, |
70 | #endif | ||
71 | #ifdef B576000 | ||
72 | {B576000, 576000/200 + 0x8000u}, | ||
58 | #endif | 73 | #endif |
59 | #ifdef B921600 | 74 | #ifdef B921600 |
60 | {B921600, 921600/256 + 0x8000U}, | 75 | {B921600, 921600/200 + 0x8000u}, |
76 | #endif | ||
77 | #ifdef B1152000 | ||
78 | {B1152000, 1152000/200 + 0x8000u}, | ||
79 | #endif | ||
80 | |||
81 | #ifdef B500000 | ||
82 | {B500000, 500000/200 + 0x8000u}, | ||
83 | #endif | ||
84 | #ifdef B1000000 | ||
85 | {B1000000, 1000000/200 + 0x8000u}, | ||
86 | #endif | ||
87 | #ifdef B1500000 | ||
88 | {B1500000, 1500000/200 + 0x8000u}, | ||
89 | #endif | ||
90 | #ifdef B2000000 | ||
91 | {B2000000, 2000000/200 + 0x8000u}, | ||
92 | #endif | ||
93 | #ifdef B2500000 | ||
94 | {B2500000, 2500000/200 + 0x8000u}, | ||
61 | #endif | 95 | #endif |
96 | #ifdef B3000000 | ||
97 | {B3000000, 3000000/200 + 0x8000u}, | ||
98 | #endif | ||
99 | #ifdef B3500000 | ||
100 | {B3500000, 3500000/200 + 0x8000u}, | ||
101 | #endif | ||
102 | #ifdef B4000000 | ||
103 | {B4000000, 4000000/200 + 0x8000u}, | ||
104 | #endif | ||
105 | /* 4000000/200 = 0x4e20, bit#15 still does not interfere with the value */ | ||
106 | /* (can use /800 if higher speeds would appear, /1600 won't work for B500000) */ | ||
62 | }; | 107 | }; |
63 | 108 | ||
109 | /* | ||
110 | * TODO: maybe we can just bite the bullet, ditch the table and use termios2 | ||
111 | * Linux API (supports arbitrary baud rates, no Bxxxx mess needed)? Example: | ||
112 | * | ||
113 | * #include <asm/termios.h> | ||
114 | * #include <asm/ioctls.h> | ||
115 | * struct termios2 t; | ||
116 | * ioctl(fd, TCGETS2, &t); | ||
117 | * t.c_ospeed = t.c_ispeed = 543210; | ||
118 | * t.c_cflag &= ~CBAUD; | ||
119 | * t.c_cflag |= BOTHER; | ||
120 | * ioctl(fd, TCSETS2, &t); | ||
121 | */ | ||
122 | |||
64 | enum { NUM_SPEEDS = ARRAY_SIZE(speeds) }; | 123 | enum { NUM_SPEEDS = ARRAY_SIZE(speeds) }; |
65 | 124 | ||
66 | unsigned FAST_FUNC tty_baud_to_value(speed_t speed) | 125 | unsigned FAST_FUNC tty_baud_to_value(speed_t speed) |
@@ -69,8 +128,8 @@ unsigned FAST_FUNC tty_baud_to_value(speed_t speed) | |||
69 | 128 | ||
70 | do { | 129 | do { |
71 | if (speed == speeds[i].speed) { | 130 | if (speed == speeds[i].speed) { |
72 | if (speeds[i].value & 0x8000U) { | 131 | if (speeds[i].value & 0x8000u) { |
73 | return ((unsigned long) (speeds[i].value) & 0x7fffU) * 256; | 132 | return ((unsigned)(speeds[i].value) & 0x7fffU) * 200; |
74 | } | 133 | } |
75 | return speeds[i].value; | 134 | return speeds[i].value; |
76 | } | 135 | } |
diff --git a/libbb/udp_io.c b/libbb/udp_io.c index a32af9bd2..6e3ef484e 100644 --- a/libbb/udp_io.c +++ b/libbb/udp_io.c | |||
@@ -70,7 +70,13 @@ send_to_from(int fd, void *buf, size_t len, int flags, | |||
70 | msg.msg_flags = flags; | 70 | msg.msg_flags = flags; |
71 | 71 | ||
72 | cmsgptr = CMSG_FIRSTHDR(&msg); | 72 | cmsgptr = CMSG_FIRSTHDR(&msg); |
73 | if (to->sa_family == AF_INET && from->sa_family == AF_INET) { | 73 | /* |
74 | * Users report that to->sa_family can be AF_INET6 too, | ||
75 | * if "to" was acquired by recv_from_to(). IOW: recv_from_to() | ||
76 | * was seen showing IPv6 "from" even when the destination | ||
77 | * of received packet (our local address) was IPv4. | ||
78 | */ | ||
79 | if (/* to->sa_family == AF_INET && */ from->sa_family == AF_INET) { | ||
74 | struct in_pktinfo *pktptr; | 80 | struct in_pktinfo *pktptr; |
75 | cmsgptr->cmsg_level = IPPROTO_IP; | 81 | cmsgptr->cmsg_level = IPPROTO_IP; |
76 | cmsgptr->cmsg_type = IP_PKTINFO; | 82 | cmsgptr->cmsg_type = IP_PKTINFO; |
@@ -86,7 +92,7 @@ send_to_from(int fd, void *buf, size_t len, int flags, | |||
86 | pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; | 92 | pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; |
87 | } | 93 | } |
88 | # if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) | 94 | # if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) |
89 | else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { | 95 | else if (/* to->sa_family == AF_INET6 && */ from->sa_family == AF_INET6) { |
90 | struct in6_pktinfo *pktptr; | 96 | struct in6_pktinfo *pktptr; |
91 | cmsgptr->cmsg_level = IPPROTO_IPV6; | 97 | cmsgptr->cmsg_level = IPPROTO_IPV6; |
92 | cmsgptr->cmsg_type = IPV6_PKTINFO; | 98 | cmsgptr->cmsg_type = IPV6_PKTINFO; |
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index f488f8e0c..766a89e5f 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -70,7 +70,8 @@ pid_t FAST_FUNC xspawn(char **argv) | |||
70 | return pid; | 70 | return pid; |
71 | } | 71 | } |
72 | 72 | ||
73 | #if ENABLE_FEATURE_PREFER_APPLETS | 73 | #if ENABLE_FEATURE_PREFER_APPLETS \ |
74 | || ENABLE_FEATURE_SH_NOFORK | ||
74 | static jmp_buf die_jmp; | 75 | static jmp_buf die_jmp; |
75 | static void jump(void) | 76 | static void jump(void) |
76 | { | 77 | { |
@@ -176,7 +177,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
176 | 177 | ||
177 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ | 178 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ |
178 | } | 179 | } |
179 | #endif /* FEATURE_PREFER_APPLETS */ | 180 | #endif /* FEATURE_PREFER_APPLETS || FEATURE_SH_NOFORK */ |
180 | 181 | ||
181 | int FAST_FUNC spawn_and_wait(char **argv) | 182 | int FAST_FUNC spawn_and_wait(char **argv) |
182 | { | 183 | { |
diff --git a/libbb/xconnect.c b/libbb/xconnect.c index c318af419..ee54898e3 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c | |||
@@ -500,12 +500,15 @@ char* FAST_FUNC xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa) | |||
500 | { | 500 | { |
501 | return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT); | 501 | return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT); |
502 | } | 502 | } |
503 | #ifndef NI_NUMERICSCOPE | ||
504 | # define NI_NUMERICSCOPE 0 | ||
505 | #endif | ||
503 | char* FAST_FUNC xmalloc_sockaddr2dotted(const struct sockaddr *sa) | 506 | char* FAST_FUNC xmalloc_sockaddr2dotted(const struct sockaddr *sa) |
504 | { | 507 | { |
505 | return sockaddr2str(sa, NI_NUMERICHOST); | 508 | return sockaddr2str(sa, NI_NUMERICHOST | NI_NUMERICSCOPE); |
506 | } | 509 | } |
507 | 510 | ||
508 | char* FAST_FUNC xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa) | 511 | char* FAST_FUNC xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa) |
509 | { | 512 | { |
510 | return sockaddr2str(sa, NI_NUMERICHOST | IGNORE_PORT); | 513 | return sockaddr2str(sa, NI_NUMERICHOST | NI_NUMERICSCOPE | IGNORE_PORT); |
511 | } | 514 | } |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index e9222f690..1b11caf6b 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -235,8 +235,16 @@ void FAST_FUNC xwrite(int fd, const void *buf, size_t count) | |||
235 | { | 235 | { |
236 | if (count) { | 236 | if (count) { |
237 | ssize_t size = full_write(fd, buf, count); | 237 | ssize_t size = full_write(fd, buf, count); |
238 | if ((size_t)size != count) | 238 | if ((size_t)size != count) { |
239 | bb_error_msg_and_die("short write"); | 239 | /* |
240 | * Two cases: write error immediately; | ||
241 | * or some writes succeeded, then we hit an error. | ||
242 | * In either case, errno is set. | ||
243 | */ | ||
244 | bb_perror_msg_and_die( | ||
245 | size >= 0 ? "short write" : "write error" | ||
246 | ); | ||
247 | } | ||
240 | } | 248 | } |
241 | } | 249 | } |
242 | void FAST_FUNC xwrite_str(int fd, const char *str) | 250 | void FAST_FUNC xwrite_str(int fd, const char *str) |