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

📄 redir.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 3 页
字号:
/* redir.c -- Functions to perform input and output redirection. *//* Copyright (C) 1997-2009 Free Software Foundation, Inc.   This file is part of GNU Bash, the Bourne Again SHell.   Bash is free software: you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation, either version 3 of the License, or   (at your option) any later version.   Bash is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with Bash.  If not, see <http://www.gnu.org/licenses/>.*/#include "config.h"#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)  #pragma alloca#endif /* _AIX && RISC6000 && !__GNUC__ */#include <stdio.h>#include "bashtypes.h"#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)#  include <sys/file.h>#endif#include "filecntl.h"#include "posixstat.h"#if defined (HAVE_UNISTD_H)#  include <unistd.h>#endif#include <errno.h>#if !defined (errno)extern int errno;#endif#include "bashansi.h"#include "bashintl.h"#include "memalloc.h"#define NEED_FPURGE_DECL#include "shell.h"#include "flags.h"#include "execute_cmd.h"#include "redir.h"#if defined (BUFFERED_INPUT)#  include "input.h"#endif#define SHELL_FD_BASE	10int expanding_redir;extern int posixly_correct;extern int last_command_exit_value;extern REDIRECT *redirection_undo_list;extern REDIRECT *exec_redirection_undo_list;/* Static functions defined and used in this file. */static void add_exec_redirect __P((REDIRECT *));static int add_undo_redirect __P((int, enum r_instruction, int));static int add_undo_close_redirect __P((int));static int expandable_redirection_filename __P((REDIRECT *));static int stdin_redirection __P((enum r_instruction, int));static int undoablefd __P((int));static int do_redirection_internal __P((REDIRECT *, int));static int write_here_document __P((int, WORD_DESC *));static int write_here_string __P((int, WORD_DESC *));static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));static int redir_special_open __P((int, char *, int, int, enum r_instruction));static int noclobber_open __P((char *, int, int, enum r_instruction));static int redir_open __P((char *, int, int, enum r_instruction));static int redir_varassign __P((REDIRECT *, int));static int redir_varvalue __P((REDIRECT *));/* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to   a new redirection and when creating the redirection undo list. */static REDIRECTEE rd;/* Set to errno when a here document cannot be created for some reason.   Used to print a reasonable error message. */static int heredoc_errno;#define REDIRECTION_ERROR(r, e, fd) \do { \  if ((r) < 0) \    { \      if (fd >= 0) \	close (fd); \      last_command_exit_value = EXECUTION_FAILURE;\      return ((e) == 0 ? EINVAL : (e));\    } \} while (0)voidredirection_error (temp, error)     REDIRECT *temp;     int error;{  char *filename, *allocname;  int oflags;  allocname = 0;  if (temp->rflags & REDIR_VARASSIGN)    filename = savestring (temp->redirector.filename->word);  else if (temp->redirector.dest < 0)    /* This can happen when read_token_word encounters overflow, like in       exec 4294967297>x */    filename = _("file descriptor out of range");#ifdef EBADF  /* This error can never involve NOCLOBBER */  else if (error != NOCLOBBER_REDIRECT && temp->redirector.dest >= 0 && error == EBADF)    {      /* If we're dealing with two file descriptors, we have to guess about         which one is invalid; in the cases of r_{duplicating,move}_input and         r_{duplicating,move}_output we're here because dup2() failed. */      switch (temp->instruction)        {        case r_duplicating_input:        case r_duplicating_output:        case r_move_input:        case r_move_output:	  filename = allocname = itos (temp->redirectee.dest);	  break;	case r_duplicating_input_word:	  if (temp->redirector.dest == 0)	/* Guess */	    filename = temp->redirectee.filename->word;	/* XXX */	  else	    filename = allocname = itos (temp->redirector.dest);	  break;	case r_duplicating_output_word:	  if (temp->redirector.dest == 1)	/* Guess */	    filename = temp->redirectee.filename->word;	/* XXX */	  else	    filename = allocname = itos (temp->redirector.dest);	  break;	default:	  filename = allocname = itos (temp->redirector.dest);	  break;        }    }#endif  else if (expandable_redirection_filename (temp))    {expandable_filename:      if (posixly_correct && interactive_shell == 0)	{	  oflags = temp->redirectee.filename->flags;	  temp->redirectee.filename->flags |= W_NOGLOB;	}      filename = allocname = redirection_expand (temp->redirectee.filename);      if (posixly_correct && interactive_shell == 0)	temp->redirectee.filename->flags = oflags;      if (filename == 0)	filename = temp->redirectee.filename->word;    }  else if (temp->redirectee.dest < 0)    filename = "file descriptor out of range";  else    filename = allocname = itos (temp->redirectee.dest);  switch (error)    {    case AMBIGUOUS_REDIRECT:      internal_error (_("%s: ambiguous redirect"), filename);      break;    case NOCLOBBER_REDIRECT:      internal_error (_("%s: cannot overwrite existing file"), filename);      break;#if defined (RESTRICTED_SHELL)    case RESTRICTED_REDIRECT:      internal_error (_("%s: restricted: cannot redirect output"), filename);      break;#endif /* RESTRICTED_SHELL */    case HEREDOC_REDIRECT:      internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));      break;    case BADVAR_REDIRECT:      internal_error (_("%s: cannot assign fd to variable"), filename);      break;    default:      internal_error ("%s: %s", filename, strerror (error));      break;    }  FREE (allocname);}/* Perform the redirections on LIST.  If flags & RX_ACTIVE, then actually   make input and output file descriptors, otherwise just do whatever is   neccessary for side effecting.  flags & RX_UNDOABLE says to remember   how to undo the redirections later, if non-zero.  If flags & RX_CLEXEC   is non-zero, file descriptors opened in do_redirection () have their   close-on-exec flag set. */intdo_redirections (list, flags)     REDIRECT *list;     int flags;{  int error;  REDIRECT *temp;  if (flags & RX_UNDOABLE)    {      if (redirection_undo_list)	{	  dispose_redirects (redirection_undo_list);	  redirection_undo_list = (REDIRECT *)NULL;	}      if (exec_redirection_undo_list)	dispose_exec_redirects ();    }  for (temp = list; temp; temp = temp->next)    {      error = do_redirection_internal (temp, flags);      if (error)	{	  redirection_error (temp, error);	  return (error);	}    }  return (0);}/* Return non-zero if the redirection pointed to by REDIRECT has a   redirectee.filename that can be expanded. */static intexpandable_redirection_filename (redirect)     REDIRECT *redirect;{  switch (redirect->instruction)    {    case r_output_direction:    case r_appending_to:    case r_input_direction:    case r_inputa_direction:    case r_err_and_out:    case r_append_err_and_out:    case r_input_output:    case r_output_force:    case r_duplicating_input_word:    case r_duplicating_output_word:    case r_move_input_word:    case r_move_output_word:      return 1;    default:      return 0;    }}/* Expand the word in WORD returning a string.  If WORD expands to   multiple words (or no words), then return NULL. */char *redirection_expand (word)     WORD_DESC *word;{  char *result;  WORD_LIST *tlist1, *tlist2;  WORD_DESC *w;  w = copy_word (word);  if (posixly_correct)    w->flags |= W_NOSPLIT;  tlist1 = make_word_list (w, (WORD_LIST *)NULL);  expanding_redir = 1;  tlist2 = expand_words_no_vars (tlist1);  expanding_redir = 0;  dispose_words (tlist1);  if (!tlist2 || tlist2->next)    {      /* We expanded to no words, or to more than a single word.	 Dispose of the word list and return NULL. */      if (tlist2)	dispose_words (tlist2);      return ((char *)NULL);    }  result = string_list (tlist2);  /* XXX savestring (tlist2->word->word)? */  dispose_words (tlist2);  return (result);}static intwrite_here_string (fd, redirectee)     int fd;     WORD_DESC *redirectee;{  char *herestr;  int herelen, n, e;  expanding_redir = 1;  herestr = expand_string_to_string (redirectee->word, 0);  expanding_redir = 0;  herelen = STRLEN (herestr);  n = write (fd, herestr, herelen);  if (n == herelen)    {      n = write (fd, "\n", 1);      herelen = 1;    }  e = errno;  FREE (herestr);  if (n != herelen)    {      if (e == 0)	e = ENOSPC;      return e;    }  return 0;}  /* Write the text of the here document pointed to by REDIRECTEE to the file   descriptor FD, which is already open to a temp file.  Return 0 if the   write is successful, otherwise return errno. */static intwrite_here_document (fd, redirectee)     int fd;     WORD_DESC *redirectee;{  char *document;  int document_len, fd2;  FILE *fp;  register WORD_LIST *t, *tlist;  /* Expand the text if the word that was specified had     no quoting.  The text that we expand is treated     exactly as if it were surrounded by double quotes. */  if (redirectee->flags & W_QUOTED)    {      document = redirectee->word;      document_len = strlen (document);      /* Set errno to something reasonable if the write fails. */      if (write (fd, document, document_len) < document_len)	{	  if (errno == 0)	    errno = ENOSPC;	  return (errno);	}      else	return 0;    }  expanding_redir = 1;  tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);  expanding_redir = 0;  if (tlist)    {      /* Try using buffered I/O (stdio) and writing a word	 at a time, letting stdio do the work of buffering	 for us rather than managing our own strings.  Most	 stdios are not particularly fast, however -- this	 may need to be reconsidered later. */      if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)	{	  if (fd2 >= 0)	    close (fd2);	  return (errno);	}      errno = 0;      for (t = tlist; t; t = t->next)	{	  /* This is essentially the body of	     string_list_internal expanded inline. */	  document = t->word->word;	  document_len = strlen (document);	  if (t != tlist)	    putc (' ', fp);	/* separator */	  fwrite (document, document_len, 1, fp);	  if (ferror (fp))	    {	      if (errno == 0)		errno = ENOSPC;	      fd2 = errno;	      fclose(fp);	      dispose_words (tlist);	      return (fd2);	    }	}      dispose_words (tlist);      if (fclose (fp) != 0)	{	  if (errno == 0)	    errno = ENOSPC;	  return (errno);	}    }  return 0;}/* Create a temporary file holding the text of the here document pointed to   by REDIRECTEE, and return a file descriptor open for reading to the temp   file.  Return -1 on any error, and make sure errno is set appropriately. */static inthere_document_to_fd (redirectee, ri)     WORD_DESC *redirectee;     enum r_instruction ri;{  char *filename;  int r, fd, fd2;  fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename);  /* If we failed for some reason other than the file existing, abort */  if (fd < 0)    {      FREE (filename);      return (fd);    }  errno = r = 0;		/* XXX */  /* write_here_document returns 0 on success, errno on failure. */  if (redirectee->word)    r = (ri != r_reading_string) ? write_here_document (fd, redirectee)				 : write_here_string (fd, redirectee);

⌨️ 快捷键说明

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