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

📄 execute_cmd.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 5 页
字号:
coproc_fdrestore (cp)     struct coproc *cp;{  cp->c_rfd = cp->c_rsave;  cp->c_wfd = cp->c_wsave;}voidcoproc_pidchk (pid, status)     pid_t pid;{  struct coproc *cp;  cp = getcoprocbypid (pid);#if 0  if (cp)    itrace("coproc_pidchk: pid %d has died", pid);#endif  if (cp)    {      cp->c_status = status;      cp->c_flags |= COPROC_DEAD;      cp->c_flags &= ~COPROC_RUNNING;#if 0      coproc_dispose (cp);#endif    }}voidcoproc_setvars (cp)     struct coproc *cp;{  SHELL_VAR *v;  char *namevar, *t;  int l;#if defined (ARRAY_VARS)  arrayind_t ind;#endif  if (cp->c_name == 0)    return;  l = strlen (cp->c_name);  namevar = xmalloc (l + 16);#if defined (ARRAY_VARS)  v = find_variable (cp->c_name);  if (v == 0)    v = make_new_array_variable (cp->c_name);  if (array_p (v) == 0)    v = convert_var_to_array (v);  t = itos (cp->c_rfd);  ind = 0;  v = bind_array_variable (cp->c_name, ind, t, 0);  free (t);  t = itos (cp->c_wfd);  ind = 1;  bind_array_variable (cp->c_name, ind, t, 0);  free (t);#else  sprintf (namevar, "%s_READ", cp->c_name);  t = itos (cp->c_rfd);  bind_variable (namevar, t, 0);  free (t);  sprintf (namevar, "%s_WRITE", cp->c_name);  t = itos (cp->c_wfd);  bind_variable (namevar, t, 0);  free (t);#endif  sprintf (namevar, "%s_PID", cp->c_name);  t = itos (cp->c_pid);  bind_variable (namevar, t, 0);  free (t);  free (namevar);}voidcoproc_unsetvars (cp)     struct coproc *cp;{  int l;  char *namevar;  if (cp->c_name == 0)    return;  l = strlen (cp->c_name);  namevar = xmalloc (l + 16);  sprintf (namevar, "%s_PID", cp->c_name);  unbind_variable (namevar);  #if defined (ARRAY_VARS)  unbind_variable (cp->c_name);#else  sprintf (namevar, "%s_READ", cp->c_name);  unbind_variable (namevar);  sprintf (namevar, "%s_WRITE", cp->c_name);  unbind_variable (namevar);#endif    free (namevar);}static intexecute_coproc (command, pipe_in, pipe_out, fds_to_close)     COMMAND *command;     int pipe_in, pipe_out;     struct fd_bitmap *fds_to_close;{  int rpipe[2], wpipe[2], estat;  pid_t coproc_pid;  Coproc *cp;  char *tcmd;  /* XXX -- will require changes to handle multiple coprocs */  if (sh_coproc.c_pid != NO_PID)    {#if 0      internal_error ("execute_coproc: coproc [%d:%s] already exists", sh_coproc.c_pid, sh_coproc.c_name);      return (last_command_exit_value = EXECUTION_FAILURE);#else      internal_warning ("execute_coproc: coproc [%d:%s] still exists", sh_coproc.c_pid, sh_coproc.c_name);#endif    }  coproc_init (&sh_coproc);  command_string_index = 0;  tcmd = make_command_string (command);  sh_openpipe ((int *)&rpipe);	/* 0 = parent read, 1 = child write */  sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */  coproc_pid = make_child (savestring (tcmd), 1);  if (coproc_pid == 0)    {      close (rpipe[0]);      close (wpipe[1]);      estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close);      fflush (stdout);      fflush (stderr);      exit (estat);    }  close (rpipe[1]);  close (wpipe[0]);  cp = coproc_alloc (command->value.Coproc->name, coproc_pid);  cp->c_rfd = rpipe[0];  cp->c_wfd = wpipe[1];  SET_CLOSE_ON_EXEC (cp->c_rfd);  SET_CLOSE_ON_EXEC (cp->c_wfd);  coproc_setvars (cp);#if 0  itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command);#endif  close_pipes (pipe_in, pipe_out);#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)  unlink_fifo_list ();#endif  stop_pipeline (1, (COMMAND *)NULL);  DESCRIBE_PID (coproc_pid);  run_pending_traps ();  return (EXECUTION_SUCCESS);}#endifstatic voidrestore_stdin (s)     int s;{  dup2 (s, 0);  close (s);}/* Catch-all cleanup function for lastpipe code for unwind-protects */static voidlastpipe_cleanup (s)     int s;{  unfreeze_jobs_list ();}static intexecute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)     COMMAND *command;     int asynchronous, pipe_in, pipe_out;     struct fd_bitmap *fds_to_close;{  int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result;  int lstdin, lastpipe_flag, lastpipe_jid;  COMMAND *cmd;  struct fd_bitmap *fd_bitmap;  pid_t lastpid;#if defined (JOB_CONTROL)  sigset_t set, oset;  BLOCK_CHILD (set, oset);#endif /* JOB_CONTROL */  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;  prev = pipe_in;  cmd = command;  while (cmd && cmd->type == cm_connection &&	 cmd->value.Connection && cmd->value.Connection->connector == '|')    {      /* Make a pipeline between the two commands. */      if (pipe (fildes) < 0)	{	  sys_error (_("pipe error"));#if defined (JOB_CONTROL)	  terminate_current_pipeline ();	  kill_current_pipeline ();	  UNBLOCK_CHILD (oset);#endif /* JOB_CONTROL */	  last_command_exit_value = EXECUTION_FAILURE;	  /* The unwind-protects installed below will take care	     of closing all of the open file descriptors. */	  throw_to_top_level ();	  return (EXECUTION_FAILURE);	/* XXX */	}      /* Here is a problem: with the new file close-on-exec	 code, the read end of the pipe (fildes[0]) stays open	 in the first process, so that process will never get a	 SIGPIPE.  There is no way to signal the first process	 that it should close fildes[0] after forking, so it	 remains open.  No SIGPIPE is ever sent because there	 is still a file descriptor open for reading connected	 to the pipe.  We take care of that here.  This passes	 around a bitmap of file descriptors that must be	 closed after making a child process in execute_simple_command. */      /* We need fd_bitmap to be at least as big as fildes[0].	 If fildes[0] is less than fds_to_close->size, then	 use fds_to_close->size. */      new_bitmap_size = (fildes[0] < fds_to_close->size)				? fds_to_close->size				: fildes[0] + 8;      fd_bitmap = new_fd_bitmap (new_bitmap_size);      /* Now copy the old information into the new bitmap. */      xbcopy ((char *)fds_to_close->bitmap, (char *)fd_bitmap->bitmap, fds_to_close->size);      /* And mark the pipe file descriptors to be closed. */      fd_bitmap->bitmap[fildes[0]] = 1;      /* In case there are pipe or out-of-processes errors, we	 want all these file descriptors to be closed when	 unwind-protects are run, and the storage used for the	 bitmaps freed up. */      begin_unwind_frame ("pipe-file-descriptors");      add_unwind_protect (dispose_fd_bitmap, fd_bitmap);      add_unwind_protect (close_fd_bitmap, fd_bitmap);      if (prev >= 0)	add_unwind_protect (close, prev);      dummyfd = fildes[1];      add_unwind_protect (close, dummyfd);#if defined (JOB_CONTROL)      add_unwind_protect (restore_signal_mask, &oset);#endif /* JOB_CONTROL */      if (ignore_return && cmd->value.Connection->first)	cmd->value.Connection->first->flags |= CMD_IGNORE_RETURN;      execute_command_internal (cmd->value.Connection->first, asynchronous,				prev, fildes[1], fd_bitmap);      if (prev >= 0)	close (prev);      prev = fildes[0];      close (fildes[1]);      dispose_fd_bitmap (fd_bitmap);      discard_unwind_frame ("pipe-file-descriptors");      cmd = cmd->value.Connection->second;    }  lastpid = last_made_pid;  /* Now execute the rightmost command in the pipeline.  */  if (ignore_return && cmd)    cmd->flags |= CMD_IGNORE_RETURN;  lastpipe_flag = 0;  begin_unwind_frame ("lastpipe-exec");  lstdin = -1;  /* If the `lastpipe' option is set with shopt, and job control is not     enabled, execute the last element of non-async pipelines in the     current shell environment. */  if (lastpipe_opt && job_control == 0 && asynchronous == 0 && pipe_out == NO_PIPE && prev > 0)    {      lstdin = move_to_high_fd (0, 0, 255);      if (lstdin > 0)	{	  do_piping (prev, pipe_out);	  prev = NO_PIPE;	  add_unwind_protect (restore_stdin, lstdin);	  lastpipe_flag = 1;	  freeze_jobs_list ();	  lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL);	/* XXX */	  add_unwind_protect (lastpipe_cleanup, lastpipe_jid);	}      cmd->flags |= CMD_LASTPIPE;    }	    if (prev >= 0)    add_unwind_protect (close, prev);  exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);  if (lstdin > 0)    restore_stdin (lstdin);  if (prev >= 0)    close (prev);#if defined (JOB_CONTROL)  UNBLOCK_CHILD (oset);#endif  QUIT;  if (lastpipe_flag)    {#if defined (JOB_CONTROL)      append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid);#endif      lstdin = wait_for (lastpid);#if defined (JOB_CONTROL)      exec_result = job_exit_status (lastpipe_jid);#endif      unfreeze_jobs_list ();    }  discard_unwind_frame ("lastpipe-exec");  return (exec_result);}static intexecute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)     COMMAND *command;     int asynchronous, pipe_in, pipe_out;     struct fd_bitmap *fds_to_close;{  COMMAND *tc, *second;  int ignore_return, exec_result, was_error_trap, invert;  volatile int save_line_number;  ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;  switch (command->value.Connection->connector)    {    /* Do the first command asynchronously. */    case '&':      tc = command->value.Connection->first;      if (tc == 0)	return (EXECUTION_SUCCESS);      if (ignore_return)	tc->flags |= CMD_IGNORE_RETURN;      tc->flags |= CMD_AMPERSAND;      /* If this shell was compiled without job control support,	 if we are currently in a subshell via `( xxx )', or if job	 control is not active then the standard input for an	 asynchronous command is forced to /dev/null. */#if defined (JOB_CONTROL)      if ((subshell_environment || !job_control) && !stdin_redir)#else      if (!stdin_redir)#endif /* JOB_CONTROL */	tc->flags |= CMD_STDIN_REDIR;      exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close);      QUIT;      if (tc->flags & CMD_STDIN_REDIR)	tc->flags &= ~CMD_STDIN_REDIR;      second = command->value.Connection->second;      if (second)	{	  if (ignore_return)	    second->flags |= CMD_IGNORE_RETURN;	  exec_result = execute_command_internal (second, asynchronous, pipe_in, pipe_out, fds_to_close);	}      break;    /* Just call execute command on both sides. */    case ';':      if (ignore_return)	{	  if (command->value.Connection->first)	    command->value.Connection->first->flags |= CMD_IGNORE_RETURN;	  if (command->value.Connection->second)	    command->value.Connection->second->flags |= CMD_IGNORE_RETURN;	}      executing_list++;      QUIT;      execute_command (command->value.Connection->first);      QUIT;      exec_result = execute_command_internal (command->value.Connection->second,				      asynchronous, pipe_in, pipe_out,				      fds_to_close);      executing_list--;      break;    case '|':      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;      line_number_for_err_trap = line_number;      exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);      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;    case AND_AND:    case OR_OR:      if (asynchronous)	{	  /* If we have something like `a && b &' or `a || b &', run the	     && or || stuff in a subshell.  Force a subshell and just call	     execute_command_internal again.  Leave asynchronous on	     so that we get a report from the parent shell about the	     background job. */	  command->flags |= CMD_FORCE_SUBSHELL;	  exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);	  break;	}      /* Execute the first command.  If the result of that is successful	 and the connector is AND_AND, or the result is not succes

⌨️ 快捷键说明

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