Bash-4.3 distribution sources and documentation
This commit is contained in:
parent
4539d736f1
commit
ac50fbac37
497 changed files with 129395 additions and 87598 deletions
|
|
@ -1,7 +1,7 @@
|
|||
This file is read.def, from which is created read.c.
|
||||
It implements the builtin "read" in Bash.
|
||||
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
|
@ -51,15 +51,17 @@ Options:
|
|||
-r do not allow backslashes to escape any characters
|
||||
-s do not echo input coming from a terminal
|
||||
-t timeout time out and return failure if a complete line of input is
|
||||
not read withint TIMEOUT seconds. The value of the TMOUT
|
||||
not read within TIMEOUT seconds. The value of the TMOUT
|
||||
variable is the default timeout. TIMEOUT may be a
|
||||
fractional number. If TIMEOUT is 0, read returns success only
|
||||
if input is available on the specified file descriptor. The
|
||||
fractional number. If TIMEOUT is 0, read returns immediately,
|
||||
without trying to read any data, returning success only if
|
||||
input is available on the specified file descriptor. The
|
||||
exit status is greater than 128 if the timeout is exceeded
|
||||
-u fd read from file descriptor FD instead of the standard input
|
||||
|
||||
Exit Status:
|
||||
The return code is zero, unless end-of-file is encountered, read times out,
|
||||
The return code is zero, unless end-of-file is encountered, read times out
|
||||
(in which case it's greater than 128), a variable assignment error occurs,
|
||||
or an invalid file descriptor is supplied as the argument to -u.
|
||||
$END
|
||||
|
||||
|
|
@ -101,10 +103,17 @@ $END
|
|||
# include "input.h"
|
||||
#endif
|
||||
|
||||
#include "shmbutil.h"
|
||||
|
||||
#if !defined(errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern void run_pending_traps __P((void));
|
||||
|
||||
extern int posixly_correct;
|
||||
extern int trapped_signal_received;
|
||||
|
||||
struct ttsave
|
||||
{
|
||||
int fd;
|
||||
|
|
@ -127,15 +136,26 @@ static void ttyrestore __P((struct ttsave *));
|
|||
static sighandler sigalrm __P((int));
|
||||
static void reset_alarm __P((void));
|
||||
|
||||
static procenv_t alrmbuf;
|
||||
/* Try this to see what the rest of the shell can do with the information. */
|
||||
procenv_t alrmbuf;
|
||||
int sigalrm_seen;
|
||||
|
||||
static int reading;
|
||||
static SigHandler *old_alrm;
|
||||
static unsigned char delim;
|
||||
|
||||
/* In all cases, SIGALRM just sets a flag that we check periodically. This
|
||||
avoids problems with the semi-tricky stuff we do with the xfree of
|
||||
input_string at the top of the unwind-protect list (see below). */
|
||||
|
||||
/* Set a flag that CHECK_ALRM can check. This relies on zread calling
|
||||
trap.c:check_signals_and_traps(), which knows about sigalrm_seen and
|
||||
alrmbuf. */
|
||||
static sighandler
|
||||
sigalrm (s)
|
||||
int s;
|
||||
{
|
||||
longjmp (alrmbuf, 1);
|
||||
sigalrm_seen = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -158,7 +178,7 @@ read_builtin (list)
|
|||
register char *varname;
|
||||
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
|
||||
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
|
||||
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd;
|
||||
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd, lastsig, t_errno;
|
||||
unsigned int tmsec, tmusec;
|
||||
long ival, uval;
|
||||
intmax_t intval;
|
||||
|
|
@ -199,6 +219,9 @@ read_builtin (list)
|
|||
#endif
|
||||
USE_VAR(list);
|
||||
USE_VAR(ps2);
|
||||
USE_VAR(lastsig);
|
||||
|
||||
sigalrm_seen = reading = 0;
|
||||
|
||||
i = 0; /* Index into the string that we are reading. */
|
||||
raw = edit = 0; /* Not reading raw input by default. */
|
||||
|
|
@ -306,6 +329,18 @@ read_builtin (list)
|
|||
return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
#endif
|
||||
|
||||
/* Convenience: check early whether or not the first of possibly several
|
||||
variable names is a valid identifier, and bail early if so. */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
|
||||
#else
|
||||
if (list && legal_identifier (list->word->word) == 0)
|
||||
#endif
|
||||
{
|
||||
sh_invalidid (list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* If we're asked to ignore the delimiter, make sure we do. */
|
||||
if (ignore_delim)
|
||||
delim = -1;
|
||||
|
|
@ -380,14 +415,15 @@ read_builtin (list)
|
|||
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
{
|
||||
code = setjmp (alrmbuf);
|
||||
code = setjmp_nosigs (alrmbuf);
|
||||
if (code)
|
||||
{
|
||||
sigalrm_seen = 0;
|
||||
/* Tricky. The top of the unwind-protect stack is the free of
|
||||
input_string. We want to run all the rest and use input_string,
|
||||
so we have to save input_string temporarily, run the unwind-
|
||||
protects, then restore input_string so we can use it later. */
|
||||
|
||||
protects, then restore input_string so we can use it later */
|
||||
orig_input_string = 0;
|
||||
input_string[i] = '\0'; /* make sure it's terminated */
|
||||
if (i == 0)
|
||||
{
|
||||
|
|
@ -464,10 +500,12 @@ read_builtin (list)
|
|||
/* This *must* be the top unwind-protect on the stack, so the manipulation
|
||||
of the unwind-protect stack after the realloc() works right. */
|
||||
add_unwind_protect (xfree, input_string);
|
||||
interrupt_immediately++;
|
||||
terminate_immediately++;
|
||||
|
||||
unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
|
||||
CHECK_ALRM;
|
||||
if ((nchars > 0) && (input_is_tty == 0) && ignore_delim) /* read -N */
|
||||
unbuffered_read = 2;
|
||||
else if ((nchars > 0) || (delim != '\n') || input_is_pipe)
|
||||
unbuffered_read = 1;
|
||||
|
||||
if (prompt && edit == 0)
|
||||
{
|
||||
|
|
@ -482,6 +520,8 @@ read_builtin (list)
|
|||
ps2 = 0;
|
||||
for (print_ps2 = eof = retval = 0;;)
|
||||
{
|
||||
CHECK_ALRM;
|
||||
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
{
|
||||
|
|
@ -492,7 +532,9 @@ read_builtin (list)
|
|||
}
|
||||
if (rlbuf == 0)
|
||||
{
|
||||
reading = 1;
|
||||
rlbuf = edit_line (prompt ? prompt : "", itext);
|
||||
reading = 0;
|
||||
rlind = 0;
|
||||
}
|
||||
if (rlbuf == 0)
|
||||
|
|
@ -515,26 +557,58 @@ read_builtin (list)
|
|||
print_ps2 = 0;
|
||||
}
|
||||
|
||||
if (unbuffered_read)
|
||||
retval = zread (fd, &c, 1);
|
||||
#if 0
|
||||
if (posixly_correct == 0)
|
||||
interrupt_immediately++;
|
||||
#endif
|
||||
reading = 1;
|
||||
if (unbuffered_read == 2)
|
||||
retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr);
|
||||
else if (unbuffered_read)
|
||||
retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1);
|
||||
else
|
||||
retval = zreadc (fd, &c);
|
||||
retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
|
||||
reading = 0;
|
||||
#if 0
|
||||
if (posixly_correct == 0)
|
||||
interrupt_immediately--;
|
||||
#endif
|
||||
|
||||
if (retval <= 0)
|
||||
{
|
||||
if (retval < 0 && errno == EINTR)
|
||||
{
|
||||
lastsig = LASTSIG();
|
||||
if (lastsig == 0)
|
||||
lastsig = trapped_signal_received;
|
||||
run_pending_traps (); /* because interrupt_immediately is not set */
|
||||
}
|
||||
else
|
||||
lastsig = 0;
|
||||
CHECK_TERMSIG;
|
||||
eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
CHECK_ALRM;
|
||||
|
||||
#if defined (READLINE)
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_ALRM;
|
||||
if (i + 4 >= size) /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
|
||||
{
|
||||
input_string = (char *)xrealloc (input_string, size += 128);
|
||||
remove_unwind_protect ();
|
||||
add_unwind_protect (xfree, input_string);
|
||||
char *t;
|
||||
t = (char *)xrealloc (input_string, size += 128);
|
||||
|
||||
/* Only need to change unwind-protect if input_string changes */
|
||||
if (t != input_string)
|
||||
{
|
||||
input_string = t;
|
||||
remove_unwind_protect ();
|
||||
add_unwind_protect (xfree, input_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the next character is to be accepted verbatim, a backslash
|
||||
|
|
@ -565,9 +639,12 @@ read_builtin (list)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((unsigned char)c == delim)
|
||||
if (ignore_delim == 0 && (unsigned char)c == delim)
|
||||
break;
|
||||
|
||||
if (c == '\0' && delim != '\0')
|
||||
continue; /* skip NUL bytes in input */
|
||||
|
||||
if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
|
||||
{
|
||||
saw_escape++;
|
||||
|
|
@ -576,9 +653,10 @@ read_builtin (list)
|
|||
|
||||
add_char:
|
||||
input_string[i++] = c;
|
||||
CHECK_ALRM;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (nchars > 0 && MB_CUR_MAX > 1)
|
||||
if (nchars > 0 && MB_CUR_MAX > 1 && is_basic (c) == 0)
|
||||
{
|
||||
input_string[i] = '\0'; /* for simplicity and debugging */
|
||||
i += read_mbchar (fd, input_string, i, c, unbuffered_read);
|
||||
|
|
@ -591,15 +669,16 @@ add_char:
|
|||
break;
|
||||
}
|
||||
input_string[i] = '\0';
|
||||
CHECK_ALRM;
|
||||
|
||||
#if 1
|
||||
if (retval < 0)
|
||||
{
|
||||
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
|
||||
t_errno = errno;
|
||||
if (errno != EINTR)
|
||||
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
|
||||
run_unwind_frame ("read_builtin");
|
||||
return (EXECUTION_FAILURE);
|
||||
return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
reset_alarm ();
|
||||
|
|
@ -631,9 +710,6 @@ add_char:
|
|||
|
||||
assign_vars:
|
||||
|
||||
interrupt_immediately--;
|
||||
terminate_immediately--;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
/* If -a was given, take the string read, break it into a list of words,
|
||||
an assign them to `arrayname' in turn. */
|
||||
|
|
@ -658,6 +734,8 @@ assign_vars:
|
|||
xfree (input_string);
|
||||
return EXECUTION_FAILURE; /* existing associative array */
|
||||
}
|
||||
else if (invisible_p (var))
|
||||
VUNSETATTR (var, att_invisible);
|
||||
array_flush (array_cell (var));
|
||||
|
||||
alist = list_string (input_string, ifs_chars, 0);
|
||||
|
|
@ -703,7 +781,7 @@ assign_vars:
|
|||
var = bind_variable ("REPLY", input_string, 0);
|
||||
VUNSETATTR (var, att_invisible);
|
||||
|
||||
free (input_string);
|
||||
xfree (input_string);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
|
@ -829,6 +907,7 @@ bind_read_variable (name, value)
|
|||
char *name, *value;
|
||||
{
|
||||
SHELL_VAR *v;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (name) == 0)
|
||||
v = bind_variable (name, value, 0);
|
||||
|
|
@ -867,6 +946,7 @@ read_mbchar (fd, string, ind, ch, unbuffered)
|
|||
if (ret == (size_t)-2)
|
||||
{
|
||||
ps = ps_back;
|
||||
/* We don't want to be interrupted during a multibyte char read */
|
||||
if (unbuffered)
|
||||
r = zread (fd, &c, 1);
|
||||
else
|
||||
|
|
@ -947,7 +1027,9 @@ edit_line (p, itext)
|
|||
rl_startup_hook = set_itext;
|
||||
deftext = itext;
|
||||
}
|
||||
|
||||
ret = readline (p);
|
||||
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
old_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue