]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fixes for glibc time/gettimeofday issue; fix issue with history file containing one...
authorChet Ramey <chet.ramey@case.edu>
Mon, 27 Mar 2023 13:28:12 +0000 (09:28 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 27 Mar 2023 13:28:12 +0000 (09:28 -0400)
25 files changed:
CWRU/CWRU.chlog
MANIFEST
aclocal.m4
configure
examples/loadables/finfo.c
examples/loadables/id.c
examples/loadables/stat.c
examples/loadables/strftime.c
examples/loadables/tee.c
examples/loadables/tty.c
general.h
include/posixtime.h
lib/readline/complete.c
lib/readline/examples/histexamp.c
lib/readline/histfile.c
lib/readline/history.c
lib/readline/misc.c
lib/readline/undo.c
lib/sh/tmpfile.c
parse.y
support/man2html.c
tests/history.right
tests/history.tests
tests/history7.sub [new file with mode: 0644]
variables.c

index 58fb8733b471b3244d92f48d1d713cbd1b6b4742..f6a147566a55ce110ab1cfe72bf02b270d979a12 100644 (file)
@@ -5748,3 +5748,74 @@ pcomplete.c
        - gen_globpat_matches: set noglob_dot_filenames here since we're not
          calling shell_glob_filename to do it
          From a report by Grisha Levit <grishalevit@gmail.com>
+
+                                  3/22
+                                  ----
+lib/readline/misc.c
+       - rl_maybe_replace_line: if we're replacing a history entry with the
+         current line buffer and undo list, then zero out any undo list in
+         _rl_saved_line_for_history, since we're not going to use it any more
+         Fixes asan error reported by Grisha Levit <grishalevit@gmail.com>
+
+lib/readline/undo.c
+       - rl_free_undo_list: if we're freeing rl_undo_list, it can't be a
+         valid value for data in _rl_saved_line_for_history
+         Fixes asan error reported by Grisha Levit <grishalevit@gmail.com>
+
+lib/readline/complete.c
+       - display_matches: don't call rl_display_match_list if we received a
+         signal during get_y_or_n and didn't jump out for some reason
+         From a report by Grisha Levit <grishalevit@gmail.com>
+       - rl_display_match_list: return if we received a signal during
+         _rl_internal_pager (via get_y_or_n) and didn't jump out
+         From a report by Grisha Levit <grishalevit@gmail.com>
+
+                                  3/23
+                                  ----
+lib/readline/history.c
+       - history_truncate_file: don't bother trying to read the existing
+         history file if we're just truncating it to 0 lines
+
+                                  3/24
+                                  ----
+lib/readline/history.c
+       - history_truncate_file: fix off-by-one error that resulted in the
+         timestamp associated with the first history entry not being written
+         to the truncated history file
+         From a report by Grisha Levit <grishalevit@gmail.com>
+
+parse.y        
+       - decode_prompt_string: do something rational if localtime() returns
+         NULL (extraordinarily rare)
+         From a report by Paul Eggert <eggert@cs.ucla.edu>
+
+examples/loadables/stat.c
+       - stattime: ditto
+
+examples/loadables/strftime.c
+       - strftime_builtin: ditto
+
+lib/readline/examples/histexamp.c
+       - main: ditto
+
+include/posixtime.h
+       - getnow(): new inline function, calls gettimeofday and returns tv_sec;
+         replacement for time(0). From Paul Eggert <eggert@cs.ucla.edu>
+
+general.h
+       - NOW: use a call to getnow() to standardize on gettimeofday for time
+         information
+
+lib/readline/history.c
+       - include #posixtime.h for getnow()
+       - hist_inittime: use getnow() instead of calling time(0)
+
+parse.y
+       - posixtime.h: include instead of <time.h>
+       - decode_prompt_string: use getnow() instead of calling time(0)
+
+                                  3/27
+                                  ----
+parse.y
+       - count_all_jobs: add extern definition if JOB_CONTROL is not defined.
+         From Emanuele Torre <torreemanuele6@gmail.com>
index 24cd4eeb48b32df1b8f74915e343633caec49a28..14c2e0f1b7cd3a4902b4afb43ffeafe6a8672a13 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1208,6 +1208,7 @@ tests/history3.sub        f
 tests/history4.sub     f
 tests/history5.sub     f
 tests/history6.sub     f
+tests/history7.sub     f
 tests/ifs.tests                f
 tests/ifs.right                f
 tests/ifs1.sub         f
index 37546c6c6454a3bb4cb3c44feb6fe37175d5c3c9..93251a7643de2397c44656ddf97c4558b889b323 100644 (file)
@@ -238,6 +238,9 @@ AC_CACHE_VAL(bash_cv_dup2_broken,
 #include <sys/types.h>
 #include <fcntl.h>
 #include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
 int
 main()
 {
index 78e55ecfca55bc205aac01b534e157363022f8b9..f5d1fad254c6fa9fb6b4f3f706b813cd896ef63c 100755 (executable)
--- a/configure
+++ b/configure
@@ -18135,6 +18135,9 @@ else $as_nop
 #include <sys/types.h>
 #include <fcntl.h>
 #include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
 int
 main()
 {
index 6491ef0ed2ab236fe241badd15d3c7088e42425c..64a9e9108936fabda1552e505fca6e4b374dda55 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 /*
-   Copyright (C) 1999-2009,2022 Free Software Foundation, Inc.
+   Copyright (C) 1999-2009,2022,2023 Free Software Foundation, Inc.
 
    This file is part of GNU Bash.
    Bash is free software: you can redistribute it and/or modify
@@ -96,8 +96,7 @@ static int    pmask;
 #define OPTIONS                "acdgiflmnopsuACGMP:U"
 
 static int
-octal(s)
-char   *s;
+octal(char *s)
 {
        int     r;
 
@@ -108,9 +107,7 @@ char        *s;
 }
 
 static int
-finfo_main(argc, argv)
-int    argc;
-char   **argv;
+finfo_main(int argc, char **argv)
 {
        register int    i;
        int     mode, flags, opt;
@@ -162,8 +159,7 @@ char        **argv;
 }
 
 static struct stat *
-getstat(f)
-char   *f;
+getstat(char *f)
 {
        static struct stat st;
        int     fd, r;
@@ -190,8 +186,7 @@ char        *f;
 }
 
 static int
-printfinfo(f)
-char   *f;
+printfinfo(char *f)
 {
        struct stat *st;
 
@@ -200,15 +195,13 @@ char      *f;
 }
 
 static int
-getperm(m)
-int    m;
+getperm(int m)
 {
        return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID));
 }
 
 static void
-perms(m)
-int    m;
+perms(int m)
 {
        char ubits[4], gbits[4], obits[4];      /* u=rwx,g=rwx,o=rwx */
        int i;
@@ -251,8 +244,7 @@ int m;
 }
 
 static void
-printmode(mode)
-int    mode;
+printmode(int mode)
 {
        if (S_ISBLK(mode))
                printf("S_IFBLK ");
@@ -277,8 +269,7 @@ int mode;
 }
 
 static int
-printst(st)
-struct stat *st;
+printst(struct stat *st)
 {
        struct passwd   *pw;
        struct group    *gr;
@@ -314,9 +305,7 @@ struct stat *st;
 }
 
 static int
-printsome(f, flags)
-char   *f;
-int    flags;
+printsome(char *f, int flags)
 {
        struct stat *st;
        struct passwd *pw;
@@ -400,8 +389,7 @@ int flags;
 
 #ifndef NOBUILTIN
 int
-finfo_builtin(list)
-     WORD_LIST *list;
+finfo_builtin(WORD_LIST *list)
 {
   int c, r;
   char **v;
@@ -456,34 +444,26 @@ struct builtin finfo_struct = {
 #endif
 
 #ifdef NOBUILTIN
-#if defined (PREFER_STDARG)
-#  include <stdarg.h>
-#else
-#  if defined (PREFER_VARARGS)
-#    include <varargs.h>
-#  endif
-#endif
+#include <stdarg.h>
 
 char *this_command_name;
 
-main(argc, argv)
-int    argc;
-char   **argv;
+int
+main(int argc, char **argv)
 {
        this_command_name = argv[0];
        exit(finfo_main(argc, argv));
 }
 
 void
-builtin_usage()
+builtin_usage(void)
 {
        fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, prog, OPTIONS);
 }
 
 #ifndef HAVE_STRERROR
 char *
-strerror(e)
-int    e;
+strerror(int e)
 {
        static char     ebuf[40];
        extern int      sys_nerr;
@@ -497,23 +477,20 @@ int       e;
 }
 #endif
 
-char *
-xmalloc(s)
-size_t s;
+PTR_T
+xmalloc(size_t s)
 {
        char    *ret;
-       extern char *malloc();
 
        ret = malloc(s);
        if (ret)
                return (ret);
-       fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s);
+       fprintf(stderr, "%s: cannot malloc %zu bytes\n", prog, s);
        exit(1);
 }
 
 char *
-base_pathname(p)
-char   *p;
+base_pathname(char *p)
 {
        char    *t;
 
@@ -523,9 +500,7 @@ char        *p;
 }
 
 int
-legal_number (string, result)
-     char *string;
-     long *result;
+legal_number (char *string, long result)
 {
   int sign;
   long value;
@@ -584,9 +559,7 @@ extern int optind;
 extern char *optarg;
 
 int
-sh_getopt(c, v, o)
-int    c;
-char   **v, *o;
+sh_getopt(int c, char **v, char *o)
 {
        int     r;
 
@@ -596,43 +569,18 @@ char      **v, *o;
        return r;
 }
 
-#if defined (USE_VARARGS)
 void
-#if defined (PREFER_STDARG)
 builtin_error (const char *format, ...)
-#else
-builtin_error (format, va_alist)
-     const char *format;
-     va_dcl
-#endif
 {
   va_list args;
 
   if (this_command_name && *this_command_name)
     fprintf (stderr, "%s: ", this_command_name);
 
-#if defined (PREFER_STDARG)
   va_start (args, format);
-#else
-  va_start (args);
-#endif
 
   vfprintf (stderr, format, args);
   va_end (args);
   fprintf (stderr, "\n");
 }
-#else
-void
-builtin_error (format, arg1, arg2, arg3, arg4, arg5)
-     char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
-{
-  if (this_command_name && *this_command_name)
-    fprintf (stderr, "%s: ", this_command_name);
-
-  fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
-  fprintf (stderr, "\n");
-  fflush (stderr);
-}
-#endif /* !USE_VARARGS */
-
 #endif
index f46f75cebeb870776594723ab1e26405b87f2345..98c37ea3b1cfb3cf2269f2c3d8b33b92368dd230 100644 (file)
@@ -41,9 +41,9 @@
 #endif
 
 #if !defined (HAVE_GETPW_DECLS)
-extern struct passwd *getpwuid ();
+extern struct passwd *getpwuid (uid_t);
 #endif
-extern struct group *getgrgid ();
+extern struct group *getgrgid (gid_t);
 
 #include "shell.h"
 #include "builtins.h"
index 3ca1a5897a8214f412b186783c2d7d03f0f5ac39..1093f7b059693adfd2d95751046a1156ab9c1887 100644 (file)
@@ -3,7 +3,7 @@
 /* See Makefile for compilation details. */
 
 /*
-   Copyright (C) 2016,2022 Free Software Foundation, Inc.
+   Copyright (C) 2016,2022-2023 Free Software Foundation, Inc.
 
    This file is part of GNU Bash.
    Bash is free software: you can redistribute it and/or modify
@@ -261,6 +261,8 @@ stattime (time_t t, const char *timefmt)
 
   fmt = timefmt ? timefmt : DEFTIMEFMT;
   tm = localtime (&t);
+  if (tm == 0)
+    return (itos (t));
 
   ret = xmalloc (TIMELEN_MAX);
 
index e6c8141eba1e4a3ce01d0781afc0934d8b371918..506b330102087d6f63bf557967c8493d583e6dab 100644 (file)
@@ -80,6 +80,12 @@ strftime_builtin (WORD_LIST *list)
     secs = NOW;
 
   t = localtime (&secs);
+  if (t == 0)
+    {
+      builtin_error ("%s: timestamp out of range", list && list->word->word ? list->word->word : "now");
+      return (EXECUTION_FAILURE);
+    }
+       
 
   tbsize = strlen (format) * 4;
   tbuf = 0;
index 9f26b2d44e92765333a14d336e5d7d4f942919a2..c74cb64738a0e807bc10af2f1aacaa6efd2b1152 100644 (file)
@@ -58,7 +58,7 @@ static FLIST *tee_flist;
 
 extern int interrupt_immediately;
 
-extern char *strerror ();
+extern char *strerror (int);
 
 int
 tee_builtin (WORD_LIST *list)
index b717766a1732a0384e7e43d6a2f545218fe12948..27a851bf4fb4f4e6824f38ee54b3e5ba15fba4f3 100644 (file)
@@ -28,7 +28,7 @@
 #include "bashgetopt.h"
 #include "common.h"
 
-extern char *ttyname ();
+extern char *ttyname (int);
 
 int
 tty_builtin (WORD_LIST *list)
index fa57251a56656192350f89901a2b7a169388bd72..74b97f4297fb8a4630bb3ec7c6a1eb8b7518250c 100644 (file)
--- a/general.h
+++ b/general.h
@@ -242,7 +242,7 @@ typedef int sh_builtin_func_t (WORD_LIST *); /* sh_wlist_func_t */
 
 #endif /* SH_FUNCTION_TYPEDEF */
 
-#define NOW    ((time_t) time ((time_t *) 0))
+#define NOW    getnow()
 #define GETTIME(tv)    gettimeofday(&(tv), NULL)
 
 /* Some defines for calling file status functions. */
index 319cb168e34caef14525f8b8a50458347d88bcff..a731b006ad89d31ef8628f5e60f4d365ca056fda 100644 (file)
@@ -52,6 +52,15 @@ struct timeval
 extern int gettimeofday (struct timeval * restrict, void * restrict);
 #endif
 
+/* consistently use gettimeofday for time information */
+static inline time_t
+getnow(void)
+{
+  struct timeval now;
+  gettimeofday (&now, 0);
+  return now.tv_sec;
+}
+
 /* These exist on BSD systems, at least. */
 #if !defined (timerclear)
 #  define timerclear(tvp)      do { (tvp)->tv_sec = 0; (tvp)->tv_usec = 0; } while (0)
index 2016d393c67ecb37de84f9c92c157c4752bce7df..ce9b8cd0093d2bdf81f1ee97a6aafd99a0798e9f 100644 (file)
@@ -1630,7 +1630,7 @@ rl_display_match_list (char **matches, int len, int max)
          if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
            {
              lines = _rl_internal_pager (lines);
-             if (lines < 0)
+             if (lines < 0 || _rl_complete_display_matches_interrupt)
                return;
            }
        }
@@ -1658,7 +1658,7 @@ rl_display_match_list (char **matches, int len, int max)
                  if (_rl_page_completions && lines >= _rl_screenheight - 1)
                    {
                      lines = _rl_internal_pager (lines);
-                     if (lines < 0)
+                     if (lines < 0 || _rl_complete_display_matches_interrupt)
                        return;
                    }
                }
@@ -1745,7 +1745,9 @@ display_matches (char **matches)
        }
     }
 
-  rl_display_match_list (matches, len, max);
+  /* We rely on the caller to set MATCHES to 0 when this returns. */
+  if (_rl_complete_display_matches_interrupt == 0)
+    rl_display_match_list (matches, len, max);
 
   rl_forced_update_display ();
   rl_display_fixed = 1;
index 309d769b3845e254132dab0aac3fb11050b4e150..2e946acac30bfd27605271e60c795b1978f951e0 100644 (file)
@@ -32,9 +32,7 @@
 #include <string.h>
 
 int
-main (argc, argv)
-     int argc;
-     char **argv;
+main (int argc, char **argv)
 {
   char line[1024], *t;
   int len, done;
@@ -91,6 +89,7 @@ main (argc, argv)
          register HIST_ENTRY **the_list;
          register int i;
          time_t tt;
+         struct tm *tm;
          char timestr[128];
 
          the_list = history_list ();
@@ -98,8 +97,9 @@ main (argc, argv)
            for (i = 0; the_list[i]; i++)
              {
                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);
index a3c8d9bff43928110ff63ebcaee337843a25fec3..2af71d35255c644ade154c8fcaca1a30fff5dcc5 100644 (file)
@@ -1,6 +1,6 @@
 /* histfile.c - functions to manipulate the history file. */
 
-/* Copyright (C) 1989-2019 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2019,2023 Free Software Foundation, Inc.
 
    This file contains the GNU History Library (History), a set of
    routines for managing the text of previously typed lines.
@@ -578,6 +578,15 @@ history_truncate_file (const char *fname, int lines)
       goto truncate_exit;
     }
 
+  /* Don't bother with any of this if we're truncating to zero length. */
+  if (lines == 0)
+    {
+      close (file);
+      buffer[chars_read = 0] = '\0';
+      bp = buffer;
+      goto truncate_write;
+    }
+
   chars_read = read (file, buffer, file_size);
   close (file);
 
@@ -586,30 +595,38 @@ history_truncate_file (const char *fname, int lines)
       rv = (chars_read < 0) ? errno : 0;
       goto truncate_exit;
     }
+  buffer[chars_read] = '\0';   /* for the initial check of bp1[1] */
 
   /* Count backwards from the end of buffer until we have passed
      LINES lines.  bp1 is set funny initially.  But since bp[1] can't
      be a comment character (since it's off the end) and *bp can't be
-     both a newline and the history comment character, it should be OK. */
-  for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
+     both a newline and the history comment character, it should be OK.
+     If we are writing history timestamps, we need to add one to LINES
+     because we decrement it one extra time the first time through the loop
+     and we need the final timestamp line. */
+  lines += history_write_timestamps;
+  for (bp1 = bp = buffer + chars_read - 1; lines > 0 && bp > buffer; bp--)
     {
       if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
        lines--;
       bp1 = bp;
     }
 
-  /* If this is the first line, then the file contains exactly the
+  /* This is the right line, so move to its start. If we're writing history
+     timestamps, we want to go back until *bp == '\n' and bp1 starts a
+     history timestamp. If we're not, just move back to *bp == '\n'.
+     If this is the first line, then the file contains exactly the
      number of lines we want to truncate to, so we don't need to do
-     anything.  It's the first line if we don't find a newline between
-     the current value of i and 0.  Otherwise, write from the start of
-     this line until the end of the buffer. */
+     anything, and we'll end up with bp == buffer.
+     Otherwise, write from the start of this line until the end of the
+     buffer. */
   for ( ; bp > buffer; bp--)
     {
-      if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
-        {
+      if (*bp == '\n' && (history_write_timestamps == 0 || HIST_TIMESTAMP_START(bp1)))
+       {
          bp++;
          break;
-        }
+       }
       bp1 = bp;
     }
 
@@ -623,15 +640,22 @@ history_truncate_file (const char *fname, int lines)
       goto truncate_exit;
     }
 
