terminal fixes

This commit is contained in:
boreddevnl 2026-03-08 21:17:40 +01:00
parent 3fbcf3d4fd
commit b40d3c050d
12 changed files with 149 additions and 28 deletions

Binary file not shown.

Binary file not shown.

View file

@ -871,10 +871,12 @@ void cmd_screen_clear() {
for(int c=0; c<terminal_cols; c++) {
screen_buffer[r * terminal_cols + c].c = ' ';
screen_buffer[r * terminal_cols + c].color = COLOR_DARK_TEXT;
screen_buffer[r * terminal_cols + c].attrs = 0;
}
}
cursor_row = 0;
cursor_col = 0;
wm_mark_dirty(win_cmd.x, win_cmd.y, win_cmd.w, win_cmd.h);
}
// Public for CLI apps to use - exit/close the terminal window
@ -1159,8 +1161,6 @@ void cmd_process_finished(void) {
return;
}
extern int cursor_col;
void cmd_putchar(char c);
if (cursor_col > 0) {
cmd_putchar('\n');
}
@ -2000,6 +2000,21 @@ void cmd_handle_click(Window *win, int x, int y) {
}
}
static void cmd_handle_close(Window *win) {
if (!win) return;
extern process_t* process_get_by_ui_window(void *win);
extern void process_terminate(process_t *proc);
// Find any process associated with this terminal window and terminate it
process_t *proc = process_get_by_ui_window(win);
if (proc) {
process_terminate(proc);
}
win->visible = false;
}
void cmd_set_raw_mode(bool enabled) {
terminal_raw_mode = enabled;
}
@ -2470,6 +2485,7 @@ void cmd_init(void) {
win_cmd.handle_key = cmd_key;
win_cmd.handle_click = cmd_handle_click;
win_cmd.handle_right_click = NULL;
win_cmd.handle_close = cmd_handle_close;
win_cmd.handle_resize = cmd_handle_resize;
win_cmd.resizable = true;

Binary file not shown.

View file

@ -272,6 +272,27 @@ int network_tcp_recv(void *buf, size_t max_len) {
return (int)copied;
}
int network_tcp_recv_nb(void *buf, size_t max_len) {
if (network_processing) return -1;
network_processing = 1;
if (!tcp_recv_queue) {
network_processing = 0;
return 0;
}
size_t to_copy = max_len;
if (to_copy > tcp_recv_queue->tot_len) to_copy = tcp_recv_queue->tot_len;
if (to_copy > 0xFFFF) to_copy = 0xFFFF; // pbuf_copy_partial limit
size_t copied = pbuf_copy_partial(tcp_recv_queue, buf, (u16_t)to_copy, 0);
struct pbuf *remainder = pbuf_free_header(tcp_recv_queue, (u16_t)copied);
if (current_tcp_pcb) tcp_recved(current_tcp_pcb, (u16_t)copied);
tcp_recv_queue = remainder;
network_processing = 0;
return (int)copied;
}
int network_tcp_close(void) {
if (network_processing) return 0;
network_processing = 1;

View file

@ -89,6 +89,13 @@ int network_dhcp_acquire(void);
int network_get_gateway_ip(ipv4_address_t* ip);
int network_get_dns_ip(ipv4_address_t *ip);
int network_icmp_single_ping(ipv4_address_t *dest);
int network_tcp_connect(const ipv4_address_t *ip, uint16_t port);
int network_tcp_send(const void *data, size_t len);
int network_tcp_recv(void *buf, size_t max_len);
int network_tcp_recv_nb(void *buf, size_t max_len);
int network_tcp_close(void);
int network_dns_lookup(const char *name, ipv4_address_t *out_ip);
int network_set_dns_server(const ipv4_address_t *ip);
void network_cleanup(void);
void network_force_unlock(void);

View file

@ -329,6 +329,72 @@ uint64_t process_schedule(uint64_t current_rsp) {
return current_process->rsp;
}
static void process_cleanup_inner(process_t *proc) {
if (!proc || proc->pid == 0xFFFFFFFF) return;
// 1. Cleanup side effects
extern Window win_cmd;
if (proc->ui_window && (proc->ui_window != &win_cmd)) {
wm_remove_window((Window *)proc->ui_window);
proc->ui_window = NULL;
}
extern void fat32_close(struct FAT32_FileHandle *fh);
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
if (proc->fds[i]) {
fat32_close(proc->fds[i]);
proc->fds[i] = NULL;
}
}
extern void cmd_process_finished(void);
cmd_process_finished();
extern void network_cleanup_pcb(void *pcb);
// TODO: We need per-process PCB tracking to call this safely
// For now, let's NOT call global network_cleanup
}
void process_terminate(process_t *to_delete) {
if (!to_delete || to_delete->pid == 0xFFFFFFFF) return;
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
process_cleanup_inner(to_delete);
// 2. Find previous process in circular list
process_t *prev = to_delete;
while (prev->next != to_delete) {
prev = prev->next;
}
if (prev == to_delete) {
// Only one process (should be kernel), cannot terminate.
asm volatile("push %0; popfq" : : "r"(rflags));
return;
}
// 3. Remove current from list
prev->next = to_delete->next;
if (to_delete == current_process) {
current_process = to_delete->next;
// WARNING: If this was called as a regular function and not via a task switch,
// the stack might be in a weird state. But usually we call this via window manager
// or other external triggers.
}
// Mark slot as free
to_delete->pid = 0xFFFFFFFF;
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
to_delete->user_stack_alloc = NULL;
to_delete->kernel_stack_alloc = NULL;
asm volatile("push %0; popfq" : : "r"(rflags));
}
uint64_t process_terminate_current(void) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
@ -338,26 +404,7 @@ uint64_t process_terminate_current(void) {
return 0;
}
// 1. Cleanup side effects
extern Window win_cmd;
if (current_process->ui_window && (current_process->ui_window != &win_cmd)) {
wm_remove_window((Window *)current_process->ui_window);
current_process->ui_window = NULL;
}
extern void fat32_close(struct FAT32_FileHandle *fh);
for (int i = 0; i < MAX_PROCESS_FDS; i++) {
if (current_process->fds[i]) {
fat32_close(current_process->fds[i]);
current_process->fds[i] = NULL;
}
}
extern void cmd_process_finished(void);
cmd_process_finished();
extern void network_cleanup(void);
network_cleanup();
process_cleanup_inner(current_process);
// 2. Find previous process in circular list
process_t *prev = current_process;

View file

@ -55,6 +55,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str);
process_t* process_get_current(void);
uint64_t process_schedule(uint64_t current_rsp);
uint64_t process_terminate_current(void);
void process_terminate(process_t *proc);
void process_push_gui_event(process_t *proc, gui_event_t *ev);
process_t* process_get_by_ui_window(void* win);

