Skip to content

Instantly share code, notes, and snippets.

@justinmeiners
Created June 18, 2021 17:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinmeiners/26964e9b4f5fef2fa37eca60588baead to your computer and use it in GitHub Desktop.
Save justinmeiners/26964e9b4f5fef2fa37eca60588baead to your computer and use it in GitHub Desktop.
import Darwin
enum CatError: Error {
case open(path: String)
}
func parsePosixCommands(_ args: [String]) -> ([String], [String]) {
let endOfOptions = args.firstIndex { $0 == "--" } ?? args.count
let certainArguments = args.suffix(from: endOfOptions)
var toConsider = args.prefix(upTo: endOfOptions)
let p = toConsider.partition(by: { $0.count > 1 && $0.starts(with: "-") })
return (
Array(toConsider.suffix(from: p)),
Array(toConsider.prefix(upTo: p) + certainArguments)
)
}
func cat(from: UnsafeMutablePointer<FILE>, to: UnsafeMutablePointer<FILE>) {
let bufferSize = 8192
let buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: bufferSize,
alignment: 4)
while feof(from) == 0 {
fread(buffer.baseAddress!, 1, bufferSize, from)
fwrite(buffer.baseAddress!, 1, bufferSize, to)
}
}
func cat(path: String) throws {
let opened = path == "-" ? stdin : fopen(path, "rb")
guard let handle = opened else {
throw CatError.open(path: path)
}
cat(from: handle, to: stdout)
fclose(handle)
}
let (options, args) = parsePosixCommands(Array(CommandLine.arguments.dropFirst()))
let unbuffered = args.contains("-u")
if unbuffered {
setvbuf(stdout, nil, _IONBF, 0)
}
var failures: Int32 = 0
if args.count == 0 {
cat(from: stdin, to: stdout)
} else {
for path in args {
do {
try cat(path: path)
} catch CatError.open(let path) {
failures += 1
let message = "failed to open: \(path)\n"
fputs(message, stderr)
}
}
}
exit(failures)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment