aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer Oliver <spen@spen-soft.co.uk>2013-03-27 16:28:31 +0000
committerFreddie Chopin <freddie.chopin@gmail.com>2013-04-21 07:28:32 +0000
commitff1108ad383c6c36095a36fc69fd3d19d6995e0f (patch)
tree85a548e3bea45d7d5cd7d44dc874ef155f8ad09e
parentd7646942f2fbbbb37af2effb3e7fdeb03c3fe6be (diff)
telnet: add telnet history support
adapted from Yoshinori Sato's patch: https://github.com/ysat0/openocd/commit/2f07f4600a0da8206612d78c159bbe1171aa41c2 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>
-rw-r--r--src/helper/configuration.c44
-rw-r--r--src/helper/configuration.h1
-rw-r--r--src/server/telnet_server.c85
3 files changed, 130 insertions, 0 deletions
diff --git a/src/helper/configuration.c b/src/helper/configuration.c
index 49c1c08f..bfb73fd7 100644
--- a/src/helper/configuration.c
+++ b/src/helper/configuration.c
@@ -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;
+}
diff --git a/src/helper/configuration.h b/src/helper/configuration.h
index b329da76..749f007d 100644
--- a/src/helper/configuration.h
+++ b/src/helper/configuration.h
@@ -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 */
diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c
index f182a043..ecdb2bfa 100644
--- a/src/server/telnet_server.c
+++ b/src/server/telnet_server.c
@@ -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]);