2017-08-05 22:08:39 +00:00
|
|
|
// Prototypes for functions for manipulating fish script variables.
|
2005-10-04 15:11:39 +00:00
|
|
|
#ifndef FISH_ENV_H
|
|
|
|
#define FISH_ENV_H
|
|
|
|
|
2016-04-29 01:26:46 +00:00
|
|
|
#include <stddef.h>
|
2015-07-25 15:14:25 +00:00
|
|
|
#include <stdint.h>
|
2017-02-14 04:37:27 +00:00
|
|
|
|
2022-06-21 16:08:09 +00:00
|
|
|
#include <map>
|
2016-04-21 06:00:54 +00:00
|
|
|
#include <memory>
|
2016-04-29 01:26:46 +00:00
|
|
|
#include <string>
|
2020-06-25 05:46:32 +00:00
|
|
|
#include <unordered_map>
|
2022-08-21 06:14:48 +00:00
|
|
|
#include <utility>
|
2022-08-21 21:51:33 +00:00
|
|
|
#include <vector>
|
2005-10-04 15:11:39 +00:00
|
|
|
|
2011-12-27 03:18:46 +00:00
|
|
|
#include "common.h"
|
2023-02-11 20:31:08 +00:00
|
|
|
#include "cxx.h"
|
2017-08-28 07:25:41 +00:00
|
|
|
#include "maybe.h"
|
2023-04-30 02:58:45 +00:00
|
|
|
#include "wutil.h"
|
|
|
|
|
2023-04-29 19:43:41 +00:00
|
|
|
struct event_list_ffi_t;
|
|
|
|
|
2023-04-30 02:58:45 +00:00
|
|
|
#if INCLUDE_RUST_HEADERS
|
|
|
|
#include "env/env_ffi.rs.h"
|
|
|
|
#else
|
|
|
|
struct EnvVar;
|
2023-04-29 19:43:41 +00:00
|
|
|
struct EnvNull;
|
|
|
|
struct EnvStackRef;
|
2023-04-30 02:58:45 +00:00
|
|
|
#endif
|
2022-08-21 06:14:48 +00:00
|
|
|
|
2023-04-30 02:58:51 +00:00
|
|
|
/// FFI helper for events.
|
|
|
|
struct Event;
|
|
|
|
struct event_list_ffi_t {
|
|
|
|
event_list_ffi_t(const event_list_ffi_t &) = delete;
|
|
|
|
event_list_ffi_t &operator=(const event_list_ffi_t &) = delete;
|
|
|
|
event_list_ffi_t();
|
|
|
|
#if INCLUDE_RUST_HEADERS
|
|
|
|
std::vector<rust::Box<Event>> events{};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Append an Event pointer, which came from Box::into_raw().
|
|
|
|
void push(void *event);
|
|
|
|
};
|
|
|
|
|
2023-04-23 19:39:34 +00:00
|
|
|
struct owning_null_terminated_array_t;
|
2005-10-04 15:11:39 +00:00
|
|
|
|
2023-05-16 19:35:14 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-02-08 01:21:35 +00:00
|
|
|
|
2018-09-25 03:59:55 +00:00
|
|
|
// Flags that may be passed as the 'mode' in env_stack_t::set() / environment_t::get().
|
2022-10-15 20:15:04 +00:00
|
|
|
enum : uint16_t {
|
2018-09-25 04:17:05 +00:00
|
|
|
/// Default mode. Used with `env_stack_t::get()` to indicate the caller doesn't care what scope
|
|
|
|
/// the var is in or whether it is exported or unexported.
|
2014-07-14 00:30:48 +00:00
|
|
|
ENV_DEFAULT = 0,
|
2016-04-29 01:26:46 +00:00
|
|
|
/// Flag for local (to the current block) variable.
|
2017-08-05 22:08:39 +00:00
|
|
|
ENV_LOCAL = 1 << 0,
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_FUNCTION = 1 << 1,
|
2017-08-05 22:08:39 +00:00
|
|
|
/// Flag for global variable.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_GLOBAL = 1 << 2,
|
2017-08-05 22:08:39 +00:00
|
|
|
/// Flag for universal variable.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_UNIVERSAL = 1 << 3,
|
2016-04-29 01:26:46 +00:00
|
|
|
/// Flag for exported (to commands) variable.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_EXPORT = 1 << 4,
|
2016-04-29 01:26:46 +00:00
|
|
|
/// Flag for unexported variable.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_UNEXPORT = 1 << 5,
|
2018-09-10 01:32:15 +00:00
|
|
|
/// Flag to mark a variable as a path variable.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_PATHVAR = 1 << 6,
|
2018-09-10 01:32:15 +00:00
|
|
|
/// Flag to unmark a variable as a path variable.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_UNPATHVAR = 1 << 7,
|
2016-04-29 01:26:46 +00:00
|
|
|
/// Flag for variable update request from the user. All variable changes that are made directly
|
2017-08-05 22:08:39 +00:00
|
|
|
/// by the user, such as those from the `read` and `set` builtin must have this flag set. It
|
|
|
|
/// serves one purpose: to indicate that an error should be returned if the user is attempting
|
|
|
|
/// to modify a var that should not be modified by direct user action; e.g., a read-only var.
|
Add `set --function` (#8145)
* Add `set --function`
This makes the function's scope available, even inside of blocks. Outside of blocks it's the toplevel local scope.
This removes the need to declare variables locally before use, and will probably end up being the main way variables get set.
E.g.:
```fish
set -l thing
if condition
set thing one
else
set thing two
end
```
could be written as
```fish
if condition
set -f thing one
else
set -f thing two
end
```
Note: Many scripts shipped with fish use workarounds like `and`/`or`
instead of `if`, so it isn't easy to find good examples.
Also, if there isn't an else-branch in that above, just with
```fish
if condition
set -f thing one
end
```
that means something different from setting it before! Now, if
`condition` isn't true, it would use a global (or universal) variable of
te same name!
Some more interesting parts:
Because it *is* a local scope, setting a variable `-f` and
`-l` in the toplevel of a function ends up the same:
```fish
function foo2
set -l foo bar
set -f foo baz # modifies the *same* variable!
end
```
but setting it locally inside a block creates a new local variable
that shadows the function-scoped variable:
```fish
function foo3
set -f foo bar
begin
set -l foo banana
# $foo is banana
end
# $foo is bar again
end
```
This is how local variables already work. "Local" is actually "block-scoped".
Also `set --show` will only show the closest local scope, so it won't
show a shadowed function-level variable. Again, this is how local
variables already work, and could be done as a separate change.
As a fun tidbit, functions with --no-scope-shadowing can now use this to set variables in the calling function. That's probably okay given that it's already an escape hatch (but to be clear: if it turns out to problematic I reserve the right to remove it).
Fixes #565
2021-08-01 18:08:12 +00:00
|
|
|
ENV_USER = 1 << 8,
|
2014-07-14 00:30:48 +00:00
|
|
|
};
|
2022-10-15 20:15:04 +00:00
|
|
|
using env_mode_flags_t = uint16_t;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2018-09-25 03:59:55 +00:00
|
|
|
/// Return values for `env_stack_t::set()`.
|
2018-04-01 03:12:52 +00:00
|
|
|
enum { ENV_OK, ENV_PERM, ENV_SCOPE, ENV_INVALID, ENV_NOT_FOUND };
|
2016-04-29 01:26:46 +00:00
|
|
|
|
|
|
|
/// A struct of configuration directories, determined in main() that fish will optionally pass to
|
|
|
|
/// env_init.
|
|
|
|
struct config_paths_t {
|
2017-08-05 22:08:39 +00:00
|
|
|
wcstring data; // e.g., /usr/local/share
|
|
|
|
wcstring sysconf; // e.g., /usr/local/etc
|
|
|
|
wcstring doc; // e.g., /usr/local/share/doc/fish
|
|
|
|
wcstring bin; // e.g., /usr/local/bin
|
2012-07-18 17:50:38 +00:00
|
|
|
};
|
2006-04-10 15:36:26 +00:00
|
|
|
|
2019-05-12 21:00:44 +00:00
|
|
|
/// A collection of status and pipestatus.
|
|
|
|
struct statuses_t {
|
|
|
|
/// Status of the last job to exit.
|
|
|
|
int status{0};
|
|
|
|
|
2020-03-31 18:27:17 +00:00
|
|
|
/// Signal from the most recent process in the last job that was terminated by a signal.
|
|
|
|
/// 0 if all processes exited normally.
|
|
|
|
int kill_signal{0};
|
|
|
|
|
2019-05-12 21:00:44 +00:00
|
|
|
/// Pipestatus value.
|
|
|
|
std::vector<int> pipestatus{};
|
|
|
|
|
|
|
|
/// Return a statuses for a single process status.
|
|
|
|
static statuses_t just(int s) {
|
|
|
|
statuses_t result{};
|
|
|
|
result.status = s;
|
|
|
|
result.pipestatus.push_back(s);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-04-29 01:26:46 +00:00
|
|
|
/// Initialize environment variable data.
|
2021-11-08 19:36:01 +00:00
|
|
|
void env_init(const struct config_paths_t *paths = nullptr, bool do_uvars = true,
|
|
|
|
bool default_paths = false);
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2017-02-16 04:09:26 +00:00
|
|
|
/// Various things we need to initialize at run-time that don't really fit any of the other init
|
|
|
|
/// routines.
|
|
|
|
void misc_init();
|
|
|
|
|
2019-03-25 07:41:04 +00:00
|
|
|
/// env_var_t is an immutable value-type data structure representing the value of an environment
|
2023-04-29 19:43:41 +00:00
|
|
|
/// variable. This wraps the EnvVar type from Rust.
|
2017-08-06 01:22:49 +00:00
|
|
|
class env_var_t {
|
2018-09-10 01:32:15 +00:00
|
|
|
public:
|
2018-01-30 20:36:50 +00:00
|
|
|
using env_var_flags_t = uint8_t;
|
|
|
|
enum {
|
2018-09-10 01:32:15 +00:00
|
|
|
flag_export = 1 << 0, // whether the variable is exported
|
|
|
|
flag_read_only = 1 << 1, // whether the variable is read only
|
|
|
|
flag_pathvar = 1 << 2, // whether the variable is a path variable
|
2018-01-30 20:36:50 +00:00
|
|
|
};
|
2023-04-29 19:43:41 +00:00
|
|
|
env_var_t() : env_var_t(wcstring_list_ffi_t{}, 0) {}
|
|
|
|
env_var_t(const wcstring_list_ffi_t &vals, uint8_t flags);
|
2023-04-30 02:58:45 +00:00
|
|
|
env_var_t(const env_var_t &);
|
2017-12-23 00:54:15 +00:00
|
|
|
env_var_t(env_var_t &&) = default;
|
2019-03-25 07:41:04 +00:00
|
|
|
|
2018-01-30 20:36:50 +00:00
|
|
|
env_var_t(wcstring val, env_var_flags_t flags)
|
2023-04-30 02:58:45 +00:00
|
|
|
: env_var_t{std::vector<wcstring>{std::move(val)}, flags} {}
|
2017-12-23 00:54:15 +00:00
|
|
|
|
2023-04-30 02:58:45 +00:00
|
|
|
// Construct from FFI. This transfers ownership of the EnvVar, which should originate
|
|
|
|
// in Box::into_raw().
|
|
|
|
static env_var_t new_ffi(EnvVar *ptr);
|
2017-12-23 00:54:15 +00:00
|
|
|
|
2023-04-30 02:58:45 +00:00
|
|
|
// Get the underlying EnvVar pointer.
|
|
|
|
// Note you may need to mem::transmute this, since autocxx gets confused when going from Rust ->
|
|
|
|
// C++ -> Rust.
|
|
|
|
const EnvVar *ffi_ptr() const { return &*this->impl_; }
|
|
|
|
|
|
|
|
bool empty() const;
|
|
|
|
bool exports() const;
|
|
|
|
bool is_read_only() const;
|
|
|
|
bool is_pathvar() const;
|
|
|
|
env_var_flags_t get_flags() const;
|
2013-02-12 07:16:50 +00:00
|
|
|
|
2017-08-06 01:22:49 +00:00
|
|
|
wcstring as_string() const;
|
2023-04-18 22:19:10 +00:00
|
|
|
void to_list(std::vector<wcstring> &out) const;
|
2023-04-30 02:58:45 +00:00
|
|
|
std::vector<wcstring> as_list() const;
|
|
|
|
wcstring_list_ffi_t as_list_ffi() const { return as_list(); }
|
2017-08-05 22:08:39 +00:00
|
|
|
|
2018-09-30 23:34:01 +00:00
|
|
|
/// \return the character used when delimiting quoted expansion.
|
|
|
|
wchar_t get_delimiter() const;
|
|
|
|
|
2018-01-30 20:36:50 +00:00
|
|
|
static env_var_flags_t flags_for(const wchar_t *name);
|
|
|
|
|
2023-04-30 02:58:45 +00:00
|
|
|
env_var_t &operator=(const env_var_t &);
|
2017-12-23 00:54:15 +00:00
|
|
|
env_var_t &operator=(env_var_t &&) = default;
|
2013-02-12 07:16:50 +00:00
|
|
|
|
2023-04-30 02:58:45 +00:00
|
|
|
bool operator==(const env_var_t &rhs) const;
|
2019-05-05 10:09:25 +00:00
|
|
|
bool operator!=(const env_var_t &rhs) const { return !(*this == rhs); }
|
2023-04-30 02:58:45 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
env_var_t(rust::Box<EnvVar> &&impl) : impl_(std::move(impl)) {}
|
|
|
|
|
|
|
|
rust::Box<EnvVar> impl_;
|
2012-01-14 09:06:47 +00:00
|
|
|
};
|
2020-06-25 05:46:32 +00:00
|
|
|
typedef std::unordered_map<wcstring, env_var_t> var_table_t;
|
2013-02-20 01:48:51 +00:00
|
|
|
|
2018-09-09 09:25:51 +00:00
|
|
|
/// An environment is read-only access to variable values.
|
|
|
|
class environment_t {
|
|
|
|
protected:
|
|
|
|
environment_t() = default;
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual maybe_t<env_var_t> get(const wcstring &key,
|
|
|
|
env_mode_flags_t mode = ENV_DEFAULT) const = 0;
|
2023-04-18 22:19:10 +00:00
|
|
|
virtual std::vector<wcstring> get_names(env_mode_flags_t flags) const = 0;
|
2018-09-09 09:25:51 +00:00
|
|
|
virtual ~environment_t();
|
2018-09-11 05:29:52 +00:00
|
|
|
|
2023-04-20 10:24:53 +00:00
|
|
|
maybe_t<env_var_t> get_unless_empty(const wcstring &key,
|
|
|
|
env_mode_flags_t mode = ENV_DEFAULT) const;
|
2023-03-19 02:45:00 +00:00
|
|
|
/// \return a environment variable as a unique pointer, or nullptr if none.
|
|
|
|
std::unique_ptr<env_var_t> get_or_null(const wcstring &key,
|
|
|
|
env_mode_flags_t mode = ENV_DEFAULT) const;
|
|
|
|
|
2018-09-11 05:29:52 +00:00
|
|
|
/// Returns the PWD with a terminating slash.
|
2019-06-10 17:26:21 +00:00
|
|
|
virtual wcstring get_pwd_slash() const;
|
2018-09-11 05:29:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// The null environment contains nothing.
|
|
|
|
class null_environment_t : public environment_t {
|
|
|
|
public:
|
2023-04-29 19:43:41 +00:00
|
|
|
null_environment_t();
|
|
|
|
~null_environment_t();
|
2018-09-11 05:29:52 +00:00
|
|
|
|
|
|
|
maybe_t<env_var_t> get(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT) const override;
|
2023-04-18 22:19:10 +00:00
|
|
|
std::vector<wcstring> get_names(env_mode_flags_t flags) const override;
|
2023-04-29 19:43:41 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
rust::Box<EnvNull> impl_;
|
2018-09-09 09:25:51 +00:00
|
|
|
};
|
|
|
|
|
2019-05-10 16:10:43 +00:00
|
|
|
/// A mutable environment which allows scopes to be pushed and popped.
|
|
|
|
class env_stack_t final : public environment_t {
|
2019-04-14 20:37:44 +00:00
|
|
|
friend class parser_t;
|
|
|
|
|
2019-11-08 07:15:26 +00:00
|
|
|
/// \return whether we are the principal stack.
|
2023-04-29 19:43:41 +00:00
|
|
|
bool is_principal() const;
|
2019-11-08 07:15:26 +00:00
|
|
|
|
2019-05-10 16:10:43 +00:00
|
|
|
public:
|
2018-09-09 19:17:31 +00:00
|
|
|
~env_stack_t() override;
|
2018-09-14 07:36:26 +00:00
|
|
|
env_stack_t(env_stack_t &&);
|
|
|
|
|
2019-05-10 16:10:43 +00:00
|
|
|
/// Implementation of environment_t.
|
|
|
|
maybe_t<env_var_t> get(const wcstring &key, env_mode_flags_t mode = ENV_DEFAULT) const override;
|
2019-05-10 01:04:30 +00:00
|
|
|
|
2019-05-10 16:10:43 +00:00
|
|
|
/// Implementation of environment_t.
|
2023-04-18 22:19:10 +00:00
|
|
|
std::vector<wcstring> get_names(env_mode_flags_t flags) const override;
|
2019-05-10 01:38:18 +00:00
|
|
|
|
2018-09-09 19:17:31 +00:00
|
|
|
/// Sets the variable with the specified name to the given values.
|
2023-04-18 22:19:10 +00:00
|
|
|
int set(const wcstring &key, env_mode_flags_t mode, std::vector<wcstring> vals);
|
2018-09-09 19:17:31 +00:00
|
|
|
|
2023-03-19 03:11:18 +00:00
|
|
|
/// Sets the variable with the specified name to the given values.
|
|
|
|
/// The values should have type const wchar_t *const * (but autocxx doesn't support that).
|
|
|
|
int set_ffi(const wcstring &key, env_mode_flags_t mode, const void *vals, size_t count);
|
|
|
|
|
2018-09-09 19:17:31 +00:00
|
|
|
/// Sets the variable with the specified name to a single value.
|
2021-10-26 15:32:13 +00:00
|
|
|
int set_one(const wcstring &key, env_mode_flags_t mode, wcstring val);
|
2018-09-09 19:17:31 +00:00
|
|
|
|
|
|
|
/// Sets the variable with the specified name to no values.
|
2021-10-26 15:32:13 +00:00
|
|
|
int set_empty(const wcstring &key, env_mode_flags_t mode);
|
2018-09-09 19:17:31 +00:00
|
|
|
|
|
|
|
/// Update the PWD variable based on the result of getcwd.
|
|
|
|
void set_pwd_from_getcwd();
|
|
|
|
|
|
|
|
/// Remove environment variable.
|
|
|
|
///
|
|
|
|
/// \param key The name of the variable to remove
|
|
|
|
/// \param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If
|
|
|
|
/// this is a user request, read-only variables can not be removed. The mode may also specify
|
|
|
|
/// the scope of the variable that should be erased.
|
|
|
|
///
|
|
|
|
/// \return zero if the variable existed, and non-zero if the variable did not exist
|
2021-10-26 15:32:13 +00:00
|
|
|
int remove(const wcstring &key, int mode);
|
2018-09-09 19:17:31 +00:00
|
|
|
|
|
|
|
/// Push the variable stack. Used for implementing local variables for functions and for-loops.
|
|
|
|
void push(bool new_scope);
|
|
|
|
|
|
|
|
/// Pop the variable stack. Used for implementing local variables for functions and for-loops.
|
|
|
|
void pop();
|
|
|
|
|
2019-05-10 16:10:43 +00:00
|
|
|
/// Returns an array containing all exported variables in a format suitable for execv.
|
2021-02-14 21:15:29 +00:00
|
|
|
std::shared_ptr<owning_null_terminated_array_t> export_arr();
|
2019-05-10 16:10:43 +00:00
|
|
|
|
|
|
|
/// Snapshot this environment. This means returning a read-only copy. Local variables are copied
|
|
|
|
/// but globals are shared (i.e. changes to global will be visible to this snapshot). This
|
|
|
|
/// returns a shared_ptr for convenience, since the most common reason to snapshot is because
|
|
|
|
/// you want to read from another thread.
|
|
|
|
std::shared_ptr<environment_t> snapshot() const;
|
2018-09-09 19:17:31 +00:00
|
|
|
|
2019-05-12 21:00:44 +00:00
|
|
|
/// Helpers to get and set the proc statuses.
|
|
|
|
/// These correspond to $status and $pipestatus.
|
|
|
|
statuses_t get_last_statuses() const;
|
|
|
|
int get_last_status() const;
|
|
|
|
void set_last_statuses(statuses_t s);
|
|
|
|
|
2019-05-19 03:58:45 +00:00
|
|
|
/// Sets up argv as the given list of strings.
|
2023-04-18 22:19:10 +00:00
|
|
|
void set_argv(std::vector<wcstring> argv);
|
2018-09-09 19:17:31 +00:00
|
|
|
|
2019-06-10 17:26:21 +00:00
|
|
|
/// Slightly optimized implementation.
|
|
|
|
wcstring get_pwd_slash() const override;
|
|
|
|
|
2023-03-19 02:45:00 +00:00
|
|
|
/// "Override" of get_or_null, as autocxx doesn't understand inheritance.
|
|
|
|
std::unique_ptr<env_var_t> get_or_null(const wcstring &key,
|
|
|
|
env_mode_flags_t mode = ENV_DEFAULT) const {
|
|
|
|
return environment_t::get_or_null(key, mode);
|
|
|
|
}
|
|
|
|
|
2022-03-28 01:59:34 +00:00
|
|
|
/// Synchronizes universal variable changes.
|
|
|
|
/// If \p always is set, perform synchronization even if there's no pending changes from this
|
|
|
|
/// instance (that is, look for changes from other fish instances).
|
|
|
|
/// \return a list of events for changed variables.
|
2023-02-11 20:31:08 +00:00
|
|
|
std::vector<rust::Box<Event>> universal_sync(bool always);
|
2022-03-28 01:59:34 +00:00
|
|
|
|
2018-09-09 19:17:31 +00:00
|
|
|
// Compatibility hack; access the "environment stack" from back when there was just one.
|
2019-05-20 16:27:46 +00:00
|
|
|
static const std::shared_ptr<env_stack_t> &principal_ref();
|
|
|
|
static env_stack_t &principal() { return *principal_ref(); }
|
2018-09-14 07:36:26 +00:00
|
|
|
|
|
|
|
// Access a variable stack that only represents globals.
|
|
|
|
// Do not push or pop from this.
|
|
|
|
static env_stack_t &globals();
|
2023-04-29 19:43:41 +00:00
|
|
|
|
2023-06-19 19:03:46 +00:00
|
|
|
/// Access the underlying Rust implementation.
|
|
|
|
/// This returns a const rust::Box<EnvStackRef> *, or in Rust terms, a *const Box<EnvStackRef>.
|
|
|
|
const void *get_impl_ffi() const { return &impl_; }
|
|
|
|
|
2023-04-29 19:43:41 +00:00
|
|
|
private:
|
|
|
|
env_stack_t(rust::Box<EnvStackRef> imp);
|
|
|
|
|
|
|
|
/// The implementation. Do not access this directly.
|
|
|
|
rust::Box<EnvStackRef> impl_;
|
2018-09-09 19:17:31 +00:00
|
|
|
};
|
|
|
|
|
2023-05-16 23:02:18 +00:00
|
|
|
#if INCLUDE_RUST_HEADERS
|
|
|
|
struct EnvDyn;
|
|
|
|
/// Wrapper around rust's `&dyn Environment` deriving from `environment_t`.
|
|
|
|
class env_dyn_t final : public environment_t {
|
|
|
|
public:
|
|
|
|
env_dyn_t(rust::Box<EnvDyn> impl) : impl_(std::move(impl)) {}
|
|
|
|
maybe_t<env_var_t> get(const wcstring &key, env_mode_flags_t mode) const;
|
|
|
|
|
|
|
|
std::vector<wcstring> get_names(env_mode_flags_t flags) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
rust::Box<EnvDyn> impl_;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2018-09-28 15:14:27 +00:00
|
|
|
/// Gets a path appropriate for runtime storage
|
|
|
|
wcstring env_get_runtime_path();
|
2019-03-26 03:18:00 +00:00
|
|
|
|
2019-05-22 23:09:59 +00:00
|
|
|
/// 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.
|
2023-05-16 19:35:14 +00:00
|
|
|
extern "C" {
|
2019-05-22 23:09:59 +00:00
|
|
|
void setenv_lock(const char *name, const char *value, int overwrite);
|
|
|
|
void unsetenv_lock(const char *name);
|
2023-05-16 19:35:14 +00:00
|
|
|
}
|
2019-05-22 23:09:59 +00:00
|
|
|
|
2022-06-21 16:08:09 +00:00
|
|
|
/// Returns the originally inherited variables and their values.
|
|
|
|
/// This is a simple key->value map and not e.g. cut into paths.
|
|
|
|
const std::map<wcstring, wcstring> &env_get_inherited();
|
2023-04-30 02:58:45 +00:00
|
|
|
|
2023-04-30 02:58:51 +00:00
|
|
|
/// Populate the values in the "$history" variable.
|
|
|
|
/// fish_history_val is the value of the "$fish_history" variable, or "fish" if not set.
|
|
|
|
wcstring_list_ffi_t get_history_variable_text_ffi(const wcstring &fish_history_val);
|
|
|
|
|
2005-10-04 15:11:39 +00:00
|
|
|
#endif
|