diff --git a/src/fish.cpp b/src/fish.cpp index 45776143f..a6520edc0 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -77,6 +77,8 @@ class fish_cmd_opts_t { bool is_login{false}; /// Whether this is an interactive session. bool is_interactive_session{false}; + /// Whether to enable private mode. + bool enable_private_mode{false}; }; /// If we are doing profiling, the filename to output to. @@ -209,7 +211,7 @@ static struct config_paths_t determine_config_directory_paths(const char *argv0) } // Source the file config.fish in the given directory. -static void source_config_in_directory(const wcstring &dir) { +static void source_config_in_directory(parser_t &parser, const wcstring &dir) { // If the config.fish file doesn't exist or isn't readable silently return. Fish versions up // thru 2.2.0 would instead try to source the file with stderr redirected to /dev/null to deal // with that possibility. @@ -228,33 +230,30 @@ static void source_config_in_directory(const wcstring &dir) { FLOGF(config, L"sourcing %ls", escaped_pathname.c_str()); const wcstring cmd = L"builtin source " + escaped_pathname; - parser_t &parser = parser_t::principal_parser(); set_is_within_fish_initialization(true); parser.eval(cmd, io_chain_t()); set_is_within_fish_initialization(false); } /// Parse init files. exec_path is the path of fish executable as determined by argv[0]. -static int read_init(const struct config_paths_t &paths) { - source_config_in_directory(paths.data); - source_config_in_directory(paths.sysconf); +static int read_init(parser_t &parser, const struct config_paths_t &paths) { + source_config_in_directory(parser, paths.data); + source_config_in_directory(parser, paths.sysconf); // We need to get the configuration directory before we can source the user configuration file. // If path_get_config returns false then we have no configuration directory and no custom config // to load. wcstring config_dir; if (path_get_config(config_dir)) { - source_config_in_directory(config_dir); + source_config_in_directory(parser, config_dir); } return 1; } -int run_command_list(std::vector *cmds, const io_chain_t &io) { - parser_t &parser = parser_t::principal_parser(); - +int run_command_list(parser_t &parser, std::vector *cmds, const io_chain_t &io) { for (const auto &cmd : *cmds) { - const wcstring cmd_wcs = str2wcstring(cmd); + wcstring cmd_wcs = str2wcstring(cmd); parser.eval(cmd_wcs, io); } @@ -357,7 +356,7 @@ static int fish_parse_opt(int argc, char **argv, fish_cmd_opts_t *opts) { break; } case 'P': { - start_private_mode(); + opts->enable_private_mode = true; break; } case 'v': { @@ -447,6 +446,7 @@ int main(int argc, char **argv) { if (opts.is_login) mark_login(); if (opts.no_exec) mark_no_exec(); if (opts.is_interactive_session) set_interactive_session(session_interactivity_t::explicit_); + if (opts.enable_private_mode) start_private_mode(env_stack_t::globals()); // Only save (and therefore restore) the fg process group if we are interactive. See issues // #197 and #1002. @@ -456,6 +456,7 @@ int main(int argc, char **argv) { const struct config_paths_t paths = determine_config_directory_paths(argv[0]); env_init(&paths); + // Set features early in case other initialization depends on them. // Start with the ones set in the environment, then those set on the command line (so the // command line takes precedence). @@ -472,13 +473,13 @@ int main(int argc, char **argv) { parser_t &parser = parser_t::principal_parser(); - if (read_init(paths)) { + if (read_init(parser, paths)) { // Stomp the exit status of any initialization commands (issue #635). parser.set_last_statuses(statuses_t::just(STATUS_CMD_OK)); // Run post-config commands specified as arguments, if any. if (!opts.postconfig_cmds.empty()) { - res = run_command_list(&opts.postconfig_cmds, {}); + res = run_command_list(parser, &opts.postconfig_cmds, {}); } if (!opts.batch_cmds.empty()) { @@ -488,7 +489,7 @@ int main(int argc, char **argv) { fish_xdm_login_hack_hack_hack_hack(&opts.batch_cmds, argc - my_optind, argv + my_optind); } - res = run_command_list(&opts.batch_cmds, {}); + res = run_command_list(parser, &opts.batch_cmds, {}); reader_set_end_loop(false); } else if (my_optind == argc) { // Implicitly interactive mode. diff --git a/src/history.cpp b/src/history.cpp index d9e1600bf..311c821d4 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1437,13 +1437,12 @@ history_t &history_t::history_with_name(const wcstring &name) { return *hist; } -static std::atomic private_mode{false}; +static relaxed_atomic_bool_t private_mode{false}; -void start_private_mode() { - private_mode.store(true); - auto &vars = parser_t::principal_parser().vars(); +void start_private_mode(env_stack_t &vars) { + private_mode = true; vars.set_one(L"fish_history", ENV_GLOBAL, L""); vars.set_one(L"fish_private_mode", ENV_GLOBAL, L"1"); } -bool in_private_mode() { return private_mode.load(); } +bool in_private_mode() { return private_mode; } diff --git a/src/history.h b/src/history.h index 66aa52aea..1c1e746b5 100644 --- a/src/history.h +++ b/src/history.h @@ -22,6 +22,7 @@ #include "wutil.h" // IWYU pragma: keep struct io_streams_t; +class env_stack_t; class environment_t; // Fish supports multiple shells writing to history at once. Here is its strategy: @@ -291,7 +292,7 @@ path_list_t valid_paths(const path_list_t &paths, const wcstring &working_direct bool all_paths_are_valid(const path_list_t &paths, const wcstring &working_directory); /// Sets private mode on. Once in private mode, it cannot be turned off. -void start_private_mode(); +void start_private_mode(env_stack_t &vars); /// Queries private mode status. bool in_private_mode();