--- a/shell/ash.c +++ b/shell/ash.c @@ -1569,14 +1569,14 @@ static char *optptr; /* used by nextopt */ /* - * XXX - should get rid of. have all builtins use getopt(3). the - * library getopt must have the BSD extension static variable "optreset" - * otherwise it can't be used within the shell safely. + * XXX - should get rid of. Have all builtins use getopt(3). + * The library getopt must have the BSD extension static variable + * "optreset", otherwise it can't be used within the shell safely. * - * Standard option processing (a la getopt) for builtin routines. The - * only argument that is passed to nextopt is the option string; the - * other arguments are unnecessary. It return the character, or '\0' on - * end of input. + * Standard option processing (a la getopt) for builtin routines. + * The only argument that is passed to nextopt is the option string; + * the other arguments are unnecessary. It returns the character, + * or '\0' on end of input. */ static int nextopt(const char *optstring) @@ -1587,13 +1587,20 @@ p = optptr; if (p == NULL || *p == '\0') { + /* We ate entire "-param", take next one */ p = *argptr; - if (p == NULL || *p != '-' || *++p == '\0') + if (p == NULL) + return '\0'; + if (*p != '-') + return '\0'; + if (*++p == '\0') /* just "-" ? */ return '\0'; argptr++; - if (LONE_DASH(p)) /* check for "--" */ + if (LONE_DASH(p)) /* "--" ? */ return '\0'; + /* p => next "-param" */ } + /* p => some option char in the middle of a "-param" */ c = *p++; for (q = optstring; *q != c;) { if (*q == '\0') @@ -1602,8 +1609,11 @@ q++; } if (*++q == ':') { - if (*p == '\0' && (p = *argptr++) == NULL) - ash_msg_and_raise_error("no arg for -%c option", c); + if (*p == '\0') { + p = *argptr++; + if (p == NULL) + ash_msg_and_raise_error("no arg for -%c option", c); + } optionarg = p; p = NULL; } @@ -7428,8 +7438,10 @@ else if (c != 'p') abort(); #endif - if (verify) + /* Mimic bash: just "command -v" doesn't complain, it's a nop */ + if (verify && (*argptr != NULL)) { return describe_command(*argptr, verify - VERIFY_BRIEF); + } return 0; } @@ -7788,16 +7800,33 @@ static void evaltree(union node *n, int flags) { + + struct jmploc *volatile savehandler = exception_handler; + struct jmploc jmploc; int checkexit = 0; void (*evalfn)(union node *, int); - unsigned isor; int status; + if (n == NULL) { TRACE(("evaltree(NULL) called\n")); - goto out; + goto out1; } TRACE(("pid %d, evaltree(%p: %d, %d) called\n", getpid(), n, n->type, flags)); + + exception_handler = &jmploc; + { + int err = setjmp(jmploc.loc); + if (err) { + /* if it was a signal, check for trap handlers */ + if (exception == EXSIG) + goto out; + /* continue on the way out */ + exception_handler = savehandler; + longjmp(exception_handler->loc, err); + } + } + switch (n->type) { default: #if DEBUG @@ -7843,19 +7872,20 @@ goto calleval; case NAND: case NOR: - case NSEMI: + case NSEMI: { + #if NAND + 1 != NOR #error NAND + 1 != NOR #endif #if NOR + 1 != NSEMI #error NOR + 1 != NSEMI #endif - isor = n->type - NAND; + unsigned is_or = n->type - NAND; evaltree( n->nbinary.ch1, - (flags | ((isor >> 1) - 1)) & EV_TESTED + (flags | ((is_or >> 1) - 1)) & EV_TESTED ); - if (!exitstatus == isor) + if (!exitstatus == is_or) break; if (!evalskip) { n = n->nbinary.ch2; @@ -7866,6 +7896,7 @@ break; } break; + } case NIF: evaltree(n->nif.test, EV_TESTED); if (evalskip) @@ -7886,8 +7917,11 @@ exitstatus = status; break; } + out: - if ((checkexit & exitstatus)) + exception_handler = savehandler; + out1: + if (checkexit & exitstatus) evalskip |= SKIPEVAL; else if (pendingsig && dotrap()) goto exexit;