mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-25 14:55:25 +02:00
fixes for glibc time/gettimeofday issue; fix issue with history file containing one line too few if saving timestamps; fix for signal arriving while displaying readline completions
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
Vendored
+3
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
+22
-74
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
extern char *ttyname ();
|
||||
extern char *ttyname (int);
|
||||
|
||||
int
|
||||
tty_builtin (WORD_LIST *list)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
+36
-12
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-4
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 *
|
||||
|
||||
+2
-1
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
timefmt[0] = '%';
|
||||
timefmt[1] = 'X'; /* locale-specific current time */
|
||||
timefmt[2] = '\0';
|
||||
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
|
||||
{
|
||||
strcpy (timebuf, "??");
|
||||
tslen = 2;
|
||||
}
|
||||
tslen = strftime (timebuf, sizeof (timebuf), timefmt, tm);
|
||||
free (timefmt);
|
||||
|
||||
if (tslen == 0)
|
||||
timebuf[0] = '\0';
|
||||
|
||||
+11
-2
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -131,3 +131,4 @@ ${THIS_SH} ./history3.sub
|
||||
${THIS_SH} ./history4.sub
|
||||
${THIS_SH} ./history5.sub
|
||||
${THIS_SH} ./history6.sub
|
||||
${THIS_SH} ./history7.sub
|
||||
|
||||
@@ -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
|
||||
+1
-2
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user