1This file is read.def, from which is created read.c.
2It implements the builtin "read" in Bash.
3
4Copyright (C) 1987-2009 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with Bash.  If not, see <http://www.gnu.org/licenses/>.
20
21$PRODUCES read.c
22
23$BUILTIN read
24$FUNCTION read_builtin
25$SHORT_DOC read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
26Read a line from the standard input and split it into fields.
27
28Reads a single line from the standard input, or from file descriptor FD
29if the -u option is supplied.  The line is split into fields as with word
30splitting, and the first word is assigned to the first NAME, the second
31word to the second NAME, and so on, with any leftover words assigned to
32the last NAME.  Only the characters found in $IFS are recognized as word
33delimiters.
34
35If no NAMEs are supplied, the line read is stored in the REPLY variable.
36
37Options:
38  -a array	assign the words read to sequential indices of the array
39		variable ARRAY, starting at zero
40  -d delim	continue until the first character of DELIM is read, rather
41		than newline
42  -e		use Readline to obtain the line in an interactive shell
43  -i text	Use TEXT as the initial text for Readline
44  -n nchars	return after reading NCHARS characters rather than waiting
45		for a newline
46  -p prompt	output the string PROMPT without a trailing newline before
47		attempting to read
48  -r		do not allow backslashes to escape any characters
49  -s		do not echo input coming from a terminal
50  -t timeout	time out and return failure if a complete line of input is
51		not read withint TIMEOUT seconds.  The value of the TMOUT
52		variable is the default timeout.  TIMEOUT may be a
53		fractional number.  If TIMEOUT is 0, read returns success only
54		if input is available on the specified file descriptor.  The
55		exit status is greater than 128 if the timeout is exceeded
56  -u fd		read from file descriptor FD instead of the standard input
57
58Exit Status:
59The return code is zero, unless end-of-file is encountered, read times out,
60or an invalid file descriptor is supplied as the argument to -u.
61$END
62
63#include <config.h>
64
65#include "bashtypes.h"
66#include "posixstat.h"
67
68#include <stdio.h>
69
70#include "bashansi.h"
71
72#if defined (HAVE_UNISTD_H)
73#  include <unistd.h>
74#endif
75
76#include <signal.h>
77#include <errno.h>
78
79#ifdef __CYGWIN__
80#  include <fcntl.h>
81#  include <io.h>
82#endif
83
84#include "../bashintl.h"
85
86#include "../shell.h"
87#include "common.h"
88#include "bashgetopt.h"
89
90#include <shtty.h>
91
92#if defined (READLINE)
93#include "../bashline.h"
94#include <readline/readline.h>
95#endif
96
97#if defined (BUFFERED_INPUT)
98#  include "input.h"
99#endif
100
101#if !defined(errno)
102extern int errno;
103#endif
104
105struct ttsave
106{
107  int fd;
108  TTYSTRUCT *attrs;
109};
110
111#if defined (READLINE)
112static void reset_attempted_completion_function __P((char *));
113static int set_itext __P((void));
114static char *edit_line __P((char *, char *));
115static void set_eol_delim __P((int));
116static void reset_eol_delim __P((char *));
117#endif
118static SHELL_VAR *bind_read_variable __P((char *, char *));
119#if defined (HANDLE_MULTIBYTE)
120static int read_mbchar __P((int, char *, int, int, int));
121#endif
122static void ttyrestore __P((struct ttsave *));
123
124static sighandler sigalrm __P((int));
125static void reset_alarm __P((void));
126
127static procenv_t alrmbuf;
128static SigHandler *old_alrm;
129static unsigned char delim;
130
131static sighandler
132sigalrm (s)
133     int s;
134{
135  longjmp (alrmbuf, 1);
136}
137
138static void
139reset_alarm ()
140{
141  set_signal_handler (SIGALRM, old_alrm);
142  falarm (0, 0);
143}
144
145/* Read the value of the shell variables whose names follow.
146   The reading is done from the current input stream, whatever
147   that may be.  Successive words of the input line are assigned
148   to the variables mentioned in LIST.  The last variable in LIST
149   gets the remainder of the words on the line.  If no variables
150   are mentioned in LIST, then the default variable is $REPLY. */
151int
152read_builtin (list)
153     WORD_LIST *list;
154{
155  register char *varname;
156  int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
157  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
158  int raw, edit, nchars, silent, have_timeout, fd;
159  unsigned int tmsec, tmusec;
160  long ival, uval;
161  intmax_t intval;
162  char c;
163  char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
164  char *e, *t, *t1, *ps2, *tofree;
165  struct stat tsb;
166  SHELL_VAR *var;
167  TTYSTRUCT ttattrs, ttset;
168  struct ttsave termsave;
169#if defined (ARRAY_VARS)
170  WORD_LIST *alist;
171#endif
172#if defined (READLINE)
173  char *rlbuf, *itext;
174  int rlind;
175#endif
176
177  USE_VAR(size);
178  USE_VAR(i);
179  USE_VAR(pass_next);
180  USE_VAR(print_ps2);
181  USE_VAR(saw_escape);
182  USE_VAR(input_is_pipe);
183/*  USE_VAR(raw); */
184  USE_VAR(edit);
185  USE_VAR(tmsec);
186  USE_VAR(tmusec);
187  USE_VAR(nchars);
188  USE_VAR(silent);
189  USE_VAR(ifs_chars);
190  USE_VAR(prompt);
191  USE_VAR(arrayname);
192#if defined (READLINE)
193  USE_VAR(rlbuf);
194  USE_VAR(rlind);
195  USE_VAR(itext);
196#endif
197  USE_VAR(list);
198  USE_VAR(ps2);
199
200  i = 0;		/* Index into the string that we are reading. */
201  raw = edit = 0;	/* Not reading raw input by default. */
202  silent = 0;
203  arrayname = prompt = (char *)NULL;
204  fd = 0;		/* file descriptor to read from */
205
206#if defined (READLINE)
207  rlbuf = itext = (char *)0;
208  rlind = 0;
209#endif
210
211  tmsec = tmusec = 0;		/* no timeout */
212  nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
213  delim = '\n';		/* read until newline */
214
215  reset_internal_getopt ();
216  while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:")) != -1)
217    {
218      switch (opt)
219	{
220	case 'r':
221	  raw = 1;
222	  break;
223	case 'p':
224	  prompt = list_optarg;
225	  break;
226	case 's':
227	  silent = 1;
228	  break;
229	case 'e':
230#if defined (READLINE)
231	  edit = 1;
232#endif
233	  break;
234	case 'i':
235#if defined (READLINE)
236	  itext = list_optarg;
237#endif
238	  break;
239#if defined (ARRAY_VARS)
240	case 'a':
241	  arrayname = list_optarg;
242	  break;
243#endif
244	case 't':
245	  code = uconvert (list_optarg, &ival, &uval);
246	  if (code == 0 || ival < 0 || uval < 0)
247	    {
248	      builtin_error (_("%s: invalid timeout specification"), list_optarg);
249	      return (EXECUTION_FAILURE);
250	    }
251	  else
252	    {
253	      have_timeout = 1;
254	      tmsec = ival;
255	      tmusec = uval;
256	    }
257	  break;
258	case 'n':
259	  code = legal_number (list_optarg, &intval);
260	  if (code == 0 || intval < 0 || intval != (int)intval)
261	    {
262	      sh_invalidnum (list_optarg);
263	      return (EXECUTION_FAILURE);
264	    }
265	  else
266	    nchars = intval;
267	  break;
268	case 'u':
269	  code = legal_number (list_optarg, &intval);
270	  if (code == 0 || intval < 0 || intval != (int)intval)
271	    {
272	      builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
273	      return (EXECUTION_FAILURE);
274	    }
275	  else
276	    fd = intval;
277	  if (sh_validfd (fd) == 0)
278	    {
279	      builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
280	      return (EXECUTION_FAILURE);
281	    }
282	  break;
283	case 'd':
284	  delim = *list_optarg;
285	  break;
286	default:
287	  builtin_usage ();
288	  return (EX_USAGE);
289	}
290    }
291  list = loptend;
292
293  /* `read -t 0 var' tests whether input is available with select/FIONREAD,
294     and fails if those are unavailable */
295  if (have_timeout && tmsec == 0 && tmusec == 0)
296#if 0
297    return (EXECUTION_FAILURE);
298#else
299    return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
300#endif
301
302  /* IF IFS is unset, we use the default of " \t\n". */
303  ifs_chars = getifs ();
304  if (ifs_chars == 0)		/* XXX - shouldn't happen */
305    ifs_chars = "";
306  for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
307    skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
308
309  input_string = (char *)xmalloc (size = 112);	/* XXX was 128 */
310  input_string[0] = '\0';
311
312  /* $TMOUT, if set, is the default timeout for read. */
313  if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
314    {
315      code = uconvert (e, &ival, &uval);
316      if (code == 0 || ival < 0 || uval < 0)
317	tmsec = tmusec = 0;
318      else
319	{
320	  tmsec = ival;
321	  tmusec = uval;
322	}
323    }
324
325  begin_unwind_frame ("read_builtin");
326
327#if defined (BUFFERED_INPUT)
328  if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
329    sync_buffered_stream (default_buffered_input);
330#endif
331
332  input_is_tty = isatty (fd);
333  if (input_is_tty == 0)
334#ifndef __CYGWIN__
335    input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
336#else
337    input_is_pipe = 1;
338#endif
339
340  /* If the -p, -e or -s flags were given, but input is not coming from the
341     terminal, turn them off. */
342  if ((prompt || edit || silent) && input_is_tty == 0)
343    {
344      prompt = (char *)NULL;
345#if defined (READLINE)
346      itext = (char *)NULL;
347#endif
348      edit = silent = 0;
349    }
350
351#if defined (READLINE)
352  if (edit)
353    add_unwind_protect (xfree, rlbuf);
354#endif
355
356  pass_next = 0;	/* Non-zero signifies last char was backslash. */
357  saw_escape = 0;	/* Non-zero signifies that we saw an escape char */
358
359  if (tmsec > 0 || tmusec > 0)
360    {
361      /* Turn off the timeout if stdin is a regular file (e.g. from
362	 input redirection). */
363      if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
364	tmsec = tmusec = 0;
365    }
366
367  if (tmsec > 0 || tmusec > 0)
368    {
369      code = setjmp (alrmbuf);
370      if (code)
371	{
372	  /* Tricky.  The top of the unwind-protect stack is the free of
373	     input_string.  We want to run all the rest and use input_string,
374	     so we have to remove it from the stack. */
375	  remove_unwind_protect ();
376	  run_unwind_frame ("read_builtin");
377	  input_string[i] = '\0';	/* make sure it's terminated */
378	  retval = 128+SIGALRM;
379	  goto assign_vars;
380	}
381      old_alrm = set_signal_handler (SIGALRM, sigalrm);
382      add_unwind_protect (reset_alarm, (char *)NULL);
383#if defined (READLINE)
384      if (edit)
385	add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
386#endif
387      falarm (tmsec, tmusec);
388    }
389
390  /* If we've been asked to read only NCHARS chars, or we're using some
391     character other than newline to terminate the line, do the right
392     thing to readline or the tty. */
393  if (nchars > 0 || delim != '\n')
394    {
395#if defined (READLINE)
396      if (edit)
397	{
398	  if (nchars > 0)
399	    {
400	      unwind_protect_int (rl_num_chars_to_read);
401	      rl_num_chars_to_read = nchars;
402	    }
403	  if (delim != '\n')
404	    {
405	      set_eol_delim (delim);
406	      add_unwind_protect (reset_eol_delim, (char *)NULL);
407	    }
408	}
409      else
410#endif
411      if (input_is_tty)
412	{
413	  /* ttsave() */
414	  termsave.fd = fd;
415	  ttgetattr (fd, &ttattrs);
416	  termsave.attrs = &ttattrs;
417
418	  ttset = ttattrs;	  
419	  i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
420	  if (i < 0)
421	    sh_ttyerror (1);
422	  add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
423	}
424    }
425  else if (silent)	/* turn off echo but leave term in canonical mode */
426    {
427      /* ttsave (); */
428      termsave.fd = fd;
429      ttgetattr (fd, &ttattrs);
430      termsave.attrs = &ttattrs;
431
432      ttset = ttattrs;
433      i = ttfd_noecho (fd, &ttset);			/* ttnoecho (); */
434      if (i < 0)
435	sh_ttyerror (1);
436
437      add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
438    }
439
440  /* This *must* be the top unwind-protect on the stack, so the manipulation
441     of the unwind-protect stack after the realloc() works right. */
442  add_unwind_protect (xfree, input_string);
443  interrupt_immediately++;
444  terminate_immediately++;
445
446  unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
447
448  if (prompt && edit == 0)
449    {
450      fprintf (stderr, "%s", prompt);
451      fflush (stderr);
452    }
453
454#if defined (__CYGWIN__) && defined (O_TEXT)
455  setmode (0, O_TEXT);
456#endif
457
458  ps2 = 0;
459  for (print_ps2 = eof = retval = 0;;)
460    {
461#if defined (READLINE)
462      if (edit)
463	{
464	  if (rlbuf && rlbuf[rlind] == '\0')
465	    {
466	      xfree (rlbuf);
467	      rlbuf = (char *)0;
468	    }
469	  if (rlbuf == 0)
470	    {
471	      rlbuf = edit_line (prompt ? prompt : "", itext);
472	      rlind = 0;
473	    }
474	  if (rlbuf == 0)
475	    {
476	      eof = 1;
477	      break;
478	    }
479	  c = rlbuf[rlind++];
480	}
481      else
482	{
483#endif
484
485      if (print_ps2)
486	{
487	  if (ps2 == 0)
488	    ps2 = get_string_value ("PS2");
489	  fprintf (stderr, "%s", ps2 ? ps2 : "");
490	  fflush (stderr);
491	  print_ps2 = 0;
492	}
493
494      if (unbuffered_read)
495	retval = zread (fd, &c, 1);
496      else
497	retval = zreadc (fd, &c);
498
499      if (retval <= 0)
500	{
501	  eof = 1;
502	  break;
503	}
504
505#if defined (READLINE)
506	}
507#endif
508
509      if (i + 4 >= size)	/* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
510	{
511	  input_string = (char *)xrealloc (input_string, size += 128);
512	  remove_unwind_protect ();
513	  add_unwind_protect (xfree, input_string);
514	}
515
516      /* If the next character is to be accepted verbatim, a backslash
517	 newline pair still disappears from the input. */
518      if (pass_next)
519	{
520	  pass_next = 0;
521	  if (c == '\n')
522	    {
523	      i--;		/* back up over the CTLESC */
524	      if (interactive && input_is_tty && raw == 0)
525		print_ps2 = 1;
526	    }
527	  else
528	    goto add_char;
529	  continue;
530	}
531
532      /* This may cause problems if IFS contains CTLESC */
533      if (c == '\\' && raw == 0)
534	{
535	  pass_next++;
536	  if (skip_ctlesc == 0)
537	    {
538	      saw_escape++;
539	      input_string[i++] = CTLESC;
540	    }
541	  continue;
542	}
543
544      if ((unsigned char)c == delim)
545	break;
546
547      if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
548	{
549	  saw_escape++;
550	  input_string[i++] = CTLESC;
551	}
552
553add_char:
554      input_string[i++] = c;
555
556#if defined (HANDLE_MULTIBYTE)
557      if (nchars > 0 && MB_CUR_MAX > 1)
558	{
559	  input_string[i] = '\0';	/* for simplicity and debugging */
560	  i += read_mbchar (fd, input_string, i, c, unbuffered_read);
561	}
562#endif
563
564      nr++;
565
566      if (nchars > 0 && nr >= nchars)
567	break;
568    }
569  input_string[i] = '\0';
570
571#if 1
572  if (retval < 0)
573    {
574      builtin_error (_("read error: %d: %s"), fd, strerror (errno));
575      run_unwind_frame ("read_builtin");
576      return (EXECUTION_FAILURE);
577    }
578#endif
579
580  if (tmsec > 0 || tmusec > 0)
581    reset_alarm ();
582
583  if (nchars > 0 || delim != '\n')
584    {
585#if defined (READLINE)
586      if (edit)
587	{
588	  if (nchars > 0)
589	    rl_num_chars_to_read = 0;
590	  if (delim != '\n')
591	    reset_eol_delim ((char *)NULL);
592	}
593      else
594#endif
595      if (input_is_tty)
596	ttyrestore (&termsave);
597    }
598  else if (silent)
599    ttyrestore (&termsave);
600
601  if (unbuffered_read == 0)
602    zsyncfd (fd);
603
604  interrupt_immediately--;
605  terminate_immediately--;
606  discard_unwind_frame ("read_builtin");
607
608  retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
609
610assign_vars:
611
612#if defined (ARRAY_VARS)
613  /* If -a was given, take the string read, break it into a list of words,
614     an assign them to `arrayname' in turn. */
615  if (arrayname)
616    {
617      if (legal_identifier (arrayname) == 0)
618	{
619	  sh_invalidid (arrayname);
620	  xfree (input_string);
621	  return (EXECUTION_FAILURE);
622	}
623
624      var = find_or_make_array_variable (arrayname, 1);
625      if (var == 0)
626	{
627	  xfree (input_string);
628	  return EXECUTION_FAILURE;	/* readonly or noassign */
629	}
630      array_flush (array_cell (var));
631
632      alist = list_string (input_string, ifs_chars, 0);
633      if (alist)
634	{
635	  if (saw_escape)
636	    dequote_list (alist);
637	  else
638	    word_list_remove_quoted_nulls (alist);
639	  assign_array_var_from_word_list (var, alist, 0);
640	  dispose_words (alist);
641	}
642      xfree (input_string);
643      return (retval);
644    }
645#endif /* ARRAY_VARS */ 
646
647  /* If there are no variables, save the text of the line read to the
648     variable $REPLY.  ksh93 strips leading and trailing IFS whitespace,
649     so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
650     same way, but I believe that the difference in behaviors is useful
651     enough to not do it.  Without the bash behavior, there is no way
652     to read a line completely without interpretation or modification
653     unless you mess with $IFS (e.g., setting it to the empty string).
654     If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
655  if (list == 0)
656    {
657#if 0
658      orig_input_string = input_string;
659      for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
660	;
661      input_string = t;
662      input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
663#endif
664
665      if (saw_escape)
666	{
667	  t = dequote_string (input_string);
668	  var = bind_variable ("REPLY", t, 0);
669	  free (t);
670	}
671      else
672	var = bind_variable ("REPLY", input_string, 0);
673      VUNSETATTR (var, att_invisible);
674
675      free (input_string);
676      return (retval);
677    }
678
679  /* This code implements the Posix.2 spec for splitting the words
680     read and assigning them to variables. */
681  orig_input_string = input_string;
682
683  /* Remove IFS white space at the beginning of the input string.  If
684     $IFS is null, no field splitting is performed. */
685  for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
686    ;
687  input_string = t;
688  for (; list->next; list = list->next)
689    {
690      varname = list->word->word;
691#if defined (ARRAY_VARS)
692      if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
693#else
694      if (legal_identifier (varname) == 0)
695#endif
696	{
697	  sh_invalidid (varname);
698	  xfree (orig_input_string);
699	  return (EXECUTION_FAILURE);
700	}
701
702      /* If there are more variables than words read from the input,
703	 the remaining variables are set to the empty string. */
704      if (*input_string)
705	{
706	  /* This call updates INPUT_STRING. */
707	  t = get_word_from_string (&input_string, ifs_chars, &e);
708	  if (t)
709	    *e = '\0';
710	  /* Don't bother to remove the CTLESC unless we added one
711	     somewhere while reading the string. */
712	  if (t && saw_escape)
713	    {
714	      t1 = dequote_string (t);
715	      var = bind_read_variable (varname, t1);
716	      xfree (t1);
717	    }
718	  else
719	    var = bind_read_variable (varname, t);
720	}
721      else
722	{
723	  t = (char *)0;
724	  var = bind_read_variable (varname, "");
725	}
726
727      FREE (t);
728      if (var == 0)
729	{
730	  xfree (orig_input_string);
731	  return (EXECUTION_FAILURE);
732	}
733
734      stupidly_hack_special_variables (varname);
735      VUNSETATTR (var, att_invisible);
736    }
737
738  /* Now assign the rest of the line to the last variable argument. */
739#if defined (ARRAY_VARS)
740  if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
741#else
742  if (legal_identifier (list->word->word) == 0)
743#endif
744    {
745      sh_invalidid (list->word->word);
746      xfree (orig_input_string);
747      return (EXECUTION_FAILURE);
748    }
749
750#if 0
751  /* This has to be done this way rather than using string_list
752     and list_string because Posix.2 says that the last variable gets the
753     remaining words and their intervening separators. */
754  input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
755#else
756  /* Check whether or not the number of fields is exactly the same as the
757     number of variables. */
758  tofree = NULL;
759  if (*input_string)
760    {
761      t1 = input_string;
762      t = get_word_from_string (&input_string, ifs_chars, &e);
763      if (*input_string == 0)
764	tofree = input_string = t;
765      else
766	{
767	  input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
768	  tofree = t;
769	}
770    }
771#endif
772
773  if (saw_escape)
774    {
775      t = dequote_string (input_string);
776      var = bind_read_variable (list->word->word, t);
777      xfree (t);
778    }
779  else
780    var = bind_read_variable (list->word->word, input_string);
781  stupidly_hack_special_variables (list->word->word);
782  FREE (tofree);
783
784  if (var)
785    VUNSETATTR (var, att_invisible);
786  xfree (orig_input_string);
787
788  return (retval);
789}
790
791static SHELL_VAR *
792bind_read_variable (name, value)
793     char *name, *value;
794{
795#if defined (ARRAY_VARS)
796  if (valid_array_reference (name) == 0)
797    return (bind_variable (name, value, 0));
798  else
799    return (assign_array_element (name, value, 0));
800#else /* !ARRAY_VARS */
801  return bind_variable (name, value, 0);
802#endif /* !ARRAY_VARS */
803}
804
805#if defined (HANDLE_MULTIBYTE)
806static int
807read_mbchar (fd, string, ind, ch, unbuffered)
808     int fd;
809     char *string;
810     int ind, ch, unbuffered;
811{
812  char mbchar[MB_LEN_MAX + 1];
813  int i, n, r;
814  char c;
815  size_t ret;
816  mbstate_t ps, ps_back;
817  wchar_t wc;
818
819  memset (&ps, '\0', sizeof (mbstate_t));
820  memset (&ps_back, '\0', sizeof (mbstate_t));
821  
822  mbchar[0] = ch;
823  i = 1;
824  for (n = 0; n <= MB_LEN_MAX; n++)
825    {
826      ps_back = ps;
827      ret = mbrtowc (&wc, mbchar, i, &ps);
828      if (ret == (size_t)-2)
829	{
830	  ps = ps_back;
831	  if (unbuffered)
832	    r = zread (fd, &c, 1);
833	  else
834	    r = zreadc (fd, &c);
835	  if (r < 0)
836	    goto mbchar_return;
837	  mbchar[i++] = c;	
838	  continue;
839	}
840      else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
841	break;
842    }
843
844mbchar_return:
845  if (i > 1)	/* read a multibyte char */
846    /* mbchar[0] is already string[ind-1] */
847    for (r = 1; r < i; r++)
848      string[ind+r-1] = mbchar[r];
849  return i - 1;
850}
851#endif
852
853
854static void
855ttyrestore (ttp)
856     struct ttsave *ttp;
857{
858  ttsetattr (ttp->fd, ttp->attrs);
859}
860
861#if defined (READLINE)
862static rl_completion_func_t *old_attempted_completion_function = 0;
863static rl_hook_func_t *old_startup_hook;
864static char *deftext;
865
866static void
867reset_attempted_completion_function (cp)
868     char *cp;
869{
870  if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
871    rl_attempted_completion_function = old_attempted_completion_function;
872}
873
874static int
875set_itext ()
876{
877  int r1, r2;
878
879  r1 = r2 = 0;
880  if (old_startup_hook)
881    r1 = (*old_startup_hook) ();
882  if (deftext)
883    {
884      r2 = rl_insert_text (deftext);
885      deftext = (char *)NULL;
886      rl_startup_hook = old_startup_hook;
887      old_startup_hook = (rl_hook_func_t *)NULL;
888    }
889  return (r1 || r2);
890}
891
892static char *
893edit_line (p, itext)
894     char *p;
895     char *itext;
896{
897  char *ret;
898  int len;
899
900  if (bash_readline_initialized == 0)
901    initialize_readline ();
902
903  old_attempted_completion_function = rl_attempted_completion_function;
904  rl_attempted_completion_function = (rl_completion_func_t *)NULL;
905  if (itext)
906    {
907      old_startup_hook = rl_startup_hook;
908      rl_startup_hook = set_itext;
909      deftext = itext;
910    }
911  ret = readline (p);
912  rl_attempted_completion_function = old_attempted_completion_function;
913  old_attempted_completion_function = (rl_completion_func_t *)NULL;
914
915  if (ret == 0)
916    return ret;
917  len = strlen (ret);
918  ret = (char *)xrealloc (ret, len + 2);
919  ret[len++] = delim;
920  ret[len] = '\0';
921  return ret;
922}
923
924static int old_delim_ctype;
925static rl_command_func_t *old_delim_func;
926static int old_newline_ctype;
927static rl_command_func_t *old_newline_func;
928
929static unsigned char delim_char;
930
931static void
932set_eol_delim (c)
933     int c;
934{
935  Keymap cmap;
936
937  if (bash_readline_initialized == 0)
938    initialize_readline ();
939  cmap = rl_get_keymap ();
940
941  /* Change newline to self-insert */
942  old_newline_ctype = cmap[RETURN].type;
943  old_newline_func =  cmap[RETURN].function;
944  cmap[RETURN].type = ISFUNC;
945  cmap[RETURN].function = rl_insert;
946
947  /* Bind the delimiter character to accept-line. */
948  old_delim_ctype = cmap[c].type;
949  old_delim_func = cmap[c].function;
950  cmap[c].type = ISFUNC;
951  cmap[c].function = rl_newline;
952
953  delim_char = c;
954}
955
956static void
957reset_eol_delim (cp)
958     char *cp;
959{
960  Keymap cmap;
961
962  cmap = rl_get_keymap ();
963
964  cmap[RETURN].type = old_newline_ctype;
965  cmap[RETURN].function = old_newline_func;
966
967  cmap[delim_char].type = old_delim_ctype;
968  cmap[delim_char].function = old_delim_func;
969}
970#endif
971