+/* --- @bc__setenv@ --- *
+ *
+ * Arguments: @sym_env *e@ = pointer to environment variable block
+ * @const char *val@ = value to set
+ *
+ * Returns: ---
+ *
+ * Use: Sets an environment variable block to the right value.
+ */
+
+static void bc__setenv(sym_env *e, const char *val)
+{
+ e->val = xmalloc(strlen(e->_base.name) + 1 + strlen(val) + 1);
+ sprintf(e->val, "%s=%s", e->_base.name, val);
+}
+
+/* --- @bc__putenv@ --- *
+ *
+ * Arguments: @const char *var@ = name of the variable to set, or 0 if
+ * this is embedded in the value string
+ * @const char *val@ = value to set, or 0 if the variable must
+ * be removed
+ * @unsigned int fl@ = flags to set
+ * @unsigned int force@ = force overwrite of preserved variables
+ *
+ * Returns: Pointer to symbol block, or zero if it was deleted.
+ *
+ * Use: Puts an item into the environment.
+ */
+
+static sym_env *bc__putenv(const char *var, const char *val,
+ unsigned int fl, unsigned int force)
+{
+ unsigned int f;
+ sym_env *e;
+ char *q = 0;
+ size_t sz;
+
+ /* --- Sort out embedded variable names --- */
+
+ if (!var) {
+ const char *p = strchr(val, '=');
+
+ if (p) {
+ sz = p - val;
+ q = xmalloc(sz + 1);
+ memcpy(q, val, sz);
+ q[sz] = 0;
+ var = q;
+ val = p + 1;
+ } else {
+ var = val;
+ val = 0;
+ }
+ }
+
+ /* --- Find the variable block --- */
+
+ if (val) {
+ e = sym_find(&bc__env, var, -1, sizeof(*e), &f);
+ if (~e->f & envFlag_preserve || force) {
+ if (f)
+ free(e->val);
+ bc__setenv(e, val);
+ }
+ } else {
+ e = sym_find(&bc__env, var, -1, 0, 0);
+ if (e && (force || ~e->f & envFlag_preserve))
+ sym_remove(&bc__env, e);
+ e = 0;
+ }
+
+ /* --- Tidy up and return --- */
+
+ if (q)
+ free(q);
+ if (e)
+ e->f = fl;
+ return (e);
+}
+