⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 execute_cmd.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 5 页
字号:
open_files (){  register int i;  int f, fd_table_size;  fd_table_size = getdtablesize ();  fprintf (stderr, "pid %ld open files:", (long)getpid ());  for (i = 3; i < fd_table_size; i++)    {      if ((f = fcntl (i, F_GETFD, 0)) != -1)	fprintf (stderr, " %d (%s)", i, f ? "close" : "open");    }  fprintf (stderr, "\n");}#endifstatic voidasync_redirect_stdin (){  int fd;  fd = open ("/dev/null", O_RDONLY);  if (fd > 0)    {      dup2 (fd, 0);      close (fd);    }  else if (fd < 0)    internal_error (_("cannot redirect standard input from /dev/null: %s"), strerror (errno));}#define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)/* Execute the command passed in COMMAND, perhaps doing it asynchrounously.   COMMAND is exactly what read_command () places into GLOBAL_COMMAND.   ASYNCHROUNOUS, if non-zero, says to do this command in the background.   PIPE_IN and PIPE_OUT are file descriptors saying where input comes   from and where it goes.  They can have the value of NO_PIPE, which means   I/O is stdin/stdout.   FDS_TO_CLOSE is a list of file descriptors to close once the child has   been forked.  This list often contains the unusable sides of pipes, etc.   EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible   return values.  Executing a command with nothing in it returns   EXECUTION_SUCCESS. */intexecute_command_internal (command, asynchronous, pipe_in, pipe_out,			  fds_to_close)     COMMAND *command;     int asynchronous;     int pipe_in, pipe_out;     struct fd_bitmap *fds_to_close;{  int exec_result, user_subshell, invert, ignore_return, was_error_trap;  REDIRECT *my_undo_list, *exec_undo_list;  volatile int last_pid;  volatile int save_line_number;#if 0  if (command == 0 || breaking || continuing || read_but_dont_execute)    return (EXECUTION_SUCCESS);#else  if (breaking || continuing)    return (last_command_exit_value);  if (command == 0 || read_but_dont_execute)    return (EXECUTION_SUCCESS);#endif  QUIT;  run_pending_traps ();#if 0  if (running_trap == 0)#endif    currently_executing_command = command;  invert = (command->flags & CMD_INVERT_RETURN) != 0;  /* If we're inverting the return value and `set -e' has been executed,     we don't want a failing command to inadvertently cause the shell     to exit. */  if (exit_immediately_on_error && invert)	/* XXX */    command->flags |= CMD_IGNORE_RETURN;	/* XXX */  exec_result = EXECUTION_SUCCESS;  /* If a command was being explicitly run in a subshell, or if it is     a shell control-structure, and it has a pipe, then we do the command     in a subshell. */  if (command->type == cm_subshell && (command->flags & CMD_NO_FORK))    return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));#if defined (COPROCESS_SUPPORT)  if (command->type == cm_coproc)    return (execute_coproc (command, pipe_in, pipe_out, fds_to_close));#endif  user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);  if (command->type == cm_subshell ||      (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) ||      (shell_control_structure (command->type) &&       (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))    {      pid_t paren_pid;      /* Fork a subshell, turn off the subshell bit, turn off job	 control and call execute_command () on the command again. */      line_number_for_err_trap = line_number;      paren_pid = make_child (savestring (make_command_string (command)),			      asynchronous);      if (paren_pid == 0)	exit (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));	/* NOTREACHED */      else	{	  close_pipes (pipe_in, pipe_out);#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)	  unlink_fifo_list ();#endif	  /* If we are part of a pipeline, and not the end of the pipeline,	     then we should simply return and let the last command in the	     pipe be waited for.  If we are not in a pipeline, or are the	     last command in the pipeline, then we wait for the subshell	     and return its exit status as usual. */	  if (pipe_out != NO_PIPE)	    return (EXECUTION_SUCCESS);	  stop_pipeline (asynchronous, (COMMAND *)NULL);	  if (asynchronous == 0)	    {	      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;	      invert = (command->flags & CMD_INVERT_RETURN) != 0;	      ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;	      exec_result = wait_for (paren_pid);	      /* If we have to, invert the return value. */	      if (invert)		exec_result = ((exec_result == EXECUTION_SUCCESS)				? EXECUTION_FAILURE				: EXECUTION_SUCCESS);	      last_command_exit_value = exec_result;	      if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)		{		  save_line_number = line_number;		  line_number = line_number_for_err_trap;		  run_error_trap ();		  line_number = save_line_number;		}	      if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)		{		  run_pending_traps ();		  jump_to_top_level (ERREXIT);		}	      return (last_command_exit_value);	    }	  else	    {	      DESCRIBE_PID (paren_pid);	      run_pending_traps ();	      return (EXECUTION_SUCCESS);	    }	}    }#if defined (COMMAND_TIMING)  if (command->flags & CMD_TIME_PIPELINE)    {      if (asynchronous)	{	  command->flags |= CMD_FORCE_SUBSHELL;	  exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);	}      else	{	  exec_result = time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close);#if 0	  if (running_trap == 0)#endif	    currently_executing_command = (COMMAND *)NULL;	}      return (exec_result);    }#endif /* COMMAND_TIMING */  if (shell_control_structure (command->type) && command->redirects)    stdin_redir = stdin_redirects (command->redirects);  /* Handle WHILE FOR CASE etc. with redirections.  (Also '&' input     redirection.)  */  if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0)    {      cleanup_redirects (redirection_undo_list);      redirection_undo_list = (REDIRECT *)NULL;      dispose_exec_redirects ();      return (last_command_exit_value = EXECUTION_FAILURE);    }  if (redirection_undo_list)    {      /* XXX - why copy here? */      my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);      dispose_redirects (redirection_undo_list);      redirection_undo_list = (REDIRECT *)NULL;    }  else    my_undo_list = (REDIRECT *)NULL;  if (exec_redirection_undo_list)    {      /* XXX - why copy here? */      exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list);      dispose_redirects (exec_redirection_undo_list);      exec_redirection_undo_list = (REDIRECT *)NULL;    }  else    exec_undo_list = (REDIRECT *)NULL;  if (my_undo_list || exec_undo_list)    begin_unwind_frame ("loop_redirections");  if (my_undo_list)    add_unwind_protect ((Function *)cleanup_redirects, my_undo_list);  if (exec_undo_list)    add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;  QUIT;  switch (command->type)    {    case cm_simple:      {	save_line_number = line_number;	/* We can't rely on variables retaining their values across a	   call to execute_simple_command if a longjmp occurs as the	   result of a `return' builtin.  This is true for sure with gcc. */#if defined (RECYCLES_PIDS)	last_made_pid = NO_PID;#endif	last_pid = last_made_pid;	was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;	if (ignore_return && command->value.Simple)	  command->value.Simple->flags |= CMD_IGNORE_RETURN;	if (command->flags & CMD_STDIN_REDIR)	  command->value.Simple->flags |= CMD_STDIN_REDIR;	line_number_for_err_trap = line_number = command->value.Simple->line;	exec_result =	  execute_simple_command (command->value.Simple, pipe_in, pipe_out,				  asynchronous, fds_to_close);	line_number = save_line_number;	/* The temporary environment should be used for only the simple	   command immediately following its definition. */	dispose_used_env_vars ();#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)	/* Reclaim memory allocated with alloca () on machines which	   may be using the alloca emulation code. */	(void) alloca (0);#endif /* (ultrix && mips) || C_ALLOCA */	/* If we forked to do the command, then we must wait_for ()	   the child. */	/* XXX - this is something to watch out for if there are problems	   when the shell is compiled without job control. */	if (already_making_children && pipe_out == NO_PIPE &&	    last_made_pid != last_pid)	  {	    stop_pipeline (asynchronous, (COMMAND *)NULL);	    if (asynchronous)	      {		DESCRIBE_PID (last_made_pid);	      }	    else#if !defined (JOB_CONTROL)	      /* Do not wait for asynchronous processes started from		 startup files. */	    if (last_made_pid != last_asynchronous_pid)#endif	    /* When executing a shell function that executes other	       commands, this causes the last simple command in	       the function to be waited for twice.  This also causes	       subshells forked to execute builtin commands (e.g., in	       pipelines) to be waited for twice. */	      exec_result = wait_for (last_made_pid);	  }      }      /* 2009/02/13 -- pipeline failure is processed elsewhere.  This handles	 only the failure of a simple command. */      if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)	{	  last_command_exit_value = exec_result;	  line_number = line_number_for_err_trap;	  run_error_trap ();	  line_number = save_line_number;	}      if (ignore_return == 0 && invert == 0 &&	  ((posixly_correct && interactive == 0 && special_builtin_failed) ||	   (exit_immediately_on_error && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)))	{	  last_command_exit_value = exec_result;	  run_pending_traps ();	  jump_to_top_level (ERREXIT);	}      break;    case cm_for:      if (ignore_return)	command->value.For->flags |= CMD_IGNORE_RETURN;      exec_result = execute_for_command (command->value.For);      break;#if defined (ARITH_FOR_COMMAND)    case cm_arith_for:      if (ignore_return)	command->value.ArithFor->flags |= CMD_IGNORE_RETURN;      exec_result = execute_arith_for_command (command->value.ArithFor);      break;#endif#if defined (SELECT_COMMAND)    case cm_select:      if (ignore_return)	command->value.Select->flags |= CMD_IGNORE_RETURN;      exec_result = execute_select_command (command->value.Select);      break;#endif    case cm_case:      if (ignore_return)	command->value.Case->flags |= CMD_IGNORE_RETURN;      exec_result = execute_case_command (command->value.Case);      break;    case cm_while:      if (ignore_return)	command->value.While->flags |= CMD_IGNORE_RETURN;      exec_result = execute_while_command (command->value.While);      break;    case cm_until:      if (ignore_return)	command->value.While->flags |= CMD_IGNORE_RETURN;      exec_result = execute_until_command (command->value.While);      break;    case cm_if:      if (ignore_return)	command->value.If->flags |= CMD_IGNORE_RETURN;      exec_result = execute_if_command (command->value.If);      break;    case cm_group:      /* This code can be executed from either of two paths: an explicit	 '{}' command, or via a function call.  If we are executed via a	 function call, we have already taken care of the function being	 executed in the background (down there in execute_simple_command ()),	 and this command should *not* be marked as asynchronous.  If we	 are executing a regular '{}' group command, and asynchronous == 1,	 we must want to execute the whole command in the background, so we	 need a subshell, and we want the stuff executed in that subshell	 (this group command) to be executed in the foreground of that	 subshell (i.e. there will not be *another* subshell forked).	 What we do is to force a subshell if asynchronous, and then call	 execute_command_internal again with asynchronous still set to 1,	 but with the original group command, so the printed command will	 look right.	 The code above that handles forking off subshells will note that	 both subshell and async are on, and turn off async in the child	 after forking the subshell (but leave async set in the parent, so	 the normal call to describe_pid is made).  This turning off	 async is *crucial*; if it is not done, this will fall into an	 infinite loop of executions through this spot in subshell after	 subshell until the process limit is exhausted. */      if (asynchronous)	{	  command->flags |= CMD_FORCE_SUBSHELL;	  exec_result =	    execute_command_internal (command, 1, pipe_in, pipe_out,				      fds_to_close);	}      else	{	  if (ignore_return && command->value.Group->command)	    command->value.Group->command->flags |= CMD_IGNORE_RETURN;	  exec_result =	    execute_command_internal (command->value.Group->command,				      asynchronous, pipe_in, pipe_out,				      fds_to_close);	}      break;    case cm_connection:      exec_result = execute_connection (command, asynchronous,					pipe_in, pipe_out, fds_to_close);      break;#if defined (DPAREN_ARITHMETIC)    case cm_arith:      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;      if (ignore_return)	command->value.Arith->flags |= CMD_IGNORE_RETURN;      line_number_for_err_trap = save_line_number = line_number;      exec_result = execute_arith_command (command->value.Arith);      line_number = save_line_number;      if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)	{	  last_command_exit_value = exec_result;	  save_line_number = line_number;	  line_number = line_number_for_err_trap;	  run_error_trap ();	  line_number = save_line_number;	}      if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)	{	  last_command_exit_value = exec_result;	  run_pending_traps ();	  jump_to_top_level (ERREXIT);	}      break;#endif#if defined (COND_COMMAND)    case cm_cond:      was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;      if (ignore_return)	command->value.Cond->flags |= CMD_IGNORE_RETURN;      line_number_for_err_trap = save_line_number = line_number;      exec_result = execute_cond_command (command->value.Cond);      line_number = save_line_number;      if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)	{	  last_command_exit_value = exec_result;	  save_line_number = line_number;	  line_number = line_number_for_err_trap;	  run_error_trap ();	  line_number = save_line_number;	}      if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)	{	  last_command_exit_value = exec_result;	  run_pending_traps ();	  jump_to_top_level (ERREXIT);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -