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 | |
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
-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 |