158 lines
4.4 KiB
C
158 lines
4.4 KiB
C
#include "drivers/device/device.h"
|
|
#include "drivers/keyboard/keyboard.h"
|
|
#include "drivers/terminal/terminal.h"
|
|
#include "prog/shell.h"
|
|
#include "mem/mem.h"
|
|
#include "types.h"
|
|
#include "std/stdio.h"
|
|
#include "std/string.h"
|
|
#include "kernel.h"
|
|
|
|
bool shell_running = false;
|
|
|
|
struct registered_command *registered_commands[COMMAND_REGISTER_SIZE];
|
|
int registered_commands_index = 0;
|
|
|
|
char shell_buf[SHELL_BUFFER_SIZE];
|
|
int shell_buf_index = 0;
|
|
|
|
void shell_start(int kbfd)
|
|
{
|
|
printf("hhhos kernel shell\n");
|
|
shell_running = true;
|
|
while (shell_running)
|
|
{
|
|
printf("\n& ");
|
|
|
|
while (true)
|
|
{
|
|
usize scancode = (usize)read(kbfd, NULL);
|
|
if (!scancode)
|
|
continue;
|
|
|
|
bool special = true;
|
|
bool finished = false;
|
|
|
|
switch (scancode)
|
|
{
|
|
case 72:
|
|
terminal_row--;
|
|
break;
|
|
case 75:
|
|
terminal_column--;
|
|
break;
|
|
case 77:
|
|
terminal_column++;
|
|
break;
|
|
case 80:
|
|
terminal_row++;
|
|
break;
|
|
case 0x1C:
|
|
finished = true;
|
|
break;
|
|
default:
|
|
special = false;
|
|
}
|
|
|
|
if (finished)
|
|
{
|
|
char cmd_name_buffer[64];
|
|
int i;
|
|
for (i = 0; i < shell_buf_index; i++)
|
|
{
|
|
if (shell_buf[i] == ' ' || shell_buf[i] == '\0')
|
|
break;
|
|
cmd_name_buffer[i] = shell_buf[i];
|
|
}
|
|
cmd_name_buffer[i + 1] = '\0';
|
|
if (!shell_handle_command(cmd_name_buffer, shell_buf))
|
|
{
|
|
printf("\nshell: no such registered command %s", cmd_name_buffer);
|
|
};
|
|
shell_buf_index = 0;
|
|
break;
|
|
}
|
|
if (!special)
|
|
{
|
|
if (shell_buf_index < SHELL_BUFFER_SIZE)
|
|
{
|
|
const unsigned char key = keyboard_get_key_from_scancode(scancode);
|
|
shell_buf[shell_buf_index] = key;
|
|
terminal_putchar(key);
|
|
shell_buf_index++;
|
|
}
|
|
else
|
|
{
|
|
printf("shell: buffer overflow (i = %d)\n", shell_buf_index);
|
|
break;
|
|
}
|
|
}
|
|
terminal_updatecursor();
|
|
}
|
|
}
|
|
}
|
|
|
|
void shell_stop()
|
|
{
|
|
for (int i = 0; i < registered_commands_index; i++)
|
|
{
|
|
free(registered_commands[i]);
|
|
}
|
|
registered_commands_index = 0;
|
|
shell_buf_index = 0;
|
|
|
|
shell_running = false;
|
|
}
|
|
|
|
void shell_register_command_handler(const char *command, int fd_handler)
|
|
{
|
|
struct registered_command *reg = (struct registered_command *)malloc(sizeof(struct registered_command));
|
|
reg->command = command;
|
|
reg->fd_handler = fd_handler;
|
|
registered_commands[registered_commands_index] = reg;
|
|
registered_commands_index++;
|
|
}
|
|
|
|
int shell_handle_command(const char *command, const char *args)
|
|
{
|
|
/* find the command handler */
|
|
for (int i = 0; i < registered_commands_index; i++)
|
|
{
|
|
struct registered_command *reg = (struct registered_command *)registered_commands[i];
|
|
if (!memcmp(reg->command, command, strlen(command)))
|
|
{
|
|
struct command_run_packet *packet = (struct command_run_packet *)malloc(sizeof(struct command_run_packet));
|
|
packet->args = args;
|
|
/* communicate the arguments and other parameters to the command handler by writing to its file descriptor */
|
|
write(reg->fd_handler, packet);
|
|
free(packet);
|
|
return 1;
|
|
}
|
|
}
|
|
/* we didn't find anything :( */
|
|
return 0;
|
|
}
|
|
|
|
void shell_register_basic_commands()
|
|
{
|
|
void *dummy_read(void *unused)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
void *fishfetch_write(void *unused)
|
|
{
|
|
printf("\n<>< OS: hhhos\n");
|
|
printf(" SHELL: hhhos kernel shell compatible\n");
|
|
printf(" DISPLAY: %s\n", (is_using_framebuffer()) ? "Framebuffer" : "Other");
|
|
printf(" TOTAL MEMORY: %ld KiB\n", get_total_memory() / 1024);
|
|
}
|
|
|
|
struct device fishfetch_device = {
|
|
write : &fishfetch_write,
|
|
read : &dummy_read
|
|
};
|
|
|
|
shell_register_command_handler("fishfetch", push_device(fishfetch_device));
|
|
}
|