HhhOS/arch/x86_64/prog/shell.c
2021-08-24 20:56:50 +03:00

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));
}