commit: ccd21b73a852b3b96e52adf0d788bbe93d8329bd
parent 38639154906256254347582effbfe2856da7863a
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Thu, 8 Jul 2021 13:05:16 +0200
bin/cat: New util
Diffstat:
4 files changed, 99 insertions(+), 1 deletion(-)
diff --git a/bin/Makefile.config b/bin/Makefile.config
@@ -1,2 +1,2 @@
-EXE = args basename date del dirname echo false humanize lolcat mdate pwd range sizeof sname true tty xcd
+EXE = args basename cat date del dirname echo false humanize lolcat mdate pwd range sizeof sname true tty xcd
MAN1 = basename.1 date.1 del.1 dirname.1 humanize.1 lolcat.1 sname.1
diff --git a/bin/cat.c b/bin/cat.c
@@ -0,0 +1,75 @@
+// Collection of Unix tools, comparable to coreutils
+// Copyright 2017-2021 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
+
+#define _POSIX_C_SOURCE 200809L
+#include <errno.h> /* errno */
+#include <stdio.h> /* fprintf(), BUFSIZ */
+#include <unistd.h> /* read(), write(), close() */
+#include <string.h> /* strerror(), strncmp() */
+#include <fcntl.h> /* open(), O_RDONLY */
+
+int
+concat(int fd, const char *fdname)
+{
+ ssize_t c;
+ char buf[BUFSIZ];
+
+ while((c = read(fd, buf, sizeof(buf))) > 0)
+ {
+ if(write(1, buf, (size_t)c) < 0)
+ {
+ fprintf(stderr, "\nError writing: %s\n", strerror(errno));
+ return 1;
+ }
+ }
+
+ if(c < 0)
+ {
+ fprintf(stderr, "\nError reading ‘%s’: %s\n", fdname, strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ if(argc <= 1)
+ {
+ return concat(0, "<stdin>");
+ }
+
+ for(int argi = 1; argi < argc; argi++)
+ {
+ if(strncmp(argv[argi], "-", 2) == 0)
+ {
+ if(concat(0, "<stdin>") != 0)
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ int fd = open(argv[argi], O_RDONLY);
+ if(fd < 0) {
+ fprintf(stderr, "\nError opening ‘%s’: %s\n", argv[argi], strerror(errno));
+ return 1;
+ }
+
+ if(concat(fd, argv[argi]) != 0)
+ {
+ return 1;
+ }
+
+ if(close(fd) < 0)
+ {
+ fprintf(stderr, "\nError closing ‘%s’: %s\n", argv[argi], strerror(errno));
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/test-bin/Kyuafile b/test-bin/Kyuafile
@@ -4,6 +4,7 @@ test_suite("utils")
-- /BEGIN/,$ | LC_ALL=C.UTF-8 sort
atf_test_program{name="args"}
+atf_test_program{name="cat"}
atf_test_program{name="basename"}
atf_test_program{name="dirname"}
atf_test_program{name="sname"}
diff --git a/test-bin/cat b/test-bin/cat
@@ -0,0 +1,22 @@
+#!/usr/bin/env atf-sh
+atf_test_case openfile
+openfile_body() {
+ atf_check -o file:all_bytes ../bin/cat all_bytes
+}
+
+atf_test_case stdinput
+stdinput_body() {
+ atf_check -o file:all_bytes ../bin/cat <all_bytes
+}
+
+atf_test_case devnull
+devnull_body() {
+ atf_check ../bin/cat /dev/null
+}
+
+atf_init_test_cases() {
+ cd "$(atf_get_srcdir)"
+ atf_add_test_case openfile
+ atf_add_test_case stdinput
+ atf_add_test_case devnull
+}