blob: ace0148c034ab4646871d32c807032f676402817
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 | |
10 | /* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) |
11 | * |
12 | * Changes: |
13 | * 1) Now checks for too many args. Need at least one and at most two. |
14 | * 2) Don't check for options, as per SUSv3. |
15 | * 3) Save some space by using strcmp(). Calling strncmp() here was silly. |
16 | */ |
17 | //config:config BASENAME |
18 | //config: bool "basename" |
19 | //config: default y |
20 | //config: help |
21 | //config: basename is used to strip the directory and suffix from filenames, |
22 | //config: leaving just the filename itself. Enable this option if you wish |
23 | //config: to enable the 'basename' utility. |
24 | |
25 | //applet:IF_BASENAME(APPLET_NOFORK(basename, basename, BB_DIR_USR_BIN, BB_SUID_DROP, basename)) |
26 | |
27 | //kbuild:lib-$(CONFIG_BASENAME) += basename.o |
28 | |
29 | /* BB_AUDIT SUSv3 compliant */ |
30 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/basename.html */ |
31 | |
32 | //usage:#define basename_trivial_usage |
33 | //usage: "FILE [SUFFIX]" |
34 | //usage:#define basename_full_usage "\n\n" |
35 | //usage: "Strip directory path and .SUFFIX from FILE" |
36 | //usage: |
37 | //usage:#define basename_example_usage |
38 | //usage: "$ basename /usr/local/bin/foo\n" |
39 | //usage: "foo\n" |
40 | //usage: "$ basename /usr/local/bin/\n" |
41 | //usage: "bin\n" |
42 | //usage: "$ basename /foo/bar.txt .txt\n" |
43 | //usage: "bar" |
44 | |
45 | #include "libbb.h" |
46 | |
47 | /* This is a NOFORK applet. Be very careful! */ |
48 | |
49 | int basename_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
50 | int basename_main(int argc, char **argv) |
51 | { |
52 | size_t m, n; |
53 | char *s; |
54 | |
55 | if (argv[1] && strcmp(argv[1], "--") == 0) { |
56 | argv++; |
57 | argc--; |
58 | } |
59 | |
60 | if ((unsigned)(argc-2) >= 2) { |
61 | bb_show_usage(); |
62 | } |
63 | |
64 | /* It should strip slash: /abc/def/ -> def */ |
65 | s = bb_get_last_path_component_strip(*++argv); |
66 | |
67 | m = strlen(s); |
68 | if (*++argv) { |
69 | n = strlen(*argv); |
70 | if ((m > n) && (strcmp(s+m-n, *argv) == 0)) { |
71 | m -= n; |
72 | /*s[m] = '\0'; - redundant */ |
73 | } |
74 | } |
75 | |
76 | /* puts(s) will do, but we can do without stdio this way: */ |
77 | s[m++] = '\n'; |
78 | /* NB: != is correct here: */ |
79 | return full_write(STDOUT_FILENO, s, m) != (ssize_t)m; |
80 | } |
81 |