/* 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.
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.
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))
{
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 (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. */
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;
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)
{
{
int fd;
#if !defined (HAVE_DEV_FD)
- long lfd;
+ intmax_t lfd;
#endif
fd = -1;
{
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;
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')
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)
{
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)
{
case r_duplicating_input:
case r_duplicating_output:
+ case r_move_input:
+ case r_move_output:
if (for_real && (redir_fd != redirector))
{
if (remembering)
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 */
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;
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: