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