LCOV - code coverage report
Current view: top level - bash-4.4.23 - eval.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 78 120 65.0 %
Date: 2020-10-29 14:49:28 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /* eval.c -- reading and evaluating commands. */
       2             : 
       3             : /* Copyright (C) 1996-2011 Free Software Foundation, Inc.
       4             : 
       5             :    This file is part of GNU Bash, the Bourne Again SHell.
       6             : 
       7             :    Bash is free software: you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation, either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    Bash is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "config.h"
      22             : 
      23             : #if defined (HAVE_UNISTD_H)
      24             : #  ifdef _MINIX
      25             : #    include <sys/types.h>
      26             : #  endif
      27             : #  include <unistd.h>
      28             : #endif
      29             : 
      30             : #include "bashansi.h"
      31             : #include <stdio.h>
      32             : 
      33             : #include <signal.h>
      34             : 
      35             : #include "bashintl.h"
      36             : 
      37             : #include "shell.h"
      38             : #include "flags.h"
      39             : #include "trap.h"
      40             : 
      41             : #include "builtins/common.h"
      42             : 
      43             : #include "input.h"
      44             : #include "execute_cmd.h"
      45             : 
      46             : #if defined (HISTORY)
      47             : #  include "bashhist.h"
      48             : #endif
      49             : 
      50             : extern int EOF_reached;
      51             : extern int indirection_level;
      52             : extern int posixly_correct;
      53             : extern int subshell_environment, running_under_emacs;
      54             : extern int last_command_exit_value, stdin_redir;
      55             : extern int need_here_doc;
      56             : extern int current_command_number, current_command_line_count, line_number;
      57             : extern int expand_aliases;
      58             : extern int rpm_requires;
      59             : extern char *ps0_prompt;
      60             : 
      61             : #if defined (HAVE_POSIX_SIGNALS)
      62             : extern sigset_t top_level_mask;
      63             : #endif
      64             : 
      65             : static void send_pwd_to_eterm __P((void));
      66             : static sighandler alrm_catcher __P((int));
      67             : 
      68             : /* Read and execute commands until EOF is reached.  This assumes that
      69             :    the input source has already been initialized. */
      70             : int
      71     9143248 : reader_loop ()
      72             : {
      73     9143248 :   int our_indirection_level;
      74     9143248 :   COMMAND * volatile current_command;
      75             : 
      76     9143248 :   USE_VAR(current_command);
      77             : 
      78     9143248 :   current_command = (COMMAND *)NULL;
      79             : 
      80     9143248 :   our_indirection_level = ++indirection_level;
      81             : 
      82   193430689 :   while (EOF_Reached == 0)
      83             :     {
      84             :       int code;
      85             : 
      86   182015598 :       code = setjmp_nosigs (top_level);
      87             : 
      88             : #if defined (PROCESS_SUBSTITUTION)
      89   182015598 :       unlink_fifo_list ();
      90             : #endif /* PROCESS_SUBSTITUTION */
      91             : 
      92             :       /* XXX - why do we set this every time through the loop?  And why do
      93             :          it if SIGINT is trapped in an interactive shell? */
      94   182015598 :       if (interactive_shell && signal_is_ignored (SIGINT) == 0)
      95           0 :         set_signal_handler (SIGINT, sigint_sighandler);
      96             : 
      97   182015598 :       if (code != NOT_JUMPED)
      98             :         {
      99     6871454 :           indirection_level = our_indirection_level;
     100             : 
     101     6871454 :           switch (code)
     102             :             {
     103             :               /* Some kind of throw to top_level has occurred. */
     104     6864193 :             case FORCE_EOF:
     105             :             case ERREXIT:
     106             :             case EXITPROG:
     107     6864193 :               current_command = (COMMAND *)NULL;
     108     6864193 :               if (exit_immediately_on_error)
     109           0 :                 variable_context = 0;   /* not in a function */
     110     6864193 :               EOF_Reached = EOF;
     111     6864193 :               goto exec_done;
     112             : 
     113        7261 :             case DISCARD:
     114             :               /* Make sure the exit status is reset to a non-zero value, but
     115             :                  leave existing non-zero values (e.g., > 128 on signal)
     116             :                  alone. */
     117        7261 :               if (last_command_exit_value == 0)
     118         155 :                 last_command_exit_value = EXECUTION_FAILURE;
     119        7261 :               if (subshell_environment)
     120             :                 {
     121          94 :                   current_command = (COMMAND *)NULL;
     122          94 :                   EOF_Reached = EOF;
     123          94 :                   goto exec_done;
     124             :                 }
     125             :               /* Obstack free command elements, etc. */
     126        7167 :               if (current_command)
     127             :                 {
     128        6999 :                   dispose_command (current_command);
     129        6999 :                   current_command = (COMMAND *)NULL;
     130             :                 }
     131             : #if defined (HAVE_POSIX_SIGNALS)
     132        7167 :               sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
     133             : #endif
     134        7167 :               break;
     135             : 
     136           0 :             default:
     137           0 :               command_error ("reader_loop", CMDERR_BADJUMP, code, 0);
     138             :             }
     139   175144144 :         }
     140             : 
     141   175151311 :       executing = 0;
     142   175151311 :       if (temporary_env)
     143           0 :         dispose_used_env_vars ();
     144             : 
     145             : #if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
     146             :       /* Attempt to reclaim memory allocated with alloca (). */
     147             :       (void) alloca (0);
     148             : #endif
     149             : 
     150   175151311 :       if (read_command () == 0)
     151             :         {
     152   172983176 :           if (interactive_shell == 0 && (read_but_dont_execute && !rpm_requires))
     153             :             {
     154           0 :               last_command_exit_value = EXECUTION_SUCCESS;
     155           0 :               dispose_command (global_command);
     156           0 :               global_command = (COMMAND *)NULL;
     157             :             }
     158   172983176 :           else if (current_command = global_command)
     159             :             {
     160    64203870 :               global_command = (COMMAND *)NULL;
     161    64203870 :               current_command_number++;
     162             : 
     163    64203870 :               executing = 1;
     164    64203870 :               stdin_redir = 0;
     165             : 
     166             :               /* If the shell is interactive, expand and display $PS0 after reading a
     167             :                  command (possibly a list or pipeline) and before executing it. */
     168    64203870 :               if (interactive && ps0_prompt)
     169             :                 {
     170           0 :                   char *ps0_string;
     171             : 
     172           0 :                   ps0_string = decode_prompt_string (ps0_prompt);
     173           0 :                   if (ps0_string && *ps0_string)
     174             :                     {
     175           0 :                       fprintf (stderr, "%s", ps0_string);
     176           0 :                       fflush (stderr);
     177             :                     }
     178           0 :                   free (ps0_string);
     179             :                 }
     180             : 
     181    64203870 :               execute_command (current_command);
     182             : 
     183    64196920 :             exec_done:
     184    64196920 :               QUIT;
     185             : 
     186    64196920 :               if (current_command)
     187             :                 {
     188    57332633 :                   dispose_command (current_command);
     189    57332633 :                   current_command = (COMMAND *)NULL;
     190             :                 }
     191             :             }
     192             :         }
     193             :       else
     194             :         {
     195             :           /* Parse error, maybe discard rest of stream if not interactive. */
     196     2167967 :           if (interactive == 0)
     197     2167967 :             EOF_Reached = EOF;
     198             :         }
     199   175144193 :       if (just_one_command)
     200           0 :         EOF_Reached = EOF;
     201             :     }
     202     9143297 :   indirection_level--;
     203     9143297 :   return (last_command_exit_value);
     204             : }
     205             : 
     206             : static sighandler
     207           0 : alrm_catcher(i)
     208             :      int i;
     209             : {
     210           0 :   printf (_("\007timed out waiting for input: auto-logout\n"));
     211           0 :   fflush (stdout);
     212           0 :   bash_logout ();       /* run ~/.bash_logout if this is a login shell */
     213           0 :   jump_to_top_level (EXITPROG);
     214             :   SIGRETURN (0);
     215             : }
     216             : 
     217             : /* Send an escape sequence to emacs term mode to tell it the
     218             :    current working directory. */
     219             : static void
     220           0 : send_pwd_to_eterm ()
     221             : {
     222           0 :   char *pwd, *f;
     223             : 
     224           0 :   f = 0;
     225           0 :   pwd = get_string_value ("PWD");
     226           0 :   if (pwd == 0)
     227           0 :     f = pwd = get_working_directory ("eterm");
     228           0 :   fprintf (stderr, "\032/%s\n", pwd);
     229           0 :   free (f);
     230           0 : }
     231             : 
     232             : /* Call the YACC-generated parser and return the status of the parse.
     233             :    Input is read from the current input stream (bash_input).  yyparse
     234             :    leaves the parsed command in the global variable GLOBAL_COMMAND.
     235             :    This is where PROMPT_COMMAND is executed. */
     236             : int
     237   275737382 : parse_command ()
     238             : {
     239   275737382 :   int r;
     240   275737382 :   char *command_to_execute;
     241             : 
     242   275737382 :   need_here_doc = 0;
     243   275737382 :   run_pending_traps ();
     244             : 
     245             :   /* Allow the execution of a random command just before the printing
     246             :      of each primary prompt.  If the shell variable PROMPT_COMMAND
     247             :      is set then the value of it is the command to execute. */
     248             :   /* The tests are a combination of SHOULD_PROMPT() and prompt_again() 
     249             :      from parse.y, which are the conditions under which the prompt is
     250             :      actually printed. */
     251   275737382 :   if (interactive && bash_input.type != st_string && parser_expanding_alias() == 0)
     252             :     {
     253           0 :       command_to_execute = get_string_value ("PROMPT_COMMAND");
     254           0 :       if (command_to_execute)
     255           0 :         execute_variable_command (command_to_execute, "PROMPT_COMMAND");
     256             : 
     257           0 :       if (running_under_emacs == 2)
     258           0 :         send_pwd_to_eterm ();   /* Yuck */
     259             :     }
     260             : 
     261   275737382 :   current_command_line_count = 0;
     262   275737382 :   r = yyparse ();
     263             : 
     264   275737214 :   if (need_here_doc)
     265          49 :     gather_here_documents ();
     266             : 
     267   275737214 :   return (r);
     268             : }
     269             : 
     270             : /* Read and parse a command, returning the status of the parse.  The command
     271             :    is left in the globval variable GLOBAL_COMMAND for use by reader_loop.
     272             :    This is where the shell timeout code is executed. */
     273             : int
     274   175151311 : read_command ()
     275             : {
     276   175151311 :   SHELL_VAR *tmout_var;
     277   175151311 :   int tmout_len, result;
     278   175151311 :   SigHandler *old_alrm;
     279             : 
     280   175151311 :   set_current_prompt_level (1);
     281   175151311 :   global_command = (COMMAND *)NULL;
     282             : 
     283             :   /* Only do timeouts if interactive. */
     284   175151311 :   tmout_var = (SHELL_VAR *)NULL;
     285   175151311 :   tmout_len = 0;
     286   175151311 :   old_alrm = (SigHandler *)NULL;
     287             : 
     288   175151311 :   if (interactive)
     289             :     {
     290           0 :       tmout_var = find_variable ("TMOUT");
     291             : 
     292           0 :       if (tmout_var && var_isset (tmout_var))
     293             :         {
     294           0 :           tmout_len = atoi (value_cell (tmout_var));
     295           0 :           if (tmout_len > 0)
     296             :             {
     297           0 :               old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
     298           0 :               alarm (tmout_len);
     299             :             }
     300             :         }
     301             :     }
     302             : 
     303   175151311 :   QUIT;
     304             : 
     305   175151311 :   current_command_line_count = 0;
     306   175151311 :   result = parse_command ();
     307             : 
     308   175151143 :   if (interactive && tmout_var && (tmout_len > 0))
     309             :     {
     310           0 :       alarm(0);
     311           0 :       set_signal_handler (SIGALRM, old_alrm);
     312             :     }
     313             : 
     314   175151143 :   return (result);
     315             : }

Generated by: LCOV version 1.14.0.6.4058