diff options
| author | Victor Mignot <victor@vmignot.fr> | 2026-03-04 15:04:26 +0100 |
|---|---|---|
| committer | Victor Mignot <victor@vmignot.fr> | 2026-03-09 19:53:55 +0100 |
| commit | 340ca1a5bdf9a03819872f7370891b6bf5529441 (patch) | |
| tree | 901c39d96011d1960bdb50800c055d863fd2f218 /src | |
| parent | 309765abe1eedb58c2b8271793257b198012f445 (diff) | |
| download | futiles-340ca1a5bdf9a03819872f7370891b6bf5529441.tar.gz | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/cat.c | 74 | ||||
| -rw-r--r-- | src/main.c | 4 |
2 files changed, 77 insertions, 1 deletions
diff --git a/src/cat.c b/src/cat.c new file mode 100644 index 0000000..2370d29 --- /dev/null +++ b/src/cat.c @@ -0,0 +1,74 @@ +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define CAT_USAGE "Usage: cat [-u] [file...]\n" +#define STDIN_ARG "-" +#define BUFFER_SIZE 20480 + +static void close_file(int fd) { + if (fd != STDIN_FILENO) { + close(fd); + } +} + +static bool print_file_content(const char *path) { + char buffer[BUFFER_SIZE]; + int input = -1; + ssize_t ret = -1; + + if (strcmp(path, STDIN_ARG) == 0) { + input = STDIN_FILENO; + } else { + if ((input = open(path, O_RDONLY)) == -1) { + fprintf(stderr,"Can't open file '%s': %s\n", path, strerror(errno)); + return false; + } + } + + do { + ret = read(input, buffer, BUFFER_SIZE); + if (ret > 0) { + write(STDOUT_FILENO, buffer, ret); + } + } while (ret > 0); + + if (ret == -1) { + fprintf(stderr, "Failed to read file '%s': %s\n", path, strerror(errno)); + } + + close_file(input); + + return ret == 0; +} + +int cat_main(int argc, char *argv[]) { + int opt = 0; + bool ret = false; + + while ((opt = getopt(argc, argv, "u")) != -1) { + if (opt != 'u') { + perror(CAT_USAGE); + return EXIT_FAILURE; + } + } + + for (int i = optind; i < argc; i++) { + ret = print_file_content(argv[i]); + if (!ret) { + break; + } + } + + /* If no argument was provided, we use stdin by default */ + if (argc - optind == 0) { + ret = print_file_content(STDIN_ARG); + } + + return ret ? EXIT_SUCCESS : EXIT_FAILURE; +} @@ -8,6 +8,7 @@ typedef int util_main(int, char **); extern util_main true_main; extern util_main false_main; extern util_main basename_main; +extern util_main cat_main; typedef struct futiles_util futiles_util_t; struct futiles_util { @@ -20,7 +21,8 @@ const futiles_util_t utils[] = { { .name = "futiles", .main = display_utils }, { .name = "true", .main = true_main }, { .name = "false", .main = false_main }, - { .name = "basename", .main = basename_main } + { .name = "basename", .main = basename_main }, + { .name = "cat", .main = cat_main } }; #define UTILS_NB (sizeof(utils) / sizeof(futiles_util_t)) |
