+
+/*
+ * Set an environment variable specified by the user.
+ */
+static int
+user_setenv(char **argv)
+{
+ char *arg = argv[0];
+ char *eqp;
+ struct userenv *uep, **insp;
+
+ if ((eqp = strchr(arg, '=')) == NULL) {
+ option_error("missing = in name=value: %s", arg);
+ return 0;
+ }
+ if (eqp == arg) {
+ option_error("missing variable name: %s", arg);
+ return 0;
+ }
+ for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
+ int nlen = strlen(uep->ue_name);
+ if (nlen == (eqp - arg) &&
+ strncmp(arg, uep->ue_name, nlen) == 0)
+ break;
+ }
+ /* Ignore attempts by unprivileged users to override privileged sources */
+ if (uep != NULL && !privileged_option && uep->ue_priv)
+ return 1;
+ /* The name never changes, so allocate it with the structure */
+ if (uep == NULL) {
+ uep = malloc(sizeof (*uep) + (eqp-arg));
+ strncpy(uep->ue_name, arg, eqp-arg);
+ uep->ue_name[eqp-arg] = '\0';
+ uep->ue_next = NULL;
+ insp = &userenv_list;
+ while (*insp != NULL)
+ insp = &(*insp)->ue_next;
+ *insp = uep;
+ } else {
+ struct userenv *uep2;
+ for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
+ if (uep2 != uep && !uep2->ue_isset)
+ break;
+ }
+ if (uep2 == NULL && !uep->ue_isset)
+ find_option("unset")->flags |= OPT_NOPRINT;
+ free(uep->ue_value);
+ }
+ uep->ue_isset = 1;
+ uep->ue_priv = privileged_option;
+ uep->ue_source = option_source;
+ uep->ue_value = strdup(eqp + 1);
+ curopt->flags &= ~OPT_NOPRINT;
+ return 1;
+}
+
+static void
+user_setprint(option_t *opt, printer_func printer, void *arg)
+{
+ struct userenv *uep, *uepnext;
+
+ uepnext = userenv_list;
+ while (uepnext != NULL && !uepnext->ue_isset)
+ uepnext = uepnext->ue_next;
+ while ((uep = uepnext) != NULL) {
+ uepnext = uep->ue_next;
+ while (uepnext != NULL && !uepnext->ue_isset)
+ uepnext = uepnext->ue_next;
+ (*printer)(arg, "%s=%s", uep->ue_name, uep->ue_value);
+ if (uepnext != NULL)
+ (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
+ else
+ opt->source = uep->ue_source;
+ }
+}
+
+static int
+user_unsetenv(char **argv)
+{
+ struct userenv *uep, **insp;
+ char *arg = argv[0];
+
+ if (strchr(arg, '=') != NULL) {
+ option_error("unexpected = in name: %s", arg);
+ return 0;
+ }
+ if (*arg == '\0') {
+ option_error("missing variable name for unset");
+ return 0;
+ }
+ for (uep = userenv_list; uep != NULL; uep = uep->ue_next) {
+ if (strcmp(arg, uep->ue_name) == 0)
+ break;
+ }
+ /* Ignore attempts by unprivileged users to override privileged sources */
+ if (uep != NULL && !privileged_option && uep->ue_priv)
+ return 1;
+ /* The name never changes, so allocate it with the structure */
+ if (uep == NULL) {
+ uep = malloc(sizeof (*uep) + strlen(arg));
+ strcpy(uep->ue_name, arg);
+ uep->ue_next = NULL;
+ insp = &userenv_list;
+ while (*insp != NULL)
+ insp = &(*insp)->ue_next;
+ *insp = uep;
+ } else {
+ struct userenv *uep2;
+ for (uep2 = userenv_list; uep2 != NULL; uep2 = uep2->ue_next) {
+ if (uep2 != uep && uep2->ue_isset)
+ break;
+ }
+ if (uep2 == NULL && uep->ue_isset)
+ find_option("set")->flags |= OPT_NOPRINT;
+ free(uep->ue_value);
+ }
+ uep->ue_isset = 0;
+ uep->ue_priv = privileged_option;
+ uep->ue_source = option_source;
+ uep->ue_value = NULL;
+ curopt->flags &= ~OPT_NOPRINT;
+ return 1;
+}
+
+static void
+user_unsetprint(option_t *opt, printer_func printer, void *arg)
+{
+ struct userenv *uep, *uepnext;
+
+ uepnext = userenv_list;
+ while (uepnext != NULL && uepnext->ue_isset)
+ uepnext = uepnext->ue_next;
+ while ((uep = uepnext) != NULL) {
+ uepnext = uep->ue_next;
+ while (uepnext != NULL && uepnext->ue_isset)
+ uepnext = uepnext->ue_next;
+ (*printer)(arg, "%s", uep->ue_name);
+ if (uepnext != NULL)
+ (*printer)(arg, "\t\t# (from %s)\n%s ", uep->ue_source, opt->name);
+ else
+ opt->source = uep->ue_source;
+ }
+}