]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/read.def
Imported from ../bash-2.01.1.tar.gz.
[thirdparty/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 # include <unistd.h>
47 #endif
48
49 #include <errno.h>
50
51 #include "../shell.h"
52 #include "common.h"
53 #include "bashgetopt.h"
54
55 #if defined (READLINE)
56 #include "../bashline.h"
57 #include <readline/readline.h>
58 #endif
59
60 #if !defined(errno)
61 extern int errno;
62 #endif
63
64 #define issep(c) (strchr (ifs_chars, (c)))
65
66 extern int interrupt_immediately;
67
68 #if defined (READLINE)
69 static char *edit_line ();
70 #endif
71 static SHELL_VAR *bind_read_variable ();
72
73 /* Read the value of the shell variables whose names follow.
74 The reading is done from the current input stream, whatever
75 that may be. Successive words of the input line are assigned
76 to the variables mentioned in LIST. The last variable in LIST
77 gets the remainder of the words on the line. If no variables
78 are mentioned in LIST, then the default variable is $REPLY. */
79 int
80 read_builtin (list)
81 WORD_LIST *list;
82 {
83 register char *varname;
84 int size, i, raw, pass_next, saw_escape, eof, opt, retval, edit;
85 char c;
86 char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
87 char *e, *t, *t1;
88 SHELL_VAR *var;
89 #if defined (ARRAY_VARS)
90 WORD_LIST *alist;
91 #endif
92 #if defined (READLINE)
93 char *rlbuf;
94 int rlind;
95 #endif
96
97 i = 0; /* Index into the string that we are reading. */
98 raw = edit = 0; /* Not reading raw input by default. */
99 arrayname = prompt = (char *)NULL;
100
101 #if defined (READLINE)
102 rlbuf = (char *)0;
103 rlind = 0;
104 #endif
105
106 reset_internal_getopt ();
107 while ((opt = internal_getopt (list, "erp:a:")) != -1)
108 {
109 switch (opt)
110 {
111 case 'r':
112 raw = 1;
113 break;
114 case 'p':
115 prompt = list_optarg;
116 break;
117 case 'e':
118 #if defined (READLINE)
119 edit = 1;
120 #endif
121 break;
122 #if defined (ARRAY_VARS)
123 case 'a':
124 arrayname = list_optarg;
125 break;
126 #endif
127 default:
128 builtin_usage ();
129 return (EX_USAGE);
130 }
131 }
132 list = loptend;
133
134 /* IF IFS is unset, we use the default of " \t\n". */
135 var = find_variable ("IFS");
136 ifs_chars = var ? value_cell (var) : " \t\n";
137 if (ifs_chars == 0) /* XXX */
138 ifs_chars = ""; /* XXX */
139
140 input_string = xmalloc (size = 128);
141
142 begin_unwind_frame ("read_builtin");
143 add_unwind_protect (xfree, input_string);
144 #if defined (READLINE)
145 add_unwind_protect (xfree, rlbuf);
146 #endif
147 interrupt_immediately++;
148
149 /* If the -p or -e flags were given, but input is not coming from the
150 terminal, turn them off. */
151 if ((prompt || edit) && (isatty (0) == 0))
152 {
153 prompt = (char *)NULL;
154 edit = 0;
155 }
156
157 if (prompt && edit == 0)
158 {
159 fprintf (stderr, "%s", prompt);
160 fflush (stderr);
161 }
162
163 pass_next = 0; /* Non-zero signifies last char was backslash. */
164 saw_escape = 0; /* Non-zero signifies that we saw an escape char */
165
166 for (eof = 0;;)
167 {
168 #if defined (READLINE)
169 if (edit)
170 {
171 if (rlbuf && rlbuf[rlind] == '\0')
172 {
173 xfree (rlbuf);
174 rlbuf = (char *)0;
175 }
176 if (rlbuf == 0)
177 {
178 rlbuf = edit_line (prompt ? prompt : "");
179 rlind = 0;
180 }
181 if (rlbuf == 0)
182 {
183 eof = 1;
184 break;
185 }
186 c = rlbuf[rlind++];
187 }
188 else
189 #endif
190
191 while (((retval = read (0, &c, 1)) < 0) && errno == EINTR)
192 ;
193 if (retval <= 0)
194 {
195 eof = 1;
196 break;
197 }
198
199 if (i + 2 >= size)
200 input_string = xrealloc (input_string, size += 128);
201
202 /* If the next character is to be accepted verbatim, a backslash
203 newline pair still disappears from the input. */
204 if (pass_next)
205 {
206 if (c == '\n')
207 i--; /* back up over the CTLESC */
208 else
209 input_string[i++] = c;
210 pass_next = 0;
211 continue;
212 }
213
214 if (c == '\\' && raw == 0)
215 {
216 pass_next++;
217 saw_escape++;
218 input_string[i++] = CTLESC;
219 continue;
220 }
221
222 if (c == '\n')
223 break;
224
225 if (c == CTLESC || c == CTLNUL)
226 {
227 saw_escape++;
228 input_string[i++] = CTLESC;
229 }
230
231 input_string[i++] = c;
232 }
233 input_string[i] = '\0';
234
235 interrupt_immediately--;
236 discard_unwind_frame ("read_builtin");
237
238 retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
239
240 #if defined (ARRAY_VARS)
241 /* If -a was given, take the string read, break it into a list of words,
242 an assign them to `arrayname' in turn. */
243 if (arrayname)
244 {
245 var = find_variable (arrayname);
246 if (var == 0)
247 var = make_new_array_variable (arrayname);
248 else if (array_p (var) == 0)
249 var = convert_var_to_array (var);
250
251 empty_array (array_cell (var));
252
253 alist = list_string (input_string, ifs_chars, 0);
254 if (alist)
255 {
256 assign_array_var_from_word_list (var, alist);
257 dispose_words (alist);
258 }
259 xfree (input_string);
260 return (retval);
261 }
262 #endif /* ARRAY_VARS */
263
264 /* If there are no variables, save the text of the line read to the
265 variable $REPLY. ksh93 strips leading and trailing IFS whitespace,
266 so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
267 same way, but I believe that the difference in behaviors is useful
268 enough to not do it. Without the bash behavior, there is no way
269 to read a line completely without interpretation or modification.
270 If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
271 if (list == 0)
272 {
273 #if 0
274 orig_input_string = input_string;
275 for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
276 ;
277 input_string = t;
278 input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
279 #endif
280
281 if (saw_escape)
282 {
283 t = dequote_string (input_string);
284 var = bind_variable ("REPLY", t);
285 free (t);
286 }
287 else
288 var = bind_variable ("REPLY", input_string);
289 var->attributes &= ~att_invisible;
290 #if 0
291 free (orig_input_string);
292 #else
293 free (input_string);
294 #endif
295 return (retval);
296 }
297
298 /* This code implements the Posix.2 spec for splitting the words
299 read and assigning them to variables. */
300 orig_input_string = input_string;
301
302 /* Remove IFS white space at the beginning of the input string. If
303 $IFS is null, no field splitting is performed. */
304 for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && issep(*t); t++)
305 ;
306 input_string = t;
307
308 for (; list->next; list = list->next)
309 {
310 varname = list->word->word;
311 #if defined (ARRAY_VARS)
312 if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
313 #else
314 if (legal_identifier (varname) == 0)
315 #endif
316 {
317 builtin_error ("`%s': not a valid identifier", varname);
318 free (orig_input_string);
319 return (EXECUTION_FAILURE);
320 }
321
322 /* If there are more variables than words read from the input,
323 the remaining variables are set to the empty string. */
324 if (*input_string)
325 {
326 /* This call updates INPUT_STRING. */
327 t = get_word_from_string (&input_string, ifs_chars, &e);
328 if (t)
329 *e = '\0';
330 /* Don't bother to remove the CTLESC unless we added one
331 somewhere while reading the string. */
332 if (t && saw_escape)
333 {
334 t1 = dequote_string (t);
335 var = bind_read_variable (varname, t1);
336 free (t1);
337 }
338 else
339 var = bind_read_variable (varname, t);
340 }
341 else
342 {
343 t = (char *)0;
344 var = bind_read_variable (varname, "");
345 }
346
347 FREE (t);
348 if (var == 0)
349 {
350 free (orig_input_string);
351 return (EXECUTION_FAILURE);
352 }
353
354 stupidly_hack_special_variables (varname);
355 var->attributes &= ~att_invisible;
356 }
357
358 /* Now assign the rest of the line to the last variable argument. */
359 #if defined (ARRAY_VARS)
360 if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
361 #else
362 if (legal_identifier (list->word->word) == 0)
363 #endif
364 {
365 builtin_error ("`%s': not a valid identifier", list->word->word);
366 free (orig_input_string);
367 return (EXECUTION_FAILURE);
368 }
369
370 /* This has to be done this way rather than using string_list
371 and list_string because Posix.2 says that the last variable gets the
372 remaining words and their intervening separators. */
373 input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
374
375 if (saw_escape)
376 {
377 t = dequote_string (input_string);
378 var = bind_read_variable (list->word->word, t);
379 free (t);
380 }
381 else
382 var = bind_read_variable (list->word->word, input_string);
383 stupidly_hack_special_variables (list->word->word);
384 if (var)
385 var->attributes &= ~att_invisible;
386 free (orig_input_string);
387
388 return (retval);
389 }
390
391 static SHELL_VAR *
392 bind_read_variable (name, value)
393 char *name, *value;
394 {
395 #if defined (ARRAY_VARS)
396 if (valid_array_reference (name) == 0)
397 {
398 if (legal_identifier (name) == 0)
399 {
400 builtin_error ("`%s': not a valid identifier", name);
401 return ((SHELL_VAR *)NULL);
402 }
403 return (bind_variable (name, value));
404 }
405 else
406 return (do_array_element_assignment (name, value));
407 #else
408 return bind_variable (name, value);
409 #endif
410 }
411
412 #if defined (READLINE)
413 static char *
414 edit_line (p)
415 char *p;
416 {
417 char *ret;
418 int len;
419
420 if (!bash_readline_initialized)
421 initialize_readline ();
422 ret = readline (p);
423 if (ret == 0)
424 return ret;
425 len = strlen (ret);
426 ret = xrealloc (ret, len + 2);
427 ret[len++] = '\n';
428 ret[len] = '\0';
429 return ret;
430 }
431 #endif