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(®, 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