319 lines
8.3 KiB
C
319 lines
8.3 KiB
C
|
/**************************************************************************
|
||
|
*
|
||
|
* FILE envvar.c
|
||
|
* MODULE OF fvwm
|
||
|
*
|
||
|
* DESCRIPTION Routines to expand environment-variables into strings.
|
||
|
* Will understand both $ENV and ${ENV} -type variables.
|
||
|
*
|
||
|
* WRITTEN BY Sverre H. Huseby
|
||
|
* sverrehu@ifi.uio.no
|
||
|
*
|
||
|
* CREATED 1995/10/3
|
||
|
*
|
||
|
**************************************************************************/
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "fvwmlib.h"
|
||
|
|
||
|
#ifndef NULL
|
||
|
#define NULL 0
|
||
|
#endif
|
||
|
|
||
|
/**************************************************************************
|
||
|
* *
|
||
|
* P R I V A T E D A T A *
|
||
|
* *
|
||
|
**************************************************************************/
|
||
|
|
||
|
/**************************************************************************
|
||
|
* *
|
||
|
* P R I V A T E F U N C T I O N S *
|
||
|
* *
|
||
|
**************************************************************************/
|
||
|
|
||
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* NAME strDel
|
||
|
*
|
||
|
* FUNCTION Delete characters from a string.
|
||
|
*
|
||
|
* INPUT s the string to delete characters from.
|
||
|
* idx index of first character to delete.
|
||
|
* n number of characters to delete.
|
||
|
*
|
||
|
* OUTPUT s string with characters deleted.
|
||
|
*
|
||
|
* DESCRIPTION Deletes characters from a string by moving following
|
||
|
* characters back.
|
||
|
*
|
||
|
*/
|
||
|
static void strDel(char *s, int idx, int n)
|
||
|
{
|
||
|
int l;
|
||
|
char *p;
|
||
|
|
||
|
if (idx >= (l = strlen(s)))
|
||
|
return;
|
||
|
if (idx + n > l)
|
||
|
n = l - idx;
|
||
|
s += idx;
|
||
|
p = s + n;
|
||
|
do {
|
||
|
*s++ = *p;
|
||
|
} while (*p++);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* NAME strIns
|
||
|
*
|
||
|
* FUNCTION Insert a string into a string.
|
||
|
*
|
||
|
* INPUT s the string to insert into.
|
||
|
* ins the string to insert.
|
||
|
* idx index of where to insert the string.
|
||
|
* maxstrlen max length of s, including '\0'.
|
||
|
*
|
||
|
* OUTPUT s string with characters inserted.
|
||
|
*
|
||
|
* DESCRIPTION The insertion will be done even if the string gets to
|
||
|
* long, but characters will be sacrificed at the end of s.
|
||
|
* The string is always '\0'-terminated.
|
||
|
*
|
||
|
*/
|
||
|
static void strIns(char *s, const char *ins, int idx, int maxstrlen)
|
||
|
{
|
||
|
int l, li, move;
|
||
|
char *p1, *p2;
|
||
|
|
||
|
if (idx > (l = strlen(s)))
|
||
|
idx = l;
|
||
|
li = strlen(ins);
|
||
|
move = l - idx + 1; /* include '\0' in move */
|
||
|
p1 = s + l;
|
||
|
p2 = p1 + li;
|
||
|
while (p2 >= s + maxstrlen) {
|
||
|
--p1;
|
||
|
--p2;
|
||
|
--move;
|
||
|
}
|
||
|
while (move-- > 0)
|
||
|
*p2-- = *p1--;
|
||
|
p1 = s + idx;
|
||
|
if (idx + li >= maxstrlen)
|
||
|
li = maxstrlen - idx - 1;
|
||
|
while (li--)
|
||
|
*p1++ = *ins++;
|
||
|
s[maxstrlen - 1] = '\0';
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* NAME findEnvVar
|
||
|
*
|
||
|
* FUNCTION Find first environment variable in a string.
|
||
|
*
|
||
|
* INPUT s the string to scan.
|
||
|
*
|
||
|
* OUTPUT len length of variable, including $ and { }.
|
||
|
*
|
||
|
* RETURNS Pointer to the $ that introduces the variable, or NULL
|
||
|
* if no variable is found.
|
||
|
*
|
||
|
* DESCRIPTION Searches for matches like $NAME and ${NAME}, where NAME is
|
||
|
* a sequence of characters, digits and underscores, of which
|
||
|
* the first can not be a digit.
|
||
|
*
|
||
|
* NOTE This function will only return `legal' variables. There
|
||
|
* may be $'s in the string that are not followed by what
|
||
|
* is considered a legal variable name introducer. Such
|
||
|
* occurrences are skipped.
|
||
|
*
|
||
|
*/
|
||
|
static char *findEnvVar(const char *s, int *len)
|
||
|
{
|
||
|
int brace = 0;
|
||
|
char *ret = NULL;
|
||
|
const char *next;
|
||
|
|
||
|
if (!s)
|
||
|
return NULL;
|
||
|
while (*s) {
|
||
|
next = s + 1;
|
||
|
if (*s == '$' && (isalpha(*next) || *next == '_' || *next == '{')) {
|
||
|
ret = (char *) s++;
|
||
|
if (*s == '{') {
|
||
|
brace = 1;
|
||
|
++s;
|
||
|
}
|
||
|
while (*s && (isalnum(*s) || *s == '_'))
|
||
|
++s;
|
||
|
*len = s - ret;
|
||
|
if (brace) {
|
||
|
if (*s == '}') {
|
||
|
++*len;
|
||
|
break;
|
||
|
}
|
||
|
ret = NULL;
|
||
|
} else
|
||
|
break;
|
||
|
}
|
||
|
++s;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* NAME getEnv
|
||
|
*
|
||
|
* FUNCTION Look up environment variable.
|
||
|
*
|
||
|
* INPUT name name of environment variable to look up. This
|
||
|
* may include $ and { }.
|
||
|
*
|
||
|
* RETURNS The variable contents, or "" if not found.
|
||
|
*
|
||
|
*/
|
||
|
static const char *getEnv(const char *name)
|
||
|
{
|
||
|
static char *empty = "";
|
||
|
char *ret, *tmp, *p, *p2;
|
||
|
|
||
|
if ((tmp = strdup(name)) == NULL)
|
||
|
return empty; /* better than no test at all. */
|
||
|
p = tmp;
|
||
|
if (*p == '$')
|
||
|
++p;
|
||
|
if (*p == '{') {
|
||
|
++p;
|
||
|
if ((p2 = strchr(p, '}')) != NULL)
|
||
|
*p2 = '\0';
|
||
|
}
|
||
|
if ((ret = getenv(p)) == NULL)
|
||
|
ret = empty;
|
||
|
free(tmp);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**************************************************************************
|
||
|
* *
|
||
|
* P U B L I C F U N C T I O N S *
|
||
|
* *
|
||
|
**************************************************************************/
|
||
|
|
||
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* NAME envExpand
|
||
|
*
|
||
|
* FUNCTION Expand environment variables in a string.
|
||
|
*
|
||
|
* SYNOPSIS #include "envvar.h"
|
||
|
* int envExpand(char *s, int maxstrlen);
|
||
|
*
|
||
|
* INPUT s string to expand environment variables in.
|
||
|
* maxstrlen max length of string, including '\0'.
|
||
|
*
|
||
|
* OUTPUT s the string with environment variables expanded.
|
||
|
*
|
||
|
* RETURNS Number of changes done.
|
||
|
*
|
||
|
* NOTES A non-existing variable is substituted with the empty
|
||
|
* string.
|
||
|
*
|
||
|
*/
|
||
|
int envExpand(char *s, int maxstrlen)
|
||
|
{
|
||
|
char *var, *s2, save;
|
||
|
const char *env;
|
||
|
int len, ret = 0;
|
||
|
|
||
|
s2 = s;
|
||
|
while ((var = findEnvVar(s2, &len)) != NULL) {
|
||
|
++ret;
|
||
|
save = var[len];
|
||
|
var[len] = '\0';
|
||
|
env = getEnv(var);
|
||
|
var[len] = save;
|
||
|
strDel(s, var - s, len);
|
||
|
strIns(s, env, var - s, maxstrlen);
|
||
|
s2 = var + strlen(env);
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------
|
||
|
*
|
||
|
* NAME envDupExpand
|
||
|
*
|
||
|
* FUNCTION Expand environment variables into a new string.
|
||
|
*
|
||
|
* SYNOPSIS #include "envvar.h"
|
||
|
* char *envDupExpand(const char *s, int extra);
|
||
|
*
|
||
|
* INPUT s string to expand environment variables in.
|
||
|
* extra number of extra bytes to allocate in the
|
||
|
* string, in addition to the string contents
|
||
|
* and the terminating '\0'.
|
||
|
*
|
||
|
* RETURNS A dynamically allocated string with environment
|
||
|
* variables expanded.
|
||
|
* Use free() to deallocate the buffer when it is no
|
||
|
* longer needed.
|
||
|
* NULL is returned if there is not enough memory.
|
||
|
*
|
||
|
* NOTES A non-existing variable is substituted with the empty
|
||
|
* string.
|
||
|
*
|
||
|
*/
|
||
|
char *envDupExpand(const char *s, int extra)
|
||
|
{
|
||
|
char *var, *ret, save;
|
||
|
const char *env, *s2;
|
||
|
int len, slen, elen, bufflen;
|
||
|
|
||
|
/*
|
||
|
* calculate length needed.
|
||
|
*/
|
||
|
s2 = s;
|
||
|
slen = strlen(s);
|
||
|
bufflen = slen + 1 + extra;
|
||
|
while ((var = findEnvVar(s2, &len)) != NULL) {
|
||
|
save = var[len];
|
||
|
var[len] = '\0';
|
||
|
env = getEnv(var);
|
||
|
var[len] = save;
|
||
|
elen = strlen(env);
|
||
|
/* need to make a buffer the maximum possible size, else we
|
||
|
* may get trouble while expanding. */
|
||
|
bufflen += len > elen ? len : elen;
|
||
|
s2 = var + len;
|
||
|
}
|
||
|
if (bufflen < slen + 1)
|
||
|
bufflen = slen + 1;
|
||
|
|
||
|
ret = safemalloc(bufflen);
|
||
|
|
||
|
/*
|
||
|
* now do the real expansion.
|
||
|
*/
|
||
|
strlcpy(ret, s,bufflen);
|
||
|
envExpand(ret, bufflen - extra);
|
||
|
|
||
|
return ret;
|
||
|
}
|