diff options
author | Werner Koch <[email protected]> | 2021-09-17 15:33:21 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2021-09-17 15:33:21 +0000 |
commit | 9c272dc245456d5403e3bd50553b4fdccb370e27 (patch) | |
tree | 73ea80e19e91dddddce2c5c98720cfb87d9cc38b /common/stringhelp.c | |
parent | doc: Clarify some gpg keyring options (diff) | |
download | gnupg-9c272dc245456d5403e3bd50553b4fdccb370e27.tar.gz gnupg-9c272dc245456d5403e3bd50553b4fdccb370e27.zip |
common: New function substitute_envvars.
* common/stringhelp.c (substitute_envvars): New. Based on code in
gpg-connect-agent.
* common/t-stringhelp.c: Include sysutils.h.
(test_substitute_envvars): New.
--
GnuPG-bug-id: 5599
Diffstat (limited to '')
-rw-r--r-- | common/stringhelp.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/common/stringhelp.c b/common/stringhelp.c index 4dc179738..c9e10800d 100644 --- a/common/stringhelp.c +++ b/common/stringhelp.c @@ -1692,3 +1692,107 @@ format_text (const char *text_in, int target_cols, int max_cols) return text; } + + +/* Substitute environment variables in STRING and return a new string. + * On error the function returns NULL. */ +char * +substitute_envvars (const char *string) +{ + char *line, *p, *pend; + const char *value; + size_t valuelen, n; + char *result = NULL; + + result = line = xtrystrdup (string); + if (!result) + return NULL; /* Ooops */ + + while (*line) + { + p = strchr (line, '$'); + if (!p) + goto leave; /* No or no more variables. */ + + if (p[1] == '$') /* Escaped dollar sign. */ + { + memmove (p, p+1, strlen (p+1)+1); + line = p + 1; + continue; + } + + if (p[1] == '{') + { + int count = 0; + + for (pend=p+2; *pend; pend++) + { + if (*pend == '{') + count++; + else if (*pend == '}') + { + if (--count < 0) + break; + } + } + if (!*pend) + goto leave; /* Unclosed - don't substitute. */ + } + else + { + for (pend = p+1; *pend && (alnump (pend) || *pend == '_'); pend++) + ; + } + + if (p[1] == '{' && *pend == '}') + { + int save = *pend; + *pend = 0; + value = getenv (p+2); + *pend++ = save; + } + else + { + int save = *pend; + *pend = 0; + value = getenv (p+1); + *pend = save; + } + + if (!value) + value = ""; + valuelen = strlen (value); + if (valuelen <= pend - p) + { + memcpy (p, value, valuelen); + p += valuelen; + n = pend - p; + if (n) + memmove (p, p+n, strlen (p+n)+1); + line = p; + } + else + { + char *src = result; + char *dst; + + dst = xtrymalloc (strlen (src) + valuelen + 1); + if (!dst) + { + xfree (result); + return NULL; + } + n = p - src; + memcpy (dst, src, n); + memcpy (dst + n, value, valuelen); + n += valuelen; + strcpy (dst + n, pend); + line = dst + n; + xfree (result); + result = dst; + } + } + + leave: + return result; +} |