summaryrefslogtreecommitdiff
path: root/app/fvwm/libs/envvar.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/fvwm/libs/envvar.c')
-rw-r--r--app/fvwm/libs/envvar.c318
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;
+}