mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Port/move some code from src/environment.cpp to src/env/mod.rs
The global variables are moved (not copied) from C++ to rust and exported as extern C integers. On the rust side they are accessed only with atomic semantics but regular int access is preserved from the C++ side (until that code is also ported).
This commit is contained in:
parent
3ab8b34b1e
commit
8a549cbb15
9 changed files with 74 additions and 20 deletions
52
fish-rust/src/env/mod.rs
vendored
52
fish-rust/src/env/mod.rs
vendored
|
@ -3,6 +3,58 @@ pub mod environment;
|
|||
mod environment_impl;
|
||||
pub mod var;
|
||||
|
||||
use crate::common::ToCString;
|
||||
pub use env_ffi::EnvStackSetResult;
|
||||
pub use environment::*;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
pub use var::*;
|
||||
|
||||
/// Limit `read` to 100 MiB (bytes, not wide chars) by default. This can be overriden with the
|
||||
/// `fish_read_limit` variable.
|
||||
pub const DEFAULT_READ_BYTE_LIMIT: usize = 100 * 1024 * 1024;
|
||||
|
||||
/// The actual `read` limit in effect, defaulting to [`DEFAULT_READ_BYTE_LIMIT`] but overridable
|
||||
/// with `$fish_read_limit`.
|
||||
#[no_mangle]
|
||||
pub static READ_BYTE_LIMIT: AtomicUsize = AtomicUsize::new(DEFAULT_READ_BYTE_LIMIT);
|
||||
|
||||
/// The curses `cur_term` TERMINAL pointer has been set up.
|
||||
#[no_mangle]
|
||||
pub static CURSES_INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// Does the terminal have the "eat new line" glitch.
|
||||
#[no_mangle]
|
||||
pub static TERM_HAS_XN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
mod ffi {
|
||||
extern "C" {
|
||||
pub fn setenv_lock(
|
||||
name: *const libc::c_char,
|
||||
value: *const libc::c_char,
|
||||
overwrite: libc::c_int,
|
||||
);
|
||||
pub fn unsetenv_lock(name: *const libc::c_char);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets an environment variable after obtaining a lock, to try and improve the safety of
|
||||
/// environment variables.
|
||||
///
|
||||
/// As values could contain non-unicode characters, they must first be converted from &wstr to a
|
||||
/// `CString` with [`crate::common::wcs2zstring()`].
|
||||
pub fn setenv_lock<S1: ToCString, S2: ToCString>(name: S1, value: S2, overwrite: bool) {
|
||||
let name = name.to_cstring();
|
||||
let value = value.to_cstring();
|
||||
unsafe {
|
||||
self::ffi::setenv_lock(name.as_ptr(), value.as_ptr(), libc::c_int::from(overwrite));
|
||||
}
|
||||
}
|
||||
|
||||
/// Unsets an environment variable after obtaining a lock, to try and improve the safety of
|
||||
/// environment variables.
|
||||
pub fn unsetenv_lock<S: ToCString>(name: S) {
|
||||
unsafe {
|
||||
let name = name.to_cstring();
|
||||
self::ffi::unsetenv_lock(name.as_ptr());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ static int read_in_chunks(int fd, wcstring &buff, bool split_null, bool do_seek)
|
|||
return STATUS_CMD_ERROR;
|
||||
}
|
||||
finished = true;
|
||||
} else if (str.size() > read_byte_limit) {
|
||||
} else if (str.size() > READ_BYTE_LIMIT) {
|
||||
exit_res = STATUS_READ_TOO_MUCH;
|
||||
finished = true;
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ static int read_one_char_at_a_time(int fd, wcstring &buff, int nchars, bool spli
|
|||
}
|
||||
}
|
||||
|
||||
if (nbytes > read_byte_limit) {
|
||||
if (nbytes > READ_BYTE_LIMIT) {
|
||||
exit_res = STATUS_READ_TOO_MUCH;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ static const struct woption long_options[] = {{L"background", required_argument,
|
|||
/// set_color builtin.
|
||||
maybe_t<int> builtin_set_color(parser_t &parser, io_streams_t &streams, const wchar_t **argv) {
|
||||
// By the time this is called we should have initialized the curses subsystem.
|
||||
assert(curses_initialized);
|
||||
assert(CURSES_INITIALIZED);
|
||||
|
||||
// Variables used for parsing the argument list.
|
||||
int argc = builtin_count_args(argv);
|
||||
|
|
|
@ -50,11 +50,6 @@
|
|||
/// At init, we read all the environment variables from this array.
|
||||
extern char **environ;
|
||||
|
||||
bool curses_initialized = false;
|
||||
|
||||
/// Does the terminal have the "eat_newline_glitch".
|
||||
bool term_has_xn = false;
|
||||
|
||||
// static
|
||||
env_var_t env_var_t::new_ffi(EnvVar *ptr) {
|
||||
assert(ptr != nullptr && "env_var_t::new_ffi called with null pointer");
|
||||
|
@ -575,6 +570,7 @@ wcstring env_get_runtime_path() {
|
|||
|
||||
static std::mutex s_setenv_lock{};
|
||||
|
||||
extern "C" {
|
||||
void setenv_lock(const char *name, const char *value, int overwrite) {
|
||||
scoped_lock locker(s_setenv_lock);
|
||||
setenv(name, value, overwrite);
|
||||
|
@ -584,6 +580,7 @@ void unsetenv_lock(const char *name) {
|
|||
scoped_lock locker(s_setenv_lock);
|
||||
unsetenv(name);
|
||||
}
|
||||
}
|
||||
|
||||
wcstring_list_ffi_t get_history_variable_text_ffi(const wcstring &fish_history_val) {
|
||||
wcstring_list_ffi_t out{};
|
||||
|
|
14
src/env.h
14
src/env.h
|
@ -43,8 +43,14 @@ struct event_list_ffi_t {
|
|||
|
||||
struct owning_null_terminated_array_t;
|
||||
|
||||
extern size_t read_byte_limit;
|
||||
extern bool curses_initialized;
|
||||
extern "C" {
|
||||
extern bool CURSES_INITIALIZED;
|
||||
|
||||
/// Does the terminal have the "eat_newline_glitch".
|
||||
extern bool TERM_HAS_XN;
|
||||
|
||||
extern size_t READ_BYTE_LIMIT;
|
||||
}
|
||||
|
||||
// Flags that may be passed as the 'mode' in env_stack_t::set() / environment_t::get().
|
||||
enum : uint16_t {
|
||||
|
@ -304,8 +310,6 @@ class env_stack_t final : public environment_t {
|
|||
|
||||
bool get_use_posix_spawn();
|
||||
|
||||
extern bool term_has_xn; // does the terminal have the "eat_newline_glitch"
|
||||
|
||||
/// Returns true if we think the terminal supports setting its title.
|
||||
bool term_supports_setting_title();
|
||||
|
||||
|
@ -315,8 +319,10 @@ wcstring env_get_runtime_path();
|
|||
/// A wrapper around setenv() and unsetenv() which use a lock.
|
||||
/// In general setenv() and getenv() are highly incompatible with threads. This makes it only
|
||||
/// slightly safer.
|
||||
extern "C" {
|
||||
void setenv_lock(const char *name, const char *value, int overwrite);
|
||||
void unsetenv_lock(const char *name);
|
||||
}
|
||||
|
||||
/// Returns the originally inherited variables and their values.
|
||||
/// This is a simple key->value map and not e.g. cut into paths.
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
// Limit `read` to 100 MiB (bytes not wide chars) by default. This can be overridden by the
|
||||
// fish_read_limit variable.
|
||||
constexpr size_t DEFAULT_READ_BYTE_LIMIT = 100 * 1024 * 1024;
|
||||
size_t read_byte_limit = DEFAULT_READ_BYTE_LIMIT;
|
||||
|
||||
/// List of all locale environment variable names that might trigger (re)initializing the locale
|
||||
/// subsystem. These are only the variables we're possibly interested in.
|
||||
|
@ -298,10 +297,10 @@ static void handle_read_limit_change(const environment_t &vars) {
|
|||
if (errno) {
|
||||
FLOGF(warning, "Ignoring fish_read_limit since it is not valid");
|
||||
} else {
|
||||
read_byte_limit = limit;
|
||||
READ_BYTE_LIMIT = limit;
|
||||
}
|
||||
} else {
|
||||
read_byte_limit = DEFAULT_READ_BYTE_LIMIT;
|
||||
READ_BYTE_LIMIT = DEFAULT_READ_BYTE_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -617,12 +616,12 @@ static void init_curses(const environment_t &vars) {
|
|||
apply_term_hacks(vars);
|
||||
|
||||
can_set_term_title = does_term_support_setting_title(vars);
|
||||
term_has_xn =
|
||||
TERM_HAS_XN =
|
||||
tigetflag(const_cast<char *>("xenl")) == 1; // does terminal have the eat_newline_glitch
|
||||
update_fish_color_support(vars);
|
||||
// Invalidate the cached escape sequences since they may no longer be valid.
|
||||
layout_cache_t::shared.clear();
|
||||
curses_initialized = true;
|
||||
CURSES_INITIALIZED = true;
|
||||
}
|
||||
|
||||
static constexpr const char *utf8_locales[] = {
|
||||
|
|
|
@ -1195,7 +1195,7 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser,
|
|||
auto &ld = parser.libdata();
|
||||
|
||||
scoped_push<bool> is_subshell(&ld.is_subshell, true);
|
||||
scoped_push<size_t> read_limit(&ld.read_limit, is_subcmd ? read_byte_limit : 0);
|
||||
scoped_push<size_t> read_limit(&ld.read_limit, is_subcmd ? READ_BYTE_LIMIT : 0);
|
||||
|
||||
auto prev_statuses = parser.get_last_statuses();
|
||||
const cleanup_t put_back([&] {
|
||||
|
|
|
@ -854,7 +854,7 @@ std::shared_ptr<const mapping_list_t> input_mapping_set_t::all_mappings() {
|
|||
|
||||
/// Create a list of terminfo mappings.
|
||||
static std::vector<terminfo_mapping_t> create_input_terminfo() {
|
||||
assert(curses_initialized);
|
||||
assert(CURSES_INITIALIZED);
|
||||
if (!cur_term) return {}; // setupterm() failed so we can't referency any key definitions
|
||||
|
||||
#define TERMINFO_ADD(key) \
|
||||
|
|
|
@ -1298,7 +1298,7 @@ void screen_t::reset_abandoning_line(int screen_width) {
|
|||
const_cast<char *>(exit_attribute_mode)))); // normal text ANSI escape sequence
|
||||
}
|
||||
|
||||
int newline_glitch_width = term_has_xn ? 0 : 1;
|
||||
int newline_glitch_width = TERM_HAS_XN ? 0 : 1;
|
||||
abandon_line_string.append(screen_width - non_space_width - newline_glitch_width, L' ');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue