diff options
Diffstat (limited to 'src/basename.c')
| -rw-r--r-- | src/basename.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/basename.c b/src/basename.c new file mode 100644 index 0000000..1785754 --- /dev/null +++ b/src/basename.c @@ -0,0 +1,92 @@ +#include <getopt.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#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) { + size_t j = strlen(pathname); + char *last_char = pathname + j - 1; + for (;last_char > pathname; last_char--) { + if (*last_char != '/') { + break; + } + *last_char = '\0'; + } + + return last_char; +} + +int basename_main(int argc, char *argv[]) { + char *result = NULL; + char *suffix = NULL; + char *last_slash = NULL; + char *last_char = NULL; + char *suffix_end = NULL; + bool suffix_match = true; + size_t suffix_len = 0; + char *cursor = NULL; + + + if (getopt(argc, argv, "") != -1) { + fputs(BASENAME_USAGE, stderr); + return EXIT_FAILURE; + } + + if (argc < 2 || argc > 3) { + fprintf(stderr, "%s%s", BASENAME_USAGE, BASENAME_USE); + return EXIT_FAILURE; + } + + result = argv[1]; + suffix = argc == 3 ? argv[2] : NULL; + + /* Return empty string on empty input string */ + if (result[0] == '\0') { + 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) { + puts("/"); + return EXIT_SUCCESS; + } + + /* Keep only the last node */ + last_slash = strrchr(result, '/'); + result = last_slash == NULL ? result : last_slash + 1; + + + /* Remove suffix or return it as is if it's equal to last_node */ + if (suffix == NULL) { + puts(result); + return EXIT_SUCCESS; + } + + suffix_len = strlen(suffix); + if (suffix_len > strlen(result)) { + puts(result); + return EXIT_SUCCESS; + } + + cursor = last_char; + for (suffix_end = suffix + suffix_len - 1; suffix_end > suffix; suffix_end--) { + if (*cursor != *suffix_end) { + suffix_match = false; + break; + } + cursor--; + } + + if (suffix_match && cursor != result) { + *cursor = '\0'; + } + + puts(result); + return EXIT_SUCCESS; +} |
