diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Kbuild.src | 2 | ||||
-rw-r--r-- | libbb/alloc_affinity.c | 29 | ||||
-rw-r--r-- | libbb/lineedit.c | 62 | ||||
-rw-r--r-- | libbb/popcnt.c | 46 |
4 files changed, 111 insertions, 28 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 7785ef152..32fde90e6 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -58,6 +58,7 @@ lib-y += parse_mode.o | |||
58 | lib-y += perror_msg.o | 58 | lib-y += perror_msg.o |
59 | lib-y += perror_nomsg_and_die.o | 59 | lib-y += perror_nomsg_and_die.o |
60 | lib-y += platform.o | 60 | lib-y += platform.o |
61 | lib-y += popcnt.o | ||
61 | lib-y += printable.o | 62 | lib-y += printable.o |
62 | lib-y += printable_string.o | 63 | lib-y += printable_string.o |
63 | lib-y += process_escape_sequence.o | 64 | lib-y += process_escape_sequence.o |
@@ -99,6 +100,7 @@ lib-y += xgetcwd.o | |||
99 | lib-y += xreadlink.o | 100 | lib-y += xreadlink.o |
100 | lib-y += xrealloc_vector.o | 101 | lib-y += xrealloc_vector.o |
101 | 102 | ||
103 | lib-$(CONFIG_PLATFORM_POSIX) += alloc_affinity.o | ||
102 | lib-$(CONFIG_PLATFORM_POSIX) += bb_askpass.o | 104 | lib-$(CONFIG_PLATFORM_POSIX) += bb_askpass.o |
103 | lib-$(CONFIG_PLATFORM_POSIX) += change_identity.o | 105 | lib-$(CONFIG_PLATFORM_POSIX) += change_identity.o |
104 | lib-$(CONFIG_PLATFORM_POSIX) += device_open.o | 106 | lib-$(CONFIG_PLATFORM_POSIX) += device_open.o |
diff --git a/libbb/alloc_affinity.c b/libbb/alloc_affinity.c new file mode 100644 index 000000000..b6d9f649a --- /dev/null +++ b/libbb/alloc_affinity.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 2024 Denys Vlasenko | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | #include <sched.h> | ||
10 | #include "libbb.h" | ||
11 | |||
12 | unsigned long* FAST_FUNC get_malloc_cpu_affinity(int pid, unsigned *sz) | ||
13 | { | ||
14 | unsigned long *mask = NULL; | ||
15 | unsigned sz_in_bytes = *sz; | ||
16 | |||
17 | for (;;) { | ||
18 | mask = xrealloc(mask, sz_in_bytes); | ||
19 | if (sched_getaffinity(pid, sz_in_bytes, (void*)mask) == 0) | ||
20 | break; /* got it */ | ||
21 | sz_in_bytes *= 2; | ||
22 | if (errno == EINVAL && (int)sz_in_bytes > 0) | ||
23 | continue; | ||
24 | bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); | ||
25 | } | ||
26 | //bb_error_msg("get mask[0]:%lx sz_in_bytes:%d", mask[0], sz_in_bytes); | ||
27 | *sz = sz_in_bytes; | ||
28 | return mask; | ||
29 | } | ||
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 811e3e475..bd4a17348 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -351,7 +351,7 @@ static unsigned save_string(char *dst, unsigned maxsize) | |||
351 | return i; | 351 | return i; |
352 | } | 352 | } |
353 | } | 353 | } |
354 | /* I thought just fputwc(c, stdout) would work. But no... */ | 354 | /* I thought just fputwc(c, stderr) would work. But no... */ |
355 | static void BB_PUTCHAR(wchar_t c) | 355 | static void BB_PUTCHAR(wchar_t c) |
356 | { | 356 | { |
357 | if (unicode_status == UNICODE_ON) { | 357 | if (unicode_status == UNICODE_ON) { |
@@ -360,11 +360,11 @@ static void BB_PUTCHAR(wchar_t c) | |||
360 | ssize_t len = wcrtomb(buf, c, &mbst); | 360 | ssize_t len = wcrtomb(buf, c, &mbst); |
361 | if (len > 0) { | 361 | if (len > 0) { |
362 | buf[len] = '\0'; | 362 | buf[len] = '\0'; |
363 | fputs_stdout(buf); | 363 | fputs(buf, stderr); |
364 | } | 364 | } |
365 | } else { | 365 | } else { |
366 | /* In this case, c is always one byte */ | 366 | /* In this case, c is always one byte */ |
367 | putchar(c); | 367 | bb_putchar_stderr(c); |
368 | } | 368 | } |
369 | } | 369 | } |
370 | # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS | 370 | # if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS |
@@ -410,7 +410,7 @@ static void save_string(char *dst, unsigned maxsize) | |||
410 | safe_strncpy(dst, command_ps, maxsize); | 410 | safe_strncpy(dst, command_ps, maxsize); |
411 | } | 411 | } |
412 | # endif | 412 | # endif |
413 | # define BB_PUTCHAR(c) bb_putchar(c) | 413 | # define BB_PUTCHAR(c) bb_putchar_stderr(c) |
414 | /* Should never be called: */ | 414 | /* Should never be called: */ |
415 | int adjust_width_and_validate_wc(unsigned *width_adj, int wc); | 415 | int adjust_width_and_validate_wc(unsigned *width_adj, int wc); |
416 | #endif | 416 | #endif |
@@ -469,7 +469,7 @@ static void put_cur_glyph_and_inc_cursor(void) | |||
469 | if (c == BB_NUL) | 469 | if (c == BB_NUL) |
470 | c = ' '; | 470 | c = ' '; |
471 | BB_PUTCHAR(c); | 471 | BB_PUTCHAR(c); |
472 | bb_putchar('\b'); | 472 | bb_putchar_stderr('\b'); |
473 | #endif | 473 | #endif |
474 | cmdedit_y++; | 474 | cmdedit_y++; |
475 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { | 475 | if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) { |
@@ -531,12 +531,12 @@ static void goto_new_line(void) | |||
531 | put_till_end_and_adv_cursor(); | 531 | put_till_end_and_adv_cursor(); |
532 | /* "cursor == 0" is only if prompt is "" and user input is empty */ | 532 | /* "cursor == 0" is only if prompt is "" and user input is empty */ |
533 | if (cursor == 0 || cmdedit_x != 0) | 533 | if (cursor == 0 || cmdedit_x != 0) |
534 | bb_putchar('\n'); | 534 | bb_putchar_stderr('\n'); |
535 | } | 535 | } |
536 | 536 | ||
537 | static void beep(void) | 537 | static void beep(void) |
538 | { | 538 | { |
539 | bb_putchar('\007'); | 539 | bb_putchar_stderr('\007'); |
540 | } | 540 | } |
541 | 541 | ||
542 | /* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor. | 542 | /* Full or last/sole prompt line, reset edit cursor, calculate terminal cursor. |
@@ -544,7 +544,10 @@ static void beep(void) | |||
544 | */ | 544 | */ |
545 | static void put_prompt_custom(bool is_full) | 545 | static void put_prompt_custom(bool is_full) |
546 | { | 546 | { |
547 | fputs_stdout((is_full ? cmdedit_prompt : prompt_last_line)); | 547 | /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html |
548 | * says that shells must write $PSn to stderr, not stdout. | ||
549 | */ | ||
550 | fputs((is_full ? cmdedit_prompt : prompt_last_line), stderr); | ||
548 | cursor = 0; | 551 | cursor = 0; |
549 | cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */ | 552 | cmdedit_y = cmdedit_prmt_len / cmdedit_termw; /* new quasireal y */ |
550 | cmdedit_x = cmdedit_prmt_len % cmdedit_termw; | 553 | cmdedit_x = cmdedit_prmt_len % cmdedit_termw; |
@@ -582,16 +585,16 @@ static void input_backward(unsigned num) | |||
582 | /* This is longer by 5 bytes on x86. | 585 | /* This is longer by 5 bytes on x86. |
583 | * Also gets miscompiled for ARM users | 586 | * Also gets miscompiled for ARM users |
584 | * (busybox.net/bugs/view.php?id=2274). | 587 | * (busybox.net/bugs/view.php?id=2274). |
585 | * printf(("\b\b\b\b" + 4) - num); | 588 | * fprintf(("\b\b\b\b" + 4) - num, stderr); |
586 | * return; | 589 | * return; |
587 | */ | 590 | */ |
588 | do { | 591 | do { |
589 | bb_putchar('\b'); | 592 | bb_putchar_stderr('\b'); |
590 | } while (--num); | 593 | } while (--num); |
591 | return; | 594 | return; |
592 | } | 595 | } |
593 | #endif | 596 | #endif |
594 | printf(ESC"[%uD", num); | 597 | fprintf(stderr, ESC"[%uD", num); |
595 | return; | 598 | return; |
596 | } | 599 | } |
597 | 600 | ||
@@ -616,7 +619,7 @@ static void input_backward(unsigned num) | |||
616 | */ | 619 | */ |
617 | unsigned sv_cursor; | 620 | unsigned sv_cursor; |
618 | /* go to 1st column; go up to first line */ | 621 | /* go to 1st column; go up to first line */ |
619 | printf("\r" ESC"[%uA", cmdedit_y); | 622 | fprintf(stderr, "\r" ESC"[%uA", cmdedit_y); |
620 | cmdedit_y = 0; | 623 | cmdedit_y = 0; |
621 | sv_cursor = cursor; | 624 | sv_cursor = cursor; |
622 | put_prompt_last_line(); /* sets cursor to 0 */ | 625 | put_prompt_last_line(); /* sets cursor to 0 */ |
@@ -631,12 +634,12 @@ static void input_backward(unsigned num) | |||
631 | cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw; | 634 | cmdedit_x = (cmdedit_termw * cmdedit_y - num) % cmdedit_termw; |
632 | cmdedit_y -= lines_up; | 635 | cmdedit_y -= lines_up; |
633 | /* go to 1st column; go up */ | 636 | /* go to 1st column; go up */ |
634 | printf("\r" ESC"[%uA", lines_up); | 637 | fprintf(stderr, "\r" ESC"[%uA", lines_up); |
635 | /* go to correct column. | 638 | /* go to correct column. |
636 | * xterm, konsole, Linux VT interpret 0 as 1 below! wow. | 639 | * xterm, konsole, Linux VT interpret 0 as 1 below! wow. |
637 | * need to *make sure* we skip it if cmdedit_x == 0 */ | 640 | * need to *make sure* we skip it if cmdedit_x == 0 */ |
638 | if (cmdedit_x) | 641 | if (cmdedit_x) |
639 | printf(ESC"[%uC", cmdedit_x); | 642 | fprintf(stderr, ESC"[%uC", cmdedit_x); |
640 | } | 643 | } |
641 | } | 644 | } |
642 | 645 | ||
@@ -644,11 +647,11 @@ static void input_backward(unsigned num) | |||
644 | static void draw_custom(int y, int back_cursor, bool is_full) | 647 | static void draw_custom(int y, int back_cursor, bool is_full) |
645 | { | 648 | { |
646 | if (y > 0) /* up y lines */ | 649 | if (y > 0) /* up y lines */ |
647 | printf(ESC"[%uA", y); | 650 | fprintf(stderr, ESC"[%uA", y); |
648 | bb_putchar('\r'); | 651 | bb_putchar_stderr('\r'); |
649 | put_prompt_custom(is_full); | 652 | put_prompt_custom(is_full); |
650 | put_till_end_and_adv_cursor(); | 653 | put_till_end_and_adv_cursor(); |
651 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); | 654 | fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr); |
652 | input_backward(back_cursor); | 655 | input_backward(back_cursor); |
653 | } | 656 | } |
654 | 657 | ||
@@ -693,7 +696,7 @@ static void input_delete(int save) | |||
693 | command_len--; | 696 | command_len--; |
694 | put_till_end_and_adv_cursor(); | 697 | put_till_end_and_adv_cursor(); |
695 | /* Last char is still visible, erase it (and more) */ | 698 | /* Last char is still visible, erase it (and more) */ |
696 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); | 699 | fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr); |
697 | input_backward(cursor - j); /* back to old pos cursor */ | 700 | input_backward(cursor - j); /* back to old pos cursor */ |
698 | } | 701 | } |
699 | 702 | ||
@@ -1110,8 +1113,8 @@ static void remove_chunk(int16_t *int_buf, int beg, int end) | |||
1110 | if (dbg_bmp) { | 1113 | if (dbg_bmp) { |
1111 | int i; | 1114 | int i; |
1112 | for (i = 0; int_buf[i]; i++) | 1115 | for (i = 0; int_buf[i]; i++) |
1113 | bb_putchar((unsigned char)int_buf[i]); | 1116 | bb_putchar_stderr((unsigned char)int_buf[i]); |
1114 | bb_putchar('\n'); | 1117 | bb_putchar_stderr('\n'); |
1115 | } | 1118 | } |
1116 | } | 1119 | } |
1117 | /* Caller ensures that match_buf points to a malloced buffer | 1120 | /* Caller ensures that match_buf points to a malloced buffer |
@@ -1294,7 +1297,7 @@ static void showfiles(void) | |||
1294 | int nc; | 1297 | int nc; |
1295 | 1298 | ||
1296 | for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) { | 1299 | for (nc = 1; nc < ncols && n+nrows < nfiles; n += nrows, nc++) { |
1297 | printf("%s%-*s", matches[n], | 1300 | fprintf(stderr, "%s%-*s", matches[n], |
1298 | (int)(column_width - unicode_strwidth(matches[n])), "" | 1301 | (int)(column_width - unicode_strwidth(matches[n])), "" |
1299 | ); | 1302 | ); |
1300 | } | 1303 | } |
@@ -1650,7 +1653,7 @@ void FAST_FUNC show_history(const line_input_t *st) | |||
1650 | if (!st) | 1653 | if (!st) |
1651 | return; | 1654 | return; |
1652 | for (i = 0; i < st->cnt_history; i++) | 1655 | for (i = 0; i < st->cnt_history; i++) |
1653 | printf("%4d %s\n", i, st->history[i]); | 1656 | fprintf(stderr, "%4d %s\n", i, st->history[i]); |
1654 | } | 1657 | } |
1655 | 1658 | ||
1656 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1659 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY |
@@ -2090,7 +2093,7 @@ static void ask_terminal(void) | |||
2090 | pfd.events = POLLIN; | 2093 | pfd.events = POLLIN; |
2091 | if (safe_poll(&pfd, 1, 0) == 0) { | 2094 | if (safe_poll(&pfd, 1, 0) == 0) { |
2092 | S.sent_ESC_br6n = 1; | 2095 | S.sent_ESC_br6n = 1; |
2093 | fputs_stdout(ESC"[6n"); | 2096 | fputs(ESC"[6n", stderr); |
2094 | fflush_all(); /* make terminal see it ASAP! */ | 2097 | fflush_all(); /* make terminal see it ASAP! */ |
2095 | } | 2098 | } |
2096 | } | 2099 | } |
@@ -2857,13 +2860,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2857 | /* Control-k -- clear to end of line */ | 2860 | /* Control-k -- clear to end of line */ |
2858 | command_ps[cursor] = BB_NUL; | 2861 | command_ps[cursor] = BB_NUL; |
2859 | command_len = cursor; | 2862 | command_len = cursor; |
2860 | printf(SEQ_CLEAR_TILL_END_OF_SCREEN); | 2863 | fputs(SEQ_CLEAR_TILL_END_OF_SCREEN, stderr); |
2861 | break; | 2864 | break; |
2862 | case CTRL('L'): | 2865 | case CTRL('L'): |
2863 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) | 2866 | vi_case(CTRL('L')|VI_CMDMODE_BIT:) |
2864 | /* Control-l -- clear screen */ | 2867 | /* Control-l -- clear screen */ |
2865 | /* cursor to top,left; clear to the end of screen */ | 2868 | /* cursor to top,left; clear to the end of screen */ |
2866 | printf(ESC"[H" ESC"[J"); | 2869 | fputs(ESC"[H" ESC"[J", stderr); |
2867 | draw_full(command_len - cursor); | 2870 | draw_full(command_len - cursor); |
2868 | break; | 2871 | break; |
2869 | #if MAX_HISTORY > 0 | 2872 | #if MAX_HISTORY > 0 |
@@ -3050,8 +3053,8 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
3050 | beep(); | 3053 | beep(); |
3051 | } else { | 3054 | } else { |
3052 | command_ps[cursor] = ic; | 3055 | command_ps[cursor] = ic; |
3053 | bb_putchar(ic); | 3056 | bb_putchar_stderr(ic); |
3054 | bb_putchar('\b'); | 3057 | bb_putchar_stderr('\b'); |
3055 | } | 3058 | } |
3056 | break; | 3059 | break; |
3057 | case '\x1b': /* ESC */ | 3060 | case '\x1b': /* ESC */ |
@@ -3249,7 +3252,10 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
3249 | #undef read_line_input | 3252 | #undef read_line_input |
3250 | int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) | 3253 | int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) |
3251 | { | 3254 | { |
3252 | fputs_stdout(prompt); | 3255 | /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html |
3256 | * says that shells must write $PSn to stderr, not stdout. | ||
3257 | */ | ||
3258 | fputs(prompt, stderr); | ||
3253 | fflush_all(); | 3259 | fflush_all(); |
3254 | if (!fgets(command, maxsize, stdin)) | 3260 | if (!fgets(command, maxsize, stdin)) |
3255 | return -1; | 3261 | return -1; |
diff --git a/libbb/popcnt.c b/libbb/popcnt.c new file mode 100644 index 000000000..fe8cd240f --- /dev/null +++ b/libbb/popcnt.c | |||
@@ -0,0 +1,46 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 2024 Denys Vlasenko | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | #include "libbb.h" | ||
10 | |||
11 | unsigned FAST_FUNC bb_popcnt_32(uint32_t m) | ||
12 | { | ||
13 | /* replace each 2 bit group with the count of set bits in it */ | ||
14 | /* 00->00 01->01 10->01 11->10 */ | ||
15 | m = m - ((m >> 1) & 0x55555555); | ||
16 | /* in each 4 bit group, add two 2-bit counts */ | ||
17 | m = (m & 0x33333333) + ((m >> 2) & 0x33333333); | ||
18 | /* in each 8 bit group, add two 4-bit counts (in fact, 3-bit, 0nnn with n=0..4) */ | ||
19 | m = (m + (m >> 4)) & 0x0f0f0f0f; | ||
20 | #if 1 /* assume 32*32->32 multiply is fast */ | ||
21 | m = m * 0x01010101; /* top byte = m + (m<<8) + (m<<16) + (m<<24) */ | ||
22 | return m >> 24; | ||
23 | #else | ||
24 | /* 0000aaaa0000bbbb0000cccc0000dddd */ | ||
25 | /* + 0000aaaa0000bbbb0000cccc */ | ||
26 | /* = 0000xxxx000_a+b_000xxxxx000_c+d_ (we don't care about x bits) */ | ||
27 | m += m >> 8; /* in each 16-bit group, lowest 5 bits is the count */ | ||
28 | /* 0000xxxx000_a+b_000xxxxx000_c+d_ */ | ||
29 | /* + 0000xxxx000_a+b_ */ | ||
30 | /* = 0000xxxx000xxxxx00xxxxxx00a+b+cd */ | ||
31 | m += m >> 16; /* in each 32-bit group, lowest 6 bits is the count */ | ||
32 | return m & 0x3f; /* clear x bits */ | ||
33 | #endif | ||
34 | } | ||
35 | |||
36 | #if ULONG_MAX > 0xffffffff | ||
37 | unsigned FAST_FUNC bb_popcnt_long(unsigned long m) | ||
38 | { | ||
39 | BUILD_BUG_ON(sizeof(m) != 8); | ||
40 | /* 64-bit version of bb_popcnt_32 exists, but it uses 64-bit constants, | ||
41 | * which are awkward to generate on assembly level on most CPUs. | ||
42 | * For now, just add two 32-bit counts: | ||
43 | */ | ||
44 | return bb_popcnt_32((uint32_t)m) + bb_popcnt_32((uint32_t)(m >> 32)); | ||
45 | } | ||
46 | #endif | ||