198 lines
5.0 KiB
Modula-2
198 lines
5.0 KiB
Modula-2
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
|
|
Software Foundation; either version 1, 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; see the file COPYING. If not, write to the Free Software
|
|
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
$PRODUCES read.c
|
|
|
|
$BUILTIN read
|
|
$FUNCTION read_builtin
|
|
$SHORT_DOC read [-r] [name ...]
|
|
One line is read from the standard input, and the first word is
|
|
assigned to the first NAME, the second word to the second NAME, etc.
|
|
with leftover words assigned to the last NAME. Only the characters
|
|
found in $IFS are recognized as word delimiters. The return code is
|
|
zero, unless end-of-file is encountered. If the -r option is given, a
|
|
backslash-newline pair (\\n) is not ignored, and the backslash is
|
|
considered to be part of the line.
|
|
$END
|
|
|
|
#include <stdio.h>
|
|
#include "../shell.h"
|
|
|
|
static int stream_close ();
|
|
|
|
/* 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
|
|
are mentioned in LIST, then the default variable is $REPLY.
|
|
|
|
S. R. Bourne's shell complains if you don't name a variable
|
|
to receive the stuff that is read. GNU's shell doesn't. This
|
|
allows you to let the user type random things. */
|
|
read_builtin (list)
|
|
WORD_LIST *list;
|
|
{
|
|
extern int interrupt_immediately, free ();
|
|
extern SHELL_VAR *bind_variable ();
|
|
register char *varname;
|
|
int size, c, i = 0, fildes, ignore_backslash_nl = 1;
|
|
char *input_string, *ifs_chars;
|
|
WORD_LIST *words, *rwords, *list_string ();
|
|
extern char *string_list_dollar_star ();
|
|
FILE *input_stream;
|
|
|
|
ifs_chars = get_string_value ("IFS");
|
|
input_string = (char *)xmalloc (size = 128);
|
|
|
|
/* We need unbuffered input from stdin. So we make a new
|
|
unbuffered stream with the same file descriptor, then
|
|
unbuffer that one. */
|
|
fildes = dup (fileno (stdin));
|
|
|
|
if (fildes == -1)
|
|
return (EXECUTION_FAILURE);
|
|
|
|
input_stream = fdopen (fildes, "r");
|
|
|
|
if (!input_stream)
|
|
{
|
|
close (fildes);
|
|
return (EXECUTION_FAILURE);
|
|
}
|
|
|
|
setbuf (input_stream, (char *)NULL);
|
|
|
|
{
|
|
begin_unwind_frame ("read_builtin");
|
|
add_unwind_protect (free, input_string);
|
|
add_unwind_protect (stream_close, input_stream);
|
|
interrupt_immediately++;
|
|
}
|
|
|
|
while (list)
|
|
{
|
|
if (strcmp (list->word->word, "-r") == 0)
|
|
{
|
|
ignore_backslash_nl = 0;
|
|
list = list->next;
|
|
}
|
|
else if (strcmp (list->word->word, "--") == 0)
|
|
{
|
|
list = list->next;
|
|
break;
|
|
}
|
|
else if (*list->word->word == '-')
|
|
{
|
|
bad_option (list->word->word);
|
|
return (EXECUTION_FAILURE);
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
while ((c = getc (input_stream)) != EOF)
|
|
{
|
|
if (i + 1 >= size)
|
|
input_string = (char *)xrealloc (input_string, size += 128);
|
|
|
|
input_string[i++] = c;
|
|
|
|
if (c == '\n')
|
|
{
|
|
if (ignore_backslash_nl &&
|
|
(i >= 2) && (input_string[i - 2] == '\\'))
|
|
{
|
|
i -= 2;
|
|
continue;
|
|
}
|
|
/* Both ksh and the s5r3 sh chop off the trailing newline. */
|
|
i--;
|
|
break;
|
|
}
|
|
}
|
|
input_string[i] = '\0';
|
|
|
|
interrupt_immediately--;
|
|
discard_unwind_frame ("read_builtin");
|
|
|
|
fclose (input_stream);
|
|
|
|
if (c == EOF)
|
|
return (EXECUTION_FAILURE);
|
|
|
|
if (!list)
|
|
{
|
|
SHELL_VAR *var;
|
|
|
|
var = bind_variable ("REPLY", input_string);
|
|
var->attributes &= ~att_invisible;
|
|
free (input_string);
|
|
}
|
|
else
|
|
{
|
|
words = list_string (input_string, ifs_chars, 0);
|
|
rwords = words;
|
|
|
|
free (input_string);
|
|
|
|
while (list)
|
|
{
|
|
SHELL_VAR *var;
|
|
|
|
varname = list->word->word;
|
|
|
|
if (!list->next)
|
|
{
|
|
/* Call string_list_dollar_star because P1003.2.9 specifies
|
|
that the intervening separators are preserved in the
|
|
result of a read that specifies fewer variables than words
|
|
read. */
|
|
char *t = words ? string_list_dollar_star (words) : "";
|
|
var = bind_variable (varname, t);
|
|
}
|
|
else
|
|
var = bind_variable (varname, words ? words->word->word : "");
|
|
|
|
stupidly_hack_special_variables (varname);
|
|
var->attributes &= ~att_invisible;
|
|
|
|
list = list->next;
|
|
if (words)
|
|
words = words->next;
|
|
}
|
|
if (rwords)
|
|
dispose_words (rwords);
|
|
}
|
|
|
|
return (EXECUTION_SUCCESS);
|
|
}
|
|
|
|
/* This way I don't have to know whether fclose () is a
|
|
function or a macro. */
|
|
static int
|
|
stream_close (file)
|
|
FILE *file;
|
|
{
|
|
return (fclose (file));
|
|
}
|
|
|