|  | /* | 
|  | * Copyright (c) 2023, Meta | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include "posix_shell.h" | 
|  |  | 
|  | #include <ctype.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include <zephyr/shell/shell.h> | 
|  |  | 
|  | #define HELP_ENV_GET   "[NAME]" | 
|  | #define HELP_ENV_SET   "NAME VALUE | NAME=VALUE" | 
|  | #define HELP_ENV_UNSET "NAME.." | 
|  |  | 
|  | static int cmd_env_get(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | const char *name; | 
|  | const char *value; | 
|  |  | 
|  | switch (argc) { | 
|  | case 1: { | 
|  | extern char **environ; | 
|  | /* list all environment variables */ | 
|  | if (environ != NULL) { | 
|  | for (char **envp = environ; *envp != NULL; ++envp) { | 
|  | shell_print(sh, "%s", *envp); | 
|  | } | 
|  | } | 
|  | } break; | 
|  | case 2: | 
|  | /* list a specific environment variable */ | 
|  | name = argv[1]; | 
|  | value = getenv(name); | 
|  | if (value != NULL) { | 
|  | shell_print(sh, "%s", value); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | return EXIT_FAILURE; | 
|  | } | 
|  |  | 
|  | return EXIT_SUCCESS; | 
|  | } | 
|  |  | 
|  | static bool is_shell_env_name(const char *name) | 
|  | { | 
|  | char c; | 
|  |  | 
|  | if (name == NULL || name[0] == '\0') { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | for (size_t i = 0, N = strlen(name); i < N; ++i) { | 
|  | c = name[i]; | 
|  |  | 
|  | if (c == '_') { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (isalpha(c)) { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (i > 0 && isdigit(c)) { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static int cmd_env_set(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | int ret; | 
|  | char *value; | 
|  | const char *name; | 
|  |  | 
|  | switch (argc) { | 
|  | case 2: | 
|  | name = argv[1]; | 
|  | value = strchr(argv[1], '='); | 
|  | if (value != NULL) { | 
|  | *value = '\0'; | 
|  | ++value; | 
|  | } | 
|  | break; | 
|  | case 3: | 
|  | name = argv[1]; | 
|  | value = argv[2]; | 
|  | break; | 
|  | default: | 
|  | return EXIT_FAILURE; | 
|  | } | 
|  |  | 
|  | /* silently drop "poorly conditioned" environment variables */ | 
|  | if (!is_shell_env_name(name)) { | 
|  | shell_print(sh, "bad name"); | 
|  | return EXIT_SUCCESS; | 
|  | } | 
|  |  | 
|  | ret = setenv(name, value, 1); | 
|  | if (ret == -1) { | 
|  | return EXIT_FAILURE; | 
|  | } | 
|  |  | 
|  | return EXIT_SUCCESS; | 
|  | } | 
|  |  | 
|  | static int cmd_env_unset(const struct shell *sh, size_t argc, char **argv) | 
|  | { | 
|  | for (--argc, ++argv; argc > 0; --argc, ++argv) { | 
|  | (void)unsetenv(argv[0]); | 
|  | } | 
|  |  | 
|  | return EXIT_SUCCESS; | 
|  | } | 
|  |  | 
|  | SHELL_STATIC_SUBCMD_SET_CREATE(sub_env, SHELL_CMD(set, NULL, HELP_ENV_SET, cmd_env_set), | 
|  | SHELL_CMD(get, NULL, HELP_ENV_GET, cmd_env_get), | 
|  | SHELL_CMD(unset, NULL, HELP_ENV_UNSET, cmd_env_unset), | 
|  | SHELL_SUBCMD_SET_END /* Array terminated. */ | 
|  | ); | 
|  |  | 
|  | POSIX_CMD_ADD(env, &sub_env, "Print system information", NULL, 1, 255); |