From 5a0fb93bc8d584a8e953317905162b366d2bba4c Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Mon, 17 Sep 2007 18:01:38 +0000 Subject: [PATCH] ebl Add readline history support to bconsole. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5585 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/console/console.c | 309 ++++++++++++++++++++--------------- bacula/technotes-2.3 | 2 + 2 files changed, 178 insertions(+), 133 deletions(-) diff --git a/bacula/src/console/console.c b/bacula/src/console/console.c index c691c2316f..c2c4dd5f73 100644 --- a/bacula/src/console/console.c +++ b/bacula/src/console/console.c @@ -333,6 +333,171 @@ static int tls_pem_callback(char *buf, int size, const void *userdata) #endif } +#ifdef HAVE_READLINE +#define READLINE_LIBRARY 1 +#undef free +#include "readline.h" +#include "history.h" + +int +get_cmd(FILE *input, const char *prompt, BSOCK *sock, int sec) +{ + char *line; + + rl_catch_signals = 0; /* do it ourselves */ + line = readline((char *)prompt); /* cast needed for old readlines */ + + if (!line) { + exit(1); + } + strip_trailing_junk(line); + sock->msglen = pm_strcpy(&sock->msg, line); + if (sock->msglen) { + add_history(sock->msg); + } + free(line); + return 1; +} + +#else /* no readline, do it ourselves */ + +#if !defined(HAVE_WIN32) +static bool bisatty(int fd) +{ + if (no_conio) { + return false; + } + return isatty(fd); +} +#endif + +/* + * Returns: 1 if data available + * 0 if timeout + * -1 if error + */ +static int +wait_for_data(int fd, int sec) +{ +#if defined(HAVE_WIN32) + return 1; +#else + fd_set fdset; + struct timeval tv; + + tv.tv_sec = sec; + tv.tv_usec = 0; + for ( ;; ) { + FD_ZERO(&fdset); + FD_SET((unsigned)fd, &fdset); + switch(select(fd + 1, &fdset, NULL, NULL, &tv)) { + case 0: /* timeout */ + return 0; + case -1: + if (errno == EINTR || errno == EAGAIN) { + continue; + } + return -1; /* error return */ + default: + return 1; + } + } +#endif +} + +/* + * Get next input command from terminal. + * + * Returns: 1 if got input + * 0 if timeout + * -1 if EOF or error + */ +int +get_cmd(FILE *input, const char *prompt, BSOCK *sock, int sec) +{ + int len; + if (!stop) { + if (output == stdout || teeout) { + sendit(prompt); + } + } +again: + switch (wait_for_data(fileno(input), sec)) { + case 0: + return 0; /* timeout */ + case -1: + return -1; /* error */ + default: + len = sizeof_pool_memory(sock->msg) - 1; + if (stop) { + sleep(1); + goto again; + } +#ifdef HAVE_CONIO + if (bisatty(fileno(input))) { + input_line(sock->msg, len); + break; + } +#endif +#ifdef HAVE_WIN32 /* use special console for input on win32 */ + if (input == stdin) { + if (win32_cgets(sock->msg, len) == NULL) { + return -1; + } + } + else +#endif + if (fgets(sock->msg, len, input) == NULL) { + return -1; + + } + break; + } + if (usrbrk()) { + clrbrk(); + } + strip_trailing_junk(sock->msg); + sock->msglen = strlen(sock->msg); + return 1; +} + +#endif /* ! HAVE_READLINE */ + + +static int console_update_history(const char *histfile) +{ + int ret=0; + +#ifdef HAVE_READLINE +/* first, try to truncate the history file, and if it + * fail, the file is probably not present, and we + * can use write_history to create it + */ + + if (history_truncate_file(histfile, 100) == 0) { + ret = append_history(history_length, histfile); + } else { + ret = write_history(histfile); + } + +#endif + + return ret; +} + +static int console_init_history(const char *histfile) +{ + int ret=0; + +#ifdef HAVE_READLINE + + using_history(); + ret = read_history(histfile); + +#endif + + return ret; +} /********************************************************************* * @@ -587,6 +752,9 @@ try_again: sendit(_("Enter a period to cancel a command.\n")); + /* Read/Update history file if HOME exists */ + POOL_MEM history_file; + /* Run commands in ~/.bconsolerc if any */ char *env = getenv("HOME"); if (env) { @@ -598,6 +766,10 @@ try_again: read_and_process_input(fd, UA_sock); fclose(fd); } + + pm_strcpy(history_file, env); + pm_strcat(history_file, "/.bconsole_history"); + console_init_history(history_file.c_str()); } read_and_process_input(stdin, UA_sock); @@ -607,11 +779,14 @@ try_again: UA_sock->close(); } + if (env) { + console_update_history(history_file.c_str()); + } + terminate_console(0); return 0; } - /* Cleanup and then exit */ static void terminate_console(int sig) { @@ -702,138 +877,6 @@ static int check_resources() return OK; } - -#ifdef HAVE_READLINE -#define READLINE_LIBRARY 1 -#undef free -#include "readline.h" -#include "history.h" - - -int -get_cmd(FILE *input, const char *prompt, BSOCK *sock, int sec) -{ - char *line; - - rl_catch_signals = 0; /* do it ourselves */ - line = readline((char *)prompt); /* cast needed for old readlines */ - - if (!line) { - exit(1); - } - strip_trailing_junk(line); - sock->msglen = pm_strcpy(&sock->msg, line); - if (sock->msglen) { - add_history(sock->msg); - } - free(line); - return 1; -} - -#else /* no readline, do it ourselves */ - -#if !defined(HAVE_WIN32) -static bool bisatty(int fd) -{ - if (no_conio) { - return false; - } - return isatty(fd); -} -#endif - -/* - * Returns: 1 if data available - * 0 if timeout - * -1 if error - */ -static int -wait_for_data(int fd, int sec) -{ -#if defined(HAVE_WIN32) - return 1; -#else - fd_set fdset; - struct timeval tv; - - tv.tv_sec = sec; - tv.tv_usec = 0; - for ( ;; ) { - FD_ZERO(&fdset); - FD_SET((unsigned)fd, &fdset); - switch(select(fd + 1, &fdset, NULL, NULL, &tv)) { - case 0: /* timeout */ - return 0; - case -1: - if (errno == EINTR || errno == EAGAIN) { - continue; - } - return -1; /* error return */ - default: - return 1; - } - } -#endif -} - -/* - * Get next input command from terminal. - * - * Returns: 1 if got input - * 0 if timeout - * -1 if EOF or error - */ -int -get_cmd(FILE *input, const char *prompt, BSOCK *sock, int sec) -{ - int len; - if (!stop) { - if (output == stdout || teeout) { - sendit(prompt); - } - } -again: - switch (wait_for_data(fileno(input), sec)) { - case 0: - return 0; /* timeout */ - case -1: - return -1; /* error */ - default: - len = sizeof_pool_memory(sock->msg) - 1; - if (stop) { - sleep(1); - goto again; - } -#ifdef HAVE_CONIO - if (bisatty(fileno(input))) { - input_line(sock->msg, len); - break; - } -#endif -#ifdef HAVE_WIN32 /* use special console for input on win32 */ - if (input == stdin) { - if (win32_cgets(sock->msg, len) == NULL) { - return -1; - } - } - else -#endif - if (fgets(sock->msg, len, input) == NULL) { - return -1; - - } - break; - } - if (usrbrk()) { - clrbrk(); - } - strip_trailing_junk(sock->msg); - sock->msglen = strlen(sock->msg); - return 1; -} - -#endif /* end non-readline code */ - static int versioncmd(FILE *input, BSOCK *UA_sock) { senditf("Version: " VERSION " (" BDATE ") %s %s %s\n", diff --git a/bacula/technotes-2.3 b/bacula/technotes-2.3 index 3055db2b96..0f24bd9d7c 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -2,6 +2,8 @@ General: 17Sep07 +ebl Add history support to bconsole when using readline. + Using Ctrl-D to exit doesn't update .bconsole_history kes Modify new volume algorithm to use max MediaId for generating next volume number rather than the count of Volumes. This should essentially eliminate the failure rate if some volumes were deleted. Bug #921. -- 2.39.5