diff options
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 72 |
1 files changed, 53 insertions, 19 deletions
diff --git a/shell/ash.c b/shell/ash.c index dd20fe338..45b00709a 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -1569,14 +1569,14 @@ static char *optionarg; /* set by nextopt (like getopt) */ | |||
| 1569 | static char *optptr; /* used by nextopt */ | 1569 | static char *optptr; /* used by nextopt */ |
| 1570 | 1570 | ||
| 1571 | /* | 1571 | /* |
| 1572 | * XXX - should get rid of. have all builtins use getopt(3). the | 1572 | * XXX - should get rid of. Have all builtins use getopt(3). |
| 1573 | * library getopt must have the BSD extension static variable "optreset" | 1573 | * The library getopt must have the BSD extension static variable |
| 1574 | * otherwise it can't be used within the shell safely. | 1574 | * "optreset", otherwise it can't be used within the shell safely. |
| 1575 | * | 1575 | * |
| 1576 | * Standard option processing (a la getopt) for builtin routines. The | 1576 | * Standard option processing (a la getopt) for builtin routines. |
| 1577 | * only argument that is passed to nextopt is the option string; the | 1577 | * The only argument that is passed to nextopt is the option string; |
| 1578 | * other arguments are unnecessary. It return the character, or '\0' on | 1578 | * the other arguments are unnecessary. It returns the character, |
| 1579 | * end of input. | 1579 | * or '\0' on end of input. |
| 1580 | */ | 1580 | */ |
| 1581 | static int | 1581 | static int |
| 1582 | nextopt(const char *optstring) | 1582 | nextopt(const char *optstring) |
| @@ -1587,13 +1587,20 @@ nextopt(const char *optstring) | |||
| 1587 | 1587 | ||
| 1588 | p = optptr; | 1588 | p = optptr; |
| 1589 | if (p == NULL || *p == '\0') { | 1589 | if (p == NULL || *p == '\0') { |
| 1590 | /* We ate entire "-param", take next one */ | ||
| 1590 | p = *argptr; | 1591 | p = *argptr; |
| 1591 | if (p == NULL || *p != '-' || *++p == '\0') | 1592 | if (p == NULL) |
| 1593 | return '\0'; | ||
| 1594 | if (*p != '-') | ||
| 1595 | return '\0'; | ||
| 1596 | if (*++p == '\0') /* just "-" ? */ | ||
| 1592 | return '\0'; | 1597 | return '\0'; |
| 1593 | argptr++; | 1598 | argptr++; |
| 1594 | if (LONE_DASH(p)) /* check for "--" */ | 1599 | if (LONE_DASH(p)) /* "--" ? */ |
| 1595 | return '\0'; | 1600 | return '\0'; |
| 1601 | /* p => next "-param" */ | ||
| 1596 | } | 1602 | } |
| 1603 | /* p => some option char in the middle of a "-param" */ | ||
| 1597 | c = *p++; | 1604 | c = *p++; |
| 1598 | for (q = optstring; *q != c;) { | 1605 | for (q = optstring; *q != c;) { |
| 1599 | if (*q == '\0') | 1606 | if (*q == '\0') |
| @@ -1602,8 +1609,11 @@ nextopt(const char *optstring) | |||
| 1602 | q++; | 1609 | q++; |
| 1603 | } | 1610 | } |
| 1604 | if (*++q == ':') { | 1611 | if (*++q == ':') { |
| 1605 | if (*p == '\0' && (p = *argptr++) == NULL) | 1612 | if (*p == '\0') { |
| 1606 | ash_msg_and_raise_error("no arg for -%c option", c); | 1613 | p = *argptr++; |
| 1614 | if (p == NULL) | ||
| 1615 | ash_msg_and_raise_error("no arg for -%c option", c); | ||
| 1616 | } | ||
| 1607 | optionarg = p; | 1617 | optionarg = p; |
| 1608 | p = NULL; | 1618 | p = NULL; |
| 1609 | } | 1619 | } |
| @@ -7428,8 +7438,10 @@ commandcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) | |||
| 7428 | else if (c != 'p') | 7438 | else if (c != 'p') |
| 7429 | abort(); | 7439 | abort(); |
| 7430 | #endif | 7440 | #endif |
| 7431 | if (verify) | 7441 | /* Mimic bash: just "command -v" doesn't complain, it's a nop */ |
| 7442 | if (verify && (*argptr != NULL)) { | ||
| 7432 | return describe_command(*argptr, verify - VERIFY_BRIEF); | 7443 | return describe_command(*argptr, verify - VERIFY_BRIEF); |
| 7444 | } | ||
| 7433 | 7445 | ||
| 7434 | return 0; | 7446 | return 0; |
| 7435 | } | 7447 | } |
| @@ -7788,16 +7800,33 @@ static void prehash(union node *); | |||
| 7788 | static void | 7800 | static void |
| 7789 | evaltree(union node *n, int flags) | 7801 | evaltree(union node *n, int flags) |
| 7790 | { | 7802 | { |
| 7803 | |||
| 7804 | struct jmploc *volatile savehandler = exception_handler; | ||
| 7805 | struct jmploc jmploc; | ||
| 7791 | int checkexit = 0; | 7806 | int checkexit = 0; |
| 7792 | void (*evalfn)(union node *, int); | 7807 | void (*evalfn)(union node *, int); |
| 7793 | unsigned isor; | ||
| 7794 | int status; | 7808 | int status; |
| 7809 | |||
| 7795 | if (n == NULL) { | 7810 | if (n == NULL) { |
| 7796 | TRACE(("evaltree(NULL) called\n")); | 7811 | TRACE(("evaltree(NULL) called\n")); |
| 7797 | goto out; | 7812 | goto out1; |
| 7798 | } | 7813 | } |
| 7799 | TRACE(("pid %d, evaltree(%p: %d, %d) called\n", | 7814 | TRACE(("pid %d, evaltree(%p: %d, %d) called\n", |
| 7800 | getpid(), n, n->type, flags)); | 7815 | getpid(), n, n->type, flags)); |
| 7816 | |||
| 7817 | exception_handler = &jmploc; | ||
| 7818 | { | ||
| 7819 | int err = setjmp(jmploc.loc); | ||
| 7820 | if (err) { | ||
| 7821 | /* if it was a signal, check for trap handlers */ | ||
| 7822 | if (exception == EXSIG) | ||
| 7823 | goto out; | ||
| 7824 | /* continue on the way out */ | ||
| 7825 | exception_handler = savehandler; | ||
| 7826 | longjmp(exception_handler->loc, err); | ||
| 7827 | } | ||
| 7828 | } | ||
| 7829 | |||
| 7801 | switch (n->type) { | 7830 | switch (n->type) { |
| 7802 | default: | 7831 | default: |
| 7803 | #if DEBUG | 7832 | #if DEBUG |
| @@ -7843,19 +7872,20 @@ evaltree(union node *n, int flags) | |||
| 7843 | goto calleval; | 7872 | goto calleval; |
| 7844 | case NAND: | 7873 | case NAND: |
| 7845 | case NOR: | 7874 | case NOR: |
| 7846 | case NSEMI: | 7875 | case NSEMI: { |
| 7876 | |||
| 7847 | #if NAND + 1 != NOR | 7877 | #if NAND + 1 != NOR |
| 7848 | #error NAND + 1 != NOR | 7878 | #error NAND + 1 != NOR |
| 7849 | #endif | 7879 | #endif |
| 7850 | #if NOR + 1 != NSEMI | 7880 | #if NOR + 1 != NSEMI |
| 7851 | #error NOR + 1 != NSEMI | 7881 | #error NOR + 1 != NSEMI |
| 7852 | #endif | 7882 | #endif |
| 7853 | isor = n->type - NAND; | 7883 | unsigned is_or = n->type - NAND; |
| 7854 | evaltree( | 7884 | evaltree( |
| 7855 | n->nbinary.ch1, | 7885 | n->nbinary.ch1, |
| 7856 | (flags | ((isor >> 1) - 1)) & EV_TESTED | 7886 | (flags | ((is_or >> 1) - 1)) & EV_TESTED |
| 7857 | ); | 7887 | ); |
| 7858 | if (!exitstatus == isor) | 7888 | if (!exitstatus == is_or) |
| 7859 | break; | 7889 | break; |
| 7860 | if (!evalskip) { | 7890 | if (!evalskip) { |
| 7861 | n = n->nbinary.ch2; | 7891 | n = n->nbinary.ch2; |
| @@ -7866,6 +7896,7 @@ evaltree(union node *n, int flags) | |||
| 7866 | break; | 7896 | break; |
| 7867 | } | 7897 | } |
| 7868 | break; | 7898 | break; |
| 7899 | } | ||
| 7869 | case NIF: | 7900 | case NIF: |
| 7870 | evaltree(n->nif.test, EV_TESTED); | 7901 | evaltree(n->nif.test, EV_TESTED); |
| 7871 | if (evalskip) | 7902 | if (evalskip) |
| @@ -7886,8 +7917,11 @@ evaltree(union node *n, int flags) | |||
| 7886 | exitstatus = status; | 7917 | exitstatus = status; |
| 7887 | break; | 7918 | break; |
| 7888 | } | 7919 | } |
| 7920 | |||
| 7889 | out: | 7921 | out: |
| 7890 | if ((checkexit & exitstatus)) | 7922 | exception_handler = savehandler; |
| 7923 | out1: | ||
| 7924 | if (checkexit & exitstatus) | ||
| 7891 | evalskip |= SKIPEVAL; | 7925 | evalskip |= SKIPEVAL; |
| 7892 | else if (pendingsig && dotrap()) | 7926 | else if (pendingsig && dotrap()) |
| 7893 | goto exexit; | 7927 | goto exexit; |
