Files
Sprinter-SDCC/applications/Volkov/tests/p1_platform/p1_exec_test.c
T
snark13 8e389c03f8 Volkov: добавить Sprinter Commander
Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места.

Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
2026-09-10 10:45:30 +03:00

117 lines
3.7 KiB
C

/*
* p1_exec_test.c — проверка EXEC, возврата к родителю и WAIT.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <conio.h>
#include <sprinter.h>
#include "p1_platform.h"
typedef struct {
int rc;
int error;
uint8_t exit_code;
uint8_t wait_code;
uint8_t page_w1;
uint8_t page_w2;
uint8_t page_w3;
char cwd[256];
} P1ExecResult;
static P1ExecResult short_result;
static P1ExecResult path_result;
static char cwd_before[256];
static void run_exec_case(const char *label, const char *path,
uint8_t path_mode, P1ExecResult *result)
{
p1_heading(label);
printf("Calling EXEC: B=%u, path=%s\n", (unsigned)path_mode, path);
cputs("The child switches to 40x32 and waits for one key.\r\n");
cputs("After that it returns code 0x5A.\r\n\r\n");
cputs("Press any key to call EXEC...");
(void)getkey();
errno = 0;
result->rc = p1_exec(path_mode, path);
result->error = errno;
result->exit_code = p1_exec_exit_code;
result->wait_code = p1_wait_code();
/* Сначала снять страницы, затем исправлять видеорежим и печатать. */
result->page_w1 = _io_page_w1;
result->page_w2 = _io_page_w2;
result->page_w3 = _io_page_w3;
if (getcwd(result->cwd, sizeof(result->cwd)) == 0) {
result->cwd[0] = 0;
}
(void)settextmode(TEXT_MODE_80x32);
}
static void print_result(const char *name, const P1ExecResult *result)
{
printf("%s: rc=%d errno=%d exit=%02X wait=%02X pages=%02X/%02X/%02X\n",
name, result->rc, result->error,
(unsigned)result->exit_code, (unsigned)result->wait_code,
(unsigned)result->page_w1, (unsigned)result->page_w2,
(unsigned)result->page_w3);
printf(" cwd=%s\n", result->cwd[0] ? result->cwd : "<getcwd failed>");
}
int p1_test_exec(void)
{
uint8_t before_w1 = _io_page_w1;
uint8_t before_w2 = _io_page_w2;
uint8_t before_w3 = _io_page_w3;
int failed = 0;
if (getcwd(cwd_before, sizeof(cwd_before)) == 0) {
p1_heading("EXEC: setup failed");
printf("getcwd failed: errno=%d\n", errno);
return -1;
}
/* B=0 характеризуем для будущей командной строки. Ошибка этого случая
* не блокирует PoC: Commander будет передавать явный путь с B=1. */
run_exec_case("EXEC case 1: short name / PATH",
"P1CHILD.EXE", 0, &short_result);
/* B=1 и явный относительный путь — обязательный случай PoC. */
run_exec_case("EXEC case 2: explicit path",
".\\P1CHILD.EXE", 1, &path_result);
p1_heading("EXEC results");
printf("Parent before: pages=%02X/%02X/%02X cwd=%s\n",
(unsigned)before_w1, (unsigned)before_w2, (unsigned)before_w3,
cwd_before);
print_result("B=0", &short_result);
print_result("B=1", &path_result);
if (path_result.rc != 0 || path_result.exit_code != 0x5A ||
path_result.wait_code != 0x5A) {
puts("Required B=1 EXEC result is incorrect.");
failed++;
}
if (path_result.page_w1 != before_w1 || path_result.page_w2 != before_w2 ||
path_result.page_w3 != before_w3) {
puts("Parent window mapping was not restored.");
failed++;
}
if (strcmp(path_result.cwd, cwd_before) != 0) {
puts("Parent CWD changed after child.");
failed++;
}
if (short_result.rc != 0) {
puts("NOTE: B=0 short-name lookup failed; explicit B=1 remains usable.");
}
printf("EXEC checks failed: %u\n", (unsigned)failed);
return failed ? -1 : 0;
}