Newer
Older
CubeCactusCpp / os / userland / shell.c
@agalyaramadoss agalyaramadoss on 6 Dec 7 KB fixed keyboard serial mode
/* Simple Shell for CubeCactusOS
 * Basic command-line interface
 */

extern int printf(const char* format, ...);
extern void putchar(char c);
extern char getchar_blocking();
extern void* memset(void* dest, int val, unsigned long count);
extern unsigned long strlen(const char* str);
extern int strcmp(const char* s1, const char* s2);

/* Serial port functions */
extern void serial_init();
extern char serial_getchar();
extern void serial_putchar(char c);
extern void serial_puts(const char* str);
extern int serial_available();

#define MAX_INPUT 128
#define MAX_ARGS 16

static char input_buffer[MAX_INPUT];
static int input_pos = 0;

/* String comparison */
int strcmp(const char* s1, const char* s2) {
    while (*s1 && (*s1 == *s2)) {
        s1++;
        s2++;
    }
    return *(unsigned char*)s1 - *(unsigned char*)s2;
}

/* String starts with prefix */
int starts_with(const char* str, const char* prefix) {
    while (*prefix) {
        if (*str++ != *prefix++) return 0;
    }
    return 1;
}

/* Get a character from serial port */
char getchar_blocking() {
    return serial_getchar();
}

/* Print shell prompt */
void print_prompt() {
    printf("cubecactusos# ");
}

/* Clear input buffer */
void clear_input() {
    memset(input_buffer, 0, MAX_INPUT);
    input_pos = 0;
}

/* Execute command with serial output */
void execute_command_serial(const char* cmd) {
    if (strlen(cmd) == 0) {
        return;
    }
    
    if (strcmp(cmd, "help") == 0) {
        serial_puts("\r\nCubeCactusOS Shell Commands:\r\n");
        serial_puts("  help     - Show this help message\r\n");
        serial_puts("  about    - Display OS information\r\n");
        serial_puts("  mem      - Display memory information\r\n");
        serial_puts("  echo     - Echo text to screen\r\n");
        serial_puts("  shutdown - Shutdown the system\r\n");
        serial_puts("\r\n");
    }
    else if (strcmp(cmd, "about") == 0) {
        serial_puts("\r\nCubeCactusOS v0.1.0\r\n");
        serial_puts("A microkernel-based operating system\r\n");
        serial_puts("Based on MINIX3 architecture\r\n");
        serial_puts("Built with: x86_64-elf-gcc\r\n\r\n");
    }
    else if (strcmp(cmd, "mem") == 0) {
        serial_puts("\r\nMemory Information:\r\n");
        serial_puts("  Total RAM: 512 MB\r\n");
        serial_puts("  Kernel: ~10 KB\r\n");
        serial_puts("  Available: ~512 MB\r\n\r\n");
    }
    else if (starts_with(cmd, "echo ")) {
        serial_puts("\r\n");
        serial_puts(cmd + 5);
        serial_puts("\r\n\r\n");
    }
    else if (strcmp(cmd, "shutdown") == 0) {
        serial_puts("\r\nShutting down...\r\n");
        serial_puts("System halted.\r\n");
        for(;;) {
            __asm__ __volatile__("hlt");
        }
    }
    else {
        serial_puts("\r\nUnknown command: ");
        serial_puts(cmd);
        serial_puts("\r\nType 'help' for available commands.\r\n\r\n");
    }
}

