diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-12 09:51:03 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-12 09:51:03 +0000 |
commit | 7e497527ea2edf0d75c9de243ba8202eaf87ee9d (patch) | |
tree | f08b32894dd919f2b4f7652c40a36d65282b9bc1 | |
parent | e26b2783a5d8e69d14e5531244c4f2c93312e715 (diff) | |
download | busybox-w32-7e497527ea2edf0d75c9de243ba8202eaf87ee9d.tar.gz busybox-w32-7e497527ea2edf0d75c9de243ba8202eaf87ee9d.tar.bz2 busybox-w32-7e497527ea2edf0d75c9de243ba8202eaf87ee9d.zip |
msh: instead of fixing "ls | cd", "cd | ls" etc just disallow
builtins in pipes. They make no sense there anyway.
msh: shrink umask builtin.
function old new delta
execute 2508 2509 +1
doset 326 317 -9
forkexec 1370 1345 -25
doumask 165 101 -64
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 1/-98) Total: -97 bytes
-rw-r--r-- | shell/msh.c | 180 |
1 files changed, 85 insertions, 95 deletions
diff --git a/shell/msh.c b/shell/msh.c index 99b03947e..ee54ef2d4 100644 --- a/shell/msh.c +++ b/shell/msh.c | |||
@@ -86,7 +86,7 @@ static char *itoa(int n) | |||
86 | # include "busybox.h" /* for applet_names */ | 86 | # include "busybox.h" /* for applet_names */ |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | /*#define MSHDEBUG 1*/ | 89 | //#define MSHDEBUG 4 |
90 | 90 | ||
91 | #ifdef MSHDEBUG | 91 | #ifdef MSHDEBUG |
92 | int mshdbg = MSHDEBUG; | 92 | int mshdbg = MSHDEBUG; |
@@ -244,11 +244,6 @@ static const char *const T_CMD_NAMES[] = { | |||
244 | }; | 244 | }; |
245 | #endif | 245 | #endif |
246 | 246 | ||
247 | /* | ||
248 | * actions determining the environment of a process | ||
249 | */ | ||
250 | #define FEXEC 1 /* execute without forking */ | ||
251 | |||
252 | #define AREASIZE (90000) | 247 | #define AREASIZE (90000) |
253 | 248 | ||
254 | /* | 249 | /* |
@@ -402,8 +397,6 @@ struct var { | |||
402 | 397 | ||
403 | static int yyparse(void); | 398 | static int yyparse(void); |
404 | 399 | ||
405 | static int execute(struct op *t, int *pin, int *pout, int act); | ||
406 | |||
407 | 400 | ||
408 | /* -------- io.h -------- */ | 401 | /* -------- io.h -------- */ |
409 | /* io buffer */ | 402 | /* io buffer */ |
@@ -495,7 +488,8 @@ static char **getwords(struct wdblock *wb); | |||
495 | 488 | ||
496 | /* -------- misc stuff -------- */ | 489 | /* -------- misc stuff -------- */ |
497 | 490 | ||
498 | static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp); | 491 | static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp); |
492 | static int execute(struct op *t, int *pin, int *pout, int no_fork); | ||
499 | static int iosetup(struct ioword *iop, int pipein, int pipeout); | 493 | static int iosetup(struct ioword *iop, int pipein, int pipeout); |
500 | static void brkset(struct brkcon *bc); | 494 | static void brkset(struct brkcon *bc); |
501 | static int dolabel(struct op *t); | 495 | static int dolabel(struct op *t); |
@@ -564,10 +558,13 @@ static const char *const signame[] = { | |||
564 | }; | 558 | }; |
565 | 559 | ||
566 | 560 | ||
561 | typedef int (*builtin_func_ptr)(struct op *); | ||
562 | |||
567 | struct builtincmd { | 563 | struct builtincmd { |
568 | const char *name; | 564 | const char *name; |
569 | int (*builtinfunc)(struct op *t); | 565 | builtin_func_ptr builtinfunc; |
570 | }; | 566 | }; |
567 | |||
571 | static const struct builtincmd builtincmds[] = { | 568 | static const struct builtincmd builtincmds[] = { |
572 | { "." , dodot }, | 569 | { "." , dodot }, |
573 | { ":" , dolabel }, | 570 | { ":" , dolabel }, |
@@ -1373,7 +1370,7 @@ static void onecommand(void) | |||
1373 | if (!FLAG['n']) { | 1370 | if (!FLAG['n']) { |
1374 | DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n", | 1371 | DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n", |
1375 | outtree)); | 1372 | outtree)); |
1376 | execute(outtree, NOPIPE, NOPIPE, 0); | 1373 | execute(outtree, NOPIPE, NOPIPE, /* no_fork: */ 0); |
1377 | } | 1374 | } |
1378 | 1375 | ||
1379 | if (!interactive && intr) { | 1376 | if (!interactive && intr) { |
@@ -2450,7 +2447,7 @@ static struct op *findcase(struct op *t, const char *w) | |||
2450 | * execute tree | 2447 | * execute tree |
2451 | */ | 2448 | */ |
2452 | 2449 | ||
2453 | static int execute(struct op *t, int *pin, int *pout, int act) | 2450 | static int execute(struct op *t, int *pin, int *pout, int no_fork) |
2454 | { | 2451 | { |
2455 | struct op *t1; | 2452 | struct op *t1; |
2456 | volatile int i, rv, a; | 2453 | volatile int i, rv, a; |
@@ -2495,17 +2492,17 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2495 | outtree = outtree_save; | 2492 | outtree = outtree_save; |
2496 | 2493 | ||
2497 | if (t->left) | 2494 | if (t->left) |
2498 | rv = execute(t->left, pin, pout, 0); | 2495 | rv = execute(t->left, pin, pout, /* no_fork: */ 0); |
2499 | if (t->right) | 2496 | if (t->right) |
2500 | rv = execute(t->right, pin, pout, 0); | 2497 | rv = execute(t->right, pin, pout, /* no_fork: */ 0); |
2501 | break; | 2498 | break; |
2502 | 2499 | ||
2503 | case TPAREN: | 2500 | case TPAREN: |
2504 | rv = execute(t->left, pin, pout, 0); | 2501 | rv = execute(t->left, pin, pout, /* no_fork: */ 0); |
2505 | break; | 2502 | break; |
2506 | 2503 | ||
2507 | case TCOM: | 2504 | case TCOM: |
2508 | rv = forkexec(t, pin, pout, act, wp); | 2505 | rv = forkexec(t, pin, pout, no_fork, wp); |
2509 | break; | 2506 | break; |
2510 | 2507 | ||
2511 | case TPIPE: | 2508 | case TPIPE: |
@@ -2517,14 +2514,14 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2517 | break; | 2514 | break; |
2518 | pv[0] = remap(pv[0]); | 2515 | pv[0] = remap(pv[0]); |
2519 | pv[1] = remap(pv[1]); | 2516 | pv[1] = remap(pv[1]); |
2520 | (void) execute(t->left, pin, pv, 0); | 2517 | (void) execute(t->left, pin, pv, /* no_fork: */ 0); |
2521 | rv = execute(t->right, pv, pout, 0); | 2518 | rv = execute(t->right, pv, pout, /* no_fork: */ 0); |
2522 | } | 2519 | } |
2523 | break; | 2520 | break; |
2524 | 2521 | ||
2525 | case TLIST: | 2522 | case TLIST: |
2526 | (void) execute(t->left, pin, pout, 0); | 2523 | (void) execute(t->left, pin, pout, /* no_fork: */ 0); |
2527 | rv = execute(t->right, pin, pout, 0); | 2524 | rv = execute(t->right, pin, pout, /* no_fork: */ 0); |
2528 | break; | 2525 | break; |
2529 | 2526 | ||
2530 | case TASYNC: | 2527 | case TASYNC: |
@@ -2544,7 +2541,7 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2544 | close(0); | 2541 | close(0); |
2545 | xopen(bb_dev_null, O_RDONLY); | 2542 | xopen(bb_dev_null, O_RDONLY); |
2546 | } | 2543 | } |
2547 | _exit(execute(t->left, pin, pout, FEXEC)); | 2544 | _exit(execute(t->left, pin, pout, /* no_fork: */ 1)); |
2548 | } | 2545 | } |
2549 | interactive = hinteractive; | 2546 | interactive = hinteractive; |
2550 | if (i != -1) { | 2547 | if (i != -1) { |
@@ -2562,10 +2559,10 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2562 | 2559 | ||
2563 | case TOR: | 2560 | case TOR: |
2564 | case TAND: | 2561 | case TAND: |
2565 | rv = execute(t->left, pin, pout, 0); | 2562 | rv = execute(t->left, pin, pout, /* no_fork: */ 0); |
2566 | t1 = t->right; | 2563 | t1 = t->right; |
2567 | if (t1 != NULL && (rv == 0) == (t->type == TAND)) | 2564 | if (t1 != NULL && (rv == 0) == (t->type == TAND)) |
2568 | rv = execute(t1, pin, pout, 0); | 2565 | rv = execute(t1, pin, pout, /* no_fork: */ 0); |
2569 | break; | 2566 | break; |
2570 | 2567 | ||
2571 | case TFOR: | 2568 | case TFOR: |
@@ -2585,7 +2582,7 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2585 | brkset(&bc); | 2582 | brkset(&bc); |
2586 | for (t1 = t->left; i-- && *wp != NULL;) { | 2583 | for (t1 = t->left; i-- && *wp != NULL;) { |
2587 | setval(vp, *wp++); | 2584 | setval(vp, *wp++); |
2588 | rv = execute(t1, pin, pout, 0); | 2585 | rv = execute(t1, pin, pout, /* no_fork: */ 0); |
2589 | } | 2586 | } |
2590 | brklist = brklist->nextlev; | 2587 | brklist = brklist->nextlev; |
2591 | break; | 2588 | break; |
@@ -2597,17 +2594,17 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2597 | goto broken; | 2594 | goto broken; |
2598 | brkset(&bc); | 2595 | brkset(&bc); |
2599 | t1 = t->left; | 2596 | t1 = t->left; |
2600 | while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE)) | 2597 | while ((execute(t1, pin, pout, /* no_fork: */ 0) == 0) == (t->type == TWHILE)) |
2601 | rv = execute(t->right, pin, pout, 0); | 2598 | rv = execute(t->right, pin, pout, /* no_fork: */ 0); |
2602 | brklist = brklist->nextlev; | 2599 | brklist = brklist->nextlev; |
2603 | break; | 2600 | break; |
2604 | 2601 | ||
2605 | case TIF: | 2602 | case TIF: |
2606 | case TELIF: | 2603 | case TELIF: |
2607 | if (t->right != NULL) { | 2604 | if (t->right != NULL) { |
2608 | rv = !execute(t->left, pin, pout, 0) ? | 2605 | rv = !execute(t->left, pin, pout, /* no_fork: */ 0) ? |
2609 | execute(t->right->left, pin, pout, 0) : | 2606 | execute(t->right->left, pin, pout, /* no_fork: */ 0) : |
2610 | execute(t->right->right, pin, pout, 0); | 2607 | execute(t->right->right, pin, pout, /* no_fork: */ 0); |
2611 | } | 2608 | } |
2612 | break; | 2609 | break; |
2613 | 2610 | ||
@@ -2623,7 +2620,7 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2623 | t1 = findcase(t->left, cp); | 2620 | t1 = findcase(t->left, cp); |
2624 | if (t1 != NULL) { | 2621 | if (t1 != NULL) { |
2625 | DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1)); | 2622 | DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1)); |
2626 | rv = execute(t1, pin, pout, 0); | 2623 | rv = execute(t1, pin, pout, /* no_fork: */ 0); |
2627 | DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1)); | 2624 | DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1)); |
2628 | } | 2625 | } |
2629 | break; | 2626 | break; |
@@ -2641,7 +2638,7 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2641 | if (rv >= 0) { | 2638 | if (rv >= 0) { |
2642 | t1 = t->left; | 2639 | t1 = t->left; |
2643 | if (t1) { | 2640 | if (t1) { |
2644 | rv = execute(t1, pin, pout, 0); | 2641 | rv = execute(t1, pin, pout, /* no_fork: */ 0); |
2645 | } | 2642 | } |
2646 | } | 2643 | } |
2647 | break; | 2644 | break; |
@@ -2669,8 +2666,6 @@ static int execute(struct op *t, int *pin, int *pout, int act) | |||
2669 | return rv; | 2666 | return rv; |
2670 | } | 2667 | } |
2671 | 2668 | ||
2672 | typedef int (*builtin_func_ptr)(struct op *); | ||
2673 | |||
2674 | static builtin_func_ptr inbuilt(const char *s) | 2669 | static builtin_func_ptr inbuilt(const char *s) |
2675 | { | 2670 | { |
2676 | const struct builtincmd *bp; | 2671 | const struct builtincmd *bp; |
@@ -2681,17 +2676,17 @@ static builtin_func_ptr inbuilt(const char *s) | |||
2681 | return NULL; | 2676 | return NULL; |
2682 | } | 2677 | } |
2683 | 2678 | ||
2684 | static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | 2679 | static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp) |
2685 | { | 2680 | { |
2686 | pid_t newpid; | 2681 | pid_t newpid; |
2687 | int i; | 2682 | int i; |
2688 | builtin_func_ptr bltin = NULL; | 2683 | builtin_func_ptr bltin = NULL; |
2689 | int f; | 2684 | const char *bltin_name = NULL; |
2690 | const char *cp = NULL; | 2685 | const char *cp; |
2691 | struct ioword **iopp; | 2686 | struct ioword **iopp; |
2692 | int resetsig; | 2687 | int resetsig; |
2693 | char **owp; | 2688 | char **owp; |
2694 | int forked = 0; | 2689 | int forked; |
2695 | 2690 | ||
2696 | int *hpin = pin; | 2691 | int *hpin = pin; |
2697 | int *hpout = pout; | 2692 | int *hpout = pout; |
@@ -2712,11 +2707,10 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2712 | (void) &owp; | 2707 | (void) &owp; |
2713 | #endif | 2708 | #endif |
2714 | 2709 | ||
2715 | DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin, | 2710 | DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, no_fork %d\n", t, pin, |
2716 | pout, act)); | 2711 | pout, no_fork)); |
2717 | DBGPRINTF7(("FORKEXEC: t->words is %s\n", | 2712 | DBGPRINTF7(("FORKEXEC: t->words is %s\n", |
2718 | ((t->words == NULL) ? "NULL" : t->words[0]))); | 2713 | ((t->words == NULL) ? "NULL" : t->words[0]))); |
2719 | |||
2720 | owp = wp; | 2714 | owp = wp; |
2721 | resetsig = 0; | 2715 | resetsig = 0; |
2722 | if (t->type == TCOM) { | 2716 | if (t->type == TCOM) { |
@@ -2725,32 +2719,36 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2725 | cp = *wp; | 2719 | cp = *wp; |
2726 | 2720 | ||
2727 | /* strip all initial assignments */ | 2721 | /* strip all initial assignments */ |
2728 | /* not correct wrt PATH=yyy command etc */ | 2722 | /* FIXME: not correct wrt PATH=yyy command etc */ |
2729 | if (FLAG['x']) { | 2723 | if (FLAG['x']) { |
2730 | DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n", | 2724 | DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n", |
2731 | cp, wp, owp)); | 2725 | cp, wp, owp)); |
2732 | echo(cp ? wp : owp); | 2726 | echo(cp ? wp : owp); |
2733 | } | 2727 | } |
2734 | 2728 | ||
2735 | if (cp == NULL && t->ioact == NULL) { | 2729 | if (cp == NULL) { |
2736 | while ((cp = *owp++) != NULL && assign(cp, COPYV)) | 2730 | if (t->ioact == NULL) { |
2737 | continue; | 2731 | while ((cp = *owp++) != NULL && assign(cp, COPYV)) |
2738 | DBGPRINTF(("FORKEXEC: returning setstatus()\n")); | 2732 | continue; |
2739 | return setstatus(0); | 2733 | DBGPRINTF(("FORKEXEC: returning setstatus(0)\n")); |
2740 | } | 2734 | return setstatus(0); |
2741 | if (cp != NULL) { | 2735 | } |
2736 | } else { /* cp != NULL */ | ||
2737 | bltin_name = cp; | ||
2742 | bltin = inbuilt(cp); | 2738 | bltin = inbuilt(cp); |
2743 | } | 2739 | } |
2744 | } | 2740 | } |
2745 | 2741 | ||
2742 | forked = 0; | ||
2746 | t->words = wp; | 2743 | t->words = wp; |
2747 | f = act; | 2744 | DBGPRINTF(("FORKEXEC: bltin %p, no_fork %d, owp %p\n", bltin, |
2748 | 2745 | no_fork, owp)); | |
2749 | DBGPRINTF(("FORKEXEC: bltin %p, f&FEXEC 0x%x, owp %p\n", bltin, | 2746 | /* Don't fork if it is a lone builtin (not in pipe) |
2750 | f & FEXEC, owp)); | 2747 | * OR we are told to _not_ fork */ |
2751 | 2748 | if ((!bltin || pin || pout) /* not lone bltin AND */ | |
2752 | if (!bltin && (f & FEXEC) == 0) { | 2749 | && !no_fork /* not told to avoid fork */ |
2753 | /* Save values in case the child process alters them */ | 2750 | ) { |
2751 | /* Save values in case child alters them after vfork */ | ||
2754 | hpin = pin; | 2752 | hpin = pin; |
2755 | hpout = pout; | 2753 | hpout = pout; |
2756 | hwp = *wp; | 2754 | hwp = *wp; |
@@ -2760,9 +2758,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2760 | hexecflg = execflg; | 2758 | hexecflg = execflg; |
2761 | 2759 | ||
2762 | DBGPRINTF3(("FORKEXEC: calling vfork()...\n")); | 2760 | DBGPRINTF3(("FORKEXEC: calling vfork()...\n")); |
2763 | |||
2764 | newpid = vfork(); | 2761 | newpid = vfork(); |
2765 | |||
2766 | if (newpid == -1) { | 2762 | if (newpid == -1) { |
2767 | DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n")); | 2763 | DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n")); |
2768 | return -1; | 2764 | return -1; |
@@ -2783,8 +2779,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2783 | } | 2779 | } |
2784 | 2780 | ||
2785 | /* Child */ | 2781 | /* Child */ |
2786 | DBGPRINTF(("FORKEXEC: child process, bltin=%p\n", bltin)); | 2782 | DBGPRINTF(("FORKEXEC: child process, bltin=%p (%s)\n", bltin, bltin_name)); |
2787 | |||
2788 | if (interactive) { | 2783 | if (interactive) { |
2789 | signal(SIGINT, SIG_IGN); | 2784 | signal(SIGINT, SIG_IGN); |
2790 | signal(SIGQUIT, SIG_IGN); | 2785 | signal(SIGQUIT, SIG_IGN); |
@@ -2802,20 +2797,6 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2802 | if (!bltin) | 2797 | if (!bltin) |
2803 | export(lookup(cp)); | 2798 | export(lookup(cp)); |
2804 | 2799 | ||
2805 | #if 1 | ||
2806 | /* How to fix it: | ||
2807 | * explicitly pass pin[0] and pout[1] to builtins | ||
2808 | * instead of making them rely on fd 0/1, | ||
2809 | * and do not xmove_fd(pin[0]/pout[1]) below if bltin != NULL. | ||
2810 | */ | ||
2811 | if ((pin || pout) && bltin && bltin != doexec) { | ||
2812 | err("piping to/from shell builtins not yet done"); | ||
2813 | if (forked) | ||
2814 | _exit(-1); | ||
2815 | return -1; | ||
2816 | } | ||
2817 | #endif | ||
2818 | |||
2819 | if (pin) { | 2800 | if (pin) { |
2820 | xmove_fd(pin[0], 0); | 2801 | xmove_fd(pin[0], 0); |
2821 | if (pin[1] != 0) | 2802 | if (pin[1] != 0) |
@@ -2830,33 +2811,36 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2830 | iopp = t->ioact; | 2811 | iopp = t->ioact; |
2831 | if (iopp) { | 2812 | if (iopp) { |
2832 | if (bltin && bltin != doexec) { | 2813 | if (bltin && bltin != doexec) { |
2833 | prs(cp); | 2814 | prs(bltin_name); |
2834 | err(": cannot redirect shell command"); | 2815 | err(": cannot redirect shell command"); |
2835 | if (forked) | 2816 | if (forked) |
2836 | _exit(-1); | 2817 | _exit(-1); |
2837 | return -1; | 2818 | return -1; |
2838 | } | 2819 | } |
2839 | while (*iopp) | 2820 | while (*iopp) { |
2840 | if (iosetup(*iopp++, pin != NULL, pout != NULL)) { | 2821 | if (iosetup(*iopp++, pin != NULL, pout != NULL)) { |
2841 | /* system-detected error */ | 2822 | /* system-detected error */ |
2842 | if (forked) | 2823 | if (forked) |
2843 | _exit(-1); | 2824 | _exit(-1); |
2844 | return -1; | 2825 | return -1; |
2845 | } | 2826 | } |
2827 | } | ||
2846 | } | 2828 | } |
2847 | 2829 | ||
2848 | if (bltin) { | 2830 | if (bltin) { |
2831 | if (forked || pin || pout) { | ||
2832 | /* Builtin in pipe: disallowed */ | ||
2833 | /* TODO: allow "exec"? */ | ||
2834 | prs(bltin_name); | ||
2835 | err(": cannot run builtin as part of pipe"); | ||
2836 | if (forked) | ||
2837 | _exit(-1); | ||
2838 | return -1; | ||
2839 | } | ||
2849 | i = setstatus(bltin(t)); | 2840 | i = setstatus(bltin(t)); |
2850 | if (forked) | 2841 | if (forked) |
2851 | _exit(i); | 2842 | _exit(i); |
2852 | DBGPRINTF(("FORKEXEC: returning i=%d\n", i)); | 2843 | DBGPRINTF(("FORKEXEC: returning i=%d\n", i)); |
2853 | /* Builtins in pipes ("ls /dev/null | cd"): | ||
2854 | * here "cd" (which is not a child) will return to main msh, | ||
2855 | * and we will read from ls's output as if it is our next command! | ||
2856 | * Result: "/dev/null: cannot execute" | ||
2857 | * and then we reach EOF on stdin and exit. | ||
2858 | * See above for possible way to fix this. | ||
2859 | */ | ||
2860 | return i; | 2844 | return i; |
2861 | } | 2845 | } |
2862 | 2846 | ||
@@ -2869,7 +2853,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2869 | } | 2853 | } |
2870 | 2854 | ||
2871 | if (t->type == TPAREN) | 2855 | if (t->type == TPAREN) |
2872 | _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC)); | 2856 | _exit(execute(t->left, NOPIPE, NOPIPE, /* no_fork: */ 1)); |
2873 | if (wp[0] == NULL) | 2857 | if (wp[0] == NULL) |
2874 | _exit(0); | 2858 | _exit(0); |
2875 | 2859 | ||
@@ -2880,7 +2864,7 @@ static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp) | |||
2880 | if (!execflg) | 2864 | if (!execflg) |
2881 | trap[0] = NULL; | 2865 | trap[0] = NULL; |
2882 | 2866 | ||
2883 | DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid)); | 2867 | DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", getpid())); |
2884 | 2868 | ||
2885 | leave(); | 2869 | leave(); |
2886 | /* NOTREACHED */ | 2870 | /* NOTREACHED */ |
@@ -2927,6 +2911,7 @@ static int iosetup(struct ioword *iop, int pipein, int pipeout) | |||
2927 | iop->io_flag = IOCLOSE; | 2911 | iop->io_flag = IOCLOSE; |
2928 | iop->io_flag &= ~(IOREAD | IOWRITE); | 2912 | iop->io_flag &= ~(IOREAD | IOWRITE); |
2929 | } | 2913 | } |
2914 | |||
2930 | switch (iop->io_flag) { | 2915 | switch (iop->io_flag) { |
2931 | case IOREAD: | 2916 | case IOREAD: |
2932 | u = open(cp, O_RDONLY); | 2917 | u = open(cp, O_RDONLY); |
@@ -2944,6 +2929,8 @@ static int iosetup(struct ioword *iop, int pipein, int pipeout) | |||
2944 | lseek(u, (long) 0, SEEK_END); | 2929 | lseek(u, (long) 0, SEEK_END); |
2945 | break; | 2930 | break; |
2946 | } | 2931 | } |
2932 | /* fall through to creation if >>file doesn't exist */ | ||
2933 | |||
2947 | case IOWRITE: | 2934 | case IOWRITE: |
2948 | u = creat(cp, 0666); | 2935 | u = creat(cp, 0666); |
2949 | break; | 2936 | break; |
@@ -2956,6 +2943,7 @@ static int iosetup(struct ioword *iop, int pipein, int pipeout) | |||
2956 | close(iop->io_unit); | 2943 | close(iop->io_unit); |
2957 | return 0; | 2944 | return 0; |
2958 | } | 2945 | } |
2946 | |||
2959 | if (u < 0) { | 2947 | if (u < 0) { |
2960 | prs(cp); | 2948 | prs(cp); |
2961 | prs(": cannot "); | 2949 | prs(": cannot "); |
@@ -3148,7 +3136,7 @@ static int run(struct ioarg *argp, int (*f) (struct ioarg *)) | |||
3148 | yynerrs = 0; | 3136 | yynerrs = 0; |
3149 | failpt = rt; | 3137 | failpt = rt; |
3150 | if (setjmp(failpt) == 0 && yyparse() == 0) | 3138 | if (setjmp(failpt) == 0 && yyparse() == 0) |
3151 | rv = execute(outtree, NOPIPE, NOPIPE, 0); | 3139 | rv = execute(outtree, NOPIPE, NOPIPE, /* no_fork: */ 0); |
3152 | quitenv(); | 3140 | quitenv(); |
3153 | } else { | 3141 | } else { |
3154 | DBGPRINTF(("RUN: error from newenv()!\n")); | 3142 | DBGPRINTF(("RUN: error from newenv()!\n")); |
@@ -3267,20 +3255,21 @@ static int dologin(struct op *t) | |||
3267 | 3255 | ||
3268 | static int doumask(struct op *t) | 3256 | static int doumask(struct op *t) |
3269 | { | 3257 | { |
3270 | int i, n; | 3258 | int i; |
3271 | char *cp; | 3259 | char *cp; |
3272 | 3260 | ||
3273 | cp = t->words[1]; | 3261 | cp = t->words[1]; |
3274 | if (cp == NULL) { | 3262 | if (cp == NULL) { |
3275 | i = umask(0); | 3263 | i = umask(0); |
3276 | umask(i); | 3264 | umask(i); |
3277 | for (n = 3 * 4; (n -= 3) >= 0;) | 3265 | printf("%04o\n", i); |
3278 | fputc('0' + ((i >> n) & 07), stderr); | ||
3279 | fputc('\n', stderr); | ||
3280 | } else { | 3266 | } else { |
3281 | for (n = 0; *cp >= '0' && *cp <= '7'; cp++) | 3267 | i = bb_strtou(cp, NULL, 8); |
3282 | n = n * 8 + (*cp - '0'); | 3268 | if (errno) { |
3283 | umask(n); | 3269 | err("umask: bad octal number"); |
3270 | return 1; | ||
3271 | } | ||
3272 | umask(i); | ||
3284 | } | 3273 | } |
3285 | return 0; | 3274 | return 0; |
3286 | } | 3275 | } |
@@ -3292,14 +3281,15 @@ static int doexec(struct op *t) | |||
3292 | xint *ofail; | 3281 | xint *ofail; |
3293 | 3282 | ||
3294 | t->ioact = NULL; | 3283 | t->ioact = NULL; |
3295 | for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++); | 3284 | for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++) |
3285 | continue; | ||
3296 | if (i == 0) | 3286 | if (i == 0) |
3297 | return 1; | 3287 | return 1; |
3298 | execflg = 1; | 3288 | execflg = 1; |
3299 | ofail = failpt; | 3289 | ofail = failpt; |
3300 | failpt = ex; | 3290 | failpt = ex; |
3301 | if (setjmp(failpt) == 0) | 3291 | if (setjmp(failpt) == 0) |
3302 | execute(t, NOPIPE, NOPIPE, FEXEC); | 3292 | execute(t, NOPIPE, NOPIPE, /* no_fork: */ 1); |
3303 | failpt = ofail; | 3293 | failpt = ofail; |
3304 | execflg = 0; | 3294 | execflg = 0; |
3305 | return 1; | 3295 | return 1; |