Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / redir.c
diff --git a/redir.c b/redir.c
index 6fdcc94..e420011 100644 (file)
--- a/redir.c
+++ b/redir.c
@@ -1,6 +1,6 @@
 /* redir.c -- Functions to perform input and output redirection. */
 
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2002 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -66,14 +66,15 @@ static int stdin_redirection __P((enum r_instruction, int));
 static int do_redirection_internal __P((REDIRECT *, int, int, int));
 
 static int write_here_document __P((int, WORD_DESC *));
-static int here_document_to_fd __P((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));
 
-/* Spare redirector used when translating [N]>&WORD or [N]<&WORD to a new
-   redirection and when creating the redirection undo list. */
+/* 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.
@@ -95,7 +96,23 @@ redirection_error (temp, error)
     filename = "file descriptor out of range";
 #ifdef EBADF
   else if (temp->redirector >= 0 && errno == EBADF)
-    filename = allocname = itos (temp->redirector);
+    {
+      /* 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;
+       default:
+         filename = allocname = itos (temp->redirector);
+         break;
+        }
+    }
 #endif
   else if (expandable_redirection_filename (temp))
     {
@@ -197,6 +214,8 @@ expandable_redirection_filename (redirect)
     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:
@@ -235,6 +254,34 @@ redirection_expand (word)
   return (result);
 }
 
+static int
+write_here_string (fd, redirectee)
+     int fd;
+     WORD_DESC *redirectee;
+{
+  char *herestr;
+  int herelen, n, e;
+
+  herestr = expand_string_to_string (redirectee->word, 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. */
@@ -316,8 +363,9 @@ write_here_document (fd, redirectee)
    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 int
-here_document_to_fd (redirectee)
+here_document_to_fd (redirectee, ri)
      WORD_DESC *redirectee;
+     enum r_instruction ri;
 {
   char *filename;
   int r, fd, fd2;
@@ -334,7 +382,8 @@ here_document_to_fd (redirectee)
   errno = r = 0;               /* XXX */
   /* write_here_document returns 0 on success, errno on failure. */
   if (redirectee->word)
-    r = write_here_document (fd, redirectee);
+    r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
+                                : write_here_string (fd, redirectee);
 
   if (r)
     {
@@ -416,7 +465,7 @@ redir_special_open (spec, filename, flags, mode, ri)
 {
   int fd;
 #if !defined (HAVE_DEV_FD)
-  long lfd;
+  intmax_t lfd;
 #endif
 
   fd = -1;
@@ -562,7 +611,7 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
 {
   WORD_DESC *redirectee;
   int redir_fd, fd, redirector, r, oflags;
-  long lfd;
+  intmax_t lfd;
   char *redirectee_word;
   enum r_instruction ri;
   REDIRECT *new_redirect;
@@ -572,12 +621,14 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
   redirector = redirect->redirector;
   ri = redirect->instruction;
 
-  if (ri == r_duplicating_input_word || ri == r_duplicating_output_word)
+  if (TRANSLATE_REDIRECT (ri))
     {
-      /* We have [N]>&WORD or [N]<&WORD.  Expand WORD, then translate
+      /* We have [N]>&WORD[-] or [N]<&WORD[-].  Expand WORD, then translate
         the redirection into a new one and continue. */
       redirectee_word = redirection_expand (redirectee);
 
+      /* XXX - what to do with [N]<&$w- where w is unset or null?  ksh93
+              closes N. */
       if (redirectee_word == 0)
        return (AMBIGUOUS_REDIRECT);
       else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
@@ -591,11 +642,21 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
            rd.dest = lfd;
          else
            rd.dest = -1;       /* XXX */
-         new_redirect = make_redirection (redirector,
-                                          (ri == r_duplicating_input_word
-                                               ? r_duplicating_input
-                                               : r_duplicating_output),
-                                          rd);         
+         switch (ri)
+           {
+           case r_duplicating_input_word:
+             new_redirect = make_redirection (redirector, r_duplicating_input, rd);
+             break;
+           case r_duplicating_output_word:
+             new_redirect = make_redirection (redirector, r_duplicating_output, rd);
+             break;
+           case r_move_input_word:
+             new_redirect = make_redirection (redirector, r_move_input, rd);
+             break;
+           case r_move_output_word:
+             new_redirect = make_redirection (redirector, r_move_output, rd);
+             break;
+           }
        }
       else if (ri == r_duplicating_output_word && redirector == 1)
        {
@@ -744,11 +805,12 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
 
     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);
+         fd = here_document_to_fd (redirectee, ri);
 
          if (fd < 0)
            {
@@ -796,6 +858,8 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
 
     case r_duplicating_input:
     case r_duplicating_output:
+    case r_move_input:
+    case r_move_output:
       if (for_real && (redir_fd != redirector))
        {
          if (remembering)
@@ -815,7 +879,7 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
            return (errno);
 
 #if defined (BUFFERED_INPUT)
-         if (ri == r_duplicating_input)
+         if (ri == r_duplicating_input || ri == r_move_input)
            duplicate_buffered_stream (redir_fd, redirector);
 #endif /* BUFFERED_INPUT */
 
@@ -829,6 +893,10 @@ do_redirection_internal (redirect, for_real, remembering, set_clexec)
          if (((fcntl (redir_fd, F_GETFD, 0) == 1) || set_clexec) &&
               (redirector > 2))
            SET_CLOSE_ON_EXEC (redirector);
+
+         /* dup-and-close redirection */
+         if (ri == r_move_input || ri == r_move_output)
+           close (redir_fd);
        }
       break;
 
@@ -946,6 +1014,7 @@ stdin_redirection (ri, redirector)
     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: