diff --git a/Sys/Sources/LinuxSys/include/LinuxSys.h b/Sys/Sources/LinuxSys/include/LinuxSys.h index 31ca8fc..ec1f8ce 100644 --- a/Sys/Sources/LinuxSys/include/LinuxSys.h +++ b/Sys/Sources/LinuxSys/include/LinuxSys.h @@ -39,9 +39,12 @@ AK_EXISTING_OPTIONS(EPOLL_EVENTS); extern __pid_t gettid (void) __THROW; extern int ppoll (struct pollfd *__fds, nfds_t __nfds, - const struct timespec *__timeout, - const __sigset_t *__ss) - __fortified_attr_access (__write_only__, 1, 2); + const struct timespec *__timeout, + const __sigset_t *__ss) + __fortified_attr_access (__write_only__, 1, 2); +extern int execvpe (const char *__file, char *const __argv[], + char *const __envp[]) + __THROW __nonnull ((1, 2)); #endif diff --git a/TinyFoundation/Sources/TinyFoundation/Process/SpoonProcess.swift b/TinyFoundation/Sources/TinyFoundation/Process/SpoonProcess.swift index bb77d60..0992a79 100644 --- a/TinyFoundation/Sources/TinyFoundation/Process/SpoonProcess.swift +++ b/TinyFoundation/Sources/TinyFoundation/Process/SpoonProcess.swift @@ -15,6 +15,7 @@ fileprivate struct ForkMetadata { // this stuff should be pre-allocated since we should not really do ANY allocations after forking due to the fact that vfork does not copy original process' memory. it's a very shady gray zone in memory management on OS side // essentially, the only thing allocated will be the stack for the `forkedCall` function call let executablePath: UnsafePointer + let isAbsolute: Bool let arguments: UnsafeMutablePointer?> let environment: UnsafeMutablePointer?> let workDirectoryPath: UnsafePointer? @@ -27,9 +28,15 @@ fileprivate func forkedCall(info: UnsafeMutableRawPointer!) -> CInt { chdir(workDirectoryPath) } - return execve(metadata.executablePath /* path */, - metadata.arguments /* argv */, - metadata.environment /* envp */ ) + if metadata.isAbsolute { + return execve(metadata.executablePath /* path */, + metadata.arguments /* argv */, + metadata.environment /* envp */ ) + } else { + return execvpe(metadata.executablePath /* path */, + metadata.arguments /* argv */, + metadata.environment /* envp */ ) + } } public func spoonProcess(executablePath: FilePath, arguments: [String] = [], environment: [String: String]? = nil, workDirectoryPath: FilePath? = nil) throws -> CInt { @@ -37,6 +44,7 @@ public func spoonProcess(executablePath: FilePath, arguments: [String] = [], env let environment = (environment ?? ProcessInfo.processInfo.environment).map { "\($0)=\($1)" } var metadata = ForkMetadata( executablePath: arguments[0].withCString { strdup($0) }, + isAbsolute: executablePath.isAbsolute, arguments: arguments.nullTerminatedArrayOfCStrings, environment: environment.nullTerminatedArrayOfCStrings, workDirectoryPath: workDirectoryPath?.withCString { strdup($0) }