/* Execute command */
void execute_command(const char* cmd) {
    if (strlen(cmd) == 0) {
        return;
    }
    
    if (strcmp(cmd, "help") == 0) {
        printf("\nCubeCactusOS Shell Commands:\n");
        printf("  help     - Show this help message\n");
        printf("  about    - Display OS information\n");
        printf("  clear    - Clear the screen (not implemented)\n");
        printf("  echo     - Echo text to screen\n");
        printf("  mem      - Display memory information\n");
        printf("  uptime   - Show system uptime (not implemented)\n");
        printf("  reboot   - Reboot the system (not implemented)\n");
        printf("  shutdown - Shutdown the system (not implemented)\n");
        printf("\n");
    }
    else if (strcmp(cmd, "about") == 0) {
        printf("\nCubeCactusOS v0.1.0\n");
        printf("A microkernel-based operating system\n");
        printf("Based on MINIX3 architecture\n");
        printf("Built with: x86_64-elf-gcc\n");
        printf("\nComponents:\n");
        printf("  - Microkernel (IPC, scheduling)\n");
        printf("  - Process Manager (PM)\n");
        printf("  - Virtual File System (VFS)\n");
        printf("  - TTY Driver\n");
        printf("\n");
    }
    else if (strcmp(cmd, "mem") == 0) {
        printf("\nMemory Information:\n");
        printf("  Total RAM: 512 MB (configured)\n");
        printf("  Kernel Memory: ~10 KB\n");
        printf("  Available: ~512 MB\n");
        printf("  (Note: Memory management not fully implemented)\n");
        printf("\n");
    }
    else if (starts_with(cmd, "echo ")) {
        printf("\n%s\n\n", cmd + 5);
    }
    else if (strcmp(cmd, "clear") == 0) {
        printf("\n(Clear screen not yet implemented)\n\n");
    }
    else if (strcmp(cmd, "uptime") == 0) {
        printf("\nSystem uptime: (Not yet implemented)\n");
        printf("Kernel has been running since boot.\n\n");
    }
    else if (strcmp(cmd, "reboot") == 0) {
        printf("\nRebooting system...\n");
        printf("(Reboot not yet implemented - please restart QEMU)\n\n");
    }
    else if (strcmp(cmd, "shutdown") == 0) {
        printf("\nShutting down...\n");
        printf("System halted. You can close QEMU now.\n");
        for(;;) {
            __asm__ __volatile__("hlt");
        }
    }
    else {
        printf("\nUnknown command: %s\n", cmd);
        printf("Type 'help' for available commands.\n\n");
    }
}

/* Read a line of input */
void read_line(char* buffer, int max_len) {
    int pos = 0;
    
    while (1) {
        char c = getchar_blocking();
        
        if (c == '\n') {
            buffer[pos] = '\0';
            putchar('\n');
            break;
        } else if (c == '\b') {
            /* Backspace */
            if (pos > 0) {
                pos--;
                /* Move cursor back, print space, move back again */
                putchar('\b');
                putchar(' ');
                putchar('\b');
            }
        } else if (c >= 32 && c <= 126 && pos < max_len - 1) {
            /* Printable character */
            buffer[pos++] = c;
            putchar(c);
        }
    }
}

/* Main shell loop */
void shell_main() {
    char cmd_buffer[MAX_INPUT];
    
    /* Initialize serial port */
    serial_init();
    
    /* Send welcome message to both VGA and serial */
    printf("========================================\n");
    printf("   CubeCactusOS v0.1.0\n");
    printf("========================================\n\n");
    
    serial_puts("\r\n========================================\r\n");
    serial_puts("   Welcome to CubeCactusOS Shell!\r\n");
    serial_puts("========================================\r\n");
    serial_puts("Type 'help' for available commands.\r\n\r\n");
    
    /* Interactive shell loop */
    while (1) {
        /* Print prompt to serial */
        serial_puts("cubecactusos# ");
        
        /* Read command from serial */
        int pos = 0;
        while (1) {
            char c = serial_getchar();
            
            /* Echo character back */
            serial_putchar(c);
            
            if (c == '\r' || c == '\n') {
                cmd_buffer[pos] = '\0';
                serial_puts("\r\n");
                break;
            } else if (c == '\b' || c == 127) {
                /* Backspace */
                if (pos > 0) {
                    pos--;
                    serial_puts(" \b"); /* Erase character */
                }
            } else if (c >= 32 && c <= 126 && pos < MAX_INPUT - 1) {
                /* Printable character */
                cmd_buffer[pos++] = c;
            }
        }
        
        /* Execute command and send output to serial */
        if (strlen(cmd_buffer) > 0) {
            execute_command_serial(cmd_buffer);
        }
    }
}