+/* --- @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 (!f || ~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);
+}
+
+/* --- @bc__addGroups@ --- *
+ *
+ * Arguments: @gid_t *g@ = pointer to a group array
+ * @int *png@ = pointer to number of entries in the array
+ * @const gid_t *a@ = pointer to groups to add
+ * @int na@ = number of groups to add
+ *
+ * Returns: Zero if it was OK, nonzero if we should stop now.
+ *
+ * Use: Adds groups to a groups array.
+ */
+
+static int bc__addGroups(gid_t *g, int *png, const gid_t *a, int na)
+{
+ int i, j;
+ int ng = *png;
+
+ for (i = 0; i < na; i++) {
+
+ /* --- Ensure this group isn't already in the list --- */
+
+ for (j = 0; j < ng; j++) {
+ if (a[i] == g[j])
+ goto next_group;
+ }
+
+ /* --- See if there's room for more --- */
+
+ if (ng >= NGROUPS_MAX) {
+ moan("too many groups (system limit exceeded) -- some have been lost");
+ *png = ng;
+ return (-1);
+ }
+
+ /* --- Add the group --- */
+
+ g[ng++] = a[i];
+ next_group:;
+ }
+
+ *png = ng;
+ return (0);
+}
+