/* * p1_exec_test.c — проверка EXEC, возврата к родителю и WAIT. */ #include #include #include #include #include #include #include #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 : ""); } 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; }