#include #include #include #include #include #define BASENAME_OUT_FMT "%s\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) { 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) { fprintf(stderr, BASENAME_USAGE); 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 "" on empty input string */ if (result[0] == '\0') { printf(BASENAME_OUT_FMT, ""); 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, "/"); 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) { printf(BASENAME_OUT_FMT, result); return EXIT_SUCCESS; } suffix_len = strlen(suffix); if (suffix_len > strlen(result)) { printf(BASENAME_OUT_FMT, 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'; } printf(BASENAME_OUT_FMT, result); return EXIT_SUCCESS; }