Expand admin SSH command capabilities

Add per-session history, tab completion, interactive prompts, and
bounded input handling. Support deferred lifecycle and host-key actions
after output drains, and document the expanded administration workflow.
This commit is contained in:
2026-08-30 18:34:01 +02:00
parent 0a1bbd6782
commit c2c11fee4e
14 changed files with 699 additions and 224 deletions
+48
View File
@@ -10,6 +10,11 @@
#include "esp_console.h"
#include "linenoise/linenoise.h"
static const char *const s_root_candidates[] = {
"help", "status", "debug", "display", "serial", "broker", "usb", "user",
"wifi", "web", "ssh", "ping", "nslookup", "traceroute", "reboot", "memory",
};
/* Keep full-line candidate strings grouped by their registered root command. */
static const char *const s_completion_candidates[] = {
/* Hardware debug commands and safe fixed arguments. */
@@ -197,6 +202,49 @@ static const char *const s_completion_candidates[] = {
"ssh reset --force",
};
bool console_completion_expand(const char *line, char *completed, size_t capacity)
{
if (line == NULL || completed == NULL || capacity == 0U) {
return false;
}
size_t line_length = strlen(line);
const char *const *candidates = strchr(line, ' ') == NULL
? s_root_candidates
: s_completion_candidates;
size_t candidate_count = strchr(line, ' ') == NULL
? sizeof(s_root_candidates) / sizeof(s_root_candidates[0])
: sizeof(s_completion_candidates) /
sizeof(s_completion_candidates[0]);
const char *first = NULL;
size_t common_length = 0U;
for (size_t index = 0U; index < candidate_count; ++index) {
const char *candidate = candidates[index];
if (strncmp(candidate, line, line_length) != 0) {
continue;
}
if (first == NULL) {
first = candidate;
common_length = strlen(candidate);
continue;
}
size_t candidate_length = strlen(candidate);
if (common_length > candidate_length) {
common_length = candidate_length;
}
size_t offset = line_length;
while (offset < common_length && first[offset] == candidate[offset]) {
++offset;
}
common_length = offset;
}
if (first == NULL || common_length <= line_length || common_length >= capacity) {
return false;
}
memcpy(completed, first, common_length);
completed[common_length] = '\0';
return true;
}
static ssize_t console_read_with_late_terminal_upgrade(int file_descriptor,
void *buffer,
size_t size)