diff --git a/Makefile b/Makefile index ede899d..10da400 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,7 @@ iso: cp grubshit/callee2 katauos/katau/callee2 cp grubshit/zsh katauos/katau/zsh + cp grubshit/ksh katauos/katau/ksh sudo umount tmp/ grub-mkrescue -o boot.iso katauos/ diff --git a/include/keyboard.h b/include/keyboard.h index 0914541..ab393b6 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -3,7 +3,14 @@ #include "../include/utils.h" #include "../include/stdio.h" +#include + +#define STDIN_BUFFER_SIZE 4096 +extern char stdin_buffer[STDIN_BUFFER_SIZE]; +extern int stdin_pos; +extern bool stdin_has_line; void handle_keyboard(); +void init_keyboard(); #endif diff --git a/include/task.h b/include/task.h index 08c1d2e..cd17008 100644 --- a/include/task.h +++ b/include/task.h @@ -27,6 +27,12 @@ typedef enum TaskState Terminated } TaskState; +enum WaitingReason { + NONE, + TIMER, + STDIN, +}; + typedef void (*EntryPoint)(void); // Структура контекста для переключения между процессами @@ -71,6 +77,7 @@ typedef struct Process uint32_t kstack_top; size_t wake_up_time;//wake up time in ticks of the processor, gets set by nanosleep syscall + enum WaitingReason waiting_reason; } Process; extern Process* current; diff --git a/src/drivers/keyboard.c b/src/drivers/keyboard.c index 5ba2288..87b3223 100644 --- a/src/drivers/keyboard.c +++ b/src/drivers/keyboard.c @@ -1,5 +1,11 @@ #include "../include/keyboard.h" #include +#include "../include/task.h" +#include "../include/string.h" + +char stdin_buffer[STDIN_BUFFER_SIZE]; +int stdin_pos = 0; +bool stdin_has_line = false; unsigned char kbdus[128] = { @@ -87,39 +93,60 @@ bool caps_pressed; void keyboard_wait(); -void handle_keyboard() -{//3a - uint8_t scancode = inb(0x60); +void handle_keyboard() { + uint8_t scancode = inb(0x60); - if(scancode & 0x80)//key released - { - scancode = scancode-0x80; - if(scancode == 0x2a || scancode == 0x36) - shift_pressed = false; - //printf("(%X)%c released ", scancode, kbdus[scancode-0x80]); - } - else//key pressed - { - if(scancode == 0x2a || scancode == 0x36) - { - shift_pressed = true; - return; - } + if (scancode & 0x80) { // Released + scancode -= 0x80; + if (scancode == 0x2A || scancode == 0x36) shift_pressed = false; + } else { // Pressed + if (scancode == 0x2A || scancode == 0x36) { + shift_pressed = true; + return; + } + if (scancode == 0x3A) { // Caps + return; + } - if(scancode == 0x3a) - { - caps_pressed = !caps_pressed; - outb(0x60, 0xed);//set LED command - keyboard_wait(); - outb(0x60, caps_pressed << 2);//0 is scroll lock, 1 is numlock, 2 is caps lock - return; - } + char c; + if (shift_pressed || caps_pressed) c = kbdus2[scancode]; + else c = kbdus[scancode]; - if(shift_pressed || caps_pressed) - printf("%c", kbdus2[scancode]); - else - printf("%c", kbdus[scancode]); //printf("(0x%X)%c", scancode, kbdus[scancode]); - } + if (c == '\b') { //Backspace + if (stdin_pos > 0) { + stdin_pos--; + printf("\b \b"); + } + } else if (c == '\n') { // Enter + if (stdin_pos < STDIN_BUFFER_SIZE - 1) { + stdin_buffer[stdin_pos++] = '\n'; + printf("\n"); + } + stdin_has_line = true; + + // Wake-up: wake up all Waiting tasks on STDIN + scheduler_lock(); + Process *p = queue; + while (p) { + if (p->state == Waiting && p->waiting_reason == STDIN) { + p->state = Ready; + p->waiting_reason = NONE; + } + p = p->next; + } + scheduler_unlock(); + } else if (c != 0 && stdin_pos < STDIN_BUFFER_SIZE - 1) {//if printable + stdin_buffer[stdin_pos++] = c; + printf("%c", c);//echo + } + } +} + +void init_keyboard() +{ + memset(stdin_buffer, 0, STDIN_BUFFER_SIZE); + stdin_pos = 0; + stdin_has_line = false; } void keyboard_wait() diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 3d87ec6..b7ae9eb 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -16,6 +16,7 @@ #include "../include/atapi.h" #include "../include/vfs.h" #include "../include/apic.h" +#include "../include/keyboard.h" #include @@ -131,10 +132,12 @@ void kmain(unsigned int magic, unsigned int info) mount_fs(); + init_keyboard(); + l9660_dir dir; l9660_file file; - follow_path("/katau/dash.", &file, &dir); + follow_path("/katau/ksh.", &file, &dir); exec_from_file(&file, &dir); diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index bdc4249..0f1b8c7 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -152,19 +152,55 @@ int sys_fork(TrapFrame *tf) return child->pid; } +#include "../../include/keyboard.h" int sys_read(TrapFrame *tf) { - if(tf->ebx < 3) + int fd = tf->ebx; + char *user_buf = (char *)tf->ecx; + size_t count = tf->edx; + + if (fd == STDIN_FILENO) { + scheduler_lock(); + while (!stdin_has_line) {//while enter has not been pressed + current->state = Waiting; + current->waiting_reason = STDIN; + schedule(); + } + scheduler_unlock(); + + //find the pos of the first \n + int line_len = 0; + while (line_len < stdin_pos && stdin_buffer[line_len] != '\n') line_len++; + if (line_len < stdin_pos) line_len++; + + //copy the input to the user buffer + int to_copy = (line_len < count) ? line_len : count; + memcpy(user_buf, stdin_buffer, to_copy); + + memmove(stdin_buffer, stdin_buffer + to_copy, stdin_pos - to_copy); + stdin_pos -= to_copy; + + stdin_has_line = false; + for (int i = 0; i < stdin_pos; i++) { + if (stdin_buffer[i] == '\n') { + stdin_has_line = true; + break; + } + } + + return to_copy; + } + else if(fd < 3) { - //TODO: implement stdin handling here + return -EBADF; } else { - if(current->file_descriptors[tf->ebx] == NULL) + if(current->file_descriptors[fd] == NULL) { return -EBADF; } - return vfs_read_file_length(current->file_descriptors[tf->ebx], (uint8_t*)tf->ecx, tf->edx); + return vfs_read_file_length(current->file_descriptors[fd], (uint8_t*)user_buf, count); //return 0;//fat_fread(current->file_descriptors[tf->ebx], (void*)tf->ecx, tf->edx); } } @@ -497,7 +533,7 @@ uint32_t sys_getcwd(TrapFrame *tf) //strcpy((char*)tf->ebx, current->cwd->fat->path); - return tf->ebx; + return strlen(final_path);//tf->ebx; } int sys_getpid(TrapFrame *tf) @@ -551,6 +587,7 @@ uint32_t sys_nanosleep(TrapFrame *tf) scheduler_lock(); current->wake_up_time = timer_ticks + ms; current->state = Waiting; + current->waiting_reason = TIMER; schedule(); scheduler_unlock(); @@ -566,7 +603,7 @@ void handle_syscall(TrapFrame *tf) debug_log("EDX: %X\n", tf->edx); */ - debug_log("calling 0x%X\n", tf->eax); + //debug_log("calling 0x%X\n", tf->eax); switch(tf->eax) { diff --git a/src/tasking/task.c b/src/tasking/task.c index e4d960c..87656e0 100644 --- a/src/tasking/task.c +++ b/src/tasking/task.c @@ -106,8 +106,11 @@ void schedule() { // Step 1: Iterate through all processes to wake up any that are due. Process* p = queue; while (p) { - if (p->state == Waiting && timer_ticks >= p->wake_up_time) { - p->state = Ready; + if(p->state == Waiting){ + if (p->waiting_reason == TIMER && timer_ticks >= p->wake_up_time) { + p->state = Ready; + p->waiting_reason = NONE; + } } p = p->next; }