aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcmd/repl-interacter.cc33
-rw-r--r--src/libcmd/repl-interacter.hh5
2 files changed, 36 insertions, 2 deletions
diff --git a/src/libcmd/repl-interacter.cc b/src/libcmd/repl-interacter.cc
index d3567e021..41589cda1 100644
--- a/src/libcmd/repl-interacter.cc
+++ b/src/libcmd/repl-interacter.cc
@@ -1,6 +1,8 @@
#include <cstdio>
#include <iostream>
#include <string>
+#include <string_view>
+#include <cerrno>
#ifdef READLINE
#include <readline/history.h>
@@ -176,15 +178,42 @@ bool ReadlineLikeInteracter::getLine(std::string & input, ReplPromptType promptT
if (!s)
return false;
- write_history(historyFile.c_str());
+ this->writeHistory();
input += s;
input += '\n';
return true;
}
+void ReadlineLikeInteracter::writeHistory()
+{
+ int ret = write_history(historyFile.c_str());
+ int writeHistErr = errno;
+
+ if (ret == 0) {
+ return;
+ }
+
+ // If the open fails, editline returns EOF. If the close fails, editline
+ // forwards the return value of fclose(), which is EOF on error.
+ // readline however, returns the errno.
+ // So if we didn't get exactly EOF, then consider the return value the error
+ // code; otherwise use the errno we saved above.
+ // https://github.com/troglobit/editline/issues/66
+ if (ret != EOF) {
+ writeHistErr = ret;
+ }
+
+ // In any of these cases, we should explicitly ignore the error, but log
+ // them so the user isn't confused why their history is getting eaten.
+
+ std::string_view const errMsg(std::strerror(writeHistErr));
+ warn("ignoring error writing repl history to %s: %s", this->historyFile, errMsg);
+
+}
+
ReadlineLikeInteracter::~ReadlineLikeInteracter()
{
- write_history(historyFile.c_str());
+ this->writeHistory();
}
AutomationInteracter::Guard AutomationInteracter::init(detail::ReplCompleterMixin *)
diff --git a/src/libcmd/repl-interacter.hh b/src/libcmd/repl-interacter.hh
index c31b1a1e6..8f815fceb 100644
--- a/src/libcmd/repl-interacter.hh
+++ b/src/libcmd/repl-interacter.hh
@@ -42,6 +42,11 @@ public:
}
virtual Guard init(detail::ReplCompleterMixin * repl) override;
virtual bool getLine(std::string & input, ReplPromptType promptType) override;
+ /** Writes the current history to the history file.
+ *
+ * This function logs but ignores errors from readline's write_history().
+ */
+ virtual void writeHistory();
virtual ~ReadlineLikeInteracter() override;
};