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 2018-11-09 14:58:24 +00:00
parent b8dfd02788
commit 4586c042eb
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, exceptions.c. The C language doesn't include exception handling,
so I implement it using setjmp and longjmp. The global variable so I implement it using setjmp and longjmp. The global variable
exception contains the type of exception. EXERROR is raised by 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 INTERRUPTS: In an interactive shell, an interrupt will cause an
EXINT exception to return to the main command loop. (Exception: 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; 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 * 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. * formatting. It then raises the error exception.
*/ */
static void 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 * An interrupt trumps an error. Certain places catch error
@ -168,14 +168,17 @@ exverror(int cond, const char *msg, va_list ap)
#ifdef DEBUG #ifdef DEBUG
if (msg) if (msg)
TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); TRACE(("verrorwithstatus(%d, \"%s\") pid=%d\n",
status, msg, getpid()));
else else
TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); TRACE(("verrorwithstatus(%d, NULL) pid=%d\n",
status, getpid()));
#endif #endif
if (msg) if (msg)
vwarning(msg, ap); vwarning(msg, ap);
flushall(); flushall();
exraise(cond); exitstatus = status;
exraise(EXERROR);
} }
@ -184,16 +187,16 @@ error(const char *msg, ...)
{ {
va_list ap; va_list ap;
va_start(ap, msg); va_start(ap, msg);
exverror(EXERROR, msg, ap); verrorwithstatus(2, msg, ap);
va_end(ap); va_end(ap);
} }
void void
exerror(int cond, const char *msg, ...) errorwithstatus(int status, const char *msg, ...)
{ {
va_list ap; va_list ap;
va_start(ap, msg); va_start(ap, msg);
exverror(cond, msg, ap); verrorwithstatus(status, msg, ap);
va_end(ap); va_end(ap);
} }

View File

@ -55,9 +55,8 @@ extern volatile sig_atomic_t exception;
/* exceptions */ /* exceptions */
#define EXINT 0 /* SIGINT received */ #define EXINT 0 /* SIGINT received */
#define EXERROR 1 /* a generic error */ #define EXERROR 1 /* a generic error with exitstatus */
#define EXEXEC 2 /* command execution failed */ #define EXEXIT 2 /* call exitshell(exitstatus) */
#define EXEXIT 3 /* call exitshell(exitstatus) */
/* /*
@ -83,7 +82,7 @@ void exraise(int) __dead2;
void onint(void) __dead2; void onint(void) __dead2;
void warning(const char *, ...) __printflike(1, 2); void warning(const char *, ...) __printflike(1, 2);
void error(const char *, ...) __printf0like(1, 2) __dead2; 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; handler = savehandler;
e = exception; e = exception;
popredir(); popredir();
if (e == EXERROR || e == EXEXEC) { if (e == EXERROR && in_redirect) {
if (in_redirect) { FORCEINTON;
if (e == EXERROR) return;
exitstatus = 2;
FORCEINTON;
return;
}
} }
longjmp(handler->loc, 1); longjmp(handler->loc, 1);
} else { } else {
@ -506,7 +502,7 @@ exphere(union node *redir, struct arglist *fn)
forcelocal++; forcelocal++;
savehandler = handler; savehandler = handler;
if (setjmp(jmploc.loc)) if (setjmp(jmploc.loc))
need_longjmp = exception != EXERROR && exception != EXEXEC; need_longjmp = exception != EXERROR;
else { else {
handler = &jmploc; handler = &jmploc;
expandarg(redir->nhere.doc, fn, 0); expandarg(redir->nhere.doc, fn, 0);
@ -671,8 +667,6 @@ evalbackcmd(union node *n, struct backcmd *result)
savehandler = handler; savehandler = handler;
if (setjmp(jmploc.loc)) { if (setjmp(jmploc.loc)) {
if (exception == EXERROR) if (exception == EXERROR)
exitstatus = 2;
else if (exception == EXEXEC)
/* nothing */; /* nothing */;
else if (exception != 0) { else if (exception != 0) {
handler = savehandler; handler = savehandler;
@ -1092,8 +1086,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
e = exception; e = exception;
if (e == EXINT) if (e == EXINT)
exitstatus = SIGINT+128; exitstatus = SIGINT+128;
else if (e != EXEXEC && e != EXEXIT)
exitstatus = 2;
goto cmddone; goto cmddone;
} }
handler = &jmploc; handler = &jmploc;
@ -1142,8 +1134,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
if (cmdentry.u.index != EXECCMD) if (cmdentry.u.index != EXECCMD)
popredir(); popredir();
if (e != -1) { if (e != -1) {
if ((e != EXERROR && e != EXEXEC) if (e != EXERROR || cmdentry.special)
|| cmdentry.special)
exraise(e); exraise(e);
popfilesupto(savetopfile); popfilesupto(savetopfile);
if (flags != EV_BACKCMD) if (flags != EV_BACKCMD)

View File

@ -133,13 +133,10 @@ shellexec(char **argv, char **envp, const char *path, int idx)
} }
/* Map to POSIX errors */ /* Map to POSIX errors */
if (e == ENOENT || e == ENOTDIR) { if (e == ENOENT || e == ENOTDIR)
exitstatus = 127; errorwithstatus(127, "%s: not found", argv[0]);
exerror(EXEXEC, "%s: not found", argv[0]); else
} else { errorwithstatus(126, "%s: %s", argv[0], strerror(e));
exitstatus = 126;
exerror(EXEXEC, "%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) { if (pid == 0) {
TRACE(("Child shell %d\n", (int)getpid())); TRACE(("Child shell %d\n", (int)getpid()));
if (setjmp(jmploc.loc)) if (setjmp(jmploc.loc))
_exit(exception == EXEXEC ? exitstatus : 2); _exit(exitstatus);
if (pip != NULL) { if (pip != NULL) {
close(pip[0]); close(pip[0]);
if (pip[1] != 1) { if (pip[1] != 1) {

View File

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