#endif
#include "internal.h"
+#include "virterror_internal.h"
#include "base64.h"
#include "buf.h"
#include "console.h"
*/
char *logfile; /* log file name */
int log_fd; /* log file descriptor */
+ char *historydir; /* readline history directory name */
+ char *historyfile; /* readline history file name */
} __vshControl;
}
-static void
-vshReadlineInit(void)
+static int
+vshReadlineInit(vshControl *ctl)
{
+ char *userdir = NULL;
+
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "virsh";
/* Limit the total size of the history buffer */
stifle_history(500);
+
+ /* Prepare to read/write history from/to the ~/.virsh/history file */
+ userdir = virGetUserDirectory(NULL, getuid());
+
+ if (userdir == NULL)
+ return -1;
+
+ if (virAsprintf(&ctl->historydir, "%s/.virsh", userdir) < 0) {
+ vshError(ctl, "%s", _("Out of memory"));
+ free(userdir);
+ return -1;
+ }
+
+ if (virAsprintf(&ctl->historyfile, "%s/history", ctl->historydir) < 0) {
+ vshError(ctl, "%s", _("Out of memory"));
+ free(userdir);
+ return -1;
+ }
+
+ free(userdir);
+
+ read_history(ctl->historyfile);
+
+ return 0;
+}
+
+static void
+vshReadlineDeinit (vshControl *ctl)
+{
+ if (ctl->historyfile != NULL) {
+ if (mkdir(ctl->historydir, 0755) < 0 && errno != EEXIST) {
+ char ebuf[1024];
+ vshError(ctl, _("Failed to create '%s': %s"),
+ ctl->historydir, virStrerror(errno, ebuf, sizeof ebuf));
+ } else
+ write_history(ctl->historyfile);
+ }
+
+ free(ctl->historydir);
+ free(ctl->historyfile);
+
+ ctl->historydir = NULL;
+ ctl->historyfile = NULL;
}
static char *
#else /* !USE_READLINE */
+static int
+vshReadlineInit (vshControl *ctl ATTRIBUTE_UNUSED)
+{
+ /* empty */
+ return 0;
+}
+
static void
-vshReadlineInit (void)
+vshReadlineDeinit (vshControl *ctl ATTRIBUTE_UNUSED)
{
/* empty */
}
static int
vshDeinit(vshControl *ctl)
{
+ vshReadlineDeinit(ctl);
vshCloseLogFile(ctl);
free(ctl->name);
if (ctl->conn) {
_("Type: 'help' for help with commands\n"
" 'quit' to quit\n\n"));
}
- vshReadlineInit();
+
+ if (vshReadlineInit(ctl) < 0) {
+ vshDeinit(ctl);
+ exit(EXIT_FAILURE);
+ }
+
do {
const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
ctl->cmdstr =