View file

@ -153,7 +153,14 @@ static void user_window_resize(Window *win, int w, int h) {
}
static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
static uint64_t syscall_handler_inner(registers_t *regs) {
uint64_t syscall_num = regs->rax;
uint64_t arg1 = regs->rdi;
uint64_t arg2 = regs->rsi;
uint64_t arg3 = regs->rdx;
uint64_t arg4 = regs->r10;
uint64_t arg5 = regs->r8;
extern void cmd_write(const char *str);
extern void serial_write(const char *str);
@ -561,7 +568,7 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6
} else if (cmd == GUI_CMD_GET_EVENT) {
Window *win = (Window *)arg2;
gui_event_t *ev_out = (gui_event_t *)arg3;
if (!win || !ev_out) return 0;
if (!ev_out) return 0;
if (proc->gui_event_head != proc->gui_event_tail) {
*ev_out = proc->gui_events[proc->gui_event_head];
proc->gui_event_head = (proc->gui_event_head + 1) % MAX_GUI_EVENTS;
@ -1056,6 +1063,11 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6
extern void cmd_set_raw_mode(bool enabled);
cmd_set_raw_mode((bool)arg2);
return 0;
} else if (cmd == 42) { // SYSTEM_CMD_TCP_RECV_NB
void *buf = (void *)arg2;
size_t max_len = (size_t)arg3;
extern int network_tcp_recv_nb(void *buf, size_t max_len);
return (uint64_t)network_tcp_recv_nb(buf, max_len);
}
return -1;
}
@ -1071,8 +1083,14 @@ uint64_t syscall_handler_c(registers_t *regs) {
return process_terminate_current();
}
if (syscall_num == 5 && regs->rdi == 43) { // SYSTEM_CMD_YIELD
extern uint64_t process_schedule(uint64_t current_rsp);
regs->rax = 0;
return process_schedule((uint64_t)regs);
}
// Normal syscalls
regs->rax = syscall_handler_inner(regs->rax, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8);
regs->rax = syscall_handler_inner(regs);
// Return current RSP to assembly wrapper
return (uint64_t)regs;

View file

@ -207,6 +207,10 @@ int sys_tcp_recv(void *buf, size_t max_len) {
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_TCP_RECV, (uint64_t)buf, (uint64_t)max_len);
}
int sys_tcp_recv_nb(void *buf, size_t max_len) {
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_TCP_RECV_NB, (uint64_t)buf, (uint64_t)max_len);
}
int sys_tcp_close(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_TCP_CLOSE, 0);
}
@ -223,3 +227,7 @@ void sys_network_force_unlock(void) {
syscall2(SYS_SYSTEM, SYSTEM_CMD_NET_UNLOCK, 0);
}
void sys_yield(void) {
syscall1(SYS_SYSTEM, SYSTEM_CMD_YIELD);
}

View file

@ -69,6 +69,8 @@
#define SYSTEM_CMD_SET_DNS 38
#define SYSTEM_CMD_NET_UNLOCK 39
#define SYSTEM_CMD_SET_RAW_MODE 41
#define SYSTEM_CMD_TCP_RECV_NB 42
#define SYSTEM_CMD_YIELD 43
// Internal assembly entry into Ring 0
extern uint64_t syscall0(uint64_t sys_num);
@ -133,10 +135,12 @@ void sys_set_text_color(uint32_t color);
int sys_tcp_connect(const net_ipv4_address_t *ip, uint16_t port);
int sys_tcp_send(const void *data, size_t len);
int sys_tcp_recv(void *buf, size_t max_len);
int sys_tcp_recv_nb(void *buf, size_t max_len);
int sys_tcp_close(void);
int sys_dns_lookup(const char *name, net_ipv4_address_t *out_ip);
int sys_set_dns_server(const net_ipv4_address_t *ip);
void sys_network_force_unlock(void);
void sys_yield(void);
#endif

View file

@ -363,7 +363,7 @@ int main(int argc, char **argv) {
}
if (!connected) break;
int len = sys_tcp_recv(recv_buf, sizeof(recv_buf) - 1);
int len = sys_tcp_recv_nb(recv_buf, sizeof(recv_buf) - 1);
if (len < 0) {
printf("\r\n[Connection error]\r\n");
connected = 0;
@ -377,8 +377,7 @@ int main(int argc, char **argv) {
connected = 0;
break;
}
// Brief spin
for (volatile int d = 0; d < 100; d++);
sys_yield();
continue;
}