void env_destroy() { env_universal_destroy(); while (&top->env != global) { env_pop(); } env_read_only.clear(); env_electric.clear(); var_table_t::iterator iter; for (iter = global->begin(); iter != global->end(); ++iter) { const var_entry_t &entry = iter->second; if (entry.exportv) { mark_changed_exported(); break; } } delete top; }
wcstring_list_t env_get_names(int flags) { scoped_lock lock(env_lock); wcstring_list_t result; std::set<wcstring> names; int show_local = flags & ENV_LOCAL; int show_global = flags & ENV_GLOBAL; int show_universal = flags & ENV_UNIVERSAL; env_node_t *n=top; const bool show_exported = (flags & ENV_EXPORT) || !(flags & ENV_UNEXPORT); const bool show_unexported = (flags & ENV_UNEXPORT) || !(flags & ENV_EXPORT); if (!show_local && !show_global && !show_universal) { show_local =show_universal = show_global=1; } if (show_local) { while (n) { if (n == global_env) break; add_key_to_string_set(n->env, &names, show_exported, show_unexported); if (n->new_scope) break; else n = n->next; } } if (show_global) { add_key_to_string_set(global_env->env, &names, show_exported, show_unexported); if (show_unexported) { result.insert(result.end(), env_electric.begin(), env_electric.end()); } if (show_exported) { result.push_back(L"COLUMNS"); result.push_back(L"LINES"); } } if (show_universal && uvars()) { const wcstring_list_t uni_list = uvars()->get_names(show_exported, show_unexported); names.insert(uni_list.begin(), uni_list.end()); } result.insert(result.end(), names.begin(), names.end()); return result; }
void env_init(const struct config_paths_t *paths /* or NULL */) { /* env_read_only variables can not be altered directly by the user */ const wchar_t * const ro_keys[] = { L"status", L"history", L"version", L"_", L"LINES", L"COLUMNS", L"PWD", //L"SHLVL", // will be inserted a bit lower down L"FISH_VERSION", }; for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) { env_read_only.insert(ro_keys[i]); } /* Names of all dynamically calculated variables */ env_electric.insert(L"history"); env_electric.insert(L"status"); env_electric.insert(L"umask"); env_electric.insert(L"COLUMNS"); env_electric.insert(L"LINES"); top = new env_node_t; global_env = top; global = &top->env; /* Now the environemnt variable handling is set up, the next step is to insert valid data */ /* Import environment variables */ for (char **p = (environ ? environ : __environ); p && *p; p++) { const wcstring key_and_val = str2wcstring(*p); //like foo=bar size_t eql = key_and_val.find(L'='); if (eql == wcstring::npos) { // no equals found if (is_read_only(key_and_val) || is_electric(key_and_val)) continue; env_set(key_and_val, L"", ENV_EXPORT | ENV_GLOBAL); } else { wcstring key = key_and_val.substr(0, eql); if (is_read_only(key) || is_electric(key)) continue; wcstring val = key_and_val.substr(eql + 1); if (variable_is_colon_delimited_array(key)) { std::replace(val.begin(), val.end(), L':', ARRAY_SEP); } env_set(key, val.c_str(), ENV_EXPORT | ENV_GLOBAL); } } /* Set the given paths in the environment, if we have any */ if (paths != NULL) { env_set(FISH_DATADIR_VAR, paths->data.c_str(), ENV_GLOBAL); env_set(FISH_SYSCONFDIR_VAR, paths->sysconf.c_str(), ENV_GLOBAL); env_set(FISH_HELPDIR_VAR, paths->doc.c_str(), ENV_GLOBAL); env_set(FISH_BIN_DIR, paths->bin.c_str(), ENV_GLOBAL); } /* Set up the PATH variable */ setup_path(); /* Set up the USER variable */ if (env_get_string(L"USER").missing_or_empty()) { const struct passwd *pw = getpwuid(getuid()); if (pw && pw->pw_name) { const wcstring uname = str2wcstring(pw->pw_name); env_set(L"USER", uname.c_str(), ENV_GLOBAL | ENV_EXPORT); } } /* Set up the version variables */ wcstring version = str2wcstring(get_fish_version()); env_set(L"version", version.c_str(), ENV_GLOBAL); env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); /* Set up SHLVL variable */ const env_var_t shlvl_str = env_get_string(L"SHLVL"); wcstring nshlvl_str = L"1"; if (! shlvl_str.missing()) { wchar_t *end; long shlvl_i = wcstol(shlvl_str.c_str(), &end, 10); while (iswspace(*end)) ++end; /* skip trailing whitespace */ if (shlvl_i >= 0 && *end == '\0') { nshlvl_str = to_string<long>(shlvl_i + 1); } } env_set(L"SHLVL", nshlvl_str.c_str(), ENV_GLOBAL | ENV_EXPORT); env_read_only.insert(L"SHLVL"); /* Set up the HOME variable */ if (env_get_string(L"HOME").missing_or_empty()) { const env_var_t unam = env_get_string(L"USER"); char *unam_narrow = wcs2str(unam.c_str()); struct passwd *pw = getpwnam(unam_narrow); if (pw->pw_dir != NULL) { const wcstring dir = str2wcstring(pw->pw_dir); env_set(L"HOME", dir.c_str(), ENV_GLOBAL | ENV_EXPORT); } free(unam_narrow); } /* Set PWD */ env_set_pwd(); /* Set up universal variables. The empty string means to use the deafult path. */ assert(s_universal_variables == NULL); s_universal_variables = new env_universal_t(L""); s_universal_variables->load(); /* Set g_log_forks */ env_var_t log_forks = env_get_string(L"fish_log_forks"); g_log_forks = ! log_forks.missing_or_empty() && from_string<bool>(log_forks); /* Set g_use_posix_spawn. Default to true. */ env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn"); g_use_posix_spawn = (use_posix_spawn.missing_or_empty() ? true : from_string<bool>(use_posix_spawn)); /* Set fish_bind_mode to "default" */ env_set(FISH_BIND_MODE_VAR, DEFAULT_BIND_MODE, ENV_GLOBAL); /* Now that the global scope is fully initialized, add a toplevel local scope. This same local scope will persist throughout the lifetime of the fish process, and it will ensure that `set -l` commands run at the command-line don't affect the global scope. */ env_push(false); }
static bool is_electric(const wcstring &key) { return env_electric.find(key.c_str()) != env_electric.end(); }
static bool is_read_only(const wcstring &key) { return env_read_only.find(key.c_str()) != env_read_only.end(); }
void env_init(const struct config_paths_t *paths /* or NULL */) { /* env_read_only variables can not be altered directly by the user */ const wchar_t * const ro_keys[] = { L"status", L"history", L"version", L"_", L"LINES", L"COLUMNS", L"PWD", L"SHLVL", L"FISH_VERSION", }; for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) { env_read_only.insert(ro_keys[i]); } /* HOME and USER should be writeable by root, since this can be a convenient way to install software. */ if (getuid() != 0) { env_read_only.insert(L"HOME"); env_read_only.insert(L"USER"); } /* Names of all dynamically calculated variables */ env_electric.insert(L"history"); env_electric.insert(L"status"); env_electric.insert(L"umask"); top = new env_node_t; global_env = top; global = &top->env; /* Now the environemnt variable handling is set up, the next step is to insert valid data */ /* Import environment variables */ for (char **p = (environ ? environ : __environ); p && *p; p++) { const wcstring key_and_val = str2wcstring(*p); //like foo=bar size_t eql = key_and_val.find(L'='); if (eql == wcstring::npos) { // no equals found env_set(key_and_val, L"", ENV_EXPORT); } else { wcstring key = key_and_val.substr(0, eql); wcstring val = key_and_val.substr(eql + 1); if (variable_can_be_array(val)) { std::replace(val.begin(), val.end(), L':', ARRAY_SEP); } env_set(key, val.c_str(), ENV_EXPORT | ENV_GLOBAL); } } /* Set the given paths in the environment, if we have any */ if (paths != NULL) { env_set(FISH_DATADIR_VAR, paths->data.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_SYSCONFDIR_VAR, paths->sysconf.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_HELPDIR_VAR, paths->doc.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_BIN_DIR, paths->bin.c_str(), ENV_GLOBAL | ENV_EXPORT); } /* Set up the PATH variable */ setup_path(); /* Set up the USER variable */ const struct passwd *pw = getpwuid(getuid()); if (pw && pw->pw_name) { const wcstring uname = str2wcstring(pw->pw_name); env_set(L"USER", uname.c_str(), ENV_GLOBAL | ENV_EXPORT); } /* Set up the version variables */ wcstring version = str2wcstring(FISH_BUILD_VERSION); env_set(L"version", version.c_str(), ENV_GLOBAL); env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL); const env_var_t fishd_dir_wstr = env_get_string(L"FISHD_SOCKET_DIR"); const env_var_t user_dir_wstr = env_get_string(L"USER"); wchar_t * fishd_dir = fishd_dir_wstr.missing()?NULL:const_cast<wchar_t*>(fishd_dir_wstr.c_str()); wchar_t * user_dir = user_dir_wstr.missing()?NULL:const_cast<wchar_t*>(user_dir_wstr.c_str()); env_universal_init(fishd_dir , user_dir , &start_fishd, &universal_callback); /* Set up SHLVL variable */ const env_var_t shlvl_str = env_get_string(L"SHLVL"); wcstring nshlvl_str = L"1"; if (! shlvl_str.missing()) { long shlvl_i = wcstol(shlvl_str.c_str(), NULL, 10); if (shlvl_i >= 0) { nshlvl_str = to_string<long>(shlvl_i + 1); } } env_set(L"SHLVL", nshlvl_str.c_str(), ENV_GLOBAL | ENV_EXPORT); /* Set correct defaults for e.g. USER and HOME variables */ env_set_defaults(); /* Set g_log_forks */ env_var_t log_forks = env_get_string(L"fish_log_forks"); g_log_forks = ! log_forks.missing_or_empty() && from_string<bool>(log_forks); /* Set g_use_posix_spawn. Default to true. */ env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn"); g_use_posix_spawn = (use_posix_spawn.missing_or_empty() ? true : from_string<bool>(use_posix_spawn)); }