1/* vi: set sw=4 ts=4: */ 2/* 3 * Mini basename implementation for busybox 4 * 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 */ 9/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) 10 * 11 * Changes: 12 * 1) Now checks for too many args. Need at least one and at most two. 13 * 2) Don't check for options, as per SUSv3. 14 * 3) Save some space by using strcmp(). Calling strncmp() here was silly. 15 */ 16//config:config BASENAME 17//config: bool "basename (438 bytes)" 18//config: default y 19//config: help 20//config: basename is used to strip the directory and suffix from filenames, 21//config: leaving just the filename itself. Enable this option if you wish 22//config: to enable the 'basename' utility. 23 24//applet:IF_BASENAME(APPLET_NOFORK(basename, basename, BB_DIR_USR_BIN, BB_SUID_DROP, basename)) 25 26//kbuild:lib-$(CONFIG_BASENAME) += basename.o 27 28/* BB_AUDIT SUSv3 compliant */ 29/* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */ 30 31//usage:#define basename_trivial_usage 32//usage: "FILE [SUFFIX] | -a FILE... | -s SUFFIX FILE..." 33//usage:#define basename_full_usage "\n\n" 34//usage: "Strip directory path and SUFFIX from FILE\n" 35//usage: "\n -a All arguments are FILEs" 36//usage: "\n -s SUFFIX Remove SUFFIX (implies -a)" 37//usage: 38//usage:#define basename_example_usage 39//usage: "$ basename /usr/local/bin/foo\n" 40//usage: "foo\n" 41//usage: "$ basename /usr/local/bin/\n" 42//usage: "bin\n" 43//usage: "$ basename /foo/bar.txt .txt\n" 44//usage: "bar" 45 46#include "libbb.h" 47 48/* This is a NOFORK applet. Be very careful! */ 49 50int basename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 51int basename_main(int argc UNUSED_PARAM, char **argv) 52{ 53 unsigned opts; 54 const char *suffix = NULL; 55 56 /* '+': stop at first non-option */ 57 opts = getopt32(argv, "^+" "as:" 58 "\0" "-1" /* At least one argument */ 59 , &suffix 60 ); 61 argv += optind; 62 63 do { 64 char *s; 65 size_t m; 66 67 /* It should strip slash: /abc/def/ -> def */ 68 s = bb_get_last_path_component_strip(*argv++); 69 m = strlen(s); 70 if (!opts) { 71 if (*argv) { 72 suffix = *argv; 73 if (argv[1]) 74 bb_show_usage(); 75 } 76 } 77 if (suffix) { 78 size_t n = strlen(suffix); 79 if ((m > n) && (strcmp(s + m - n, suffix) == 0)) { 80 m -= n; 81 /*s[m] = '\0'; - redundant */ 82 } 83 } 84 /* puts(s) will do, but we can do without stdio this way: */ 85 s[m++] = '\n'; 86 /* NB: != is correct here: */ 87 if (full_write(STDOUT_FILENO, s, m) != (ssize_t)m) 88 return EXIT_FAILURE; 89 } while (opts && *argv); 90 91 return EXIT_SUCCESS; 92} 93