diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/basename.c | 17 | ||||
| -rw-r--r-- | src/cat.c | 74 | ||||
| -rw-r--r-- | src/false.c | 5 | ||||
| -rw-r--r-- | src/main.c | 15 | ||||
| -rw-r--r-- | src/true.c | 4 |
5 files changed, 90 insertions, 25 deletions
diff --git a/src/basename.c b/src/basename.c index e07a7ee..1785754 100644 --- a/src/basename.c +++ b/src/basename.c @@ -4,8 +4,7 @@ #include <stdio.h> #include <string.h> -#define BASENAME_OUT_FMT "%s\n" -#define BASENAME_USAGE "Usage: basename NAME [SUFFIX]\n" +#define BASENAME_USAGE "Usage: basename NAME [SUFFIX]\n" #define BASENAME_USE "Return non-directory portion of a pathname\n" static char *remove_trailing_slashes(char *pathname) { @@ -33,7 +32,7 @@ int basename_main(int argc, char *argv[]) { if (getopt(argc, argv, "") != -1) { - fprintf(stderr, BASENAME_USAGE); + fputs(BASENAME_USAGE, stderr); return EXIT_FAILURE; } @@ -45,16 +44,16 @@ int basename_main(int argc, char *argv[]) { result = argv[1]; suffix = argc == 3 ? argv[2] : NULL; - /* Return "" on empty input string */ + /* Return empty string on empty input string */ if (result[0] == '\0') { - printf(BASENAME_OUT_FMT, ""); + puts(""); return EXIT_SUCCESS; } /* Remove trailing whitespace and return "/" if the path was all slashes */ last_char = remove_trailing_slashes(result); if (last_char == result) { - printf(BASENAME_OUT_FMT, "/"); + puts("/"); return EXIT_SUCCESS; } @@ -65,13 +64,13 @@ int basename_main(int argc, char *argv[]) { /* Remove suffix or return it as is if it's equal to last_node */ if (suffix == NULL) { - printf(BASENAME_OUT_FMT, result); + puts(result); return EXIT_SUCCESS; } suffix_len = strlen(suffix); if (suffix_len > strlen(result)) { - printf(BASENAME_OUT_FMT, result); + puts(result); return EXIT_SUCCESS; } @@ -88,6 +87,6 @@ int basename_main(int argc, char *argv[]) { *cursor = '\0'; } - printf(BASENAME_OUT_FMT, result); + puts(result); return EXIT_SUCCESS; } 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; +} diff --git a/src/false.c b/src/false.c index 2601ae2..f30e835 100644 --- a/src/false.c +++ b/src/false.c @@ -1,6 +1,3 @@ -int false_main(int argc, char *argv[]) { - (void) argc; - (void) argv; - +int false_main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) { return 1; } @@ -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,26 +21,22 @@ 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)) -int display_utils(int argc, char *argv[]) { - (void) argc; - (void) argv; - - printf("Available utils: "); +int display_utils([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) { + fputs("Available utils: ", stdout); for (size_t i = 1; i < UTILS_NB; i++) { printf("%s ", utils[i].name); } - printf("\n"); + putc('\n', stdout); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { - (void) argc; - char *called_basename = basename(argv[0]); for (size_t i = 0; i < UTILS_NB; i++) { @@ -1,5 +1,3 @@ -int true_main(int argc, char *argv[]) { - (void) argc; - (void) argv; +int true_main([[maybe_unused]] int argc, [[maybe_unused]] char *argv[]) { return 0; } |
