diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-06-14 19:08:06 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-06-14 19:08:06 +0200 |
commit | 15409bae5ffdfce4ef17c4ccf14c8cd4c1b8f37e (patch) | |
tree | 852b915a69d57679a05ef5fec0ee6608cdcf2dee /src/qregisters.cpp | |
parent | 573951d4e2bb4fb1d14212583a59ce76344593cc (diff) | |
download | sciteco-15409bae5ffdfce4ef17c4ccf14c8cd4c1b8f37e.tar.gz |
handle environment variables more consistently
* the registers beginning with "$" are exported into sub-process
environments. Therefore macros can now modify the environment
(variables) of commands executed via EC/EG.
A variable can be modified temporarily, e.g.:
[[$FOO] ^U[$FOO]bar$ EC...$ ][$FOO]
* SciTECO accesses the global environment registers instead of
using g_getenv(). Therefore now, tilde-expansion will always
use the current value of the "$HOME" register.
Previously, both register and environment variable could diverge.
* This effectively fully maps the process environment to a subset of
Q-Registers beginning with "$".
* This hasn't been implemented by mapping those registers to
special implementations that updates the process environment
directly, since g_setenv() is non-thread-safe on UNIX
and we're expected to have threads soon - at least in the GTK+ UI.
Diffstat (limited to 'src/qregisters.cpp')
-rw-r--r-- | src/qregisters.cpp | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/src/qregisters.cpp b/src/qregisters.cpp index 20c1380..22d7300 100644 --- a/src/qregisters.cpp +++ b/src/qregisters.cpp @@ -529,7 +529,80 @@ QRegisterTable::edit(QRegister *reg) QRegisters::current = reg; } -/* +void +QRegisterTable::set_environ(void) +{ + /* + * NOTE: Using g_get_environ() would be more efficient, + * but it appears to be broken, at least on Wine + * and Windows 2000. + */ + gchar **env = g_listenv(); + + for (gchar **key = env; *key; key++) { + gchar name[1 + strlen(*key) + 1]; + QRegister *reg; + + name[0] = '$'; + strcpy(name + 1, *key); + + reg = insert(name); + reg->set_string(g_getenv(*key)); + } + + g_strfreev(env); +} + +gchar ** +QRegisterTable::get_environ(void) +{ + QRegister *first = nfind("$"); + + gint envp_len = 1; + gchar **envp, **p; + + /* + * Iterate over all registers beginning with "$" to + * guess the size required for the environment array. + * This may waste a few bytes because not __every__ + * register beginning with "$" is an environment + * register. + */ + for (QRegister *cur = first; + cur && cur->name[0] == '$'; + cur = (QRegister *)cur->next()) + envp_len++; + + p = envp = (gchar **)g_malloc(sizeof(gchar *)*envp_len); + + for (QRegister *cur = first; + cur && cur->name[0] == '$'; + cur = (QRegister *)cur->next()) { + gchar *value; + + /* + * Ignore the "$" register (not an environment + * variable register) and registers whose + * name contains "=" (not allowed in environment + * variable names). + */ + if (!cur->name[1] || strchr(cur->name+1, '=')) + continue; + + value = cur->get_string(); + /* more efficient than g_environ_setenv() */ + *p++ = g_strconcat(cur->name+1, "=", value, NIL); + g_free(value); + } + + *p = NULL; + + return envp; +} + +/** + * Free resources associated with table. + * * This is similar to RBTree::clear() but * has the advantage that we can check whether some * register is currently edited. |