mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-01 01:20:00 +02:00
commit bash-20090910 snapshot
This commit is contained in:
@@ -8767,3 +8767,37 @@ variables.c
|
||||
bashline.c
|
||||
- fix to bash_execute_unix_command to avoid possible null pointer
|
||||
dereference if READLINE_LINE or READLINE_POINT is not bound
|
||||
|
||||
9/11
|
||||
----
|
||||
[Prayers for the victimes of 9/11/2001]
|
||||
|
||||
command.h
|
||||
- add `rflags' member to struct redirect to hold private flags and
|
||||
state information
|
||||
- change redirector to a REDIRECTEE instead of int to prepare for
|
||||
possible future changes
|
||||
|
||||
{copy_cmd,dispose_cmd,make_cmd,print_cmd,redir}.c
|
||||
- changes resulting from type change of `redirector' member of struct
|
||||
redirect: change x->redirector to x->redirector.dest and add code
|
||||
where appropriate to deal with x->redirector.filename
|
||||
|
||||
make_cmd.h
|
||||
- change extern declaration for make_redirection
|
||||
|
||||
make_cmd.c
|
||||
- first argument of make_redirection is now a `REDIRECTEE' to prepare
|
||||
for possible future changes. First arg is now assigned directly to
|
||||
redirector member instead of assigning int to redirector.dest
|
||||
|
||||
{make_cmd,redir}.c,parse.y
|
||||
- changes resulting from type change of first argument to
|
||||
make_redirection from int to REDIRECTEE. In general, changes are
|
||||
using REDIRECTEE sd and assigning old argument to sd.dest, then
|
||||
passing sd to make_redirection
|
||||
|
||||
make_cmd.[ch],parse.y
|
||||
- add fourth argument to make_redirection: flags. Sets initial value
|
||||
of `rflags' member of struct redirect
|
||||
- changed all callers of make_redirection to add fourth argument of 0
|
||||
|
||||
@@ -8763,3 +8763,36 @@ builtins/mapfile.def
|
||||
variables.c
|
||||
- fix to valid_exportstr to avoid possible null pointer dereferences
|
||||
pointed out by clang/scan-build
|
||||
|
||||
bashline.c
|
||||
- fix to bash_execute_unix_command to avoid possible null pointer
|
||||
dereference if READLINE_LINE or READLINE_POINT is not bound
|
||||
|
||||
9/11
|
||||
----
|
||||
[Prayers for the victimes of 9/11/2001]
|
||||
|
||||
command.h
|
||||
- add `rflags' member to struct redirect to hold private flags and
|
||||
state information
|
||||
- change redirector to a REDIRECTEE instead of int to prepare for
|
||||
possible future changes
|
||||
|
||||
{copy_cmd,dispose_cmd,make_cmd,print_cmd,redir}.c
|
||||
- changes resulting from type change of `redirector' member of struct
|
||||
redirect: change x->redirector to x->redirector.dest and add code
|
||||
where appropriate to deal with x->redirector.filename
|
||||
|
||||
make_cmd.h
|
||||
- change extern declaration for make_redirection
|
||||
|
||||
make_cmd.c
|
||||
- first argument of make_redirection is now a `REDIRECTEE' to prepare
|
||||
for possible future changes. First arg is now assigned directly to
|
||||
redirector member instead of assigning int to redirector.dest
|
||||
|
||||
{make_cmd,redir}.c,parse.y
|
||||
- changes resulting from type change of first argument to
|
||||
make_redirection from int to REDIRECTEE. In general, changes are
|
||||
using REDIRECTEE sd and assigning old argument to sd.dest, then
|
||||
passing sd to make_redirection
|
||||
|
||||
@@ -35,11 +35,15 @@ enum r_instruction {
|
||||
r_append_err_and_out
|
||||
};
|
||||
|
||||
/* Redirection flags; values for rflags */
|
||||
#define REDIR_VARASSIGN 0x01
|
||||
|
||||
/* Redirection errors. */
|
||||
#define AMBIGUOUS_REDIRECT -1
|
||||
#define NOCLOBBER_REDIRECT -2
|
||||
#define RESTRICTED_REDIRECT -3 /* can only happen in restricted shells. */
|
||||
#define HEREDOC_REDIRECT -4 /* here-doc temp file can't be created */
|
||||
#define BADVAR_REDIRECT -5 /* something wrong with {varname}redir */
|
||||
|
||||
#define CLOBBERING_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_err_and_out)
|
||||
@@ -135,7 +139,8 @@ typedef union {
|
||||
(or translator in redir.c) encountered an out-of-range file descriptor. */
|
||||
typedef struct redirect {
|
||||
struct redirect *next; /* Next element, or NULL. */
|
||||
int redirector; /* Descriptor to be redirected. */
|
||||
REDIRECTEE redirector; /* Descriptor or varname to be redirected. */
|
||||
int rflags; /* Private flags for this redirection */
|
||||
int flags; /* Flag value for `open'. */
|
||||
enum r_instruction instruction; /* What to do with the information. */
|
||||
REDIRECTEE redirectee; /* File descriptor or filename */
|
||||
|
||||
+384
@@ -0,0 +1,384 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (_COMMAND_H_)
|
||||
#define _COMMAND_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/* Instructions describing what kind of thing to do for a redirection. */
|
||||
enum r_instruction {
|
||||
r_output_direction, r_input_direction, r_inputa_direction,
|
||||
r_appending_to, r_reading_until, r_reading_string,
|
||||
r_duplicating_input, r_duplicating_output, r_deblank_reading_until,
|
||||
r_close_this, r_err_and_out, r_input_output, r_output_force,
|
||||
r_duplicating_input_word, r_duplicating_output_word,
|
||||
r_move_input, r_move_output, r_move_input_word, r_move_output_word,
|
||||
r_append_err_and_out
|
||||
};
|
||||
|
||||
/* Redirection flags; values for rflags */
|
||||
#define REDIR_VARASSIGN 0x01
|
||||
|
||||
/* Redirection errors. */
|
||||
#define AMBIGUOUS_REDIRECT -1
|
||||
#define NOCLOBBER_REDIRECT -2
|
||||
#define RESTRICTED_REDIRECT -3 /* can only happen in restricted shells. */
|
||||
#define HEREDOC_REDIRECT -4 /* here-doc temp file can't be created */
|
||||
#define BADVAR_REDIRECT -5 /* something wrong with {varname}redir
|
||||
|
||||
#define CLOBBERING_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_err_and_out)
|
||||
|
||||
#define OUTPUT_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_input_output || ri == r_err_and_out || ri == r_append_err_and_out)
|
||||
|
||||
#define INPUT_REDIRECT(ri) \
|
||||
(ri == r_input_direction || ri == r_inputa_direction || ri == r_input_output)
|
||||
|
||||
#define WRITE_REDIRECT(ri) \
|
||||
(ri == r_output_direction || \
|
||||
ri == r_input_output || \
|
||||
ri == r_err_and_out || \
|
||||
ri == r_appending_to || \
|
||||
ri == r_append_err_and_out || \
|
||||
ri == r_output_force)
|
||||
|
||||
/* redirection needs translation */
|
||||
#define TRANSLATE_REDIRECT(ri) \
|
||||
(ri == r_duplicating_input_word || ri == r_duplicating_output_word || \
|
||||
ri == r_move_input_word || ri == r_move_output_word)
|
||||
|
||||
/* Command Types: */
|
||||
enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
cm_connection, cm_function_def, cm_until, cm_group,
|
||||
cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc };
|
||||
|
||||
/* Possible values for the `flags' field of a WORD_DESC. */
|
||||
#define W_HASDOLLAR 0x000001 /* Dollar sign present. */
|
||||
#define W_QUOTED 0x000002 /* Some form of quote character is present. */
|
||||
#define W_ASSIGNMENT 0x000004 /* This word is a variable assignment. */
|
||||
#define W_GLOBEXP 0x000008 /* This word is the result of a glob expansion. */
|
||||
#define W_NOSPLIT 0x000010 /* Do not perform word splitting on this word. */
|
||||
#define W_NOGLOB 0x000020 /* Do not perform globbing on this word. */
|
||||
#define W_NOSPLIT2 0x000040 /* Don't split word except for $@ expansion. */
|
||||
#define W_TILDEEXP 0x000080 /* Tilde expand this assignment word */
|
||||
#define W_DOLLARAT 0x000100 /* $@ and its special handling */
|
||||
#define W_DOLLARSTAR 0x000200 /* $* and its special handling */
|
||||
#define W_NOCOMSUB 0x000400 /* Don't perform command substitution on this word */
|
||||
#define W_ASSIGNRHS 0x000800 /* Word is rhs of an assignment statement */
|
||||
#define W_NOTILDE 0x001000 /* Don't perform tilde expansion on this word */
|
||||
#define W_ITILDE 0x002000 /* Internal flag for word expansion */
|
||||
#define W_NOEXPAND 0x004000 /* Don't expand at all -- do quote removal */
|
||||
#define W_COMPASSIGN 0x008000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x010000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x020000 /* word is assignment argument to command */
|
||||
#define W_HASQUOTEDNULL 0x040000 /* word contains a quoted null character */
|
||||
#define W_DQUOTE 0x080000 /* word should be treated as if double-quoted */
|
||||
#define W_NOPROCSUB 0x100000 /* don't perform process substitution */
|
||||
#define W_HASCTLESC 0x200000 /* word contains literal CTLESC characters */
|
||||
#define W_ASSIGNASSOC 0x400000 /* word looks like associative array assignment */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
#define SUBSHELL_PAREN 0x02 /* subshell caused by ( ... ) */
|
||||
#define SUBSHELL_COMSUB 0x04 /* subshell caused by `command` or $(command) */
|
||||
#define SUBSHELL_FORK 0x08 /* subshell caused by executing a disk command */
|
||||
#define SUBSHELL_PIPE 0x10 /* subshell from a pipeline element */
|
||||
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
|
||||
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
|
||||
|
||||
/* A structure which represents a word. */
|
||||
typedef struct word_desc {
|
||||
char *word; /* Zero terminated string. */
|
||||
int flags; /* Flags associated with this word. */
|
||||
} WORD_DESC;
|
||||
|
||||
/* A linked list of words. */
|
||||
typedef struct word_list {
|
||||
struct word_list *next;
|
||||
WORD_DESC *word;
|
||||
} WORD_LIST;
|
||||
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Shell Command Structs */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* What a redirection descriptor looks like. If the redirection instruction
|
||||
is ri_duplicating_input or ri_duplicating_output, use DEST, otherwise
|
||||
use the file in FILENAME. Out-of-range descriptors are identified by a
|
||||
negative DEST. */
|
||||
|
||||
typedef union {
|
||||
int dest; /* Place to redirect REDIRECTOR to, or ... */
|
||||
WORD_DESC *filename; /* filename to redirect to. */
|
||||
} REDIRECTEE;
|
||||
|
||||
/* Structure describing a redirection. If REDIRECTOR is negative, the parser
|
||||
(or translator in redir.c) encountered an out-of-range file descriptor. */
|
||||
typedef struct redirect {
|
||||
struct redirect *next; /* Next element, or NULL. */
|
||||
REDIRECTEE redirector; /* Descriptor or varname to be redirected. */
|
||||
int rflags; /* Private flags for this redirection */
|
||||
int flags; /* Flag value for `open'. */
|
||||
enum r_instruction instruction; /* What to do with the information. */
|
||||
REDIRECTEE redirectee; /* File descriptor or filename */
|
||||
char *here_doc_eof; /* The word that appeared in <<foo. */
|
||||
} REDIRECT;
|
||||
|
||||
/* An element used in parsing. A single word or a single redirection.
|
||||
This is an ephemeral construct. */
|
||||
typedef struct element {
|
||||
WORD_DESC *word;
|
||||
REDIRECT *redirect;
|
||||
} ELEMENT;
|
||||
|
||||
/* Possible values for command->flags. */
|
||||
#define CMD_WANT_SUBSHELL 0x01 /* User wants a subshell: ( command ) */
|
||||
#define CMD_FORCE_SUBSHELL 0x02 /* Shell needs to force a subshell. */
|
||||
#define CMD_INVERT_RETURN 0x04 /* Invert the exit value. */
|
||||
#define CMD_IGNORE_RETURN 0x08 /* Ignore the exit value. For set -e. */
|
||||
#define CMD_NO_FUNCTIONS 0x10 /* Ignore functions during command lookup. */
|
||||
#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
|
||||
#define CMD_NO_FORK 0x40 /* Don't fork; just call execve */
|
||||
#define CMD_TIME_PIPELINE 0x80 /* Time a pipeline */
|
||||
#define CMD_TIME_POSIX 0x100 /* time -p; use POSIX.2 time output spec. */
|
||||
#define CMD_AMPERSAND 0x200 /* command & */
|
||||
#define CMD_STDIN_REDIR 0x400 /* async command needs implicit </dev/null */
|
||||
#define CMD_COMMAND_BUILTIN 0x0800 /* command executed by `command' builtin */
|
||||
#define CMD_COPROC_SUBSHELL 0x1000
|
||||
|
||||
/* What a command looks like. */
|
||||
typedef struct command {
|
||||
enum command_type type; /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
|
||||
int flags; /* Flags controlling execution environment. */
|
||||
int line; /* line number the command starts on */
|
||||
REDIRECT *redirects; /* Special redirects for FOR CASE, etc. */
|
||||
union {
|
||||
struct for_com *For;
|
||||
struct case_com *Case;
|
||||
struct while_com *While;
|
||||
struct if_com *If;
|
||||
struct connection *Connection;
|
||||
struct simple_com *Simple;
|
||||
struct function_def *Function_def;
|
||||
struct group_com *Group;
|
||||
#if defined (SELECT_COMMAND)
|
||||
struct select_com *Select;
|
||||
#endif
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
struct arith_com *Arith;
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
struct cond_com *Cond;
|
||||
#endif
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
struct arith_for_com *ArithFor;
|
||||
#endif
|
||||
struct subshell_com *Subshell;
|
||||
struct coproc_com *Coproc;
|
||||
} value;
|
||||
} COMMAND;
|
||||
|
||||
/* Structure used to represent the CONNECTION type. */
|
||||
typedef struct connection {
|
||||
int ignore; /* Unused; simplifies make_command (). */
|
||||
COMMAND *first; /* Pointer to the first command. */
|
||||
COMMAND *second; /* Pointer to the second command. */
|
||||
int connector; /* What separates this command from others. */
|
||||
} CONNECTION;
|
||||
|
||||
/* Structures used to represent the CASE command. */
|
||||
|
||||
/* Values for FLAGS word in a PATTERN_LIST */
|
||||
#define CASEPAT_FALLTHROUGH 0x01
|
||||
#define CASEPAT_TESTNEXT 0x02
|
||||
|
||||
/* Pattern/action structure for CASE_COM. */
|
||||
typedef struct pattern_list {
|
||||
struct pattern_list *next; /* Clause to try in case this one failed. */
|
||||
WORD_LIST *patterns; /* Linked list of patterns to test. */
|
||||
COMMAND *action; /* Thing to execute if a pattern matches. */
|
||||
int flags;
|
||||
} PATTERN_LIST;
|
||||
|
||||
/* The CASE command. */
|
||||
typedef struct case_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `case' keyword appears on */
|
||||
WORD_DESC *word; /* The thing to test. */
|
||||
PATTERN_LIST *clauses; /* The clauses to test against, or NULL. */
|
||||
} CASE_COM;
|
||||
|
||||
/* FOR command. */
|
||||
typedef struct for_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `for' keyword appears on */
|
||||
WORD_DESC *name; /* The variable name to get mapped over. */
|
||||
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
|
||||
COMMAND *action; /* The action to execute.
|
||||
During execution, NAME is bound to successive
|
||||
members of MAP_LIST. */
|
||||
} FOR_COM;
|
||||
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
typedef struct arith_for_com {
|
||||
int flags;
|
||||
int line; /* generally used for error messages */
|
||||
WORD_LIST *init;
|
||||
WORD_LIST *test;
|
||||
WORD_LIST *step;
|
||||
COMMAND *action;
|
||||
} ARITH_FOR_COM;
|
||||
#endif
|
||||
|
||||
#if defined (SELECT_COMMAND)
|
||||
/* KSH SELECT command. */
|
||||
typedef struct select_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `select' keyword appears on */
|
||||
WORD_DESC *name; /* The variable name to get mapped over. */
|
||||
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
|
||||
COMMAND *action; /* The action to execute.
|
||||
During execution, NAME is bound to the member of
|
||||
MAP_LIST chosen by the user. */
|
||||
} SELECT_COM;
|
||||
#endif /* SELECT_COMMAND */
|
||||
|
||||
/* IF command. */
|
||||
typedef struct if_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
COMMAND *test; /* Thing to test. */
|
||||
COMMAND *true_case; /* What to do if the test returned non-zero. */
|
||||
COMMAND *false_case; /* What to do if the test returned zero. */
|
||||
} IF_COM;
|
||||
|
||||
/* WHILE command. */
|
||||
typedef struct while_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
COMMAND *test; /* Thing to test. */
|
||||
COMMAND *action; /* Thing to do while test is non-zero. */
|
||||
} WHILE_COM;
|
||||
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
/* The arithmetic evaluation command, ((...)). Just a set of flags and
|
||||
a WORD_LIST, of which the first element is the only one used, for the
|
||||
time being. */
|
||||
typedef struct arith_com {
|
||||
int flags;
|
||||
int line;
|
||||
WORD_LIST *exp;
|
||||
} ARITH_COM;
|
||||
#endif /* DPAREN_ARITHMETIC */
|
||||
|
||||
/* The conditional command, [[...]]. This is a binary tree -- we slippped
|
||||
a recursive-descent parser into the YACC grammar to parse it. */
|
||||
#define COND_AND 1
|
||||
#define COND_OR 2
|
||||
#define COND_UNARY 3
|
||||
#define COND_BINARY 4
|
||||
#define COND_TERM 5
|
||||
#define COND_EXPR 6
|
||||
|
||||
typedef struct cond_com {
|
||||
int flags;
|
||||
int line;
|
||||
int type;
|
||||
WORD_DESC *op;
|
||||
struct cond_com *left, *right;
|
||||
} COND_COM;
|
||||
|
||||
/* The "simple" command. Just a collection of words and redirects. */
|
||||
typedef struct simple_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the command starts on */
|
||||
WORD_LIST *words; /* The program name, the arguments,
|
||||
variable assignments, etc. */
|
||||
REDIRECT *redirects; /* Redirections to perform. */
|
||||
} SIMPLE_COM;
|
||||
|
||||
/* The "function definition" command. */
|
||||
typedef struct function_def {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* Line number the function def starts on. */
|
||||
WORD_DESC *name; /* The name of the function. */
|
||||
COMMAND *command; /* The parsed execution tree. */
|
||||
char *source_file; /* file in which function was defined, if any */
|
||||
} FUNCTION_DEF;
|
||||
|
||||
/* A command that is `grouped' allows pipes and redirections to affect all
|
||||
commands in the group. */
|
||||
typedef struct group_com {
|
||||
int ignore; /* See description of CMD flags. */
|
||||
COMMAND *command;
|
||||
} GROUP_COM;
|
||||
|
||||
typedef struct subshell_com {
|
||||
int flags;
|
||||
COMMAND *command;
|
||||
} SUBSHELL_COM;
|
||||
|
||||
#define COPROC_RUNNING 0x01
|
||||
#define COPROC_DEAD 0x02
|
||||
|
||||
typedef struct coproc {
|
||||
char *c_name;
|
||||
pid_t c_pid;
|
||||
int c_rfd;
|
||||
int c_wfd;
|
||||
int c_rsave;
|
||||
int c_wsave;
|
||||
int c_flags;
|
||||
int c_status;
|
||||
} Coproc;
|
||||
|
||||
typedef struct coproc_com {
|
||||
int flags;
|
||||
char *name;
|
||||
COMMAND *command;
|
||||
} COPROC_COM;
|
||||
|
||||
extern COMMAND *global_command;
|
||||
extern Coproc sh_coproc;
|
||||
|
||||
/* Possible command errors */
|
||||
#define CMDERR_DEFAULT 0
|
||||
#define CMDERR_BADTYPE 1
|
||||
#define CMDERR_BADCONN 2
|
||||
#define CMDERR_BADJUMP 3
|
||||
|
||||
#define CMDERR_LAST 3
|
||||
|
||||
/* Forward declarations of functions declared in copy_cmd.c. */
|
||||
|
||||
extern FUNCTION_DEF *copy_function_def_contents __P((FUNCTION_DEF *, FUNCTION_DEF *));
|
||||
extern FUNCTION_DEF *copy_function_def __P((FUNCTION_DEF *));
|
||||
|
||||
extern WORD_DESC *copy_word __P((WORD_DESC *));
|
||||
extern WORD_LIST *copy_word_list __P((WORD_LIST *));
|
||||
extern REDIRECT *copy_redirect __P((REDIRECT *));
|
||||
extern REDIRECT *copy_redirects __P((REDIRECT *));
|
||||
extern COMMAND *copy_command __P((COMMAND *));
|
||||
|
||||
#endif /* _COMMAND_H_ */
|
||||
@@ -113,7 +113,15 @@ copy_redirect (redirect)
|
||||
REDIRECT *new_redirect;
|
||||
|
||||
new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT));
|
||||
#if 0
|
||||
FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT)));
|
||||
#else
|
||||
*new_redirect = *redirect; /* let the compiler do the fast structure copy */
|
||||
#endif
|
||||
|
||||
if (redirect->rflags & REDIR_VARASSIGN)
|
||||
new_redirect->redirector.filename = copy_word (redirect->redirector.filename);
|
||||
|
||||
switch (redirect->instruction)
|
||||
{
|
||||
case r_reading_until:
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
*** ../bash-20090903/redir.c 2009-08-17 17:46:34.000000000 -0400
|
||||
--- redir.c 2009-09-11 17:29:54.000000000 -0400
|
||||
***************
|
||||
*** 99,111 ****
|
||||
int oflags;
|
||||
|
||||
allocname = 0;
|
||||
! if (temp->redirector < 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)
|
||||
{
|
||||
/* 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
|
||||
--- 99,113 ----
|
||||
int oflags;
|
||||
|
||||
allocname = 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.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
|
||||
***************
|
||||
*** 119,125 ****
|
||||
filename = allocname = itos (temp->redirectee.dest);
|
||||
break;
|
||||
default:
|
||||
! filename = allocname = itos (temp->redirector);
|
||||
break;
|
||||
}
|
||||
}
|
||||
--- 121,127 ----
|
||||
filename = allocname = itos (temp->redirectee.dest);
|
||||
break;
|
||||
default:
|
||||
! filename = allocname = itos (temp->redirector.dest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
***************
|
||||
*** 162,167 ****
|
||||
--- 164,173 ----
|
||||
internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));
|
||||
break;
|
||||
|
||||
+ case BADVAR_REDIRECT:
|
||||
+ internal_error (_("cannot assign fd to variable %s"), filename);
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
internal_error ("%s: %s", filename, strerror (error));
|
||||
break;
|
||||
***************
|
||||
*** 649,658 ****
|
||||
char *redirectee_word;
|
||||
enum r_instruction ri;
|
||||
REDIRECT *new_redirect;
|
||||
|
||||
redirectee = redirect->redirectee.filename;
|
||||
redir_fd = redirect->redirectee.dest;
|
||||
! redirector = redirect->redirector;
|
||||
ri = redirect->instruction;
|
||||
|
||||
if (redirect->flags & RX_INTERNAL)
|
||||
--- 655,665 ----
|
||||
char *redirectee_word;
|
||||
enum r_instruction ri;
|
||||
REDIRECT *new_redirect;
|
||||
+ REDIRECTEE sd;
|
||||
|
||||
redirectee = redirect->redirectee.filename;
|
||||
redir_fd = redirect->redirectee.dest;
|
||||
! redirector = redirect->redirector.dest;
|
||||
ri = redirect->instruction;
|
||||
|
||||
if (redirect->flags & RX_INTERNAL)
|
||||
***************
|
||||
*** 670,680 ****
|
||||
return (AMBIGUOUS_REDIRECT);
|
||||
else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
|
||||
{
|
||||
rd.dest = 0;
|
||||
! new_redirect = make_redirection (redirector, r_close_this, rd);
|
||||
}
|
||||
else if (all_digits (redirectee_word))
|
||||
{
|
||||
if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
|
||||
rd.dest = lfd;
|
||||
else
|
||||
--- 677,689 ----
|
||||
return (AMBIGUOUS_REDIRECT);
|
||||
else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
|
||||
{
|
||||
+ sd.dest = redirector;
|
||||
rd.dest = 0;
|
||||
! new_redirect = make_redirection (sd, r_close_this, rd, 0);
|
||||
}
|
||||
else if (all_digits (redirectee_word))
|
||||
{
|
||||
+ sd.dest = redirector;
|
||||
if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
|
||||
rd.dest = lfd;
|
||||
else
|
||||
***************
|
||||
*** 682,704 ****
|
||||
switch (ri)
|
||||
{
|
||||
case r_duplicating_input_word:
|
||||
! new_redirect = make_redirection (redirector, r_duplicating_input, rd);
|
||||
break;
|
||||
case r_duplicating_output_word:
|
||||
! new_redirect = make_redirection (redirector, r_duplicating_output, rd);
|
||||
break;
|
||||
case r_move_input_word:
|
||||
! new_redirect = make_redirection (redirector, r_move_input, rd);
|
||||
break;
|
||||
case r_move_output_word:
|
||||
! new_redirect = make_redirection (redirector, r_move_output, rd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ri == r_duplicating_output_word && redirector == 1)
|
||||
{
|
||||
rd.filename = make_bare_word (redirectee_word);
|
||||
! new_redirect = make_redirection (1, r_err_and_out, rd);
|
||||
}
|
||||
else
|
||||
{
|
||||
--- 691,714 ----
|
||||
switch (ri)
|
||||
{
|
||||
case r_duplicating_input_word:
|
||||
! new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
|
||||
break;
|
||||
case r_duplicating_output_word:
|
||||
! new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
|
||||
break;
|
||||
case r_move_input_word:
|
||||
! new_redirect = make_redirection (sd, r_move_input, rd, 0);
|
||||
break;
|
||||
case r_move_output_word:
|
||||
! new_redirect = make_redirection (sd, r_move_output, rd, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ri == r_duplicating_output_word && redirector == 1)
|
||||
{
|
||||
+ sd.dest = 1;
|
||||
rd.filename = make_bare_word (redirectee_word);
|
||||
! new_redirect = make_redirection (sd, r_err_and_out, rd, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
***************
|
||||
*** 730,736 ****
|
||||
redirectee = new_redirect->redirectee.filename;
|
||||
|
||||
redir_fd = new_redirect->redirectee.dest;
|
||||
! redirector = new_redirect->redirector;
|
||||
ri = new_redirect->instruction;
|
||||
|
||||
/* Overwrite the flags element of the old redirect with the new value. */
|
||||
--- 740,746 ----
|
||||
redirectee = new_redirect->redirectee.filename;
|
||||
|
||||
redir_fd = new_redirect->redirectee.dest;
|
||||
! redirector = new_redirect->redirector.dest;
|
||||
ri = new_redirect->instruction;
|
||||
|
||||
/* Overwrite the flags element of the old redirect with the new value. */
|
||||
***************
|
||||
*** 1021,1026 ****
|
||||
--- 1031,1037 ----
|
||||
{
|
||||
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)
|
||||
***************
|
||||
*** 1034,1049 ****
|
||||
|
||||
clexec_flag = fcntl (fd, F_GETFD, 0);
|
||||
|
||||
rd.dest = 0;
|
||||
! closer = make_redirection (new_fd, r_close_this, rd);
|
||||
closer->flags |= RX_INTERNAL;
|
||||
dummy_redirect = copy_redirects (closer);
|
||||
|
||||
rd.dest = new_fd;
|
||||
if (fd == 0)
|
||||
! new_redirect = make_redirection (fd, r_duplicating_input, rd);
|
||||
else
|
||||
! new_redirect = make_redirection (fd, r_duplicating_output, rd);
|
||||
new_redirect->flags |= RX_INTERNAL;
|
||||
if (clexec_flag == 0 && fd >= 3 && new_fd >= SHELL_FD_BASE)
|
||||
new_redirect->flags |= RX_SAVCLEXEC;
|
||||
--- 1045,1062 ----
|
||||
|
||||
clexec_flag = fcntl (fd, F_GETFD, 0);
|
||||
|
||||
+ sd.dest = new_fd;
|
||||
rd.dest = 0;
|
||||
! 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 (sd, r_duplicating_input, rd, 0);
|
||||
else
|
||||
! 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;
|
||||
***************
|
||||
*** 1066,1073 ****
|
||||
to save others. */
|
||||
if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)
|
||||
{
|
||||
rd.dest = new_fd;
|
||||
! new_redirect = make_redirection (fd, r_duplicating_output, rd);
|
||||
new_redirect->flags |= RX_INTERNAL;
|
||||
|
||||
add_exec_redirect (new_redirect);
|
||||
--- 1079,1087 ----
|
||||
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 (sd, r_duplicating_output, rd, 0);
|
||||
new_redirect->flags |= RX_INTERNAL;
|
||||
|
||||
add_exec_redirect (new_redirect);
|
||||
***************
|
||||
*** 1096,1104 ****
|
||||
int fd;
|
||||
{
|
||||
REDIRECT *closer;
|
||||
|
||||
rd.dest = 0;
|
||||
! closer = make_redirection (fd, r_close_this, rd);
|
||||
closer->flags |= RX_INTERNAL;
|
||||
closer->next = redirection_undo_list;
|
||||
redirection_undo_list = closer;
|
||||
--- 1110,1120 ----
|
||||
int fd;
|
||||
{
|
||||
REDIRECT *closer;
|
||||
+ REDIRECTEE sd;
|
||||
|
||||
+ sd.dest = fd;
|
||||
rd.dest = 0;
|
||||
! closer = make_redirection (sd, r_close_this, rd, 0);
|
||||
closer->flags |= RX_INTERNAL;
|
||||
closer->next = redirection_undo_list;
|
||||
redirection_undo_list = closer;
|
||||
***************
|
||||
*** 1154,1159 ****
|
||||
int n;
|
||||
|
||||
for (n = 0, rp = redirs; rp; rp = rp->next)
|
||||
! n += stdin_redirection (rp->instruction, rp->redirector);
|
||||
return n;
|
||||
}
|
||||
--- 1170,1175 ----
|
||||
int n;
|
||||
|
||||
for (n = 0, rp = redirs; rp; rp = rp->next)
|
||||
! n += stdin_redirection (rp->instruction, rp->redirector.dest);
|
||||
return n;
|
||||
}
|
||||
@@ -309,6 +309,10 @@ dispose_redirects (list)
|
||||
{
|
||||
t = list;
|
||||
list = list->next;
|
||||
|
||||
if (t->rflags & REDIR_VARASSIGN)
|
||||
dispose_word (t->redirector.filename);
|
||||
|
||||
switch (t->instruction)
|
||||
{
|
||||
case r_reading_until:
|
||||
|
||||
+4
-2
@@ -673,10 +673,11 @@ document_done:
|
||||
INSTRUCTION is the instruction type, SOURCE is a file descriptor,
|
||||
and DEST is a file descriptor or a WORD_DESC *. */
|
||||
REDIRECT *
|
||||
make_redirection (source, instruction, dest_and_filename)
|
||||
int source;
|
||||
make_redirection (source, instruction, dest_and_filename, flags)
|
||||
REDIRECTEE source;
|
||||
enum r_instruction instruction;
|
||||
REDIRECTEE dest_and_filename;
|
||||
int flags;
|
||||
{
|
||||
REDIRECT *temp;
|
||||
WORD_DESC *w;
|
||||
@@ -690,6 +691,7 @@ make_redirection (source, instruction, dest_and_filename)
|
||||
temp->redirectee = dest_and_filename;
|
||||
temp->instruction = instruction;
|
||||
temp->flags = 0;
|
||||
temp->rflags = flags;
|
||||
temp->next = (REDIRECT *)NULL;
|
||||
|
||||
switch (instruction)
|
||||
|
||||
+2
-3
@@ -526,7 +526,6 @@ make_simple_command (element, command)
|
||||
ELEMENT element;
|
||||
COMMAND *command;
|
||||
{
|
||||
itrace("make_simple_command");
|
||||
/* If we are starting from scratch, then make the initial command
|
||||
structure. Also note that we have to fill in all the slots, since
|
||||
malloc doesn't return zeroed space. */
|
||||
@@ -675,7 +674,7 @@ document_done:
|
||||
and DEST is a file descriptor or a WORD_DESC *. */
|
||||
REDIRECT *
|
||||
make_redirection (source, instruction, dest_and_filename)
|
||||
int source;
|
||||
REDIRECTEE source;
|
||||
enum r_instruction instruction;
|
||||
REDIRECTEE dest_and_filename;
|
||||
{
|
||||
@@ -690,7 +689,7 @@ make_redirection (source, instruction, dest_and_filename)
|
||||
temp->redirector = source;
|
||||
temp->redirectee = dest_and_filename;
|
||||
temp->instruction = instruction;
|
||||
temp->flags = 0;
|
||||
temp->flags = temp->rflags = 0;
|
||||
temp->next = (REDIRECT *)NULL;
|
||||
|
||||
switch (instruction)
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ extern COMMAND *make_until_command __P((COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_bare_simple_command __P((void));
|
||||
extern COMMAND *make_simple_command __P((ELEMENT, COMMAND *));
|
||||
extern void make_here_document __P((REDIRECT *, int));
|
||||
extern REDIRECT *make_redirection __P((int, enum r_instruction, REDIRECTEE));
|
||||
extern REDIRECT *make_redirection __P((REDIRECTEE, enum r_instruction, REDIRECTEE, int));
|
||||
extern COMMAND *make_function_def __P((WORD_DESC *, COMMAND *, int, int));
|
||||
extern COMMAND *clean_simple_command __P((COMMAND *));
|
||||
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/* make_cmd.h -- Declarations of functions found in make_cmd.c */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (_MAKE_CMD_H_)
|
||||
#define _MAKE_CMD_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
extern void cmd_init __P((void));
|
||||
|
||||
extern WORD_DESC *alloc_word_desc __P((void));
|
||||
extern WORD_DESC *make_bare_word __P((const char *));
|
||||
extern WORD_DESC *make_word_flags __P((WORD_DESC *, const char *));
|
||||
extern WORD_DESC *make_word __P((const char *));
|
||||
extern WORD_DESC *make_word_from_token __P((int));
|
||||
|
||||
extern WORD_LIST *make_word_list __P((WORD_DESC *, WORD_LIST *));
|
||||
|
||||
#define add_string_to_list(s, l) make_word_list (make_word(s), (l))
|
||||
|
||||
extern COMMAND *make_command __P((enum command_type, SIMPLE_COM *));
|
||||
extern COMMAND *command_connect __P((COMMAND *, COMMAND *, int));
|
||||
extern COMMAND *make_for_command __P((WORD_DESC *, WORD_LIST *, COMMAND *, int));
|
||||
extern COMMAND *make_group_command __P((COMMAND *));
|
||||
extern COMMAND *make_case_command __P((WORD_DESC *, PATTERN_LIST *, int));
|
||||
extern PATTERN_LIST *make_pattern_list __P((WORD_LIST *, COMMAND *));
|
||||
extern COMMAND *make_if_command __P((COMMAND *, COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_while_command __P((COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_until_command __P((COMMAND *, COMMAND *));
|
||||
extern COMMAND *make_bare_simple_command __P((void));
|
||||
extern COMMAND *make_simple_command __P((ELEMENT, COMMAND *));
|
||||
extern void make_here_document __P((REDIRECT *, int));
|
||||
extern REDIRECT *make_redirection __P((REDIRECTEE, enum r_instruction, REDIRECTEE));
|
||||
extern COMMAND *make_function_def __P((WORD_DESC *, COMMAND *, int, int));
|
||||
extern COMMAND *clean_simple_command __P((COMMAND *));
|
||||
|
||||
extern COMMAND *make_arith_command __P((WORD_LIST *));
|
||||
|
||||
extern COMMAND *make_select_command __P((WORD_DESC *, WORD_LIST *, COMMAND *, int));
|
||||
|
||||
#if defined (COND_COMMAND)
|
||||
extern COND_COM *make_cond_node __P((int, WORD_DESC *, COND_COM *, COND_COM *));
|
||||
extern COMMAND *make_cond_command __P((COND_COM *));
|
||||
#endif
|
||||
|
||||
extern COMMAND *make_arith_for_command __P((WORD_LIST *, COMMAND *, int));
|
||||
|
||||
extern COMMAND *make_subshell_command __P((COMMAND *));
|
||||
extern COMMAND *make_coproc_command __P((char *, COMMAND *));
|
||||
|
||||
extern COMMAND *connect_async_list __P((COMMAND *, COMMAND *, int));
|
||||
|
||||
#endif /* !_MAKE_CMD_H */
|
||||
@@ -310,6 +310,7 @@ static int word_top = -1;
|
||||
static int token_to_read;
|
||||
static WORD_DESC *word_desc_to_read;
|
||||
|
||||
static REDIRECTEE source;
|
||||
static REDIRECTEE redir;
|
||||
%}
|
||||
|
||||
@@ -332,7 +333,7 @@ static REDIRECTEE redir;
|
||||
%token IN BANG TIME TIMEOPT
|
||||
|
||||
/* More general tokens. yylex () knows how to make these. */
|
||||
%token <word> WORD ASSIGNMENT_WORD
|
||||
%token <word> WORD ASSIGNMENT_WORD REDIR_WORD
|
||||
%token <number> NUMBER
|
||||
%token <word_list> ARITH_CMD ARITH_FOR_EXPRS
|
||||
%token <command> COND_CMD
|
||||
@@ -419,159 +420,187 @@ word_list: WORD
|
||||
|
||||
redirection: '>' WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_output_direction, redir);
|
||||
$$ = make_redirection (source, r_output_direction, redir, 0);
|
||||
}
|
||||
| '<' WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_input_direction, redir);
|
||||
$$ = make_redirection (source, r_input_direction, redir, 0);
|
||||
}
|
||||
| NUMBER '>' WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_output_direction, redir);
|
||||
$$ = make_redirection (source, r_output_direction, redir, 0);
|
||||
}
|
||||
| NUMBER '<' WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_input_direction, redir);
|
||||
$$ = make_redirection (source, r_input_direction, redir, 0);
|
||||
}
|
||||
| GREATER_GREATER WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_appending_to, redir);
|
||||
$$ = make_redirection (source, r_appending_to, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_GREATER WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_appending_to, redir);
|
||||
$$ = make_redirection (source, r_appending_to, redir, 0);
|
||||
}
|
||||
| LESS_LESS WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_reading_until, redir);
|
||||
$$ = make_redirection (source, r_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| NUMBER LESS_LESS WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_reading_until, redir);
|
||||
$$ = make_redirection (source, r_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| LESS_LESS_LESS WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_reading_string, redir);
|
||||
$$ = make_redirection (source, r_reading_string, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_LESS_LESS WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_reading_string, redir);
|
||||
$$ = make_redirection (source, r_reading_string, redir, 0);
|
||||
}
|
||||
| LESS_AND NUMBER
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.dest = $2;
|
||||
$$ = make_redirection (0, r_duplicating_input, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_AND NUMBER
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_input, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input, redir, 0);
|
||||
}
|
||||
| GREATER_AND NUMBER
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.dest = $2;
|
||||
$$ = make_redirection (1, r_duplicating_output, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_AND NUMBER
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_output, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output, redir, 0);
|
||||
}
|
||||
| LESS_AND WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_duplicating_input_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input_word, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_AND WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_input_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input_word, redir, 0);
|
||||
}
|
||||
| GREATER_AND WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_duplicating_output_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output_word, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_AND WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_output_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output_word, redir, 0);
|
||||
}
|
||||
| LESS_LESS_MINUS WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection
|
||||
(0, r_deblank_reading_until, redir);
|
||||
$$ = make_redirection (source, r_deblank_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| NUMBER LESS_LESS_MINUS WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection
|
||||
($1, r_deblank_reading_until, redir);
|
||||
$$ = make_redirection (source, r_deblank_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| GREATER_AND '-'
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection (1, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_AND '-'
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection ($1, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| LESS_AND '-'
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection (0, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_AND '-'
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection ($1, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| AND_GREATER WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_err_and_out, redir);
|
||||
$$ = make_redirection (source, r_err_and_out, redir, 0);
|
||||
}
|
||||
| AND_GREATER_GREATER WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_append_err_and_out, redir);
|
||||
$$ = make_redirection (source, r_append_err_and_out, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_GREATER WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_input_output, redir);
|
||||
$$ = make_redirection (source, r_input_output, redir, 0);
|
||||
}
|
||||
| LESS_GREATER WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_input_output, redir);
|
||||
$$ = make_redirection (source, r_input_output, redir, 0);
|
||||
}
|
||||
| GREATER_BAR WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_output_force, redir);
|
||||
$$ = make_redirection (source, r_output_force, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_BAR WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_output_force, redir);
|
||||
$$ = make_redirection (source, r_output_force, redir, 0);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1119,12 +1148,13 @@ pipeline: pipeline '|' newline_list pipeline
|
||||
{
|
||||
/* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */
|
||||
COMMAND *tc;
|
||||
REDIRECTEE rd;
|
||||
REDIRECTEE rd, sd;
|
||||
REDIRECT *r;
|
||||
|
||||
tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
|
||||
sd.dest = 2;
|
||||
rd.dest = 1;
|
||||
r = make_redirection (2, r_duplicating_output, rd);
|
||||
r = make_redirection (sd, r_duplicating_output, rd, 0);
|
||||
if (tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
|
||||
@@ -310,6 +310,7 @@ static int word_top = -1;
|
||||
static int token_to_read;
|
||||
static WORD_DESC *word_desc_to_read;
|
||||
|
||||
static REDIRECTEE source;
|
||||
static REDIRECTEE redir;
|
||||
%}
|
||||
|
||||
@@ -419,159 +420,187 @@ word_list: WORD
|
||||
|
||||
redirection: '>' WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_output_direction, redir);
|
||||
$$ = make_redirection (source, r_output_direction, redir, 0);
|
||||
}
|
||||
| '<' WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_input_direction, redir);
|
||||
$$ = make_redirection (source, r_input_direction, redir, 0);
|
||||
}
|
||||
| NUMBER '>' WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_output_direction, redir);
|
||||
$$ = make_redirection (source, r_output_direction, redir, 0);
|
||||
}
|
||||
| NUMBER '<' WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_input_direction, redir);
|
||||
$$ = make_redirection (source, r_input_direction, redir, 0);
|
||||
}
|
||||
| GREATER_GREATER WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_appending_to, redir);
|
||||
$$ = make_redirection (source, r_appending_to, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_GREATER WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_appending_to, redir);
|
||||
$$ = make_redirection (source, r_appending_to, redir, 0);
|
||||
}
|
||||
| LESS_LESS WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_reading_until, redir);
|
||||
$$ = make_redirection (source, r_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| NUMBER LESS_LESS WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_reading_until, redir);
|
||||
$$ = make_redirection (source, r_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| LESS_LESS_LESS WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_reading_string, redir);
|
||||
$$ = make_redirection (source, r_reading_string, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_LESS_LESS WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_reading_string, redir);
|
||||
$$ = make_redirection (source, r_reading_string, redir, 0);
|
||||
}
|
||||
| LESS_AND NUMBER
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.dest = $2;
|
||||
$$ = make_redirection (0, r_duplicating_input, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_AND NUMBER
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_input, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input, redir, 0);
|
||||
}
|
||||
| GREATER_AND NUMBER
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.dest = $2;
|
||||
$$ = make_redirection (1, r_duplicating_output, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_AND NUMBER
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_output, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output, redir, 0);
|
||||
}
|
||||
| LESS_AND WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_duplicating_input_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input_word, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_AND WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_input_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_input_word, redir, 0);
|
||||
}
|
||||
| GREATER_AND WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_duplicating_output_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output_word, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_AND WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_duplicating_output_word, redir);
|
||||
$$ = make_redirection (source, r_duplicating_output_word, redir, 0);
|
||||
}
|
||||
| LESS_LESS_MINUS WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection
|
||||
(0, r_deblank_reading_until, redir);
|
||||
$$ = make_redirection (source, r_deblank_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| NUMBER LESS_LESS_MINUS WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection
|
||||
($1, r_deblank_reading_until, redir);
|
||||
$$ = make_redirection (source, r_deblank_reading_until, redir, 0);
|
||||
redir_stack[need_here_doc++] = $$;
|
||||
}
|
||||
| GREATER_AND '-'
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection (1, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_AND '-'
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection ($1, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| LESS_AND '-'
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection (0, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_AND '-'
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.dest = 0;
|
||||
$$ = make_redirection ($1, r_close_this, redir);
|
||||
$$ = make_redirection (source, r_close_this, redir, 0);
|
||||
}
|
||||
| AND_GREATER WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_err_and_out, redir);
|
||||
$$ = make_redirection (source, r_err_and_out, redir, 0);
|
||||
}
|
||||
| AND_GREATER_GREATER WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_append_err_and_out, redir);
|
||||
$$ = make_redirection (source, r_append_err_and_out, redir, 0);
|
||||
}
|
||||
| NUMBER LESS_GREATER WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_input_output, redir);
|
||||
$$ = make_redirection (source, r_input_output, redir, 0);
|
||||
}
|
||||
| LESS_GREATER WORD
|
||||
{
|
||||
source.dest = 0;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (0, r_input_output, redir);
|
||||
$$ = make_redirection (source, r_input_output, redir, 0);
|
||||
}
|
||||
| GREATER_BAR WORD
|
||||
{
|
||||
source.dest = 1;
|
||||
redir.filename = $2;
|
||||
$$ = make_redirection (1, r_output_force, redir);
|
||||
$$ = make_redirection (source, r_output_force, redir, 0);
|
||||
}
|
||||
| NUMBER GREATER_BAR WORD
|
||||
{
|
||||
source.dest = $1;
|
||||
redir.filename = $3;
|
||||
$$ = make_redirection ($1, r_output_force, redir);
|
||||
$$ = make_redirection (source, r_output_force, redir, 0);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1119,12 +1148,13 @@ pipeline: pipeline '|' newline_list pipeline
|
||||
{
|
||||
/* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */
|
||||
COMMAND *tc;
|
||||
REDIRECTEE rd;
|
||||
REDIRECTEE rd, sd;
|
||||
REDIRECT *r;
|
||||
|
||||
tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
|
||||
sd.dest = 2;
|
||||
rd.dest = 1;
|
||||
r = make_redirection (2, r_duplicating_output, rd);
|
||||
r = make_redirection (sd, r_duplicating_output, rd, 0);
|
||||
if (tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
@@ -3505,12 +3535,12 @@ eof_error:
|
||||
else if MBTEST(ch == close && (tflags & LEX_INCASE) == 0) /* ending delimiter */
|
||||
{
|
||||
count--;
|
||||
itrace("parse_comsub:%d: found close: count = %d", line_number, count);
|
||||
/*itrace("parse_comsub:%d: found close: count = %d", line_number, count);*/
|
||||
}
|
||||
else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && (tflags & LEX_INCASE) == 0 && ch == open) /* nested begin */
|
||||
{
|
||||
count++;
|
||||
itrace("parse_comsub:%d: found open: count = %d", line_number, count);
|
||||
/*itrace("parse_comsub:%d: found open: count = %d", line_number, count);*/
|
||||
}
|
||||
|
||||
/* Add this character. */
|
||||
|
||||
+4
-4
@@ -988,7 +988,7 @@ print_redirection_list (redirects)
|
||||
else
|
||||
hdtail = heredocs = newredir;
|
||||
}
|
||||
else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
|
||||
else if (redirects->instruction == r_duplicating_output_word && redirects->redirector.dest == 1)
|
||||
{
|
||||
/* Temporarily translate it as the execution code does. */
|
||||
redirects->instruction = r_err_and_out;
|
||||
@@ -1024,8 +1024,8 @@ print_heredoc_header (redirect)
|
||||
kill_leading = redirect->instruction == r_deblank_reading_until;
|
||||
|
||||
/* Here doc header */
|
||||
if (redirect->redirector != 0)
|
||||
cprintf ("%d", redirect->redirector);
|
||||
if (redirect->redirector.dest != 0)
|
||||
cprintf ("%d", redirect->redirector.dest);
|
||||
|
||||
/* If the here document delimiter is quoted, single-quote it. */
|
||||
if (redirect->redirectee.filename->flags & W_QUOTED)
|
||||
@@ -1055,7 +1055,7 @@ print_redirection (redirect)
|
||||
|
||||
kill_leading = 0;
|
||||
redirectee = redirect->redirectee.filename;
|
||||
redirector = redirect->redirector;
|
||||
redirector = redirect->redirector.dest;
|
||||
redir_fd = redirect->redirectee.dest;
|
||||
|
||||
switch (redirect->instruction)
|
||||
|
||||
+26
-3
@@ -360,16 +360,16 @@ xtrace_set (fd, fp)
|
||||
{
|
||||
if (fd >= 0 && sh_validfd (fd) == 0)
|
||||
{
|
||||
internal_error ("xtrace_set: %d: invalid file descriptor", fd);
|
||||
internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
|
||||
return;
|
||||
}
|
||||
if (fp == 0)
|
||||
{
|
||||
internal_error ("xtrace_set: NULL file pointer");
|
||||
internal_error (_("xtrace_set: NULL file pointer"));
|
||||
return;
|
||||
}
|
||||
if (fd >= 0 && fileno (fp) != fd)
|
||||
internal_warning ("xtrace fd (%d) != fileno xtrace fp (%d)", fd, fileno (fp));
|
||||
internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
|
||||
|
||||
xtrace_fd = fd;
|
||||
xtrace_fp = fp;
|
||||
@@ -381,6 +381,29 @@ xtrace_init ()
|
||||
xtrace_set (-1, stderr);
|
||||
}
|
||||
|
||||
void
|
||||
xtrace_reset ()
|
||||
{
|
||||
if (xtrace_fd >= 0 && xtrace_fp)
|
||||
{
|
||||
fflush (xtrace_fp);
|
||||
fclose (xtrace_fp);
|
||||
}
|
||||
else if (xtrace_fd >= 0)
|
||||
close (xtrace_fd);
|
||||
|
||||
xtrace_fd = -1;
|
||||
xtrace_fp = stderr;
|
||||
}
|
||||
|
||||
void
|
||||
xtrace_fdchk (fd)
|
||||
int fd;
|
||||
{
|
||||
if (fd == xtrace_fd)
|
||||
xtrace_reset ();
|
||||
}
|
||||
|
||||
/* Return a string denoting what our indirection level is. */
|
||||
|
||||
char *
|
||||
|
||||
@@ -99,13 +99,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
|
||||
@@ -119,7 +121,7 @@ redirection_error (temp, error)
|
||||
filename = allocname = itos (temp->redirectee.dest);
|
||||
break;
|
||||
default:
|
||||
filename = allocname = itos (temp->redirector);
|
||||
filename = allocname = itos (temp->redirector.dest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -162,6 +164,10 @@ redirection_error (temp, error)
|
||||
internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));
|
||||
break;
|
||||
|
||||
case BADVAR_REDIRECT:
|
||||
internal_error (_("cannot assign fd to variable %s"), filename);
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_error ("%s: %s", filename, strerror (error));
|
||||
break;
|
||||
@@ -649,10 +655,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)
|
||||
@@ -670,11 +677,13 @@ do_redirection_internal (redirect, flags)
|
||||
return (AMBIGUOUS_REDIRECT);
|
||||
else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
|
||||
{
|
||||
sd.dest = 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.dest = redirector;
|
||||
if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
|
||||
rd.dest = lfd;
|
||||
else
|
||||
@@ -682,23 +691,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)
|
||||
{
|
||||
sd.dest = 1;
|
||||
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
|
||||
{
|
||||
@@ -730,7 +740,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. */
|
||||
@@ -1021,6 +1031,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)
|
||||
@@ -1034,16 +1045,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;
|
||||
@@ -1066,8 +1079,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);
|
||||
@@ -1096,9 +1110,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;
|
||||
@@ -1154,6 +1170,6 @@ stdin_redirects (redirs)
|
||||
int n;
|
||||
|
||||
for (n = 0, rp = redirs; rp; rp = rp->next)
|
||||
n += stdin_redirection (rp->instruction, rp->redirector);
|
||||
n += stdin_redirection (rp->instruction, rp->redirector.dest);
|
||||
return n;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user