aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-08-20 15:16:00 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-08-20 15:16:00 +0200
commit869994cf4f9647fdfb519a1945f8582e71d3df3d (patch)
tree30741b547421ab4c82e5bdf631afacec7665e3e0 /shell
parente9abe75fda82a986b0b40969ebdd4aa92bcb52e3 (diff)
downloadbusybox-w32-869994cf4f9647fdfb519a1945f8582e71d3df3d.tar.gz
busybox-w32-869994cf4f9647fdfb519a1945f8582e71d3df3d.tar.bz2
busybox-w32-869994cf4f9647fdfb519a1945f8582e71d3df3d.zip
hush: bit better comments in redirect code. No logic changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/shell/hush.c b/shell/hush.c
index b41d9d04b..9b45b312f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -6099,10 +6099,12 @@ static int setup_redirects(struct command *prog, int squirrel[])
6099 6099
6100 for (redir = prog->redirects; redir; redir = redir->next) { 6100 for (redir = prog->redirects; redir; redir = redir->next) {
6101 if (redir->rd_type == REDIRECT_HEREDOC2) { 6101 if (redir->rd_type == REDIRECT_HEREDOC2) {
6102 /* rd_fd<<HERE case */ 6102 /* "rd_fd<<HERE" case */
6103 if (squirrel && redir->rd_fd < 3 6103 if (redir->rd_fd <= 2
6104 && squirrel
6104 && squirrel[redir->rd_fd] < 0 6105 && squirrel[redir->rd_fd] < 0
6105 ) { 6106 ) {
6107 /* Save old fds 0..2 if redirect uses them */
6106 squirrel[redir->rd_fd] = dup(redir->rd_fd); 6108 squirrel[redir->rd_fd] = dup(redir->rd_fd);
6107 } 6109 }
6108 /* for REDIRECT_HEREDOC2, rd_filename holds _contents_ 6110 /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
@@ -6114,7 +6116,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
6114 } 6116 }
6115 6117
6116 if (redir->rd_dup == REDIRFD_TO_FILE) { 6118 if (redir->rd_dup == REDIRFD_TO_FILE) {
6117 /* rd_fd<*>file case (<*> is <,>,>>,<>) */ 6119 /* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
6118 char *p; 6120 char *p;
6119 if (redir->rd_filename == NULL) { 6121 if (redir->rd_filename == NULL) {
6120 /* Something went wrong in the parse. 6122 /* Something went wrong in the parse.
@@ -6127,20 +6129,33 @@ static int setup_redirects(struct command *prog, int squirrel[])
6127 openfd = open_or_warn(p, mode); 6129 openfd = open_or_warn(p, mode);
6128 free(p); 6130 free(p);
6129 if (openfd < 0) { 6131 if (openfd < 0) {
6130 /* this could get lost if stderr has been redirected, but 6132 /* Error message from open_or_warn can be lost
6131 * bash and ash both lose it as well (though zsh doesn't!) */ 6133 * if stderr has been redirected, but bash
6132//what the above comment tries to say? 6134 * and ash both lose it as well
6135 * (though zsh doesn't!)
6136 */
6133 return 1; 6137 return 1;
6134 } 6138 }
6135 } else { 6139 } else {
6136 /* rd_fd<*>rd_dup or rd_fd<*>- cases */ 6140 /* "rd_fd<*>rd_dup" or "rd_fd<*>-" cases */
6137 openfd = redir->rd_dup; 6141 openfd = redir->rd_dup;
6138 } 6142 }
6139 6143
6140 if (openfd != redir->rd_fd) { 6144 if (openfd != redir->rd_fd) {
6141 if (squirrel && redir->rd_fd < 3 6145 if (redir->rd_fd <= 2
6146 && squirrel
6142 && squirrel[redir->rd_fd] < 0 6147 && squirrel[redir->rd_fd] < 0
6143 ) { 6148 ) {
6149 /* Save old fds 0..2 if redirect uses them */
6150//FIXME: script fd's also need this! "sh SCRIPT" and SCRIPT has "echo FOO 3>&-":
6151// open("SCRIPT", O_RDONLY) = 3
6152// fcntl(3, F_SETFD, FD_CLOEXEC) = 0
6153// read(3, "echo FOO 3>&-\n....", 4096) = N
6154// close(3) = 0
6155// write(1, "FOO\n", 4) = 4
6156// ...
6157// read(3, 0x205f8e0, 4096) = -1 EBADF <== BUG
6158//
6144 squirrel[redir->rd_fd] = dup(redir->rd_fd); 6159 squirrel[redir->rd_fd] = dup(redir->rd_fd);
6145 } 6160 }
6146 if (openfd == REDIRFD_CLOSE) { 6161 if (openfd == REDIRFD_CLOSE) {
@@ -6159,7 +6174,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
6159static void restore_redirects(int squirrel[]) 6174static void restore_redirects(int squirrel[])
6160{ 6175{
6161 int i, fd; 6176 int i, fd;
6162 for (i = 0; i < 3; i++) { 6177 for (i = 0; i <= 2; i++) {
6163 fd = squirrel[i]; 6178 fd = squirrel[i];
6164 if (fd != -1) { 6179 if (fd != -1) {
6165 /* We simply die on error */ 6180 /* We simply die on error */
@@ -7144,6 +7159,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
7144 if (x->b_function == builtin_exec && argv_expanded[1] == NULL) { 7159 if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
7145 debug_printf("exec with redirects only\n"); 7160 debug_printf("exec with redirects only\n");
7146 rcode = setup_redirects(command, NULL); 7161 rcode = setup_redirects(command, NULL);
7162 /* rcode=1 can be if redir file can't be opened */
7147 goto clean_up_and_ret1; 7163 goto clean_up_and_ret1;
7148 } 7164 }
7149 } 7165 }
@@ -7270,9 +7286,20 @@ static NOINLINE int run_pipe(struct pipe *pi)
7270 if (pipefds.rd > 1) 7286 if (pipefds.rd > 1)
7271 close(pipefds.rd); 7287 close(pipefds.rd);
7272 /* Like bash, explicit redirects override pipes, 7288 /* Like bash, explicit redirects override pipes,
7273 * and the pipe fd is available for dup'ing. */ 7289 * and the pipe fd (fd#1) is available for dup'ing:
7274 if (setup_redirects(command, NULL)) 7290 * "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
7291 * of cmd1 goes into pipe.
7292 */
7293 if (setup_redirects(command, NULL)) {
7294 /* Happens when redir file can't be opened:
7295 * $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
7296 * FOO
7297 * hush: can't open '/qwe/rty': No such file or directory
7298 * BAZ
7299 * (echo BAR is not executed, it hits _exit(1) below)
7300 */
7275 _exit(1); 7301 _exit(1);
7302 }
7276 7303
7277 /* Stores to nommu_save list of env vars putenv'ed 7304 /* Stores to nommu_save list of env vars putenv'ed
7278 * (NOMMU, on MMU we don't need that) */ 7305 * (NOMMU, on MMU we don't need that) */