OreBolt-OS/modules/orebolt-vterm/vterm.c

94 lines
2.8 KiB
C
Executable File

/*
* vterm.c -- FreeDOS Emulation Bridge module
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* Forks dosbox with a custom config for the
* FreeDOS environment. BACK key sends SIGTERM to the child.
* Monitors child exit via waitpid(WNOHANG).
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#include <linux/input.h>
#include "h2_ui.h"
#include "log_manager.h"
int main(void) {
init_h2_graphics_runtime("X86 EMULATION ENVIRONMENT");
LOG_INF("vterm module started");
lv_obj_t *scr = lv_scr_act();
lv_obj_t *title = lv_label_create(scr);
lv_label_set_text(title, "EMULATION RUNTIME ENGINE");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 15);
lv_obj_set_style_text_color(title, COLOR_PRIMARY, LV_PART_MAIN);
lv_obj_t *status = lv_label_create(scr);
lv_label_set_text(status, "Launching FreeDOS container...\n[BACK] to terminate");
lv_obj_align(status, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_style_text_align(status, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_timer_handler();
pid_t pid = fork();
if (pid == 0) {
char *args[] = {"/usr/bin/dosbox", "-conf", "/data/vterm/dosbox.conf", NULL};
execv(args[0], args);
_exit(1);
}
if (pid < 0) {
lv_label_set_text(status, "FORK FAILED");
LOG_ERR("fork failed for dosbox");
} else {
LOG_INF("dosbox launched (pid %d)", (int)pid);
}
int input_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
struct input_event ev;
int child_done = (pid < 0);
while (!child_done) {
lv_timer_handler();
int wstatus;
pid_t ret = waitpid(pid, &wstatus, WNOHANG);
if (ret == pid) {
child_done = 1;
lv_label_set_text(status, "DOSBOX EXITED.\n[BACK] to return");
LOG_INF("dosbox exited");
}
if (input_fd >= 0 && read(input_fd, &ev, sizeof(struct input_event)) > 0) {
if (ev.type == EV_KEY && ev.code == H2_KEY_BACK && ev.value == 1) {
if (!child_done && pid > 0) {
kill(pid, SIGTERM);
usleep(200000);
waitpid(pid, &wstatus, WNOHANG);
LOG_INF("dosbox terminated by user");
}
break;
}
}
usleep(20000);
}
if (child_done && input_fd >= 0) {
while (1) {
lv_timer_handler();
if (read(input_fd, &ev, sizeof(struct input_event)) > 0) {
if (ev.type == EV_KEY && ev.code == H2_KEY_BACK && ev.value == 1)
break;
}
usleep(20000);
}
}
if (input_fd >= 0) close(input_fd);
LOG_INF("vterm module exited");
return 0;
}