Decrement SHLVL when running exec

`exec` removes fish from the shell "stack", so SHLVL needs to be
decremented to match. This means `exec fish` will result in the same
SHLVL in the new fish instance.

Also tweak the SHLVL logic to interpret an environment SHLVL of "3foo"
as garbage instead of as the value "3".

Fixes #1693.
This commit is contained in:
Kevin Ballard 2014-09-19 17:31:34 -07:00
parent 761be8ab7f
commit 940f264ee6
4 changed files with 31 additions and 2 deletions

View file

@ -542,8 +542,10 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
wcstring nshlvl_str = L"1"; wcstring nshlvl_str = L"1";
if (! shlvl_str.missing()) if (! shlvl_str.missing())
{ {
long shlvl_i = wcstol(shlvl_str.c_str(), NULL, 10); wchar_t *end;
if (shlvl_i >= 0) 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); nshlvl_str = to_string<long>(shlvl_i + 1);
} }

View file

@ -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. */ /* 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)) 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 launch_process _never_ returns
*/ */

View file

@ -236,5 +236,12 @@ echo Missing: $testu
# test SHLVL # test SHLVL
# use a subshell to ensure a clean slate # use a subshell to ensure a clean slate
env SHLVL= ../fish -c 'echo SHLVL: $SHLVL; ../fish -c \'echo SHLVL: $SHLVL\'' 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 true

View file

@ -23,3 +23,8 @@ Missing:
Missing: Missing:
SHLVL: 1 SHLVL: 1
SHLVL: 2 SHLVL: 2
SHLVL: 1
SHLVL: 1
SHLVL: 1
SHLVL: 4
SHLVL: 4