history library can now read history from non-regular files; fix for readline char search and macros; better fix for PROMPT_COMMAND and aliases ending in newlines; fix for casting COMMAND * and SIMPLE_COM * when parsing |&; fix to avoid undefined behavior when performing left and right arithmetic shifts

This commit is contained in:
Chet Ramey
2025-08-01 16:26:31 -04:00
parent 01070d4324
commit c1d9c08853
19 changed files with 217 additions and 45 deletions
+78 -6
View File
@@ -58,6 +58,7 @@
# include <unistd.h>
#endif
#include <string.h>
#include <ctype.h>
#if defined (__EMX__)
@@ -145,6 +146,9 @@ static int histfile_backup (const char *, const char *);
static int histfile_restore (const char *, const char *);
static int history_rename (const char *, const char *);
static int history_write_slow (int, HIST_ENTRY **, int, int);
static ssize_t history_read_slow (int, char **);
/* Return the string that should be used in the place of this
filename. This only matters when you don't specify the
filename to read_history (), or write_history (). */
@@ -258,6 +262,69 @@ read_history (const char *filename)
return (read_history_range (filename, 0, -1));
}
#define RBUFSIZE 4096
/* Read from a non-regular file until EOF, assuming we can't trust the file
size as reported by fstat. */
static ssize_t
history_read_slow (int fd, char **bufp)
{
char *ret, *r;
size_t retsize, retlen;
char rbuf[RBUFSIZE];
ssize_t nr, nw;
if (bufp == 0)
return -1;
retsize = RBUFSIZE;
ret = malloc(retsize);
if (ret == 0)
return -1;
retlen = 0;
while (nr = read (fd, rbuf, sizeof (rbuf)))
{
if (nr < 0)
{
free (ret);
*bufp = NULL;
return -1;
}
if (retlen >= retsize - nr - 1)
{
retsize *= 2;
r = realloc (ret, retsize);
if (r == 0)
{
free(ret);
*bufp = NULL;
return -1;
}
ret = r;
}
memcpy (ret + retlen, rbuf, nr);
retlen += nr;
}
if (retlen + 1 >= retsize)
{
retsize += 1;
r = realloc (ret, retsize);
if (r == 0)
{
free (ret);
*bufp = NULL;
return -1;
}
ret = r;
}
ret[retlen] = '\0';
*bufp = ret;
return (ssize_t)retlen;
}
/* Read a range of lines from FILENAME, adding them to the history list.
Start reading at the FROM'th line and end at the TO'th. If FROM
is zero, start at the beginning. If TO is less than FROM, read
@@ -294,12 +361,15 @@ read_history_range (const char *filename, int from, int to)
if (S_ISREG (finfo.st_mode) == 0)
{
#ifdef EFTYPE
errno = EFTYPE;
#else
errno = EINVAL;
#endif
goto error_and_exit;
chars_read = history_read_slow (file, &buffer);
if (chars_read == 0)
{
free (buffer);
free (input);
close (file);
return 0;
}
goto after_file_read;
}
else
{
@@ -341,6 +411,8 @@ read_history_range (const char *filename, int from, int to)
chars_read = read (file, buffer, file_size);
#endif
after_file_read:
if (chars_read < 0)
{
error_and_exit:
+1
View File
@@ -137,6 +137,7 @@ _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
else
{
key = _rl_bracketed_read_key ();
/* XXX - add to macro def? */
rl_restore_prompt ();
rl_clear_message ();
RL_UNSETSTATE(RL_STATE_NUMERICARG);
+9 -1
View File
@@ -1786,13 +1786,17 @@ static int
_rl_char_search (int count, int fdir, int bdir)
{
char mbchar[MB_LEN_MAX];
int mb_len;
int mb_len, i;
mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
if (mb_len <= 0)
return 1;
if (RL_ISSTATE (RL_STATE_MACRODEF))
for (i = 0; i < mb_len; i++)
_rl_add_macro_char (mbchar[i]);
if (count < 0)
return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
else
@@ -1805,9 +1809,13 @@ _rl_char_search (int count, int fdir, int bdir)
int c;
c = _rl_bracketed_read_key ();
if (c < 0)
return 1;
if (RL_ISSTATE (RL_STATE_MACRODEF))
_rl_add_macro_char (c);
if (count < 0)
return (_rl_char_search_internal (-count, bdir, c));
else