xref: /illumos-gate/usr/src/cmd/basename/basename.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*55381082Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <locale.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
31*55381082Smuffin #ifndef	XPG4
32*55381082Smuffin #include <unistd.h>
33*55381082Smuffin #include <regex.h>
34*55381082Smuffin #include <libintl.h>
35*55381082Smuffin #endif
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)387c478bd9Sstevel@tonic-gate main(int argc, char **argv)
397c478bd9Sstevel@tonic-gate {
407c478bd9Sstevel@tonic-gate 	char	*p;
417c478bd9Sstevel@tonic-gate 	char	*string;
427c478bd9Sstevel@tonic-gate 	char	*suffix;
43*55381082Smuffin #ifndef	XPG4
44*55381082Smuffin 	int	r;
45*55381082Smuffin 	char	suf_buf[256];
46*55381082Smuffin 	char	*suf_pat;
47*55381082Smuffin 	size_t	suf_len;
48*55381082Smuffin 	regex_t	reg;
49*55381082Smuffin 	regmatch_t	pmatch[2];
50*55381082Smuffin #endif
517c478bd9Sstevel@tonic-gate 
52*55381082Smuffin 	/*
53*55381082Smuffin 	 * For better performance, defer the setlocale()/textdomain()
54*55381082Smuffin 	 * calls until they get really required.
55*55381082Smuffin 	 */
567c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
577c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
587c478bd9Sstevel@tonic-gate #endif
59*55381082Smuffin 	if (argc == 1) {
60*55381082Smuffin 		(void) puts(".");
61*55381082Smuffin 		return (0);
62*55381082Smuffin 	}
637c478bd9Sstevel@tonic-gate 
64*55381082Smuffin #ifdef	XPG4
657c478bd9Sstevel@tonic-gate 	if (strcmp(argv[1], "--") == 0) {
667c478bd9Sstevel@tonic-gate 		argv++;
677c478bd9Sstevel@tonic-gate 		argc--;
68*55381082Smuffin 		if (argc == 1) {
69*55381082Smuffin 			(void) puts(".");
70*55381082Smuffin 			return (0);
71*55381082Smuffin 		}
72*55381082Smuffin 	}
73*55381082Smuffin #endif
74*55381082Smuffin 	if (argc > 3) {
75*55381082Smuffin 		(void) setlocale(LC_ALL, "");
76*55381082Smuffin 		(void) textdomain(TEXT_DOMAIN);
77*55381082Smuffin 		(void) fputs(gettext("Usage: basename string [ suffix ]\n"),
78*55381082Smuffin 		    stderr);
79*55381082Smuffin 		return (1);
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	string = argv[1];
837c478bd9Sstevel@tonic-gate 	suffix = (argc == 2) ? NULL : argv[2];
847c478bd9Sstevel@tonic-gate 
85*55381082Smuffin 	if (*string == '\0') {
86*55381082Smuffin 		(void) puts(".");
87*55381082Smuffin 		return (0);
88*55381082Smuffin 	}
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	/* remove trailing slashes */
91*55381082Smuffin 	p = string + strlen(string) - 1;
92*55381082Smuffin 	while (p >= string && *p == '/')
937c478bd9Sstevel@tonic-gate 		*p-- = '\0';
947c478bd9Sstevel@tonic-gate 
95*55381082Smuffin 	if (*string == '\0') {
96*55381082Smuffin 		(void) puts("/");
97*55381082Smuffin 		return (0);
98*55381082Smuffin 	}
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	/* skip to one past last slash */
1017c478bd9Sstevel@tonic-gate 	if ((p = strrchr(string, '/')) != NULL)
1027c478bd9Sstevel@tonic-gate 		string = p + 1;
1037c478bd9Sstevel@tonic-gate 
104*55381082Smuffin 	if (suffix == NULL) {
105*55381082Smuffin 		(void) puts(string);
106*55381082Smuffin 		return (0);
107*55381082Smuffin 	}
108*55381082Smuffin 
109*55381082Smuffin #ifdef	XPG4
1107c478bd9Sstevel@tonic-gate 	/*
1117c478bd9Sstevel@tonic-gate 	 * if a suffix is present and is not the same as the remaining
1127c478bd9Sstevel@tonic-gate 	 * string and is identical to the last characters in the remaining
1137c478bd9Sstevel@tonic-gate 	 * string, remove those characters from the string.
1147c478bd9Sstevel@tonic-gate 	 */
115*55381082Smuffin 	if (strcmp(string, suffix) != 0) {
116*55381082Smuffin 		p = string + strlen(string) - strlen(suffix);
117*55381082Smuffin 		if (strcmp(p, suffix) == 0)
118*55381082Smuffin 			*p = '\0';
119*55381082Smuffin 	}
120*55381082Smuffin 	(void) puts(string);
1217c478bd9Sstevel@tonic-gate 	return (0);
122*55381082Smuffin #else
123*55381082Smuffin 	(void) setlocale(LC_ALL, "");
124*55381082Smuffin 	(void) textdomain(TEXT_DOMAIN);
1257c478bd9Sstevel@tonic-gate 
126*55381082Smuffin 	suf_len = 6 + strlen(suffix) + 1 + 1; /* \(.*\)suffix$ */
127*55381082Smuffin 	if (suf_len > sizeof (suf_buf)) {
128*55381082Smuffin 		suf_pat = malloc(suf_len);
129*55381082Smuffin 		if (suf_pat == NULL) {
130*55381082Smuffin 			(void) fputs("malloc failed\n", stderr);
131*55381082Smuffin 			return (1);
132*55381082Smuffin 		}
133*55381082Smuffin 	} else {
134*55381082Smuffin 		suf_pat = suf_buf;
135*55381082Smuffin 	}
136*55381082Smuffin 	(void) strcpy(suf_pat, "\\(.*\\)");
137*55381082Smuffin 	(void) strcpy(suf_pat + 6, suffix);
138*55381082Smuffin 	*(suf_pat + suf_len - 1 - 1) = '$';
139*55381082Smuffin 	*(suf_pat + suf_len - 1) = '\0';
140*55381082Smuffin 
141*55381082Smuffin 	r = regcomp(&reg, suf_pat, 0);
142*55381082Smuffin 	if (r != 0) {
143*55381082Smuffin 		(void) fprintf(stderr,
144*55381082Smuffin 		    "Internal error: regcomp failed for \"%s\"\n",
145*55381082Smuffin 		    suf_pat);
146*55381082Smuffin 		return (1);
147*55381082Smuffin 	}
148*55381082Smuffin 	r = regexec(&reg, string, 2, pmatch, 0);
149*55381082Smuffin 	if (r == 0) {
150*55381082Smuffin 		if (pmatch[0].rm_so == (regoff_t)-1 ||
151*55381082Smuffin 		    pmatch[1].rm_so == (regoff_t)-1 ||
152*55381082Smuffin 		    pmatch[1].rm_so != 0) {
153*55381082Smuffin 			(void) fprintf(stderr, "Internal error: regexec did "
154*55381082Smuffin 			    "not set sub-expression for:\n");
155*55381082Smuffin 			(void) fprintf(stderr, "path: \"%s\"\n", string);
156*55381082Smuffin 			(void) fprintf(stderr, "pattern: \"%s\"", suf_pat);
157*55381082Smuffin 			return (1);
158*55381082Smuffin 		}
159*55381082Smuffin 		if (pmatch[1].rm_so == pmatch[1].rm_eo) {
160*55381082Smuffin 			/* a null string matched */
161*55381082Smuffin 			(void) printf("%s\n", string);
162*55381082Smuffin 			return (0);
163*55381082Smuffin 		}
164*55381082Smuffin 		string[pmatch[1].rm_eo] = '\0';
165*55381082Smuffin 	}
166*55381082Smuffin 	(void) puts(string);
167*55381082Smuffin 	return (0);
168*55381082Smuffin #endif
1697c478bd9Sstevel@tonic-gate }
170