virsh: Add persistent history using libreadline

This commit is contained in:
Matthias Bolte 2010-01-03 15:45:10 +01:00
parent 96ceb12443
commit a4a38ffda1
1 changed files with 65 additions and 4 deletions

View File

@ -41,6 +41,7 @@
#endif #endif
#include "internal.h" #include "internal.h"
#include "virterror_internal.h"
#include "base64.h" #include "base64.h"
#include "buf.h" #include "buf.h"
#include "console.h" #include "console.h"
@ -197,6 +198,8 @@ typedef struct __vshControl {
*/ */
char *logfile; /* log file name */ char *logfile; /* log file name */
int log_fd; /* log file descriptor */ int log_fd; /* log file descriptor */
char *historydir; /* readline history directory name */
char *historyfile; /* readline history file name */
} __vshControl; } __vshControl;
@ -8689,9 +8692,11 @@ vshReadlineCompletion(const char *text, int start,
} }
static void static int
vshReadlineInit(void) vshReadlineInit(vshControl *ctl)
{ {
char *userdir = NULL;
/* Allow conditional parsing of the ~/.inputrc file. */ /* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "virsh"; rl_readline_name = "virsh";
@ -8700,6 +8705,49 @@ vshReadlineInit(void)
/* Limit the total size of the history buffer */ /* Limit the total size of the history buffer */
stifle_history(500); 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 * static char *
@ -8710,8 +8758,15 @@ vshReadline (vshControl *ctl ATTRIBUTE_UNUSED, const char *prompt)
#else /* !USE_READLINE */ #else /* !USE_READLINE */
static int
vshReadlineInit (vshControl *ctl ATTRIBUTE_UNUSED)
{
/* empty */
return 0;
}
static void static void
vshReadlineInit (void) vshReadlineDeinit (vshControl *ctl ATTRIBUTE_UNUSED)
{ {
/* empty */ /* empty */
} }
@ -8743,6 +8798,7 @@ vshReadline (vshControl *ctl, const char *prompt)
static int static int
vshDeinit(vshControl *ctl) vshDeinit(vshControl *ctl)
{ {
vshReadlineDeinit(ctl);
vshCloseLogFile(ctl); vshCloseLogFile(ctl);
free(ctl->name); free(ctl->name);
if (ctl->conn) { if (ctl->conn) {
@ -8969,7 +9025,12 @@ main(int argc, char **argv)
_("Type: 'help' for help with commands\n" _("Type: 'help' for help with commands\n"
" 'quit' to quit\n\n")); " 'quit' to quit\n\n"));
} }
vshReadlineInit();
if (vshReadlineInit(ctl) < 0) {
vshDeinit(ctl);
exit(EXIT_FAILURE);
}
do { do {
const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW; const char *prompt = ctl->readonly ? VSH_PROMPT_RO : VSH_PROMPT_RW;
ctl->cmdstr = ctl->cmdstr =