telnet: add telnet history support 10/1310/2
authorSpencer Oliver <spen@spen-soft.co.uk>
Wed, 27 Mar 2013 16:28:31 +0000 (16:28 +0000)
committerFreddie Chopin <freddie.chopin@gmail.com>
Sun, 21 Apr 2013 07:28:32 +0000 (07:28 +0000)
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>
src/helper/configuration.c
src/helper/configuration.h
src/server/telnet_server.c

index 49c1c08..bfb73fd 100644 (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;
+}
index b329da7..749f007 100644 (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 */
index f182a04..ecdb2bf 100644 (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]);