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 /shell | |
| 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
Diffstat (limited to 'shell')
| -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; |
