summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/basename.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/coreutils/basename.c b/coreutils/basename.c
index 0dd2c43..0b721c0 100644
--- a/coreutils/basename.c
+++ b/coreutils/basename.c
@@ -29,9 +29,11 @@
/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */
//usage:#define basename_trivial_usage
-//usage: "FILE [SUFFIX]"
+//usage: "FILE [SUFFIX] | -a FILE... | -s SUFFIX FILE..."
//usage:#define basename_full_usage "\n\n"
-//usage: "Strip directory path and .SUFFIX from FILE"
+//usage: "Strip directory path and SUFFIX from FILE\n"
+//usage: "\n -a All arguments are FILEs"
+//usage: "\n -s SUFFIX Remove SUFFIX (implies -a)"
//usage:
//usage:#define basename_example_usage
//usage: "$ basename /usr/local/bin/foo\n"
@@ -48,31 +50,43 @@
int basename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int basename_main(int argc UNUSED_PARAM, char **argv)
{
- size_t m, n;
- char *s;
+ unsigned opts;
+ const char *suffix = NULL;
- if (argv[1] && strcmp(argv[1], "--") == 0) {
- argv++;
- }
- if (!argv[1])
- bb_show_usage();
+ /* '+': stop at first non-option */
+ opts = getopt32(argv, "^+" "as:"
+ "\0" "-1" /* At least one argument */
+ , &suffix
+ );
+ argv += optind;
- /* It should strip slash: /abc/def/ -> def */
- s = bb_get_last_path_component_strip(*++argv);
+ do {
+ char *s;
+ size_t m;
- m = strlen(s);
- if (*++argv) {
- if (argv[1])
- bb_show_usage();
- n = strlen(*argv);
- if ((m > n) && (strcmp(s+m-n, *argv) == 0)) {
- m -= n;
- /*s[m] = '\0'; - redundant */
+ /* It should strip slash: /abc/def/ -> def */
+ s = bb_get_last_path_component_strip(*argv++);
+ m = strlen(s);
+ if (!opts) {
+ if (*argv) {
+ suffix = *argv;
+ if (argv[1])
+ bb_show_usage();
+ }
}
- }
+ if (suffix) {
+ size_t n = strlen(suffix);
+ if ((m > n) && (strcmp(s + m - n, suffix) == 0)) {
+ m -= n;
+ /*s[m] = '\0'; - redundant */
+ }
+ }
+ /* puts(s) will do, but we can do without stdio this way: */
+ s[m++] = '\n';
+ /* NB: != is correct here: */
+ if (full_write(STDOUT_FILENO, s, m) != (ssize_t)m)
+ return EXIT_FAILURE;
+ } while (opts && *argv);
- /* puts(s) will do, but we can do without stdio this way: */
- s[m++] = '\n';
- /* NB: != is correct here: */
- return full_write(STDOUT_FILENO, s, m) != (ssize_t)m;
+ return EXIT_SUCCESS;
}