69b708fe76487485dc04bcb8087a6fcdf65e629b
[platform/upstream/coreutils.git] / src / basename.c
1 /* basename -- strip directory and suffix from file names
2    Copyright (C) 1990-1997, 1999-2008 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Usage: basename name [suffix]
18    NAME is a file name; SUFFIX is a suffix to strip from it.
19
20    basename /usr/foo/lossage/functions.l
21    => functions.l
22    basename /usr/foo/lossage/functions.l .l
23    => functions
24    basename functions.lisp p
25    => functions.lis */
26
27 #include <config.h>
28 #include <getopt.h>
29 #include <stdio.h>
30 #include <sys/types.h>
31
32 #include "system.h"
33 #include "long-options.h"
34 #include "error.h"
35 #include "quote.h"
36
37 /* The official name of this program (e.g., no `g' prefix).  */
38 #define PROGRAM_NAME "basename"
39
40 #define AUTHORS proper_name ("David MacKenzie")
41
42 void
43 usage (int status)
44 {
45   if (status != EXIT_SUCCESS)
46     fprintf (stderr, _("Try `%s --help' for more information.\n"),
47              program_name);
48   else
49     {
50       printf (_("\
51 Usage: %s NAME [SUFFIX]\n\
52   or:  %s OPTION\n\
53 "),
54               program_name, program_name);
55       fputs (_("\
56 Print NAME with any leading directory components removed.\n\
57 If specified, also remove a trailing SUFFIX.\n\
58 \n\
59 "), stdout);
60       fputs (HELP_OPTION_DESCRIPTION, stdout);
61       fputs (VERSION_OPTION_DESCRIPTION, stdout);
62       printf (_("\
63 \n\
64 Examples:\n\
65   %s /usr/bin/sort       Output \"sort\".\n\
66   %s include/stdio.h .h  Output \"stdio\".\n\
67 "),
68               program_name, program_name);
69       emit_bug_reporting_address ();
70     }
71   exit (status);
72 }
73
74 /* Remove SUFFIX from the end of NAME if it is there, unless NAME
75    consists entirely of SUFFIX. */
76
77 static void
78 remove_suffix (char *name, const char *suffix)
79 {
80   char *np;
81   const char *sp;
82
83   np = name + strlen (name);
84   sp = suffix + strlen (suffix);
85
86   while (np > name && sp > suffix)
87     if (*--np != *--sp)
88       return;
89   if (np > name)
90     *np = '\0';
91 }
92
93 int
94 main (int argc, char **argv)
95 {
96   char *name;
97
98   initialize_main (&argc, &argv);
99   set_program_name (argv[0]);
100   setlocale (LC_ALL, "");
101   bindtextdomain (PACKAGE, LOCALEDIR);
102   textdomain (PACKAGE);
103
104   atexit (close_stdout);
105
106   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION,
107                       usage, AUTHORS, (char const *) NULL);
108   if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
109     usage (EXIT_FAILURE);
110
111   if (argc < optind + 1)
112     {
113       error (0, 0, _("missing operand"));
114       usage (EXIT_FAILURE);
115     }
116
117   if (optind + 2 < argc)
118     {
119       error (0, 0, _("extra operand %s"), quote (argv[optind + 2]));
120       usage (EXIT_FAILURE);
121     }
122
123   name = base_name (argv[optind]);
124   strip_trailing_slashes (name);
125
126   /* Per POSIX, `basename // /' must return `//' on platforms with
127      distinct //.  On platforms with drive letters, this generalizes
128      to making `basename c: :' return `c:'.  This rule is captured by
129      skipping suffix stripping if base_name returned an absolute path
130      or a drive letter (only possible if name is a file-system
131      root).  */
132   if (argc == optind + 2 && IS_RELATIVE_FILE_NAME (name)
133       && ! FILE_SYSTEM_PREFIX_LEN (name))
134     remove_suffix (name, argv[optind + 1]);
135
136   puts (name);
137   free (name);
138
139   exit (EXIT_SUCCESS);
140 }