+truncate_write:
   tempname = history_tempfile (filename);
 
   if ((file = open (tempname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) != -1)
     {
       if (write (file, bp, chars_read - (bp - buffer)) < 0)
-       rv = errno;
+       {
+         rv = errno;
+         close (file);
+       }
 
       if (rv == 0 && fstat (file, &nfinfo) < 0)
-       rv = errno;
+       {
+         rv = errno;
+         close (file);
+       }
 
       if (rv == 0 && close (file) < 0)
        rv = errno;
index 42580301c46385b29a1b2275a27a2b99b7a010eb..ee52e8297eed27d732044e865e0958aff4fca25b 100644 (file)
@@ -42,6 +42,7 @@
 #  endif
 #  include <unistd.h>
 #endif
+#include "posixtime.h"
 
 #include <errno.h>
 
@@ -261,7 +262,7 @@ hist_inittime (void)
   time_t t;
   char ts[64], *ret;
 
-  t = (time_t) time ((time_t *)0);
+  t = getnow ();
 #if defined (HAVE_VSNPRINTF)           /* assume snprintf if vsnprintf exists */
   snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
 #else
index 764482a05fb3c9070263f2c1c94d759ab5325d3c..e1ccecae3d5566a455144829012c928c37d67f28 100644 (file)
@@ -340,13 +340,14 @@ rl_maybe_replace_line (void)
       xfree (temp->line);
       FREE (temp->timestamp);
       xfree (temp);
+      /* What about _rl_saved_line_for_history? if the saved undo list is
+        rl_undo_list, and we just put that into a history entry, should
+        we set the saved undo list to NULL? */
+      if (_rl_saved_line_for_history && (UNDO_LIST *)_rl_saved_line_for_history->data == rl_undo_list)
+       _rl_saved_line_for_history->data = 0;
       /* Do we want to set rl_undo_list = 0 here since we just saved it into
         a history entry? */
       rl_undo_list = 0;
-
-      /* XXX - what about _rl_saved_line_for_history? if the saved undo list
-        is rl_undo_list, and we just put that into a history entry, should
-        we set the saved undo list to NULL? */
     }
   return 0;
 }
