diff --git a/Sources/Subprocess/Configuration.swift b/Sources/Subprocess/Configuration.swift index aaeca18..d67eede 100644 --- a/Sources/Subprocess/Configuration.swift +++ b/Sources/Subprocess/Configuration.swift @@ -39,7 +39,8 @@ public struct Configuration: Sendable { /// The environment to use when running the executable. public var environment: Environment /// The working directory to use when running the executable. - public var workingDirectory: FilePath + /// If this property is `nil`, the subprocess will inherit the working directory from the parent process. + public var workingDirectory: FilePath? /// The platform specific options to use when /// running the subprocess. public var platformOptions: PlatformOptions @@ -54,7 +55,7 @@ public struct Configuration: Sendable { self.executable = executable self.arguments = arguments self.environment = environment - self.workingDirectory = workingDirectory ?? .currentWorkingDirectory + self.workingDirectory = workingDirectory self.platformOptions = platformOptions } @@ -107,7 +108,7 @@ extension Configuration: CustomStringConvertible, CustomDebugStringConvertible { executable: \(self.executable.description), arguments: \(self.arguments.description), environment: \(self.environment.description), - workingDirectory: \(self.workingDirectory), + workingDirectory: \(self.workingDirectory?.string ?? ""), platformOptions: \(self.platformOptions.description(withIndent: 1)) ) """ @@ -119,7 +120,7 @@ extension Configuration: CustomStringConvertible, CustomDebugStringConvertible { executable: \(self.executable.debugDescription), arguments: \(self.arguments.debugDescription), environment: \(self.environment.debugDescription), - workingDirectory: \(self.workingDirectory), + workingDirectory: \(self.workingDirectory?.string ?? ""), platformOptions: \(self.platformOptions.description(withIndent: 1)) ) """ @@ -714,14 +715,6 @@ internal struct CreatedPipe: ~Copyable { } } -extension FilePath { - static var currentWorkingDirectory: Self { - let path = getcwd(nil, 0)! - defer { free(path) } - return .init(String(cString: path)) - } -} - extension Optional where Wrapped: Collection { func withOptionalUnsafeBufferPointer( _ body: ((UnsafeBufferPointer)?) throws -> Result diff --git a/Sources/Subprocess/Platforms/Subprocess+Darwin.swift b/Sources/Subprocess/Platforms/Subprocess+Darwin.swift index 0b93cd7..a45e3e1 100644 --- a/Sources/Subprocess/Platforms/Subprocess+Darwin.swift +++ b/Sources/Subprocess/Platforms/Subprocess+Darwin.swift @@ -349,9 +349,13 @@ extension Configuration { } // Setup cwd - let intendedWorkingDir = self.workingDirectory.string - let chdirError: Int32 = intendedWorkingDir.withPlatformString { workDir in - return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) + let chdirError: Int32 + if let intendedWorkingDir = self.workingDirectory?.string { + chdirError = intendedWorkingDir.withPlatformString { workDir in + return posix_spawn_file_actions_addchdir_np(&fileActions, workDir) + } + } else { + chdirError = 0 } // Error handling @@ -457,12 +461,13 @@ extension Configuration { errorRead: errorReadFileDescriptor, errorWrite: errorWriteFileDescriptor ) - let workingDirectory = self.workingDirectory.string - guard Configuration.pathAccessible(workingDirectory, mode: F_OK) else { - throw SubprocessError( - code: .init(.failedToChangeWorkingDirectory(workingDirectory)), - underlyingError: .init(rawValue: ENOENT) - ) + if let workingDirectory = self.workingDirectory?.string { + guard Configuration.pathAccessible(workingDirectory, mode: F_OK) else { + throw SubprocessError( + code: .init(.failedToChangeWorkingDirectory(workingDirectory)), + underlyingError: .init(rawValue: ENOENT) + ) + } } throw SubprocessError( code: .init(.executableNotFound(self.executable.description)), diff --git a/Sources/Subprocess/Platforms/Subprocess+Linux.swift b/Sources/Subprocess/Platforms/Subprocess+Linux.swift index bf0d4d3..66e8de6 100644 --- a/Sources/Subprocess/Platforms/Subprocess+Linux.swift +++ b/Sources/Subprocess/Platforms/Subprocess+Linux.swift @@ -85,11 +85,10 @@ extension Configuration { errorReadFileDescriptor?.platformDescriptor() ?? -1, ] - let workingDirectory: String = self.workingDirectory.string // Spawn var pid: pid_t = 0 let spawnError: CInt = possibleExecutablePath.withCString { exePath in - return workingDirectory.withCString { workingDir in + return (self.workingDirectory?.string).withOptionalCString { workingDir in return supplementaryGroups.withOptionalUnsafeBufferPointer { sgroups in return fileDescriptors.withUnsafeBufferPointer { fds in return _subprocess_fork_exec( @@ -173,12 +172,13 @@ extension Configuration { errorRead: errorReadFileDescriptor, errorWrite: errorWriteFileDescriptor ) - let workingDirectory = self.workingDirectory.string - guard Configuration.pathAccessible(workingDirectory, mode: F_OK) else { - throw SubprocessError( - code: .init(.failedToChangeWorkingDirectory(workingDirectory)), - underlyingError: .init(rawValue: ENOENT) - ) + if let workingDirectory = self.workingDirectory?.string { + guard Configuration.pathAccessible(workingDirectory, mode: F_OK) else { + throw SubprocessError( + code: .init(.failedToChangeWorkingDirectory(workingDirectory)), + underlyingError: .init(rawValue: ENOENT) + ) + } } throw SubprocessError( code: .init(.executableNotFound(self.executable.description)), diff --git a/Sources/Subprocess/Platforms/Subprocess+Windows.swift b/Sources/Subprocess/Platforms/Subprocess+Windows.swift index 184b7b4..d65b2ea 100644 --- a/Sources/Subprocess/Platforms/Subprocess+Windows.swift +++ b/Sources/Subprocess/Platforms/Subprocess+Windows.swift @@ -84,7 +84,7 @@ extension Configuration { try environment.withCString( encodedAs: UTF16.self ) { environmentW in - try intendedWorkingDir.withNTPathRepresentation { intendedWorkingDirW in + try intendedWorkingDir.withOptionalNTPathRepresentation { intendedWorkingDirW in let created = CreateProcessW( applicationNameW, UnsafeMutablePointer(mutating: commandAndArgsW), @@ -223,7 +223,7 @@ extension Configuration { try environment.withCString( encodedAs: UTF16.self ) { environmentW in - try intendedWorkingDir.withNTPathRepresentation { intendedWorkingDirW in + try intendedWorkingDir.withOptionalNTPathRepresentation { intendedWorkingDirW in let created = CreateProcessWithLogonW( usernameW, domainW, @@ -769,7 +769,7 @@ extension Configuration { applicationName: String?, commandAndArgs: String, environment: String, - intendedWorkingDir: String + intendedWorkingDir: String? ) { // Prepare environment var env: [String: String] = [:] @@ -806,19 +806,21 @@ extension Configuration { commandAndArgs ) = try self.generateWindowsCommandAndAgruments() // Validate workingDir - guard Self.pathAccessible(self.workingDirectory.string) else { - throw SubprocessError( - code: .init( - .failedToChangeWorkingDirectory(self.workingDirectory.string) - ), - underlyingError: nil - ) + if let workingDirectory = self.workingDirectory?.string { + guard Self.pathAccessible(workingDirectory) else { + throw SubprocessError( + code: .init( + .failedToChangeWorkingDirectory(workingDirectory) + ), + underlyingError: nil + ) + } } return ( applicationName: applicationName, commandAndArgs: commandAndArgs, environment: environmentString, - intendedWorkingDir: self.workingDirectory.string + intendedWorkingDir: self.workingDirectory?.string ) } diff --git a/Sources/_SubprocessCShims/process_shims.c b/Sources/_SubprocessCShims/process_shims.c index 276be1e..55a2364 100644 --- a/Sources/_SubprocessCShims/process_shims.c +++ b/Sources/_SubprocessCShims/process_shims.c @@ -397,9 +397,11 @@ static int _subprocess_posix_spawn_fallback( if (rc != 0) { return rc; } } // Setup working directory - rc = _subprocess_addchdir_np(&file_actions, working_directory); - if (rc != 0) { - return rc; + if (working_directory != NULL) { + rc = _subprocess_addchdir_np(&file_actions, working_directory); + if (rc != 0) { + return rc; + } } // Close parent side