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 (c) 1996, by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * MKS Library -- basename -- produce base name of a file name
31  * NOTE: not standard SVID routine.
32  *
33  * Copyright 1985, 1995 by Mortice Kern Systems Inc.  All rights reserved.
34  *
35  * james Partanen, June '95
36  *
37  */
38 #ifdef M_RCSID
39 #ifndef lint
40 static char rcsID[] = "$Header: /rd/src/libc/gen/rcs/base.c 1.26 1995/08/02 17:32:36 rodney Exp $";
41 #endif
42 #endif
43 
44 #include <string.h>
45 
46 #define DIRNAME		0
47 #define BASENAME	1
48 
49 #define M_FSDELIM(c)	((c)=='/')
50 #define M_DRDELIM(c)	(0)
51 
52 static char curdir[] = ".";
53 
54 /*f
55  * Since the goal is essentially common: find the last occurring
56  * M_FSDELIM, and since most of the degenerate cases end up with the
57  * same result, let's do most of the work in one function.
58  *	- check degenerate arg forms
59  *	- deal with a possible drive specifier
60  *	- deal with degenerate paths
61  *	- find last non-trailing M_FSDELIM
62  *	- deal with degenerate dirname
63  *	- deal with general case, returning prefix or suffix based on type
64  */
65 static char *
66 basedir(char *arg, int type)
67 {
68 	register char *cp, *path;
69 
70 	if (arg==(char *)0 || *arg=='\0' ||
71 		(*arg=='.' && (arg[1]=='\0' ||
72 		(type==DIRNAME && arg[1]=='.' && arg[2]=='\0'))))
73 
74 		return curdir;	/* arg NULL, empty, ".", or ".." in DIRNAME */
75 
76 	if (M_DRDELIM(arg[1]))	/* drive-specified pathnames */
77 		path = arg+2;
78 	else
79 		path = arg;
80 
81 	if (path[1]=='\0'&&M_FSDELIM(*path))	/* "/", or drive analog */
82 		return arg;
83 
84 	cp = strchr(path, '\0');
85 	cp--;
86 
87 	while (cp != path && M_FSDELIM(*cp))
88 		*(cp--) = '\0';
89 
90 	for (;cp>path && !M_FSDELIM(*cp); cp--)
91 		;
92 
93 	if (!M_FSDELIM(*cp))
94 		if (type==DIRNAME && path!=arg) {
95 			*path = '\0';
96 			return arg;	/* curdir on the specified drive */
97 		} else
98 			return (type==DIRNAME)?curdir:path;
99 	else if (cp == path && type == DIRNAME) {
100 		cp[1] = '\0';
101 		return arg;		/* root directory involved */
102 	} else if (cp == path && cp[1] == '\0')
103 		return(arg);
104 	else if (type == BASENAME)
105 		return ++cp;
106 	*cp = '\0';
107 	return arg;
108 }
109 
110 /*f
111  * Finds the dirname of the given file.  Spec1170 conformant.
112  */
113 char *
114 dirname(char *arg)
115 {
116 	return(basedir(arg, DIRNAME));
117 }
118 
119 /*f
120  * Finds the basename of the given file.  Spec1170 conformant.
121  */
122 char *
123 basename(char *arg)
124 {
125 	return(basedir(arg, BASENAME));
126 }
127 
128 #ifdef TEST_MAIN_BASE_C
129 #include <stdio.h>
130 
131 int main(int argc, char **argv)
132 {
133 	int cnt;
134 	char arg[128];
135 	char *tmp;
136 
137 	if (argc>1) {
138 		for (cnt=argc--;argc;argc--) {
139 			tmp = strdup(argv[cnt-argc]);
140 			printf("%s\t%s\n",
141 				dirname(argv[cnt-argc]),
142 				basename(tmp));
143 			free(tmp);
144 		}
145 		return 0;
146 	}
147 
148 	printf("enter pathnames less than 128 chars.  enter 'q' to quit.\n");
149 
150 	while(gets(arg))
151 		if (!strcmp(arg, "q"))
152 			break;
153 		else {
154 			tmp = strdup(arg);
155 			printf("%s\t%s\n", dirname(arg), basename(tmp));
156 			free(tmp);
157 		}
158 
159 	return 0;
160 }
161 #endif /* TEST_MAIN_BASE_C */
162