diff options
Diffstat (limited to 'app/fvwm/libs/envvar.c')
-rw-r--r-- | app/fvwm/libs/envvar.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/app/fvwm/libs/envvar.c b/app/fvwm/libs/envvar.c new file mode 100644 index 000000000..35d5f887f --- /dev/null +++ b/app/fvwm/libs/envvar.c @@ -0,0 +1,318 @@ +/************************************************************************** + * + * 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; +} |