just found a patch done by me some months ago, I have been using bash-4.2
with this patch for half a year, should be quite stable; it's mainly to
implement unlimited .bash_history;
1) HISTFILESIZE has a bug that current bash manual saying if HISTFILESIZE
is unset, then HISTFILE will be unlimited, but it seems there is no way to
unset it in bash_profile or any rc file?
2) remove duplicates in HISTFILE also, not just in current history in
memory, we can say this a deep dedup? it only run deep dedup when
HC_ERASEDUPS set,
Not sure if this can be applied to latest trunk code, but I can revamp it
to latest tree if there are interests;
Thanks,
--- bash-4.2.orig/bashhist.c 2010-08-13 18:09:08.0 -0700
+++ bash-4.2/bashhist.c 2011-11-02 11:34:36.350166000 -0700
@@ -29,6 +29,8 @@
# include
#endif
+#include
+
#include "bashtypes.h"
#include
#include
@@ -281,9 +283,6 @@ load_history ()
set_if_not ("HISTSIZE", "500");
sv_histsize ("HISTSIZE");
- set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
- sv_histsize ("HISTFILESIZE");
-
/* Read the history in HISTFILE into the history list. */
hf = get_string_value ("HISTFILE");
@@ -345,6 +344,69 @@ bash_delete_last_history ()
return r;
}
+int
+erasedups_history (nelements, filename)
+ int nelements;
+ const char *filename;
+{
+ HIST_ENTRY *temp;
+ int r, fd, rv = 0;
+ size_t cursize, mmap_size;
+ char *buffer, *line, *lineend;
+
+ fd = open (filename, O_RDWR);
+
+ if (fd < 0)
+return errno;
+
+ cursize = lseek (fd, 0, SEEK_END);
+
+ using_history ();
+
+ mmap_size = cursize +1; /* for possibly not newline ending */
+ buffer = mmap (0, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if ((void *)buffer == MAP_FAILED)
+{
+ rv = errno;
+ close (fd);
+ return rv;
+}
+
+ line = buffer;
+ while (line < buffer+cursize) {
+lineend = strchr (line, '\n');
+
+if (!lineend) { /* last line not newline ending? */
+ lineend = line + strlen(line);
+ *lineend = '\n';
+ buffer[++cursize] = '\0';
+}
+
+for (r = 0; (temp = previous_history ()) && r < nelements; r++)
+ if (STREQN (line, temp->line, strlen (temp->line))) {
+ memmove (line, lineend+1, (buffer+cursize) - (lineend+1));
+ cursize -= (lineend+1 - line);
+ buffer[cursize] = '\0';
+ lineend = NULL;
+ break;
+ }
+using_history ();
+
+if (lineend)
+ line = lineend+1;
+ }
+
+ if (ftruncate (fd, cursize) == -1)
+rv = errno;
+ if (!rv && msync (buffer, cursize, 0) == -1)
+rv = errno;
+ if (!rv && munmap (buffer, mmap_size) == -1)
+rv = errno;
+ close (fd);
+
+ return rv;
+}
+
#ifdef INCLUDE_UNUSED
/* Write the existing history out to the history file. */
void
@@ -389,9 +451,16 @@ maybe_append_history (filename)
}
close (fd);
}
+ if (history_control & HC_ERASEDUPS)
+ erasedups_history (history_lines_this_session, filename);
result = append_history (history_lines_this_session, filename);
history_lines_in_file += history_lines_this_session;
- history_lines_this_session = 0;
+
+ {
+ char *hf = get_string_value ("HISTFILE");
+ if (hf && *hf && !strcmp(hf, filename))
+ history_lines_this_session = 0;
+ }
}
return (result);
}
@@ -426,6 +495,8 @@ maybe_save_shell_history ()
using_history ();
if (history_lines_this_session <= where_history () ||
force_append_history)
{
+ if (history_control & HC_ERASEDUPS)
+ erasedups_history (history_lines_this_session, hf);
result = append_history (history_lines_this_session, hf);
history_lines_in_file += history_lines_this_session;
}
--
Cheng Renquan (程任全)