// cat — concatenate files to fd 1 for /bin/cat. // // With no arguments it copies fd 0 to fd 1 until EOF (the `echo hi | cat` case, // where fd 0 is the pipe read end). With arguments it opens each path and copies // its bytes to fd 1; a path that cannot be opened prints a diagnostic to fd 2 // and the next path is tried. No flags. // // Exercises a top-level `const`, an `if`/`else`, nested `while` loops with // `continue` and `orelse break`, and a cross-module import alias // (`use syscall_defs as defs`) for the EACCES error code. flibc_mem is imported // for parity with the other coreutils. use flibc use syscall_defs as defs link "flibc_start" link "flibc_mem" const BUF_LEN usize = 512 fn drain(fd i32) { var buf [BUF_LEN]u8 = undefined while true { n := flibc.sys.read(fd, &buf, buf.len) if n <= 0 { break } _ = flibc.sys.write_fd(1, &buf, #intCast(n)) } } export fn main(argc usize, argv argv) noreturn { if argc <= 1 { drain(0) } else { var i usize = 1 while i < argc { path := argv[i] orelse break i += 1 fd := flibc.sys.open(path) if fd < 0 { var msg []u8 = "cat: cannot open\n" if fd == -defs.EACCES { msg = "cat: Permission denied\n" } _ = flibc.sys.write_fd(2, msg.ptr, msg.len) continue } drain(fd) _ = flibc.sys.close(fd) } } flibc.exit() }