From ddcaa0c99bd73671a424650c70415b178144ea7f Mon Sep 17 00:00:00 2001 From: NIWA Naoya Date: Fri, 28 Nov 2025 11:03:52 +0900 Subject: [PATCH] CLI: Add support for mapping stdin to a host file in syscall emulation --- src/cli/main.cpp | 13 +++++++++++++ src/os_emulation/ossyscall.cpp | 19 +++++++++++++++++++ src/os_emulation/ossyscall.h | 9 +++++++++ 3 files changed, 41 insertions(+) diff --git a/src/cli/main.cpp b/src/cli/main.cpp index 7fa5e1b6..a97733af 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -96,6 +96,8 @@ void create_parser(QCommandLineParser &p) { p.addOption( { { "serial-out", "serout" }, "File connected to the serial port output.", "FNAME" }); p.addOption({ { "os-emulation", "osemu" }, "Operating system emulation." }); + p.addOption( + { { "std-in", "stdin" }, "File connected to the syscall standard input.", "FNAME" }); p.addOption( { { "std-out", "stdout" }, "File connected to the syscall standard output.", "FNAME" }); p.addOption( @@ -419,8 +421,13 @@ void configure_serial_port(QCommandLineParser &p, SerialPort *ser_port) { void configure_osemu(QCommandLineParser &p, MachineConfig &config, Machine *machine) { CharIOHandler *std_out = nullptr; + QScopedPointer std_in_path; int siz; + siz = p.values("std-in").size(); + if (siz >= 1) { + std_in_path.reset(new QString(p.values("std-in").at(siz - 1))); + } siz = p.values("std-out").size(); if (siz >= 1) { auto *qf = new QFile(p.values("std-out").at(siz - 1)); @@ -438,6 +445,12 @@ void configure_osemu(QCommandLineParser &p, MachineConfig &config, Machine *mach auto *osemu_handler = new osemu::OsSyscallExceptionHandler( config.osemu_known_syscall_stop(), config.osemu_unknown_syscall_stop(), config.osemu_fs_root()); + if (!std_in_path.isNull() && !std_in_path->isEmpty()) { + if (!osemu_handler->map_stdin_to_hostfile(*std_in_path)) { + fprintf(stderr, "Failed to map stdin to host file '%s'\n", std_in_path->toLatin1().data()); + exit(EXIT_FAILURE); + } + } if (std_out) { machine::Machine::connect( osemu_handler, &osemu::OsSyscallExceptionHandler::char_written, std_out, diff --git a/src/os_emulation/ossyscall.cpp b/src/os_emulation/ossyscall.cpp index 0ab96d76..b9f9bceb 100644 --- a/src/os_emulation/ossyscall.cpp +++ b/src/os_emulation/ossyscall.cpp @@ -623,6 +623,25 @@ bool OsSyscallExceptionHandler::handle_exception( return true; } +bool OsSyscallExceptionHandler::map_stdin_to_hostfile(const QString &hostpath) { + if (hostpath.isEmpty()) return false; + int hostfd = open(hostpath.toLatin1().data(), O_RDONLY); + if (hostfd < 0) { + fprintf(stderr, "map_stdin_to_hostfile: failed to open host file '%s' errno=%d", hostpath.toLatin1().data(), errno); + return false; + } + if (fd_mapping.size() <= 0) { + fd_mapping.push_back(FD_UNUSED); + } + // If there is an existing host fd mapped at target fd 0, close it (but don't close FD_TERMINAL/FD_UNUSED/FD_INVALID) + int prev = fd_mapping[0]; + if (prev >= 0 && prev != FD_TERMINAL && prev != FD_UNUSED && prev != FD_INVALID) { + close(prev); + } + fd_mapping[0] = hostfd; + return true; +} + int32_t OsSyscallExceptionHandler::write_mem( machine::FrontendMemory *mem, Address addr, diff --git a/src/os_emulation/ossyscall.h b/src/os_emulation/ossyscall.h index d20a00cf..0a87a71a 100644 --- a/src/os_emulation/ossyscall.h +++ b/src/os_emulation/ossyscall.h @@ -35,6 +35,15 @@ class OsSyscallExceptionHandler : public machine::ExceptionHandler { machine::Address next_addr, machine::Address jump_branch_pc, machine::Address mem_ref_addr) override; + /** + * Map target fd 0 (stdin) to a host file opened from @hostpath. + * Returns true on success (host file opened and mapped), false on error. + * + * Notes: + * - Existing mapping at target fd 0 is closed if it refers to a host fd. + * - Uses filepath_to_host() to resolve @hostpath into host file path respecting fs_root. + */ + bool map_stdin_to_hostfile(const QString &hostpath); OSSYCALL_HANDLER_DECLARE(syscall_default_handler); OSSYCALL_HANDLER_DECLARE(do_sys_exit); OSSYCALL_HANDLER_DECLARE(do_sys_set_thread_area);