diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-02 15:35:45 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-02 15:35:45 +0000 |
commit | 4ac530c0ef4f2c4c15a177456b01e240bfb9f1aa (patch) | |
tree | 3485963e2615b501d56aa03ff8f399abbce7c53c /shell/hush.c | |
parent | ef36ead37061690f9a20b5f03164e99ab1b9bdd4 (diff) | |
download | busybox-w32-4ac530c0ef4f2c4c15a177456b01e240bfb9f1aa.tar.gz busybox-w32-4ac530c0ef4f2c4c15a177456b01e240bfb9f1aa.tar.bz2 busybox-w32-4ac530c0ef4f2c4c15a177456b01e240bfb9f1aa.zip |
hush: add debugging for tracing execution,
add FIXME for 'true | exit 3; echo $?' case
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/shell/hush.c b/shell/hush.c index 8dfe2be93..f931a06e1 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -85,6 +85,7 @@ | |||
85 | //#define DEBUG_SHELL | 85 | //#define DEBUG_SHELL |
86 | /* Finer-grained debug switch */ | 86 | /* Finer-grained debug switch */ |
87 | //#define DEBUG_SHELL_JOBS | 87 | //#define DEBUG_SHELL_JOBS |
88 | //#define DEBUG_SHELL_EXECUTION | ||
88 | 89 | ||
89 | #if !ENABLE_HUSH_INTERACTIVE | 90 | #if !ENABLE_HUSH_INTERACTIVE |
90 | #undef ENABLE_FEATURE_EDITING | 91 | #undef ENABLE_FEATURE_EDITING |
@@ -315,6 +316,12 @@ static char *indenter(int i) | |||
315 | #define debug_jobs_printf(...) do {} while (0) | 316 | #define debug_jobs_printf(...) do {} while (0) |
316 | #endif | 317 | #endif |
317 | 318 | ||
319 | #ifdef DEBUG_SHELL_EXECUTION | ||
320 | #define debug_exec_printf(...) fprintf(stderr, __VA_ARGS__) | ||
321 | #else | ||
322 | #define debug_exec_printf(...) do {} while (0) | ||
323 | #endif | ||
324 | |||
318 | #define final_printf debug_printf | 325 | #define final_printf debug_printf |
319 | 326 | ||
320 | static void __syntax(int line) | 327 | static void __syntax(int line) |
@@ -1322,11 +1329,11 @@ static void pseudo_exec(struct child_prog *child) | |||
1322 | } | 1329 | } |
1323 | 1330 | ||
1324 | if (child->group) { | 1331 | if (child->group) { |
1325 | debug_printf("runtime nesting to group\n"); | ||
1326 | // FIXME: do not modify globals! Think vfork! | 1332 | // FIXME: do not modify globals! Think vfork! |
1327 | #if ENABLE_HUSH_INTERACTIVE | 1333 | #if ENABLE_HUSH_INTERACTIVE |
1328 | interactive_fd = 0; /* crucial!!!! */ | 1334 | interactive_fd = 0; /* crucial!!!! */ |
1329 | #endif | 1335 | #endif |
1336 | debug_exec_printf("pseudo_exec: run_list_real\n"); | ||
1330 | rcode = run_list_real(child->group); | 1337 | rcode = run_list_real(child->group); |
1331 | /* OK to leak memory by not calling free_pipe_list, | 1338 | /* OK to leak memory by not calling free_pipe_list, |
1332 | * since this process is about to exit */ | 1339 | * since this process is about to exit */ |
@@ -1641,6 +1648,8 @@ static int run_pipe_real(struct pipe *pi) | |||
1641 | int rcode; | 1648 | int rcode; |
1642 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); | 1649 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); |
1643 | 1650 | ||
1651 | debug_exec_printf("run_pipe_real start:\n"); | ||
1652 | |||
1644 | nextin = 0; | 1653 | nextin = 0; |
1645 | #if ENABLE_HUSH_JOB | 1654 | #if ENABLE_HUSH_JOB |
1646 | pi->pgrp = -1; | 1655 | pi->pgrp = -1; |
@@ -1658,8 +1667,10 @@ static int run_pipe_real(struct pipe *pi) | |||
1658 | setup_redirects(child, squirrel); | 1667 | setup_redirects(child, squirrel); |
1659 | /* XXX could we merge code with following builtin case, | 1668 | /* XXX could we merge code with following builtin case, |
1660 | * by creating a pseudo builtin that calls run_list_real? */ | 1669 | * by creating a pseudo builtin that calls run_list_real? */ |
1670 | debug_exec_printf(": run_list_real\n"); | ||
1661 | rcode = run_list_real(child->group); | 1671 | rcode = run_list_real(child->group); |
1662 | restore_redirects(squirrel); | 1672 | restore_redirects(squirrel); |
1673 | debug_exec_printf("run_pipe_real return %d\n", rcode); | ||
1663 | return rcode; | 1674 | return rcode; |
1664 | } | 1675 | } |
1665 | 1676 | ||
@@ -1707,8 +1718,10 @@ static int run_pipe_real(struct pipe *pi) | |||
1707 | char *str; | 1718 | char *str; |
1708 | 1719 | ||
1709 | str = make_string(argv + i); | 1720 | str = make_string(argv + i); |
1721 | debug_exec_printf(": parse_string_outer '%s'\n", str); | ||
1710 | parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING); | 1722 | parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING); |
1711 | free(str); | 1723 | free(str); |
1724 | debug_exec_printf("run_pipe_real return %d\n", last_return_code); | ||
1712 | return last_return_code; | 1725 | return last_return_code; |
1713 | } | 1726 | } |
1714 | for (x = bltins; x->cmd; x++) { | 1727 | for (x = bltins; x->cmd; x++) { |
@@ -1725,8 +1738,10 @@ static int run_pipe_real(struct pipe *pi) | |||
1725 | * things seem to work with glibc. */ | 1738 | * things seem to work with glibc. */ |
1726 | // TODO: fflush(NULL)? | 1739 | // TODO: fflush(NULL)? |
1727 | setup_redirects(child, squirrel); | 1740 | setup_redirects(child, squirrel); |
1741 | debug_exec_printf(": builtin '%s' '%s'...\n", x->cmd, argv[i+1]); | ||
1728 | rcode = x->function(argv + i); | 1742 | rcode = x->function(argv + i); |
1729 | restore_redirects(squirrel); | 1743 | restore_redirects(squirrel); |
1744 | debug_exec_printf("run_pipe_real return %d\n", rcode); | ||
1730 | return rcode; | 1745 | return rcode; |
1731 | } | 1746 | } |
1732 | } | 1747 | } |
@@ -1735,8 +1750,10 @@ static int run_pipe_real(struct pipe *pi) | |||
1735 | const struct bb_applet *a = find_applet_by_name(argv[i]); | 1750 | const struct bb_applet *a = find_applet_by_name(argv[i]); |
1736 | if (a && a->nofork) { | 1751 | if (a && a->nofork) { |
1737 | setup_redirects(child, squirrel); | 1752 | setup_redirects(child, squirrel); |
1753 | debug_exec_printf(": run_single_fg_nofork '%s' '%s'...\n", argv[i], argv[i+1]); | ||
1738 | rcode = run_single_fg_nofork(pi, a, argv + i); | 1754 | rcode = run_single_fg_nofork(pi, a, argv + i); |
1739 | restore_redirects(squirrel); | 1755 | restore_redirects(squirrel); |
1756 | debug_exec_printf("run_pipe_real return %d\n", rcode); | ||
1740 | return rcode; | 1757 | return rcode; |
1741 | } | 1758 | } |
1742 | } | 1759 | } |
@@ -1751,6 +1768,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1751 | 1768 | ||
1752 | for (i = 0; i < pi->num_progs; i++) { | 1769 | for (i = 0; i < pi->num_progs; i++) { |
1753 | child = &(pi->progs[i]); | 1770 | child = &(pi->progs[i]); |
1771 | debug_exec_printf(": pipe member '%s' '%s'...\n", child->argv[0], child->argv[1]); | ||
1754 | 1772 | ||
1755 | /* pipes are inserted between pairs of commands */ | 1773 | /* pipes are inserted between pairs of commands */ |
1756 | if ((i + 1) < pi->num_progs) { | 1774 | if ((i + 1) < pi->num_progs) { |
@@ -1831,6 +1849,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1831 | but it doesn't matter */ | 1849 | but it doesn't matter */ |
1832 | nextin = pipefds[0]; | 1850 | nextin = pipefds[0]; |
1833 | } | 1851 | } |
1852 | debug_exec_printf("run_pipe_real return -1\n"); | ||
1834 | return -1; | 1853 | return -1; |
1835 | } | 1854 | } |
1836 | 1855 | ||
@@ -1846,18 +1865,23 @@ static int run_list_real(struct pipe *pi) | |||
1846 | int flag_restore = 0; | 1865 | int flag_restore = 0; |
1847 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ | 1866 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ |
1848 | reserved_style rmode, skip_more_in_this_rmode = RES_XXXX; | 1867 | reserved_style rmode, skip_more_in_this_rmode = RES_XXXX; |
1868 | |||
1869 | debug_exec_printf("run_list_real start:\n"); | ||
1870 | |||
1849 | /* check syntax for "for" */ | 1871 | /* check syntax for "for" */ |
1850 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { | 1872 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { |
1851 | if ((rpipe->r_mode == RES_IN || rpipe->r_mode == RES_FOR) | 1873 | if ((rpipe->r_mode == RES_IN || rpipe->r_mode == RES_FOR) |
1852 | && (rpipe->next == NULL) | 1874 | && (rpipe->next == NULL) |
1853 | ) { | 1875 | ) { |
1854 | syntax(); | 1876 | syntax(); |
1877 | debug_exec_printf("run_list_real return 1\n"); | ||
1855 | return 1; | 1878 | return 1; |
1856 | } | 1879 | } |
1857 | if ((rpipe->r_mode == RES_IN && rpipe->next->r_mode == RES_IN && rpipe->next->progs->argv != NULL) | 1880 | if ((rpipe->r_mode == RES_IN && rpipe->next->r_mode == RES_IN && rpipe->next->progs->argv != NULL) |
1858 | || (rpipe->r_mode == RES_FOR && rpipe->next->r_mode != RES_IN) | 1881 | || (rpipe->r_mode == RES_FOR && rpipe->next->r_mode != RES_IN) |
1859 | ) { | 1882 | ) { |
1860 | syntax(); | 1883 | syntax(); |
1884 | debug_exec_printf("run_list_real return 1\n"); | ||
1861 | return 1; | 1885 | return 1; |
1862 | } | 1886 | } |
1863 | } | 1887 | } |
@@ -1933,8 +1957,8 @@ static int run_list_real(struct pipe *pi) | |||
1933 | if (pi->num_progs == 0) | 1957 | if (pi->num_progs == 0) |
1934 | continue; | 1958 | continue; |
1935 | save_num_progs = pi->num_progs; /* save number of programs */ | 1959 | save_num_progs = pi->num_progs; /* save number of programs */ |
1960 | debug_exec_printf(": run_pipe_real with %d members\n", pi->num_progs); | ||
1936 | rcode = run_pipe_real(pi); | 1961 | rcode = run_pipe_real(pi); |
1937 | debug_printf("run_pipe_real returned %d\n", rcode); | ||
1938 | if (rcode != -1) { | 1962 | if (rcode != -1) { |
1939 | /* We only ran a builtin: rcode was set by the return value | 1963 | /* We only ran a builtin: rcode was set by the return value |
1940 | * of run_pipe_real(), and we don't need to wait for anything. */ | 1964 | * of run_pipe_real(), and we don't need to wait for anything. */ |
@@ -1972,6 +1996,7 @@ static int run_list_real(struct pipe *pi) | |||
1972 | } | 1996 | } |
1973 | checkjobs(NULL); | 1997 | checkjobs(NULL); |
1974 | } | 1998 | } |
1999 | debug_exec_printf("run_list_real return %d\n", rcode); | ||
1975 | return rcode; | 2000 | return rcode; |
1976 | } | 2001 | } |
1977 | 2002 | ||
@@ -2047,6 +2072,7 @@ static int run_list(struct pipe *pi) | |||
2047 | { | 2072 | { |
2048 | int rcode = 0; | 2073 | int rcode = 0; |
2049 | if (fake_mode == 0) { | 2074 | if (fake_mode == 0) { |
2075 | debug_exec_printf("run_list: run_list_real with %d members\n", pi->num_progs); | ||
2050 | rcode = run_list_real(pi); | 2076 | rcode = run_list_real(pi); |
2051 | } | 2077 | } |
2052 | /* free_pipe_list has the side effect of clearing memory | 2078 | /* free_pipe_list has the side effect of clearing memory |
@@ -3083,6 +3109,10 @@ static void update_ifs_map(void) | |||
3083 | * from builtin_source() */ | 3109 | * from builtin_source() */ |
3084 | static int parse_stream_outer(struct in_str *inp, int flag) | 3110 | static int parse_stream_outer(struct in_str *inp, int flag) |
3085 | { | 3111 | { |
3112 | // FIXME: 'true | exit 3; echo $?' is parsed as a whole, | ||
3113 | // as a result $? is replaced by 0, not 3! | ||
3114 | // Need to stop & execute stuff at ';', not parse till EOL! | ||
3115 | |||
3086 | struct p_context ctx; | 3116 | struct p_context ctx; |
3087 | o_string temp = NULL_O_STRING; | 3117 | o_string temp = NULL_O_STRING; |
3088 | int rcode; | 3118 | int rcode; |
@@ -3102,6 +3132,7 @@ static int parse_stream_outer(struct in_str *inp, int flag) | |||
3102 | if (rcode != 1 && ctx.old_flag == 0) { | 3132 | if (rcode != 1 && ctx.old_flag == 0) { |
3103 | done_word(&temp, &ctx); | 3133 | done_word(&temp, &ctx); |
3104 | done_pipe(&ctx, PIPE_SEQ); | 3134 | done_pipe(&ctx, PIPE_SEQ); |
3135 | debug_exec_printf("parse_stream_outer: run_list\n"); | ||
3105 | run_list(ctx.list_head); | 3136 | run_list(ctx.list_head); |
3106 | } else { | 3137 | } else { |
3107 | if (ctx.old_flag != 0) { | 3138 | if (ctx.old_flag != 0) { |