telnet_server: fix valgrind error
[fw/openocd] / src / server / telnet_server.c
index 13fbc3fda61fe0d42acc5b6873cc72085233ac01..4fc71f384e26a693e9bc0dc5d538811da732065d 100644 (file)
@@ -222,9 +222,8 @@ static int telnet_new_connection(struct connection *connection)
 {
        struct telnet_connection *telnet_connection;
        struct telnet_service *telnet_service = connection->service->priv;
-       int i;
 
-       telnet_connection = malloc(sizeof(struct telnet_connection));
+       telnet_connection = calloc(1, sizeof(struct telnet_connection));
 
        if (!telnet_connection) {
                LOG_ERROR("Failed to allocate telnet connection.");
@@ -234,9 +233,6 @@ static int telnet_new_connection(struct connection *connection)
        connection->priv = telnet_connection;
 
        /* initialize telnet connection information */
-       telnet_connection->closed = false;
-       telnet_connection->line_size = 0;
-       telnet_connection->line_cursor = 0;
        telnet_connection->prompt = strdup("> ");
        telnet_connection->prompt_visible = true;
        telnet_connection->state = TELNET_STATE_DATA;
@@ -257,11 +253,6 @@ static int telnet_new_connection(struct connection *connection)
        telnet_write(connection, "\r", 1);
        telnet_prompt(connection);
 
-       /* initialize history */
-       for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)
-               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);
@@ -592,16 +583,30 @@ static void telnet_auto_complete(struct connection *connection)
 
        LIST_HEAD(matches);
 
-       /* user command sequence, either at line beginning
-        * or we start over after these characters ';', '[', '{' */
+       /* - user command sequence, either at line beginning
+        *   or we start over after these characters ';', '[', '{'
+        * - user variable sequence, start after the character '$'
+        *   and do not contain white spaces */
+       bool is_variable_auto_completion = false;
+       bool have_spaces = false;
        size_t seq_start = (t_con->line_cursor == 0) ? 0 : (t_con->line_cursor - 1);
-       while (seq_start > 0) {
+       while (1) {
                char c = t_con->line[seq_start];
+
                if (c == ';' || c == '[' || c == '{') {
                        seq_start++;
                        break;
+               } else if (c == ' ') {
+                       have_spaces = true;
+               } else if (c == '$' && !have_spaces) {
+                       is_variable_auto_completion = true;
+                       seq_start++;
+                       break;
                }
 
+               if (seq_start == 0)
+                       break;
+
                seq_start--;
        }
 
@@ -631,7 +636,12 @@ static void telnet_auto_complete(struct connection *connection)
        query[usr_cmd_len] = '\0';
 
        /* filter commands */
-       char *query_cmd = alloc_printf("_telnet_autocomplete_helper {%s*}", query);
+       char *query_cmd;
+
+       if (is_variable_auto_completion)
+               query_cmd = alloc_printf("lsort [info vars {%s*}]", query);
+       else
+               query_cmd = alloc_printf("_telnet_autocomplete_helper {%s*}", query);
 
        if (!query_cmd) {
                LOG_ERROR("Out of memory");
@@ -659,20 +669,22 @@ static void telnet_auto_complete(struct connection *connection)
 
                /* validate the command */
                bool ignore_cmd = false;
-               Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE);
-
-               if (!jim_cmd) {
-                       /* Why we are here? Let's ignore it! */
-                       ignore_cmd = true;
-               } else if (jimcmd_is_oocd_command(jim_cmd)) {
-                       struct command *cmd = jimcmd_privdata(jim_cmd);
+               if (!is_variable_auto_completion) {
+                       Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE);
 
-                       if (cmd && !cmd->handler && !cmd->jim_handler) {
-                               /* Initial part of a multi-word command. Ignore it! */
-                               ignore_cmd = true;
-                       } else if (cmd && cmd->mode == COMMAND_CONFIG) {
-                               /* Not executable after config phase. Ignore it! */
+                       if (!jim_cmd) {
+                               /* Why we are here? Let's ignore it! */
                                ignore_cmd = true;
+                       } else if (jimcmd_is_oocd_command(jim_cmd)) {
+                               struct command *cmd = jimcmd_privdata(jim_cmd);
+
+                               if (cmd && !cmd->handler && !cmd->jim_handler) {
+                                       /* Initial part of a multi-word command. Ignore it! */
+                                       ignore_cmd = true;
+                               } else if (cmd && cmd->mode == COMMAND_CONFIG) {
+                                       /* Not executable after config phase. Ignore it! */
+                                       ignore_cmd = true;
+                               }
                        }
                }
 
@@ -925,6 +937,15 @@ static int telnet_connection_closed(struct connection *connection)
        return ERROR_OK;
 }
 
+static const struct service_driver telnet_service_driver = {
+       .name = "telnet",
+       .new_connection_during_keep_alive_handler = NULL,
+       .new_connection_handler = telnet_new_connection,
+       .input_handler = telnet_input,
+       .connection_closed_handler = telnet_connection_closed,
+       .keep_client_alive_handler = NULL,
+};
+
 int telnet_init(char *banner)
 {
        if (strcmp(telnet_port, "disabled") == 0) {
@@ -942,8 +963,7 @@ int telnet_init(char *banner)
 
        telnet_service->banner = banner;
 
-       int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
-               telnet_new_connection, telnet_input, telnet_connection_closed,
+       int ret = add_service(&telnet_service_driver, telnet_port, CONNECTION_LIMIT_UNLIMITED,
                telnet_service);
 
        if (ret != ERROR_OK) {