index c9c2a5b2d327ecda500eda00dcdd2bee247c23bb..492894c33c99e5fe27873006f0d4855678da1b9c 100644 (file)
@@ -122,6 +122,8 @@ rl_free_undo_list (void)
   _rl_free_undo_list (rl_undo_list);
   rl_undo_list = (UNDO_LIST *)NULL;
   _hs_replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
+  if (_rl_saved_line_for_history && (UNDO_LIST *)_rl_saved_line_for_history->data == orig_list)
+    _rl_saved_line_for_history->data = 0;
 }
 
 UNDO_LIST *
index 18582b104c5fbe54c54f59bcf1e749974f82f7cd..5026760966ce16dc00bc6dc5822747863ee2f136 100644 (file)
@@ -279,10 +279,11 @@ char *
 sh_mktmpdir (const char *nameroot, int flags)
 {
   char *filename;
+  int fd;
 #ifdef USE_MKDTEMP
   char *tdir, *dirname;
   const char *lroot;
-  int fd, tdlen;
+  int tdlen;
   
   filename = (char *)xmalloc (PATH_MAX + 1);
   tdir = get_tmpdir (flags);
diff --git a/parse.y b/parse.y
index 639912b6334610fcda4dfaa8b86d9134bfe233ef..a4c4c07c8640b65b1a0c1ca5868aad7f2f85f5ab 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -73,6 +73,7 @@
 #  include "jobs.h"
 #else
 extern int cleanup_dead_jobs (void);
+extern int count_all_jobs (void);
 #endif /* JOB_CONTROL */
 
 #if defined (ALIAS)
@@ -85,7 +86,7 @@ typedef void *alias_t;
 #  ifndef _MINIX
 #    include <sys/param.h>
 #  endif
-#  include <time.h>
+#  include "posixtime.h"
 #  if defined (TM_IN_SYS_TIME)
 #    include <sys/types.h>
 #    include <sys/time.h>
@@ -5976,13 +5977,17 @@ decode_prompt_string (char *string)
            case '@':
            case 'A':
              /* Make the current time/date into a string. */
-             (void) time (&the_time);
+             the_time = getnow ();
 #if defined (HAVE_TZSET)
              sv_tz ("TZ");             /* XXX -- just make sure */
 #endif
              tm = localtime (&the_time);
-
-             if (c == 'd')
+             if (tm == 0)
+               {
+                 strcpy (timebuf, "??");
+                 tslen = 2;
+               }
+             else if (c == 'd')
                tslen = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
              else if (c == 't')
                tslen = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
@@ -6005,22 +6010,36 @@ decode_prompt_string (char *string)
              if (string[1] != '{')             /* } */
                goto not_escape;
 
-             (void) time (&the_time);
+             the_time = getnow ();
              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 tflen;
+                 tflen = string - t;
+                 timefmt = xmalloc (tflen + 3);
+                 memcpy (timefmt, t, tflen);
+                 timefmt[tflen] = '\0';
+
+                 if (timefmt[0] == '\0')
+                   {
+                     timefmt[0] = '%';
+                     timefmt[1] = 'X'; /* locale-specific current time */
+                     timefmt[2] = '\0';
+                   }
+
+                 tslen = strftime (timebuf, sizeof (timebuf), timefmt, tm);
+                 free (timefmt);
+               }
+             else
                {
-                 timefmt[0] = '%';
-                 timefmt[1] = 'X';     /* locale-specific current time */
-                 timefmt[2] = '\0';
+                 strcpy (timebuf, "??");
+                 tslen = 2;
                }
