Imported from ../bash-2.03.tar.gz.
[platform/upstream/bash.git] / builtins / read.def
1 This file is read.def, from which is created read.c.
2 It implements the builtin "read" in Bash.
3
4 Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING.  If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 $PRODUCES read.c
23
24 $BUILTIN read
25 $FUNCTION read_builtin
26 $SHORT_DOC read [-r] [-p prompt] [-a array] [-e] [name ...]
27 One line is read from the standard input, and the first word is
28 assigned to the first NAME, the second word to the second NAME, and so
29 on, with leftover words assigned to the last NAME.  Only the characters
30 found in $IFS are recognized as word delimiters.  The return code is
31 zero, unless end-of-file is encountered.  If no NAMEs are supplied, the
32 line read is stored in the REPLY variable.  If the -r option is given,
33 this signifies `raw' input, and backslash escaping is disabled.  If
34 the `-p' option is supplied, the string supplied as an argument is
35 output without a trailing newline before attempting to read.  If -a is
36 supplied, the words read are assigned to sequential indices of ARRAY,
37 starting at zero.  If -e is supplied and the shell is interactive,
38 readline is used to obtain the line.
39 $END
40
41 #include <config.h>
42
43 #include <stdio.h>
44
45 #if defined (HAVE_UNISTD_H)
46 #  ifdef _MINIX
47 #    include <sys/types.h>
48 #  endif
49 #  include <unistd.h>
50 #endif
51
52 #include <errno.h>
53
54 #include "../shell.h"
55 #include "common.h"
56 #include "bashgetopt.h"
57
58 #if defined (READLINE)
59 #include "../bashline.h"
60 #include <readline/readline.h>
61 #endif
62
63 #if !defined(errno)
64 extern int errno;
65 #endif
66
67 #define issep(c)        (strchr (ifs_chars, (c)))
68
69 extern int interrupt_immediately;
70
71 #if defined (READLINE)
72 static char *edit_line ();
73 #endif
74 static SHELL_VAR *bind_read_variable ();
75
76 /* Read the value of the shell variables whose names follow.
77    The reading is done from the current input stream, whatever
78    that may be.  Successive words of the input line are assigned
79    to the variables mentioned in LIST.  The last variable in LIST
80    gets the remainder of the words on the line.  If no variables
81    are mentioned in LIST, then the default variable is $REPLY. */
82 int
83 read_builtin (list)
84      WORD_LIST *list;
85 {
86   register char *varname;
87   int size, i, raw, pass_next, saw_escape, eof, opt, retval, edit;
88   char c;
89   char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
90   char *e, *t, *t1;
91   SHELL_VAR *var;
92 #if defined (ARRAY_VARS)
93   WORD_LIST *alist;
94 #endif
95 #if defined (READLINE)
96   char *rlbuf;
97   int rlind;
98 #endif
99
100   i = 0;                /* Index into the string that we are reading. */
101   raw = edit = 0;       /* Not reading raw input by default. */
102   arrayname = prompt = (char *)NULL;
103
104 #if defined (READLINE)
105   rlbuf = (char *)0;
106   rlind = 0;
107 #endif
108
109   reset_internal_getopt ();
110   while ((opt = internal_getopt (list, "erp:a:")) != -1)
111     {
112       switch (opt)
113         {
114         case 'r':
115           raw = 1;
116           break;
117         case 'p':
118           prompt = list_optarg;
119           break;
120         case 'e':
121 #if defined (READLINE)
122           edit = 1;
123 #endif
124           break;
125 #if defined (ARRAY_VARS)
126         case 'a':
127           arrayname = list_optarg;
128           break;
129 #endif
130         default:
131           builtin_usage ();
132           return (EX_USAGE);
133         }
134     }
135   list = loptend;
136
137   /* IF IFS is unset, we use the default of " \t\n". */
138   var = find_variable ("IFS");
139   ifs_chars = var ? value_cell (var) : " \t\n";
140   if (ifs_chars == 0)           /* XXX */
141     ifs_chars = "";             /* XXX */
142
143   input_string = xmalloc (size = 128);
144
145   begin_unwind_frame ("read_builtin");
146   add_unwind_protect (xfree, input_string);
147 #if defined (READLINE)
148   add_unwind_protect (xfree, rlbuf);
149 #endif
150   interrupt_immediately++;
151
152   /* If the -p or -e flags were given, but input is not coming from the
153      terminal, turn them off. */
154   if ((prompt || edit) && (isatty (0) == 0))
155     {
156       prompt = (char *)NULL;
157       edit = 0;
158     }
159
160   if (prompt && edit == 0)
161     {
162       fprintf (stderr, "%s", prompt);
163       fflush (stderr);
164     }
165
166   pass_next = 0;        /* Non-zero signifies last char was backslash. */
167   saw_escape = 0;       /* Non-zero signifies that we saw an escape char */
168
169   for (eof = 0;;)
170     {
171 #if defined (READLINE)
172       if (edit)
173         {
174           if (rlbuf && rlbuf[rlind] == '\0')
175             {
176               xfree (rlbuf);
177               rlbuf = (char *)0;
178             }
179           if (rlbuf == 0)
180             {
181               rlbuf = edit_line (prompt ? prompt : "");
182               rlind = 0;
183             }
184           if (rlbuf == 0)
185             {
186               eof = 1;
187               break;
188             }
189           c = rlbuf[rlind++];
190         }
191       else
192         {
193 #endif
194
195       while (((retval = read (0, &c, 1)) < 0) && errno == EINTR)
196         ;
197       if (retval <= 0)
198         {
199           eof = 1;
200           break;
201         }
202
203 #if defined (READLINE)
204         }
205 #endif
206
207       if (i + 2 >= size)
208         input_string = xrealloc (input_string, size += 128);
209
210       /* If the next character is to be accepted verbatim, a backslash
211          newline pair still disappears from the input. */
212       if (pass_next)
213         {
214           if (c == '\n')
215             i--;                /* back up over the CTLESC */
216           else
217             input_string[i++] = c;
218           pass_next = 0;
219           continue;
220         }
221
222       if (c == '\\' && raw == 0)
223         {
224           pass_next++;
225           saw_escape++;
226           input_string[i++] = CTLESC;
227           continue;
228         }
229
230       if (c == '\n')
231         break;
232
233       if (c == CTLESC || c == CTLNUL)
234         {
235           saw_escape++;
236           input_string[i++] = CTLESC;
237         }
238
239       input_string[i++] = c;
240     }
241   input_string[i] = '\0';
242
243   interrupt_immediately--;
244   discard_unwind_frame ("read_builtin");
245
246   retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
247
248 #if defined (ARRAY_VARS)
249   /* If -a was given, take the string read, break it into a list of words,
250      an assign them to `arrayname' in turn. */
251   if (arrayname)
252     {
253       var = find_variable (arrayname);
254       if (var == 0)
255         var = make_new_array_variable (arrayname);
256       else if (array_p (var) == 0)
257         var = convert_var_to_array (var);
258
259       empty_array (array_cell (var));
260
261       alist = list_string (input_string, ifs_chars, 0);
262       if (alist)
263         {
264           assign_array_var_from_word_list (var, alist);
265           dispose_words (alist);
266         }
267       xfree (input_string);
268       return (retval);
269     }
270 #endif /* ARRAY_VARS */ 
271
272   /* If there are no variables, save the text of the line read to the
273      variable $REPLY.  ksh93 strips leading and trailing IFS whitespace,
274      so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
275      same way, but I believe that the difference in behaviors is useful
276      enough to not do it.  Without the bash behavior, there is no way
277      to read a line completely without interpretation or modification.
278      If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
279   if (list == 0)
280     {
281 #if 0
282       orig_input_string = input_string;
283       for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
284         ;
285       input_string = t;
286       input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
287 #endif
288
289       if (saw_escape)
290         {
291           t = dequote_string (input_string);
292           var = bind_variable ("REPLY", t);
293           free (t);
294         }
295       else
296         var = bind_variable ("REPLY", input_string);
297       var->attributes &= ~att_invisible;
298 #if 0
299       free (orig_input_string);
300 #else
301       free (input_string);
302 #endif
303       return (retval);
304     }
305
306   /* This code implements the Posix.2 spec for splitting the words
307      read and assigning them to variables. */
308   orig_input_string = input_string;
309
310   /* Remove IFS white space at the beginning of the input string.  If
311      $IFS is null, no field splitting is performed. */
312   for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
313     ;
314   input_string = t;
315
316   for (; list->next; list = list->next)
317     {
318       varname = list->word->word;
319 #if defined (ARRAY_VARS)
320       if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
321 #else
322       if (legal_identifier (varname) == 0)
323 #endif
324         {
325           builtin_error ("`%s': not a valid identifier", varname);
326           free (orig_input_string);
327           return (EXECUTION_FAILURE);
328         }
329
330       /* If there are more variables than words read from the input,
331          the remaining variables are set to the empty string. */
332       if (*input_string)
333         {
334           /* This call updates INPUT_STRING. */
335           t = get_word_from_string (&input_string, ifs_chars, &e);
336           if (t)
337             *e = '\0';
338           /* Don't bother to remove the CTLESC unless we added one
339              somewhere while reading the string. */
340           if (t && saw_escape)
341             {
342               t1 = dequote_string (t);
343               var = bind_read_variable (varname, t1);
344               free (t1);
345             }
346           else
347             var = bind_read_variable (varname, t);
348         }
349       else
350         {
351           t = (char *)0;
352           var = bind_read_variable (varname, "");
353         }
354
355       FREE (t);
356       if (var == 0)
357         {
358           free (orig_input_string);
359           return (EXECUTION_FAILURE);
360         }
361
362       stupidly_hack_special_variables (varname);
363       var->attributes &= ~att_invisible;
364     }
365
366   /* Now assign the rest of the line to the last variable argument. */
367 #if defined (ARRAY_VARS)
368   if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
369 #else
370   if (legal_identifier (list->word->word) == 0)
371 #endif
372     {
373       builtin_error ("`%s': not a valid identifier", list->word->word);
374       free (orig_input_string);
375       return (EXECUTION_FAILURE);
376     }
377
378   /* This has to be done this way rather than using string_list
379      and list_string because Posix.2 says that the last variable gets the
380      remaining words and their intervening separators. */
381   input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
382
383   if (saw_escape)
384     {
385       t = dequote_string (input_string);
386       var = bind_read_variable (list->word->word, t);
387       free (t);
388     }
389   else
390     var = bind_read_variable (list->word->word, input_string);
391   stupidly_hack_special_variables (list->word->word);
392   if (var)
393     var->attributes &= ~att_invisible;
394   free (orig_input_string);
395
396   return (retval);
397 }
398
399 static SHELL_VAR *
400 bind_read_variable (name, value)
401      char *name, *value;
402 {
403 #if defined (ARRAY_VARS)
404   if (valid_array_reference (name) == 0)
405     {
406 #if 0
407       if (legal_identifier (name) == 0)
408         {
409           builtin_error ("`%s': not a valid identifier", name);
410           return ((SHELL_VAR *)NULL);
411         }
412 #endif
413       return (bind_variable (name, value));
414     }
415   else
416     return (do_array_element_assignment (name, value));
417 #else
418   return bind_variable (name, value);
419 #endif
420 }
421
422 #if defined (READLINE)
423 static char *
424 edit_line (p)
425      char *p;
426 {
427   char *ret;
428   int len;
429
430   if (!bash_readline_initialized)
431     initialize_readline ();
432   ret = readline (p);
433   if (ret == 0)
434     return ret;
435   len = strlen (ret);
436   ret = xrealloc (ret, len + 2);
437   ret[len++] = '\n';
438   ret[len] = '\0';
439   return ret;
440 }
441 #endif