209 lines
4.9 KiB
C
209 lines
4.9 KiB
C
#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;
|
|
}
|