Bash-4.1 distribution source
This commit is contained in:
parent
89a92869e5
commit
0001803f0b
252 changed files with 51563 additions and 37176 deletions
174
redir.c
174
redir.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue