1 /* redir.c -- Functions to perform input and output redirection. */
3 /* Copyright (C) 1997-2002 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 Bash is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22 #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
24 #endif /* _AIX && RISC6000 && !__GNUC__ */
27 #include "bashtypes.h"
28 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
29 # include <sys/file.h>
32 #include "posixstat.h"
34 #if defined (HAVE_UNISTD_H)
50 #include "execute_cmd.h"
53 #if defined (BUFFERED_INPUT)
59 extern int posixly_correct;
60 extern REDIRECT *redirection_undo_list;
61 extern REDIRECT *exec_redirection_undo_list;
63 /* Static functions defined and used in this file. */
64 static void add_undo_close_redirect __P((int));
65 static void add_exec_redirect __P((REDIRECT *));
66 static int add_undo_redirect __P((int));
67 static int expandable_redirection_filename __P((REDIRECT *));
68 static int stdin_redirection __P((enum r_instruction, int));
69 static int do_redirection_internal __P((REDIRECT *, int));
71 static int write_here_document __P((int, WORD_DESC *));
72 static int write_here_string __P((int, WORD_DESC *));
73 static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));
75 static int redir_special_open __P((int, char *, int, int, enum r_instruction));
76 static int noclobber_open __P((char *, int, int, enum r_instruction));
77 static int redir_open __P((char *, int, int, enum r_instruction));
79 /* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
80 a new redirection and when creating the redirection undo list. */
83 /* Set to errno when a here document cannot be created for some reason.
84 Used to print a reasonable error message. */
85 static int heredoc_errno;
88 redirection_error (temp, error)
92 char *filename, *allocname;
96 if (temp->redirector < 0)
97 /* This can happen when read_token_word encounters overflow, like in
99 filename = _("file descriptor out of range");
101 else if (temp->redirector >= 0 && errno == EBADF)
103 /* If we're dealing with two file descriptors, we have to guess about
104 which one is invalid; in the cases of r_{duplicating,move}_input and
105 r_{duplicating,move}_output we're here because dup2() failed. */
106 switch (temp->instruction)
108 case r_duplicating_input:
109 case r_duplicating_output:
112 filename = allocname = itos (temp->redirectee.dest);
115 filename = allocname = itos (temp->redirector);
120 else if (expandable_redirection_filename (temp))
122 if (posixly_correct && interactive_shell == 0)
124 oflags = temp->redirectee.filename->flags;
125 temp->redirectee.filename->flags |= W_NOGLOB;
127 filename = allocname = redirection_expand (temp->redirectee.filename);
128 if (posixly_correct && interactive_shell == 0)
129 temp->redirectee.filename->flags = oflags;
131 filename = temp->redirectee.filename->word;
133 else if (temp->redirectee.dest < 0)
134 filename = "file descriptor out of range";
136 filename = allocname = itos (temp->redirectee.dest);
140 case AMBIGUOUS_REDIRECT:
141 internal_error (_("%s: ambiguous redirect"), filename);
144 case NOCLOBBER_REDIRECT:
145 internal_error (_("%s: cannot overwrite existing file"), filename);
148 #if defined (RESTRICTED_SHELL)
149 case RESTRICTED_REDIRECT:
150 internal_error (_("%s: restricted: cannot redirect output"), filename);
152 #endif /* RESTRICTED_SHELL */
154 case HEREDOC_REDIRECT:
155 internal_error (_("cannot create temp file for here document: %s"), strerror (heredoc_errno));
159 internal_error ("%s: %s", filename, strerror (error));
166 /* Perform the redirections on LIST. If flags & RX_ACTIVE, then actually
167 make input and output file descriptors, otherwise just do whatever is
168 neccessary for side effecting. flags & RX_UNDOABLE says to remember
169 how to undo the redirections later, if non-zero. If flags & RX_CLEXEC
170 is non-zero, file descriptors opened in do_redirection () have their
171 close-on-exec flag set. */
173 do_redirections (list, flags)
180 if (flags & RX_UNDOABLE)
182 if (redirection_undo_list)
184 dispose_redirects (redirection_undo_list);
185 redirection_undo_list = (REDIRECT *)NULL;
187 if (exec_redirection_undo_list)
188 dispose_exec_redirects ();
191 for (temp = list; temp; temp = temp->next)
193 error = do_redirection_internal (temp, flags);
196 redirection_error (temp, error);
203 /* Return non-zero if the redirection pointed to by REDIRECT has a
204 redirectee.filename that can be expanded. */
206 expandable_redirection_filename (redirect)
209 switch (redirect->instruction)
211 case r_output_direction:
213 case r_input_direction:
214 case r_inputa_direction:
218 case r_duplicating_input_word:
219 case r_duplicating_output_word:
220 case r_move_input_word:
221 case r_move_output_word:
229 /* Expand the word in WORD returning a string. If WORD expands to
230 multiple words (or no words), then return NULL. */
232 redirection_expand (word)
236 WORD_LIST *tlist1, *tlist2;
239 w = copy_word (word);
241 w->flags |= W_NOSPLIT;
243 tlist1 = make_word_list (w, (WORD_LIST *)NULL);
245 tlist2 = expand_words_no_vars (tlist1);
247 dispose_words (tlist1);
249 if (!tlist2 || tlist2->next)
251 /* We expanded to no words, or to more than a single word.
252 Dispose of the word list and return NULL. */
254 dispose_words (tlist2);
255 return ((char *)NULL);
257 result = string_list (tlist2); /* XXX savestring (tlist2->word->word)? */
258 dispose_words (tlist2);
263 write_here_string (fd, redirectee)
265 WORD_DESC *redirectee;
270 herestr = expand_string_to_string (redirectee->word, 0);
271 herelen = STRLEN (herestr);
273 n = write (fd, herestr, herelen);
276 n = write (fd, "\n", 1);
290 /* Write the text of the here document pointed to by REDIRECTEE to the file
291 descriptor FD, which is already open to a temp file. Return 0 if the
292 write is successful, otherwise return errno. */
294 write_here_document (fd, redirectee)
296 WORD_DESC *redirectee;
299 int document_len, fd2;
301 register WORD_LIST *t, *tlist;
303 /* Expand the text if the word that was specified had
304 no quoting. The text that we expand is treated
305 exactly as if it were surrounded by double quotes. */
307 if (redirectee->flags & W_QUOTED)
309 document = redirectee->word;
310 document_len = strlen (document);
311 /* Set errno to something reasonable if the write fails. */
312 if (write (fd, document, document_len) < document_len)
322 tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
325 /* Try using buffered I/O (stdio) and writing a word
326 at a time, letting stdio do the work of buffering
327 for us rather than managing our own strings. Most
328 stdios are not particularly fast, however -- this
329 may need to be reconsidered later. */
330 if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)
337 for (t = tlist; t; t = t->next)
339 /* This is essentially the body of
340 string_list_internal expanded inline. */
341 document = t->word->word;
342 document_len = strlen (document);
344 putc (' ', fp); /* separator */
345 fwrite (document, document_len, 1, fp);
352 dispose_words (tlist);
356 dispose_words (tlist);
357 if (fclose (fp) != 0)
367 /* Create a temporary file holding the text of the here document pointed to
368 by REDIRECTEE, and return a file descriptor open for reading to the temp
369 file. Return -1 on any error, and make sure errno is set appropriately. */
371 here_document_to_fd (redirectee, ri)
372 WORD_DESC *redirectee;
373 enum r_instruction ri;
378 fd = sh_mktmpfd ("sh-thd", MT_USERANDOM, &filename);
380 /* If we failed for some reason other than the file existing, abort */
387 errno = r = 0; /* XXX */
388 /* write_here_document returns 0 on success, errno on failure. */
389 if (redirectee->word)
390 r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
391 : write_here_string (fd, redirectee);
402 /* In an attempt to avoid races, we close the first fd only after opening
404 /* Make the document really temporary. Also make it the input. */
405 fd2 = open (filename, O_RDONLY, 0600);
418 if (unlink (filename) < 0)
421 #if defined (__CYGWIN__)
422 /* Under CygWin 1.1.0, the unlink will fail if the file is
423 open. This hack will allow the previous action of silently
424 ignoring the error, but will still leave the file there. This
425 needs some kind of magic. */
428 #endif /* __CYGWIN__ */
440 #define RF_DEVSTDERR 2
441 #define RF_DEVSTDIN 3
442 #define RF_DEVSTDOUT 4
446 /* A list of pattern/value pairs for filenames that the redirection
447 code handles specially. */
448 static STRING_INT_ALIST _redir_special_filenames[] = {
449 #if !defined (HAVE_DEV_FD)
450 { "/dev/fd/[0-9]*", RF_DEVFD },
452 #if !defined (HAVE_DEV_STDIN)
453 { "/dev/stderr", RF_DEVSTDERR },
454 { "/dev/stdin", RF_DEVSTDIN },
455 { "/dev/stdout", RF_DEVSTDOUT },
457 #if defined (NETWORK_REDIRECTIONS)
458 { "/dev/tcp/*/*", RF_DEVTCP },
459 { "/dev/udp/*/*", RF_DEVUDP },
465 redir_special_open (spec, filename, flags, mode, ri)
469 enum r_instruction ri;
472 #if !defined (HAVE_DEV_FD)
479 #if !defined (HAVE_DEV_FD)
481 if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
484 fd = fcntl (fd, F_DUPFD, 10);
487 fd = AMBIGUOUS_REDIRECT;
491 #if !defined (HAVE_DEV_STDIN)
493 fd = fcntl (0, F_DUPFD, 10);
496 fd = fcntl (1, F_DUPFD, 10);
499 fd = fcntl (2, F_DUPFD, 10);
503 #if defined (NETWORK_REDIRECTIONS)
506 #if defined (HAVE_NETWORK)
507 fd = netopen (filename);
509 internal_warning (_("/dev/(tcp|udp)/host/port not supported without networking"));
510 fd = open (filename, flags, mode);
513 #endif /* NETWORK_REDIRECTIONS */
519 /* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
520 race conditions and avoiding the problem where the file is replaced
521 between the stat(2) and open(2). */
523 noclobber_open (filename, flags, mode, ri)
526 enum r_instruction ri;
529 struct stat finfo, finfo2;
531 /* If the file exists and is a regular file, return an error
533 r = stat (filename, &finfo);
534 if (r == 0 && (S_ISREG (finfo.st_mode)))
535 return (NOCLOBBER_REDIRECT);
537 /* If the file was not present (r != 0), make sure we open it
538 exclusively so that if it is created before we open it, our open
539 will fail. Make sure that we do not truncate an existing file.
540 Note that we don't turn on O_EXCL unless the stat failed -- if
541 the file was not a regular file, we leave O_EXCL off. */
545 fd = open (filename, flags|O_EXCL, mode);
546 return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
548 fd = open (filename, flags, mode);
550 /* If the open failed, return the file descriptor right away. */
552 return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
554 /* OK, the open succeeded, but the file may have been changed from a
555 non-regular file to a regular file between the stat and the open.
556 We are assuming that the O_EXCL open handles the case where FILENAME
557 did not exist and is symlinked to an existing file between the stat
560 /* If we can open it and fstat the file descriptor, and neither check
561 revealed that it was a regular file, and the file has not been replaced,
562 return the file descriptor. */
563 if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) &&
564 r == 0 && (S_ISREG (finfo.st_mode) == 0) &&
565 same_file (filename, filename, &finfo, &finfo2))
568 /* The file has been replaced. badness. */
571 return (NOCLOBBER_REDIRECT);
575 redir_open (filename, flags, mode, ri)
578 enum r_instruction ri;
582 r = find_string_in_alist (filename, _redir_special_filenames, 1);
584 return (redir_special_open (r, filename, flags, mode, ri));
586 /* If we are in noclobber mode, you are not allowed to overwrite
587 existing files. Check before opening. */
588 if (noclobber && CLOBBERING_REDIRECT (ri))
590 fd = noclobber_open (filename, flags, mode, ri);
591 if (fd == NOCLOBBER_REDIRECT)
592 return (NOCLOBBER_REDIRECT);
596 fd = open (filename, flags, mode);
598 if ((fd < 0) && (errno == EACCES))
599 fd = open (filename, flags & ~O_CREAT, mode);
606 /* Do the specific redirection requested. Returns errno or one of the
607 special redirection errors (*_REDIRECT) in case of error, 0 on success.
608 If flags & RX_ACTIVE is zero, then just do whatever is neccessary to
609 produce the appropriate side effects. flags & RX_UNDOABLE, if non-zero,
610 says to remember how to undo each redirection. If flags & RX_CLEXEC is
611 non-zero, then we set all file descriptors > 2 that we open to be
614 do_redirection_internal (redirect, flags)
618 WORD_DESC *redirectee;
619 int redir_fd, fd, redirector, r, oflags;
621 char *redirectee_word;
622 enum r_instruction ri;
623 REDIRECT *new_redirect;
625 redirectee = redirect->redirectee.filename;
626 redir_fd = redirect->redirectee.dest;
627 redirector = redirect->redirector;
628 ri = redirect->instruction;
630 if (TRANSLATE_REDIRECT (ri))
632 /* We have [N]>&WORD[-] or [N]<&WORD[-]. Expand WORD, then translate
633 the redirection into a new one and continue. */
634 redirectee_word = redirection_expand (redirectee);
636 /* XXX - what to do with [N]<&$w- where w is unset or null? ksh93
638 if (redirectee_word == 0)
639 return (AMBIGUOUS_REDIRECT);
640 else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
643 new_redirect = make_redirection (redirector, r_close_this, rd);
645 else if (all_digits (redirectee_word))
647 if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
650 rd.dest = -1; /* XXX */
653 case r_duplicating_input_word:
654 new_redirect = make_redirection (redirector, r_duplicating_input, rd);
656 case r_duplicating_output_word:
657 new_redirect = make_redirection (redirector, r_duplicating_output, rd);
659 case r_move_input_word:
660 new_redirect = make_redirection (redirector, r_move_input, rd);
662 case r_move_output_word:
663 new_redirect = make_redirection (redirector, r_move_output, rd);
667 else if (ri == r_duplicating_output_word && redirector == 1)
669 rd.filename = make_bare_word (redirectee_word);
670 new_redirect = make_redirection (1, r_err_and_out, rd);
674 free (redirectee_word);
675 return (AMBIGUOUS_REDIRECT);
678 free (redirectee_word);
680 /* Set up the variables needed by the rest of the function from the
682 if (new_redirect->instruction == r_err_and_out)
686 /* Copy the word without allocating any memory that must be
688 redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
689 xbcopy ((char *)new_redirect->redirectee.filename,
690 (char *)redirectee, sizeof (WORD_DESC));
692 alloca_hack = (char *)
693 alloca (1 + strlen (new_redirect->redirectee.filename->word));
694 redirectee->word = alloca_hack;
695 strcpy (redirectee->word, new_redirect->redirectee.filename->word);
698 /* It's guaranteed to be an integer, and shouldn't be freed. */
699 redirectee = new_redirect->redirectee.filename;
701 redir_fd = new_redirect->redirectee.dest;
702 redirector = new_redirect->redirector;
703 ri = new_redirect->instruction;
705 /* Overwrite the flags element of the old redirect with the new value. */
706 redirect->flags = new_redirect->flags;
707 dispose_redirects (new_redirect);
712 case r_output_direction:
714 case r_input_direction:
715 case r_inputa_direction:
716 case r_err_and_out: /* command &>filename */
719 if (posixly_correct && interactive_shell == 0)
721 oflags = redirectee->flags;
722 redirectee->flags |= W_NOGLOB;
724 redirectee_word = redirection_expand (redirectee);
725 if (posixly_correct && interactive_shell == 0)
726 redirectee->flags = oflags;
728 if (redirectee_word == 0)
729 return (AMBIGUOUS_REDIRECT);
731 #if defined (RESTRICTED_SHELL)
732 if (restricted && (WRITE_REDIRECT (ri)))
734 free (redirectee_word);
735 return (RESTRICTED_REDIRECT);
737 #endif /* RESTRICTED_SHELL */
739 fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
740 free (redirectee_word);
742 if (fd == NOCLOBBER_REDIRECT)
748 if (flags & RX_ACTIVE)
750 if (flags & RX_UNDOABLE)
752 /* Only setup to undo it if the thing to undo is active. */
753 if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
754 add_undo_redirect (redirector);
756 add_undo_close_redirect (redirector);
759 #if defined (BUFFERED_INPUT)
760 check_bash_input (redirector);
763 if ((fd != redirector) && (dup2 (fd, redirector) < 0))
766 #if defined (BUFFERED_INPUT)
767 /* Do not change the buffered stream for an implicit redirection
768 of /dev/null to fd 0 for asynchronous commands without job
769 control (r_inputa_direction). */
770 if (ri == r_input_direction || ri == r_input_output)
771 duplicate_buffered_stream (fd, redirector);
772 #endif /* BUFFERED_INPUT */
775 * If we're remembering, then this is the result of a while, for
776 * or until loop with a loop redirection, or a function/builtin
777 * executing in the parent shell with a redirection. In the
778 * function/builtin case, we want to set all file descriptors > 2
779 * to be close-on-exec to duplicate the effect of the old
780 * for i = 3 to NOFILE close(i) loop. In the case of the loops,
781 * both sh and ksh leave the file descriptors open across execs.
782 * The Posix standard mentions only the exec builtin.
784 if ((flags & RX_CLEXEC) && (redirector > 2))
785 SET_CLOSE_ON_EXEC (redirector);
788 if (fd != redirector)
790 #if defined (BUFFERED_INPUT)
791 if (INPUT_REDIRECT (ri))
792 close_buffered_fd (fd);
794 #endif /* !BUFFERED_INPUT */
795 close (fd); /* Don't close what we just opened! */
798 /* If we are hacking both stdout and stderr, do the stderr
800 if (ri == r_err_and_out)
802 if (flags & RX_ACTIVE)
804 if (flags & RX_UNDOABLE)
805 add_undo_redirect (2);
812 case r_reading_until:
813 case r_deblank_reading_until:
814 case r_reading_string:
815 /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
816 the new input. Place it in a temporary file. */
819 fd = here_document_to_fd (redirectee, ri);
823 heredoc_errno = errno;
824 return (HEREDOC_REDIRECT);
827 if (flags & RX_ACTIVE)
829 if (flags & RX_UNDOABLE)
831 /* Only setup to undo it if the thing to undo is active. */
832 if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
833 add_undo_redirect (redirector);
835 add_undo_close_redirect (redirector);
838 #if defined (BUFFERED_INPUT)
839 check_bash_input (redirector);
841 if (fd != redirector && dup2 (fd, redirector) < 0)
848 #if defined (BUFFERED_INPUT)
849 duplicate_buffered_stream (fd, redirector);
852 if ((flags & RX_CLEXEC) && (redirector > 2))
853 SET_CLOSE_ON_EXEC (redirector);
856 if (fd != redirector)
857 #if defined (BUFFERED_INPUT)
858 close_buffered_fd (fd);
865 case r_duplicating_input:
866 case r_duplicating_output:
869 if ((flags & RX_ACTIVE) && (redir_fd != redirector))
871 if (flags & RX_UNDOABLE)
873 /* Only setup to undo it if the thing to undo is active. */
874 if (fcntl (redirector, F_GETFD, 0) != -1)
875 add_undo_redirect (redirector);
877 add_undo_close_redirect (redirector);
880 #if defined (BUFFERED_INPUT)
881 check_bash_input (redirector);
883 /* This is correct. 2>&1 means dup2 (1, 2); */
884 if (dup2 (redir_fd, redirector) < 0)
887 #if defined (BUFFERED_INPUT)
888 if (ri == r_duplicating_input || ri == r_move_input)
889 duplicate_buffered_stream (redir_fd, redirector);
890 #endif /* BUFFERED_INPUT */
892 /* First duplicate the close-on-exec state of redirectee. dup2
893 leaves the flag unset on the new descriptor, which means it
894 stays open. Only set the close-on-exec bit for file descriptors
895 greater than 2 in any case, since 0-2 should always be open
896 unless closed by something like `exec 2<&-'. */
897 /* if ((already_set || set_unconditionally) && (ok_to_set))
899 if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (flags & RX_CLEXEC)) &&
901 SET_CLOSE_ON_EXEC (redirector);
903 /* dup-and-close redirection */
904 if (ri == r_move_input || ri == r_move_output)
910 if (flags & RX_ACTIVE)
912 if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
913 add_undo_redirect (redirector);
915 #if defined (BUFFERED_INPUT)
916 check_bash_input (redirector);
917 close_buffered_fd (redirector);
918 #else /* !BUFFERED_INPUT */
920 #endif /* !BUFFERED_INPUT */
924 case r_duplicating_input_word:
925 case r_duplicating_output_word:
931 #define SHELL_FD_BASE 10
933 /* Remember the file descriptor associated with the slot FD,
934 on REDIRECTION_UNDO_LIST. Note that the list will be reversed
935 before it is executed. Any redirections that need to be undone
936 even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
937 are also saved on EXEC_REDIRECTION_UNDO_LIST. */
939 add_undo_redirect (fd)
942 int new_fd, clexec_flag;
943 REDIRECT *new_redirect, *closer, *dummy_redirect;
945 new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
949 sys_error (_("redirection error: cannot duplicate fd"));
953 clexec_flag = fcntl (fd, F_GETFD, 0);
956 closer = make_redirection (new_fd, r_close_this, rd);
957 dummy_redirect = copy_redirects (closer);
961 new_redirect = make_redirection (fd, r_duplicating_input, rd);
963 new_redirect = make_redirection (fd, r_duplicating_output, rd);
964 new_redirect->next = closer;
966 closer->next = redirection_undo_list;
967 redirection_undo_list = new_redirect;
969 /* Save redirections that need to be undone even if the undo list
970 is thrown away by the `exec' builtin. */
971 add_exec_redirect (dummy_redirect);
973 /* File descriptors used only for saving others should always be
974 marked close-on-exec. Unfortunately, we have to preserve the
975 close-on-exec state of the file descriptor we are saving, since
976 fcntl (F_DUPFD) sets the new file descriptor to remain open
977 across execs. If, however, the file descriptor whose state we
978 are saving is <= 2, we can just set the close-on-exec flag,
979 because file descriptors 0-2 should always be open-on-exec,
980 and the restore above in do_redirection() will take care of it. */
981 if (clexec_flag || fd < 3)
982 SET_CLOSE_ON_EXEC (new_fd);
987 /* Set up to close FD when we are finished with the current command
988 and its redirections. */
990 add_undo_close_redirect (fd)
996 closer = make_redirection (fd, r_close_this, rd);
997 closer->next = redirection_undo_list;
998 redirection_undo_list = closer;
1002 add_exec_redirect (dummy_redirect)
1003 REDIRECT *dummy_redirect;
1005 dummy_redirect->next = exec_redirection_undo_list;
1006 exec_redirection_undo_list = dummy_redirect;
1009 /* Return 1 if the redirection specified by RI and REDIRECTOR alters the
1012 stdin_redirection (ri, redirector)
1013 enum r_instruction ri;
1018 case r_input_direction:
1019 case r_inputa_direction:
1020 case r_input_output:
1021 case r_reading_until:
1022 case r_deblank_reading_until:
1023 case r_reading_string:
1025 case r_duplicating_input:
1026 case r_duplicating_input_word:
1028 return (redirector == 0);
1029 case r_output_direction:
1030 case r_appending_to:
1031 case r_duplicating_output:
1033 case r_output_force:
1034 case r_duplicating_output_word:
1040 /* Return non-zero if any of the redirections in REDIRS alter the standard
1043 stdin_redirects (redirs)
1049 for (n = 0, rp = redirs; rp; rp = rp->next)
1050 n += stdin_redirection (rp->instruction, rp->redirector);