aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Kbuild.src2
-rw-r--r--libbb/alloc_affinity.c29
-rw-r--r--libbb/lineedit.c62
-rw-r--r--libbb/popcnt.c46
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
58lib-y += perror_msg.o 58lib-y += perror_msg.o
59lib-y += perror_nomsg_and_die.o 59lib-y += perror_nomsg_and_die.o
60lib-y += platform.o 60lib-y += platform.o
61lib-y += popcnt.o
61lib-y += printable.o 62lib-y += printable.o
62lib-y += printable_string.o 63lib-y += printable_string.o
63lib-y += process_escape_sequence.o 64lib-y += process_escape_sequence.o
@@ -99,6 +100,7 @@ lib-y += xgetcwd.o
99lib-y += xreadlink.o 100lib-y += xreadlink.o
100lib-y += xrealloc_vector.o 101lib-y += xrealloc_vector.o
101 102
103lib-$(CONFIG_PLATFORM_POSIX) += alloc_affinity.o
102lib-$(CONFIG_PLATFORM_POSIX) += bb_askpass.o 104lib-$(CONFIG_PLATFORM_POSIX) += bb_askpass.o
103lib-$(CONFIG_PLATFORM_POSIX) += change_identity.o 105lib-$(CONFIG_PLATFORM_POSIX) += change_identity.o
104lib-$(CONFIG_PLATFORM_POSIX) += device_open.o 106lib-$(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
12unsigned 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... */
355static void BB_PUTCHAR(wchar_t c) 355static 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: */
415int adjust_width_and_validate_wc(unsigned *width_adj, int wc); 415int 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
537static void beep(void) 537static 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 */
545static void put_prompt_custom(bool is_full) 545static 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)
644static void draw_custom(int y, int back_cursor, bool is_full) 647static 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
3250int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) 3253int 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
11unsigned 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
37unsigned 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