Home | History | Annotate | Download | only in basename
      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
     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(&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