basename.c revision 132187
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1991, 1993, 1994
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3541568Sarchiestatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1991, 1993, 1994\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
3887258Smarkm#endif
391590Srgrimes
4087628Sdwmalone#if 0
411590Srgrimes#ifndef lint
4287628Sdwmalonestatic char sccsid[] = "@(#)basename.c	8.4 (Berkeley) 5/4/95";
431590Srgrimes#endif /* not lint */
4487628Sdwmalone#endif
451590Srgrimes
4687628Sdwmalone#include <sys/cdefs.h>
4787628Sdwmalone__FBSDID("$FreeBSD: head/usr.bin/basename/basename.c 132187 2004-07-15 06:15:10Z tjr $");
4887628Sdwmalone
4965508Sdes#include <err.h>
5065413Sdes#include <libgen.h>
51132187Stjr#include <limits.h>
52132187Stjr#include <locale.h>
531590Srgrimes#include <stdio.h>
5478717Sdd#include <stdlib.h>
5565508Sdes#include <string.h>
5623690Speter#include <unistd.h>
57132187Stjr#include <wchar.h>
581590Srgrimes
59132187Stjrvoid stripsuffix(char *, const char *, size_t);
6092920Simpvoid usage(void);
611590Srgrimes
621590Srgrimesint
63102944Sdwmalonemain(int argc, char **argv)
641590Srgrimes{
65132187Stjr	char *p, *suffix;
6699137Sjmallett	size_t suffixlen;
6799137Sjmallett	int aflag, ch;
681590Srgrimes
69132187Stjr	setlocale(LC_ALL, "");
70132187Stjr
7199137Sjmallett	aflag = 0;
7299137Sjmallett	suffix = NULL;
7399137Sjmallett	suffixlen = 0;
7499137Sjmallett
7599137Sjmallett	while ((ch = getopt(argc, argv, "as:")) != -1)
761590Srgrimes		switch(ch) {
7799137Sjmallett		case 'a':
7899137Sjmallett			aflag = 1;
7999137Sjmallett			break;
8099137Sjmallett		case 's':
8199137Sjmallett			suffix = optarg;
8299137Sjmallett			break;
831590Srgrimes		case '?':
841590Srgrimes		default:
851590Srgrimes			usage();
861590Srgrimes		}
871590Srgrimes	argc -= optind;
881590Srgrimes	argv += optind;
891590Srgrimes
9099137Sjmallett	if (argc < 1)
911590Srgrimes		usage();
921590Srgrimes
9367024Sdes	if (!*argv[0]) {
9467024Sdes		printf("\n");
9567024Sdes		exit(0);
9667024Sdes	}
9765508Sdes	if ((p = basename(argv[0])) == NULL)
9865508Sdes		err(1, "%s", argv[0]);
9999137Sjmallett	if ((suffix == NULL && !aflag) && argc == 2) {
10099137Sjmallett		suffix = argv[1];
10199137Sjmallett		argc--;
10299137Sjmallett	}
10399137Sjmallett	if (suffix != NULL)
10499137Sjmallett		suffixlen = strlen(suffix);
10599137Sjmallett	while (argc--) {
10699137Sjmallett		if ((p = basename(*argv)) == NULL)
10799137Sjmallett			err(1, "%s", argv[0]);
108132187Stjr		stripsuffix(p, suffix, suffixlen);
10999137Sjmallett		argv++;
11099137Sjmallett		(void)printf("%s\n", p);
11199137Sjmallett	}
1121590Srgrimes	exit(0);
1131590Srgrimes}
1141590Srgrimes
1151590Srgrimesvoid
116132187Stjrstripsuffix(char *p, const char *suffix, size_t suffixlen)
117132187Stjr{
118132187Stjr	char *q, *r;
119132187Stjr	mbstate_t mbs;
120132187Stjr	size_t n;
121132187Stjr
122132187Stjr	if (suffixlen && (q = strchr(p, '\0') - suffixlen) > p &&
123132187Stjr	    strcmp(suffix, q) == 0) {
124132187Stjr		/* Ensure that the match occurred on a character boundary. */
125132187Stjr		memset(&mbs, 0, sizeof(mbs));
126132187Stjr		for (r = p; r < q; r += n) {
127132187Stjr			n = mbrlen(r, MB_LEN_MAX, &mbs);
128132187Stjr			if (n == (size_t)-1 || n == (size_t)-2) {
129132187Stjr				memset(&mbs, 0, sizeof(mbs));
130132187Stjr				n = 1;
131132187Stjr			}
132132187Stjr		}
133132187Stjr		/* Chop off the suffix. */
134132187Stjr		if (q == r)
135132187Stjr			*q = '\0';
136132187Stjr	}
137132187Stjr}
138132187Stjr
139132187Stjrvoid
140102944Sdwmaloneusage(void)
1411590Srgrimes{
1421590Srgrimes
14399137Sjmallett	(void)fprintf(stderr,
14499137Sjmallett"usage: basename string [suffix]\n"
14599137Sjmallett"       basename [-a] [-s suffix] string [...]\n");
1461590Srgrimes	exit(1);
1471590Srgrimes}
148