telnet: add telnet history support

adapted from Yoshinori Sato's patch:
2f07f4600a

Change-Id: I084b86d316b0aa6e9593f007c024961dbda805e9
Signed-off-by: Spencer Oliver <spen@spen-soft.co.uk>
Reviewed-on: http://openocd.zylin.com/1310
Tested-by: jenkins
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
This commit is contained in:
Spencer Oliver 2013-03-27 16:28:31 +00:00 committed by Freddie Chopin
parent d7646942f2
commit ff1108ad38
3 changed files with 130 additions and 0 deletions

View File

@ -128,3 +128,47 @@ int parse_config_file(struct command_context *cmd_ctx)
return ERROR_OK;
}
#ifndef _WIN32
#include <pwd.h>
#endif
char *get_home_dir(const char *append_path)
{
char *home = getenv("HOME");
if (home == NULL) {
#ifdef _WIN32
home = getenv("USERPROFILE");
if (home == NULL) {
char homepath[MAX_PATH];
char *drive = getenv("HOMEDRIVE");
char *path = getenv("HOMEPATH");
if (drive && path) {
snprintf(homepath, MAX_PATH, "%s/%s", drive, path);
home = homepath;
}
}
#else
struct passwd *pwd = getpwuid(getuid());
if (pwd)
home = pwd->pw_dir;
#endif
}
if (home == NULL)
return home;
char *home_path;
if (append_path)
home_path = alloc_printf("%s/%s", home, append_path);
else
home_path = alloc_printf("%s", home);
return home_path;
}

View File

@ -40,5 +40,6 @@ int configuration_output_handler(struct command_context *cmd_ctx,
FILE *open_file_from_path(const char *file, const char *mode);
char *find_file(const char *name);
char *get_home_dir(const char *append_path);
#endif /* CONFIGURATION_H */

View File

@ -30,6 +30,7 @@
#include "telnet_server.h"
#include <target/target_request.h>
#include <helper/configuration.h>
static const char *telnet_port;
@ -40,6 +41,7 @@ static char *negotiate =
"\xFF\xFE\x01"; /* IAC DON'T Echo */
#define CTRL(c) (c - '@')
#define TELNET_HISTORY ".openocd_history"
/* The only way we can detect that the socket is closed is the first time
* we write to it, we will fail. Subsequent write operations will
@ -127,6 +129,82 @@ static void telnet_log_callback(void *priv, const char *file, unsigned line,
telnet_write(connection, "\b", 1);
}
static void telnet_load_history(struct telnet_connection *t_con)
{
FILE *histfp;
char buffer[TELNET_BUFFER_SIZE];
int i = 0;
char *history = get_home_dir(TELNET_HISTORY);
if (history == NULL) {
LOG_INFO("unable to get user home directory, telnet history will be disabled");
return;
}
histfp = fopen(history, "rb");
if (histfp) {
while (fgets(buffer, sizeof(buffer), histfp) != NULL) {
char *p = strchr(buffer, '\n');
if (p)
*p = '\0';
if (buffer[0] && i < TELNET_LINE_HISTORY_SIZE)
t_con->history[i++] = strdup(buffer);
}
t_con->next_history = i;
t_con->next_history %= TELNET_LINE_HISTORY_SIZE;
/* try to set to last entry - 1, that way we skip over any exit/shutdown cmds */
t_con->current_history = t_con->next_history > 0 ? i - 1 : 0;
fclose(histfp);
}
free(history);
}
static void telnet_save_history(struct telnet_connection *t_con)
{
FILE *histfp;
int i;
int num;
char *history = get_home_dir(TELNET_HISTORY);
if (history == NULL) {
LOG_INFO("unable to get user home directory, telnet history will be disabled");
return;
}
histfp = fopen(history, "wb");
if (histfp) {
num = TELNET_LINE_HISTORY_SIZE;
i = t_con->current_history + 1;
i %= TELNET_LINE_HISTORY_SIZE;
while (t_con->history[i] == NULL && num > 0) {
i++;
i %= TELNET_LINE_HISTORY_SIZE;
num--;
}
if (num > 0) {
for (; num > 0; num--) {
fprintf(histfp, "%s\n", t_con->history[i]);
i++;
i %= TELNET_LINE_HISTORY_SIZE;
}
}
fclose(histfp);
}
free(history);
}
static int telnet_new_connection(struct connection *connection)
{
struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection));
@ -164,6 +242,7 @@ static int telnet_new_connection(struct connection *connection)
telnet_connection->history[i] = NULL;
telnet_connection->next_history = 0;
telnet_connection->current_history = 0;
telnet_load_history(telnet_connection);
log_add_callback(telnet_log_callback, connection);
@ -306,6 +385,9 @@ static int telnet_input(struct connection *connection)
/* to suppress prompt in log callback during command execution */
t_con->line_cursor = -1;
if (strcmp(t_con->line, "shutdown") == 0)
telnet_save_history(t_con);
retval = command_run_line(command_context, t_con->line);
t_con->line_cursor = 0;
@ -490,6 +572,9 @@ static int telnet_connection_closed(struct connection *connection)
t_con->prompt = NULL;
}
/* save telnet history */
telnet_save_history(t_con);
for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++) {
if (t_con->history[i]) {
free(t_con->history[i]);