logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git
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:

Mbin/Makefile.config2+-
Abin/cat.c75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest-bin/Kyuafile1+
Atest-bin/cat22++++++++++++++++++++++
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 +}