aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--env.cpp6
-rw-r--r--exec.cpp15
-rw-r--r--tests/test3.in7
-rw-r--r--tests/test3.out5
4 files changed, 31 insertions, 2 deletions
diff --git a/env.cpp b/env.cpp
index 353085b8..c9f986b1 100644
--- a/env.cpp
+++ b/env.cpp
@@ -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);
}
diff --git a/exec.cpp b/exec.cpp
index 3b5506da..7706dcc5 100644
--- a/exec.cpp
+++ b/exec.cpp
@@ -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