-             tslen = strftime (timebuf, sizeof (timebuf), timefmt, tm);
-             free (timefmt);
 
              if (tslen == 0)
                timebuf[0] = '\0';
index e6f441b4a353ebff7c2875ae6e13c668df88d8d1..097f48ee5beb7d2444600ab9103320805961611c 100644 (file)
@@ -452,10 +452,19 @@ print_sig(void)
        struct tm *timetm;
        time_t  clock;
 
-       datbuf[0] = '\0';
+#ifdef HAVE_GETTIMEOFDAY
+       struct timeval tv;
+       gettimeofday (&tv, 0);
+       clock = tv.tv_sec;
+#else
        clock = time(NULL);
+#endif
        timetm = localtime(&clock);
-       strftime(datbuf, MED_STR_MAX, TIMEFORMAT, timetm);
+       datbuf[0] = '\0';
+       if (timetm)
+         strftime(datbuf, MED_STR_MAX, TIMEFORMAT, timetm);
+       else
+         strcpy (datbuf, "??");
        printf(signature, manpage, datbuf);
 }
 
index 5273de6bc85309936db10ec8e5287ff198321f1b..82e576fc0524f598b9227cd08e440eb52298b62a 100644 (file)
@@ -297,3 +297,47 @@ out of range 4
     7  echo 9
     8  echo 10
     5  echo 10
