diff options
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/com32/hdt/hdt-cli.c')
-rw-r--r-- | contrib/syslinux/syslinux-4.03/com32/hdt/hdt-cli.c | 1121 |
1 files changed, 0 insertions, 1121 deletions
diff --git a/contrib/syslinux/syslinux-4.03/com32/hdt/hdt-cli.c b/contrib/syslinux/syslinux-4.03/com32/hdt/hdt-cli.c deleted file mode 100644 index 639bcdb..0000000 --- a/contrib/syslinux/syslinux-4.03/com32/hdt/hdt-cli.c +++ /dev/null @@ -1,1121 +0,0 @@ -/* ----------------------------------------------------------------------- * - * - * Copyright 2009 Erwan Velu - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall - * be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * ----------------------------------------------------------------------- - */ - -#include <stdlib.h> -#include <string.h> -#include <syslinux/config.h> -#include <getkey.h> -#include "hdt-cli.h" -#include "hdt-common.h" - -struct cli_mode_descr *list_modes[] = { - &hdt_mode, - &dmi_mode, - &syslinux_mode, - &pxe_mode, - &kernel_mode, - &cpu_mode, - &pci_mode, - &vesa_mode, - &disk_mode, - &vpd_mode, - &memory_mode, - NULL, -}; - -/* - * .aliases = {"q", "quit"} won't work since it is an array of pointers, not an - * array of variables. There is no easy way around it besides declaring the arrays of - * strings first. - */ -const char *exit_aliases[] = { "q", "quit" }; -const char *help_aliases[] = { "h", "?" }; - -/* List of aliases */ -struct cli_alias hdt_aliases[] = { - { - .command = CLI_EXIT, - .nb_aliases = 2, - .aliases = exit_aliases, - }, - { - .command = CLI_HELP, - .nb_aliases = 2, - .aliases = help_aliases, - }, -}; - -struct cli_mode_descr *current_mode; -int autocomplete_backlog; - -struct autocomplete_list { - char autocomplete_token[MAX_LINE_SIZE]; - struct autocomplete_list *next; -}; -struct autocomplete_list *autocomplete_head = NULL; -struct autocomplete_list *autocomplete_tail = NULL; -struct autocomplete_list *autocomplete_last_seen = NULL; - -static void autocomplete_add_token_to_list(const char *token) -{ - struct autocomplete_list *new = malloc(sizeof(struct autocomplete_list)); - - strlcpy(new->autocomplete_token, token, sizeof(new->autocomplete_token)); - new->next = NULL; - autocomplete_backlog++; - - if (autocomplete_tail != NULL) - autocomplete_tail->next = new; - if (autocomplete_head == NULL) - autocomplete_head = new; - autocomplete_tail = new; -} - -static void autocomplete_destroy_list(void) -{ - struct autocomplete_list *tmp = NULL; - - while (autocomplete_head != NULL) { - tmp = autocomplete_head->next; - free(autocomplete_head); - autocomplete_head = tmp; - } - autocomplete_backlog = 0; - autocomplete_tail = NULL; - autocomplete_last_seen = NULL; -} - -/** - * set_mode - set the current mode of the cli - * @mode: mode to set - * - * Unlike cli_set_mode, this function is not used by the cli directly. - **/ -void set_mode(cli_mode_t mode, struct s_hardware *hardware) -{ - int i = 0; - - switch (mode) { - case EXIT_MODE: - hdt_cli.mode = mode; - break; - case HDT_MODE: - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_HDT); - break; - case PXE_MODE: - if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { - printf("You are not currently using PXELINUX\n"); - break; - } - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_PXE); - break; - case KERNEL_MODE: - detect_pci(hardware); - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_KERNEL); - break; - case SYSLINUX_MODE: - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_SYSLINUX); - break; - case VESA_MODE: - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_VESA); - break; - case PCI_MODE: - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_PCI); - if (!hardware->pci_detection) - cli_detect_pci(hardware); - break; - case CPU_MODE: - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_CPU); - if (!hardware->dmi_detection) - detect_dmi(hardware); - if (!hardware->cpu_detection) - cpu_detect(hardware); - break; - case DMI_MODE: - detect_dmi(hardware); - if (!hardware->is_dmi_valid) { - printf("No valid DMI table found, exiting.\n"); - break; - } - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_DMI); - break; - case DISK_MODE: - detect_disks(hardware); - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_DISK); - break; - case VPD_MODE: - detect_vpd(hardware); - if (!hardware->is_vpd_valid) { - printf("No valid VPD table found, exiting.\n"); - break; - } - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_VPD); - break; - case MEMORY_MODE: - hdt_cli.mode = mode; - snprintf(hdt_cli.prompt, sizeof(hdt_cli.prompt), "%s> ", CLI_MEMORY); - break; - default: - /* Invalid mode */ - printf("Unknown mode, please choose among:\n"); - while (list_modes[i]) { - printf("\t%s\n", list_modes[i]->name); - i++; - } - } - - find_cli_mode_descr(hdt_cli.mode, ¤t_mode); - /* There is not cli_mode_descr struct for the exit mode */ - if (current_mode == NULL && hdt_cli.mode != EXIT_MODE) { - /* Shouldn't get here... */ - printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); - } -} - -/** - * mode_s_to_mode_t - given a mode string, return the cli_mode_t representation - **/ -cli_mode_t mode_s_to_mode_t(char *name) -{ - int i = 0; - - while (list_modes[i]) { - if (!strncmp(name, list_modes[i]->name, sizeof(list_modes[i]->name))) - break; - i++; - } - - if (!list_modes[i]) - return INVALID_MODE; - else - return list_modes[i]->mode; -} - -/** - * find_cli_mode_descr - find the cli_mode_descr struct associated to a mode - * @mode: mode to look for - * @mode_found: store the mode if found, NULL otherwise - * - * Given a mode name, return a pointer to the associated cli_mode_descr - * structure. - * Note: the current mode name is stored in hdt_cli.mode. - **/ -void find_cli_mode_descr(cli_mode_t mode, struct cli_mode_descr **mode_found) -{ - int i = 0; - - while (list_modes[i] && list_modes[i]->mode != mode) - i++; - - /* Shouldn't get here... */ - if (!list_modes[i]) - *mode_found = NULL; - else - *mode_found = list_modes[i]; -} - -/** - * expand_aliases - resolve aliases mapping - * @line: command line to parse - * @command: first token in the line - * @module: second token in the line - * @argc: number of arguments - * @argv: array of arguments - * - * We maintain a small list of static alises to enhance user experience. - * Only commands can be aliased (first token). Otherwise it can become really hairy... - **/ -static void expand_aliases(char *line __unused, char **command, char **module, - int *argc, char **argv) -{ - struct cli_mode_descr *mode; - int i, j; - - find_cli_mode_descr(mode_s_to_mode_t(*command), &mode); - if (mode != NULL && *module == NULL) { - /* - * The user specified a mode instead of `set mode...', e.g. - * `dmi' instead of `set mode dmi' - */ - - /* *argv is NULL since *module is NULL */ - *argc = 1; - *argv = malloc(*argc * sizeof(char *)); - argv[0] = malloc((sizeof(*command) + 1) * sizeof(char)); - strlcpy(argv[0], *command, sizeof(*command) + 1); - dprintf("CLI DEBUG: ALIAS %s ", *command); - - strlcpy(*command, CLI_SET, sizeof(CLI_SET)); /* set */ - - *module = malloc(sizeof(CLI_MODE) * sizeof(char)); - strlcpy(*module, CLI_MODE, sizeof(CLI_MODE)); /* mode */ - - dprintf("--> %s %s %s\n", *command, *module, argv[0]); - goto out; - } - - /* Simple aliases mapping a single command to another one */ - for (i = 0; i < MAX_ALIASES; i++) { - for (j = 0; j < hdt_aliases[i].nb_aliases; j++) { - if (!strncmp(*command, hdt_aliases[i].aliases[j], - sizeof(hdt_aliases[i].aliases[j]))) { - dprintf("CLI DEBUG: ALIAS %s ", *command); - strlcpy(*command, hdt_aliases[i].command, - sizeof(hdt_aliases[i].command) + 1); - dprintf("--> %s\n", *command); - goto out; /* Don't allow chaining aliases */ - } - } - } - return; - -out: - dprintf("CLI DEBUG: New parameters:\n"); - dprintf("CLI DEBUG: command = %s\n", *command); - dprintf("CLI DEBUG: module = %s\n", *module); - dprintf("CLI DEBUG: argc = %d\n", *argc); - for (i = 0; i < *argc; i++) - dprintf("CLI DEBUG: argv[%d] = %s\n", i, argv[0]); - return; -} - -/** - * parse_command_line - low level parser for the command line - * @line: command line to parse - * @command: first token in the line - * @module: second token in the line - * @argc: number of arguments - * @argv: array of arguments - * - * The format of the command line is: - * <main command> [<module on which to operate> [<args>]] - * command is always malloc'ed (even for an empty line) - **/ -static void parse_command_line(char *line, char **command, char **module, - int *argc, char **argv) -{ - int argc_iter = 0, args_pos = 0, token_found = 0, token_len = 0; - int args_len = 0; - char *pch = NULL, *pch_next = NULL, *tmp_pch_next = NULL; - - *command = NULL; - *module = NULL; - *argc = 0; - - pch = line; - while (pch != NULL) { - pch_next = strchr(pch + 1, ' '); - tmp_pch_next = pch_next; - - /* - * Skip whitespaces if the user entered - * 'set mode foo' for 'set mode foo' - * ^ ^ - * |___|___ pch - * |___ pch_next <- wrong! - * - * We still keep the position into tmp_pch_next to compute - * the lenght of the current token. - */ - while (pch_next != NULL && !strncmp(pch_next, CLI_SPACE, 1)) - pch_next++; - - /* End of line guaranteed to be zeroed */ - if (pch_next == NULL) { - token_len = (int)(strchr(pch + 1, '\0') - pch); - args_len = token_len; - } else { - token_len = (int)(tmp_pch_next - pch); - args_len = (int)(pch_next - pch); - } - - if (token_found == 0) { - /* Main command to execute */ - *command = malloc((token_len + 1) * sizeof(char)); - strlcpy(*command, pch, token_len); - (*command)[token_len] = '\0'; - dprintf("CLI DEBUG: command = %s\n", *command); - args_pos += args_len; - } else if (token_found == 1) { - /* Module */ - *module = malloc((token_len + 1) * sizeof(char)); - strlcpy(*module, pch, token_len); - (*module)[token_len] = '\0'; - dprintf("CLI DEBUG: module = %s\n", *module); - args_pos += args_len; - } else - (*argc)++; - - token_found++; - pch = pch_next; - } - dprintf("CLI DEBUG: argc = %d\n", *argc); - - /* Skip arguments handling if none is supplied */ - if (!*argc) - return; - - /* Transform the arguments string into an array */ - *argv = malloc(*argc * sizeof(char *)); - pch = strtok(line + args_pos, CLI_SPACE); - while (pch != NULL) { - dprintf("CLI DEBUG: argv[%d] = %s\n", argc_iter, pch); - argv[argc_iter] = malloc(sizeof(pch) * sizeof(char)); - strlcpy(argv[argc_iter], pch, sizeof(pch)); - argc_iter++; - pch = strtok(NULL, CLI_SPACE); - /* - * strtok(NULL, CLI_SPACE) over a stream of spaces - * will return an empty string - */ - while (pch != NULL && !strncmp(pch, "", 1)) - pch = strtok(NULL, CLI_SPACE); - } -} - -/** - * find_cli_callback_descr - find a callback in a list of modules - * @module_name: Name of the module to find - * @modules_list: Lits of modules among which to find @module_name - * @module_found: Pointer to the matched module, NULL if not found - * - * Given a module name and a list of possible modules, find the corresponding - * module structure that matches the module name and store it in @module_found. - **/ -void find_cli_callback_descr(const char *module_name, - struct cli_module_descr *modules_list, - struct cli_callback_descr **module_found) -{ - int modules_iter = 0; - - if (modules_list == NULL) - goto not_found; - - /* Find the callback to execute */ - while (modules_list->modules[modules_iter].name && - strcmp(module_name, modules_list->modules[modules_iter].name) != 0) - modules_iter++; - - if (modules_list->modules[modules_iter].name) { - *module_found = &(modules_list->modules[modules_iter]); - dprintf("CLI DEBUG: module %s found\n", (*module_found)->name); - return; - } - -not_found: - *module_found = NULL; - return; -} - -/** - * autocomplete_command - print matching commands - * @command: Beginning of the command - * - * Given a string @command, print all availables commands starting with - * @command. Commands are found within the list of commands for the current - * mode and the hdt mode (if the current mode is not hdt). - **/ -static void autocomplete_command(char *command) -{ - int j = 0; - struct cli_callback_descr *associated_module = NULL; - - /* First take care of the two special commands: 'show' and 'set' */ - if (strncmp(CLI_SHOW, command, strlen(command)) == 0) { - printf("%s\n", CLI_SHOW); - autocomplete_add_token_to_list(CLI_SHOW); - } - if (strncmp(CLI_SET, command, strlen(command)) == 0) { - printf("%s\n", CLI_SET); - autocomplete_add_token_to_list(CLI_SET); - } - - /* - * Then, go through the modes for the special case - * '<mode>' -> 'set mode <mode>' - */ - while (list_modes[j]) { - if (strncmp(list_modes[j]->name, command, strlen(command)) == 0) { - printf("%s\n", list_modes[j]->name); - autocomplete_add_token_to_list(list_modes[j]->name); - } - j++; - } - - /* - * Let's go now through the list of default_modules for the current mode - * (single token commands for the current_mode) - */ - j = 0; - if (current_mode->default_modules && current_mode->default_modules->modules) { - while (current_mode->default_modules->modules[j].name) { - if (strncmp(current_mode->default_modules->modules[j].name, - command, strlen(command)) == 0) { - printf("%s\n", current_mode->default_modules->modules[j].name); - autocomplete_add_token_to_list(current_mode->default_modules-> - modules[j].name); - } - j++; - } - } - - /* - * Finally, if the current_mode is not hdt, list the available - * default_modules of hdt (these are always available from any mode). - */ - if (current_mode->mode == HDT_MODE) - return; - - if (!hdt_mode.default_modules || !hdt_mode.default_modules->modules) - return; - - j = 0; - while (hdt_mode.default_modules && - hdt_mode.default_modules->modules[j].name) { - /* - * Any default command that is present in hdt mode but - * not in the current mode is available. A default - * command can be redefined in the current mode though. - * This next call tests this use case: if it is - * overwritten, do not print it again. - */ - find_cli_callback_descr(hdt_mode.default_modules->modules[j].name, - current_mode->default_modules, - &associated_module); - if (associated_module == NULL && - strncmp(command, - hdt_mode.default_modules->modules[j].name, - strlen(command)) == 0) { - printf("%s\n", hdt_mode.default_modules->modules[j].name); - autocomplete_add_token_to_list(hdt_mode.default_modules->modules[j]. - name); - } - j++; - } -} - -/** - * autocomplete_module - print matching modules - * @command: Command on the command line (not NULL) - * @module: Beginning of the module - * - * Given a command @command and a string @module, print all availables modules - * starting with @module for command @command. Commands are found within the - * list of commands for the current mode and the hdt mode (if the current mode - * is not hdt). - **/ -static void autocomplete_module(char *command, char *module) -{ - int j = 0; - char autocomplete_full_line[MAX_LINE_SIZE]; - - if (strncmp(CLI_SHOW, command, strlen(command)) == 0) { - if (!current_mode->show_modules || !current_mode->show_modules->modules) - return; - - while (current_mode->show_modules->modules[j].name) { - if (strncmp(current_mode->show_modules->modules[j].name, - module, strlen(module)) == 0) { - printf("%s\n", current_mode->show_modules->modules[j].name); - sprintf(autocomplete_full_line, "%s %s", - CLI_SHOW, current_mode->show_modules->modules[j].name); - autocomplete_add_token_to_list(autocomplete_full_line); - } - j++; - } - } else if (strncmp(CLI_SET, command, strlen(command)) == 0) { - j = 0; - if (!current_mode->set_modules || !current_mode->set_modules->modules) - return; - - while (current_mode->set_modules->modules[j].name) { - if (strncmp(current_mode->set_modules->modules[j].name, - module, strlen(module)) == 0) { - printf("%s\n", current_mode->set_modules->modules[j].name); - sprintf(autocomplete_full_line, "%s %s", - CLI_SET, current_mode->set_modules->modules[j].name); - autocomplete_add_token_to_list(autocomplete_full_line); - } - j++; - } - } -} - -/** - * autocomplete - find possible matches for a command line - * @line: command line to parse - **/ -static void autocomplete(char *line) -{ - int i; - int argc = 0; - char *command = NULL, *module = NULL; - char **argv = NULL; - - parse_command_line(line, &command, &module, &argc, argv); - - /* If the user specified arguments, there is nothing we can complete */ - if (argc != 0) - goto out; - - /* No argument, (the start of) a module has been specified */ - if (module != NULL) { - autocomplete_module(command, module); - free(module); - goto out; - } - - /* No argument, no module, (the start of) a command has been specified */ - if (command != NULL) { - autocomplete_command(command); - free(command); - goto out; - } - -out: - /* Let's not forget to clean ourselves */ - for (i = 0; i < argc; i++) - free(argv[i]); - if (argc > 0) - free(argv); - return; -} - -/** - * exec_command - main logic to map the command line to callbacks - **/ -static void exec_command(char *line, struct s_hardware *hardware) -{ - int argc, i = 0; - char *command = NULL, *module = NULL; - char **argv = NULL; - struct cli_callback_descr *current_module = NULL; - - /* This will allocate memory for command and module */ - parse_command_line(line, &command, &module, &argc, argv); - - /* - * Expand shortcuts, if needed - * This will allocate memory for argc/argv - */ - expand_aliases(line, &command, &module, &argc, argv); - - if (module == NULL) { - dprintf("CLI DEBUG: single command detected\n"); - /* - * A single word was specified: look at the list of default - * commands in the current mode to see if there is a match. - * If not, it may be a generic function (exit, help, ...). These - * are stored in the list of default commands of the hdt mode. - */ - find_cli_callback_descr(command, current_mode->default_modules, - ¤t_module); - if (current_module != NULL) - current_module->exec(argc, argv, hardware); - else if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1) && - current_mode->show_modules != NULL && - current_mode->show_modules->default_callback != NULL) - current_mode->show_modules->default_callback(argc, argv, hardware); - else if (!strncmp(command, CLI_SET, sizeof(CLI_SET) - 1) && - current_mode->set_modules != NULL && - current_mode->set_modules->default_callback != NULL) - current_mode->set_modules->default_callback(argc, argv, hardware); - else { - find_cli_callback_descr(command, hdt_mode.default_modules, - ¤t_module); - if (current_module != NULL) - current_module->exec(argc, argv, hardware); - else - printf("unknown command: '%s'\n", command); - } - } else { - /* - * A module has been specified! We now need to find the type of command. - * - * The syntax of the cli is the following: - * <type of command> <module on which to operate> <args> - * e.g. - * dmi> show system - * dmi> show bank 1 - * dmi> show memory 0 1 - * pci> show device 12 - * hdt> set mode dmi - */ - if (!strncmp(command, CLI_SHOW, sizeof(CLI_SHOW) - 1)) { - dprintf("CLI DEBUG: %s command detected\n", CLI_SHOW); - /* Look first for a 'show' callback in the current mode */ - find_cli_callback_descr(module, current_mode->show_modules, - ¤t_module); - /* Execute the callback, if found */ - if (current_module != NULL) - current_module->exec(argc, argv, hardware); - else { - /* Look now for a 'show' callback in the hdt mode */ - find_cli_callback_descr(module, hdt_mode.show_modules, - ¤t_module); - /* Execute the callback, if found */ - if (current_module != NULL) - current_module->exec(argc, argv, hardware); - else - printf("unknown module: '%s'\n", module); - } - } else if (!strncmp(command, CLI_SET, sizeof(CLI_SET) - 1)) { - dprintf("CLI DEBUG: %s command detected\n", CLI_SET); - /* Look now for a 'set' callback in the hdt mode */ - find_cli_callback_descr(module, current_mode->set_modules, - ¤t_module); - /* Execute the callback, if found */ - if (current_module != NULL) - current_module->exec(argc, argv, hardware); - else { - /* Look now for a 'set' callback in the hdt mode */ - find_cli_callback_descr(module, hdt_mode.set_modules, - ¤t_module); - /* Execute the callback, if found */ - if (current_module != NULL) - current_module->exec(argc, argv, hardware); - else - printf("unknown module: '%s'\n", module); - } - } - } - - /* Let's not forget to clean ourselves */ - if (command != NULL) - free(command); - if (module != NULL) - free(module); - for (i = 0; i < argc; i++) - free(argv[i]); - if (argc > 0) - free(argv); -} - -static void reset_prompt(void) -{ - /* No need to display the prompt if we exit */ - if (hdt_cli.mode != EXIT_MODE) { - printf("%s", hdt_cli.prompt); - /* Reset the line */ - hdt_cli.cursor_pos = 0; - } -} - -void start_auto_mode(struct s_hardware *hardware) -{ - char *mypch; - int nb_commands = 0; - char *commands[MAX_NB_AUTO_COMMANDS]; - - if (!quiet) - more_printf("\nEntering Auto mode\n"); - - /* Protecting the auto_label from the strtok modifications */ - char *temp = strdup(hardware->auto_label); - - /* Searching & saving all commands */ - mypch = strtok(temp, AUTO_SEPARATOR); - while (mypch != NULL) { - if ((strlen(remove_spaces(mypch)) > 0) && - (remove_spaces(mypch)[0] != AUTO_SEPARATOR[0])) { - nb_commands++; - if ((commands[nb_commands] = malloc(AUTO_COMMAND_SIZE)) != NULL) { - sprintf(commands[nb_commands], "%s", remove_spaces(mypch)); - } else - nb_commands--; - } - mypch = strtok(NULL, AUTO_SEPARATOR); - } - - /* Executing found commands */ - for (int i = 1; i <= nb_commands; i++) { - if (commands[i]) { - if (!quiet) - more_printf("%s%s\n", hdt_cli.prompt, commands[i]); - exec_command(commands[i], hardware); - free(commands[i]); - } - } - - if (!quiet) - more_printf("\nExiting Auto mode\n"); - - more_printf("\n"); -} - -void print_history(int argc, char **argv, struct s_hardware * hardware) -{ - (void)argc; - (void)argv; - (void)hardware; - - reset_more_printf(); - for (int i = 1; i <= MAX_HISTORY_SIZE; i++) { - if (i == hdt_cli.history_pos) { - more_printf("*%d:'%s'\n", i, hdt_cli.history[i]); - continue; - } - if (strlen(hdt_cli.history[i]) == 0) - continue; - more_printf(" %d:'%s'\n", i, hdt_cli.history[i]); - } -} - -/* Code that manages the cli mode */ -void start_cli_mode(struct s_hardware *hardware) -{ - int current_key = 0; - int future_history_pos = 1; /* position of the next position in the history */ - int current_future_history_pos = 1; /* Temp variable */ - bool display_history = true; /* Temp Variable */ - char temp_command[MAX_LINE_SIZE]; - - hdt_cli.cursor_pos = 0; - memset(hdt_cli.history, 0, sizeof(hdt_cli.history)); - hdt_cli.history_pos = 1; - hdt_cli.max_history_pos = 1; - - /* Find the mode selected */ - set_mode(HDT_MODE, hardware); - find_cli_mode_descr(hdt_cli.mode, ¤t_mode); - if (current_mode == NULL) { - /* Shouldn't get here... */ - printf("!!! BUG: Mode '%d' unknown.\n", hdt_cli.mode); - return; - } - - /* Start the auto mode if the command line is set */ - if (strlen(hardware->auto_label) > 0) { - start_auto_mode(hardware); - } - - printf("Entering CLI mode\n"); - - reset_prompt(); - - while (hdt_cli.mode != EXIT_MODE) { - - /* Display the cursor */ - display_cursor(true); - - /* Let's put the cursor blinking until we get an input */ - set_cursor_blink(true); - - /* We wait endlessly for a keyboard input */ - current_key = get_key(stdin, 0); - - /* We have to cancel the blinking mode to prevent - * input text to blink */ - set_cursor_blink(false); - - /* Reset autocomplete buffer unless TAB is pressed */ - if (current_key != KEY_TAB) - autocomplete_destroy_list(); - - switch (current_key) { - /* clear until then end of line */ - case KEY_CTRL('k'): - /* Clear the end of the line */ - clear_end_of_line(); - memset(&INPUT[hdt_cli.cursor_pos], 0, - strlen(INPUT) - hdt_cli.cursor_pos); - break; - - case KEY_CTRL('c'): - printf("\n"); - reset_prompt(); - break; - - case KEY_LEFT: - if (hdt_cli.cursor_pos > 0) { - move_cursor_left(1); - hdt_cli.cursor_pos--; - } - break; - - case KEY_RIGHT: - if (hdt_cli.cursor_pos < (int)strlen(INPUT)) { - move_cursor_right(1); - hdt_cli.cursor_pos++; - } - break; - - case KEY_CTRL('e'): - case KEY_END: - /* Calling with a 0 value will make the cursor move */ - /* So, let's move the cursor only if needed */ - if ((strlen(INPUT) - hdt_cli.cursor_pos) > 0) { - /* Return to the begining of line */ - move_cursor_right(strlen(INPUT) - hdt_cli.cursor_pos); - hdt_cli.cursor_pos = strlen(INPUT); - } - break; - - case KEY_CTRL('a'): - case KEY_HOME: - /* Calling with a 0 value will make the cursor move */ - /* So, let's move the cursor only if needed */ - if (hdt_cli.cursor_pos > 0) { - /* Return to the begining of line */ - move_cursor_left(hdt_cli.cursor_pos); - hdt_cli.cursor_pos = 0; - } - break; - - case KEY_UP: - - /* Saving future position */ - current_future_history_pos = future_history_pos; - - /* We have to compute the next position */ - if (future_history_pos == 1) { - future_history_pos = MAX_HISTORY_SIZE; - } else { - future_history_pos--; - } - - /* Does the next position is valid */ - if (strlen(hdt_cli.history[future_history_pos]) == 0) { - /* Position is invalid, restoring position */ - future_history_pos = current_future_history_pos; - break; - } - - /* Let's make that future position the one we use */ - memset(INPUT, 0, sizeof(INPUT)); - strlcpy(INPUT, hdt_cli.history[future_history_pos], sizeof(INPUT)); - - /* Clear the line */ - clear_line(); - - /* Move to the begining of line */ - move_cursor_to_column(0); - - reset_prompt(); - printf("%s", INPUT); - hdt_cli.cursor_pos = strlen(INPUT); - break; - - case KEY_DOWN: - display_history = true; - - /* Saving future position */ - current_future_history_pos = future_history_pos; - - if (future_history_pos == MAX_HISTORY_SIZE) { - future_history_pos = 1; - } else { - future_history_pos++; - } - - /* Does the next position is valid */ - if (strlen(hdt_cli.history[future_history_pos]) == 0) - display_history = false; - - /* An exception is made to reach the last empty line */ - if (future_history_pos == hdt_cli.max_history_pos) - display_history = true; - - if (display_history == false) { - /* Position is invalid, restoring position */ - future_history_pos = current_future_history_pos; - break; - } - - /* Let's make that future position the one we use */ - memset(INPUT, 0, sizeof(INPUT)); - strlcpy(INPUT, hdt_cli.history[future_history_pos], sizeof(INPUT)); - - /* Clear the line */ - clear_line(); - - /* Move to the begining of line */ - move_cursor_to_column(0); - - reset_prompt(); - printf("%s", INPUT); - hdt_cli.cursor_pos = strlen(INPUT); - break; - - case KEY_TAB: - if (autocomplete_backlog) { - clear_line(); - /* Move to the begining of line */ - move_cursor_to_column(0); - reset_prompt(); - printf("%s", autocomplete_last_seen->autocomplete_token); - strlcpy(INPUT, - autocomplete_last_seen->autocomplete_token, - sizeof(INPUT)); - hdt_cli.cursor_pos = strlen(INPUT); - - /* Cycle through the list */ - autocomplete_last_seen = autocomplete_last_seen->next; - if (autocomplete_last_seen == NULL) - autocomplete_last_seen = autocomplete_head; - } else { - printf("\n"); - autocomplete(skip_spaces(INPUT)); - autocomplete_last_seen = autocomplete_head; - - printf("%s%s", hdt_cli.prompt, INPUT); - } - break; - - case KEY_ENTER: - printf("\n"); - if (strlen(remove_spaces(INPUT)) < 1) { - reset_prompt(); - break; - } - exec_command(remove_spaces(INPUT), hardware); - hdt_cli.history_pos++; - - /* Did we reach the end of the history ?*/ - if (hdt_cli.history_pos > MAX_HISTORY_SIZE) { - /* Let's return at the beginning */ - hdt_cli.history_pos = 1; - } - - /* Does the next position is already used ? - * If yes, we are cycling in history */ - if (strlen(INPUT) > 0) { - /* Let's clean that entry */ - memset(&INPUT,0,sizeof(INPUT)); - } - - future_history_pos = hdt_cli.history_pos; - if (hdt_cli.history_pos > hdt_cli.max_history_pos) - hdt_cli.max_history_pos = hdt_cli.history_pos; - reset_prompt(); - break; - - case KEY_CTRL('d'): - case KEY_DELETE: - /* No need to delete when input is empty */ - if (strlen(INPUT) == 0) - break; - /* Don't delete when cursor is at the end of the line */ - if (hdt_cli.cursor_pos >= strlen(INPUT)) - break; - - for (int c = hdt_cli.cursor_pos; c < (int)strlen(INPUT) - 1; c++) - INPUT[c] = INPUT[c + 1]; - INPUT[strlen(INPUT) - 1] = '\0'; - - /* Clear the end of the line */ - clear_end_of_line(); - - /* Print the resulting buffer */ - printf("%s", INPUT + hdt_cli.cursor_pos); - - /* Replace the cursor at the proper place */ - if (strlen(INPUT + hdt_cli.cursor_pos) > 0) - move_cursor_left(strlen(INPUT + hdt_cli.cursor_pos)); - break; - - case KEY_DEL: - case KEY_BACKSPACE: - /* Don't delete prompt */ - if (hdt_cli.cursor_pos == 0) - break; - - for (int c = hdt_cli.cursor_pos - 1; - c < (int)strlen(INPUT) - 1; c++) - INPUT[c] = INPUT[c + 1]; - INPUT[strlen(INPUT) - 1] = '\0'; - - /* Get one char back */ - move_cursor_left(1); - - /* Clear the end of the line */ - clear_end_of_line(); - - /* Print the resulting buffer */ - printf("%s", INPUT + hdt_cli.cursor_pos - 1); - - /* Realing to a char before the place we were */ - hdt_cli.cursor_pos--; - move_cursor_to_column(strlen(hdt_cli.prompt) + hdt_cli.cursor_pos + - 1); - - break; - - case KEY_F1: - printf("\n"); - exec_command(CLI_HELP, hardware); - reset_prompt(); - break; - - default: - if ((current_key < 0x20) || (current_key > 0x7e)) - break; - /* Prevent overflow */ - if (hdt_cli.cursor_pos > MAX_LINE_SIZE - 2) - break; - /* If we aren't at the end of the input line, let's insert */ - if (hdt_cli.cursor_pos < (int)strlen(INPUT)) { - char key[2]; - int trailing_chars = strlen(INPUT) - hdt_cli.cursor_pos; - memset(temp_command, 0, sizeof(temp_command)); - strlcpy(temp_command, INPUT, hdt_cli.cursor_pos); - sprintf(key, "%c", current_key); - strncat(temp_command, key, 1); - strncat(temp_command, - INPUT + hdt_cli.cursor_pos, trailing_chars); - memset(INPUT, 0, sizeof(INPUT)); - snprintf(INPUT, sizeof(INPUT), "%s", temp_command); - - /* Clear the end of the line */ - clear_end_of_line(); - - /* Print the resulting buffer */ - printf("%s", INPUT + hdt_cli.cursor_pos); - - /* Return where we must put the new char */ - move_cursor_left(trailing_chars); - - } else { - putchar(current_key); - INPUT[hdt_cli.cursor_pos] = current_key; - } - hdt_cli.cursor_pos++; - break; - } - } -} |