Re: [PATCH] Save more readline state when running compgen

2023-03-22 Thread Chet Ramey

On 3/21/23 7:00 PM, Koichi Murase wrote:

2023年3月22日(水) 6:00 Greg Wooledge :

I don't use programmable completion, but I could *imagine* someone using
a temp file to store the results, then using mapfile to read them back
in, to avoid the fork() that the command substitution uses.


I wouldn't say my usage is typical, but I do that in fact. I have a
shell function to do that for an arbitrary command (which I once
posted in help-bash [1] but now it's old. The latest is [2]) and use
it everywhere.


So is your function suite dependent on the compgen invocations changing
the readline completion state?

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/




Re: [PATCH] Save more readline state when running compgen

2023-03-22 Thread Koichi Murase
2023年3月22日(水) 22:51 Chet Ramey :
> > I wouldn't say my usage is typical, but I do that in fact. I have a
> > shell function to do that for an arbitrary command (which I once
> > posted in help-bash [1] but now it's old. The latest is [2]) and use
> > it everywhere.
>
> So is your function suite dependent on the compgen invocations changing
> the readline completion state?

I mean the function itself does not rely on the compgen, but I call
compgen through such a function so the compgen would be executed in
the main shell. If I understand this report correctly, it changes the
state of Readline. But I'm not sure if it affects any observable
behavior in my specific setup because I re-implement the entire
completion so these `compgen's are not called from inside the readline
bindable function `complete'. Do you think calling `compgen', which
leaves the state of `compopt -o filenames', etc., outside the bindable
function `compete' would affect any behaviors?

--
Koichi



[PATCH] Don't dump core if localtime returns NULL

2023-03-22 Thread Paul Eggert
* examples/loadables/stat.c (stattime):
* examples/loadables/strftime.c (strftime_builtin):
* lib/readline/examples/histexamp.c (main):
* parse.y (decode_prompt_string):
Do something reasonable if localtime returns NULL.
This can happen, for example, if someone sets the system
clock to such an absurdly high value so that tm_year cannot
represent the year, and localtime returns NULL with
errno == EOVERFLOW.
---
 examples/loadables/stat.c |  2 ++
 examples/loadables/strftime.c |  7 ++
 lib/readline/examples/histexamp.c |  6 +++--
 parse.y   | 40 ++-
 4 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/examples/loadables/stat.c b/examples/loadables/stat.c
index 1e60e7b6..cc722c05 100644
--- a/examples/loadables/stat.c
+++ b/examples/loadables/stat.c
@@ -271,6 +271,8 @@ stattime (t, timefmt)
 
   fmt = timefmt ? timefmt : DEFTIMEFMT;
   tm = localtime (&t);
+  if (!tm)
+return itos (t);
 
   ret = xmalloc (TIMELEN_MAX);
 
diff --git a/examples/loadables/strftime.c b/examples/loadables/strftime.c
index f4e194e6..656ecdeb 100644
--- a/examples/loadables/strftime.c
+++ b/examples/loadables/strftime.c
@@ -81,6 +81,13 @@ strftime_builtin (list)
 secs = NOW;
 
   t = localtime (&secs);
+  if (!t)
+{
+  builtin_error ("%s: %s",
+list && list->word->word ? list->word->word : "now",
+_("timestamp out of range"));
+  return (EXECUTION_FAILURE);
+}
 
   tbsize = strlen (format) * 4;
   tbuf = 0;
diff --git a/lib/readline/examples/histexamp.c 
b/lib/readline/examples/histexamp.c
index 309d769b..b321dd0b 100644
--- a/lib/readline/examples/histexamp.c
+++ b/lib/readline/examples/histexamp.c
@@ -97,9 +97,11 @@ main (argc, argv)
  if (the_list)
for (i = 0; the_list[i]; i++)
  {
+   struct tm *tm;
tt = history_get_time (the_list[i]);
-   if (tt)
- strftime (timestr, sizeof (timestr), "%a %R", localtime(&tt));
+   tm = tt ? localtime (&tt) : 0;
+   if (tm)
+ strftime (timestr, sizeof (timestr), "%a %R", tm);
else
  strcpy (timestr, "??");
printf ("%d: %s: %s\n", i + history_base, timestr, 
the_list[i]->line);
diff --git a/parse.y b/parse.y
index 1d12e639..1d188101 100644
--- a/parse.y
+++ b/parse.y
@@ -5775,7 +5775,12 @@ decode_prompt_string (string)
 #endif
  tm = localtime (&the_time);
 
- if (c == 'd')
+ if (!tm)
+   {
+ strcpy (timebuf, "??");
+ n = 2;
+   }
+ else if (c == 'd')
n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
  else if (c == 't')
n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
@@ -5801,19 +5806,32 @@ decode_prompt_string (string)
  (void) time (&the_time);
  tm = localtime (&the_time);
  string += 2;  /* skip { */
- timefmt = xmalloc (strlen (string) + 3);
- for (t = timefmt; *string && *string != '}'; )
-   *t++ = *string++;
- *t = '\0';
+ t = string;
+ while (*string && *string != '}')
+   string++;
  c = *string;  /* tested at add_string */
- if (timefmt[0] == '\0')
+ 
+ if (tm)
+   {
+ size_t timefmtlen = string - t;
+ timefmt = xmalloc (timefmtlen + 3);
+ memcpy (timefmt, t, timefmtlen);
+ timefmt[timefmtlen] = '\0';
+ 
+ if (timefmt[0] == '\0')
+   {
+ timefmt[0] = '%';
+ timefmt[1] = 'X'; /* locale-specific current time */
+ timefmt[2] = '\0';
+   }
+ n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
+ free (timefmt);
+   }
+ else
{
- timefmt[0] = '%';
- timefmt[1] = 'X'; /* locale-specific current time */
- timefmt[2] = '\0';
+ strcpy (timebuf, "??");
+ n = 2;
}
- n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
- free (timefmt);
 
  if (n == 0)
timebuf[0] = '\0';
-- 
2.39.2