mirror of
https://github.com/sheumann/hush.git
synced 2024-09-12 00:55:11 +00:00
hush: readability improvements.
fix some more obscure bugs. a new redir4.tests is known to fail.
This commit is contained in:
parent
e05f9286a9
commit
c96865f445
202
shell/hush.c
202
shell/hush.c
@ -341,7 +341,11 @@ typedef enum redir_type {
|
|||||||
REDIRECT_HEREDOC = 4,
|
REDIRECT_HEREDOC = 4,
|
||||||
REDIRECT_IO = 5,
|
REDIRECT_IO = 5,
|
||||||
REDIRECT_HEREDOC2 = 6, /* REDIRECT_HEREDOC after heredoc is loaded */
|
REDIRECT_HEREDOC2 = 6, /* REDIRECT_HEREDOC after heredoc is loaded */
|
||||||
|
|
||||||
REDIRFD_CLOSE = -3,
|
REDIRFD_CLOSE = -3,
|
||||||
|
REDIRFD_SYNTAX_ERR = -2,
|
||||||
|
REDIRFD_TO_FILE = -1, /* otherwise, rd_fd if redirected to rd_dup */
|
||||||
|
|
||||||
HEREDOC_SKIPTABS = 1,
|
HEREDOC_SKIPTABS = 1,
|
||||||
HEREDOC_QUOTED = 2,
|
HEREDOC_QUOTED = 2,
|
||||||
} redir_type;
|
} redir_type;
|
||||||
@ -2427,6 +2431,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
|
|
||||||
for (redir = prog->redirects; redir; redir = redir->next) {
|
for (redir = prog->redirects; redir; redir = redir->next) {
|
||||||
if (redir->rd_type == REDIRECT_HEREDOC2) {
|
if (redir->rd_type == REDIRECT_HEREDOC2) {
|
||||||
|
/* rd_fd<<HERE case */
|
||||||
if (squirrel && redir->rd_fd < 3) {
|
if (squirrel && redir->rd_fd < 3) {
|
||||||
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
||||||
}
|
}
|
||||||
@ -2438,15 +2443,16 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redir->rd_dup == -1) {
|
if (redir->rd_dup == REDIRFD_TO_FILE) {
|
||||||
|
/* rd_fd<*>file case (<*> is <,>,>>,<>) */
|
||||||
char *p;
|
char *p;
|
||||||
if (redir->rd_filename == NULL) {
|
if (redir->rd_filename == NULL) {
|
||||||
/* Something went wrong in the parse.
|
/* Something went wrong in the parse.
|
||||||
* Pretend it didn't happen */
|
* Pretend it didn't happen */
|
||||||
|
bb_error_msg("bug in redirect parse");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mode = redir_table[redir->rd_type].mode;
|
mode = redir_table[redir->rd_type].mode;
|
||||||
//TODO: check redir for names like '\\'
|
|
||||||
p = expand_string_to_string(redir->rd_filename);
|
p = expand_string_to_string(redir->rd_filename);
|
||||||
openfd = open_or_warn(p, mode);
|
openfd = open_or_warn(p, mode);
|
||||||
free(p);
|
free(p);
|
||||||
@ -2457,6 +2463,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* rd_fd<*>rd_dup or rd_fd<*>- cases */
|
||||||
openfd = redir->rd_dup;
|
openfd = redir->rd_dup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2469,7 +2476,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
close(redir->rd_fd);
|
close(redir->rd_fd);
|
||||||
} else {
|
} else {
|
||||||
xdup2(openfd, redir->rd_fd);
|
xdup2(openfd, redir->rd_fd);
|
||||||
if (redir->rd_dup == -1)
|
if (redir->rd_dup == REDIRFD_TO_FILE)
|
||||||
close(openfd);
|
close(openfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3963,17 +3970,6 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
debug_printf_parse("done_word return 0: true null, ignored\n");
|
debug_printf_parse("done_word return 0: true null, ignored\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* If this word wasn't an assignment, next ones definitely
|
|
||||||
* can't be assignments. Even if they look like ones. */
|
|
||||||
if (word->o_assignment != DEFINITELY_ASSIGNMENT
|
|
||||||
&& word->o_assignment != WORD_IS_KEYWORD
|
|
||||||
) {
|
|
||||||
word->o_assignment = NOT_ASSIGNMENT;
|
|
||||||
} else {
|
|
||||||
if (word->o_assignment == DEFINITELY_ASSIGNMENT)
|
|
||||||
command->assignment_cnt++;
|
|
||||||
word->o_assignment = MAYBE_ASSIGNMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->pending_redirect) {
|
if (ctx->pending_redirect) {
|
||||||
/* We do not glob in e.g. >*.tmp case. bash seems to glob here
|
/* We do not glob in e.g. >*.tmp case. bash seems to glob here
|
||||||
@ -3989,14 +3985,33 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
* the expansion would result in one word."
|
* the expansion would result in one word."
|
||||||
*/
|
*/
|
||||||
ctx->pending_redirect->rd_filename = xstrdup(word->data);
|
ctx->pending_redirect->rd_filename = xstrdup(word->data);
|
||||||
|
/* Cater for >\file case:
|
||||||
|
* >\a creates file a; >\\a, >"\a", >"\\a" create file \a
|
||||||
|
* Same with heredocs:
|
||||||
|
* for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
|
||||||
|
*/
|
||||||
|
unbackslash(ctx->pending_redirect->rd_filename);
|
||||||
|
/* Is it <<"HEREDOC"? */
|
||||||
if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC
|
if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC
|
||||||
&& word->o_quoted
|
&& word->o_quoted
|
||||||
) {
|
) {
|
||||||
ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
|
ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
|
||||||
}
|
}
|
||||||
word->o_assignment = NOT_ASSIGNMENT;
|
|
||||||
debug_printf_parse("word stored in rd_filename: '%s'\n", word->data);
|
debug_printf_parse("word stored in rd_filename: '%s'\n", word->data);
|
||||||
} else {
|
} else {
|
||||||
|
/* If this word wasn't an assignment, next ones definitely
|
||||||
|
* can't be assignments. Even if they look like ones. */
|
||||||
|
if (word->o_assignment != DEFINITELY_ASSIGNMENT
|
||||||
|
&& word->o_assignment != WORD_IS_KEYWORD
|
||||||
|
) {
|
||||||
|
word->o_assignment = NOT_ASSIGNMENT;
|
||||||
|
} else {
|
||||||
|
if (word->o_assignment == DEFINITELY_ASSIGNMENT)
|
||||||
|
command->assignment_cnt++;
|
||||||
|
word->o_assignment = MAYBE_ASSIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command->group) {
|
||||||
/* "{ echo foo; } echo bar" - bad */
|
/* "{ echo foo; } echo bar" - bad */
|
||||||
/* NB: bash allows e.g.:
|
/* NB: bash allows e.g.:
|
||||||
* if true; then { echo foo; } fi
|
* if true; then { echo foo; } fi
|
||||||
@ -4004,14 +4019,13 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
* and disallows:
|
* and disallows:
|
||||||
* while if false; then false; fi; do; break; done
|
* while if false; then false; fi; do; break; done
|
||||||
* TODO? */
|
* TODO? */
|
||||||
if (command->group) {
|
|
||||||
syntax_error_at(word->data);
|
syntax_error_at(word->data);
|
||||||
debug_printf_parse("done_word return 1: syntax error, "
|
debug_printf_parse("done_word return 1: syntax error, "
|
||||||
"groups and arglists don't mix\n");
|
"groups and arglists don't mix\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#if HAS_KEYWORDS
|
#if HAS_KEYWORDS
|
||||||
#if ENABLE_HUSH_CASE
|
# if ENABLE_HUSH_CASE
|
||||||
if (ctx->ctx_dsemicolon
|
if (ctx->ctx_dsemicolon
|
||||||
&& strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */
|
&& strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */
|
||||||
) {
|
) {
|
||||||
@ -4019,12 +4033,12 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
/* ctx->ctx_res_w = RES_MATCH; */
|
/* ctx->ctx_res_w = RES_MATCH; */
|
||||||
ctx->ctx_dsemicolon = 0;
|
ctx->ctx_dsemicolon = 0;
|
||||||
} else
|
} else
|
||||||
#endif
|
# endif
|
||||||
if (!command->argv /* if it's the first word... */
|
if (!command->argv /* if it's the first word... */
|
||||||
#if ENABLE_HUSH_LOOPS
|
# if ENABLE_HUSH_LOOPS
|
||||||
&& ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
|
&& ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
|
||||||
&& ctx->ctx_res_w != RES_IN
|
&& ctx->ctx_res_w != RES_IN
|
||||||
#endif
|
# endif
|
||||||
) {
|
) {
|
||||||
debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
|
debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
|
||||||
if (reserved_word(word, ctx)) {
|
if (reserved_word(word, ctx)) {
|
||||||
@ -4090,20 +4104,23 @@ static int done_word(o_string *word, struct parse_context *ctx)
|
|||||||
|
|
||||||
/* Peek ahead in the input to find out if we have a "&n" construct,
|
/* Peek ahead in the input to find out if we have a "&n" construct,
|
||||||
* as in "2>&1", that represents duplicating a file descriptor.
|
* as in "2>&1", that represents duplicating a file descriptor.
|
||||||
* Return: REDIRFD_CLOSE (-3) if >&- "close fd" construct is seen,
|
* Return:
|
||||||
* -2 (syntax error), -1 if no & was seen, or the number found.
|
* REDIRFD_CLOSE if >&- "close fd" construct is seen,
|
||||||
|
* REDIRFD_SYNTAX_ERR if syntax error,
|
||||||
|
* REDIRFD_TO_FILE if no & was seen,
|
||||||
|
* or the number found.
|
||||||
*/
|
*/
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
#define redirect_dup_num(as_string, input) \
|
#define parse_redir_right_fd(as_string, input) \
|
||||||
redirect_dup_num(input)
|
parse_redir_right_fd(input)
|
||||||
#endif
|
#endif
|
||||||
static int redirect_dup_num(o_string *as_string, struct in_str *input)
|
static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
|
||||||
{
|
{
|
||||||
int ch, d, ok;
|
int ch, d, ok;
|
||||||
|
|
||||||
ch = i_peek(input);
|
ch = i_peek(input);
|
||||||
if (ch != '&')
|
if (ch != '&')
|
||||||
return -1;
|
return REDIRFD_TO_FILE;
|
||||||
|
|
||||||
ch = i_getch(input); /* get the & */
|
ch = i_getch(input); /* get the & */
|
||||||
nommu_addchr(as_string, ch);
|
nommu_addchr(as_string, ch);
|
||||||
@ -4127,10 +4144,10 @@ static int redirect_dup_num(o_string *as_string, struct in_str *input)
|
|||||||
//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
|
//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
|
||||||
|
|
||||||
bb_error_msg("ambiguous redirect");
|
bb_error_msg("ambiguous redirect");
|
||||||
return -2;
|
return REDIRFD_SYNTAX_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return code is 0 normally, 1 if a syntax error is detected
|
/* Return code is 0 normal, 1 if a syntax error is detected
|
||||||
*/
|
*/
|
||||||
static int parse_redirect(struct parse_context *ctx,
|
static int parse_redirect(struct parse_context *ctx,
|
||||||
int fd,
|
int fd,
|
||||||
@ -4142,12 +4159,12 @@ static int parse_redirect(struct parse_context *ctx,
|
|||||||
struct redir_struct **redirp;
|
struct redir_struct **redirp;
|
||||||
int dup_num;
|
int dup_num;
|
||||||
|
|
||||||
dup_num = -1;
|
dup_num = REDIRFD_TO_FILE;
|
||||||
if (style != REDIRECT_HEREDOC) {
|
if (style != REDIRECT_HEREDOC) {
|
||||||
/* Check for a '2>&1' type redirect */
|
/* Check for a '>&1' type redirect */
|
||||||
dup_num = redirect_dup_num(&ctx->as_string, input);
|
dup_num = parse_redir_right_fd(&ctx->as_string, input);
|
||||||
if (dup_num == -2)
|
if (dup_num == REDIRFD_SYNTAX_ERR)
|
||||||
return 1; /* syntax error */
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
int ch = i_peek(input);
|
int ch = i_peek(input);
|
||||||
dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
|
dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
|
||||||
@ -4158,7 +4175,7 @@ static int parse_redirect(struct parse_context *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (style == REDIRECT_OVERWRITE && dup_num == -1) {
|
if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
|
||||||
int ch = i_peek(input);
|
int ch = i_peek(input);
|
||||||
if (ch == '|') {
|
if (ch == '|') {
|
||||||
/* >|FILE redirect ("clobbering" >).
|
/* >|FILE redirect ("clobbering" >).
|
||||||
@ -4185,7 +4202,7 @@ static int parse_redirect(struct parse_context *ctx,
|
|||||||
redir_table[style].descrip);
|
redir_table[style].descrip);
|
||||||
|
|
||||||
redir->rd_dup = dup_num;
|
redir->rd_dup = dup_num;
|
||||||
if (style != REDIRECT_HEREDOC && dup_num != -1) {
|
if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
|
||||||
/* Erik had a check here that the file descriptor in question
|
/* Erik had a check here that the file descriptor in question
|
||||||
* is legit; I postpone that to "run time"
|
* is legit; I postpone that to "run time"
|
||||||
* A "-" representation of "close me" shows up as a -3 here */
|
* A "-" representation of "close me" shows up as a -3 here */
|
||||||
@ -4862,9 +4879,6 @@ static int parse_stream_dquoted(o_string *as_string,
|
|||||||
* only when followed by one of the following characters:
|
* only when followed by one of the following characters:
|
||||||
* $, `, ", \, or <newline>. A double quote may be quoted
|
* $, `, ", \, or <newline>. A double quote may be quoted
|
||||||
* within double quotes by preceding it with a backslash.
|
* within double quotes by preceding it with a backslash.
|
||||||
* If enabled, history expansion will be performed unless
|
|
||||||
* an ! appearing in double quotes is escaped using
|
|
||||||
* a backslash. The backslash preceding the ! is not removed."
|
|
||||||
*/
|
*/
|
||||||
if (strchr("$`\"\\", next) != NULL) {
|
if (strchr("$`\"\\", next) != NULL) {
|
||||||
o_addqchr(dest, i_getch(input));
|
o_addqchr(dest, i_getch(input));
|
||||||
@ -5081,17 +5095,71 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
if (is_ifs)
|
if (is_ifs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dest.o_assignment == MAYBE_ASSIGNMENT) {
|
|
||||||
/* ch is a special char and thus this word
|
|
||||||
* cannot be an assignment */
|
|
||||||
dest.o_assignment = NOT_ASSIGNMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
next = '\0';
|
next = '\0';
|
||||||
if (ch != '\n') {
|
if (ch != '\n') {
|
||||||
next = i_peek(input);
|
next = i_peek(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Catch <, > before deciding whether this word is
|
||||||
|
* an assignment. a=1 2>z b=2: b=2 is still assignment */
|
||||||
|
switch (ch) {
|
||||||
|
case '>':
|
||||||
|
redir_fd = redirect_opt_num(&dest);
|
||||||
|
if (done_word(&dest, &ctx)) {
|
||||||
|
goto parse_error;
|
||||||
|
}
|
||||||
|
redir_style = REDIRECT_OVERWRITE;
|
||||||
|
if (next == '>') {
|
||||||
|
redir_style = REDIRECT_APPEND;
|
||||||
|
ch = i_getch(input);
|
||||||
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
else if (next == '(') {
|
||||||
|
syntax_error(">(process) not supported");
|
||||||
|
goto parse_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (parse_redirect(&ctx, redir_fd, redir_style, input))
|
||||||
|
goto parse_error;
|
||||||
|
continue; /* back to top of while (1) */
|
||||||
|
case '<':
|
||||||
|
redir_fd = redirect_opt_num(&dest);
|
||||||
|
if (done_word(&dest, &ctx)) {
|
||||||
|
goto parse_error;
|
||||||
|
}
|
||||||
|
redir_style = REDIRECT_INPUT;
|
||||||
|
if (next == '<') {
|
||||||
|
redir_style = REDIRECT_HEREDOC;
|
||||||
|
heredoc_cnt++;
|
||||||
|
debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
|
||||||
|
ch = i_getch(input);
|
||||||
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
|
} else if (next == '>') {
|
||||||
|
redir_style = REDIRECT_IO;
|
||||||
|
ch = i_getch(input);
|
||||||
|
nommu_addchr(&ctx.as_string, ch);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
else if (next == '(') {
|
||||||
|
syntax_error("<(process) not supported");
|
||||||
|
goto parse_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (parse_redirect(&ctx, redir_fd, redir_style, input))
|
||||||
|
goto parse_error;
|
||||||
|
continue; /* back to top of while (1) */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dest.o_assignment == MAYBE_ASSIGNMENT
|
||||||
|
/* check that we are not in word in "a=1 2>word b=1": */
|
||||||
|
&& !ctx.pending_redirect
|
||||||
|
) {
|
||||||
|
/* ch is a special char and thus this word
|
||||||
|
* cannot be an assignment */
|
||||||
|
dest.o_assignment = NOT_ASSIGNMENT;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '#':
|
case '#':
|
||||||
if (dest.length == 0) {
|
if (dest.length == 0) {
|
||||||
@ -5171,52 +5239,6 @@ static struct pipe *parse_stream(char **pstring,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case '>':
|
|
||||||
redir_fd = redirect_opt_num(&dest);
|
|
||||||
if (done_word(&dest, &ctx)) {
|
|
||||||
goto parse_error;
|
|
||||||
}
|
|
||||||
redir_style = REDIRECT_OVERWRITE;
|
|
||||||
if (next == '>') {
|
|
||||||
redir_style = REDIRECT_APPEND;
|
|
||||||
ch = i_getch(input);
|
|
||||||
nommu_addchr(&ctx.as_string, ch);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else if (next == '(') {
|
|
||||||
syntax_error(">(process) not supported");
|
|
||||||
goto parse_error;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (parse_redirect(&ctx, redir_fd, redir_style, input))
|
|
||||||
goto parse_error;
|
|
||||||
break;
|
|
||||||
case '<':
|
|
||||||
redir_fd = redirect_opt_num(&dest);
|
|
||||||
if (done_word(&dest, &ctx)) {
|
|
||||||
goto parse_error;
|
|
||||||
}
|
|
||||||
redir_style = REDIRECT_INPUT;
|
|
||||||
if (next == '<') {
|
|
||||||
redir_style = REDIRECT_HEREDOC;
|
|
||||||
heredoc_cnt++;
|
|
||||||
debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
|
|
||||||
ch = i_getch(input);
|
|
||||||
nommu_addchr(&ctx.as_string, ch);
|
|
||||||
} else if (next == '>') {
|
|
||||||
redir_style = REDIRECT_IO;
|
|
||||||
ch = i_getch(input);
|
|
||||||
nommu_addchr(&ctx.as_string, ch);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else if (next == '(') {
|
|
||||||
syntax_error("<(process) not supported");
|
|
||||||
goto parse_error;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (parse_redirect(&ctx, redir_fd, redir_style, input))
|
|
||||||
goto parse_error;
|
|
||||||
break;
|
|
||||||
case ';':
|
case ';':
|
||||||
#if ENABLE_HUSH_CASE
|
#if ENABLE_HUSH_CASE
|
||||||
case_semi:
|
case_semi:
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
Test 0: var:ok
|
||||||
|
File created:ok
|
||||||
Test 1: var:ok
|
Test 1: var:ok
|
||||||
File created:ok
|
File created:ok
|
||||||
Test 2: var:ok
|
Test 2: var:ok
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
rm shell_test_$$ 2>/dev/null
|
||||||
|
var=bad
|
||||||
|
>shell_test_$$ var=ok
|
||||||
|
echo "Test 0: var:$var"
|
||||||
|
test -f shell_test_$$ && echo "File created:ok"
|
||||||
|
|
||||||
rm shell_test_$$ 2>/dev/null
|
rm shell_test_$$ 2>/dev/null
|
||||||
var=bad
|
var=bad
|
||||||
var=ok >shell_test_$$
|
var=ok >shell_test_$$
|
||||||
|
25
shell/hush_test/hush-misc/redir4.right
Normal file
25
shell/hush_test/hush-misc/redir4.right
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
shell_test
|
||||||
|
\shell_test
|
||||||
|
\shell_test
|
||||||
|
\shell_test
|
||||||
|
Here1
|
||||||
|
Ok1
|
||||||
|
Here2
|
||||||
|
Ok2
|
||||||
|
Here3
|
||||||
|
Ok3
|
||||||
|
Here4
|
||||||
|
Ok4
|
||||||
|
How with variable refs
|
||||||
|
shell_test_1
|
||||||
|
\shell_test_1
|
||||||
|
\shell_test_1
|
||||||
|
\shell_test_1
|
||||||
|
Here1
|
||||||
|
Ok1
|
||||||
|
Here2
|
||||||
|
Ok2
|
||||||
|
Here3
|
||||||
|
Ok3
|
||||||
|
Here4
|
||||||
|
Ok4
|
80
shell/hush_test/hush-misc/redir4.tests
Executable file
80
shell/hush_test/hush-misc/redir4.tests
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
rm *shell_test* 2>/dev/null
|
||||||
|
|
||||||
|
>\shell_test
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
>\\shell_test
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
>"\shell_test"
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
>"\\shell_test"
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
|
||||||
|
cat <<\shell_test
|
||||||
|
Here1
|
||||||
|
shell_test
|
||||||
|
echo Ok1
|
||||||
|
|
||||||
|
cat <<\\shell_test
|
||||||
|
Here2
|
||||||
|
\shell_test
|
||||||
|
echo Ok2
|
||||||
|
|
||||||
|
cat <<"\shell_test"
|
||||||
|
Here3
|
||||||
|
\shell_test
|
||||||
|
echo Ok3
|
||||||
|
|
||||||
|
cat <<"\\shell_test"
|
||||||
|
Here4
|
||||||
|
\shell_test
|
||||||
|
echo Ok4
|
||||||
|
|
||||||
|
|
||||||
|
echo How with variable refs
|
||||||
|
i=1
|
||||||
|
|
||||||
|
|
||||||
|
>\shell_test_$i
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
>\\shell_test_$i
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
>"\shell_test_$i"
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
>"\\shell_test_$i"
|
||||||
|
echo *shell_test*
|
||||||
|
rm *shell_test*
|
||||||
|
|
||||||
|
|
||||||
|
cat <<\shell_test_$i
|
||||||
|
Here1
|
||||||
|
shell_test_$i
|
||||||
|
echo Ok1
|
||||||
|
|
||||||
|
cat <<\\shell_test_$i
|
||||||
|
Here2
|
||||||
|
\shell_test_$i
|
||||||
|
echo Ok2
|
||||||
|
|
||||||
|
cat <<"\shell_test_$i"
|
||||||
|
Here3
|
||||||
|
\shell_test_$i
|
||||||
|
echo Ok3
|
||||||
|
|
||||||
|
cat <<"\\shell_test_$i"
|
||||||
|
Here4
|
||||||
|
\shell_test_$i
|
||||||
|
echo Ok4
|
Loading…
Reference in New Issue
Block a user