diff --git a/src/cat.zig b/src/cat.zig
index 0c4bbff..4c215ca 100644
--- a/src/cat.zig
+++ b/src/cat.zig
@@ -1,61 +1,41 @@
-const std   = @import("std");
-const mem   = std.mem;
-const stdout = std.io.getStdOut().writer();
-const process = std.process;
+const std = @import("std");
+const lib = @import("./lib.zig");
 
-const fs = std.fs;
+pub fn main() anyerror!void {
+    const args = try std.process.argsAlloc(std.heap.page_allocator);
 
-const warn  = std.debug.warn;
-const print = std.debug.print;
+    if (args.len <= 1) {
+        try print_input();
+    }
 
-const cli_arguments = @import("./cli_arguments.zig");
+    const files = args[1..];
+    for (files) |f| {
+        if (std.mem.eql(u8, f, "-")) { try print_input(); }
+        else                         { try print_file (f); }
+    }
+}
 
-pub fn get_file_size(path: []const u8) !u64 {
-    var file = try fs.cwd().openFile(path, .{});
+fn print_input() !void {
+    const stdin = std.io.getStdIn().reader();
+    var buffer: [4096]u8 = undefined;
+    while (true) {
+        const nbytes = try stdin.read(&buffer);
+        lib.print("{s}", .{buffer[0..nbytes]});
+        if (nbytes == 0) break;
+    }
+}
+
+fn print_file(dest: []const u8) !void {
+    // open file and defer closing
+    var file = try std.fs.cwd().openFile(dest, .{ .mode = .read_only });
     defer file.close();
 
-    // Find the size of the file and create a buffer with this size.
-    var file_stat = try file.stat();
-    return file_stat.size;
-}
-
-fn print_file(path: []const u8) !void {
-    const size = try get_file_size(path);
-    // print("path: {}, size: {}\n", .{path, size});
-
-    // Create another allocator, for the file.
-    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
-    defer arena.deinit();
-
-    const allocator = &arena.allocator;
-    const buffer = try allocator.alloc(u8, size + 1); // Last value will be a null-byte.
-    buffer[size] = 0;
-
-    const content = try fs.cwd().readFile(path, buffer);
-    print("{}", .{content});
-}
-
-pub fn cat() !void {
-    // Here we use an ArenaAllocator backed by a DirectAllocator because `cat` is a short-lived,
-    // one shot program. We don't need to waste time freeing memory and finding places to squish
-    // bytes into. So we free everything all at once at the very end.
-    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
-    defer arena.deinit();
-
-    const allocator = &arena.allocator;
-    var args = try process.argsAlloc(allocator);
-    defer process.argsFree(allocator, args);
-
-    // Skipping the executable binary name.
-    var arg_idx: usize = 1;
-    const gui_file_path = cli_arguments.nextArg(args, &arg_idx) orelse {
-        warn("Expected first argument to be path to gui file\n", .{});
-        return error.InvalidArgs;
-    };
-
-    try print_file(gui_file_path);
-}
-
-pub fn main() !void {
-    try cat();
+    // read file content and print everything
+    var buffer: [4096]u8 = undefined;
+    var nbytes : u64 = 0;
+    while (true) {
+        nbytes = try file.read(&buffer);
+        lib.print("{s}", .{buffer[0..nbytes]});
+        if (nbytes == 0) break;
+    }
 }