System has no equivalent to fflush. In fact, it doesn't have any equivalent to the FILE * C stream APIs β only the file descriptor APIs. If you want to flush the contents of stdout's buffer, then you'll still need to use fflush. If you'd like, you can write a wrapper function that looks more idiomatic for Swift.
I don't see how FileDescriptor.duplicate can be used instead of dup and dup2. My attempt is shown below but it doesn't work because I can't get a rawValue from the duplicate method.
Your example doesn't work because savedFD and nullFD can't be accessed outside the inner do statement. But it works fine if you get rid of the inner do statement as shown here:
import Foundation
import System
func suppressPrint(_ block: () -> Void) {
do {
let stdoutFD = try FileDescriptor.standardOutput.duplicate()
let nullFD = try FileDescriptor.open("/dev/null", .writeOnly)
_ = try nullFD.duplicate(as: .standardOutput)
block()
fflush(stdout)
_ = try stdoutFD.duplicate(as: .standardOutput)
try stdoutFD.close()
try nullFD.close()
} catch {
print("Suppression failed:", error)
}
}
You're right, savedFD and nullFD should be declared outside of the do statement. Be careful if you get rid of the do statement, however. Without it, if an error was thrown, you don't know if the body function was run or not.