/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include "bus-error.h"
#include "bus-locator.h"
#include "env-util.h"
#include "escape.h"
#include "systemctl-set-environment.h"
#include "systemctl-util.h"
#include "systemctl.h"

static int print_variable(const char *s) {
        const char *sep;
        _cleanup_free_ char *esc = NULL;

        sep = strchr(s, '=');
        if (!sep)
                return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN),
                                       "Invalid environment block");

        esc = shell_maybe_quote(sep + 1, SHELL_ESCAPE_POSIX);
        if (!esc)
                return log_oom();

        printf("%.*s=%s\n", (int)(sep-s), s, esc);
        return 0;
}

int show_environment(int argc, char *argv[], void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        const char *text;
        sd_bus *bus;
        int r;

        r = acquire_bus(BUS_MANAGER, &bus);
        if (r < 0)
                return r;

        (void) pager_open(arg_pager_flags);

        r = bus_get_property(bus, bus_systemd_mgr, "Environment", &error, &reply, "as");
        if (r < 0)
                return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));

        r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
        if (r < 0)
                return bus_log_parse_error(r);

        while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) {
                r = print_variable(text);
                if (r < 0)
                        return r;
        }
        if (r < 0)
                return bus_log_parse_error(r);

        r = sd_bus_message_exit_container(reply);
        if (r < 0)
                return bus_log_parse_error(r);

        return 0;
}

static void invalid_callback(const char *p, void *userdata) {
        _cleanup_free_ char *t = cescape(p);

        log_debug("Ignoring invalid environment assignment \"%s\".", strnull(t));
}

int set_environment(int argc, char *argv[], void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        const char *method;
        sd_bus *bus;
        int r;

        assert(argc > 1);
        assert(argv);

        r = acquire_bus(BUS_MANAGER, &bus);
        if (r < 0)
                return r;

        polkit_agent_open_maybe();

        method = streq(argv[0], "set-environment")
                ? "SetEnvironment"
                : "UnsetEnvironment";

        r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, method);
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_call(bus, m, 0, &error, NULL);
        if (r < 0)
                return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));

        return 0;
}

int import_environment(int argc, char *argv[], void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        sd_bus *bus;
        int r;

        r = acquire_bus(BUS_MANAGER, &bus);
        if (r < 0)
                return r;

        polkit_agent_open_maybe();

        r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "SetEnvironment");
        if (r < 0)
                return bus_log_create_error(r);

        if (argc < 2) {
                log_warning("Calling import-environment without a list of variable names is deprecated.");

                _cleanup_strv_free_ char **copy = strv_copy(environ);
                if (!copy)
                        return log_oom();

                strv_env_clean_with_callback(copy, invalid_callback, NULL);

                char **e;
                STRV_FOREACH(e, copy)
                        if (string_has_cc(*e, NULL))
                                log_notice("Environment variable $%.*s contains control characters, importing anyway.",
                                           (int) strcspn(*e, "="), *e);

                r = sd_bus_message_append_strv(m, copy);

        } else {
                char **a, **b;

                r = sd_bus_message_open_container(m, 'a', "s");
                if (r < 0)
                        return bus_log_create_error(r);

                STRV_FOREACH(a, strv_skip(argv, 1)) {

                        if (!env_name_is_valid(*a))
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Not a valid environment variable name: %s", *a);

                        bool found = false;
                        STRV_FOREACH(b, environ) {
                                const char *eq;

                                eq = startswith(*b, *a);
                                if (eq && *eq == '=') {
                                        if (string_has_cc(eq + 1, NULL))
                                                log_notice("Environment variable $%.*s contains control characters, importing anyway.",
                                                           (int) (eq - *b), *b);

                                        r = sd_bus_message_append(m, "s", *b);
                                        if (r < 0)
                                                return bus_log_create_error(r);

                                        found = true;
                                        break;
                                }
                        }

                        if (!found)
                                log_notice("Environment variable $%s not set, ignoring.", *a);
                }

                r = sd_bus_message_close_container(m);
        }
        if (r < 0)
                return bus_log_create_error(r);

        r = sd_bus_call(bus, m, 0, &error, NULL);
        if (r < 0)
                return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));

        return 0;
}
