diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 655bf81306f9..b8f76d57f3d8 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -324,7 +324,7 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { } if (evalskip == SKIPBREAK && --skipcount <= 0) evalskip = 0; - if (evalskip == SKIPFUNC || evalskip == SKIPFILE) + if (evalskip == SKIPRETURN) status = exitstatus; break; } @@ -1068,7 +1068,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) funcnest--; popredir(); INTON; - if (evalskip == SKIPFUNC) { + if (evalskip == SKIPRETURN) { evalskip = 0; skipcount = 0; } @@ -1305,14 +1305,8 @@ returncmd(int argc, char **argv) { int ret = argc > 1 ? number(argv[1]) : oexitstatus; - if (funcnest) { - evalskip = SKIPFUNC; - skipcount = 1; - } else { - /* skip the rest of the file */ - evalskip = SKIPFILE; - skipcount = 1; - } + evalskip = SKIPRETURN; + skipcount = 1; return ret; } diff --git a/bin/sh/eval.h b/bin/sh/eval.h index a6e87b237cb9..4129757e9f01 100644 --- a/bin/sh/eval.h +++ b/bin/sh/eval.h @@ -67,5 +67,4 @@ extern int skipcount; /* reasons for skipping commands (see comment on breakcmd routine) */ #define SKIPBREAK 1 #define SKIPCONT 2 -#define SKIPFUNC 3 -#define SKIPFILE 4 +#define SKIPRETURN 3 diff --git a/bin/sh/main.c b/bin/sh/main.c index 295f27708bd5..e4974ea7f455 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -231,7 +231,7 @@ cmdloop(int top) popstackmark(&smark); setstackmark(&smark); if (evalskip != 0) { - if (evalskip == SKIPFILE) + if (evalskip == SKIPRETURN) evalskip = 0; break; } diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 174788ddc7cb..ea1d899ed8e1 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -1145,8 +1145,10 @@ command is .Pp .D1 Ic return Op Ar exitstatus .Pp -It terminates the current executional scope, returning from the previous -nested function, sourced script, or shell instance, in that order. +It terminates the current executional scope, returning from the closest +nested function or sourced script; +if no function or sourced script is being executed, +it exits the shell instance. The .Ic return command is implemented as a special built-in command. diff --git a/tools/regression/bin/sh/builtins/return8.0 b/tools/regression/bin/sh/builtins/return8.0 new file mode 100644 index 000000000000..f00e859a74ce --- /dev/null +++ b/tools/regression/bin/sh/builtins/return8.0 @@ -0,0 +1,13 @@ +# $FreeBSD$ + +if [ "$1" = nested ]; then + return 17 +fi + +f() { + set -- nested + . "$0" + return $(($? ^ 1)) +} +f +exit $(($? ^ 16))