// POSIX compatibility support for posix proc. #include #include #include #include "posix.h" #include "posix_path.h" static SYS_PEB* gProcessPeb = NULL; // Implements the peb operation. static SYS_PEB* PosixPeb(void) { if (!gProcessPeb) gProcessPeb = SysGetPeb(); return gProcessPeb; } // Implements the posix get command line operation. __declspec(dllexport) const char* posix_get_command_line(void) { SYS_PEB* peb = PosixPeb(); if (!peb || peb->Magic != SYS_PEB_MAGIC || !peb->CommandLine.Data) return ""; return peb->CommandLine.Data; } // pid -> proc handle table (user-mode side, for waitpid). #define PROC_TABLE_SIZE 32 typedef struct { pid_t pid; uint32_t handle; bool used; } ProcEntry; static ProcEntry gProcTable[PROC_TABLE_SIZE]; // Implements the proc Table Insert operation. static void ProcTableInsert(pid_t pid, uint32_t handle) { for (int i = 0; i < PROC_TABLE_SIZE; i++) { if (!gProcTable[i].used) { gProcTable[i] = (ProcEntry){ pid, handle, true }; return; } } SysCloseHandle(handle); } // Implements the proc Table Find operation. static uint32_t ProcTableFind(pid_t pid) { for (int i = 0; i < PROC_TABLE_SIZE; i++) if (gProcTable[i].used && gProcTable[i].pid == pid) return gProcTable[i].handle; return 0; } // Implements the proc Table Remove operation. static void ProcTableRemove(pid_t pid) { for (int i = 0; i < PROC_TABLE_SIZE; i++) if (gProcTable[i].used && gProcTable[i].pid == pid) gProcTable[i].used = false; } // Build a flat Windows-style cmdline from a NULL-terminated argv array. // Each token that contains a space is wrapped in double-quotes. // argv[0] is included (it becomes the executable token visible to _start). static void BuildCmdline(char* const argv[], char* out, size_t outSize) { size_t pos = 0; for (int i = 0; argv && argv[i]; i++) { if (i > 0 && pos < outSize - 1) out[pos++] = ' '; const char* tok = argv[i]; bool needQuote = false; for (const char* c = tok; *c; c++) if (*c == ' ' || *c == '\t') { needQuote = true; break; } if (needQuote && pos < outSize - 1) out[pos++] = '"'; for (; *tok && pos < outSize - 2; tok++) { if (*tok == '"') { out[pos++] = '\\'; } out[pos++] = *tok; } if (needQuote && pos < outSize - 1) out[pos++] = '"'; } if (pos < outSize) out[pos] = '\0'; } // POSIX API. __declspec(dllexport) pid_t getpid(void) { return (pid_t)SysGetCurrentPid(); } __declspec(dllexport) int posix_spawn(pid_t* pidOut, const char* path, const posix_spawn_file_actions_t* file_actions, // ignored v1 const posix_spawnattr_t* attrp, // ignored v1 char* const argv[], char* const envp[]) // ignored v1 { (void)file_actions; (void)attrp; (void)envp; char native[512]; PosixTranslatePath(path, native, sizeof(native)); char cmdline[512]; BuildCmdline(argv, cmdline, sizeof(cmdline)); // If argv was NULL or empty, fall back to just the path so _start still // gets a meaningful argv[0]. if (cmdline[0] == '\0') { size_t len = strlen(path); if (len >= sizeof(cmdline)) len = sizeof(cmdline) - 1; memcpy(cmdline, path, len); cmdline[len] = '\0'; } uint32_t procHandle; SYS_CREATE_PROCESS_REQUEST req = { SysSvFromCstr(native), SysSvFromCstr(cmdline), &procHandle }; uint32_t s = SysCreateProcess(&req); if (s != 0) { errno = ENOENT; return -1; } uint32_t kpid = 0; SysGetProcessPid(procHandle, &kpid); ProcTableInsert((pid_t)kpid, procHandle); if (pidOut) *pidOut = (pid_t)kpid; return 0; } // options: WNOHANG not supported in v1 (always blocks). __declspec(dllexport) pid_t waitpid(pid_t pid, int* status, int options) { (void)options; uint32_t handle = ProcTableFind(pid); if (!handle) { errno = ESRCH; return -1; } SysWaitForProcess(handle); int exitCode = 0; SysGetProcessExitCode(handle, &exitCode); if (status) *status = exitCode << 8; // WEXITSTATUS convention SysCloseHandle(handle); ProcTableRemove(pid); return pid; } // Implements the exit operation. __declspec(dllexport) void exit(int status) { SysExitProcess(status); }