diff options
| author | Eric Andersen <andersen@codepoet.org> | 2003-03-14 16:05:59 +0000 |
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2003-03-14 16:05:59 +0000 |
| commit | 737f5fb890738ab9c28201768f26fa6b42409284 (patch) | |
| tree | b8ae6afa1d3382c0ac2b89b497a20e53b30136d6 /shell | |
| parent | d2b811865053f5a88ee39c7d71b81dc7fa40dd3a (diff) | |
| download | busybox-w32-737f5fb890738ab9c28201768f26fa6b42409284.tar.gz busybox-w32-737f5fb890738ab9c28201768f26fa6b42409284.tar.bz2 busybox-w32-737f5fb890738ab9c28201768f26fa6b42409284.zip | |
Patch from Jonas Holmberg, adjusted by Robert Schwebel, and
later re-adjusted by me to fix msh backtick handling
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/msh.c | 199 |
1 files changed, 144 insertions, 55 deletions
diff --git a/shell/msh.c b/shell/msh.c index 60fc1dc34..53f643de1 100644 --- a/shell/msh.c +++ b/shell/msh.c | |||
| @@ -5,6 +5,11 @@ | |||
| 5 | * This version of the Minix shell was adapted for use in busybox | 5 | * This version of the Minix shell was adapted for use in busybox |
| 6 | * by Erik Andersen <andersee@debian.org> | 6 | * by Erik Andersen <andersee@debian.org> |
| 7 | * | 7 | * |
| 8 | * - backtick expansion did not work properly | ||
| 9 | * Jonas Holmberg <jonas.holmberg@axis.com> | ||
| 10 | * Robert Schwebel <r.schwebel@pengutronix.de> | ||
| 11 | * Erik Andersen <andersee@debian.org> | ||
| 12 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
| 10 | * the Free Software Foundation; either version 2 of the License, or | 15 | * the Free Software Foundation; either version 2 of the License, or |
| @@ -222,7 +227,7 @@ static char *space (int n ); | |||
| 222 | static char *strsave (char *s, int a ); | 227 | static char *strsave (char *s, int a ); |
| 223 | static char *evalstr (char *cp, int f ); | 228 | static char *evalstr (char *cp, int f ); |
| 224 | static char *putn (int n ); | 229 | static char *putn (int n ); |
| 225 | static char *itoa (unsigned u, int n ); | 230 | static char *itoa (int n ); |
| 226 | static char *unquote (char *as ); | 231 | static char *unquote (char *as ); |
| 227 | static struct var *lookup (char *n ); | 232 | static struct var *lookup (char *n ); |
| 228 | static int rlookup (char *n ); | 233 | static int rlookup (char *n ); |
| @@ -664,7 +669,6 @@ static int heedint =1; | |||
| 664 | static struct env e ={line, iostack, iostack-1, (xint *)NULL, FDBASE, (struct env *)NULL}; | 669 | static struct env e ={line, iostack, iostack-1, (xint *)NULL, FDBASE, (struct env *)NULL}; |
| 665 | static void (*qflag)(int) = SIG_IGN; | 670 | static void (*qflag)(int) = SIG_IGN; |
| 666 | static char shellname[] = "/bin/sh"; | 671 | static char shellname[] = "/bin/sh"; |
| 667 | static char search[] = ":/bin:/usr/bin"; | ||
| 668 | static int startl; | 672 | static int startl; |
| 669 | static int peeksym; | 673 | static int peeksym; |
| 670 | static int nlseen; | 674 | static int nlseen; |
| @@ -687,7 +691,6 @@ static void * brkaddr; | |||
| 687 | static char * current_prompt; | 691 | static char * current_prompt; |
| 688 | #endif | 692 | #endif |
| 689 | 693 | ||
| 690 | |||
| 691 | /* -------- sh.c -------- */ | 694 | /* -------- sh.c -------- */ |
| 692 | /* | 695 | /* |
| 693 | * shell | 696 | * shell |
| @@ -722,11 +725,15 @@ extern int msh_main(int argc, char **argv) | |||
| 722 | setval(homedir, "/"); | 725 | setval(homedir, "/"); |
| 723 | export(homedir); | 726 | export(homedir); |
| 724 | 727 | ||
| 725 | setval(lookup("$"), itoa(getpid(), 5)); | 728 | setval(lookup("$"), putn(getpid())); |
| 726 | 729 | ||
| 727 | path = lookup("PATH"); | 730 | path = lookup("PATH"); |
| 728 | if (path->value == null) | 731 | if (path->value == null) { |
| 729 | setval(path, search); | 732 | if (geteuid() == 0) |
| 733 | setval(path, "/sbin:/bin:/usr/sbin:/usr/bin"); | ||
| 734 | else | ||
| 735 | setval(path, "/bin:/usr/bin"); | ||
| 736 | } | ||
| 730 | export(path); | 737 | export(path); |
| 731 | 738 | ||
| 732 | ifs = lookup("IFS"); | 739 | ifs = lookup("IFS"); |
| @@ -858,7 +865,7 @@ setdash() | |||
| 858 | 865 | ||
| 859 | cp = m; | 866 | cp = m; |
| 860 | for (c='a'; c<='z'; c++) | 867 | for (c='a'; c<='z'; c++) |
| 861 | if (flag[c]) | 868 | if (flag[(int)c]) |
| 862 | *cp++ = c; | 869 | *cp++ = c; |
| 863 | *cp = 0; | 870 | *cp = 0; |
| 864 | setval(lookup("-"), m); | 871 | setval(lookup("-"), m); |
| @@ -1047,32 +1054,16 @@ static char * | |||
| 1047 | putn(n) | 1054 | putn(n) |
| 1048 | register int n; | 1055 | register int n; |
| 1049 | { | 1056 | { |
| 1050 | return(itoa(n, -1)); | 1057 | return(itoa(n)); |
| 1051 | } | 1058 | } |
| 1052 | 1059 | ||
| 1053 | static char * | 1060 | static char * |
| 1054 | itoa(u, n) | 1061 | itoa(n) |
| 1055 | register unsigned u; | 1062 | register int n; |
| 1056 | int n; | ||
| 1057 | { | 1063 | { |
| 1058 | register char *cp; | ||
| 1059 | static char s[20]; | 1064 | static char s[20]; |
| 1060 | int m; | 1065 | snprintf(s, sizeof(s), "%u", n); |
| 1061 | 1066 | return(s); | |
| 1062 | m = 0; | ||
| 1063 | if (n < 0 && (int) u < 0) { | ||
| 1064 | m++; | ||
| 1065 | u = -u; | ||
| 1066 | } | ||
| 1067 | cp = s+sizeof(s); | ||
| 1068 | *--cp = 0; | ||
| 1069 | do { | ||
| 1070 | *--cp = u%10 + '0'; | ||
| 1071 | u /= 10; | ||
| 1072 | } while (--n > 0 || u); | ||
| 1073 | if (m) | ||
| 1074 | *--cp = '-'; | ||
| 1075 | return(cp); | ||
| 1076 | } | 1067 | } |
| 1077 | 1068 | ||
| 1078 | static void | 1069 | static void |
| @@ -2326,6 +2317,9 @@ int act; | |||
| 2326 | 2317 | ||
| 2327 | switch(t->type) { | 2318 | switch(t->type) { |
| 2328 | case TPAREN: | 2319 | case TPAREN: |
| 2320 | rv = execute(t->left, pin, pout, 0); | ||
| 2321 | break; | ||
| 2322 | |||
| 2329 | case TCOM: | 2323 | case TCOM: |
| 2330 | { | 2324 | { |
| 2331 | int child; | 2325 | int child; |
| @@ -2877,12 +2871,12 @@ char *c, **v, **envp; | |||
| 2877 | *v = e.linep; | 2871 | *v = e.linep; |
| 2878 | tp = *--v; | 2872 | tp = *--v; |
| 2879 | *v = e.linep; | 2873 | *v = e.linep; |
| 2880 | execve("/bin/sh", v, envp); | 2874 | execve(shellname, v, envp); |
| 2881 | *v = tp; | 2875 | *v = tp; |
| 2882 | return("no Shell"); | 2876 | return("no Shell"); |
| 2883 | 2877 | ||
| 2884 | case ENOMEM: | 2878 | case ENOMEM: |
| 2885 | return("program too big"); | 2879 | return((char*)memory_exhausted); |
| 2886 | 2880 | ||
| 2887 | case E2BIG: | 2881 | case E2BIG: |
| 2888 | return("argument list too long"); | 2882 | return("argument list too long"); |
| @@ -3643,7 +3637,7 @@ loop: | |||
| 3643 | */ | 3637 | */ |
| 3644 | static int | 3638 | static int |
| 3645 | subgetc(ec, quoted) | 3639 | subgetc(ec, quoted) |
| 3646 | register int ec; | 3640 | register char ec; |
| 3647 | int quoted; | 3641 | int quoted; |
| 3648 | { | 3642 | { |
| 3649 | register char c; | 3643 | register char c; |
| @@ -3770,59 +3764,154 @@ int quoted; | |||
| 3770 | /* | 3764 | /* |
| 3771 | * Run the command in `...` and read its output. | 3765 | * Run the command in `...` and read its output. |
| 3772 | */ | 3766 | */ |
| 3767 | |||
| 3773 | static int | 3768 | static int |
| 3774 | grave(quoted) | 3769 | grave(quoted) |
| 3775 | int quoted; | 3770 | int quoted; |
| 3776 | { | 3771 | { |
| 3777 | register int i; | ||
| 3778 | char *cp; | 3772 | char *cp; |
| 3773 | register int i; | ||
| 3774 | int j; | ||
| 3779 | int pf[2]; | 3775 | int pf[2]; |
| 3776 | static char child_cmd[LINELIM]; | ||
| 3777 | char *src; | ||
| 3778 | char *dest; | ||
| 3779 | int count; | ||
| 3780 | int ignore; | ||
| 3781 | int ignore_once; | ||
| 3782 | char *argument_list[4]; | ||
| 3780 | 3783 | ||
| 3781 | #if __GNUC__ | 3784 | #if __GNUC__ |
| 3782 | /* Avoid longjmp clobbering */ | 3785 | /* Avoid longjmp clobbering */ |
| 3783 | (void) &cp; | 3786 | (void) &cp; |
| 3784 | #endif | 3787 | #endif |
| 3788 | |||
| 3785 | for (cp = e.iop->argp->aword; *cp != '`'; cp++) | 3789 | for (cp = e.iop->argp->aword; *cp != '`'; cp++) |
| 3786 | if (*cp == 0) { | 3790 | if (*cp == 0) { |
| 3787 | err("no closing `"); | 3791 | err("no closing `"); |
| 3788 | return(0); | 3792 | return(0); |
| 3789 | } | 3793 | } |
| 3794 | |||
| 3795 | /* string copy with dollar expansion */ | ||
| 3796 | src = e.iop->argp->aword; | ||
| 3797 | dest = child_cmd; | ||
| 3798 | count = 0; | ||
| 3799 | ignore = 0; | ||
| 3800 | ignore_once = 0; | ||
| 3801 | while ((*src != '`') && (count < LINELIM)) { | ||
| 3802 | if (*src == '\'') | ||
| 3803 | ignore = !ignore; | ||
| 3804 | if (*src == '\\') | ||
| 3805 | ignore_once = 1; | ||
| 3806 | if (*src == '$' && !ignore && !ignore_once) { | ||
| 3807 | struct var *vp; | ||
| 3808 | char var_name[LINELIM]; | ||
| 3809 | char alt_value[LINELIM]; | ||
| 3810 | int var_index = 0; | ||
| 3811 | int alt_index = 0; | ||
| 3812 | char operator = 0; | ||
| 3813 | int braces = 0; | ||
| 3814 | char *value; | ||
| 3815 | |||
| 3816 | src++; | ||
| 3817 | if (*src == '{') { | ||
| 3818 | braces = 1; | ||
| 3819 | src++; | ||
| 3820 | } | ||
| 3821 | |||
| 3822 | var_name[var_index++] = *src++; | ||
| 3823 | while (isalnum(*src)) | ||
| 3824 | var_name[var_index++] = *src++; | ||
| 3825 | var_name[var_index] = 0; | ||
| 3826 | |||
| 3827 | if (braces) { | ||
| 3828 | switch (*src) { | ||
| 3829 | case '}': | ||
| 3830 | break; | ||
| 3831 | case '-': | ||
| 3832 | case '=': | ||
| 3833 | case '+': | ||
| 3834 | case '?': | ||
| 3835 | operator = *src; | ||
| 3836 | break; | ||
| 3837 | default: | ||
| 3838 | err("unclosed ${\n"); | ||
| 3839 | return(0); | ||
| 3840 | } | ||
| 3841 | if (operator) { | ||
| 3842 | src++; | ||
| 3843 | while (*src && (*src != '}')) { | ||
| 3844 | alt_value[alt_index++] = *src++; | ||
| 3845 | } | ||
| 3846 | alt_value[alt_index] = 0; | ||
| 3847 | if (*src != '}') { | ||
| 3848 | err("unclosed ${\n"); | ||
| 3849 | return(0); | ||
| 3850 | } | ||
| 3851 | } | ||
| 3852 | src++; | ||
| 3853 | } | ||
| 3854 | |||
| 3855 | vp = lookup(var_name); | ||
| 3856 | if (vp->value != null) | ||
| 3857 | value = (operator == '+')? alt_value : vp->value; | ||
| 3858 | else if (operator == '?') { | ||
| 3859 | err(alt_value); | ||
| 3860 | return(0); | ||
| 3861 | } else if (alt_index && (operator != '+')) { | ||
| 3862 | value = alt_value; | ||
| 3863 | if (operator == '=') | ||
| 3864 | setval(vp, value); | ||
| 3865 | } else | ||
| 3866 | continue; | ||
| 3867 | |||
| 3868 | while (*value && (count < LINELIM)) { | ||
| 3869 | *dest++ = *value++; | ||
| 3870 | count++; | ||
| 3871 | } | ||
| 3872 | } else { | ||
| 3873 | *dest++ = *src++; | ||
| 3874 | count++; | ||
| 3875 | ignore_once = 0; | ||
| 3876 | } | ||
| 3877 | } | ||
| 3878 | *dest = '\0'; | ||
| 3879 | |||
| 3790 | if (openpipe(pf) < 0) | 3880 | if (openpipe(pf) < 0) |
| 3791 | return(0); | 3881 | return(0); |
| 3792 | if ((i = vfork()) == -1) { | 3882 | while ((i = vfork()) == -1 && errno == EAGAIN) |
| 3883 | ; | ||
| 3884 | if (i < 0) { | ||
| 3793 | closepipe(pf); | 3885 | closepipe(pf); |
| 3794 | err("try again"); | 3886 | err((char*)memory_exhausted); |
| 3795 | return(0); | 3887 | return(0); |
| 3796 | } | 3888 | } |
| 3797 | if (i != 0) { | 3889 | if (i != 0) { |
| 3890 | waitpid(i, NULL, 0); | ||
| 3798 | e.iop->argp->aword = ++cp; | 3891 | e.iop->argp->aword = ++cp; |
| 3799 | close(pf[1]); | 3892 | close(pf[1]); |
| 3800 | PUSHIO(afile, remap(pf[0]), (int(*)(struct ioarg *))((quoted)? qgravechar: gravechar)); | 3893 | PUSHIO(afile, remap(pf[0]), (int(*)(struct ioarg *))((quoted)? qgravechar: gravechar)); |
| 3801 | return(1); | 3894 | return(1); |
| 3802 | } | 3895 | } |
| 3803 | *cp = 0; | ||
| 3804 | /* allow trapped signals */ | 3896 | /* allow trapped signals */ |
| 3805 | for (i=0; i<=_NSIG; i++) | 3897 | /* XXX - Maybe this signal stuff should go as well? */ |
| 3806 | if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN) | 3898 | for (j=0; j<=_NSIG; j++) |
| 3807 | signal(i, SIG_DFL); | 3899 | if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN) |
| 3900 | signal(j, SIG_DFL); | ||
| 3901 | |||
| 3808 | dup2(pf[1], 1); | 3902 | dup2(pf[1], 1); |
| 3809 | closepipe(pf); | 3903 | closepipe(pf); |
| 3810 | flag['e'] = 0; | 3904 | |
| 3811 | flag['v'] = 0; | 3905 | argument_list[0] = shellname; |
| 3812 | flag['n'] = 0; | 3906 | argument_list[1] = "-c"; |
| 3813 | cp = strsave(e.iop->argp->aword, 0); | 3907 | argument_list[2] = child_cmd; |
| 3814 | areanum = 1; | 3908 | argument_list[3] = 0; |
| 3815 | freehere(areanum); | 3909 | |
| 3816 | freearea(areanum); /* free old space */ | 3910 | prs(rexecve(argument_list[0], argument_list, makenv())); |
| 3817 | e.oenv = NULL; | 3911 | _exit(1); |
| 3818 | e.iop = (e.iobase = iostack) - 1; | ||
| 3819 | unquote(cp); | ||
| 3820 | interactive = 0; | ||
| 3821 | PUSHIO(aword, cp, nlchar); | ||
| 3822 | onecommand(); | ||
| 3823 | exit(1); | ||
| 3824 | } | 3912 | } |
| 3825 | 3913 | ||
| 3914 | |||
| 3826 | static char * | 3915 | static char * |
| 3827 | unquote(as) | 3916 | unquote(as) |
| 3828 | register char *as; | 3917 | register char *as; |
| @@ -4194,7 +4283,7 @@ static int my_getc( int ec) | |||
| 4194 | return(c); | 4283 | return(c); |
| 4195 | } | 4284 | } |
| 4196 | c = readc(); | 4285 | c = readc(); |
| 4197 | if (ec != '\'' && e.iop->task != XGRAVE) { | 4286 | if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) { |
| 4198 | if(c == '\\') { | 4287 | if(c == '\\') { |
| 4199 | c = readc(); | 4288 | c = readc(); |
| 4200 | if (c == '\n' && ec != '\"') | 4289 | if (c == '\n' && ec != '\"') |
| @@ -4457,7 +4546,7 @@ register struct ioarg *ap; | |||
| 4457 | } | 4546 | } |
| 4458 | 4547 | ||
| 4459 | #ifdef CONFIG_FEATURE_COMMAND_EDITING | 4548 | #ifdef CONFIG_FEATURE_COMMAND_EDITING |
| 4460 | if (interactive) { | 4549 | if (interactive && isatty(ap->afile)) { |
| 4461 | static char mycommand[BUFSIZ]; | 4550 | static char mycommand[BUFSIZ]; |
| 4462 | static int position = 0, size = 0; | 4551 | static int position = 0, size = 0; |
| 4463 | 4552 | ||
| @@ -4568,7 +4657,7 @@ static void | |||
| 4568 | prn(u) | 4657 | prn(u) |
| 4569 | unsigned u; | 4658 | unsigned u; |
| 4570 | { | 4659 | { |
| 4571 | prs(itoa(u, 0)); | 4660 | prs(itoa(u)); |
| 4572 | } | 4661 | } |
| 4573 | 4662 | ||
| 4574 | static void | 4663 | static void |
