summaryrefslogtreecommitdiff
path: root/redir.c
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>2000-03-17 21:46:59 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:53 +0000
commitbb70624e964126b7ac4ff085ba163a9c35ffa18f (patch)
treeba2dd4add13ada94b1899c6d4aca80195b80b74b /redir.c
parentb72432fdcc59300c6fe7c9d6c8a31ad3447933f5 (diff)
downloadbash-bb70624e964126b7ac4ff085ba163a9c35ffa18f.tar.gz
Imported from ../bash-2.04.tar.gz.
Diffstat (limited to 'redir.c')
-rw-r--r--redir.c252
1 files changed, 185 insertions, 67 deletions
diff --git a/redir.c b/redir.c
index f01d4141..e3dd3d54 100644
--- a/redir.c
+++ b/redir.c
@@ -6,7 +6,7 @@
Bash is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
+ the Free Software Foundation; either version 2, or (at your option)
any later version.
Bash is distributed in the hope that it will be useful, but WITHOUT
@@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License
along with Bash; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#include "config.h"
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
@@ -64,6 +64,7 @@ static void add_exec_redirect ();
static int add_undo_redirect ();
static int do_redirection_internal ();
static int expandable_redirection_filename ();
+static int stdin_redirection ();
/* Spare redirector used when translating [N]>&WORD or [N]<&WORD to a new
redirection and when creating the redirection undo list. */
@@ -79,14 +80,18 @@ redirection_error (temp, error)
int error;
{
char *filename;
+ int oflags;
if (expandable_redirection_filename (temp))
{
- if (posixly_correct && !interactive_shell)
- disallow_filename_globbing++;
+ if (posixly_correct && interactive_shell == 0)
+ {
+ oflags = temp->redirectee.filename->flags;
+ temp->redirectee.filename->flags |= W_NOGLOB;
+ }
filename = redirection_expand (temp->redirectee.filename);
- if (posixly_correct && !interactive_shell)
- disallow_filename_globbing--;
+ if (posixly_correct && interactive_shell == 0)
+ temp->redirectee.filename->flags = oflags;
if (filename == 0)
filename = savestring (temp->redirectee.filename->word);
if (filename == 0)
@@ -195,8 +200,13 @@ redirection_expand (word)
{
char *result;
WORD_LIST *tlist1, *tlist2;
+ WORD_DESC *w;
+
+ w = copy_word (word);
+ if (posixly_correct)
+ w->flags |= W_NOSPLIT;
- tlist1 = make_word_list (copy_word (word), (WORD_LIST *)NULL);
+ tlist1 = make_word_list (w, (WORD_LIST *)NULL);
tlist2 = expand_words_no_vars (tlist1);
dispose_words (tlist1);
@@ -293,7 +303,7 @@ here_document_to_fd (redirectee)
WORD_DESC *redirectee;
{
char filename[24];
- int r, fd;
+ int r, fd, fd2;
static int fnum = 0;
do
@@ -315,44 +325,122 @@ here_document_to_fd (redirectee)
if (redirectee->word)
r = write_here_document (fd, redirectee);
- close (fd);
if (r)
{
+ close (fd);
unlink (filename);
errno = r;
return (-1);
}
- /* XXX - this is raceable */
+ /* In an attempt to avoid races, we close the first fd only after opening
+ the second. */
/* Make the document really temporary. Also make it the input. */
- fd = open (filename, O_RDONLY, 0600);
+ fd2 = open (filename, O_RDONLY, 0600);
- if (fd < 0)
+ if (fd2 < 0)
{
r = errno;
unlink (filename);
+ close (fd);
errno = r;
return -1;
}
+ close (fd);
if (unlink (filename) < 0)
{
r = errno;
- close (fd);
+ close (fd2);
errno = r;
return (-1);
}
- return (fd);
+ return (fd2);
}
+#define RF_DEVFD 1
+#define RF_DEVSTDERR 2
+#define RF_DEVSTDIN 3
+#define RF_DEVSTDOUT 4
+#define RF_DEVTCP 5
+#define RF_DEVUDP 6
+
+/* A list of pattern/value pairs for filenames that the redirection
+ code handles specially. */
+static STRING_INT_ALIST _redir_special_filenames[] = {
+#if !defined (HAVE_DEV_FD)
+ { "/dev/fd/[0-9]*", RF_DEVFD },
+#endif
+#if !defined (HAVE_DEV_STDIN)
+ { "/dev/stderr", RF_DEVSTDERR },
+ { "/dev/stdin", RF_DEVSTDIN },
+ { "/dev/stdout", RF_DEVSTDOUT },
+#endif
+#if defined (NETWORK_REDIRECTIONS)
+ { "/dev/tcp/*/*", RF_DEVTCP },
+ { "/dev/udp/*/*", RF_DEVUDP },
+#endif
+ { (char *)NULL, -1 }
+};
+
+static int
+redir_special_open (spec, filename, flags, mode, ri)
+ int spec;
+ char *filename;
+ int flags, mode;
+ enum r_instruction ri;
+{
+ int fd;
+ long lfd;
+
+ fd = -1;
+ switch (spec)
+ {
+#if !defined (HAVE_DEV_FD)
+ case RF_DEVFD:
+ if (legal_number, filename+8, &lfd)
+ fd = fcntl ((int)lfd, F_DUPFD, 10);
+ else
+ fd = AMBIGUOUS_REDIRECT;
+ break;
+#endif
+
+#if !defined (HAVE_DEV_STDIN)
+ case RF_DEVSTDIN:
+ fd = fcntl (0, F_DUPFD, 10);
+ break;
+ case RF_DEVSTDOUT:
+ fd = fcntl (1, F_DUPFD, 10);
+ break;
+ case RF_DEVSTDERR:
+ fd = fcntl (2, F_DUPFD, 10);
+ break;
+#endif
+
+#if defined (NETWORK_REDIRECTIONS)
+ case RF_DEVTCP:
+ case RF_DEVUDP:
+#if defined (HAVE_NETWORK)
+ fd = netopen (filename);
+#else
+ internal_warning ("/dev/(tcp|udp)/host/port not supported without networking");
+ fd = open (filename, flags, mode);
+#endif
+ break;
+#endif /* NETWORK_REDIRECTIONS */
+ }
+
+ return fd;
+}
+
/* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
race conditions and avoiding the problem where the file is replaced
between the stat(2) and open(2). */
static int
-noclobber_open (filename, flags, ri)
+noclobber_open (filename, flags, mode, ri)
char *filename;
- int flags;
+ int flags, mode;
enum r_instruction ri;
{
int r, fd;
@@ -372,10 +460,10 @@ noclobber_open (filename, flags, ri)
flags &= ~O_TRUNC;
if (r != 0)
{
- fd = open (filename, flags|O_EXCL, 0666);
+ fd = open (filename, flags|O_EXCL, mode);
return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
}
- fd = open (filename, flags, 0666);
+ fd = open (filename, flags, mode);
/* If the open failed, return the file descriptor right away. */
if (fd < 0)
@@ -401,6 +489,38 @@ noclobber_open (filename, flags, ri)
return (NOCLOBBER_REDIRECT);
}
+static int
+redir_open (filename, flags, mode, ri)
+ char *filename;
+ int flags, mode;
+ enum r_instruction ri;
+{
+ int fd, r;
+
+ r = find_string_in_alist (filename, _redir_special_filenames, 1);
+ if (r >= 0)
+ return (redir_special_open (r, filename, flags, mode, ri));
+
+ /* If we are in noclobber mode, you are not allowed to overwrite
+ existing files. Check before opening. */
+ if (noclobber && OUTPUT_REDIRECT (ri))
+ {
+ fd = noclobber_open (filename, flags, mode, ri);
+ if (fd == NOCLOBBER_REDIRECT)
+ return (NOCLOBBER_REDIRECT);
+ }
+ else
+ {
+ fd = open (filename, flags, mode);
+#if defined (AFS)
+ if ((fd < 0) && (errno == EACCES))
+ fd = open (filename, flags & ~O_CREAT, mode);
+#endif /* AFS */
+ }
+
+ return fd;
+}
+
/* Do the specific redirection requested. Returns errno or one of the
special redirection errors (*_REDIRECT) in case of error, 0 on success.
If FOR_REAL is zero, then just do whatever is neccessary to produce the
@@ -413,7 +533,7 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
int for_real, remembering, set_clexec;
{
WORD_DESC *redirectee;
- int redir_fd, fd, redirector, r;
+ int redir_fd, fd, redirector, r, oflags;
char *redirectee_word;
enum r_instruction ri;
REDIRECT *new_redirect;
@@ -506,11 +626,14 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
case r_err_and_out: /* command &>filename */
case r_input_output:
case r_output_force:
- if (posixly_correct && !interactive_shell)
- disallow_filename_globbing++;
+ if (posixly_correct && interactive_shell == 0)
+ {
+ oflags = redirectee->flags;
+ redirectee->flags |= W_NOGLOB;
+ }
redirectee_word = redirection_expand (redirectee);
- if (posixly_correct && !interactive_shell)
- disallow_filename_globbing--;
+ if (posixly_correct && interactive_shell == 0)
+ redirectee->flags = oflags;
if (redirectee_word == 0)
return (AMBIGUOUS_REDIRECT);
@@ -523,27 +646,12 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
}
#endif /* RESTRICTED_SHELL */
- /* If we are in noclobber mode, you are not allowed to overwrite
- existing files. Check before opening. */
- if (noclobber && OUTPUT_REDIRECT (ri))
- {
- fd = noclobber_open (redirectee_word, redirect->flags, ri);
- if (fd == NOCLOBBER_REDIRECT)
- {
- free (redirectee_word);
- return (NOCLOBBER_REDIRECT);
- }
- }
- else
- {
- fd = open (redirectee_word, redirect->flags, 0666);
-#if defined (AFS)
- if ((fd < 0) && (errno == EACCES))
- fd = open (redirectee_word, redirect->flags & ~O_CREAT, 0666);
-#endif /* AFS */
- }
+ fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
free (redirectee_word);
+ if (fd == NOCLOBBER_REDIRECT)
+ return (fd);
+
if (fd < 0)
return (errno);
@@ -650,10 +758,11 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
SET_CLOSE_ON_EXEC (redirector);
}
+ if (fd != redirector)
#if defined (BUFFERED_INPUT)
- close_buffered_fd (fd);
+ close_buffered_fd (fd);
#else
- close (fd);
+ close (fd);
#endif
}
break;
@@ -672,6 +781,7 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
#if defined (BUFFERED_INPUT)
check_bash_input (redirector);
#endif
+
/* This is correct. 2>&1 means dup2 (1, 2); */
if (dup2 (redir_fd, redirector) < 0)
return (errno);
@@ -791,6 +901,36 @@ add_exec_redirect (dummy_redirect)
exec_redirection_undo_list = dummy_redirect;
}
+/* Return 1 if the redirection specified by RI and REDIRECTOR alters the
+ standard input. */
+static int
+stdin_redirection (ri, redirector)
+ enum r_instruction ri;
+ int redirector;
+{
+ switch (ri)
+ {
+ case r_input_direction:
+ case r_inputa_direction:
+ case r_input_output:
+ case r_reading_until:
+ case r_deblank_reading_until:
+ return (1);
+ case r_duplicating_input:
+ case r_duplicating_input_word:
+ case r_close_this:
+ return (redirector == 0);
+ case r_output_direction:
+ case r_appending_to:
+ case r_duplicating_output:
+ case r_err_and_out:
+ case r_output_force:
+ case r_duplicating_output_word:
+ return (0);
+ }
+ return (0);
+}
+
/* Return non-zero if any of the redirections in REDIRS alter the standard
input. */
int
@@ -801,28 +941,6 @@ stdin_redirects (redirs)
int n;
for (n = 0, rp = redirs; rp; rp = rp->next)
- switch (rp->instruction)
- {
- case r_input_direction:
- case r_inputa_direction:
- case r_input_output:
- case r_reading_until:
- case r_deblank_reading_until:
- n++;
- break;
- case r_duplicating_input:
- case r_duplicating_input_word:
- case r_close_this:
- n += (rp->redirector == 0);
- break;
- case r_output_direction:
- case r_appending_to:
- case r_duplicating_output:
- case r_err_and_out:
- case r_output_force:
- case r_duplicating_output_word:
- break;
- }
-
+ n += stdin_redirection (rp->instruction, rp->redirector);
return n;
}