/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
/* 0 = both upper and lower case */
/* 1 = initial lower case only (build variables) */
/* 2 = initial upper case only (install variables) */
#define mode(flag, pt) (!flag || ((flag == 1) && islower(pt[1])) || \
((flag == 2) && isupper(pt[1])))
/*
* For next and last functions below, values indicate whether resolution
* was possible.
*
* 0 = all OK - the variable resolved within the established parameters
* or it wasn't time for the variable to bind.
* 1 = parameter did not resolve because there was no value in the
* environment or because it was a build variable at install
* time.
*/
/*
* This gets a raw path which may contain shell variables and returns in path
* a pathname with all appropriate parameters resolved. If it comes in
* relative, it goes out relative.
*/
int
mappath(int flag, char *path)
{
char buffer[PATH_MAX];
char varname[64];
char *npt, *pt, *pt2, *copy;
char *token;
int retvalue = 0;
copy = buffer;
/*
* For each "/" separated token. If the token contains an environment
* variable, then evaluate the variable and insert it into path.
*/
for (pt = path; *pt; /* void */) {
/*
* If this is a token and it's an environment variable
* properly situated in the path...
*/
if ((*pt == '$') && isalpha(pt[1]) &&
((pt == path) || (pt[-1] == '/'))) {
/* ... and it's the right time to evaluate it... */
if (mode(flag, pt)) {
/* replace the parameter with its value. */
pt2 = varname;
for (npt = pt+1; *npt && (*npt != '/');
/* void */)
*pt2++ = *npt++;
*pt2 = '\0';
/*
* At this point EVERY token should evaluate
* to a value. If it doesn't, there's an
* error.
*/
if ((token = getenv(varname)) != NULL &&
*token != NULL) {
/* copy in parameter value */
while (*token)
*copy++ = *token++;
pt = npt;
} else {
retvalue = 1;
*copy++ = *pt++;
}
/*
* If evaluate time is wrong, determine of this is an
* error.
*/
} else {
if (flag == 2) { /* install-time. */
/*
* ALL variables MUST evaluate at
* install time.
*/
*copy++ = *pt++;
retvalue = 1;
} else if (flag == 1 && /* build-time */
islower(pt[1])) {
/*
* All build-time variables must
* evaluate at build time.
*/
retvalue = 1;
*copy++ = *pt++;
} else /* no problem. */
*copy++ = *pt++;
}
/*
* If it's a separator, copy it over to the target buffer and
* move to the start of the next token.
*/
} else if (*pt == '/') {
while (pt[1] == '/')
pt++;
if ((pt[1] == '\0') && (pt > path))
break;
*copy++ = *pt++;
/*
* If we're in the middle of a non-parametric token, copy
* that character over and try the next character.
*/
} else
*copy++ = *pt++;
}
*copy = '\0';
(void) strcpy(path, buffer);
return (retvalue);
}
/*
* This function resolves the path into an absolute path referred to
* an install root of ir.
*/
void
basepath(char *path, char *basedir, char *ir)
{
char buffer[PATH_MAX];
/* For a relative path, prepend the basedir */
if (*path != '/') {
(void) strcpy(buffer, path);
if (ir && *ir) {
while (*ir)
*path++ = *ir++;
if (path[-1] == '/')
path--;
}
if (basedir && *basedir) {
if (ir && *ir && *basedir != '/')
*path++ = '/';
while (*basedir)
*path++ = *basedir++;
if (path[-1] == '/')
path--;
}
*path++ = '/';
(void) strcpy(path, buffer);
/* For an absolute path, just prepend the install root */
} else {
if (ir && *ir) {
(void) strcpy(buffer, path);
while (*ir)
*path++ = *ir++;
if (path[-1] == '/')
path--;
(void) strcpy(path, buffer);
}
}
}
/*
* Evaluate varname and return with environment variables resolved.
* NOTE: This assumes that varname is a buffer long enough to hold the
* evaluated string.
*/
int
mapvar(int flag, char *varname)
{
char *token;
int retvalue = 0;
/* If its a parametric entry beginning with an alpha character. */
if (*varname == '$' && isalpha(varname[1])) {
/* ...and it's the right time to evaluate it... */
if (mode(flag, varname)) {
/*
* then it MUST be possible to evaluate it. If not,
* there's an error.
*/
if (((token = getenv(&varname[1])) != NULL) &&
*token) {
/* copy token into varname */
while (*token)
*varname++ = *token++;
*varname = '\0';
} else
retvalue = 1;
} else {
if (flag == 2) /* install-time. */
/*
* ALL variables MUST evaluate at install
* time.
*/
retvalue = 1;
else if (flag == 1 && /* build-time */
islower(varname[1]))
/*
* all build-time variables must evaluate at
* build time.
*/
retvalue = 1;
}
}
return (retvalue);
}