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>
__archive__
parent
d7646942f2
commit
ff1108ad38
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue