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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <locale.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #ifndef XPG4
34 #include <unistd.h>
35 #include <regex.h>
36 #include <libintl.h>
37 #endif
38
39 int
main(int argc,char ** argv)40 main(int argc, char **argv)
41 {
42 char *p;
43 char *string;
44 char *suffix;
45 #ifndef XPG4
46 int r;
47 char suf_buf[256];
48 char *suf_pat;
49 size_t suf_len;
50 regex_t reg;
51 regmatch_t pmatch[2];
52 #endif
53
54 /*
55 * For better performance, defer the setlocale()/textdomain()
56 * calls until they get really required.
57 */
58 #if !defined(TEXT_DOMAIN)
59 #define TEXT_DOMAIN "SYS_TEST"
60 #endif
61 if (argc == 1) {
62 (void) puts(".");
63 return (0);
64 }
65
66 #ifdef XPG4
67 if (strcmp(argv[1], "--") == 0) {
68 argv++;
69 argc--;
70 if (argc == 1) {
71 (void) puts(".");
72 return (0);
73 }
74 }
75 #endif
76 if (argc > 3) {
77 (void) setlocale(LC_ALL, "");
78 (void) textdomain(TEXT_DOMAIN);
79 (void) fputs(gettext("Usage: basename string [ suffix ]\n"),
80 stderr);
81 return (1);
82 }
83
84 string = argv[1];
85 suffix = (argc == 2) ? NULL : argv[2];
86
87 if (*string == '\0') {
88 (void) puts(".");
89 return (0);
90 }
91
92 /* remove trailing slashes */
93 p = string + strlen(string) - 1;
94 while (p >= string && *p == '/')
95 *p-- = '\0';
96
97 if (*string == '\0') {
98 (void) puts("/");
99 return (0);
100 }
101
102 /* skip to one past last slash */
103 if ((p = strrchr(string, '/')) != NULL)
104 string = p + 1;
105
106 if (suffix == NULL) {
107 (void) puts(string);
108 return (0);
109 }
110
111 #ifdef XPG4
112 /*
113 * if a suffix is present and is not the same as the remaining
114 * string and is identical to the last characters in the remaining
115 * string, remove those characters from the string.
116 */
117 if (strcmp(string, suffix) != 0) {
118 p = string + strlen(string) - strlen(suffix);
119 if (strcmp(p, suffix) == 0)
120 *p = '\0';
121 }
122 (void) puts(string);
123 return (0);
124 #else
125 (void) setlocale(LC_ALL, "");
126 (void) textdomain(TEXT_DOMAIN);
127
128 suf_len = 6 + strlen(suffix) + 1 + 1; /* \(.*\)suffix$ */
129 if (suf_len > sizeof (suf_buf)) {
130 suf_pat = malloc(suf_len);
131 if (suf_pat == NULL) {
132 (void) fputs("malloc failed\n", stderr);
133 return (1);
134 }
135 } else {
136 suf_pat = suf_buf;
137 }
138 (void) strcpy(suf_pat, "\\(.*\\)");
139 (void) strcpy(suf_pat + 6, suffix);
140 *(suf_pat + suf_len - 1 - 1) = '$';
141 *(suf_pat + suf_len - 1) = '\0';
142
143 r = regcomp(®, suf_pat, 0);
144 if (r != 0) {
145 (void) fprintf(stderr,
146 "Internal error: regcomp failed for \"%s\"\n",
147 suf_pat);
148 return (1);
149 }
150 r = regexec(®, string, 2, pmatch, 0);
151 if (r == 0) {
152 if (pmatch[0].rm_so == (regoff_t)-1 ||
153 pmatch[1].rm_so == (regoff_t)-1 ||
154 pmatch[1].rm_so != 0) {
155 (void) fprintf(stderr, "Internal error: regexec did "
156 "not set sub-expression for:\n");
157 (void) fprintf(stderr, "path: \"%s\"\n", string);
158 (void) fprintf(stderr, "pattern: \"%s\"", suf_pat);
159 return (1);
160 }
161 if (pmatch[1].rm_so == pmatch[1].rm_eo) {
162 /* a null string matched */
163 (void) printf("%s\n", string);
164 return (0);
165 }
166 string[pmatch[1].rm_eo] = '\0';
167 }
168 (void) puts(string);
169 return (0);
170 #endif
171 }
172