LCOV - code coverage report
Current view: top level - builtins - read.def (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 168 478 35.1 %
Date: 2020-10-29 14:49:28 Functions: 3 13 23.1 %

          Line data    Source code
       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-2015 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] [-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, but honor a delimiter if fewer than
      46             :                 NCHARS characters are read before the delimiter
      47             :   -N nchars     return only after reading exactly NCHARS characters, unless
      48             :                 EOF is encountered or read times out, ignoring any
      49             :                 delimiter
      50             :   -p prompt     output the string PROMPT without a trailing newline before
      51             :                 attempting to read
      52             :   -r    do not allow backslashes to escape any characters
      53             :   -s    do not echo input coming from a terminal
      54             :   -t timeout    time out and return failure if a complete line of
      55             :                 input is not read within TIMEOUT seconds.  The value of the
      56             :                 TMOUT variable is the default timeout.  TIMEOUT may be a
      57             :                 fractional number.  If TIMEOUT is 0, read returns
      58             :                 immediately, without trying to read any data, returning
      59             :                 success only if input is available on the specified
      60             :                 file descriptor.  The exit status is greater than 128
      61             :                 if the timeout is exceeded
      62             :   -u fd read from file descriptor FD instead of the standard input
      63             : 
      64             : Exit Status:
      65             : The return code is zero, unless end-of-file is encountered, read times out
      66             : (in which case it's greater than 128), a variable assignment error occurs,
      67             : or an invalid file descriptor is supplied as the argument to -u.
      68             : $END
      69             : 
      70             : #include <config.h>
      71             : 
      72             : #include "bashtypes.h"
      73             : #include "posixstat.h"
      74             : 
      75             : #include <stdio.h>
      76             : 
      77             : #include "bashansi.h"
      78             : 
      79             : #if defined (HAVE_UNISTD_H)
      80             : #  include <unistd.h>
      81             : #endif
      82             : 
      83             : #include <signal.h>
      84             : #include <errno.h>
      85             : 
      86             : #ifdef __CYGWIN__
      87             : #  include <fcntl.h>
      88             : #  include <io.h>
      89             : #endif
      90             : 
      91             : #include "../bashintl.h"
      92             : 
      93             : #include "../shell.h"
      94             : #include "common.h"
      95             : #include "bashgetopt.h"
      96             : 
      97             : #include <shtty.h>
      98             : 
      99             : #if defined (READLINE)
     100             : #include "../bashline.h"
     101             : #include <readline/readline.h>
     102             : #endif
     103             : 
     104             : #if defined (BUFFERED_INPUT)
     105             : #  include "input.h"
     106             : #endif
     107             : 
     108             : #include "shmbutil.h"
     109             : 
     110             : #if !defined(errno)
     111             : extern int errno;
     112             : #endif
     113             : 
     114             : extern void run_pending_traps __P((void));
     115             : 
     116             : extern int posixly_correct;
     117             : extern int trapped_signal_received;
     118             : 
     119             : struct ttsave
     120             : {
     121             :   int fd;
     122             :   TTYSTRUCT *attrs;
     123             : };
     124             : 
     125             : #if defined (READLINE)
     126             : static void reset_attempted_completion_function __P((char *));
     127             : static int set_itext __P((void));
     128             : static char *edit_line __P((char *, char *));
     129             : static void set_eol_delim __P((int));
     130             : static void reset_eol_delim __P((char *));
     131             : #endif
     132             : static SHELL_VAR *bind_read_variable __P((char *, char *));
     133             : #if defined (HANDLE_MULTIBYTE)
     134             : static int read_mbchar __P((int, char *, int, int, int));
     135             : #endif
     136             : static void ttyrestore __P((struct ttsave *));
     137             : 
     138             : static sighandler sigalrm __P((int));
     139             : static void reset_alarm __P((void));
     140             : 
     141             : /* Try this to see what the rest of the shell can do with the information. */
     142             : procenv_t alrmbuf;
     143             : int sigalrm_seen;
     144             : 
     145             : static int reading, tty_modified;
     146             : static SigHandler *old_alrm;
     147             : static unsigned char delim;
     148             : 
     149             : static struct ttsave termsave;
     150             : 
     151             : /* In all cases, SIGALRM just sets a flag that we check periodically.  This
     152             :    avoids problems with the semi-tricky stuff we do with the xfree of
     153             :    input_string at the top of the unwind-protect list (see below). */
     154             : 
     155             : /* Set a flag that CHECK_ALRM can check.  This relies on zread calling
     156             :    trap.c:check_signals_and_traps(), which knows about sigalrm_seen and
     157             :    alrmbuf. */
     158             : static sighandler
     159           0 : sigalrm (s)
     160             :      int s;
     161             : {
     162           0 :   sigalrm_seen = 1;
     163           0 : }
     164             : 
     165             : static void
     166           0 : reset_alarm ()
     167             : {
     168             :   /* Cancel alarm before restoring signal handler. */
     169           0 :   falarm (0, 0);
     170           0 :   set_signal_handler (SIGALRM, old_alrm);
     171           0 : }
     172             : 
     173             : /* Read the value of the shell variables whose names follow.
     174             :    The reading is done from the current input stream, whatever
     175             :    that may be.  Successive words of the input line are assigned
     176             :    to the variables mentioned in LIST.  The last variable in LIST
     177             :    gets the remainder of the words on the line.  If no variables
     178             :    are mentioned in LIST, then the default variable is $REPLY. */
     179             : int
     180       20214 : read_builtin (list)
     181             :      WORD_LIST *list;
     182             : {
     183       20214 :   register char *varname;
     184       20214 :   int size, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
     185       20214 :   volatile int i;
     186       20214 :   int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
     187       20214 :   int raw, edit, nchars, silent, have_timeout, ignore_delim, fd, lastsig, t_errno;
     188       20214 :   unsigned int tmsec, tmusec;
     189       20214 :   long ival, uval;
     190       20214 :   intmax_t intval;
     191       20214 :   char c;
     192       20214 :   char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
     193       20214 :   char *e, *t, *t1, *ps2, *tofree;
     194       20214 :   struct stat tsb;
     195       20214 :   SHELL_VAR *var;
     196       20214 :   TTYSTRUCT ttattrs, ttset;
     197             : #if defined (ARRAY_VARS)
     198       20214 :   WORD_LIST *alist;
     199             : #endif
     200             : #if defined (READLINE)
     201       20214 :   char *rlbuf, *itext;
     202       20214 :   int rlind;
     203             : #endif
     204             : 
     205       20214 :   USE_VAR(size);
     206       20214 :   USE_VAR(i);
     207       20214 :   USE_VAR(pass_next);
     208       20214 :   USE_VAR(print_ps2);
     209       20214 :   USE_VAR(saw_escape);
     210       20214 :   USE_VAR(input_is_pipe);
     211             : /*  USE_VAR(raw); */
     212       20214 :   USE_VAR(edit);
     213       20214 :   USE_VAR(tmsec);
     214       20214 :   USE_VAR(tmusec);
     215       20214 :   USE_VAR(nchars);
     216       20214 :   USE_VAR(silent);
     217       20214 :   USE_VAR(ifs_chars);
     218       20214 :   USE_VAR(prompt);
     219       20214 :   USE_VAR(arrayname);
     220             : #if defined (READLINE)
     221       20214 :   USE_VAR(rlbuf);
     222       20214 :   USE_VAR(rlind);
     223       20214 :   USE_VAR(itext);
     224             : #endif
     225       20214 :   USE_VAR(list);
     226       20214 :   USE_VAR(ps2);
     227       20214 :   USE_VAR(lastsig);
     228             : 
     229       20214 :   sigalrm_seen = reading = tty_modified = 0;
     230             : 
     231       20214 :   i = 0;                /* Index into the string that we are reading. */
     232       20214 :   raw = edit = 0;       /* Not reading raw input by default. */
     233       20214 :   silent = 0;
     234       20214 :   arrayname = prompt = (char *)NULL;
     235       20214 :   fd = 0;               /* file descriptor to read from */
     236             : 
     237             : #if defined (READLINE)
     238       20214 :   rlbuf = itext = (char *)0;
     239       20214 :   rlind = 0;
     240             : #endif
     241             : 
     242       20214 :   tmsec = tmusec = 0;           /* no timeout */
     243       20214 :   nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
     244       20214 :   delim = '\n';         /* read until newline */
     245       20214 :   ignore_delim = 0;
     246             : 
     247       20214 :   reset_internal_getopt ();
     248       20214 :   while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:N:")) != -1)
     249             :     {
     250           0 :       switch (opt)
     251             :         {
     252             :         case 'r':
     253             :           raw = 1;
     254             :           break;
     255           0 :         case 'p':
     256           0 :           prompt = list_optarg;
     257           0 :           break;
     258           0 :         case 's':
     259           0 :           silent = 1;
     260           0 :           break;
     261           0 :         case 'e':
     262             : #if defined (READLINE)
     263           0 :           edit = 1;
     264             : #endif
     265           0 :           break;
     266           0 :         case 'i':
     267             : #if defined (READLINE)
     268           0 :           itext = list_optarg;
     269             : #endif
     270           0 :           break;
     271             : #if defined (ARRAY_VARS)
     272           0 :         case 'a':
     273           0 :           arrayname = list_optarg;
     274           0 :           break;
     275             : #endif
     276           0 :         case 't':
     277           0 :           code = uconvert (list_optarg, &ival, &uval);
     278           0 :           if (code == 0 || ival < 0 || uval < 0)
     279             :             {
     280           0 :               builtin_error (_("%s: invalid timeout specification"), list_optarg);
     281             :               return (EXECUTION_FAILURE);
     282             :             }
     283             :           else
     284             :             {
     285           0 :               have_timeout = 1;
     286           0 :               tmsec = ival;
     287           0 :               tmusec = uval;
     288             :             }
     289           0 :           break;
     290           0 :         case 'N':
     291           0 :           ignore_delim = 1;
     292           0 :           delim = -1;
     293           0 :         case 'n':
     294           0 :           code = legal_number (list_optarg, &intval);
     295           0 :           if (code == 0 || intval < 0 || intval != (int)intval)
     296             :             {
     297           0 :               sh_invalidnum (list_optarg);
     298             :               return (EXECUTION_FAILURE);
     299             :             }
     300             :           else
     301             :             nchars = intval;
     302             :           break;
     303           0 :         case 'u':
     304           0 :           code = legal_number (list_optarg, &intval);
     305           0 :           if (code == 0 || intval < 0 || intval != (int)intval)
     306             :             {
     307           0 :               builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
     308             :               return (EXECUTION_FAILURE);
     309             :             }
     310             :           else
     311           0 :             fd = intval;
     312           0 :           if (sh_validfd (fd) == 0)
     313             :             {
     314           0 :               builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
     315             :               return (EXECUTION_FAILURE);
     316             :             }
     317             :           break;
     318           0 :         case 'd':
     319           0 :           delim = *list_optarg;
     320           0 :           break;
     321           0 :         CASE_HELPOPT;
     322           0 :         default:
     323           0 :           builtin_usage ();
     324             :           return (EX_USAGE);
     325             :         }
     326             :     }
     327       20214 :   list = loptend;
     328             : 
     329             :   /* `read -t 0 var' tests whether input is available with select/FIONREAD,
     330             :      and fails if those are unavailable */
     331       20214 :   if (have_timeout && tmsec == 0 && tmusec == 0)
     332             : #if 0
     333             :     return (EXECUTION_FAILURE);
     334             : #else
     335           0 :     return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
     336             : #endif
     337             : 
     338             :   /* Convenience: check early whether or not the first of possibly several
     339             :      variable names is a valid identifier, and bail early if so. */
     340             : #if defined (ARRAY_VARS)
     341       20214 :   if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, 0) == 0)
     342             : #else
     343             :   if (list && legal_identifier (list->word->word) == 0)
     344             : #endif
     345             :     {
     346          12 :       sh_invalidid (list->word->word);
     347             :       return (EXECUTION_FAILURE);
     348             :     }
     349             : 
     350             :   /* If we're asked to ignore the delimiter, make sure we do. */
     351       20202 :   if (ignore_delim)
     352           0 :     delim = -1;
     353             : 
     354             :   /* IF IFS is unset, we use the default of " \t\n". */
     355       20202 :   ifs_chars = getifs ();
     356       20202 :   if (ifs_chars == 0)           /* XXX - shouldn't happen */
     357           0 :     ifs_chars = "";
     358             :   /* If we want to read exactly NCHARS chars, don't split on IFS */
     359       20202 :   if (ignore_delim)
     360           0 :     ifs_chars = "";
     361       80808 :   for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
     362       60606 :     skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
     363             : 
     364       20202 :   input_string = (char *)xmalloc (size = 112);  /* XXX was 128 */
     365       20202 :   input_string[0] = '\0';
     366             : 
     367             :   /* $TMOUT, if set, is the default timeout for read. */
     368       20202 :   if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
     369             :     {
     370           0 :       code = uconvert (e, &ival, &uval);
     371           0 :       if (code == 0 || ival < 0 || uval < 0)
     372             :         tmsec = tmusec = 0;
     373             :       else
     374             :         {
     375           0 :           tmsec = ival;
     376           0 :           tmusec = uval;
     377             :         }
     378             :     }
     379             : 
     380       20202 :   begin_unwind_frame ("read_builtin");
     381             : 
     382             : #if defined (BUFFERED_INPUT)
     383       20202 :   if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
     384       20202 :     sync_buffered_stream (default_buffered_input);
     385             : #endif
     386             : 
     387       20202 :   input_is_tty = isatty (fd);
     388       20202 :   if (input_is_tty == 0)
     389             : #ifndef __CYGWIN__
     390       20202 :     input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
     391             : #else
     392             :     input_is_pipe = 1;
     393             : #endif
     394             : 
     395             :   /* If the -p, -e or -s flags were given, but input is not coming from the
     396             :      terminal, turn them off. */
     397       20202 :   if ((prompt || edit || silent) && input_is_tty == 0)
     398             :     {
     399           0 :       prompt = (char *)NULL;
     400             : #if defined (READLINE)
     401           0 :       itext = (char *)NULL;
     402             : #endif
     403           0 :       edit = silent = 0;
     404             :     }
     405             : 
     406             : #if defined (READLINE)
     407       20202 :   if (edit)
     408           0 :     add_unwind_protect (xfree, rlbuf);
     409             : #endif
     410             : 
     411       20202 :   pass_next = 0;        /* Non-zero signifies last char was backslash. */
     412       20202 :   saw_escape = 0;       /* Non-zero signifies that we saw an escape char */
     413             : 
     414       20202 :   if (tmsec > 0 || tmusec > 0)
     415             :     {
     416             :       /* Turn off the timeout if stdin is a regular file (e.g. from
     417             :          input redirection). */
     418           0 :       if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
     419             :         tmsec = tmusec = 0;
     420             :     }
     421             : 
     422       20202 :   if (tmsec > 0 || tmusec > 0)
     423             :     {
     424           0 :       code = setjmp_nosigs (alrmbuf);
     425           0 :       if (code)
     426             :         {
     427           0 :           sigalrm_seen = 0;
     428             :           /* Tricky.  The top of the unwind-protect stack is the free of
     429             :              input_string.  We want to run all the rest and use input_string,
     430             :              so we have to save input_string temporarily, run the unwind-
     431             :              protects, then restore input_string so we can use it later */
     432           0 :           orig_input_string = 0;
     433           0 :           input_string[i] = '\0';       /* make sure it's terminated */
     434           0 :           if (i == 0)
     435             :             {
     436           0 :               t = (char *)xmalloc (1);
     437           0 :               t[0] = 0;
     438             :             }
     439             :           else
     440           0 :             t = savestring (input_string);
     441             : 
     442           0 :           run_unwind_frame ("read_builtin");
     443           0 :           input_string = t;
     444           0 :           retval = 128+SIGALRM;
     445           0 :           goto assign_vars;
     446             :         }
     447           0 :       if (interactive_shell == 0)
     448           0 :         initialize_terminating_signals ();
     449           0 :       old_alrm = set_signal_handler (SIGALRM, sigalrm);
     450           0 :       add_unwind_protect (reset_alarm, (char *)NULL);
     451             : #if defined (READLINE)
     452           0 :       if (edit)
     453             :         {
     454           0 :           add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
     455           0 :           add_unwind_protect (bashline_reset_event_hook, (char *)NULL);
     456             :         }
     457             : #endif
     458           0 :       falarm (tmsec, tmusec);
     459             :     }
     460             : 
     461             :   /* If we've been asked to read only NCHARS chars, or we're using some
     462             :      character other than newline to terminate the line, do the right
     463             :      thing to readline or the tty. */
     464       20202 :   if (nchars > 0 || delim != '\n')
     465             :     {
     466             : #if defined (READLINE)
     467           0 :       if (edit)
     468             :         {
     469           0 :           if (nchars > 0)
     470             :             {
     471           0 :               unwind_protect_int (rl_num_chars_to_read);
     472           0 :               rl_num_chars_to_read = nchars;
     473             :             }
     474           0 :           if (delim != '\n')
     475             :             {
     476           0 :               set_eol_delim (delim);
     477           0 :               add_unwind_protect (reset_eol_delim, (char *)NULL);
     478             :             }
     479             :         }
     480             :       else
     481             : #endif
     482           0 :       if (input_is_tty)
     483             :         {
     484             :           /* ttsave() */
     485           0 :           termsave.fd = fd;
     486           0 :           ttgetattr (fd, &ttattrs);
     487           0 :           termsave.attrs = &ttattrs;
     488             : 
     489           0 :           ttset = ttattrs;        
     490           0 :           i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
     491           0 :           if (i < 0)
     492           0 :             sh_ttyerror (1);
     493           0 :           tty_modified = 1;
     494           0 :           add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
     495           0 :           if (interactive_shell == 0)
     496           0 :             initialize_terminating_signals ();
     497             :         }
     498             :     }
     499       20202 :   else if (silent)      /* turn off echo but leave term in canonical mode */
     500             :     {
     501             :       /* ttsave (); */
     502           0 :       termsave.fd = fd;
     503           0 :       ttgetattr (fd, &ttattrs);
     504           0 :       termsave.attrs = &ttattrs;
     505             : 
     506           0 :       ttset = ttattrs;
     507           0 :       i = ttfd_noecho (fd, &ttset);                 /* ttnoecho (); */
     508           0 :       if (i < 0)
     509           0 :         sh_ttyerror (1);
     510             : 
     511           0 :       tty_modified = 1;
     512           0 :       add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
     513           0 :       if (interactive_shell == 0)
     514           0 :         initialize_terminating_signals ();
     515             :     }
     516             : 
     517             :   /* This *must* be the top unwind-protect on the stack, so the manipulation
     518             :      of the unwind-protect stack after the realloc() works right. */
     519       20202 :   add_unwind_protect (xfree, input_string);
     520             : 
     521       20202 :   CHECK_ALRM;
     522       20202 :   if ((nchars > 0) && (input_is_tty == 0) && ignore_delim)   /* read -N */
     523             :     unbuffered_read = 2;
     524       20202 :   else if ((nchars > 0) || (delim != '\n') || input_is_pipe)
     525       20078 :     unbuffered_read = 1;
     526             : 
     527       20202 :   if (prompt && edit == 0)
     528             :     {
     529           0 :       fprintf (stderr, "%s", prompt);
     530           0 :       fflush (stderr);
     531             :     }
     532             : 
     533             : #if defined (__CYGWIN__) && defined (O_TEXT)
     534             :   setmode (0, O_TEXT);
     535             : #endif
     536             : 
     537             :   ps2 = 0;
     538             :   for (print_ps2 = eof = retval = 0;;)
     539             :     {
     540      176502 :       CHECK_ALRM;
     541             : 
     542             : #if defined (READLINE)
     543      176502 :       if (edit)
     544             :         {
     545           0 :           if (rlbuf && rlbuf[rlind] == '\0')
     546             :             {
     547           0 :               xfree (rlbuf);
     548             :               rlbuf = (char *)0;
     549             :             }
     550           0 :           if (rlbuf == 0)
     551             :             {
     552           0 :               reading = 1;
     553           0 :               rlbuf = edit_line (prompt ? prompt : "", itext);
     554           0 :               reading = 0;
     555           0 :               rlind = 0;
     556             :             }
     557           0 :           if (rlbuf == 0)
     558             :             {
     559             :               eof = 1;
     560             :               break;
     561             :             }
     562           0 :           c = rlbuf[rlind++];
     563             :         }
     564             :       else
     565             :         {
     566             : #endif
     567             : 
     568      176502 :       if (print_ps2)
     569             :         {
     570           0 :           if (ps2 == 0)
     571           0 :             ps2 = get_string_value ("PS2");
     572           0 :           fprintf (stderr, "%s", ps2 ? ps2 : "");
     573           0 :           fflush (stderr);
     574             :           print_ps2 = 0;
     575             :         }
     576             : 
     577             : #if 0
     578             :       if (posixly_correct == 0)
     579             :         interrupt_immediately++;
     580             : #endif
     581      176502 :       reading = 1;
     582      176502 :       if (unbuffered_read == 2)
     583           0 :         retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr);
     584      176502 :       else if (unbuffered_read)
     585      174896 :         retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1);
     586             :       else
     587        1606 :         retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
     588      176502 :       reading = 0;
     589             : #if 0
     590             :       if (posixly_correct == 0)
     591             :         interrupt_immediately--;
     592             : #endif
     593             : 
     594      176502 :       if (retval <= 0)
     595             :         {
     596        2876 :           if (retval < 0 && errno == EINTR)
     597             :             {
     598           0 :               lastsig = LASTSIG();
     599           0 :               if (lastsig == 0)
     600           0 :                 lastsig = trapped_signal_received;
     601           0 :               run_pending_traps ();     /* because interrupt_immediately is not set */
     602             :             }
     603             :           else
     604             :             lastsig = 0;
     605        2876 :           if (terminating_signal && tty_modified)
     606           0 :             ttyrestore (&termsave); /* fix terminal before exiting */
     607        2876 :           CHECK_TERMSIG;
     608             :           eof = 1;
     609             :           break;
     610             :         }
     611             : 
     612      173626 :       CHECK_ALRM;
     613      173626 :       QUIT;             /* in case we didn't call check_signals() */
     614             : #if defined (READLINE)
     615             :         }
     616             : #endif
     617             : 
     618      173626 :       CHECK_ALRM;
     619      173626 :       if (i + 4 >= size)     /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
     620             :         {
     621           0 :           char *t;
     622           0 :           t = (char *)xrealloc (input_string, size += 128);
     623             : 
     624             :           /* Only need to change unwind-protect if input_string changes */
     625           0 :           if (t != input_string)
     626             :             {
     627           0 :               input_string = t;
     628           0 :               remove_unwind_protect ();
     629           0 :               add_unwind_protect (xfree, input_string);
     630             :             }
     631             :         }
     632             : 
     633             :       /* If the next character is to be accepted verbatim, a backslash
     634             :          newline pair still disappears from the input. */
     635      173626 :       if (pass_next)
     636             :         {
     637           0 :           pass_next = 0;
     638           0 :           if (c == '\n')
     639             :             {
     640           0 :               i--;              /* back up over the CTLESC */
     641           0 :               if (interactive && input_is_tty && raw == 0)
     642           0 :                 print_ps2 = 1;
     643             :             }
     644             :           else
     645             :             goto add_char;
     646           0 :           continue;
     647             :         }
     648             : 
     649             :       /* This may cause problems if IFS contains CTLESC */
     650      173626 :       if (c == '\\' && raw == 0)
     651             :         {
     652           0 :           pass_next++;
     653           0 :           if (skip_ctlesc == 0)
     654             :             {
     655           0 :               saw_escape++;
     656           0 :               input_string[i++] = CTLESC;
     657             :             }
     658           0 :           continue;
     659             :         }
     660             : 
     661      173626 :       if (ignore_delim == 0 && (unsigned char)c == delim)
     662             :         break;
     663             : 
     664      156300 :       if (c == '\0' && delim != '\0')
     665             :         continue;               /* skip NUL bytes in input */
     666             : 
     667      156300 :       if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
     668             :         {
     669           0 :           saw_escape++;
     670           0 :           input_string[i++] = CTLESC;
     671             :         }
     672             : 
     673      156300 : add_char:
     674      156300 :       input_string[i++] = c;
     675      156300 :       CHECK_ALRM;
     676             : 
     677             : #if defined (HANDLE_MULTIBYTE)
     678      156300 :       if (nchars > 0 && MB_CUR_MAX > 1 && is_basic (c) == 0)
     679             :         {
     680           0 :           input_string[i] = '\0';       /* for simplicity and debugging */
     681           0 :           i += read_mbchar (fd, input_string, i, c, unbuffered_read);
     682             :         }
     683             : #endif
     684             : 
     685      156300 :       nr++;
     686             : 
     687      156300 :       if (nchars > 0 && nr >= nchars)
     688             :         break;
     689             :     }
     690       20202 :   input_string[i] = '\0';
     691       20202 :   CHECK_ALRM;
     692             : 
     693             : #if defined (READLINE)
     694       20202 :   if (edit)
     695           0 :     free (rlbuf);
     696             : #endif
     697             : 
     698       20202 :   if (retval < 0)
     699             :     {
     700           0 :       t_errno = errno;
     701           0 :       if (errno != EINTR)
     702           0 :         builtin_error (_("read error: %d: %s"), fd, strerror (errno));
     703           0 :       run_unwind_frame ("read_builtin");
     704           0 :       return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig);
     705             :     }
     706             : 
     707       20202 :   if (tmsec > 0 || tmusec > 0)
     708           0 :     reset_alarm ();
     709             : 
     710       20202 :   if (nchars > 0 || delim != '\n')
     711             :     {
     712             : #if defined (READLINE)
     713           0 :       if (edit)
     714             :         {
     715           0 :           if (nchars > 0)
     716           0 :             rl_num_chars_to_read = 0;
     717           0 :           if (delim != '\n')
     718           0 :             reset_eol_delim ((char *)NULL);
     719             :         }
     720             :       else
     721             : #endif
     722           0 :       if (input_is_tty)
     723           0 :         ttyrestore (&termsave);
     724             :     }
     725       20202 :   else if (silent)
     726           0 :     ttyrestore (&termsave);
     727             : 
     728       20202 :   if (unbuffered_read == 0)
     729         124 :     zsyncfd (fd);
     730             : 
     731       20202 :   discard_unwind_frame ("read_builtin");
     732             : 
     733       20202 :   retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
     734             : 
     735       20202 : assign_vars:
     736             : 
     737             : #if defined (ARRAY_VARS)
     738             :   /* If -a was given, take the string read, break it into a list of words,
     739             :      an assign them to `arrayname' in turn. */
     740       20202 :   if (arrayname)
     741             :     {
     742           0 :       if (legal_identifier (arrayname) == 0)
     743             :         {
     744           0 :           sh_invalidid (arrayname);
     745           0 :           xfree (input_string);
     746             :           return (EXECUTION_FAILURE);
     747             :         }
     748             : 
     749           0 :       var = find_or_make_array_variable (arrayname, 1);
     750           0 :       if (var == 0)
     751             :         {
     752           0 :           xfree (input_string);
     753             :           return EXECUTION_FAILURE;     /* readonly or noassign */
     754             :         }
     755           0 :       if (assoc_p (var))
     756             :         {
     757           0 :           builtin_error (_("%s: cannot convert associative to indexed array"), arrayname);
     758           0 :           xfree (input_string);
     759             :           return EXECUTION_FAILURE;     /* existing associative array */
     760             :         }
     761           0 :       else if (invisible_p (var))
     762           0 :         VUNSETATTR (var, att_invisible);
     763           0 :       array_flush (array_cell (var));
     764             : 
     765           0 :       alist = list_string (input_string, ifs_chars, 0);
     766           0 :       if (alist)
     767             :         {
     768           0 :           if (saw_escape)
     769           0 :             dequote_list (alist);
     770             :           else
     771           0 :             word_list_remove_quoted_nulls (alist);
     772           0 :           assign_array_var_from_word_list (var, alist, 0);
     773           0 :           dispose_words (alist);
     774             :         }
     775           0 :       xfree (input_string);
     776             :       return (retval);
     777             :     }
     778             : #endif /* ARRAY_VARS */ 
     779             : 
     780             :   /* If there are no variables, save the text of the line read to the
     781             :      variable $REPLY.  ksh93 strips leading and trailing IFS whitespace,
     782             :      so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
     783             :      same way, but I believe that the difference in behaviors is useful
     784             :      enough to not do it.  Without the bash behavior, there is no way
     785             :      to read a line completely without interpretation or modification
     786             :      unless you mess with $IFS (e.g., setting it to the empty string).
     787             :      If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
     788       20202 :   if (list == 0)
     789             :     {
     790             : #if 0
     791             :       orig_input_string = input_string;
     792             :       for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
     793             :         ;
     794             :       input_string = t;
     795             :       input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
     796             : #endif
     797             : 
     798         120 :       if (saw_escape)
     799             :         {
     800           0 :           t = dequote_string (input_string);
     801           0 :           var = bind_variable ("REPLY", t, 0);
     802           0 :           free (t);
     803             :         }
     804             :       else
     805         120 :         var = bind_variable ("REPLY", input_string, 0);
     806         120 :       if (var == 0 || readonly_p (var) || noassign_p (var))
     807             :         retval = EXECUTION_FAILURE;
     808             :       else
     809         120 :         VUNSETATTR (var, att_invisible);
     810             : 
     811         120 :       xfree (input_string);
     812             :       return (retval);
     813             :     }
     814             : 
     815             :   /* This code implements the Posix.2 spec for splitting the words
     816             :      read and assigning them to variables. */
     817       20082 :   orig_input_string = input_string;
     818             : 
     819             :   /* Remove IFS white space at the beginning of the input string.  If
     820             :      $IFS is null, no field splitting is performed. */
     821       20082 :   for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
     822           0 :     ;
     823       20082 :   input_string = t;
     824       20095 :   for (; list->next; list = list->next)
     825             :     {
     826          13 :       varname = list->word->word;
     827             : #if defined (ARRAY_VARS)
     828          13 :       if (legal_identifier (varname) == 0 && valid_array_reference (varname, 0) == 0)
     829             : #else
     830             :       if (legal_identifier (varname) == 0)
     831             : #endif
     832             :         {
     833           0 :           sh_invalidid (varname);
     834           0 :           xfree (orig_input_string);
     835             :           return (EXECUTION_FAILURE);
     836             :         }
     837             : 
     838             :       /* If there are more variables than words read from the input,
     839             :          the remaining variables are set to the empty string. */
     840          13 :       if (*input_string)
     841             :         {
     842             :           /* This call updates INPUT_STRING. */
     843           0 :           t = get_word_from_string (&input_string, ifs_chars, &e);
     844           0 :           if (t)
     845           0 :             *e = '\0';
     846             :           /* Don't bother to remove the CTLESC unless we added one
     847             :              somewhere while reading the string. */
     848           0 :           if (t && saw_escape)
     849             :             {
     850           0 :               t1 = dequote_string (t);
     851           0 :               var = bind_read_variable (varname, t1);
     852           0 :               xfree (t1);
     853             :             }
     854             :           else
     855           0 :             var = bind_read_variable (varname, t ? t : "");
     856             :         }
     857             :       else
     858             :         {
     859          13 :           t = (char *)0;
     860          13 :           var = bind_read_variable (varname, "");
     861             :         }
     862             : 
     863           0 :       FREE (t);
     864          13 :       if (var == 0)
     865             :         {
     866           0 :           xfree (orig_input_string);
     867             :           return (EXECUTION_FAILURE);
     868             :         }
     869             : 
     870          13 :       stupidly_hack_special_variables (varname);
     871          13 :       VUNSETATTR (var, att_invisible);
     872             :     }
     873             : 
     874             :   /* Now assign the rest of the line to the last variable argument. */
     875             : #if defined (ARRAY_VARS)
     876       20082 :   if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, 0) == 0)
     877             : #else
     878             :   if (legal_identifier (list->word->word) == 0)
     879             : #endif
     880             :     {
     881          13 :       sh_invalidid (list->word->word);
     882          13 :       xfree (orig_input_string);
     883             :       return (EXECUTION_FAILURE);
     884             :     }
     885             : 
     886             : #if 0
     887             :   /* This has to be done this way rather than using string_list
     888             :      and list_string because Posix.2 says that the last variable gets the
     889             :      remaining words and their intervening separators. */
     890             :   input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
     891             : #else
     892             :   /* Check whether or not the number of fields is exactly the same as the
     893             :      number of variables. */
     894       20069 :   tofree = NULL;
     895       20069 :   if (*input_string)
     896             :     {
     897       17202 :       t1 = input_string;
     898       17202 :       t = get_word_from_string (&input_string, ifs_chars, &e);
     899       17202 :       if (*input_string == 0)
     900       17202 :         tofree = input_string = t;
     901             :       else
     902             :         {
     903           0 :           input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
     904           0 :           tofree = t;
     905             :         }
     906             :     }
     907             : #endif
     908             : 
     909       20069 :   if (saw_escape && input_string && *input_string)
     910             :     {
     911           0 :       t = dequote_string (input_string);
     912           0 :       var = bind_read_variable (list->word->word, t);
     913           0 :       xfree (t);
     914             :     }
     915             :   else
     916       40138 :     var = bind_read_variable (list->word->word, input_string ? input_string : "");
     917             : 
     918       20069 :   if (var)
     919             :     {
     920       20069 :       stupidly_hack_special_variables (list->word->word);
     921       20069 :       VUNSETATTR (var, att_invisible);
     922             :     }
     923             :   else
     924             :     retval = EXECUTION_FAILURE;
     925             : 
     926       20069 :   FREE (tofree);
     927       20069 :   xfree (orig_input_string);
     928             : 
     929             :   return (retval);
     930             : }
     931             : 
     932             : static SHELL_VAR *
     933       20082 : bind_read_variable (name, value)
     934             :      char *name, *value;
     935             : {
     936       20082 :   SHELL_VAR *v;
     937             : 
     938             : #if defined (ARRAY_VARS)
     939       20082 :   if (valid_array_reference (name, 0) == 0)
     940       20082 :     v = bind_variable (name, value, 0);
     941             :   else
     942           0 :     v = assign_array_element (name, value, 0);
     943             : #else /* !ARRAY_VARS */
     944             :   v = bind_variable (name, value, 0);
     945             : #endif /* !ARRAY_VARS */
     946       20082 :   return (v == 0 ? v
     947       20082 :                  : ((readonly_p (v) || noassign_p (v)) ? (SHELL_VAR *)NULL : v));
     948             : }
     949             : 
     950             : #if defined (HANDLE_MULTIBYTE)
     951             : static int
     952           0 : read_mbchar (fd, string, ind, ch, unbuffered)
     953             :      int fd;
     954             :      char *string;
     955             :      int ind, ch, unbuffered;
     956             : {
     957           0 :   char mbchar[MB_LEN_MAX + 1];
     958           0 :   int i, n, r;
     959           0 :   char c;
     960           0 :   size_t ret;
     961           0 :   mbstate_t ps, ps_back;
     962           0 :   wchar_t wc;
     963             : 
     964           0 :   memset (&ps, '\0', sizeof (mbstate_t));
     965           0 :   memset (&ps_back, '\0', sizeof (mbstate_t));
     966             :   
     967           0 :   mbchar[0] = ch;
     968           0 :   i = 1;
     969           0 :   for (n = 0; n <= MB_LEN_MAX; n++)
     970             :     {
     971           0 :       ps_back = ps;
     972           0 :       ret = mbrtowc (&wc, mbchar, i, &ps);
     973           0 :       if (ret == (size_t)-2)
     974             :         {
     975           0 :           ps = ps_back;
     976             :           /* We don't want to be interrupted during a multibyte char read */
     977           0 :           if (unbuffered)
     978           0 :             r = zread (fd, &c, 1);
     979             :           else
     980           0 :             r = zreadc (fd, &c);
     981           0 :           if (r < 0)
     982           0 :             goto mbchar_return;
     983           0 :           mbchar[i++] = c;      
     984           0 :           continue;
     985             :         }
     986             :       else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
     987             :         break;
     988             :     }
     989             : 
     990           0 : mbchar_return:
     991           0 :   if (i > 1) /* read a multibyte char */
     992             :     /* mbchar[0] is already string[ind-1] */
     993           0 :     for (r = 1; r < i; r++)
     994           0 :       string[ind+r-1] = mbchar[r];
     995           0 :   return i - 1;
     996             : }
     997             : #endif
     998             : 
     999             : 
    1000             : static void
    1001           0 : ttyrestore (ttp)
    1002             :      struct ttsave *ttp;
    1003             : {
    1004           0 :   ttsetattr (ttp->fd, ttp->attrs);
    1005           0 :   tty_modified = 0;
    1006           0 : }
    1007             : 
    1008             : void
    1009           0 : read_tty_cleanup ()
    1010             : {
    1011           0 :   if (tty_modified)
    1012           0 :     ttyrestore (&termsave);
    1013           0 : }
    1014             : 
    1015             : int
    1016     9143340 : read_tty_modified ()
    1017             : {
    1018     9143340 :   return (tty_modified);
    1019             : }
    1020             : 
    1021             : #if defined (READLINE)
    1022             : static rl_completion_func_t *old_attempted_completion_function = 0;
    1023             : static rl_hook_func_t *old_startup_hook;
    1024             : static char *deftext;
    1025             : 
    1026             : static void
    1027           0 : reset_attempted_completion_function (cp)
    1028             :      char *cp;
    1029             : {
    1030           0 :   if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
    1031           0 :     rl_attempted_completion_function = old_attempted_completion_function;
    1032           0 : }
    1033             : 
    1034             : static int
    1035           0 : set_itext ()
    1036             : {
    1037           0 :   int r1, r2;
    1038             : 
    1039           0 :   r1 = r2 = 0;
    1040           0 :   if (old_startup_hook)
    1041           0 :     r1 = (*old_startup_hook) ();
    1042           0 :   if (deftext)
    1043             :     {
    1044           0 :       r2 = rl_insert_text (deftext);
    1045           0 :       deftext = (char *)NULL;
    1046           0 :       rl_startup_hook = old_startup_hook;
    1047           0 :       old_startup_hook = (rl_hook_func_t *)NULL;
    1048             :     }
    1049           0 :   return (r1 || r2);
    1050             : }
    1051             : 
    1052             : static char *
    1053           0 : edit_line (p, itext)
    1054             :      char *p;
    1055             :      char *itext;
    1056             : {
    1057           0 :   char *ret;
    1058           0 :   int len;
    1059             : 
    1060           0 :   if (bash_readline_initialized == 0)
    1061           0 :     initialize_readline ();
    1062             : 
    1063           0 :   old_attempted_completion_function = rl_attempted_completion_function;
    1064           0 :   rl_attempted_completion_function = (rl_completion_func_t *)NULL;
    1065           0 :   bashline_set_event_hook ();
    1066           0 :   if (itext)
    1067             :     {
    1068           0 :       old_startup_hook = rl_startup_hook;
    1069           0 :       rl_startup_hook = set_itext;
    1070           0 :       deftext = itext;
    1071             :     }
    1072             : 
    1073           0 :   ret = readline (p);
    1074             : 
    1075           0 :   rl_attempted_completion_function = old_attempted_completion_function;
    1076           0 :   old_attempted_completion_function = (rl_completion_func_t *)NULL;
    1077           0 :   bashline_reset_event_hook ();
    1078             : 
    1079           0 :   if (ret == 0)
    1080             :     return ret;
    1081           0 :   len = strlen (ret);
    1082           0 :   ret = (char *)xrealloc (ret, len + 2);
    1083           0 :   ret[len++] = delim;
    1084           0 :   ret[len] = '\0';
    1085           0 :   return ret;
    1086             : }
    1087             : 
    1088             : static int old_delim_ctype;
    1089             : static rl_command_func_t *old_delim_func;
    1090             : static int old_newline_ctype;
    1091             : static rl_command_func_t *old_newline_func;
    1092             : 
    1093             : static unsigned char delim_char;
    1094             : 
    1095             : static void
    1096           0 : set_eol_delim (c)
    1097             :      int c;
    1098             : {
    1099           0 :   Keymap cmap;
    1100             : 
    1101           0 :   if (bash_readline_initialized == 0)
    1102           0 :     initialize_readline ();
    1103           0 :   cmap = rl_get_keymap ();
    1104             : 
    1105             :   /* Change newline to self-insert */
    1106           0 :   old_newline_ctype = cmap[RETURN].type;
    1107           0 :   old_newline_func =  cmap[RETURN].function;
    1108           0 :   cmap[RETURN].type = ISFUNC;
    1109           0 :   cmap[RETURN].function = rl_insert;
    1110             : 
    1111             :   /* Bind the delimiter character to accept-line. */
    1112           0 :   old_delim_ctype = cmap[c].type;
    1113           0 :   old_delim_func = cmap[c].function;
    1114           0 :   cmap[c].type = ISFUNC;
    1115           0 :   cmap[c].function = rl_newline;
    1116             : 
    1117           0 :   delim_char = c;
    1118           0 : }
    1119             : 
    1120             : static void
    1121           0 : reset_eol_delim (cp)
    1122             :      char *cp;
    1123             : {
    1124           0 :   Keymap cmap;
    1125             : 
    1126           0 :   cmap = rl_get_keymap ();
    1127             : 
    1128           0 :   cmap[RETURN].type = old_newline_ctype;
    1129           0 :   cmap[RETURN].function = old_newline_func;
    1130             : 
    1131           0 :   cmap[delim_char].type = old_delim_ctype;
    1132           0 :   cmap[delim_char].function = old_delim_func;
    1133           0 : }
    1134             : #endif

Generated by: LCOV version 1.14.0.6.4058