diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-01-08 20:32:12 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-01-08 20:32:12 +0000 |
commit | d2c450ce811454fb77679d049538530d2cf54dd8 (patch) | |
tree | 319d23806c17472026e0a946d6ae320f513e34c0 /shell | |
parent | 474d1c57c834ee3dee6de49f109c9b570236fa60 (diff) | |
download | busybox-w32-d2c450ce811454fb77679d049538530d2cf54dd8.tar.gz busybox-w32-d2c450ce811454fb77679d049538530d2cf54dd8.tar.bz2 busybox-w32-d2c450ce811454fb77679d049538530d2cf54dd8.zip |
hush: report [v]fork failures
hush: more correct handling of piping
config: add CONFIG_NOMMU
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/shell/hush.c b/shell/hush.c index b08fe10b6..9dc85d0ba 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1777,8 +1777,8 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | |||
1777 | static int run_pipe_real(struct pipe *pi) | 1777 | static int run_pipe_real(struct pipe *pi) |
1778 | { | 1778 | { |
1779 | int i; | 1779 | int i; |
1780 | int nextin, nextout; | 1780 | int nextin; |
1781 | int pipefds[2]; /* pipefds[0] is for reading */ | 1781 | int pipefds[2]; /* pipefds[0] is for reading */ |
1782 | struct child_prog *child; | 1782 | struct child_prog *child; |
1783 | const struct built_in_command *x; | 1783 | const struct built_in_command *x; |
1784 | char *p; | 1784 | char *p; |
@@ -1789,7 +1789,6 @@ static int run_pipe_real(struct pipe *pi) | |||
1789 | 1789 | ||
1790 | debug_printf_exec("run_pipe_real start: single_fg=%d\n", single_fg); | 1790 | debug_printf_exec("run_pipe_real start: single_fg=%d\n", single_fg); |
1791 | 1791 | ||
1792 | nextin = 0; | ||
1793 | #if ENABLE_HUSH_JOB | 1792 | #if ENABLE_HUSH_JOB |
1794 | pi->pgrp = -1; | 1793 | pi->pgrp = -1; |
1795 | #endif | 1794 | #endif |
@@ -1874,13 +1873,14 @@ static int run_pipe_real(struct pipe *pi) | |||
1874 | #endif | 1873 | #endif |
1875 | } | 1874 | } |
1876 | 1875 | ||
1877 | /* Going to fork a child per each pipe member */ | ||
1878 | pi->running_progs = 0; | ||
1879 | |||
1880 | /* Disable job control signals for shell (parent) and | 1876 | /* Disable job control signals for shell (parent) and |
1881 | * for initial child code after fork */ | 1877 | * for initial child code after fork */ |
1882 | set_jobctrl_sighandler(SIG_IGN); | 1878 | set_jobctrl_sighandler(SIG_IGN); |
1883 | 1879 | ||
1880 | /* Going to fork a child per each pipe member */ | ||
1881 | pi->running_progs = 0; | ||
1882 | nextin = 0; | ||
1883 | |||
1884 | for (i = 0; i < pi->num_progs; i++) { | 1884 | for (i = 0; i < pi->num_progs; i++) { |
1885 | child = &(pi->progs[i]); | 1885 | child = &(pi->progs[i]); |
1886 | if (child->argv) | 1886 | if (child->argv) |
@@ -1889,24 +1889,20 @@ static int run_pipe_real(struct pipe *pi) | |||
1889 | debug_printf_exec(": pipe member with no argv\n"); | 1889 | debug_printf_exec(": pipe member with no argv\n"); |
1890 | 1890 | ||
1891 | /* pipes are inserted between pairs of commands */ | 1891 | /* pipes are inserted between pairs of commands */ |
1892 | if ((i + 1) < pi->num_progs) { | 1892 | pipefds[0] = 0; |
1893 | pipe(pipefds); | 1893 | pipefds[1] = 1; |
1894 | nextout = pipefds[1]; | 1894 | if ((i + 1) < pi->num_progs) |
1895 | } else { | 1895 | xpipe(pipefds); |
1896 | nextout = 1; | ||
1897 | pipefds[0] = -1; | ||
1898 | } | ||
1899 | 1896 | ||
1900 | /* XXX test for failed fork()? */ | ||
1901 | #if BB_MMU | 1897 | #if BB_MMU |
1902 | child->pid = fork(); | 1898 | child->pid = fork(); |
1903 | #else | 1899 | #else |
1904 | child->pid = vfork(); | 1900 | child->pid = vfork(); |
1905 | #endif | 1901 | #endif |
1906 | if (!child->pid) { /* child */ | 1902 | if (!child->pid) { /* child */ |
1903 | #if ENABLE_HUSH_JOB | ||
1907 | /* Every child adds itself to new process group | 1904 | /* Every child adds itself to new process group |
1908 | * with pgid == pid of first child in pipe */ | 1905 | * with pgid == pid of first child in pipe */ |
1909 | #if ENABLE_HUSH_JOB | ||
1910 | if (run_list_level == 1 && interactive_fd) { | 1906 | if (run_list_level == 1 && interactive_fd) { |
1911 | /* Don't do pgrp restore anymore on fatal signals */ | 1907 | /* Don't do pgrp restore anymore on fatal signals */ |
1912 | set_fatal_sighandler(SIG_DFL); | 1908 | set_fatal_sighandler(SIG_DFL); |
@@ -1919,12 +1915,10 @@ static int run_pipe_real(struct pipe *pi) | |||
1919 | } | 1915 | } |
1920 | } | 1916 | } |
1921 | #endif | 1917 | #endif |
1922 | /* in non-interactive case fatal sigs are already SIG_DFL */ | ||
1923 | xmove_fd(nextin, 0); | 1918 | xmove_fd(nextin, 0); |
1924 | xmove_fd(nextout, 1); | 1919 | xmove_fd(pipefds[1], 1); /* write end */ |
1925 | if (pipefds[0] != -1) { | 1920 | if (pipefds[0] > 1) |
1926 | close(pipefds[0]); /* opposite end of our output pipe */ | 1921 | close(pipefds[0]); /* read end */ |
1927 | } | ||
1928 | /* Like bash, explicit redirects override pipes, | 1922 | /* Like bash, explicit redirects override pipes, |
1929 | * and the pipe fd is available for dup'ing. */ | 1923 | * and the pipe fd is available for dup'ing. */ |
1930 | setup_redirects(child, NULL); | 1924 | setup_redirects(child, NULL); |
@@ -1933,25 +1927,29 @@ static int run_pipe_real(struct pipe *pi) | |||
1933 | set_jobctrl_sighandler(SIG_DFL); | 1927 | set_jobctrl_sighandler(SIG_DFL); |
1934 | set_misc_sighandler(SIG_DFL); | 1928 | set_misc_sighandler(SIG_DFL); |
1935 | signal(SIGCHLD, SIG_DFL); | 1929 | signal(SIGCHLD, SIG_DFL); |
1936 | pseudo_exec(child); | 1930 | pseudo_exec(child); /* does not return */ |
1937 | } | 1931 | } |
1938 | 1932 | ||
1939 | pi->running_progs++; | 1933 | if (child->pid < 0) { /* [v]fork failed */ |
1940 | 1934 | /* Clearly indicate, was it fork or vfork */ | |
1935 | bb_perror_msg(BB_MMU ? "cannot fork" : "cannot vfork"); | ||
1936 | } else { | ||
1937 | pi->running_progs++; | ||
1941 | #if ENABLE_HUSH_JOB | 1938 | #if ENABLE_HUSH_JOB |
1942 | /* Second and next children need to know pid of first one */ | 1939 | /* Second and next children need to know pid of first one */ |
1943 | if (pi->pgrp < 0) | 1940 | if (pi->pgrp < 0) |
1944 | pi->pgrp = child->pid; | 1941 | pi->pgrp = child->pid; |
1945 | #endif | 1942 | #endif |
1946 | if (nextin != 0) | 1943 | } |
1947 | close(nextin); | ||
1948 | if (nextout != 1) | ||
1949 | close(nextout); | ||
1950 | 1944 | ||
1951 | /* If there isn't another process, nextin is garbage | 1945 | if (i) |
1952 | but it doesn't matter */ | 1946 | close(nextin); |
1947 | if ((i + 1) < pi->num_progs) | ||
1948 | close(pipefds[1]); /* write end */ | ||
1949 | /* Pass read (output) pipe end to next iteration */ | ||
1953 | nextin = pipefds[0]; | 1950 | nextin = pipefds[0]; |
1954 | } | 1951 | } |
1952 | |||
1955 | debug_printf_exec("run_pipe_real return -1\n"); | 1953 | debug_printf_exec("run_pipe_real return -1\n"); |
1956 | return -1; | 1954 | return -1; |
1957 | } | 1955 | } |