/* Calcite, src/user-apps/terminal/terminal.c * Copyright 2026 Benji Dial * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include #include #include #include #include #include #include #include static struct flanterm_context *flanterm_context; static ipc_dgram_receiver_handle_t input_handle; static ipc_dgram_receiver_handle_t output_handle; static struct dispatch_queue *queue; struct got_output_param { int dgram_bytes; void *dgram; }; static void got_output(void *x) { struct got_output_param *param = x; flanterm_write(flanterm_context, param->dgram, param->dgram_bytes); heap_dealloc(param->dgram, param->dgram_bytes); heap_dealloc(param, sizeof(struct got_output_param)); } [[noreturn]] static void output_thread(uint64_t) { while (1) { int dgram_bytes = 0; ipc_receive_dgram(output_handle, 0, &dgram_bytes); void *dgram = heap_alloc(dgram_bytes); ipc_receive_dgram(output_handle, dgram, &dgram_bytes); struct got_output_param *param = heap_alloc(sizeof(struct got_output_param)); param->dgram_bytes = dgram_bytes; param->dgram = dgram; dispatch(queue, &got_output, param); } } [[noreturn]] static void input_thread(uint64_t) { //TODO while (1) sleep_ms(1000000000); } void main() { uint64_t output_pipe = ipc_create_private_dgram_pipe(); uint64_t input_pipe = ipc_create_private_dgram_pipe(); ipc_create_private_dgram_receiver(output_pipe, &output_handle); ipc_create_private_dgram_sender(input_pipe, &input_handle); struct framebuffer_info fb; map_framebuffer(&fb); flanterm_context = flanterm_fb_init( &heap_alloc, &heap_dealloc, (void *)fb.fb_base, fb.fb_width, fb.fb_height, fb.fb_pitch, 8, 16, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0); queue = create_dispatch_queue(); create_thread(&output_thread, 0); create_thread(&input_thread, 0); char input_pipe_hex[17]; to_hex(input_pipe, 16, input_pipe_hex); input_pipe_hex[16] = 0; char output_pipe_hex[17]; to_hex(output_pipe, 16, output_pipe_hex); output_pipe_hex[16] = 0; const char *envvars[4] = { "TERMINAL_INPUT_PIPE_ID", input_pipe_hex, "TERMINAL_OUTPUT_PIPE_ID", output_pipe_hex }; struct process_start_info psi; psi.forwared_envvar_count = 0; psi.set_envvar_count = 2; psi.set_envvars = envvars; start_elf("root://calcite/apps/shell/shell.elf", &psi); dispatch_loop(queue); }