Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / examples / loadables / basename.c
1 /* basename - return nondirectory portion of pathname */
2
3 /* See Makefile for compilation details. */
4
5 /*
6    Copyright (C) 1999-2009 Free Software Foundation, Inc.
7
8    This file is part of GNU Bash.
9    Bash is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13
14    Bash is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "config.h"
24
25 #if defined (HAVE_UNISTD_H)
26 #  include <unistd.h>
27 #endif
28
29 #include <stdio.h>
30 #include "builtins.h"
31 #include "shell.h"
32 #include "common.h"
33
34 basename_builtin (list)
35      WORD_LIST *list;
36 {
37   int slen, sufflen, off;
38   char *string, *suffix, *fn;
39
40   if (list == 0)
41     {
42       builtin_usage ();
43       return (EX_USAGE);
44     }
45
46   if (no_options (list))
47     return (EX_USAGE);
48
49   string = list->word->word;
50   suffix = (char *)NULL;
51   if (list->next)
52     {
53       list = list->next;
54       suffix = list->word->word;
55     }
56
57   if (list->next)
58     {
59       builtin_usage ();
60       return (EX_USAGE);
61     }
62
63   slen = strlen (string);
64
65   /* Strip trailing slashes */
66   while (slen > 0 && string[slen - 1] == '/')
67     slen--;
68
69   /* (2) If string consists entirely of slash characters, string shall be
70          set to a single slash character.  In this case, skip steps (3)
71          through (5). */
72   if (slen == 0)
73     {
74       fputs ("/\n", stdout);
75       return (EXECUTION_SUCCESS);
76     }
77
78   /* (3) If there are any trailing slash characters in string, they
79          shall be removed. */
80   string[slen] = '\0';
81
82   /* (4) If there are any slash characters remaining in string, the prefix
83          of string up to an including the last slash character in string
84          shall be removed. */
85   while (--slen >= 0)
86     if (string[slen] == '/')
87       break;
88
89   fn = string + slen + 1;
90
91   /* (5) If the suffix operand is present, is not identical to the
92          characters remaining in string, and is identical to a suffix
93          of the characters remaining in string, the suffix suffix
94          shall be removed from string.  Otherwise, string shall not be
95          modified by this step. */
96   if (suffix)
97     {
98       sufflen = strlen (suffix);
99       slen = strlen (fn);
100       if (sufflen < slen)
101         {
102           off = slen - sufflen;
103           if (strcmp (fn + off, suffix) == 0)
104             fn[off] = '\0';
105         }
106     }
107   printf ("%s\n", fn);
108   return (EXECUTION_SUCCESS);
109 }
110
111 char *basename_doc[] = {
112         "Return non-directory portion of pathname.",
113         "",
114         "The STRING is converted to a filename corresponding to the last",
115         "pathname component in STRING.  If the suffix string SUFFIX is",
116         "supplied, it is removed.",
117         (char *)NULL
118 };
119
120 /* The standard structure describing a builtin command.  bash keeps an array
121    of these structures. */
122 struct builtin basename_struct = {
123         "basename",             /* builtin name */
124         basename_builtin,       /* function implementing the builtin */
125         BUILTIN_ENABLED,        /* initial flags for builtin */
126         basename_doc,           /* array of long documentation strings. */
127         "basename string [suffix]",     /* usage synopsis */
128         0                       /* reserved for internal use */
129 };