+$ 1
+$ 2
+$ 3
+$ exit
+       6
+$ 1
+$ 2
+$ 3
+$ 4
+$ 5
+$ exit
+       6
+$ 1
+$ 2
+$ exit
+       4
+$ e 1
+$ e 2
+$ e 3
+$ exit
+       3
+e 1
+e 2
+e 3
+$ x 1
+$ x 2
+$ x 3
+$ x 4
+$ x 5
+$ exit
+       3
+x 3
+x 4
+x 5
+$ y 1
+$ y 2
+$ exit
+       2
+y 1
+y 2
+$ 1
+$ 2
+$ exit
+       0
index 5826d130411e577daa6d30d3a8803e717a35e119..2bff8811fcd9818e63f5feb0c999d3e62f57bb11 100644 (file)
@@ -131,3 +131,4 @@ ${THIS_SH} ./history3.sub
 ${THIS_SH} ./history4.sub
 ${THIS_SH} ./history5.sub
 ${THIS_SH} ./history6.sub
+${THIS_SH} ./history7.sub
diff --git a/tests/history7.sub b/tests/history7.sub
new file mode 100644 (file)
index 0000000..ad651a0
--- /dev/null
@@ -0,0 +1,73 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# test history file truncation for various values of $HISTFILESIZE
+
+: ${THIS_SH:=./bash}
+: ${TMPDIR:=/var/tmp}
+
+export HISTTIMEFORMAT=
+export HISTFILESIZE=3
+export HISTFILE=$TMPDIR/hist-$$
+export PS1='$ '
+
+rm -f $HISTFILE
+
+# exactly the number of lines
+${THIS_SH} --norc -in <<<$'1\n2\n3' 
+wc -l < $HISTFILE
+
+rm -f $HISTFILE
+
+# truncating to fewer lines
+${THIS_SH} --norc -in <<<$'1\n2\n3\n4\n5' 
+wc -l < $HISTFILE
+
+rm -f $HISTFILE
+
+# the history file contains fewer lines than $HISTFILESIZE
+${THIS_SH} --norc -in <<<$'1\n2' 
+wc -l < $HISTFILE
+
+rm -f $HISTFILE
+
+# now we try it without timestamps
+unset HISTTIMEFORMAT
+
+# exactly the number of lines
+${THIS_SH} --norc -in <<<$'e 1\ne 2\ne 3' 
+wc -l < $HISTFILE
+cat $HISTFILE
+
+rm -f $HISTFILE
+
+# truncating to fewer lines
+${THIS_SH} --norc -in <<<$'x 1\nx 2\nx 3\nx 4\nx 5' 
+wc -l < $HISTFILE
+cat $HISTFILE
+
+rm -f $HISTFILE
+
+# the history file contains fewer lines than $HISTFILESIZE
+${THIS_SH} --norc -in <<<$'y 1\ny 2' 
+wc -l < $HISTFILE
+cat $HISTFILE
+
+rm -f $HISTFILE
+
+# we want to truncate the history file to zero length
+HISTFILESIZE=0
+${THIS_SH} --norc -in <<<$'1\n2' 
+wc -l < $HISTFILE
+
+rm -f $HISTFILE
index 9f9440673fe60cefe5e3db6ff02b5461e142b5f4..1d67cc8c1369f4a5c84f2a7cbd32b2efbe1be9f3 100644 (file)
@@ -2445,8 +2445,7 @@ find_function_def (const char *name)
 /* Return the value of VAR.  VAR is assumed to have been the result of a
    lookup without any subscript, if arrays are compiled into the shell. */
 char *
-get_variable_value (var)
-     SHELL_VAR *var;
+get_variable_value (SHELL_VAR *var)
 {
   if (var == 0)
     return ((char *)NULL);