sh: Unify EXERROR and EXEXEC

The difference between EXERROR and EXEXEC was that EXEXEC passed along
exitstatus and EXERROR set exitstatus to 2 in the handling code.

By changing the places that raised EXERROR to set exitstatus to 2, the
handling of EXERROR and EXEXEC becomes the same.
This commit is contained in:
Jilles Tjoelker 2018-11-09 14:58:24 +00:00
parent a641e44515
commit bb324af62a
7 changed files with 25 additions and 44 deletions

View File

@ -35,7 +35,7 @@ EXCEPTIONS: Code for dealing with exceptions appears in
exceptions.c. The C language doesn't include exception handling,
so I implement it using setjmp and longjmp. The global variable
exception contains the type of exception. EXERROR is raised by
calling error. EXINT is an interrupt.
calling error or errorwithstatus. EXINT is an interrupt.
INTERRUPTS: In an interactive shell, an interrupt will cause an
EXINT exception to return to the main command loop. (Exception:

View File

@ -67,7 +67,7 @@ volatile sig_atomic_t suppressint;
volatile sig_atomic_t intpending;
static void exverror(int, const char *, va_list) __printf0like(2, 0) __dead2;
static void verrorwithstatus(int, const char *, va_list) __printf0like(2, 0) __dead2;
/*
* Called to raise an exception. Since C doesn't include exceptions, we
@ -154,7 +154,7 @@ warning(const char *msg, ...)
* formatting. It then raises the error exception.
*/
static void
exverror(int cond, const char *msg, va_list ap)
verrorwithstatus(int status, const char *msg, va_list ap)
{
/*
* An interrupt trumps an error. Certain places catch error
@ -168,14 +168,17 @@ exverror(int cond, const char *msg, va_list ap)
#ifdef DEBUG
if (msg)
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
TRACE(("verrorwithstatus(%d, \"%s\") pid=%d\n",
status, msg, getpid()));
else
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
TRACE(("verrorwithstatus(%d, NULL) pid=%d\n",
status, getpid()));
#endif
if (msg)
vwarning(msg, ap);
flushall();
exraise(cond);
exitstatus = status;
exraise(EXERROR);
}
@ -184,16 +187,16 @@ error(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
exverror(EXERROR, msg, ap);
verrorwithstatus(2, msg, ap);
va_end(ap);
}
void
exerror(int cond, const char *msg, ...)
errorwithstatus(int status, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
exverror(cond, msg, ap);
verrorwithstatus(status, msg, ap);
va_end(ap);
}

View File

@ -55,9 +55,8 @@ extern volatile sig_atomic_t exception;
/* exceptions */
#define EXINT 0 /* SIGINT received */
#define EXERROR 1 /* a generic error */
#define EXEXEC 2 /* command execution failed */
#define EXEXIT 3 /* call exitshell(exitstatus) */
#define EXERROR 1 /* a generic error with exitstatus */
#define EXEXIT 2 /* call exitshell(exitstatus) */
/*
@ -83,7 +82,7 @@ void exraise(int) __dead2;
void onint(void) __dead2;
void warning(const char *, ...) __printflike(1, 2);
void error(const char *, ...) __printf0like(1, 2) __dead2;
void exerror(int, const char *, ...) __printf0like(2, 3) __dead2;
void errorwithstatus(int, const char *, ...) __printf0like(2, 3) __dead2;
/*

View File

@ -466,13 +466,9 @@ evalredir(union node *n, int flags)
handler = savehandler;
e = exception;
popredir();
if (e == EXERROR || e == EXEXEC) {
if (in_redirect) {
if (e == EXERROR)
exitstatus = 2;
FORCEINTON;
return;
}
if (e == EXERROR && in_redirect) {
FORCEINTON;
return;
}
longjmp(handler->loc, 1);
} else {
@ -506,7 +502,7 @@ exphere(union node *redir, struct arglist *fn)
forcelocal++;
savehandler = handler;
if (setjmp(jmploc.loc))
need_longjmp = exception != EXERROR && exception != EXEXEC;
need_longjmp = exception != EXERROR;
else {
handler = &jmploc;
expandarg(redir->nhere.doc, fn, 0);
@ -671,8 +667,6 @@ evalbackcmd(union node *n, struct backcmd *result)
savehandler = handler;
if (setjmp(jmploc.loc)) {
if (exception == EXERROR)
exitstatus = 2;
else if (exception == EXEXEC)
/* nothing */;
else if (exception != 0) {
handler = savehandler;
@ -1092,8 +1086,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
e = exception;
if (e == EXINT)
exitstatus = SIGINT+128;
else if (e != EXEXEC && e != EXEXIT)
exitstatus = 2;
goto cmddone;
}
handler = &jmploc;
@ -1142,8 +1134,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
if (cmdentry.u.index != EXECCMD)
popredir();
if (e != -1) {
if ((e != EXERROR && e != EXEXEC)
|| cmdentry.special)
if (e != EXERROR || cmdentry.special)
exraise(e);
popfilesupto(savetopfile);
if (flags != EV_BACKCMD)

View File

@ -133,13 +133,10 @@ shellexec(char **argv, char **envp, const char *path, int idx)
}
/* Map to POSIX errors */
if (e == ENOENT || e == ENOTDIR) {
exitstatus = 127;
exerror(EXEXEC, "%s: not found", argv[0]);
} else {
exitstatus = 126;
exerror(EXEXEC, "%s: %s", argv[0], strerror(e));
}
if (e == ENOENT || e == ENOTDIR)
errorwithstatus(127, "%s: not found", argv[0]);
else
errorwithstatus(126, "%s: %s", argv[0], strerror(e));
}

View File

@ -1006,7 +1006,7 @@ vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int i
if (pid == 0) {
TRACE(("Child shell %d\n", (int)getpid()));
if (setjmp(jmploc.loc))
_exit(exception == EXEXEC ? exitstatus : 2);
_exit(exitstatus);
if (pip != NULL) {
close(pip[0]);
if (pip[1] != 1) {

View File

@ -105,15 +105,6 @@ main(int argc, char *argv[])
initcharset();
state = 0;
if (setjmp(main_handler.loc)) {
switch (exception) {
case EXERROR:
exitstatus = 2;
break;
default:
break;
}
if (state == 0 || iflag == 0 || ! rootshell ||
exception == EXEXIT)
exitshell(exitstatus);