~ubuntu-branches/ubuntu/utopic/coreutils/utopic-proposed

« back to all changes in this revision

Viewing changes to src/basename.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-11-28 03:03:42 UTC
  • mfrom: (8.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20121128030342-21zanj8354gas5gr
Tags: 8.20-3ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Make 'uname -i -p' return the real processor/hardware, instead of
    unknown.
  - Build-depend on gettext:any instead of on gettext, so that apt-get can
    properly resolve build-dependencies on the tool when cross-building.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* basename -- strip directory and suffix from file names
2
 
   Copyright (C) 1990-1997, 1999-2011 Free Software Foundation, Inc.
 
2
   Copyright (C) 1990-2012 Free Software Foundation, Inc.
3
3
 
4
4
   This program is free software: you can redistribute it and/or modify
5
5
   it under the terms of the GNU General Public License as published by
14
14
   You should have received a copy of the GNU General Public License
15
15
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
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
17
#include <config.h>
28
18
#include <getopt.h>
29
19
#include <stdio.h>
30
20
#include <sys/types.h>
31
21
 
32
22
#include "system.h"
33
 
#include "long-options.h"
34
23
#include "error.h"
35
24
#include "quote.h"
36
25
 
37
 
/* The official name of this program (e.g., no `g' prefix).  */
 
26
/* The official name of this program (e.g., no 'g' prefix).  */
38
27
#define PROGRAM_NAME "basename"
39
28
 
40
29
#define AUTHORS proper_name ("David MacKenzie")
41
30
 
 
31
static struct option const longopts[] =
 
32
{
 
33
  {"multiple", no_argument, NULL, 'a'},
 
34
  {"suffix", required_argument, NULL, 's'},
 
35
  {"zero", no_argument, NULL, 'z'},
 
36
  {GETOPT_HELP_OPTION_DECL},
 
37
  {GETOPT_VERSION_OPTION_DECL},
 
38
  {NULL, 0, NULL, 0}
 
39
};
 
40
 
42
41
void
43
42
usage (int status)
44
43
{
45
44
  if (status != EXIT_SUCCESS)
46
 
    fprintf (stderr, _("Try `%s --help' for more information.\n"),
47
 
             program_name);
 
45
    emit_try_help ();
48
46
  else
49
47
    {
50
48
      printf (_("\
51
49
Usage: %s NAME [SUFFIX]\n\
52
 
  or:  %s OPTION\n\
 
50
  or:  %s OPTION... NAME...\n\
53
51
"),
54
52
              program_name, program_name);
55
53
      fputs (_("\
57
55
If specified, also remove a trailing SUFFIX.\n\
58
56
\n\
59
57
"), stdout);
 
58
 
 
59
      fputs (_("\
 
60
  -a, --multiple       support multiple arguments and treat each as a NAME\n\
 
61
  -s, --suffix=SUFFIX  remove a trailing SUFFIX\n\
 
62
  -z, --zero           separate output with NUL rather than newline\n\
 
63
"), stdout);
60
64
      fputs (HELP_OPTION_DESCRIPTION, stdout);
61
65
      fputs (VERSION_OPTION_DESCRIPTION, stdout);
62
66
      printf (_("\
63
67
\n\
64
68
Examples:\n\
65
 
  %s /usr/bin/sort       Output \"sort\".\n\
66
 
  %s include/stdio.h .h  Output \"stdio\".\n\
 
69
  %s /usr/bin/sort          -> \"sort\"\n\
 
70
  %s include/stdio.h .h     -> \"stdio\"\n\
 
71
  %s -s .h include/stdio.h  -> \"stdio\"\n\
 
72
  %s -a any/str1 any/str2   -> \"str1\" followed by \"str2\"\n\
67
73
"),
68
 
              program_name, program_name);
 
74
              program_name, program_name, program_name, program_name);
69
75
      emit_ancillary_info ();
70
76
    }
71
77
  exit (status);
72
78
}
73
79
 
74
80
/* Remove SUFFIX from the end of NAME if it is there, unless NAME
75
 
   consists entirely of SUFFIX. */
 
81
   consists entirely of SUFFIX.  */
76
82
 
77
83
static void
78
84
remove_suffix (char *name, const char *suffix)
90
96
    *np = '\0';
91
97
}
92
98
 
 
99
/* Perform the basename operation on STRING.  If SUFFIX is non-NULL, remove
 
100
   the trailing SUFFIX.  Finally, output the result string.  */
 
101
 
 
102
static void
 
103
perform_basename (const char *string, const char *suffix, bool use_nuls)
 
104
{
 
105
  char *name = base_name (string);
 
106
  strip_trailing_slashes (name);
 
107
 
 
108
  /* Per POSIX, 'basename // /' must return '//' on platforms with
 
109
     distinct //.  On platforms with drive letters, this generalizes
 
110
     to making 'basename c: :' return 'c:'.  This rule is captured by
 
111
     skipping suffix stripping if base_name returned an absolute path
 
112
     or a drive letter (only possible if name is a file-system
 
113
     root).  */
 
114
  if (suffix && IS_RELATIVE_FILE_NAME (name) && ! FILE_SYSTEM_PREFIX_LEN (name))
 
115
    remove_suffix (name, suffix);
 
116
 
 
117
  fputs (name, stdout);
 
118
  putchar (use_nuls ? '\0' : '\n');
 
119
  free (name);
 
120
}
 
121
 
93
122
int
94
123
main (int argc, char **argv)
95
124
{
96
 
  char *name;
 
125
  bool multiple_names = false;
 
126
  bool use_nuls = false;
 
127
  const char *suffix = NULL;
97
128
 
98
129
  initialize_main (&argc, &argv);
99
130
  set_program_name (argv[0]);
103
134
 
104
135
  atexit (close_stdout);
105
136
 
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);
 
137
  while (true)
 
138
    {
 
139
      int c = getopt_long (argc, argv, "+as:z", longopts, NULL);
 
140
 
 
141
      if (c == -1)
 
142
        break;
 
143
 
 
144
      switch (c)
 
145
        {
 
146
        case 's':
 
147
          suffix = optarg;
 
148
 
 
149
        case 'a':
 
150
          multiple_names = true;
 
151
          break;
 
152
 
 
153
        case 'z':
 
154
          use_nuls = true;
 
155
          break;
 
156
 
 
157
        case_GETOPT_HELP_CHAR;
 
158
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
 
159
 
 
160
        default:
 
161
          usage (EXIT_FAILURE);
 
162
        }
 
163
    }
110
164
 
111
165
  if (argc < optind + 1)
112
166
    {
114
168
      usage (EXIT_FAILURE);
115
169
    }
116
170
 
117
 
  if (optind + 2 < argc)
 
171
  if (!multiple_names && optind + 2 < argc)
118
172
    {
119
173
      error (0, 0, _("extra operand %s"), quote (argv[optind + 2]));
120
174
      usage (EXIT_FAILURE);
121
175
    }
122
176
 
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);
 
177
  if (multiple_names)
 
178
    {
 
179
      for (; optind < argc; optind++)
 
180
        perform_basename (argv[optind], suffix, use_nuls);
 
181
    }
 
182
  else
 
183
    perform_basename (argv[optind],
 
184
                      optind + 2 == argc ? argv[optind + 1] : NULL, use_nuls);
138
185
 
139
186
  exit (EXIT_SUCCESS);
140
187
}