2020-12-12 06:33:20 +00:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
|
|
|
|
2020-12-02 02:31:58 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
int main(int argc, char ** argv) {
|
|
|
|
int suffix_present = 0, i, j;
|
|
|
|
char *basename; char c;
|
|
|
|
int basename_length = 0, last_slash = 0;
|
|
|
|
int suffix_length = 0;
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Basename takes two arguments, one for the path itself and an optional
|
|
|
|
one for a suffix to remove (e.g. ".c" to remove the C file extension).
|
|
|
|
Here, we check for that second argument to determine if we need to
|
|
|
|
remove an extension.
|
|
|
|
|
|
|
|
If there aren't multiple arguments, check if a path was even given. If
|
|
|
|
not, the POSIX spec says to just return a newline.
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
if(argc > 2) {
|
|
|
|
suffix_present = 1;
|
|
|
|
}
|
|
|
|
else if(argc == 1) {
|
|
|
|
printf("\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
If the path is just //, the POSIX spec also says to return newline
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
if(strcmp(argv[1], "//") == 0) {
|
|
|
|
printf("\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Find the end of the path (probably could've just used strlen)
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
If the last character of the path is /, then remove it
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
if(argv[1][i-1] == '/') {
|
|
|
|
argv[1][i-1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Find the last slash in the path
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
|
|
|
|
if(c == '/') {
|
|
|
|
last_slash = i;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = last_slash + 1;
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Figure out how long the basename is
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
|
|
|
|
basename_length++; i++;
|
|
|
|
}
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Allocate memory for the basename; fail out if we can't
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
basename = calloc(basename_length + 1, sizeof(*basename));
|
|
|
|
if(basename == NULL) {
|
|
|
|
fprintf(stderr, "%s: Could not allocate sufficient memory\n", argv[0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = last_slash + 1;
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Transfer the basename to the array
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
|
|
|
|
basename[i - (last_slash + 1)] = c;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
basename[basename_length] = '\0'; /* don't forget the null! */
|
2020-12-02 02:31:58 +00:00
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
If we need to remove a suffix, check if the end of the string is
|
|
|
|
actually equal to the suffix and, if it is, replace the first character
|
|
|
|
of the suffix with a null character.
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
if(suffix_present && strcmp(basename, argv[2]) != 0) {
|
|
|
|
i = 0;
|
|
|
|
for(c = argv[2][i]; c != '\0'; c = argv[2][i]) {
|
|
|
|
suffix_length++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
j = suffix_length - 1;
|
|
|
|
|
|
|
|
for(i = basename_length - 1; i > 0; i--) {
|
|
|
|
if(basename[i] != argv[2][j]) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if(j == 0) {
|
|
|
|
basename[i] = '\0';
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
j--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-06 07:12:56 +00:00
|
|
|
/*
|
|
|
|
Print the basename, free the memory, and quit!
|
|
|
|
*/
|
2020-12-02 02:31:58 +00:00
|
|
|
printf("%s\n", basename);
|
|
|
|
|
|
|
|
free(basename);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|