| #include <stdio.h> |
| #include <stdlib.h> |
| #include <console.h> |
| #include <string.h> |
| |
| #include <sys/module.h> |
| #include <sys/exec.h> |
| |
| #define INFO_PRINT(fmt, args...) printf("[COM32] " fmt, ##args) |
| |
| #define MAX_COMMAND_SIZE 80 // Maximum size of the cmd line |
| #define COMMAND_DELIM " \t\n" // Whitespace delimiters |
| #define MAX_COMMAND_ARGS (MAX_COMMAND_SIZE/2) // Maximum argument count for |
| // program execution |
| |
| /** |
| * print_help - Display usage instructions on the screen. |
| */ |
| static void print_help(void) |
| { |
| printf("List of available commands:\n"); |
| printf("exit - exits the program\n"); |
| printf("help - shows this message\n"); |
| printf("load <library>... - loads the libraries into the environment\n"); |
| printf("spawn <executable> <args> - launches an executable module\n"); |
| printf |
| ("unload <library>... - unloads the libraries from the environment\n"); |
| printf("list - prints the currently loaded modules\n"); |
| } |
| |
| /** |
| * print_prompt - Display the command prompt. |
| */ |
| static void print_prompt(void) |
| { |
| printf("\nelflink> "); |
| } |
| |
| /** |
| * read_command - Read a new command from the standard input. |
| * @cmd: the buffer to store the command |
| * @size: the maximum size of the string that can be stored in the buffer |
| * |
| * If the command is larger than the specified size, it is truncated. |
| */ |
| static void read_command(char *cmd, int size) |
| { |
| char *nl = NULL; |
| fgets(cmd, size, stdin); |
| |
| // Strip the newline |
| nl = strchr(cmd, '\n'); |
| |
| if (nl != NULL) |
| *nl = '\0'; |
| } |
| |
| /** |
| * process_spawn - Handles the execution of a 'spawn' command. |
| * |
| * The command line is in the internal buffer of strtok. |
| */ |
| static void process_spawn(void) |
| { |
| // Compose the command line |
| char **cmd_line = malloc((MAX_COMMAND_ARGS + 1) * sizeof(char *)); |
| int argc = 0, result; |
| char *crt_arg; |
| |
| do { |
| crt_arg = strtok(NULL, COMMAND_DELIM); |
| if (crt_arg != NULL && strlen(crt_arg) > 0) { |
| cmd_line[argc] = crt_arg; |
| argc++; |
| } else { |
| break; |
| } |
| } while (argc < MAX_COMMAND_ARGS); |
| |
| cmd_line[argc] = NULL; |
| |
| if (cmd_line[0] == NULL) { |
| printf("You must specify an executable module.\n"); |
| } else { |
| result = spawnv(cmd_line[0], cmd_line); |
| |
| printf("Spawn returned %d\n", result); |
| } |
| |
| free(cmd_line); |
| } |
| |
| /** |
| * process_library - Handles the execution of the 'load' and 'unload' commands. |
| * @load: contains 1 if the libraries are to be loaded, 0 for unloading. |
| * |
| * The command line is in the internal buffer of strtok. |
| */ |
| static void process_library(int load) |
| { |
| char *crt_lib; |
| int result; |
| |
| while ((crt_lib = strtok(NULL, COMMAND_DELIM)) != NULL) { |
| if (strlen(crt_lib) > 0) { |
| if (load) |
| result = load_library(crt_lib); |
| else |
| result = unload_library(crt_lib); |
| |
| if (result == 0) { |
| printf("Library '%s' %sloaded successfully.\n", crt_lib, |
| load ? "" : "un"); |
| } else { |
| printf("Could not %sload library '%s': error %d\n", |
| load ? "" : "un", crt_lib, result); |
| } |
| } |
| } |
| } |
| |
| /** |
| * process_list - Handles the execution of the 'list' command. |
| * |
| */ |
| static void process_list(void) |
| { |
| struct elf_module *module; |
| struct module_dep *crt_dep; |
| |
| for_each_module(module) { |
| printf("%s (%dK, %s, %s) : ", module->name, module->module_size >> 10, |
| module->shallow ? "shallow" : "regular", |
| module->main_func == NULL ? "library" : "program"); |
| |
| list_for_each_entry(crt_dep, &module->required, list) { |
| printf("%s ", crt_dep->module->name); |
| } |
| |
| printf("\n"); |
| } |
| } |
| |
| /** |
| * process_command - Recognizes the requested command and executes it. |
| * @cmd: the command to be executed. |
| * |
| * Returns 1 if the command was 'exit', 0 otherwise. |
| */ |
| static int process_command(char *cmd) |
| { |
| char *cmd_name; |
| |
| cmd_name = strtok(cmd, COMMAND_DELIM); |
| |
| if (strcmp(cmd_name, "exit") == 0) { |
| printf("Goodbye!\n"); |
| return 1; |
| } else if (strcmp(cmd_name, "help") == 0) { |
| print_help(); |
| } else if (strcmp(cmd_name, "load") == 0) { |
| process_library(1); |
| } else if (strcmp(cmd_name, "spawn") == 0) { |
| process_spawn(); |
| } else if (strcmp(cmd_name, "unload") == 0) { |
| process_library(0); |
| } else if (strcmp(cmd_name, "list") == 0) { |
| process_list(); |
| } else { |
| printf("Unknown command. Type 'help' for a list of valid commands.\n"); |
| } |
| |
| return 0; |
| } |
| |
| /** |
| * The entry point of 'test_com32' COM module. |
| */ |
| int main(int argc, char **argv) |
| { |
| int done = 0; |
| int res; |
| char command[MAX_COMMAND_SIZE] = { 0 }; |
| |
| // Open a standard r/w console |
| openconsole(&dev_stdcon_r, &dev_stdcon_w); |
| |
| res = exec_init(); |
| if (res != 0) { |
| printf("Failed to initialize the execution environment.\n"); |
| return res; |
| } else { |
| printf("Execution environment initialized successfully.\n"); |
| } |
| |
| printf("\nFor a list of available commands, type 'help'.\n"); |
| |
| do { |
| print_prompt(); |
| read_command(command, MAX_COMMAND_SIZE); |
| done = process_command(command); |
| |
| } while (!done); |
| |
| exec_term(); |
| |
| return 0; |
| } |