Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcmd/basename.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* David Korn
24
* AT&T Bell Laboratories
25
*
26
* namebase pathname [suffix]
27
*
28
* print the namebase of a pathname
29
*/
30
31
static const char usage[] =
32
"[-?\n@(#)$Id: basename (AT&T Research) 2010-05-06 $\n]"
33
USAGE_LICENSE
34
"[+NAME?basename - strip directory and suffix from filenames]"
35
"[+DESCRIPTION?\bbasename\b removes all leading directory components "
36
"from the file name defined by \astring\a. If the file name defined by "
37
"\astring\a has a suffix that ends in \asuffix\a, it is removed as "
38
"well.]"
39
"[+?If \astring\a consists solely of \b/\b characters the output will be "
40
"a single \b/\b unless \bPATH_LEADING_SLASHES\b returned by "
41
"\bgetconf\b(1) is \b1\b and \astring\a consists of multiple \b/\b "
42
"characters in which case \b//\b will be output. Otherwise, trailing "
43
"\b/\b characters are removed, and if there are any remaining \b/\b "
44
"characters in \astring\a, all characters up to and including the last "
45
"\b/\b are removed. Finally, if \asuffix\a is specified, and is "
46
"identical the end of \astring\a, these characters are removed. The "
47
"characters not removed from \astring\a will be written on a single line "
48
"to the standard output.]"
49
"[a:all?All operands are treated as \astring\a and each modified "
50
"pathname is printed on a separate line on the standard output.]"
51
"[s:suffix?All operands are treated as \astring\a and each modified "
52
"pathname, with \asuffix\a removed if it exists, is printed on a "
53
"separate line on the standard output.]:[suffix]"
54
"\n"
55
"\n string [suffix]\n"
56
"string ...\n"
57
"\n"
58
"[+EXIT STATUS?]"
59
"{"
60
"[+0?Successful Completion.]"
61
"[+>0?An error occurred.]"
62
"}"
63
"[+SEE ALSO?\bdirname\b(1), \bgetconf\b(1), \bbasename\b(3)]"
64
;
65
66
67
#include <cmd.h>
68
69
static void namebase(Sfio_t *outfile, register char *pathname, char *suffix)
70
{
71
register char *first, *last;
72
register int n=0;
73
for(first=last=pathname; *last; last++);
74
/* back over trailing '/' */
75
if(last>first)
76
while(*--last=='/' && last > first);
77
if(last==first && *last=='/')
78
{
79
/* all '/' or "" */
80
if(*first=='/')
81
if(*++last=='/') /* keep leading // */
82
last++;
83
}
84
else
85
{
86
for(first=last++;first>pathname && *first!='/';first--);
87
if(*first=='/')
88
first++;
89
/* check for trailing suffix */
90
if(suffix && (n=strlen(suffix)) && n<(last-first))
91
{
92
if(memcmp(last-n,suffix,n)==0)
93
last -=n;
94
}
95
}
96
if(last>first)
97
sfwrite(outfile,first,last-first);
98
sfputc(outfile,'\n');
99
}
100
101
int
102
b_basename(int argc, register char** argv, Shbltin_t* context)
103
{
104
char* string;
105
char* suffix = 0;
106
int all = 0;
107
108
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
109
for (;;)
110
{
111
switch (optget(argv, usage))
112
{
113
case 'a':
114
all = 1;
115
continue;
116
case 's':
117
all = 1;
118
suffix = opt_info.arg;
119
continue;
120
case ':':
121
error(2, "%s", opt_info.arg);
122
break;
123
case '?':
124
error(ERROR_usage(2), "%s", opt_info.arg);
125
break;
126
}
127
break;
128
}
129
argv += opt_info.index;
130
argc -= opt_info.index;
131
if (error_info.errors || argc < 1 || !all && argc > 2)
132
error(ERROR_usage(2), "%s", optusage(NiL));
133
if (!all)
134
namebase(sfstdout, argv[0], argv[1]);
135
else
136
while (string = *argv++)
137
namebase(sfstdout, string, suffix);
138
return 0;
139
}
140
141