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
39int
40main(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(&reg, 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(&reg, 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