Bash-4.1 distribution source

This commit is contained in:
Chet Ramey 2011-11-21 20:51:19 -05:00
commit 0001803f0b
252 changed files with 51563 additions and 37176 deletions

174
redir.c
View file

@ -82,6 +82,9 @@ static int redir_special_open __P((int, char *, int, int, enum r_instruction));
static int noclobber_open __P((char *, int, int, enum r_instruction));
static int redir_open __P((char *, int, int, enum r_instruction));
static int redir_varassign __P((REDIRECT *, int));
static int redir_varvalue __P((REDIRECT *));
/* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
a new redirection and when creating the redirection undo list. */
static REDIRECTEE rd;
@ -99,13 +102,15 @@ redirection_error (temp, error)
int oflags;
allocname = 0;
if (temp->redirector < 0)
if (temp->rflags & REDIR_VARASSIGN)
filename = savestring (temp->redirector.filename->word);
else if (temp->redirector.dest < 0)
/* This can happen when read_token_word encounters overflow, like in
exec 4294967297>x */
filename = _("file descriptor out of range");
#ifdef EBADF
/* This error can never involve NOCLOBBER */
else if (error != NOCLOBBER_REDIRECT && temp->redirector >= 0 && error == EBADF)
else if (error != NOCLOBBER_REDIRECT && temp->redirector.dest >= 0 && error == EBADF)
{
/* If we're dealing with two file descriptors, we have to guess about
which one is invalid; in the cases of r_{duplicating,move}_input and
@ -118,14 +123,27 @@ redirection_error (temp, error)
case r_move_output:
filename = allocname = itos (temp->redirectee.dest);
break;
case r_duplicating_input_word:
if (temp->redirector.dest == 0) /* Guess */
filename = temp->redirectee.filename->word; /* XXX */
else
filename = allocname = itos (temp->redirector.dest);
break;
case r_duplicating_output_word:
if (temp->redirector.dest == 1) /* Guess */
filename = temp->redirectee.filename->word; /* XXX */
else
filename = allocname = itos (temp->redirector.dest);
break;
default:
filename = allocname = itos (temp->redirector);
filename = allocname = itos (temp->redirector.dest);
break;
}
}
#endif
else if (expandable_redirection_filename (temp))
{
expandable_filename:
if (posixly_correct && interactive_shell == 0)
{
oflags = temp->redirectee.filename->flags;
@ -162,6 +180,10 @@ redirection_error (temp, error)
internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));
break;
case BADVAR_REDIRECT:
internal_error (_("%s: cannot assign fd to variable"), filename);
break;
default:
internal_error ("%s: %s", filename, strerror (error));
break;
@ -275,7 +297,9 @@ write_here_string (fd, redirectee)
char *herestr;
int herelen, n, e;
expanding_redir = 1;
herestr = expand_string_to_string (redirectee->word, 0);
expanding_redir = 0;
herelen = STRLEN (herestr);
n = write (fd, herestr, herelen);
@ -327,7 +351,10 @@ write_here_document (fd, redirectee)
return 0;
}
expanding_redir = 1;
tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
expanding_redir = 0;
if (tlist)
{
/* Try using buffered I/O (stdio) and writing a word
@ -644,10 +671,11 @@ do_redirection_internal (redirect, flags)
char *redirectee_word;
enum r_instruction ri;
REDIRECT *new_redirect;
REDIRECTEE sd;
redirectee = redirect->redirectee.filename;
redir_fd = redirect->redirectee.dest;
redirector = redirect->redirector;
redirector = redirect->redirector.dest;
ri = redirect->instruction;
if (redirect->flags & RX_INTERNAL)
@ -655,8 +683,9 @@ do_redirection_internal (redirect, flags)
if (TRANSLATE_REDIRECT (ri))
{
/* We have [N]>&WORD[-] or [N]<&WORD[-]. Expand WORD, then translate
the redirection into a new one and continue. */
/* We have [N]>&WORD[-] or [N]<&WORD[-] (or {V}>&WORD[-] or {V}<&WORD-).
and WORD, then translate the redirection into a new one and
continue. */
redirectee_word = redirection_expand (redirectee);
/* XXX - what to do with [N]<&$w- where w is unset or null? ksh93
@ -665,11 +694,13 @@ do_redirection_internal (redirect, flags)
return (AMBIGUOUS_REDIRECT);
else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
{
sd = redirect->redirector;
rd.dest = 0;
new_redirect = make_redirection (redirector, r_close_this, rd);
new_redirect = make_redirection (sd, r_close_this, rd, 0);
}
else if (all_digits (redirectee_word))
{
sd = redirect->redirector;
if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
rd.dest = lfd;
else
@ -677,23 +708,24 @@ do_redirection_internal (redirect, flags)
switch (ri)
{
case r_duplicating_input_word:
new_redirect = make_redirection (redirector, r_duplicating_input, rd);
new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
break;
case r_duplicating_output_word:
new_redirect = make_redirection (redirector, r_duplicating_output, rd);
new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
break;
case r_move_input_word:
new_redirect = make_redirection (redirector, r_move_input, rd);
new_redirect = make_redirection (sd, r_move_input, rd, 0);
break;
case r_move_output_word:
new_redirect = make_redirection (redirector, r_move_output, rd);
new_redirect = make_redirection (sd, r_move_output, rd, 0);
break;
}
}
else if (ri == r_duplicating_output_word && redirector == 1)
else if (ri == r_duplicating_output_word && (redirect->rflags & REDIR_VARASSIGN) == 0 && redirector == 1)
{
sd = redirect->redirector;
rd.filename = make_bare_word (redirectee_word);
new_redirect = make_redirection (1, r_err_and_out, rd);
new_redirect = make_redirection (sd, r_err_and_out, rd, 0);
}
else
{
@ -725,7 +757,7 @@ do_redirection_internal (redirect, flags)
redirectee = new_redirect->redirectee.filename;
redir_fd = new_redirect->redirectee.dest;
redirector = new_redirect->redirector;
redirector = new_redirect->redirector.dest;
ri = new_redirect->instruction;
/* Overwrite the flags element of the old redirect with the new value. */
@ -774,6 +806,9 @@ do_redirection_internal (redirect, flags)
if (flags & RX_ACTIVE)
{
if (redirect->rflags & REDIR_VARASSIGN)
redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE); /* XXX try this for now */
if (flags & RX_UNDOABLE)
{
/* Only setup to undo it if the thing to undo is active. */
@ -801,7 +836,16 @@ do_redirection_internal (redirect, flags)
fpurge (stderr);
}
if ((fd != redirector) && (dup2 (fd, redirector) < 0))
if (redirect->rflags & REDIR_VARASSIGN)
{
if ((r = redir_varassign (redirect, redirector)) < 0)
{
close (redirector);
close (fd);
return (r); /* XXX */
}
}
else if ((fd != redirector) && (dup2 (fd, redirector) < 0))
return (errno);
#if defined (BUFFERED_INPUT)
@ -837,7 +881,7 @@ do_redirection_internal (redirect, flags)
}
/* If we are hacking both stdout and stderr, do the stderr
redirection here. */
redirection here. XXX - handle {var} here? */
if (ri == r_err_and_out || ri == r_append_err_and_out)
{
if (flags & RX_ACTIVE)
@ -865,6 +909,9 @@ do_redirection_internal (redirect, flags)
return (HEREDOC_REDIRECT);
}
if (redirect->rflags & REDIR_VARASSIGN)
redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE); /* XXX try this for now */
if (flags & RX_ACTIVE)
{
if (flags & RX_UNDOABLE)
@ -879,7 +926,16 @@ do_redirection_internal (redirect, flags)
#if defined (BUFFERED_INPUT)
check_bash_input (redirector);
#endif
if (fd != redirector && dup2 (fd, redirector) < 0)
if (redirect->rflags & REDIR_VARASSIGN)
{
if ((r = redir_varassign (redirect, redirector)) < 0)
{
close (redirector);
close (fd);
return (r); /* XXX */
}
}
else if (fd != redirector && dup2 (fd, redirector) < 0)
{
r = errno;
close (fd);
@ -907,6 +963,9 @@ do_redirection_internal (redirect, flags)
case r_duplicating_output:
case r_move_input:
case r_move_output:
if ((flags & RX_ACTIVE) && (redirect->rflags & REDIR_VARASSIGN))
redirector = fcntl (redir_fd, F_DUPFD, SHELL_FD_BASE); /* XXX try this for now */
if ((flags & RX_ACTIVE) && (redir_fd != redirector))
{
if (flags & RX_UNDOABLE)
@ -920,8 +979,16 @@ do_redirection_internal (redirect, flags)
#if defined (BUFFERED_INPUT)
check_bash_input (redirector);
#endif
if (redirect->rflags & REDIR_VARASSIGN)
{
if ((r = redir_varassign (redirect, redirector)) < 0)
{
close (redirector);
return (r); /* XXX */
}
}
/* This is correct. 2>&1 means dup2 (1, 2); */
if (dup2 (redir_fd, redirector) < 0)
else if (dup2 (redir_fd, redirector) < 0)
return (errno);
#if defined (BUFFERED_INPUT)
@ -959,6 +1026,8 @@ do_redirection_internal (redirect, flags)
/* dup-and-close redirection */
if (ri == r_move_input || ri == r_move_output)
{
xtrace_fdchk (redir_fd);
close (redir_fd);
#if defined (COPROCESS_SUPPORT)
coproc_fdchk (redir_fd); /* XXX - loses coproc fds */
@ -970,12 +1039,20 @@ do_redirection_internal (redirect, flags)
case r_close_this:
if (flags & RX_ACTIVE)
{
if (redirect->rflags & REDIR_VARASSIGN)
{
redirector = redir_varvalue (redirect);
if (redirector < 0)
return AMBIGUOUS_REDIRECT;
}
if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
add_undo_redirect (redirector, ri, -1);
#if defined (COPROCESS_SUPPORT)
coproc_fdchk (redirector);
#endif
xtrace_fdchk (redirector);
#if defined (BUFFERED_INPUT)
check_bash_input (redirector);
@ -1013,6 +1090,7 @@ add_undo_redirect (fd, ri, fdbase)
{
int new_fd, clexec_flag;
REDIRECT *new_redirect, *closer, *dummy_redirect;
REDIRECTEE sd;
new_fd = fcntl (fd, F_DUPFD, (fdbase < SHELL_FD_BASE) ? SHELL_FD_BASE : fdbase+1);
if (new_fd < 0)
@ -1026,16 +1104,18 @@ add_undo_redirect (fd, ri, fdbase)
clexec_flag = fcntl (fd, F_GETFD, 0);
sd.dest = new_fd;
rd.dest = 0;
closer = make_redirection (new_fd, r_close_this, rd);
closer = make_redirection (sd, r_close_this, rd, 0);
closer->flags |= RX_INTERNAL;
dummy_redirect = copy_redirects (closer);
sd.dest = fd;
rd.dest = new_fd;
if (fd == 0)
new_redirect = make_redirection (fd, r_duplicating_input, rd);
new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
else
new_redirect = make_redirection (fd, r_duplicating_output, rd);
new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
new_redirect->flags |= RX_INTERNAL;
if (clexec_flag == 0 && fd >= 3 && new_fd >= SHELL_FD_BASE)
new_redirect->flags |= RX_SAVCLEXEC;
@ -1058,8 +1138,9 @@ add_undo_redirect (fd, ri, fdbase)
to save others. */
if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)
{
sd.dest = fd;
rd.dest = new_fd;
new_redirect = make_redirection (fd, r_duplicating_output, rd);
new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
new_redirect->flags |= RX_INTERNAL;
add_exec_redirect (new_redirect);
@ -1088,9 +1169,11 @@ add_undo_close_redirect (fd)
int fd;
{
REDIRECT *closer;
REDIRECTEE sd;
sd.dest = fd;
rd.dest = 0;
closer = make_redirection (fd, r_close_this, rd);
closer = make_redirection (sd, r_close_this, rd, 0);
closer->flags |= RX_INTERNAL;
closer->next = redirection_undo_list;
redirection_undo_list = closer;
@ -1146,6 +1229,49 @@ stdin_redirects (redirs)
int n;
for (n = 0, rp = redirs; rp; rp = rp->next)
n += stdin_redirection (rp->instruction, rp->redirector);
if ((rp->rflags & REDIR_VARASSIGN) == 0)
n += stdin_redirection (rp->instruction, rp->redirector.dest);
return n;
}
/* These don't yet handle array references */
static int
redir_varassign (redir, fd)
REDIRECT *redir;
int fd;
{
WORD_DESC *w;
SHELL_VAR *v;
w = redir->redirector.filename;
v = bind_var_to_int (w->word, fd);
if (v == 0 || readonly_p (v) || noassign_p (v))
return BADVAR_REDIRECT;
return 0;
}
static int
redir_varvalue (redir)
REDIRECT *redir;
{
SHELL_VAR *v;
char *val;
intmax_t vmax;
int i;
/* XXX - handle set -u here? */
v = find_variable (redir->redirector.filename->word);
if (v == 0 || invisible_p (v))
return -1;
val = get_variable_value (v);
if (val == 0 || *val == 0)
return -1;
if (legal_number (val, &vmax) < 0)
return -1;
i = vmax; /* integer truncation */
return i;
}