master
1const std = @import("std");
2const fs = std.fs;
3const mem = std.mem;
4const warn = std.log.warn;
5const fatal = std.process.fatal;
6
7pub fn main() !void {
8 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
9 defer arena_instance.deinit();
10 const arena = arena_instance.allocator();
11
12 var threaded: std.Io.Threaded = .init(arena);
13 defer threaded.deinit();
14 const io = threaded.io();
15
16 const args = try std.process.argsAlloc(arena);
17
18 const exe = args[0];
19 var catted_anything = false;
20 var stdout_buffer: [4096]u8 = undefined;
21 var stdout_writer = fs.File.stdout().writerStreaming(&stdout_buffer);
22 const stdout = &stdout_writer.interface;
23 var stdin_reader = fs.File.stdin().readerStreaming(io, &.{});
24
25 const cwd = fs.cwd();
26
27 for (args[1..]) |arg| {
28 if (mem.eql(u8, arg, "-")) {
29 catted_anything = true;
30 _ = try stdout.sendFileAll(&stdin_reader, .unlimited);
31 try stdout.flush();
32 } else if (mem.startsWith(u8, arg, "-")) {
33 return usage(exe);
34 } else {
35 const file = cwd.openFile(arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err});
36 defer file.close();
37
38 catted_anything = true;
39 var file_reader = file.reader(io, &.{});
40 _ = try stdout.sendFileAll(&file_reader, .unlimited);
41 try stdout.flush();
42 }
43 }
44 if (!catted_anything) {
45 _ = try stdout.sendFileAll(&stdin_reader, .unlimited);
46 try stdout.flush();
47 }
48}
49
50fn usage(exe: []const u8) !void {
51 warn("Usage: {s} [FILE]...\n", .{exe});
52 return error.Invalid;
53}