diff options
-rw-r--r-- | env.cpp | 6 | ||||
-rw-r--r-- | exec.cpp | 15 | ||||
-rw-r--r-- | tests/test3.in | 7 | ||||
-rw-r--r-- | tests/test3.out | 5 |
4 files changed, 31 insertions, 2 deletions
@@ -542,8 +542,10 @@ void env_init(const struct config_paths_t *paths /* or NULL */) wcstring nshlvl_str = L"1"; if (! shlvl_str.missing()) { - long shlvl_i = wcstol(shlvl_str.c_str(), NULL, 10); - if (shlvl_i >= 0) + 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); } @@ -651,6 +651,21 @@ void exec_job(parser_t &parser, job_t *j) /* PCA This is for handling exec. Passing all_ios here matches what fish 2.0.0 and 1.x did. It's known to be wrong - for example, it means that redirections bound for subsequent commands in the pipeline will apply to exec. However, using exec in a pipeline doesn't really make sense, so I'm not trying to fix it here. */ if (!setup_child_process(j, 0, all_ios)) { + /* decrement SHLVL as we're removing ourselves from the shell "stack" */ + const env_var_t shlvl_str = env_get_string(L"SHLVL", ENV_GLOBAL | ENV_EXPORT); + wcstring nshlvl_str = L"0"; + 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); + /* launch_process _never_ returns */ diff --git a/tests/test3.in b/tests/test3.in index 56cceeb5..b83b69c0 100644 --- a/tests/test3.in +++ b/tests/test3.in @@ -236,5 +236,12 @@ echo Missing: $testu # test SHLVL # use a subshell to ensure a clean slate env SHLVL= ../fish -c 'echo SHLVL: $SHLVL; ../fish -c \'echo SHLVL: $SHLVL\'' +# exec should decrement SHLVL +env SHLVL= ../fish -c 'echo SHLVL: $SHLVL; exec ../fish -c \'echo SHLVL: $SHLVL\'' +# garbage SHLVLs should be treated as garbage +env SHLVL=3foo ../fish -c 'echo SHLVL: $SHLVL' +# whitespace is allowed though (for bash compatibility) +env SHLVL="3 " ../fish -c 'echo SHLVL: $SHLVL' +env SHLVL=" 3" ../fish -c 'echo SHLVL: $SHLVL' true diff --git a/tests/test3.out b/tests/test3.out index 50563c05..c6a21905 100644 --- a/tests/test3.out +++ b/tests/test3.out @@ -23,3 +23,8 @@ Missing: Missing: SHLVL: 1 SHLVL: 2 +SHLVL: 1 +SHLVL: 1 +SHLVL: 1 +SHLVL: 4 +SHLVL: 4 |