sh: Make exit without parameters from EXIT trap POSIX-compliant.

It should use the original exit status, just like falling off the
end of the trap handler.

Outside an EXIT trap, 'exit' is still equivalent to 'exit $?'.
This commit is contained in:
Jilles Tjoelker 2011-01-08 23:08:13 +00:00
parent a67b22d67f
commit 70df11eaad
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=217175
4 changed files with 24 additions and 7 deletions

View File

@ -341,10 +341,7 @@ exitcmd(int argc, char **argv)
if (stoppedjobs())
return 0;
if (argc > 1)
exitstatus = number(argv[1]);
exitshell(number(argv[1]));
else
exitstatus = oexitstatus;
exitshell(exitstatus);
/*NOTREACHED*/
return 0;
exitshell_savedstatus();
}

View File

@ -80,6 +80,9 @@ static volatile sig_atomic_t gotsig[NSIG];
static int ignore_sigchld; /* Used while handling SIGCHLD traps. */
volatile sig_atomic_t gotwinch;
static int exiting; /* exitshell() has been called */
static int exiting_exitstatus; /* value passed to exitshell() */
static int getsigaction(int, sig_t *);
@ -477,11 +480,22 @@ setinteractive(int on)
*/
void
exitshell(int status)
{
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
exiting = 1;
exiting_exitstatus = status;
exitshell_savedstatus();
}
void
exitshell_savedstatus(void)
{
struct jmploc loc1, loc2;
char *p;
TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
if (!exiting)
exiting_exitstatus = oexitstatus;
exitstatus = oexitstatus = exiting_exitstatus;
if (setjmp(loc1.loc)) {
goto l1;
}
@ -498,5 +512,5 @@ l1: handler = &loc2; /* probably unnecessary */
#if JOBS
setjobctl(0);
#endif
l2: _exit(status);
l2: _exit(exiting_exitstatus);
}

View File

@ -46,3 +46,4 @@ void onsig(int);
void dotrap(void);
void setinteractive(int);
void exitshell(int) __dead2;
void exitshell_savedstatus(void) __dead2;

View File

@ -0,0 +1,5 @@
# $FreeBSD$
# exit without arguments differs from exit $? in an EXIT trap.
trap 'false; exit' 0