diff options
author | Ron Yorston <rmy@pobox.com> | 2025-08-10 07:46:58 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2025-08-10 07:46:58 +0100 |
commit | c70a65f36c017f6feb7e86415bec1a644e71dbab (patch) | |
tree | e1c3afca24fd35bd2ff142cc0ea83151fdfa5996 /libbb | |
parent | dcb4966c5492aeb67494d9ffdc58ff3054add443 (diff) | |
parent | 84766710f420dd444e2a03d33a1915ce55661e67 (diff) | |
download | busybox-w32-merge.tar.gz busybox-w32-merge.tar.bz2 busybox-w32-merge.zip |
Merge branch 'busybox' into mergemerge
Diffstat (limited to '')
-rw-r--r-- | libbb/Config.src | 4 | ||||
-rw-r--r-- | libbb/const_hack.c | 29 | ||||
-rw-r--r-- | libbb/dump.c | 10 | ||||
-rw-r--r-- | libbb/lineedit.c | 112 | ||||
-rw-r--r-- | libbb/poll_with_signals.c | 48 | ||||
-rw-r--r-- | libbb/read_key.c | 25 |
6 files changed, 154 insertions, 74 deletions
diff --git a/libbb/Config.src b/libbb/Config.src index ed6521c33..eff327c2a 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -192,8 +192,8 @@ config FEATURE_EDITING_VI | |||
192 | config FEATURE_EDITING_HISTORY | 192 | config FEATURE_EDITING_HISTORY |
193 | int "History size" | 193 | int "History size" |
194 | # Don't allow way too big values here, code uses fixed "char *history[N]" struct member | 194 | # Don't allow way too big values here, code uses fixed "char *history[N]" struct member |
195 | range 0 9999 | 195 | range 0 2000 |
196 | default 255 | 196 | default 200 |
197 | depends on FEATURE_EDITING | 197 | depends on FEATURE_EDITING |
198 | help | 198 | help |
199 | Specify command history size (0 - disable). | 199 | Specify command history size (0 - disable). |
diff --git a/libbb/const_hack.c b/libbb/const_hack.c index 75163fede..1d175481b 100644 --- a/libbb/const_hack.c +++ b/libbb/const_hack.c | |||
@@ -9,18 +9,27 @@ | |||
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | #if defined(__clang_major__) && __clang_major__ >= 9 | 11 | #if defined(__clang_major__) && __clang_major__ >= 9 |
12 | void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size) | 12 | /* Clang/llvm drops assignment to "constant" storage. Silently. |
13 | * Needs serious convincing to not eliminate the store. | ||
14 | */ | ||
15 | static ALWAYS_INLINE void* not_const_pp(const void *p) | ||
13 | { | 16 | { |
14 | ASSIGN_CONST_PTR(pptr, xzalloc(size)); | 17 | void *pp; |
18 | asm volatile ( | ||
19 | "# forget that p points to const" | ||
20 | : /*outputs*/ "=r" (pp) | ||
21 | : /*inputs*/ "0" (p) | ||
22 | ); | ||
23 | return pp; | ||
15 | } | 24 | } |
16 | 25 | void FAST_FUNC ASSIGN_CONST_PTR(const void *pptr, void *v) | |
17 | # if ENABLE_PLATFORM_MINGW32 | 26 | { |
18 | void FAST_FUNC ASSIGN_CONST_PTR(const void *pptr, const void *v) | 27 | *(void**)not_const_pp(pptr) = v; |
28 | barrier(); | ||
29 | } | ||
30 | void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size) | ||
19 | { | 31 | { |
20 | do { | 32 | *(void**)not_const_pp(pptr) = xzalloc(size); |
21 | *(void**)not_const_pp(pptr) = (void*)(v); | 33 | barrier(); |
22 | barrier(); | ||
23 | } while (0); | ||
24 | } | 34 | } |
25 | # endif | ||
26 | #endif | 35 | #endif |
diff --git a/libbb/dump.c b/libbb/dump.c index aa57eca8c..b2abe85af 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -703,15 +703,21 @@ static NOINLINE void display(priv_dumper_t* dumper) | |||
703 | conv_u(pr, bp); | 703 | conv_u(pr, bp); |
704 | break; | 704 | break; |
705 | case F_UINT: { | 705 | case F_UINT: { |
706 | union { | ||
707 | uint16_t uval16; | ||
708 | uint32_t uval32; | ||
709 | } u; | ||
706 | unsigned value = (unsigned char)*bp; | 710 | unsigned value = (unsigned char)*bp; |
707 | switch (pr->bcnt) { | 711 | switch (pr->bcnt) { |
708 | case 1: | 712 | case 1: |
709 | break; | 713 | break; |
710 | case 2: | 714 | case 2: |
711 | move_from_unaligned16(value, bp); | 715 | move_from_unaligned16(u.uval16, bp); |
716 | value = u.uval16; | ||
712 | break; | 717 | break; |
713 | case 4: | 718 | case 4: |
714 | move_from_unaligned32(value, bp); | 719 | move_from_unaligned32(u.uval32, bp); |
720 | value = u.uval32; | ||
715 | break; | 721 | break; |
716 | /* case 8: no users yet */ | 722 | /* case 8: no users yet */ |
717 | } | 723 | } |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 8e2b37853..c8a0f37fe 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -457,7 +457,7 @@ static void put_cur_glyph_and_inc_cursor(void) | |||
457 | * have automargin (IOW: it is moving cursor to next line | 457 | * have automargin (IOW: it is moving cursor to next line |
458 | * by itself (which is wrong for VT-10x terminals)), | 458 | * by itself (which is wrong for VT-10x terminals)), |
459 | * this will break things: there will be one extra empty line */ | 459 | * this will break things: there will be one extra empty line */ |
460 | puts("\r"); /* + implicit '\n' */ | 460 | fputs("\r\n", stderr); |
461 | #else | 461 | #else |
462 | /* VT-10x terminals don't wrap cursor to next line when last char | 462 | /* VT-10x terminals don't wrap cursor to next line when last char |
463 | * on the line is printed - cursor stays "over" this char. | 463 | * on the line is printed - cursor stays "over" this char. |
@@ -1302,9 +1302,10 @@ static void showfiles(void) | |||
1302 | ); | 1302 | ); |
1303 | } | 1303 | } |
1304 | if (ENABLE_UNICODE_SUPPORT) | 1304 | if (ENABLE_UNICODE_SUPPORT) |
1305 | puts(printable_string(matches[n])); | 1305 | fputs(printable_string(matches[n]), stderr); |
1306 | else | 1306 | else |
1307 | puts(matches[n]); | 1307 | fputs(matches[n], stderr); |
1308 | bb_putchar_stderr('\n'); | ||
1308 | } | 1309 | } |
1309 | } | 1310 | } |
1310 | 1311 | ||
@@ -1595,8 +1596,8 @@ unsigned FAST_FUNC size_from_HISTFILESIZE(const char *hp) | |||
1595 | # endif | 1596 | # endif |
1596 | if (hp) { | 1597 | if (hp) { |
1597 | size = atoi(hp); | 1598 | size = atoi(hp); |
1598 | if (size <= 0) | 1599 | if (size < 0) |
1599 | return 1; | 1600 | return 0; |
1600 | if (size > MAX_HISTORY) | 1601 | if (size > MAX_HISTORY) |
1601 | return MAX_HISTORY; | 1602 | return MAX_HISTORY; |
1602 | } | 1603 | } |
@@ -1690,18 +1691,21 @@ static void load_history(line_input_t *st_parm) | |||
1690 | /* NB: do not trash old history if file can't be opened */ | 1691 | /* NB: do not trash old history if file can't be opened */ |
1691 | 1692 | ||
1692 | fp = fopen_for_read(st_parm->hist_file); | 1693 | fp = fopen_for_read(st_parm->hist_file); |
1693 | if (fp) { | 1694 | if (!fp) |
1694 | /* clean up old history */ | 1695 | return; |
1695 | for (idx = st_parm->cnt_history; idx > 0;) { | 1696 | |
1696 | idx--; | 1697 | /* clean up old history */ |
1697 | free(st_parm->history[idx]); | 1698 | for (idx = st_parm->cnt_history; idx > 0;) { |
1698 | st_parm->history[idx] = NULL; | 1699 | idx--; |
1699 | } | 1700 | free(st_parm->history[idx]); |
1701 | st_parm->history[idx] = NULL; | ||
1702 | } | ||
1700 | 1703 | ||
1701 | /* fill temp_h[], retaining only last MAX_HISTORY lines */ | 1704 | /* fill temp_h[], retaining only last max_history lines */ |
1702 | memset(temp_h, 0, sizeof(temp_h)); | 1705 | memset(temp_h, 0, sizeof(temp_h)); |
1703 | idx = 0; | 1706 | idx = 0; |
1704 | st_parm->cnt_history_in_file = 0; | 1707 | st_parm->cnt_history_in_file = 0; |
1708 | if (st_parm->max_history != 0) { | ||
1705 | while ((line = xmalloc_fgetline(fp)) != NULL) { | 1709 | while ((line = xmalloc_fgetline(fp)) != NULL) { |
1706 | if (line[0] == '\0') { | 1710 | if (line[0] == '\0') { |
1707 | free(line); | 1711 | free(line); |
@@ -1714,34 +1718,34 @@ static void load_history(line_input_t *st_parm) | |||
1714 | if (idx == st_parm->max_history) | 1718 | if (idx == st_parm->max_history) |
1715 | idx = 0; | 1719 | idx = 0; |
1716 | } | 1720 | } |
1717 | fclose(fp); | 1721 | } |
1718 | 1722 | fclose(fp); | |
1719 | /* find first non-NULL temp_h[], if any */ | ||
1720 | if (st_parm->cnt_history_in_file) { | ||
1721 | while (temp_h[idx] == NULL) { | ||
1722 | idx++; | ||
1723 | if (idx == st_parm->max_history) | ||
1724 | idx = 0; | ||
1725 | } | ||
1726 | } | ||
1727 | 1723 | ||
1728 | /* copy temp_h[] to st_parm->history[] */ | 1724 | /* find first non-NULL temp_h[], if any */ |
1729 | for (i = 0; i < st_parm->max_history;) { | 1725 | if (st_parm->cnt_history_in_file != 0) { |
1730 | line = temp_h[idx]; | 1726 | while (temp_h[idx] == NULL) { |
1731 | if (!line) | ||
1732 | break; | ||
1733 | idx++; | 1727 | idx++; |
1734 | if (idx == st_parm->max_history) | 1728 | if (idx == st_parm->max_history) |
1735 | idx = 0; | 1729 | idx = 0; |
1736 | line_len = strlen(line); | ||
1737 | if (line_len >= MAX_LINELEN) | ||
1738 | line[MAX_LINELEN-1] = '\0'; | ||
1739 | st_parm->history[i++] = line; | ||
1740 | } | 1730 | } |
1741 | st_parm->cnt_history = i; | ||
1742 | if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) | ||
1743 | st_parm->cnt_history_in_file = i; | ||
1744 | } | 1731 | } |
1732 | |||
1733 | /* copy temp_h[] to st_parm->history[] */ | ||
1734 | for (i = 0; i < st_parm->max_history;) { | ||
1735 | line = temp_h[idx]; | ||
1736 | if (!line) | ||
1737 | break; | ||
1738 | idx++; | ||
1739 | if (idx == st_parm->max_history) | ||
1740 | idx = 0; | ||
1741 | line_len = strlen(line); | ||
1742 | if (line_len >= MAX_LINELEN) | ||
1743 | line[MAX_LINELEN-1] = '\0'; | ||
1744 | st_parm->history[i++] = line; | ||
1745 | } | ||
1746 | st_parm->cnt_history = i; | ||
1747 | if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) | ||
1748 | st_parm->cnt_history_in_file = i; | ||
1745 | } | 1749 | } |
1746 | 1750 | ||
1747 | # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | 1751 | # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
@@ -1749,17 +1753,27 @@ void FAST_FUNC save_history(line_input_t *st) | |||
1749 | { | 1753 | { |
1750 | FILE *fp; | 1754 | FILE *fp; |
1751 | 1755 | ||
1752 | if (!st || !st->hist_file) | 1756 | /* bash compat: HISTFILE="" disables history saving */ |
1757 | if (!st || !st->hist_file || !state->hist_file[0]) | ||
1753 | return; | 1758 | return; |
1754 | if (st->cnt_history <= st->cnt_history_in_file) | 1759 | if (st->cnt_history <= st->cnt_history_in_file) |
1755 | return; | 1760 | return; /* no new entries were added */ |
1761 | /* note: if st->max_history is 0, we do not abort: we truncate the history to 0 lines */ | ||
1756 | 1762 | ||
1757 | fp = fopen(st->hist_file, "a"); | 1763 | fp = fopen(st->hist_file, (st->max_history == 0 ? "w" : "a")); |
1758 | if (fp) { | 1764 | if (fp) { |
1759 | int i, fd; | 1765 | int i, fd; |
1760 | char *new_name; | 1766 | char *new_name; |
1761 | line_input_t *st_temp; | 1767 | line_input_t *st_temp; |
1762 | 1768 | ||
1769 | /* max_history==0 needs special-casing in general code, | ||
1770 | * just handle it in a simpler way: */ | ||
1771 | if (st->max_history == 0) { | ||
1772 | /* fopen("w") already truncated it */ | ||
1773 | fclose(fp); | ||
1774 | return; | ||
1775 | } | ||
1776 | |||
1763 | for (i = st->cnt_history_in_file; i < st->cnt_history; i++) | 1777 | for (i = st->cnt_history_in_file; i < st->cnt_history; i++) |
1764 | fprintf(fp, "%s\n", st->history[i]); | 1778 | fprintf(fp, "%s\n", st->history[i]); |
1765 | fclose(fp); | 1779 | fclose(fp); |
@@ -1769,6 +1783,8 @@ void FAST_FUNC save_history(line_input_t *st) | |||
1769 | st_temp = new_line_input_t(st->flags); | 1783 | st_temp = new_line_input_t(st->flags); |
1770 | st_temp->hist_file = st->hist_file; | 1784 | st_temp->hist_file = st->hist_file; |
1771 | st_temp->max_history = st->max_history; | 1785 | st_temp->max_history = st->max_history; |
1786 | /* load no more than max_history last lines */ | ||
1787 | /* (in unlikely case that file disappeared, st_temp gets empty history) */ | ||
1772 | load_history(st_temp); | 1788 | load_history(st_temp); |
1773 | 1789 | ||
1774 | /* write out temp file and replace hist_file atomically */ | 1790 | /* write out temp file and replace hist_file atomically */ |
@@ -1792,13 +1808,13 @@ static void save_history(char *str) | |||
1792 | int fd; | 1808 | int fd; |
1793 | int len, len2; | 1809 | int len, len2; |
1794 | 1810 | ||
1795 | if (!state->hist_file) | 1811 | /* bash compat: HISTFILE="" disables history saving */ |
1812 | if (!state->hist_file || !state->hist_file[0]) | ||
1796 | return; | 1813 | return; |
1797 | 1814 | ||
1798 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600); | 1815 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600); |
1799 | if (fd < 0) | 1816 | if (fd < 0) |
1800 | return; | 1817 | return; |
1801 | xlseek(fd, 0, SEEK_END); /* paranoia */ | ||
1802 | len = strlen(str); | 1818 | len = strlen(str); |
1803 | str[len] = '\n'; /* we (try to) do atomic write */ | 1819 | str[len] = '\n'; /* we (try to) do atomic write */ |
1804 | len2 = full_write(fd, str, len + 1); | 1820 | len2 = full_write(fd, str, len + 1); |
@@ -1853,13 +1869,10 @@ static void remember_in_history(char *str) | |||
1853 | if (str[0] == '\0') | 1869 | if (str[0] == '\0') |
1854 | return; | 1870 | return; |
1855 | i = state->cnt_history; | 1871 | i = state->cnt_history; |
1856 | /* Don't save dupes */ | 1872 | /* Don't save dups */ |
1857 | if (i && strcmp(state->history[i-1], str) == 0) | 1873 | if (i != 0 && strcmp(state->history[i-1], str) == 0) |
1858 | return; | 1874 | return; |
1859 | 1875 | ||
1860 | free(state->history[state->max_history]); /* redundant, paranoia */ | ||
1861 | state->history[state->max_history] = NULL; /* redundant, paranoia */ | ||
1862 | |||
1863 | /* If history[] is full, remove the oldest command */ | 1876 | /* If history[] is full, remove the oldest command */ |
1864 | /* we need to keep history[state->max_history] empty, hence >=, not > */ | 1877 | /* we need to keep history[state->max_history] empty, hence >=, not > */ |
1865 | if (i >= state->max_history) { | 1878 | if (i >= state->max_history) { |
@@ -1872,7 +1885,7 @@ static void remember_in_history(char *str) | |||
1872 | state->cnt_history_in_file--; | 1885 | state->cnt_history_in_file--; |
1873 | # endif | 1886 | # endif |
1874 | } | 1887 | } |
1875 | /* i <= state->max_history-1 */ | 1888 | /* i < state->max_history */ |
1876 | state->history[i++] = xstrdup(str); | 1889 | state->history[i++] = xstrdup(str); |
1877 | /* i <= state->max_history */ | 1890 | /* i <= state->max_history */ |
1878 | state->cur_history = i; | 1891 | state->cur_history = i; |
@@ -2388,7 +2401,6 @@ static int lineedit_read_key(char *read_key_buffer, int timeout) | |||
2388 | errno = EINTR; | 2401 | errno = EINTR; |
2389 | return -1; | 2402 | return -1; |
2390 | } | 2403 | } |
2391 | //FIXME: still races here with signals, but small window to poll() inside read_key | ||
2392 | IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) | 2404 | IF_FEATURE_EDITING_WINCH(S.ok_to_redraw = 1;) |
2393 | /* errno = 0; - read_key does this itself */ | 2405 | /* errno = 0; - read_key does this itself */ |
2394 | ic = read_key(STDIN_FILENO, read_key_buffer, timeout); | 2406 | ic = read_key(STDIN_FILENO, read_key_buffer, timeout); |
diff --git a/libbb/poll_with_signals.c b/libbb/poll_with_signals.c new file mode 100644 index 000000000..d3c005418 --- /dev/null +++ b/libbb/poll_with_signals.c | |||
@@ -0,0 +1,48 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 2025 Denys Vlasenko <vda.linux@googlemail.com> | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | //kbuild:lib-$(CONFIG_PLATFORM_POSIX) += poll_with_signals.o | ||
10 | |||
11 | #include "libbb.h" | ||
12 | |||
13 | /* Shells, for example, need their line input and "read" builtin | ||
14 | * to be interruptible, and the naive handling of it a-la: | ||
15 | * if (bb_got_signal) { | ||
16 | * errno = EINTR; | ||
17 | * return -1; | ||
18 | * } | ||
19 | * poll(pfd, 1, -1); // signal here would set EINTR | ||
20 | * is racy. | ||
21 | * This is a bit heavy-handed, but safe wrt races: | ||
22 | */ | ||
23 | int FAST_FUNC check_got_signal_and_poll(struct pollfd pfd[1], int timeout) | ||
24 | { | ||
25 | int n; | ||
26 | struct timespec tv; | ||
27 | sigset_t orig_mask; | ||
28 | |||
29 | if (bb_got_signal) /* optimization */ | ||
30 | goto eintr; | ||
31 | |||
32 | if (timeout >= 0) { | ||
33 | tv.tv_sec = timeout / 1000; | ||
34 | tv.tv_nsec = (timeout % 1000) * 1000000; | ||
35 | } | ||
36 | /* test bb_got_signal, then poll(), atomically wrt signals */ | ||
37 | sigfillset(&orig_mask); | ||
38 | sigprocmask2(SIG_BLOCK, &orig_mask); | ||
39 | if (bb_got_signal) { | ||
40 | sigprocmask2(SIG_SETMASK, &orig_mask); | ||
41 | eintr: | ||
42 | errno = EINTR; /* inform the caller that we got a signal */ | ||
43 | return -1; | ||
44 | } | ||
45 | n = ppoll(pfd, 1, timeout >= 0 ? &tv : NULL, &orig_mask); | ||
46 | sigprocmask2(SIG_SETMASK, &orig_mask); | ||
47 | return n; | ||
48 | } | ||
diff --git a/libbb/read_key.c b/libbb/read_key.c index 54886cc9c..2414105ee 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | 12 | int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) |
13 | { | 13 | { |
14 | struct pollfd pfd; | 14 | struct pollfd pfd[1]; |
15 | const char *seq; | 15 | const char *seq; |
16 | int n; | 16 | int n; |
17 | 17 | ||
@@ -117,8 +117,8 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
117 | return windows_read_key(fd, buffer, timeout); | 117 | return windows_read_key(fd, buffer, timeout); |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | pfd.fd = fd; | 120 | pfd->fd = fd; |
121 | pfd.events = POLLIN; | 121 | pfd->events = POLLIN; |
122 | 122 | ||
123 | buffer++; /* saved chars counter is in buffer[-1] now */ | 123 | buffer++; /* saved chars counter is in buffer[-1] now */ |
124 | 124 | ||
@@ -126,12 +126,16 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
126 | errno = 0; | 126 | errno = 0; |
127 | n = (unsigned char)buffer[-1]; | 127 | n = (unsigned char)buffer[-1]; |
128 | if (n == 0) { | 128 | if (n == 0) { |
129 | /* If no data, wait for input. | 129 | /* No data. Wait for input. */ |
130 | * If requested, wait TIMEOUT ms. TIMEOUT = -1 is useful | 130 | |
131 | * if fd can be in non-blocking mode. | 131 | /* timeout == -2 means "do not poll". Else: */ |
132 | */ | ||
133 | if (timeout >= -1) { | 132 | if (timeout >= -1) { |
134 | n = poll(&pfd, 1, timeout); | 133 | /* We must poll even if timeout == -1: |
134 | * we want to be interrupted if signal arrives, | ||
135 | * regardless of SA_RESTART-ness of that signal! | ||
136 | */ | ||
137 | /* test bb_got_signal, then poll(), atomically wrt signals */ | ||
138 | n = check_got_signal_and_poll(pfd, timeout); | ||
135 | if (n < 0 && errno == EINTR) | 139 | if (n < 0 && errno == EINTR) |
136 | return n; | 140 | return n; |
137 | if (n == 0) { | 141 | if (n == 0) { |
@@ -140,6 +144,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
140 | return -1; | 144 | return -1; |
141 | } | 145 | } |
142 | } | 146 | } |
147 | |||
143 | /* It is tempting to read more than one byte here, | 148 | /* It is tempting to read more than one byte here, |
144 | * but it breaks pasting. Example: at shell prompt, | 149 | * but it breaks pasting. Example: at shell prompt, |
145 | * user presses "c","a","t" and then pastes "\nline\n". | 150 | * user presses "c","a","t" and then pastes "\nline\n". |
@@ -178,7 +183,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
178 | * so if we block for long it's not really an escape sequence. | 183 | * so if we block for long it's not really an escape sequence. |
179 | * Timeout is needed to reconnect escape sequences | 184 | * Timeout is needed to reconnect escape sequences |
180 | * split up by transmission over a serial console. */ | 185 | * split up by transmission over a serial console. */ |
181 | if (safe_poll(&pfd, 1, 50) == 0) { | 186 | if (safe_poll(pfd, 1, 50) == 0) { |
182 | /* No more data! | 187 | /* No more data! |
183 | * Array is sorted from shortest to longest, | 188 | * Array is sorted from shortest to longest, |
184 | * we can't match anything later in array - | 189 | * we can't match anything later in array - |
@@ -227,7 +232,7 @@ int64_t FAST_FUNC read_key(int fd, char *buffer, int timeout) | |||
227 | * n = bytes read. Try to read more until we time out. | 232 | * n = bytes read. Try to read more until we time out. |
228 | */ | 233 | */ |
229 | while (n < KEYCODE_BUFFER_SIZE-1) { /* 1 for count byte at buffer[-1] */ | 234 | while (n < KEYCODE_BUFFER_SIZE-1) { /* 1 for count byte at buffer[-1] */ |
230 | if (safe_poll(&pfd, 1, 50) == 0) { | 235 | if (safe_poll(pfd, 1, 50) == 0) { |
231 | /* No more data! */ | 236 | /* No more data! */ |
232 | break; | 237 | break; |
233 | } | 238 | } |