xref: /illumos-gate/usr/src/lib/libpkg/common/mappath.c (revision 7ab4e62e3b5c454f248a38bec0d489e8f5543324)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 
31 
32 #include <limits.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <ctype.h>
37 
38 /* 0 = both upper and lower case */
39 /* 1 = initial lower case only (build variables) */
40 /* 2 = initial upper case only (install variables) */
41 #define	mode(flag, pt)	(!flag || ((flag == 1) && islower(pt[1])) || \
42 			((flag == 2) && isupper(pt[1])))
43 
44 /*
45  * For next and last functions below, values indicate whether resolution
46  * was possible.
47  *
48  *	0 = all OK - the variable resolved within the established parameters
49  *		or it wasn't time for the variable to bind.
50  *	1 = parameter did not resolve because there was no value in the
51  *		environment or because it was a build variable at install
52  *		time.
53  */
54 
55 /*
56  * This gets a raw path which may contain shell variables and returns in path
57  * a pathname with all appropriate parameters resolved. If it comes in
58  * relative, it goes out relative.
59  */
60 int
61 mappath(int flag, char *path)
62 {
63 	char buffer[PATH_MAX];
64 	char varname[64];
65 	char *npt, *pt, *pt2, *copy;
66 	char *token;
67 	int retvalue = 0;
68 
69 	copy = buffer;
70 
71 	/*
72 	 * For each "/" separated token. If the token contains an environment
73 	 * variable, then evaluate the variable and insert it into path.
74 	 */
75 	for (pt = path; *pt; /* void */) {
76 		/*
77 		 * If this is a token and it's an environment variable
78 		 * properly situated in the path...
79 		 */
80 		if ((*pt == '$') && isalpha(pt[1]) &&
81 		    ((pt == path) || (pt[-1] == '/'))) {
82 			/* ... and it's the right time to evaluate it... */
83 			if (mode(flag, pt)) {
84 				/* replace the parameter with its value. */
85 				pt2 = varname;
86 				for (npt = pt+1; *npt && (*npt != '/');
87 				    /* void */)
88 					*pt2++ = *npt++;
89 				*pt2 = '\0';
90 				/*
91 				 * At this point EVERY token should evaluate
92 				 * to a value. If it doesn't, there's an
93 				 * error.
94 				 */
95 				if ((token = getenv(varname)) != NULL &&
96 				    *token != NULL) {
97 					/* copy in parameter value */
98 					while (*token)
99 						*copy++ = *token++;
100 					pt = npt;
101 				} else {
102 					retvalue = 1;
103 					*copy++ = *pt++;
104 				}
105 			/*
106 			 * If evaluate time is wrong, determine of this is an
107 			 * error.
108 			 */
109 			} else {
110 				if (flag == 2) {	/* install-time. */
111 					/*
112 					 * ALL variables MUST evaluate at
113 					 * install time.
114 					 */
115 					*copy++ = *pt++;
116 					retvalue = 1;
117 				} else if (flag == 1 &&	/* build-time */
118 				    islower(pt[1])) {
119 					/*
120 					 * All build-time variables must
121 					 * evaluate at build time.
122 					 */
123 					retvalue = 1;
124 					*copy++ = *pt++;
125 				} else	/* no problem. */
126 					*copy++ = *pt++;
127 			}
128 		/*
129 		 * If it's a separator, copy it over to the target buffer and
130 		 * move to the start of the next token.
131 		 */
132 		} else if (*pt == '/') {
133 			while (pt[1] == '/')
134 				pt++;
135 			if ((pt[1] == '\0') && (pt > path))
136 				break;
137 			*copy++ = *pt++;
138 		/*
139 		 * If we're in the middle of a non-parametric token, copy
140 		 * that character over and try the next character.
141 		 */
142 		} else
143 			*copy++ = *pt++;
144 	}
145 	*copy = '\0';
146 	(void) strcpy(path, buffer);
147 	return (retvalue);
148 }
149 
150 /*
151  * This function resolves the path into an absolute path referred to
152  * an install root of ir.
153  */
154 void
155 basepath(char *path, char *basedir, char *ir)
156 {
157 	char buffer[PATH_MAX];
158 
159 	/* For a relative path, prepend the basedir */
160 	if (*path != '/') {
161 		(void) strcpy(buffer, path);
162 		if (ir && *ir) {
163 			while (*ir)
164 				*path++ = *ir++;
165 			if (path[-1] == '/')
166 				path--;
167 		}
168 		if (basedir && *basedir) {
169 			if (ir && *ir && *basedir != '/')
170 				*path++ = '/';
171 			while (*basedir)
172 				*path++ = *basedir++;
173 			if (path[-1] == '/')
174 				path--;
175 		}
176 		*path++ = '/';
177 		(void) strcpy(path, buffer);
178 
179 	/* For an absolute path, just prepend the install root */
180 	} else {
181 		if (ir && *ir) {
182 			(void) strcpy(buffer, path);
183 			while (*ir)
184 				*path++ = *ir++;
185 			if (path[-1] == '/')
186 				path--;
187 			(void) strcpy(path, buffer);
188 		}
189 	}
190 }
191 
192 /*
193  * Evaluate varname and return with environment variables resolved.
194  * NOTE: This assumes that varname is a buffer long enough to hold the
195  * evaluated string.
196  */
197 int
198 mapvar(int flag, char *varname)
199 {
200 	char	*token;
201 	int retvalue = 0;
202 
203 	/* If its a parametric entry beginning with an alpha character. */
204 	if (*varname == '$' && isalpha(varname[1])) {
205 		/* ...and it's the right time to evaluate it... */
206 		if (mode(flag, varname)) {
207 			/*
208 			 * then it MUST be possible to evaluate it. If not,
209 			 * there's an error.
210 			 */
211 			if (((token = getenv(&varname[1])) != NULL) &&
212 			    *token) {
213 				/* copy token into varname */
214 				while (*token)
215 					*varname++ = *token++;
216 				*varname = '\0';
217 			} else
218 				retvalue = 1;
219 		} else {
220 			if (flag == 2) /* install-time. */
221 				/*
222 				 * ALL variables MUST evaluate at install
223 				 * time.
224 				 */
225 				retvalue = 1;
226 			else if (flag == 1 &&	/* build-time */
227 			    islower(varname[1]))
228 				/*
229 				 * all build-time variables must evaluate at
230 				 * build time.
231 				 */
232 				retvalue = 1;
233 		}
234 	}
235 	return (retvalue);
236 }
237