Imported from ../bash-4.0.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-2009 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
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along 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 ...]
26 Read a line from the standard input and split it into fields.
27
28 Reads a single line from the standard input, or from file descriptor FD
29 if the -u option is supplied.  The line is split into fields as with word
30 splitting, and the first word is assigned to the first NAME, the second
31 word to the second NAME, and so on, with any leftover words assigned to
32 the last NAME.  Only the characters found in $IFS are recognized as word
33 delimiters.
34
35 If no NAMEs are supplied, the line read is stored in the REPLY variable.
36
37 Options:
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
58 Exit Status:
59 The return code is zero, unless end-of-file is encountered, read times out,
60 or 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)
102 extern int errno;
103 #endif
104
105 struct ttsave
106 {
107   int fd;
108   TTYSTRUCT *attrs;
109 };
110
111 #if defined (READLINE)
112 static void reset_attempted_completion_function __P((char *));
113 static int set_itext __P((void));
114 static char *edit_line __P((char *, char *));
115 static void set_eol_delim __P((int));
116 static void reset_eol_delim __P((char *));
117 #endif
118 static SHELL_VAR *bind_read_variable __P((char *, char *));
119 #if defined (HANDLE_MULTIBYTE)
120 static int read_mbchar __P((int, char *, int, int, int));
121 #endif
122 static void ttyrestore __P((struct ttsave *));
123
124 static sighandler sigalrm __P((int));
125 static void reset_alarm __P((void));
126
127 static procenv_t alrmbuf;
128 static SigHandler *old_alrm;
129 static unsigned char delim;
130
131 static sighandler
132 sigalrm (s)
133      int s;
134 {
135   longjmp (alrmbuf, 1);
136 }
137
138 static void
139 reset_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. */
151 int
152 read_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 #if 0
373           run_unwind_frame ("read_builtin");
374           return (EXECUTION_FAILURE);
375 #else
376           input_string[i] = '\0';       /* make sure it's terminated */
377           retval = 128+SIGALRM;;
378           goto assign_vars;
379 #endif
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
553 add_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
610 assign_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         input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
767     }
768 #endif
769
770   if (saw_escape)
771     {
772       t = dequote_string (input_string);
773       var = bind_read_variable (list->word->word, t);
774       xfree (t);
775     }
776   else
777     var = bind_read_variable (list->word->word, input_string);
778   stupidly_hack_special_variables (list->word->word);
779   FREE (tofree);
780
781   if (var)
782     VUNSETATTR (var, att_invisible);
783   xfree (orig_input_string);
784
785   return (retval);
786 }
787
788 static SHELL_VAR *
789 bind_read_variable (name, value)
790      char *name, *value;
791 {
792 #if defined (ARRAY_VARS)
793   if (valid_array_reference (name) == 0)
794     return (bind_variable (name, value, 0));
795   else
796     return (assign_array_element (name, value, 0));
797 #else /* !ARRAY_VARS */
798   return bind_variable (name, value, 0);
799 #endif /* !ARRAY_VARS */
800 }
801
802 #if defined (HANDLE_MULTIBYTE)
803 static int
804 read_mbchar (fd, string, ind, ch, unbuffered)
805      int fd;
806      char *string;
807      int ind, ch, unbuffered;
808 {
809   char mbchar[MB_LEN_MAX + 1];
810   int i, n, r;
811   char c;
812   size_t ret;
813   mbstate_t ps, ps_back;
814   wchar_t wc;
815
816   memset (&ps, '\0', sizeof (mbstate_t));
817   memset (&ps_back, '\0', sizeof (mbstate_t));
818   
819   mbchar[0] = ch;
820   i = 1;
821   for (n = 0; n <= MB_LEN_MAX; n++)
822     {
823       ps_back = ps;
824       ret = mbrtowc (&wc, mbchar, i, &ps);
825       if (ret == (size_t)-2)
826         {
827           ps = ps_back;
828           if (unbuffered)
829             r = zread (fd, &c, 1);
830           else
831             r = zreadc (fd, &c);
832           if (r < 0)
833             goto mbchar_return;
834           mbchar[i++] = c;      
835           continue;
836         }
837       else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
838         break;
839     }
840
841 mbchar_return:
842   if (i > 1)    /* read a multibyte char */
843     /* mbchar[0] is already string[ind-1] */
844     for (r = 1; r < i; r++)
845       string[ind+r-1] = mbchar[r];
846   return i - 1;
847 }
848 #endif
849
850
851 static void
852 ttyrestore (ttp)
853      struct ttsave *ttp;
854 {
855   ttsetattr (ttp->fd, ttp->attrs);
856 }
857
858 #if defined (READLINE)
859 static rl_completion_func_t *old_attempted_completion_function = 0;
860 static rl_hook_func_t *old_startup_hook;
861 static char *deftext;
862
863 static void
864 reset_attempted_completion_function (cp)
865      char *cp;
866 {
867   if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
868     rl_attempted_completion_function = old_attempted_completion_function;
869 }
870
871 static int
872 set_itext ()
873 {
874   int r1, r2;
875
876   r1 = r2 = 0;
877   if (old_startup_hook)
878     r1 = (*old_startup_hook) ();
879   if (deftext)
880     {
881       r2 = rl_insert_text (deftext);
882       deftext = (char *)NULL;
883       rl_startup_hook = old_startup_hook;
884       old_startup_hook = (rl_hook_func_t *)NULL;
885     }
886   return (r1 || r2);
887 }
888
889 static char *
890 edit_line (p, itext)
891      char *p;
892      char *itext;
893 {
894   char *ret;
895   int len;
896
897   if (bash_readline_initialized == 0)
898     initialize_readline ();
899
900   old_attempted_completion_function = rl_attempted_completion_function;
901   rl_attempted_completion_function = (rl_completion_func_t *)NULL;
902   if (itext)
903     {
904       old_startup_hook = rl_startup_hook;
905       rl_startup_hook = set_itext;
906       deftext = itext;
907     }
908   ret = readline (p);
909   rl_attempted_completion_function = old_attempted_completion_function;
910   old_attempted_completion_function = (rl_completion_func_t *)NULL;
911
912   if (ret == 0)
913     return ret;
914   len = strlen (ret);
915   ret = (char *)xrealloc (ret, len + 2);
916   ret[len++] = delim;
917   ret[len] = '\0';
918   return ret;
919 }
920
921 static int old_delim_ctype;
922 static rl_command_func_t *old_delim_func;
923 static int old_newline_ctype;
924 static rl_command_func_t *old_newline_func;
925
926 static unsigned char delim_char;
927
928 static void
929 set_eol_delim (c)
930      int c;
931 {
932   Keymap cmap;
933
934   if (bash_readline_initialized == 0)
935     initialize_readline ();
936   cmap = rl_get_keymap ();
937
938   /* Change newline to self-insert */
939   old_newline_ctype = cmap[RETURN].type;
940   old_newline_func =  cmap[RETURN].function;
941   cmap[RETURN].type = ISFUNC;
942   cmap[RETURN].function = rl_insert;
943
944   /* Bind the delimiter character to accept-line. */
945   old_delim_ctype = cmap[c].type;
946   old_delim_func = cmap[c].function;
947   cmap[c].type = ISFUNC;
948   cmap[c].function = rl_newline;
949
950   delim_char = c;
951 }
952
953 static void
954 reset_eol_delim (cp)
955      char *cp;
956 {
957   Keymap cmap;
958
959   cmap = rl_get_keymap ();
960
961   cmap[RETURN].type = old_newline_ctype;
962   cmap[RETURN].function = old_newline_func;
963
964   cmap[delim_char].type = old_delim_ctype;
965   cmap[delim_char].function = old_delim_func;
966 }
967 #endif