mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-03 10:20:49 +02:00
commit bash-20190322 snapshot
This commit is contained in:
@@ -5626,3 +5626,35 @@ execute_cmd.c
|
||||
do it at the beginning -- look at this more closely). Only do it
|
||||
for loops to avoid fd exhaustion. Fixes bug reported by
|
||||
sunnycemetery@gmail.com
|
||||
|
||||
3/22
|
||||
----
|
||||
lib/readline/{rlprivate.h,signals.c}
|
||||
- _rl_interrupt_immediately: removed as no longer used
|
||||
|
||||
redir.c
|
||||
- heredoc_expand: new function, called for both here-documents and
|
||||
here-strings, takes care of expanding the document and returns a
|
||||
string
|
||||
- write_here_document: use heredoc_expand, call write(2) once on the
|
||||
entire document; structure is now very similar to write_here_string
|
||||
|
||||
3/23
|
||||
----
|
||||
redir.c
|
||||
- here_document_to_fd: expand the here document/here string first,
|
||||
using heredoc_expand, then decide what to do; remove calls to
|
||||
write_here_document/write_here_string in favor of calling
|
||||
heredoc_write directly
|
||||
- here_document_to_fd: if the expanded document is of zero length,
|
||||
just open /dev/null right away and return it -- idea from yash
|
||||
- here_document_to_fd: if the length of the expanded document is
|
||||
between 1 and PIPESIZE (pipe capacity, computed by builtins/psize.aux
|
||||
and stored in builtins/pipesize.h), try to use a pipe: write
|
||||
the document to the write end and return the read end. Prompted by a
|
||||
report from Daniel Kahn Gillmor <dkg@fifthhorseman.net>
|
||||
|
||||
builtins/enable.def
|
||||
- dyn_load_builtin: add warning if dynamic builtin with a load function
|
||||
is loaded more than once, before running the load function a second
|
||||
time. From a suggestion by Stan Marsh <gazelle@xmission.com>
|
||||
|
||||
@@ -742,6 +742,9 @@ ${DEFDIR}/bashgetopt.o: $(BUILTIN_SRCDIR)/bashgetopt.c
|
||||
${DEFDIR}/builtext.h: $(BUILTIN_DEFS)
|
||||
@(cd $(DEFDIR) && $(MAKE) $(MFLAGS) builtext.h ) || exit 1
|
||||
|
||||
${DEFDIR}/pipesize.h:
|
||||
@(cd $(DEFDIR) && $(MAKE) $(MFLAGS) pipesize.h ) || exit 1
|
||||
|
||||
$(SDIR)/man2html$(EXEEXT): ${SUPPORT_SRC}/man2html.c
|
||||
@(cd $(SDIR) && $(MAKE) $(MFLAGS) all ) || exit 1
|
||||
|
||||
@@ -1111,6 +1114,7 @@ redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posix
|
||||
redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
|
||||
redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
|
||||
redir.o: flags.h execute_cmd.h redir.h input.h
|
||||
redir.o: ${DEFDIR}/pipesize.h
|
||||
shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
|
||||
shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
|
||||
shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
|
||||
|
||||
+6
-1
@@ -362,6 +362,8 @@ dyn_load_builtin (list, flags, filename)
|
||||
strcpy (struct_name, name);
|
||||
strcpy (struct_name + size, STRUCT_SUFFIX);
|
||||
|
||||
old_builtin = builtin_address_internal (name, 1);
|
||||
|
||||
b = (struct builtin *)dlsym (handle, struct_name);
|
||||
if (b == 0)
|
||||
{
|
||||
@@ -381,6 +383,9 @@ dyn_load_builtin (list, flags, filename)
|
||||
loadfunc = (sh_load_func_t *)dlsym (handle, funcname);
|
||||
if (loadfunc)
|
||||
{
|
||||
/* Add warning if running an init function more than once */
|
||||
if (old_builtin && (old_builtin->flags & STATIC_BUILTIN) == 0)
|
||||
builtin_warning (_("%s: dynamic builtin already loaded"), name);
|
||||
r = (*loadfunc) (name);
|
||||
if (r == 0)
|
||||
{
|
||||
@@ -396,7 +401,7 @@ dyn_load_builtin (list, flags, filename)
|
||||
b->flags |= SPECIAL_BUILTIN;
|
||||
b->handle = handle;
|
||||
|
||||
if (old_builtin = builtin_address_internal (name, 1))
|
||||
if (old_builtin)
|
||||
{
|
||||
replaced++;
|
||||
FASTCOPY ((char *)b, (char *)old_builtin, sizeof (struct builtin));
|
||||
|
||||
+6
-6
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet.ramey@case.edu
|
||||
.\"
|
||||
.\" Last Change: Tue Feb 26 09:46:20 EST 2019
|
||||
.\" Last Change: Sun Mar 24 14:05:55 EDT 2019
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2019 February 26" "GNU Bash 5.0"
|
||||
.TH BASH 1 "2019 March 24" "GNU Bash 5.0"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -5212,7 +5212,7 @@ jobs are terminated.
|
||||
.PP
|
||||
When the shell is waiting for a job or process using the \fBwait\fP
|
||||
builtin, and job control is enabled, \fBwait\fP will return when the
|
||||
job changes state. The \fB\-f\fP option will force \fBwait\fP to wait
|
||||
job changes state. The \fB\-f\fP option causes \fBwait\fP to wait
|
||||
until the job or process terminates before returning.
|
||||
.SH PROMPTING
|
||||
When executing interactively,
|
||||
@@ -10761,9 +10761,9 @@ is not given, all currently active child processes
|
||||
are waited for, and the return status is zero.
|
||||
If the \fB\-n\fP option is supplied, \fBwait\fP waits for any job to
|
||||
terminate and returns its exit status.
|
||||
If the \fB\-f\fP option is supplied, and job control is enabled,
|
||||
\fBwait\fP forces \fIid\fP to terminate before returning its status,
|
||||
instead of returning when it changes status.
|
||||
Supplying the \fB\-f\fP option, when job control is enabled,
|
||||
forces \fBwait\fP to wait for \fIid\fP to terminate before returning
|
||||
its status, instead of returning when it changes status.
|
||||
If
|
||||
.I id
|
||||
specifies a non-existent process or job, the return status is
|
||||
|
||||
+5
-4
@@ -7988,7 +7988,7 @@ Bash does not print another warning, and any stopped jobs are terminated.
|
||||
|
||||
When the shell is waiting for a job or process using the @code{wait}
|
||||
builtin, and job control is enabled, @code{wait} will return when the
|
||||
job changes state. The @option{-f} option will force @code{wait} to wait
|
||||
job changes state. The @option{-f} option causes @code{wait} to wait
|
||||
until the job or process terminates before returning.
|
||||
|
||||
@node Job Control Builtins
|
||||
@@ -8098,9 +8098,10 @@ If no arguments are given, all currently active child processes are
|
||||
waited for, and the return status is zero.
|
||||
If the @option{-n} option is supplied, @code{wait} waits for any job to
|
||||
terminate and returns its exit status.
|
||||
If the @option{-f} option is supplied, and job control is enabled,
|
||||
@code{wait} forces each @var{pid} or @var{jobspec} to terminate before
|
||||
returning its status, intead of returning when it changes status.
|
||||
Supplying the @option{-f} option, when job control is enabled,
|
||||
forces @code{wait} to wait for each @var{pid} or @var{jobspec} to
|
||||
terminate before returning its status, intead of returning when it changes
|
||||
status.
|
||||
If neither @var{jobspec} nor @var{pid} specifies an active child process
|
||||
of the shell, the return status is 127.
|
||||
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
Copyright (C) 1988-2019 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Tue Feb 26 09:46:37 EST 2019
|
||||
@set LASTCHANGE Sun Mar 24 14:05:55 EDT 2019
|
||||
|
||||
@set EDITION 5.0
|
||||
@set VERSION 5.0
|
||||
|
||||
@set UPDATED 26 February 2019
|
||||
@set UPDATED-MONTH February 2019
|
||||
@set UPDATED 24 March 2019
|
||||
@set UPDATED-MONTH March 2019
|
||||
|
||||
@@ -526,7 +526,6 @@ extern int _rl_executing_keyseq_size;
|
||||
extern _rl_search_cxt *_rl_nscxt;
|
||||
|
||||
/* signals.c */
|
||||
extern int _rl_interrupt_immediately;
|
||||
extern int volatile _rl_caught_signal;
|
||||
|
||||
extern _rl_sigcleanup_func_t *_rl_sigcleanup;
|
||||
|
||||
@@ -99,7 +99,6 @@ int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
|
||||
#endif
|
||||
|
||||
/* Private variables. */
|
||||
int _rl_interrupt_immediately = 0;
|
||||
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
|
||||
|
||||
/* If non-zero, print characters corresponding to received signals as long as
|
||||
@@ -163,14 +162,7 @@ _rl_signal_handler (int sig)
|
||||
static RETSIGTYPE
|
||||
rl_signal_handler (int sig)
|
||||
{
|
||||
if (_rl_interrupt_immediately)
|
||||
{
|
||||
_rl_interrupt_immediately = 0;
|
||||
_rl_handle_signal (sig);
|
||||
}
|
||||
else
|
||||
_rl_caught_signal = sig;
|
||||
|
||||
_rl_caught_signal = sig;
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* redir.c -- Functions to perform input and output redirection. */
|
||||
|
||||
/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1997-2019 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -58,6 +58,17 @@ extern int errno;
|
||||
# include "input.h"
|
||||
#endif
|
||||
|
||||
#include "builtins/pipesize.h"
|
||||
|
||||
/* Normally set by a build process command that computes pipe capacity */
|
||||
#ifndef PIPESIZE
|
||||
# ifdef PIPE_BUF
|
||||
# define PIPESIZE PIPE_BUF
|
||||
# else
|
||||
# define PIPESIZE 4096
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define SHELL_FD_BASE 10
|
||||
|
||||
int expanding_redir;
|
||||
@@ -74,8 +85,8 @@ static int stdin_redirection __P((enum r_instruction, int));
|
||||
static int undoablefd __P((int));
|
||||
static int do_redirection_internal __P((REDIRECT *, int));
|
||||
|
||||
static int write_here_document __P((int, WORD_DESC *));
|
||||
static int write_here_string __P((int, WORD_DESC *));
|
||||
static char *heredoc_expand __P((WORD_DESC *, enum r_instruction, size_t *));
|
||||
static int heredoc_write __P((int, char *, size_t));
|
||||
static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));
|
||||
|
||||
static int redir_special_open __P((int, char *, int, int, enum r_instruction));
|
||||
@@ -309,19 +320,45 @@ redirection_expand (word)
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
write_here_string (fd, redirectee)
|
||||
int fd;
|
||||
WORD_DESC *redirectee;
|
||||
{
|
||||
char *herestr;
|
||||
int herelen, n, e, old;
|
||||
/* Expand a here-document or here-string (determined by RI) contained in
|
||||
REDIRECTEE and return the expanded document. If LENP is non-zero, put
|
||||
the length of the returned string into *LENP.
|
||||
|
||||
This captures everything about expanding here-documents and here-strings:
|
||||
the returned document should be written directly to whatever file
|
||||
descriptor is specified. In particular, it adds a newline to the end of
|
||||
a here-string to preserve previous semantics. */
|
||||
static char *
|
||||
heredoc_expand (redirectee, ri, lenp)
|
||||
WORD_DESC *redirectee;
|
||||
enum r_instruction ri;
|
||||
size_t *lenp;
|
||||
{
|
||||
char *document;
|
||||
size_t dlen;
|
||||
int old;
|
||||
|
||||
if (redirectee->word == 0 || redirectee->word[0] == '\0')
|
||||
{
|
||||
if (lenp)
|
||||
*lenp = 0;
|
||||
return (redirectee->word);
|
||||
}
|
||||
|
||||
/* Quoted here documents are not expanded */
|
||||
if (ri != r_reading_string && (redirectee->flags & W_QUOTED))
|
||||
{
|
||||
if (lenp)
|
||||
*lenp = STRLEN (redirectee->word);
|
||||
return (redirectee->word);
|
||||
}
|
||||
|
||||
expanding_redir = 1;
|
||||
/* Now that we've changed the variable search order to ignore the temp
|
||||
environment, see if we need to change the cached IFS values. */
|
||||
sv_ifs ("IFS");
|
||||
herestr = expand_string_unsplit_to_string (redirectee->word, 0);
|
||||
document = (ri == r_reading_string) ? expand_string_unsplit_to_string (redirectee->word, 0)
|
||||
: expand_string_to_string (redirectee->word, Q_HERE_DOCUMENT);
|
||||
expanding_redir = 0;
|
||||
/* Now we need to change the variable search order back to include the temp
|
||||
environment. We force the temp environment search by forcing
|
||||
@@ -332,136 +369,108 @@ write_here_string (fd, redirectee)
|
||||
sv_ifs ("IFS");
|
||||
executing_builtin = old;
|
||||
|
||||
herelen = STRLEN (herestr);
|
||||
|
||||
n = write (fd, herestr, herelen);
|
||||
if (n == herelen)
|
||||
dlen = STRLEN (document);
|
||||
/* XXX - Add trailing newline to here-string */
|
||||
if (ri == r_reading_string)
|
||||
{
|
||||
n = write (fd, "\n", 1);
|
||||
herelen = 1;
|
||||
document = xrealloc (document, dlen + 2);
|
||||
document[dlen++] = '\n';
|
||||
document[dlen] = '\0';
|
||||
}
|
||||
if (lenp)
|
||||
*lenp = dlen;
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
/* Write HEREDOC (of length HDLEN) to FD, returning 0 on success and ERRNO on
|
||||
error. Don't handle interrupts. */
|
||||
static int
|
||||
heredoc_write (fd, heredoc, herelen)
|
||||
int fd;
|
||||
char *heredoc;
|
||||
size_t herelen;
|
||||
{
|
||||
ssize_t nw;
|
||||
int e;
|
||||
|
||||
errno = 0;
|
||||
nw = write (fd, heredoc, herelen);
|
||||
e = errno;
|
||||
FREE (herestr);
|
||||
if (n != herelen)
|
||||
if (nw != herelen)
|
||||
{
|
||||
if (e == 0)
|
||||
e = ENOSPC;
|
||||
return e;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write the text of the here document pointed to by REDIRECTEE to the file
|
||||
descriptor FD, which is already open to a temp file. Return 0 if the
|
||||
write is successful, otherwise return errno. */
|
||||
static int
|
||||
write_here_document (fd, redirectee)
|
||||
int fd;
|
||||
WORD_DESC *redirectee;
|
||||
{
|
||||
char *document;
|
||||
int document_len, fd2, old;
|
||||
FILE *fp;
|
||||
register WORD_LIST *t, *tlist;
|
||||
|
||||
/* Expand the text if the word that was specified had
|
||||
no quoting. The text that we expand is treated
|
||||
exactly as if it were surrounded by double quotes. */
|
||||
|
||||
if (redirectee->flags & W_QUOTED)
|
||||
{
|
||||
document = redirectee->word;
|
||||
document_len = strlen (document);
|
||||
/* Set errno to something reasonable if the write fails. */
|
||||
if (write (fd, document, document_len) < document_len)
|
||||
{
|
||||
if (errno == 0)
|
||||
errno = ENOSPC;
|
||||
return (errno);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
expanding_redir = 1;
|
||||
/* Now that we've changed the variable search order to ignore the temp
|
||||
environment, see if we need to change the cached IFS values. */
|
||||
sv_ifs ("IFS");
|
||||
tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
|
||||
expanding_redir = 0;
|
||||
/* Now we need to change the variable search order back to include the temp
|
||||
environment. We force the temp environment search by forcing
|
||||
executing_builtin to 1. This is what makes `read' get the right values
|
||||
for the IFS-related cached variables, for example. */
|
||||
old = executing_builtin;
|
||||
executing_builtin = 1;
|
||||
sv_ifs ("IFS");
|
||||
executing_builtin = old;
|
||||
|
||||
if (tlist)
|
||||
{
|
||||
/* Try using buffered I/O (stdio) and writing a word
|
||||
at a time, letting stdio do the work of buffering
|
||||
for us rather than managing our own strings. Most
|
||||
stdios are not particularly fast, however -- this
|
||||
may need to be reconsidered later. */
|
||||
if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)
|
||||
{
|
||||
old = errno;
|
||||
if (fd2 >= 0)
|
||||
close (fd2);
|
||||
dispose_words (tlist);
|
||||
errno = old;
|
||||
return (errno);
|
||||
}
|
||||
errno = 0;
|
||||
for (t = tlist; t; t = t->next)
|
||||
{
|
||||
/* This is essentially the body of
|
||||
string_list_internal expanded inline. */
|
||||
document = t->word->word;
|
||||
document_len = strlen (document);
|
||||
if (t != tlist)
|
||||
putc (' ', fp); /* separator */
|
||||
fwrite (document, document_len, 1, fp);
|
||||
if (ferror (fp))
|
||||
{
|
||||
if (errno == 0)
|
||||
errno = ENOSPC;
|
||||
fd2 = errno;
|
||||
fclose(fp);
|
||||
dispose_words (tlist);
|
||||
return (fd2);
|
||||
}
|
||||
}
|
||||
dispose_words (tlist);
|
||||
if (fclose (fp) != 0)
|
||||
{
|
||||
if (errno == 0)
|
||||
errno = ENOSPC;
|
||||
return (errno);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a temporary file holding the text of the here document pointed to
|
||||
by REDIRECTEE, and return a file descriptor open for reading to the temp
|
||||
file. Return -1 on any error, and make sure errno is set appropriately. */
|
||||
/* Create a temporary file or pipe holding the text of the here document
|
||||
pointed to by REDIRECTEE, and return a file descriptor open for reading
|
||||
to it. Return -1 on any error, and make sure errno is set appropriately. */
|
||||
static int
|
||||
here_document_to_fd (redirectee, ri)
|
||||
WORD_DESC *redirectee;
|
||||
enum r_instruction ri;
|
||||
{
|
||||
char *filename;
|
||||
int r, fd, fd2;
|
||||
int r, fd, fd2, herepipe[2];
|
||||
char *document;
|
||||
size_t document_len;
|
||||
|
||||
/* Expand the here-document/here-string first and then decide what to do. */
|
||||
document = heredoc_expand (redirectee, ri, &document_len);
|
||||
|
||||
/* If we have a zero-length document, don't mess with a temp file */
|
||||
if (document_len == 0)
|
||||
{
|
||||
fd = open ("/dev/null", O_RDONLY);
|
||||
r = errno;
|
||||
if (document != redirectee->word)
|
||||
FREE (document);
|
||||
errno = r;
|
||||
return fd;
|
||||
}
|
||||
|
||||
#if defined (PIPESIZE)
|
||||
/* Try to use a pipe internal to this process if the document is shorter
|
||||
than the system's pipe capacity (computed at build time). We want to
|
||||
write the entire document without write blocking. */
|
||||
if (document_len <= PIPESIZE)
|
||||
{
|
||||
if (pipe (herepipe) < 0)
|
||||
{
|
||||
r = errno;
|
||||
if (document != redirectee->word)
|
||||
free (document);
|
||||
errno = r;
|
||||
return (-1);
|
||||
}
|
||||
r = heredoc_write (herepipe[1], document, document_len);
|
||||
if (document != redirectee->word)
|
||||
free (document);
|
||||
close (herepipe[1]);
|
||||
if (r) /* write error */
|
||||
{
|
||||
close (herepipe[0]);
|
||||
errno = r;
|
||||
return (-1);
|
||||
}
|
||||
return (herepipe[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename);
|
||||
|
||||
/* If we failed for some reason other than the file existing, abort */
|
||||
if (fd < 0)
|
||||
{
|
||||
r = errno;
|
||||
FREE (filename);
|
||||
if (document != redirectee->word)
|
||||
FREE (document);
|
||||
errno = r;
|
||||
return (fd);
|
||||
}
|
||||
|
||||
@@ -469,10 +478,9 @@ here_document_to_fd (redirectee, ri)
|
||||
SET_CLOSE_ON_EXEC (fd);
|
||||
|
||||
errno = r = 0; /* XXX */
|
||||
/* write_here_document returns 0 on success, errno on failure. */
|
||||
if (redirectee->word)
|
||||
r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
|
||||
: write_here_string (fd, redirectee);
|
||||
r = heredoc_write (fd, document, document_len);
|
||||
if (document != redirectee->word)
|
||||
FREE (document);
|
||||
|
||||
if (r)
|
||||
{
|
||||
|
||||
+9
-1
@@ -1,3 +1,11 @@
|
||||
a
|
||||
b
|
||||
c
|
||||
a
|
||||
$PS4
|
||||
|
||||
|
||||
|
||||
there
|
||||
one - alpha
|
||||
two - beta
|
||||
@@ -93,6 +101,6 @@ argv[1] = <two>
|
||||
argv[2] = <threefi>
|
||||
argv[3] = <ve>
|
||||
comsub here-string
|
||||
./heredoc.tests: line 105: warning: here-document at line 103 delimited by end-of-file (wanted `EOF')
|
||||
./heredoc.tests: line 133: warning: here-document at line 131 delimited by end-of-file (wanted `EOF')
|
||||
hi
|
||||
there
|
||||
|
||||
+29
-1
@@ -1,5 +1,33 @@
|
||||
# check order and content of multiple here docs
|
||||
# basics
|
||||
cat <<EOF
|
||||
a
|
||||
b
|
||||
c
|
||||
EOF
|
||||
read x <<EOF
|
||||
a
|
||||
b
|
||||
c
|
||||
EOF
|
||||
echo "$x"
|
||||
read x y <<\EOF
|
||||
$PS4
|
||||
EOF
|
||||
echo "$x"
|
||||
|
||||
# empty here-documents
|
||||
read x <<EOF
|
||||
EOF
|
||||
echo "$x"
|
||||
read x <<\EOF
|
||||
EOF
|
||||
echo "$x"
|
||||
read x <<EOF
|
||||
$empty
|
||||
EOF
|
||||
echo "$x"
|
||||
|
||||
# check order and content of multiple here docs
|
||||
cat << EOF1 << EOF2
|
||||
hi
|
||||
EOF1
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
alpha
|
||||
beta
|
||||
4
|
||||
4
|
||||
|
||||
|
||||
|
||||
abcde
|
||||
yo
|
||||
hot damn
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
# basics
|
||||
read x <<<"alpha"
|
||||
echo "$x"
|
||||
read x <<<beta
|
||||
echo "$x"
|
||||
X=4
|
||||
read x <<<$X
|
||||
echo "$x"
|
||||
read x <<<"$X"
|
||||
echo "$x"
|
||||
unset X
|
||||
|
||||
# empty here-strings
|
||||
read x <<<""
|
||||
echo "$x"
|
||||
read x <<<"$empty"
|
||||
echo "$x"
|
||||
read x <<<$empty
|
||||
echo "$x"
|
||||
|
||||
a=hot
|
||||
b=damn
|
||||
f1()
|
||||
|
||||
Reference in New Issue
Block a user