aboutsummaryrefslogtreecommitdiff
path: root/src/basename.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basename.c')
-rw-r--r--src/basename.c92
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;
+}