1996-08-26 18:22:31 +00:00
|
|
|
This file is read.def, from which is created read.c.
|
|
|
|
It implements the builtin "read" in Bash.
|
|
|
|
|
|
|
|
Copyright (C) 1987, 1989, 1991 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
|
2000-03-17 21:46:59 +00:00
|
|
|
Software Foundation; either version 2, or (at your option) any later
|
1996-08-26 18:22:31 +00:00
|
|
|
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; see the file COPYING. If not, write to the Free Software
|
2000-03-17 21:46:59 +00:00
|
|
|
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
1996-08-26 18:22:31 +00:00
|
|
|
|
|
|
|
$PRODUCES read.c
|
|
|
|
|
|
|
|
$BUILTIN read
|
|
|
|
$FUNCTION read_builtin
|
2000-03-17 21:46:59 +00:00
|
|
|
$SHORT_DOC read [-ers] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
|
1996-08-26 18:22:31 +00:00
|
|
|
One line is read from the standard input, and the first word is
|
1996-12-23 17:02:34 +00:00
|
|
|
assigned to the first NAME, the second word to the second NAME, and so
|
|
|
|
on, with leftover words assigned to the last NAME. Only the characters
|
2000-03-17 21:46:59 +00:00
|
|
|
found in $IFS are recognized as word delimiters. If no NAMEs are supplied,
|
|
|
|
the line read is stored in the REPLY variable. If the -r option is given,
|
|
|
|
this signifies `raw' input, and backslash escaping is disabled. The
|
|
|
|
-d option causes read to continue until the first character of DELIM is
|
|
|
|
read, rather than newline. If the `-p' option is supplied, the string
|
|
|
|
PROMPT is output without a trailing newline before attempting to read.
|
|
|
|
If -a is supplied, the words read are assigned to sequential indices of
|
|
|
|
ARRAY, starting at zero. If -e is supplied and the shell is interactive,
|
|
|
|
readline is used to obtain the line. If -n is supplied with a non-zero
|
|
|
|
NCHARS argument, read returns after NCHARS characters have been read.
|
|
|
|
The -s option causes input coming from a terminal to not be echoed.
|
|
|
|
|
|
|
|
The -t option causes read to time out and return failure if a complete line
|
|
|
|
of input is not read within TIMEOUT seconds. The return code is zero,
|
|
|
|
unless end-of-file is encountered or read times out.
|
1996-08-26 18:22:31 +00:00
|
|
|
$END
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
#include "bashtypes.h"
|
|
|
|
#include "posixstat.h"
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
#include <stdio.h>
|
1996-12-23 17:02:34 +00:00
|
|
|
|
|
|
|
#if defined (HAVE_UNISTD_H)
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
#include <signal.h>
|
1997-09-22 20:22:27 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
2001-04-06 19:14:31 +00:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
# include <fcntl.h>
|
|
|
|
# include <io.h>
|
|
|
|
#endif
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
#include "../shell.h"
|
|
|
|
#include "common.h"
|
1996-12-23 17:02:34 +00:00
|
|
|
#include "bashgetopt.h"
|
1996-08-26 18:22:31 +00:00
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
#include <shtty.h>
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
#if defined (READLINE)
|
|
|
|
#include "../bashline.h"
|
|
|
|
#include <readline/readline.h>
|
|
|
|
#endif
|
1996-08-26 18:22:31 +00:00
|
|
|
|
1997-09-22 20:22:27 +00:00
|
|
|
#if !defined(errno)
|
|
|
|
extern int errno;
|
|
|
|
#endif
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
#define issep(c) (strchr (ifs_chars, (c)))
|
1996-08-26 18:22:31 +00:00
|
|
|
|
|
|
|
extern int interrupt_immediately;
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
#if defined (READLINE)
|
|
|
|
static char *edit_line ();
|
2000-03-17 21:46:59 +00:00
|
|
|
static void set_eol_delim ();
|
|
|
|
static void reset_eol_delim ();
|
1996-12-23 17:02:34 +00:00
|
|
|
#endif
|
|
|
|
static SHELL_VAR *bind_read_variable ();
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
static procenv_t alrmbuf;
|
|
|
|
static SigHandler *old_alrm;
|
|
|
|
static int delim;
|
|
|
|
|
|
|
|
static sighandler
|
|
|
|
sigalrm (s)
|
|
|
|
int s;
|
|
|
|
{
|
|
|
|
longjmp (alrmbuf, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reset_alarm ()
|
|
|
|
{
|
|
|
|
set_signal_handler (SIGALRM, old_alrm);
|
|
|
|
alarm (0);
|
|
|
|
}
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
/* Read the value of the shell variables whose names follow.
|
|
|
|
The reading is done from the current input stream, whatever
|
|
|
|
that may be. Successive words of the input line are assigned
|
|
|
|
to the variables mentioned in LIST. The last variable in LIST
|
|
|
|
gets the remainder of the words on the line. If no variables
|
1996-12-23 17:02:34 +00:00
|
|
|
are mentioned in LIST, then the default variable is $REPLY. */
|
|
|
|
int
|
1996-08-26 18:22:31 +00:00
|
|
|
read_builtin (list)
|
|
|
|
WORD_LIST *list;
|
|
|
|
{
|
|
|
|
register char *varname;
|
2000-03-17 21:46:59 +00:00
|
|
|
int size, i, pass_next, saw_escape, eof, opt, retval, code;
|
|
|
|
int input_is_tty, input_is_pipe, unbuffered_read;
|
|
|
|
int raw, edit, tmout, nchars, silent;
|
|
|
|
long timeoutval, ncharsval;
|
1996-12-23 17:02:34 +00:00
|
|
|
char c;
|
|
|
|
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
|
|
|
|
char *e, *t, *t1;
|
2000-03-17 21:46:59 +00:00
|
|
|
struct stat tsb;
|
1996-08-26 18:22:31 +00:00
|
|
|
SHELL_VAR *var;
|
1996-12-23 17:02:34 +00:00
|
|
|
#if defined (ARRAY_VARS)
|
|
|
|
WORD_LIST *alist;
|
|
|
|
#endif
|
|
|
|
#if defined (READLINE)
|
|
|
|
char *rlbuf;
|
|
|
|
int rlind;
|
|
|
|
#endif
|
1996-08-26 18:22:31 +00:00
|
|
|
|
|
|
|
i = 0; /* Index into the string that we are reading. */
|
1996-12-23 17:02:34 +00:00
|
|
|
raw = edit = 0; /* Not reading raw input by default. */
|
2000-03-17 21:46:59 +00:00
|
|
|
silent = 0;
|
1996-12-23 17:02:34 +00:00
|
|
|
arrayname = prompt = (char *)NULL;
|
|
|
|
|
|
|
|
#if defined (READLINE)
|
|
|
|
rlbuf = (char *)0;
|
|
|
|
rlind = 0;
|
|
|
|
#endif
|
1996-08-26 18:22:31 +00:00
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
tmout = -1; /* no timeout */
|
|
|
|
nchars = input_is_tty = input_is_pipe = unbuffered_read = 0;
|
|
|
|
delim = '\n'; /* read until newline */
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
reset_internal_getopt ();
|
2000-03-17 21:46:59 +00:00
|
|
|
while ((opt = internal_getopt (list, "erp:a:d:t:n:s")) != -1)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
switch (opt)
|
2001-04-06 19:14:31 +00:00
|
|
|
{
|
|
|
|
case 'r':
|
1996-12-23 17:02:34 +00:00
|
|
|
raw = 1;
|
1996-08-26 18:22:31 +00:00
|
|
|
break;
|
1996-12-23 17:02:34 +00:00
|
|
|
case 'p':
|
|
|
|
prompt = list_optarg;
|
|
|
|
break;
|
2000-03-17 21:46:59 +00:00
|
|
|
case 's':
|
|
|
|
silent = 1;
|
|
|
|
break;
|
1996-12-23 17:02:34 +00:00
|
|
|
case 'e':
|
|
|
|
#if defined (READLINE)
|
|
|
|
edit = 1;
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
#if defined (ARRAY_VARS)
|
|
|
|
case 'a':
|
|
|
|
arrayname = list_optarg;
|
|
|
|
break;
|
|
|
|
#endif
|
2000-03-17 21:46:59 +00:00
|
|
|
case 't':
|
|
|
|
code = legal_number (list_optarg, &timeoutval);
|
|
|
|
if (code == 0 || timeoutval < 0)
|
|
|
|
{
|
|
|
|
builtin_error ("%s: invalid timeout specification", list_optarg);
|
|
|
|
return (EXECUTION_FAILURE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tmout = timeoutval;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
code = legal_number (list_optarg, &ncharsval);
|
|
|
|
if (code == 0 || ncharsval < 0)
|
|
|
|
{
|
|
|
|
builtin_error ("%s: invalid number specification", list_optarg);
|
|
|
|
return (EXECUTION_FAILURE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
nchars = ncharsval;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
delim = *list_optarg;
|
|
|
|
break;
|
1996-12-23 17:02:34 +00:00
|
|
|
default:
|
|
|
|
builtin_usage ();
|
1996-08-26 18:22:31 +00:00
|
|
|
return (EX_USAGE);
|
|
|
|
}
|
|
|
|
}
|
1996-12-23 17:02:34 +00:00
|
|
|
list = loptend;
|
1996-08-26 18:22:31 +00:00
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
/* `read -t 0 var' returns failure immediately. */
|
|
|
|
if (tmout == 0)
|
|
|
|
return (EXECUTION_FAILURE);
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
/* IF IFS is unset, we use the default of " \t\n". */
|
1996-08-26 18:22:31 +00:00
|
|
|
var = find_variable ("IFS");
|
|
|
|
ifs_chars = var ? value_cell (var) : " \t\n";
|
1996-12-23 17:02:34 +00:00
|
|
|
if (ifs_chars == 0) /* XXX */
|
|
|
|
ifs_chars = ""; /* XXX */
|
1996-08-26 18:22:31 +00:00
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
input_string = xmalloc (size = 128);
|
1996-08-26 18:22:31 +00:00
|
|
|
|
|
|
|
begin_unwind_frame ("read_builtin");
|
1996-12-23 17:02:34 +00:00
|
|
|
#if defined (READLINE)
|
|
|
|
add_unwind_protect (xfree, rlbuf);
|
|
|
|
#endif
|
1996-08-26 18:22:31 +00:00
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
input_is_tty = isatty (0);
|
|
|
|
if (input_is_tty == 0)
|
2001-04-06 19:14:31 +00:00
|
|
|
#ifndef __CYGWIN__
|
2000-03-17 21:46:59 +00:00
|
|
|
input_is_pipe = (lseek (0, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
|
|
|
|
#else
|
|
|
|
input_is_pipe = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* If the -p, -e or -s flags were given, but input is not coming from the
|
1996-12-23 17:02:34 +00:00
|
|
|
terminal, turn them off. */
|
2000-03-17 21:46:59 +00:00
|
|
|
if ((prompt || edit || silent) && input_is_tty == 0)
|
1996-12-23 17:02:34 +00:00
|
|
|
{
|
|
|
|
prompt = (char *)NULL;
|
2000-03-17 21:46:59 +00:00
|
|
|
edit = silent = 0;
|
1996-12-23 17:02:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (prompt && edit == 0)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "%s", prompt);
|
|
|
|
fflush (stderr);
|
|
|
|
}
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
pass_next = 0; /* Non-zero signifies last char was backslash. */
|
|
|
|
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
if (tmout > 0)
|
|
|
|
{
|
|
|
|
/* Turn off the timeout if stdin is a regular file (e.g. from
|
|
|
|
input redirection). */
|
|
|
|
if ((fstat (0, &tsb) < 0) || S_ISREG (tsb.st_mode))
|
2001-04-06 19:14:31 +00:00
|
|
|
tmout = -1;
|
2000-03-17 21:46:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tmout > 0)
|
|
|
|
{
|
|
|
|
code = setjmp (alrmbuf);
|
|
|
|
if (code)
|
|
|
|
{
|
|
|
|
run_unwind_frame ("read_builtin");
|
|
|
|
return (EXECUTION_FAILURE);
|
|
|
|
}
|
|
|
|
old_alrm = set_signal_handler (SIGALRM, sigalrm);
|
|
|
|
add_unwind_protect (reset_alarm, (char *)NULL);
|
|
|
|
alarm (tmout);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we've been asked to read only NCHARS chars, or we're using some
|
|
|
|
character other than newline to terminate the line, do the right
|
|
|
|
thing to readline or the tty. */
|
|
|
|
if (nchars > 0 || delim != '\n')
|
|
|
|
{
|
|
|
|
#if defined (READLINE)
|
|
|
|
if (edit)
|
|
|
|
{
|
|
|
|
if (nchars > 0)
|
|
|
|
{
|
|
|
|
unwind_protect_int (rl_num_chars_to_read);
|
|
|
|
rl_num_chars_to_read = nchars;
|
|
|
|
}
|
|
|
|
if (delim != '\n')
|
|
|
|
{
|
|
|
|
set_eol_delim (delim);
|
|
|
|
add_unwind_protect (reset_eol_delim, (char *)NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (input_is_tty)
|
2001-04-06 19:14:31 +00:00
|
|
|
{
|
2000-03-17 21:46:59 +00:00
|
|
|
ttsave ();
|
|
|
|
if (silent)
|
|
|
|
ttcbreak ();
|
|
|
|
else
|
|
|
|
ttonechar ();
|
|
|
|
add_unwind_protect ((Function *)ttrestore, (char *)NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (silent) /* turn off echo but leave term in canonical mode */
|
|
|
|
{
|
|
|
|
ttsave ();
|
|
|
|
ttnoecho ();
|
|
|
|
add_unwind_protect ((Function *)ttrestore, (char *)NULL);
|
|
|
|
}
|
|
|
|
|
2001-04-06 19:14:31 +00:00
|
|
|
/* 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++;
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
|
|
|
|
|
2001-04-06 19:14:31 +00:00
|
|
|
#if defined (__CYGWIN__) && defined (O_TEXT)
|
|
|
|
setmode (0, O_TEXT);
|
|
|
|
#endif
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
for (eof = 0;;)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
#if defined (READLINE)
|
|
|
|
if (edit)
|
|
|
|
{
|
|
|
|
if (rlbuf && rlbuf[rlind] == '\0')
|
|
|
|
{
|
1997-06-05 14:59:13 +00:00
|
|
|
xfree (rlbuf);
|
1996-12-23 17:02:34 +00:00
|
|
|
rlbuf = (char *)0;
|
|
|
|
}
|
|
|
|
if (rlbuf == 0)
|
|
|
|
{
|
|
|
|
rlbuf = edit_line (prompt ? prompt : "");
|
|
|
|
rlind = 0;
|
|
|
|
}
|
|
|
|
if (rlbuf == 0)
|
|
|
|
{
|
|
|
|
eof = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
c = rlbuf[rlind++];
|
|
|
|
}
|
|
|
|
else
|
1999-02-19 17:11:39 +00:00
|
|
|
{
|
1997-09-22 20:22:27 +00:00
|
|
|
#endif
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
if (unbuffered_read)
|
|
|
|
retval = zread (0, &c, 1);
|
|
|
|
else
|
|
|
|
retval = zreadc (0, &c);
|
|
|
|
|
1997-09-22 20:22:27 +00:00
|
|
|
if (retval <= 0)
|
1996-12-23 17:02:34 +00:00
|
|
|
{
|
|
|
|
eof = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-02-19 17:11:39 +00:00
|
|
|
#if defined (READLINE)
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
if (i + 2 >= size)
|
2001-04-06 19:14:31 +00:00
|
|
|
{
|
|
|
|
input_string = xrealloc (input_string, size += 128);
|
|
|
|
remove_unwind_protect ();
|
|
|
|
add_unwind_protect (xfree, input_string);
|
|
|
|
}
|
1996-08-26 18:22:31 +00:00
|
|
|
|
|
|
|
/* If the next character is to be accepted verbatim, a backslash
|
|
|
|
newline pair still disappears from the input. */
|
|
|
|
if (pass_next)
|
|
|
|
{
|
|
|
|
if (c == '\n')
|
|
|
|
i--; /* back up over the CTLESC */
|
|
|
|
else
|
|
|
|
input_string[i++] = c;
|
|
|
|
pass_next = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
if (c == '\\' && raw == 0)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
|
|
|
pass_next++;
|
|
|
|
saw_escape++;
|
|
|
|
input_string[i++] = CTLESC;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
if (c == delim)
|
1996-08-26 18:22:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
if (c == CTLESC || c == CTLNUL)
|
|
|
|
{
|
|
|
|
saw_escape++;
|
|
|
|
input_string[i++] = CTLESC;
|
|
|
|
}
|
|
|
|
|
|
|
|
input_string[i++] = c;
|
2000-03-17 21:46:59 +00:00
|
|
|
|
|
|
|
if (nchars > 0 && i >= nchars)
|
|
|
|
break;
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
|
|
|
input_string[i] = '\0';
|
|
|
|
|
2000-03-17 21:46:59 +00:00
|
|
|
if (tmout > 0)
|
|
|
|
reset_alarm ();
|
|
|
|
|
|
|
|
if (nchars > 0 || delim != '\n')
|
|
|
|
{
|
|
|
|
#if defined (READLINE)
|
|
|
|
if (edit)
|
|
|
|
{
|
|
|
|
if (nchars > 0)
|
|
|
|
rl_num_chars_to_read = 0;
|
|
|
|
if (delim != '\n')
|
|
|
|
reset_eol_delim ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (input_is_tty)
|
|
|
|
ttrestore ();
|
|
|
|
}
|
|
|
|
else if (silent)
|
|
|
|
ttrestore ();
|
|
|
|
|
|
|
|
if (unbuffered_read == 0)
|
|
|
|
zsyncfd (0);
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
interrupt_immediately--;
|
|
|
|
discard_unwind_frame ("read_builtin");
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
|
1996-08-26 18:22:31 +00:00
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
#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. */
|
|
|
|
if (arrayname)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
var = find_variable (arrayname);
|
|
|
|
if (var == 0)
|
2001-04-06 19:14:31 +00:00
|
|
|
var = make_new_array_variable (arrayname);
|
1996-12-23 17:02:34 +00:00
|
|
|
else if (array_p (var) == 0)
|
2001-04-06 19:14:31 +00:00
|
|
|
var = convert_var_to_array (var);
|
1996-12-23 17:02:34 +00:00
|
|
|
|
|
|
|
empty_array (array_cell (var));
|
|
|
|
|
|
|
|
alist = list_string (input_string, ifs_chars, 0);
|
|
|
|
if (alist)
|
|
|
|
{
|
|
|
|
assign_array_var_from_word_list (var, alist);
|
|
|
|
dispose_words (alist);
|
|
|
|
}
|
1997-06-05 14:59:13 +00:00
|
|
|
xfree (input_string);
|
1996-12-23 17:02:34 +00:00
|
|
|
return (retval);
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
1996-12-23 17:02:34 +00:00
|
|
|
#endif /* ARRAY_VARS */
|
1996-08-26 18:22:31 +00:00
|
|
|
|
1997-06-05 14:59:13 +00:00
|
|
|
/* If there are no variables, save the text of the line read to the
|
|
|
|
variable $REPLY. ksh93 strips leading and trailing IFS whitespace,
|
|
|
|
so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
|
|
|
|
same way, but I believe that the difference in behaviors is useful
|
|
|
|
enough to not do it. Without the bash behavior, there is no way
|
2001-04-06 19:14:31 +00:00
|
|
|
to read a line completely without interpretation or modification
|
|
|
|
unless you mess with $IFS (e.g., setting it to the empty string).
|
1997-06-05 14:59:13 +00:00
|
|
|
If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
|
|
|
|
if (list == 0)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1997-06-05 14:59:13 +00:00
|
|
|
#if 0
|
|
|
|
orig_input_string = input_string;
|
|
|
|
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
|
|
|
|
;
|
|
|
|
input_string = t;
|
|
|
|
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
|
|
|
|
#endif
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
if (saw_escape)
|
|
|
|
{
|
|
|
|
t = dequote_string (input_string);
|
|
|
|
var = bind_variable ("REPLY", t);
|
|
|
|
free (t);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
var = bind_variable ("REPLY", input_string);
|
2000-03-17 21:46:59 +00:00
|
|
|
VUNSETATTR (var, att_invisible);
|
2001-04-06 19:14:31 +00:00
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
free (input_string);
|
1996-12-23 17:02:34 +00:00
|
|
|
return (retval);
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
1996-12-23 17:02:34 +00:00
|
|
|
|
|
|
|
/* This code implements the Posix.2 spec for splitting the words
|
|
|
|
read and assigning them to variables. */
|
|
|
|
orig_input_string = input_string;
|
|
|
|
|
|
|
|
/* Remove IFS white space at the beginning of the input string. If
|
|
|
|
$IFS is null, no field splitting is performed. */
|
|
|
|
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
|
|
|
|
;
|
|
|
|
input_string = t;
|
|
|
|
|
|
|
|
for (; list->next; list = list->next)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
varname = list->word->word;
|
|
|
|
#if defined (ARRAY_VARS)
|
|
|
|
if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
|
|
|
|
#else
|
|
|
|
if (legal_identifier (varname) == 0)
|
|
|
|
#endif
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
builtin_error ("`%s': not a valid identifier", varname);
|
|
|
|
free (orig_input_string);
|
|
|
|
return (EXECUTION_FAILURE);
|
|
|
|
}
|
1996-08-26 18:22:31 +00:00
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
/* If there are more variables than words read from the input,
|
|
|
|
the remaining variables are set to the empty string. */
|
|
|
|
if (*input_string)
|
|
|
|
{
|
|
|
|
/* This call updates INPUT_STRING. */
|
|
|
|
t = get_word_from_string (&input_string, ifs_chars, &e);
|
|
|
|
if (t)
|
|
|
|
*e = '\0';
|
|
|
|
/* Don't bother to remove the CTLESC unless we added one
|
|
|
|
somewhere while reading the string. */
|
|
|
|
if (t && saw_escape)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
t1 = dequote_string (t);
|
|
|
|
var = bind_read_variable (varname, t1);
|
|
|
|
free (t1);
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
|
|
|
else
|
1996-12-23 17:02:34 +00:00
|
|
|
var = bind_read_variable (varname, t);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t = (char *)0;
|
|
|
|
var = bind_read_variable (varname, "");
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
FREE (t);
|
|
|
|
if (var == 0)
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
|
|
|
free (orig_input_string);
|
|
|
|
return (EXECUTION_FAILURE);
|
|
|
|
}
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
stupidly_hack_special_variables (varname);
|
2000-03-17 21:46:59 +00:00
|
|
|
VUNSETATTR (var, att_invisible);
|
1996-12-23 17:02:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now assign the rest of the line to the last variable argument. */
|
|
|
|
#if defined (ARRAY_VARS)
|
|
|
|
if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
|
|
|
|
#else
|
|
|
|
if (legal_identifier (list->word->word) == 0)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
builtin_error ("`%s': not a valid identifier", list->word->word);
|
1996-08-26 18:22:31 +00:00
|
|
|
free (orig_input_string);
|
1996-12-23 17:02:34 +00:00
|
|
|
return (EXECUTION_FAILURE);
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
/* This has to be done this way rather than using string_list
|
|
|
|
and list_string because Posix.2 says that the last variable gets the
|
|
|
|
remaining words and their intervening separators. */
|
|
|
|
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
|
|
|
|
|
|
|
|
if (saw_escape)
|
|
|
|
{
|
|
|
|
t = dequote_string (input_string);
|
|
|
|
var = bind_read_variable (list->word->word, t);
|
|
|
|
free (t);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
var = bind_read_variable (list->word->word, input_string);
|
|
|
|
stupidly_hack_special_variables (list->word->word);
|
|
|
|
if (var)
|
2000-03-17 21:46:59 +00:00
|
|
|
VUNSETATTR (var, att_invisible);
|
1996-12-23 17:02:34 +00:00
|
|
|
free (orig_input_string);
|
|
|
|
|
1996-08-26 18:22:31 +00:00
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
1996-12-23 17:02:34 +00:00
|
|
|
static SHELL_VAR *
|
|
|
|
bind_read_variable (name, value)
|
|
|
|
char *name, *value;
|
|
|
|
{
|
|
|
|
#if defined (ARRAY_VARS)
|
|
|
|
if (valid_array_reference (name) == 0)
|
|
|
|
{
|
1998-04-17 19:52:44 +00:00
|
|
|
#if 0
|
1996-12-23 17:02:34 +00:00
|
|
|
if (legal_identifier (name) == 0)
|
2001-04-06 19:14:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
builtin_error ("`%s': not a valid identifier", name);
|
|
|
|
return ((SHELL_VAR *)NULL);
|
2001-04-06 19:14:31 +00:00
|
|
|
}
|
1998-04-17 19:52:44 +00:00
|
|
|
#endif
|
1996-12-23 17:02:34 +00:00
|
|
|
return (bind_variable (name, value));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return (do_array_element_assignment (name, value));
|
|
|
|
#else
|
|
|
|
return bind_variable (name, value);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined (READLINE)
|
|
|
|
static char *
|
|
|
|
edit_line (p)
|
|
|
|
char *p;
|
1996-08-26 18:22:31 +00:00
|
|
|
{
|
1996-12-23 17:02:34 +00:00
|
|
|
char *ret;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!bash_readline_initialized)
|
|
|
|
initialize_readline ();
|
|
|
|
ret = readline (p);
|
|
|
|
if (ret == 0)
|
|
|
|
return ret;
|
|
|
|
len = strlen (ret);
|
|
|
|
ret = xrealloc (ret, len + 2);
|
2000-03-17 21:46:59 +00:00
|
|
|
ret[len++] = delim;
|
1996-12-23 17:02:34 +00:00
|
|
|
ret[len] = '\0';
|
|
|
|
return ret;
|
1996-08-26 18:22:31 +00:00
|
|
|
}
|
2000-03-17 21:46:59 +00:00
|
|
|
|
|
|
|
static int old_delim_ctype;
|
|
|
|
static Function *old_delim_func;
|
|
|
|
static int old_newline_ctype;
|
|
|
|
static Function *old_newline_func;
|
|
|
|
|
|
|
|
static int delim_char;
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_eol_delim (c)
|
|
|
|
int c;
|
|
|
|
{
|
|
|
|
Keymap cmap;
|
|
|
|
|
|
|
|
if (bash_readline_initialized == 0)
|
|
|
|
initialize_readline ();
|
|
|
|
cmap = rl_get_keymap ();
|
|
|
|
|
|
|
|
/* Change newline to self-insert */
|
|
|
|
old_newline_ctype = cmap[RETURN].type;
|
|
|
|
old_newline_func = cmap[RETURN].function;
|
|
|
|
cmap[RETURN].type = ISFUNC;
|
|
|
|
cmap[RETURN].function = rl_insert;
|
|
|
|
|
|
|
|
/* Bind the delimiter character to accept-line. */
|
|
|
|
old_delim_ctype = cmap[c].type;
|
|
|
|
old_delim_func = cmap[c].function;
|
|
|
|
cmap[c].type = ISFUNC;
|
|
|
|
cmap[c].function = rl_newline;
|
|
|
|
|
|
|
|
delim_char = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reset_eol_delim (c)
|
|
|
|
int c;
|
|
|
|
{
|
|
|
|
Keymap cmap;
|
|
|
|
|
|
|
|
cmap = rl_get_keymap ();
|
|
|
|
|
|
|
|
cmap[RETURN].type = old_newline_ctype;
|
|
|
|
cmap[RETURN].function = old_newline_func;
|
|
|
|
|
|
|
|
cmap[delim_char].type = old_delim_ctype;
|
|
|
|
cmap[delim_char].function = old_delim_func;
|
|
|
|
}
|
1996-12-23 17:02:34 +00:00
|
|
|
#endif
|