mappath.c revision 9781:ccf49524d5dc
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 */
60int
61mappath(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 */
154void
155basepath(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 */
197int
198mapvar(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