1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <locale.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #ifndef XPG4
32 #include <unistd.h>
33 #include <regex.h>
34 #include <libintl.h>
35 #endif
36
37 int
main(int argc,char ** argv)38 main(int argc, char **argv)
39 {
40 char *p;
41 char *string;
42 char *suffix;
43 #ifndef XPG4
44 int r;
45 char suf_buf[256];
46 char *suf_pat;
47 size_t suf_len;
48 regex_t reg;
49 regmatch_t pmatch[2];
50 #endif
51
52 /*
53 * For better performance, defer the setlocale()/textdomain()
54 * calls until they get really required.
55 */
56 #if !defined(TEXT_DOMAIN)
57 #define TEXT_DOMAIN "SYS_TEST"
58 #endif
59 if (argc == 1) {
60 (void) puts(".");
61 return (0);
62 }
63
64 #ifdef XPG4
65 if (strcmp(argv[1], "--") == 0) {
66 argv++;
67 argc--;
68 if (argc == 1) {
69 (void) puts(".");
70 return (0);
71 }
72 }
73 #endif
74 if (argc > 3) {
75 (void) setlocale(LC_ALL, "");
76 (void) textdomain(TEXT_DOMAIN);
77 (void) fputs(gettext("Usage: basename string [ suffix ]\n"),
78 stderr);
79 return (1);
80 }
81
82 string = argv[1];
83 suffix = (argc == 2) ? NULL : argv[2];
84
85 if (*string == '\0') {
86 (void) puts(".");
87 return (0);
88 }
89
90 /* remove trailing slashes */
91 p = string + strlen(string) - 1;
92 while (p >= string && *p == '/')
93 *p-- = '\0';
94
95 if (*string == '\0') {
96 (void) puts("/");
97 return (0);
98 }
99
100 /* skip to one past last slash */
101 if ((p = strrchr(string, '/')) != NULL)
102 string = p + 1;
103
104 if (suffix == NULL) {
105 (void) puts(string);
106 return (0);
107 }
108
109 #ifdef XPG4
110 /*
111 * if a suffix is present and is not the same as the remaining
112 * string and is identical to the last characters in the remaining
113 * string, remove those characters from the string.
114 */
115 if (strcmp(string, suffix) != 0) {
116 p = string + strlen(string) - strlen(suffix);
117 if (strcmp(p, suffix) == 0)
118 *p = '\0';
119 }
120 (void) puts(string);
121 return (0);
122 #else
123 (void) setlocale(LC_ALL, "");
124 (void) textdomain(TEXT_DOMAIN);
125
126 suf_len = 6 + strlen(suffix) + 1 + 1; /* \(.*\)suffix$ */
127 if (suf_len > sizeof (suf_buf)) {
128 suf_pat = malloc(suf_len);
129 if (suf_pat == NULL) {
130 (void) fputs("malloc failed\n", stderr);
131 return (1);
132 }
133 } else {
134 suf_pat = suf_buf;
135 }
136 (void) strcpy(suf_pat, "\\(.*\\)");
137 (void) strcpy(suf_pat + 6, suffix);
138 *(suf_pat + suf_len - 1 - 1) = '$';
139 *(suf_pat + suf_len - 1) = '\0';
140
141 r = regcomp(®, suf_pat, 0);
142 if (r != 0) {
143 (void) fprintf(stderr,
144 "Internal error: regcomp failed for \"%s\"\n",
145 suf_pat);
146 return (1);
147 }
148 r = regexec(®, string, 2, pmatch, 0);
149 if (r == 0) {
150 if (pmatch[0].rm_so == (regoff_t)-1 ||
151 pmatch[1].rm_so == (regoff_t)-1 ||
152 pmatch[1].rm_so != 0) {
153 (void) fprintf(stderr, "Internal error: regexec did "
154 "not set sub-expression for:\n");
155 (void) fprintf(stderr, "path: \"%s\"\n", string);
156 (void) fprintf(stderr, "pattern: \"%s\"", suf_pat);
157 return (1);
158 }
159 if (pmatch[1].rm_so == pmatch[1].rm_eo) {
160 /* a null string matched */
161 (void) printf("%s\n", string);
162 return (0);
163 }
164 string[pmatch[1].rm_eo] = '\0';
165 }
166 (void) puts(string);
167 return (0);
168 #endif
169 }
170