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

📄 redir.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 3 页
字号:
	   * both sh and ksh leave the file descriptors open across execs.	   * The Posix standard mentions only the exec builtin.	   */	  if ((flags & RX_CLEXEC) && (redirector > 2))	    SET_CLOSE_ON_EXEC (redirector);	}      if (fd != redirector)	{#if defined (BUFFERED_INPUT)	  if (INPUT_REDIRECT (ri))	    close_buffered_fd (fd);	  else#endif /* !BUFFERED_INPUT */	    close (fd);		/* Don't close what we just opened! */	}      /* If we are hacking both stdout and stderr, do the stderr	 redirection here.  XXX - handle {var} here? */      if (ri == r_err_and_out || ri == r_append_err_and_out)	{	  if (flags & RX_ACTIVE)	    {	      if (flags & RX_UNDOABLE)		add_undo_redirect (2, ri, -1);	      if (dup2 (1, 2) < 0)		return (errno);	    }	}      break;    case r_reading_until:    case r_deblank_reading_until:    case r_reading_string:      /* REDIRECTEE is a pointer to a WORD_DESC containing the text of	 the new input.  Place it in a temporary file. */      if (redirectee)	{	  fd = here_document_to_fd (redirectee, ri);	  if (fd < 0)	    {	      heredoc_errno = errno;	      return (HEREDOC_REDIRECT);	    }	  if (redirect->rflags & REDIR_VARASSIGN)	    {	      redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE);		/* XXX try this for now */	      r = errno;	      if (redirector < 0)		sys_error (_("redirection error: cannot duplicate fd"));	      REDIRECTION_ERROR (redirector, r, fd);	    }	  if (flags & RX_ACTIVE)	    {	      if (flags & RX_UNDOABLE)	        {		  /* Only setup to undo it if the thing to undo is active. */		  if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))		    r = add_undo_redirect (redirector, ri, -1);		  else		    r = add_undo_close_redirect (redirector);		  if (r < 0 && (redirect->rflags & REDIR_VARASSIGN))		    close (redirector);		  REDIRECTION_ERROR (r, errno, fd);	        }#if defined (BUFFERED_INPUT)	      check_bash_input (redirector);#endif	      if (redirect->rflags & REDIR_VARASSIGN)		{		  if ((r = redir_varassign (redirect, redirector)) < 0)		    {		      close (redirector);		      close (fd);		      return (r);	/* XXX */		    }		}	      else if (fd != redirector && dup2 (fd, redirector) < 0)		{		  r = errno;		  close (fd);		  return (r);		}#if defined (BUFFERED_INPUT)	      duplicate_buffered_stream (fd, redirector);#endif	      if ((flags & RX_CLEXEC) && (redirector > 2))		SET_CLOSE_ON_EXEC (redirector);	    }	  if (fd != redirector)#if defined (BUFFERED_INPUT)	    close_buffered_fd (fd);#else	    close (fd);#endif	}      break;    case r_duplicating_input:    case r_duplicating_output:    case r_move_input:    case r_move_output:      if ((flags & RX_ACTIVE) && (redirect->rflags & REDIR_VARASSIGN))        {	  redirector = fcntl (redir_fd, F_DUPFD, SHELL_FD_BASE);		/* XXX try this for now */	  r = errno;	  if (redirector < 0)	    sys_error (_("redirection error: cannot duplicate fd"));	  REDIRECTION_ERROR (redirector, r, -1);        }      if ((flags & RX_ACTIVE) && (redir_fd != redirector))	{	  if (flags & RX_UNDOABLE)	    {	      /* Only setup to undo it if the thing to undo is active. */	      if (fcntl (redirector, F_GETFD, 0) != -1)		r = add_undo_redirect (redirector, ri, redir_fd);	      else		r = add_undo_close_redirect (redirector);	      if (r < 0 && (redirect->rflags & REDIR_VARASSIGN))		close (redirector);	      REDIRECTION_ERROR (r, errno, -1);	    }#if defined (BUFFERED_INPUT)	  check_bash_input (redirector);#endif	  if (redirect->rflags & REDIR_VARASSIGN)	    {	      if ((r = redir_varassign (redirect, redirector)) < 0)		{		  close (redirector);		  return (r);	/* XXX */		}	    }	  /* This is correct.  2>&1 means dup2 (1, 2); */	  else if (dup2 (redir_fd, redirector) < 0)	    return (errno);#if defined (BUFFERED_INPUT)	  if (ri == r_duplicating_input || ri == r_move_input)	    duplicate_buffered_stream (redir_fd, redirector);#endif /* BUFFERED_INPUT */	  /* First duplicate the close-on-exec state of redirectee.  dup2	     leaves the flag unset on the new descriptor, which means it	     stays open.  Only set the close-on-exec bit for file descriptors	     greater than 2 in any case, since 0-2 should always be open	     unless closed by something like `exec 2<&-'.  It should always	     be safe to set fds > 2 to close-on-exec if they're being used to	     save file descriptors < 2, since we don't need to preserve the	     state of the close-on-exec flag for those fds -- they should	     always be open. */	  /* if ((already_set || set_unconditionally) && (ok_to_set))		set_it () */#if 0	  if (((fcntl (redir_fd, F_GETFD, 0) == 1) || redir_fd < 2 || (flags & RX_CLEXEC)) &&	       (redirector > 2))#else	  if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (redir_fd < 2 && (flags & RX_INTERNAL)) || (flags & RX_CLEXEC)) &&	       (redirector > 2))#endif	    SET_CLOSE_ON_EXEC (redirector);	  /* When undoing saving of non-standard file descriptors (>=3) using	     file descriptors >= SHELL_FD_BASE, we set the saving fd to be	     close-on-exec and use a flag to decide how to set close-on-exec	     when the fd is restored. */	  if ((redirect->flags & RX_INTERNAL) && (redirect->flags & RX_SAVCLEXEC) && redirector >= 3 && redir_fd >= SHELL_FD_BASE)	    SET_OPEN_ON_EXEC (redirector);	    	  /* dup-and-close redirection */	  if (ri == r_move_input || ri == r_move_output)	    {	      xtrace_fdchk (redir_fd);	      close (redir_fd);#if defined (COPROCESS_SUPPORT)	      coproc_fdchk (redir_fd);	/* XXX - loses coproc fds */#endif	    }	}      break;    case r_close_this:      if (flags & RX_ACTIVE)	{	  if (redirect->rflags & REDIR_VARASSIGN)	    {	      redirector = redir_varvalue (redirect);	      if (redirector < 0)		return AMBIGUOUS_REDIRECT;	    }	  r = 0;	  if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))	    {	      r = add_undo_redirect (redirector, ri, -1);	      REDIRECTION_ERROR (r, errno, redirector);	    }#if defined (COPROCESS_SUPPORT)	  coproc_fdchk (redirector);#endif	  xtrace_fdchk (redirector);#if defined (BUFFERED_INPUT)	  check_bash_input (redirector);	  close_buffered_fd (redirector);#else /* !BUFFERED_INPUT */	  close (redirector);#endif /* !BUFFERED_INPUT */	}      break;    case r_duplicating_input_word:    case r_duplicating_output_word:      break;    }  return (0);}/* Remember the file descriptor associated with the slot FD,   on REDIRECTION_UNDO_LIST.  Note that the list will be reversed   before it is executed.  Any redirections that need to be undone   even if REDIRECTION_UNDO_LIST is discarded by the exec builtin   are also saved on EXEC_REDIRECTION_UNDO_LIST.  FDBASE says where to   start the duplicating.  If it's less than SHELL_FD_BASE, we're ok,   and can use SHELL_FD_BASE (-1 == don't care).  If it's >= SHELL_FD_BASE,   we have to make sure we don't use fdbase to save a file descriptor,   since we're going to use it later (e.g., make sure we don't save fd 0   to fd 10 if we have a redirection like 0<&10).  If the value of fdbase   puts the process over its fd limit, causing fcntl to fail, we try   again with SHELL_FD_BASE.  Return 0 on success, -1 on error. */static intadd_undo_redirect (fd, ri, fdbase)     int fd;     enum r_instruction ri;     int fdbase;{  int new_fd, clexec_flag;  REDIRECT *new_redirect, *closer, *dummy_redirect;  REDIRECTEE sd;  new_fd = fcntl (fd, F_DUPFD, (fdbase < SHELL_FD_BASE) ? SHELL_FD_BASE : fdbase+1);  if (new_fd < 0)    new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);  if (new_fd < 0)    {      sys_error (_("redirection error: cannot duplicate fd"));      return (-1);    }  clexec_flag = fcntl (fd, F_GETFD, 0);  sd.dest = new_fd;  rd.dest = 0;  closer = make_redirection (sd, r_close_this, rd, 0);  closer->flags |= RX_INTERNAL;  dummy_redirect = copy_redirects (closer);  sd.dest = fd;  rd.dest = new_fd;  if (fd == 0)    new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);  else    new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);  new_redirect->flags |= RX_INTERNAL;  if (clexec_flag == 0 && fd >= 3 && new_fd >= SHELL_FD_BASE)    new_redirect->flags |= RX_SAVCLEXEC;  new_redirect->next = closer;  closer->next = redirection_undo_list;  redirection_undo_list = new_redirect;  /* Save redirections that need to be undone even if the undo list     is thrown away by the `exec' builtin. */  add_exec_redirect (dummy_redirect);  /* experimental:  if we're saving a redirection to undo for a file descriptor     above SHELL_FD_BASE, add a redirection to be undone if the exec builtin     causes redirections to be discarded.  There needs to be a difference     between fds that are used to save other fds and then are the target of     user redirections and fds that are just the target of user redirections.     We use the close-on-exec flag to tell the difference; fds > SHELL_FD_BASE     that have the close-on-exec flag set are assumed to be fds used internally     to save others. */  if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)    {      sd.dest = fd;      rd.dest = new_fd;      new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);      new_redirect->flags |= RX_INTERNAL;      add_exec_redirect (new_redirect);    }  /* File descriptors used only for saving others should always be     marked close-on-exec.  Unfortunately, we have to preserve the     close-on-exec state of the file descriptor we are saving, since     fcntl (F_DUPFD) sets the new file descriptor to remain open     across execs.  If, however, the file descriptor whose state we     are saving is <= 2, we can just set the close-on-exec flag,     because file descriptors 0-2 should always be open-on-exec,     and the restore above in do_redirection() will take care of it. */  if (clexec_flag || fd < 3)    SET_CLOSE_ON_EXEC (new_fd);  else if (redirection_undo_list->flags & RX_SAVCLEXEC)    SET_CLOSE_ON_EXEC (new_fd);  return (0);}/* Set up to close FD when we are finished with the current command   and its redirections.  Return 0 on success, -1 on error. */static intadd_undo_close_redirect (fd)     int fd;{  REDIRECT *closer;  REDIRECTEE sd;  sd.dest = fd;  rd.dest = 0;  closer = make_redirection (sd, r_close_this, rd, 0);  closer->flags |= RX_INTERNAL;  closer->next = redirection_undo_list;  redirection_undo_list = closer;  return 0;}static voidadd_exec_redirect (dummy_redirect)     REDIRECT *dummy_redirect;{  dummy_redirect->next = exec_redirection_undo_list;  exec_redirection_undo_list = dummy_redirect;}/* Return 1 if the redirection specified by RI and REDIRECTOR alters the   standard input. */static intstdin_redirection (ri, redirector)     enum r_instruction ri;     int redirector;{  switch (ri)    {    case r_input_direction:    case r_inputa_direction:    case r_input_output:    case r_reading_until:    case r_deblank_reading_until:    case r_reading_string:      return (1);    case r_duplicating_input:    case r_duplicating_input_word:    case r_close_this:      return (redirector == 0);    case r_output_direction:    case r_appending_to:    case r_duplicating_output:    case r_err_and_out:    case r_append_err_and_out:    case r_output_force:    case r_duplicating_output_word:      return (0);    }  return (0);}/* Return non-zero if any of the redirections in REDIRS alter the standard   input. */intstdin_redirects (redirs)     REDIRECT *redirs;{  REDIRECT *rp;  int n;  for (n = 0, rp = redirs; rp; rp = rp->next)    if ((rp->rflags & REDIR_VARASSIGN) == 0)      n += stdin_redirection (rp->instruction, rp->redirector.dest);  return n;}/* These don't yet handle array references */static intredir_varassign (redir, fd)     REDIRECT *redir;     int fd;{  WORD_DESC *w;  SHELL_VAR *v;  w = redir->redirector.filename;  v = bind_var_to_int (w->word, fd);  if (v == 0 || readonly_p (v) || noassign_p (v))    return BADVAR_REDIRECT;  return 0;}static intredir_varvalue (redir)     REDIRECT *redir;{  SHELL_VAR *v;  char *val;  intmax_t vmax;  int i;  /* XXX - handle set -u here? */  v = find_variable (redir->redirector.filename->word);  if (v == 0 || invisible_p (v))    return -1;  val = get_variable_value (v);  if (val == 0 || *val == 0)    return -1;  if (legal_number (val, &vmax) < 0)    return -1;  i = vmax;	/* integer truncation */  return i;}

⌨️ 快捷键说明

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