mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 15:14:44 +00:00
add $pipestatus
support
This commit is contained in:
parent
e330dafd24
commit
2c8abdf5cb
16 changed files with 285 additions and 5 deletions
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
## Notable fixes and improvements
|
## Notable fixes and improvements
|
||||||
- Fixed infinite recursion triggered if a custom `fish_title` function calls `read` interactively
|
- Fixed infinite recursion triggered if a custom `fish_title` function calls `read` interactively
|
||||||
|
- Add `$pipestatus` support
|
||||||
|
|
||||||
### Syntax changes and new commands
|
### Syntax changes and new commands
|
||||||
- None yet.
|
- None yet.
|
||||||
|
|
|
@ -1193,6 +1193,8 @@ The user can change the settings of ``fish`` by changing the values of certain v
|
||||||
|
|
||||||
- ``status``, the `exit status <#variables-status>`_ of the last foreground job to exit. If the job was terminated through a signal, the exit status will be 128 plus the signal number.
|
- ``status``, the `exit status <#variables-status>`_ of the last foreground job to exit. If the job was terminated through a signal, the exit status will be 128 plus the signal number.
|
||||||
|
|
||||||
|
- ``pipestatus``, an array of exit statuses of all processes that made up the last executed pipe.
|
||||||
|
|
||||||
- ``USER``, the current username. This variable can be changed by the user.
|
- ``USER``, the current username. This variable can be changed by the user.
|
||||||
|
|
||||||
- ``CMD_DURATION``, the runtime of the last command in milliseconds.
|
- ``CMD_DURATION``, the runtime of the last command in milliseconds.
|
||||||
|
|
|
@ -246,7 +246,7 @@ Unlike other shells, ``fish`` stores the exit status of the last command in ``$s
|
||||||
<outp>1</outp>
|
<outp>1</outp>
|
||||||
|
|
||||||
|
|
||||||
Zero is considered success, and non-zero is failure.
|
Zero is considered success, and non-zero is failure. There is also a ``$pipestatus`` array variable for the exit statues of processes in a pipe.
|
||||||
|
|
||||||
|
|
||||||
Exports (Shell Variables)
|
Exports (Shell Variables)
|
||||||
|
|
14
src/env.cpp
14
src/env.cpp
|
@ -316,8 +316,8 @@ bool string_set_contains(const T &set, const wchar_t *val) {
|
||||||
/// Check if a variable may not be set using the set command.
|
/// Check if a variable may not be set using the set command.
|
||||||
static bool is_read_only(const wchar_t *val) {
|
static bool is_read_only(const wchar_t *val) {
|
||||||
const string_set_t env_read_only = {
|
const string_set_t env_read_only = {
|
||||||
L"PWD", L"SHLVL", L"history", L"status", L"version",
|
L"PWD", L"SHLVL", L"history", L"pipestatus", L"status", L"version",
|
||||||
L"FISH_VERSION", L"fish_pid", L"hostname", L"_", L"fish_private_mode"};
|
L"FISH_VERSION", L"fish_pid", L"hostname", L"_", L"fish_private_mode"};
|
||||||
return string_set_contains(env_read_only, val) ||
|
return string_set_contains(env_read_only, val) ||
|
||||||
(in_private_mode() && wcscmp(L"fish_history", val) == 0);
|
(in_private_mode() && wcscmp(L"fish_history", val) == 0);
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ static bool variable_should_auto_pathvar(const wcstring &name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Table of variables whose value is dynamically calculated, such as umask, status, etc.
|
/// Table of variables whose value is dynamically calculated, such as umask, status, etc.
|
||||||
static const string_set_t env_electric = {L"history", L"status", L"umask"};
|
static const string_set_t env_electric = {L"history", L"pipestatus", L"status", L"umask"};
|
||||||
|
|
||||||
static bool is_electric(const wcstring &key) { return contains(env_electric, key); }
|
static bool is_electric(const wcstring &key) { return contains(env_electric, key); }
|
||||||
|
|
||||||
|
@ -1391,6 +1391,14 @@ maybe_t<env_var_t> env_stack_t::get(const wcstring &key, env_mode_flags_t mode)
|
||||||
wcstring_list_t result;
|
wcstring_list_t result;
|
||||||
if (history) history->get_history(result);
|
if (history) history->get_history(result);
|
||||||
return env_var_t(L"history", result);
|
return env_var_t(L"history", result);
|
||||||
|
} else if (key == L"pipestatus") {
|
||||||
|
const auto& js = proc_get_last_job_statuses();
|
||||||
|
wcstring_list_t result;
|
||||||
|
result.reserve(js->size());
|
||||||
|
for (auto&& i : *js) {
|
||||||
|
result.emplace_back(to_string(i));
|
||||||
|
}
|
||||||
|
return env_var_t(L"pipestatus", result);
|
||||||
} else if (key == L"status") {
|
} else if (key == L"status") {
|
||||||
return env_var_t(L"status", to_string(proc_get_last_status()));
|
return env_var_t(L"status", to_string(proc_get_last_status()));
|
||||||
} else if (key == L"umask") {
|
} else if (key == L"umask") {
|
||||||
|
|
|
@ -275,6 +275,7 @@ static void event_fire_internal(const event_t &event) {
|
||||||
// non-interactive.
|
// non-interactive.
|
||||||
proc_push_interactive(0);
|
proc_push_interactive(0);
|
||||||
int prev_status = proc_get_last_status();
|
int prev_status = proc_get_last_status();
|
||||||
|
const auto& saved_job_statuses = proc_get_last_job_statuses();
|
||||||
parser_t &parser = parser_t::principal_parser();
|
parser_t &parser = parser_t::principal_parser();
|
||||||
|
|
||||||
event_block_t *b = parser.push_block<event_block_t>(event);
|
event_block_t *b = parser.push_block<event_block_t>(event);
|
||||||
|
@ -282,6 +283,7 @@ static void event_fire_internal(const event_t &event) {
|
||||||
parser.pop_block(b);
|
parser.pop_block(b);
|
||||||
proc_pop_interactive();
|
proc_pop_interactive();
|
||||||
proc_set_last_status(prev_status);
|
proc_set_last_status(prev_status);
|
||||||
|
proc_set_last_job_statuses(std::move(saved_job_statuses));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
src/exec.cpp
12
src/exec.cpp
|
@ -824,6 +824,7 @@ static bool exec_block_or_func_process(parser_t &parser, std::shared_ptr<job_t>
|
||||||
}
|
}
|
||||||
|
|
||||||
int status = proc_get_last_status();
|
int status = proc_get_last_status();
|
||||||
|
p->status = status;
|
||||||
|
|
||||||
// If we have a block output buffer, populate it now.
|
// If we have a block output buffer, populate it now.
|
||||||
if (!block_output_bufferfill) {
|
if (!block_output_bufferfill) {
|
||||||
|
@ -1056,6 +1057,7 @@ bool exec_job(parser_t &parser, shared_ptr<job_t> j) {
|
||||||
}
|
}
|
||||||
|
|
||||||
j->continue_job(false);
|
j->continue_job(false);
|
||||||
|
proc_set_last_job_statuses(*j);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,6 +1066,7 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, wcstrin
|
||||||
ASSERT_IS_MAIN_THREAD();
|
ASSERT_IS_MAIN_THREAD();
|
||||||
bool prev_subshell = is_subshell;
|
bool prev_subshell = is_subshell;
|
||||||
const int prev_status = proc_get_last_status();
|
const int prev_status = proc_get_last_status();
|
||||||
|
const auto& prev_job_statuses = proc_get_last_job_statuses();
|
||||||
bool split_output = false;
|
bool split_output = false;
|
||||||
|
|
||||||
const auto ifs = parser.vars().get(L"IFS");
|
const auto ifs = parser.vars().get(L"IFS");
|
||||||
|
@ -1090,7 +1093,14 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, wcstrin
|
||||||
|
|
||||||
// If the caller asked us to preserve the exit status, restore the old status. Otherwise set the
|
// If the caller asked us to preserve the exit status, restore the old status. Otherwise set the
|
||||||
// status of the subcommand.
|
// status of the subcommand.
|
||||||
proc_set_last_status(apply_exit_status ? subcommand_status : prev_status);
|
if (apply_exit_status) {
|
||||||
|
proc_set_last_status(subcommand_status);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proc_set_last_job_statuses(std::move(prev_job_statuses));
|
||||||
|
proc_set_last_status(prev_status);
|
||||||
|
}
|
||||||
|
|
||||||
is_subshell = prev_subshell;
|
is_subshell = prev_subshell;
|
||||||
|
|
||||||
if (lst == NULL || !buffer) {
|
if (lst == NULL || !buffer) {
|
||||||
|
|
|
@ -367,10 +367,12 @@ static void input_mapping_execute(const input_mapping_t &m, bool allow_commands)
|
||||||
// FIXME(snnw): if commands add stuff to input queue (e.g. commandline -f execute), we won't
|
// FIXME(snnw): if commands add stuff to input queue (e.g. commandline -f execute), we won't
|
||||||
// see that until all other commands have also been run.
|
// see that until all other commands have also been run.
|
||||||
int last_status = proc_get_last_status();
|
int last_status = proc_get_last_status();
|
||||||
|
const auto& last_job_statuses = proc_get_last_job_statuses();
|
||||||
for (const wcstring &cmd : m.commands) {
|
for (const wcstring &cmd : m.commands) {
|
||||||
parser_t::principal_parser().eval(cmd, io_chain_t(), TOP);
|
parser_t::principal_parser().eval(cmd, io_chain_t(), TOP);
|
||||||
}
|
}
|
||||||
proc_set_last_status(last_status);
|
proc_set_last_status(last_status);
|
||||||
|
proc_set_last_job_statuses(std::move(last_job_statuses));
|
||||||
input_common_next_ch(R_NULL);
|
input_common_next_ch(R_NULL);
|
||||||
} else {
|
} else {
|
||||||
// Invalid binding, mixed commands and functions. We would need to execute these one by
|
// Invalid binding, mixed commands and functions. We would need to execute these one by
|
||||||
|
|
|
@ -718,6 +718,7 @@ parse_execution_result_t parse_execution_context_t::handle_command_not_found(
|
||||||
|
|
||||||
// Set the last proc status appropriately.
|
// Set the last proc status appropriately.
|
||||||
proc_set_last_status(err_code == ENOENT ? STATUS_CMD_UNKNOWN : STATUS_NOT_EXECUTABLE);
|
proc_set_last_status(err_code == ENOENT ? STATUS_CMD_UNKNOWN : STATUS_NOT_EXECUTABLE);
|
||||||
|
proc_set_last_job_statuses(proc_get_last_status());
|
||||||
|
|
||||||
return parse_execution_errored;
|
return parse_execution_errored;
|
||||||
}
|
}
|
||||||
|
|
30
src/proc.cpp
30
src/proc.cpp
|
@ -53,6 +53,9 @@
|
||||||
/// Status of last process to exit.
|
/// Status of last process to exit.
|
||||||
static int last_status = 0;
|
static int last_status = 0;
|
||||||
|
|
||||||
|
/// Statuses of last job's processes to exit - ensure we start off with one entry of 0.
|
||||||
|
static std::shared_ptr<std::vector<int>> last_job_statuses = std::make_shared<std::vector<int>>(1);
|
||||||
|
|
||||||
/// The signals that signify crashes to us.
|
/// The signals that signify crashes to us.
|
||||||
static const int crashsignals[] = {SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSYS};
|
static const int crashsignals[] = {SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSYS};
|
||||||
|
|
||||||
|
@ -139,6 +142,33 @@ void proc_set_last_status(int s) {
|
||||||
|
|
||||||
int proc_get_last_status() { return last_status; }
|
int proc_get_last_status() { return last_status; }
|
||||||
|
|
||||||
|
void proc_set_last_job_statuses(const job_t &last_job) {
|
||||||
|
ASSERT_IS_MAIN_THREAD();
|
||||||
|
auto ljs = std::make_shared<std::vector<int>>();
|
||||||
|
ljs->reserve(last_job.processes.size());
|
||||||
|
for (auto &&p : last_job.processes) {
|
||||||
|
ljs->emplace_back(p->pid ? proc_format_status(p->status) : p->status);
|
||||||
|
}
|
||||||
|
last_job_statuses = std::move(ljs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void proc_set_last_job_statuses(std::shared_ptr<std::vector<int>> job_statuses) {
|
||||||
|
ASSERT_IS_MAIN_THREAD();
|
||||||
|
last_job_statuses = std::move(job_statuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
void proc_set_last_job_statuses(const int job_status) {
|
||||||
|
ASSERT_IS_MAIN_THREAD();
|
||||||
|
auto ljs = std::make_shared<std::vector<int>>(1);
|
||||||
|
(*ljs)[0] = job_status;
|
||||||
|
last_job_statuses = std::move(ljs);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<std::vector<int>> proc_get_last_job_statuses() {
|
||||||
|
ASSERT_IS_MAIN_THREAD();
|
||||||
|
return last_job_statuses;
|
||||||
|
}
|
||||||
|
|
||||||
// Basic thread safe job IDs. The vector consumed_job_ids has a true value wherever the job ID
|
// Basic thread safe job IDs. The vector consumed_job_ids has a true value wherever the job ID
|
||||||
// corresponding to that slot is in use. The job ID corresponding to slot 0 is 1.
|
// corresponding to that slot is in use. The job ID corresponding to slot 0 is 1.
|
||||||
static owning_lock<std::vector<bool>> locked_consumed_job_ids;
|
static owning_lock<std::vector<bool>> locked_consumed_job_ids;
|
||||||
|
|
|
@ -416,6 +416,14 @@ void proc_set_last_status(int s);
|
||||||
/// Returns the status of the last process to exit.
|
/// Returns the status of the last process to exit.
|
||||||
int proc_get_last_status();
|
int proc_get_last_status();
|
||||||
|
|
||||||
|
/// Sets the status of the last job's processes to exit from last_job.
|
||||||
|
void proc_set_last_job_statuses(const job_t &last_job);
|
||||||
|
void proc_set_last_job_statuses(std::shared_ptr<std::vector<int>>);
|
||||||
|
void proc_set_last_job_statuses(const int); // for errors where pipe is unknown
|
||||||
|
|
||||||
|
/// Returns the status of the last job's processes to exit.
|
||||||
|
std::shared_ptr<std::vector<int>> proc_get_last_job_statuses();
|
||||||
|
|
||||||
/// Notify the user about stopped or terminated jobs. Delete terminated jobs from the job list.
|
/// Notify the user about stopped or terminated jobs. Delete terminated jobs from the job list.
|
||||||
///
|
///
|
||||||
/// \param interactive whether interactive jobs should be reaped as well
|
/// \param interactive whether interactive jobs should be reaped as well
|
||||||
|
|
18
tests/pipestatus.err
Normal file
18
tests/pipestatus.err
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - builtins only
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - no builtins
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - mixed
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - non-pipe
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - negate
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - block
|
79
tests/pipestatus.expect
Normal file
79
tests/pipestatus.expect
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# vim: set filetype=expect:
|
||||||
|
#
|
||||||
|
# Verify `$pipestatus` is preserved to next prompt.
|
||||||
|
|
||||||
|
spawn $fish
|
||||||
|
|
||||||
|
expect_prompt
|
||||||
|
|
||||||
|
# no pipe
|
||||||
|
send_line "true"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "0 : 0" {}
|
||||||
|
send_line "false"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "1 : 1" {}
|
||||||
|
|
||||||
|
# no pipe but negated
|
||||||
|
send_line "! true"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "0 : 1" {}
|
||||||
|
send_line "! false"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "1 : 0" {}
|
||||||
|
|
||||||
|
# pipe
|
||||||
|
send_line "false | true | false"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "1 0 1 : 1" {}
|
||||||
|
|
||||||
|
# pipe negated
|
||||||
|
send_line "! false | true | false"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "1 0 1 : 0" {}
|
||||||
|
|
||||||
|
# pipe mixed with builtins and external
|
||||||
|
send_line "command true | false | true | true"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "0 1 0 0 : 0" {}
|
||||||
|
send_line "command true | command false | command false"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "0 1 1 : 1" {}
|
||||||
|
send_line "sh -c 'exit 3' | command false | sh -c 'exit 5'"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "3 1 5 : 5" {}
|
||||||
|
|
||||||
|
# negated pipe with mixed builtin and external
|
||||||
|
send_line "! sh -c 'exit 3' | command false | sh -c 'exit 5'"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "3 1 5 : 0" {}
|
||||||
|
|
||||||
|
# block
|
||||||
|
send_line "command false | begin; command true; end | true"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "1 0 0 : 0" {}
|
||||||
|
send_line "command false | begin; ! true; end | true"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "1 1 0 : 0" {}
|
||||||
|
|
||||||
|
# syntax error
|
||||||
|
send_line "syntax terror"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "127 : 127" {}
|
||||||
|
send_line "syntax | terror"
|
||||||
|
expect_prompt
|
||||||
|
send_line "echo \$pipestatus : \$status"
|
||||||
|
expect_prompt "127 : 127" {}
|
0
tests/pipestatus.expect.err
Normal file
0
tests/pipestatus.expect.err
Normal file
0
tests/pipestatus.expect.out
Normal file
0
tests/pipestatus.expect.out
Normal file
59
tests/pipestatus.in
Normal file
59
tests/pipestatus.in
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
logmsg "pipestatus variable - builtins only"
|
||||||
|
|
||||||
|
false | false | false; echo $pipestatus : $status
|
||||||
|
true | true | true; echo $pipestatus : $status
|
||||||
|
false | true | false; echo $pipestatus : $status
|
||||||
|
true | false | true; echo $pipestatus : $status
|
||||||
|
|
||||||
|
logmsg "pipestatus variable - no builtins"
|
||||||
|
|
||||||
|
command false | command false | command false; echo $pipestatus : $status
|
||||||
|
command true | command true | command true; echo $pipestatus : $status
|
||||||
|
command false | command true | command false; echo $pipestatus : $status
|
||||||
|
command true | command false | command true; echo $pipestatus : $status
|
||||||
|
|
||||||
|
logmsg "pipestatus variable - mixed"
|
||||||
|
|
||||||
|
command false | command false | false; echo $pipestatus : $status
|
||||||
|
command true | true | command true; echo $pipestatus : $status
|
||||||
|
false | command true | command false; echo $pipestatus : $status
|
||||||
|
true | false | command true; echo $pipestatus : $status
|
||||||
|
sh -c 'exit 5' | sh -c 'exit 2'; echo $pipestatus : $status
|
||||||
|
sh -c 'exit 3' | false | sh -c 'exit 6'; echo $pipestatus : $status
|
||||||
|
sh -c 'exit 9' | true | sh -c 'exit 3' | false; echo $pipestatus : $status
|
||||||
|
|
||||||
|
logmsg "pipestatus variable - non-pipe"
|
||||||
|
|
||||||
|
true; echo $pipestatus : $status
|
||||||
|
false; echo $pipestatus : $status
|
||||||
|
command true; echo $pipestatus : $status
|
||||||
|
command false; echo $pipestatus : $status
|
||||||
|
sh -c 'exit 4'; echo $pipestatus : $status
|
||||||
|
|
||||||
|
logmsg "pipestatus variable - negate"
|
||||||
|
|
||||||
|
! true; echo $pipestatus : $status
|
||||||
|
! false; echo $pipestatus : $status
|
||||||
|
! false | false | false; echo $pipestatus : $status
|
||||||
|
! true | command true | true; echo $pipestatus : $status
|
||||||
|
! false | true | command false; echo $pipestatus : $status
|
||||||
|
! command true | command false | command true; echo $pipestatus : $status
|
||||||
|
! sh -c 'exit 9' | true | sh -c 'exit 3'; echo $pipestatus : $status
|
||||||
|
|
||||||
|
logmsg "pipestatus variable - block"
|
||||||
|
|
||||||
|
begin; true; end; echo $pipestatus : $status
|
||||||
|
begin; false; end; echo $pipestatus : $status
|
||||||
|
begin; ! true; end; echo $pipestatus : $status
|
||||||
|
begin; ! false; end; echo $pipestatus : $status
|
||||||
|
true | begin; true; end; echo $pipestatus : $status
|
||||||
|
false | begin; false; end; echo $pipestatus : $status
|
||||||
|
true | begin; ! true; end; echo $pipestatus : $status
|
||||||
|
false | begin; ! false; end; echo $pipestatus : $status
|
||||||
|
begin; true | false; end; echo $pipestatus : $status
|
||||||
|
begin; false | true; end; echo $pipestatus : $status
|
||||||
|
begin; ! true; end | false ; echo $pipestatus : $status
|
||||||
|
begin; ! false; end | true; echo $pipestatus : $status
|
||||||
|
begin; sh -c 'exit 3'; end | begin; sh -c 'exit 5'; end; echo $pipestatus : $status
|
||||||
|
begin; ! sh -c 'exit 3'; end | begin; sh -c 'exit 5'; end; echo $pipestatus : $status
|
||||||
|
begin; ! sh -c 'exit 3'; end | begin; ! sh -c 'exit 5'; end; echo $pipestatus : $status
|
60
tests/pipestatus.out
Normal file
60
tests/pipestatus.out
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - builtins only
|
||||||
|
1 1 1 : 1
|
||||||
|
0 0 0 : 0
|
||||||
|
1 0 1 : 1
|
||||||
|
0 1 0 : 0
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - no builtins
|
||||||
|
1 1 1 : 1
|
||||||
|
0 0 0 : 0
|
||||||
|
1 0 1 : 1
|
||||||
|
0 1 0 : 0
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - mixed
|
||||||
|
1 1 1 : 1
|
||||||
|
0 0 0 : 0
|
||||||
|
1 0 1 : 1
|
||||||
|
0 1 0 : 0
|
||||||
|
5 2 : 2
|
||||||
|
3 1 6 : 6
|
||||||
|
9 0 3 1 : 1
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - non-pipe
|
||||||
|
0 : 0
|
||||||
|
1 : 1
|
||||||
|
0 : 0
|
||||||
|
1 : 1
|
||||||
|
4 : 4
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - negate
|
||||||
|
0 : 1
|
||||||
|
1 : 0
|
||||||
|
1 1 1 : 0
|
||||||
|
0 0 0 : 1
|
||||||
|
1 0 1 : 0
|
||||||
|
0 1 0 : 1
|
||||||
|
9 0 3 : 0
|
||||||
|
|
||||||
|
####################
|
||||||
|
# pipestatus variable - block
|
||||||
|
0 : 0
|
||||||
|
1 : 1
|
||||||
|
0 : 1
|
||||||
|
1 : 0
|
||||||
|
0 0 : 0
|
||||||
|
1 1 : 1
|
||||||
|
0 1 : 1
|
||||||
|
1 0 : 0
|
||||||
|
0 1 : 1
|
||||||
|
1 0 : 0
|
||||||
|
1 1 : 1
|
||||||
|
0 0 : 0
|
||||||
|
3 5 : 5
|
||||||
|
0 5 : 5
|
||||||
|
0 0 : 0
|
Loading…
Reference in a new issue