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