cheng renquan
unread,Oct 31, 2012, 3:43:50 PM10/31/12You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to bug-...@gnu.org
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.000000000 -0700
+++ bash-4.2/bashhist.c 2011-11-02 11:34:36.350166000 -0700
@@ -29,6 +29,8 @@
# include <unistd.h>
#endif
+#include <sys/mman.h>
+
#include "bashtypes.h"
#include <stdio.h>
#include <errno.h>
@@ -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 (程任全)