e3dd3d5456445b15433c026c83fa18eda835533b
[platform/upstream/bash.git] / redir.c
1 /* redir.c -- Functions to perform input and output redirection. */
2
3 /* Copyright (C) 1997 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
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)
10    any later version.
11
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.
16
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. */
20 #include "config.h"
21
22 #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
23   #pragma alloca
24 #endif /* _AIX && RISC6000 && !__GNUC__ */
25
26 #include <stdio.h>
27 #include "bashtypes.h"
28 #ifndef _MINIX
29 #  include <sys/file.h>
30 #endif
31 #include "filecntl.h"
32 #include "posixstat.h"
33
34 #if defined (HAVE_UNISTD_H)
35 #  include <unistd.h>
36 #endif
37
38 #include <errno.h>
39
40 #if !defined (errno)
41 extern int errno;
42 #endif
43
44 #include "bashansi.h"
45
46 #include "memalloc.h"
47 #include "shell.h"
48 #include "flags.h"
49 #include "execute_cmd.h"
50 #include "redir.h"
51
52 #if defined (BUFFERED_INPUT)
53 #  include "input.h"
54 #endif
55
56 extern int posixly_correct;
57 extern int interactive, interactive_shell;
58 extern REDIRECT *redirection_undo_list;
59 extern REDIRECT *exec_redirection_undo_list;
60
61 /* Static functions defined and used in this file. */
62 static void add_undo_close_redirect ();
63 static void add_exec_redirect ();
64 static int add_undo_redirect ();
65 static int do_redirection_internal ();
66 static int expandable_redirection_filename ();
67 static int stdin_redirection ();
68
69 /* Spare redirector used when translating [N]>&WORD or [N]<&WORD to a new
70    redirection and when creating the redirection undo list. */
71 static REDIRECTEE rd;
72
73 /* Set to errno when a here document cannot be created for some reason.
74    Used to print a reasonable error message. */
75 static int heredoc_errno;
76
77 void
78 redirection_error (temp, error)
79      REDIRECT *temp;
80      int error;
81 {
82   char *filename;
83   int oflags;
84
85   if (expandable_redirection_filename (temp))
86     {
87       if (posixly_correct && interactive_shell == 0)
88         {
89           oflags = temp->redirectee.filename->flags;
90           temp->redirectee.filename->flags |= W_NOGLOB;
91         }
92       filename = redirection_expand (temp->redirectee.filename);
93       if (posixly_correct && interactive_shell == 0)
94         temp->redirectee.filename->flags = oflags;
95       if (filename == 0)
96         filename = savestring (temp->redirectee.filename->word);
97       if (filename == 0)
98         {
99           filename = xmalloc (1);
100           filename[0] = '\0';
101         }
102     }
103   else
104     filename = itos (temp->redirectee.dest);
105
106   switch (error)
107     {
108     case AMBIGUOUS_REDIRECT:
109       internal_error ("%s: ambiguous redirect", filename);
110       break;
111
112     case NOCLOBBER_REDIRECT:
113       internal_error ("%s: cannot overwrite existing file", filename);
114       break;
115
116 #if defined (RESTRICTED_SHELL)
117     case RESTRICTED_REDIRECT:
118       internal_error ("%s: restricted: cannot redirect output", filename);
119       break;
120 #endif /* RESTRICTED_SHELL */
121
122     case HEREDOC_REDIRECT:
123       internal_error ("cannot create temp file for here document: %s", strerror (heredoc_errno));
124       break;
125
126     default:
127       internal_error ("%s: %s", filename, strerror (error));
128       break;
129     }
130
131   FREE (filename);
132 }
133
134 /* Perform the redirections on LIST.  If FOR_REAL, then actually make
135    input and output file descriptors, otherwise just do whatever is
136    neccessary for side effecting.  INTERNAL says to remember how to
137    undo the redirections later, if non-zero.  If SET_CLEXEC is non-zero,
138    file descriptors opened in do_redirection () have their close-on-exec
139    flag set. */
140 int
141 do_redirections (list, for_real, internal, set_clexec)
142      REDIRECT *list;
143      int for_real, internal, set_clexec;
144 {
145   int error;
146   REDIRECT *temp;
147
148   if (internal)
149     {
150       if (redirection_undo_list)
151         {
152           dispose_redirects (redirection_undo_list);
153           redirection_undo_list = (REDIRECT *)NULL;
154         }
155       if (exec_redirection_undo_list)
156         dispose_exec_redirects ();
157     }
158
159   for (temp = list; temp; temp = temp->next)
160     {
161       error = do_redirection_internal (temp, for_real, internal, set_clexec);
162       if (error)
163         {
164           redirection_error (temp, error);
165           return (error);
166         }
167     }
168   return (0);
169 }
170
171 /* Return non-zero if the redirection pointed to by REDIRECT has a
172    redirectee.filename that can be expanded. */
173 static int
174 expandable_redirection_filename (redirect)
175      REDIRECT *redirect;
176 {
177   switch (redirect->instruction)
178     {
179     case r_output_direction:
180     case r_appending_to:
181     case r_input_direction:
182     case r_inputa_direction:
183     case r_err_and_out:
184     case r_input_output:
185     case r_output_force:
186     case r_duplicating_input_word:
187     case r_duplicating_output_word:
188       return 1;
189
190     default:
191       return 0;
192     }
193 }
194
195 /* Expand the word in WORD returning a string.  If WORD expands to
196    multiple words (or no words), then return NULL. */
197 char *
198 redirection_expand (word)
199      WORD_DESC *word;
200 {
201   char *result;
202   WORD_LIST *tlist1, *tlist2;
203   WORD_DESC *w;
204
205   w = copy_word (word);
206   if (posixly_correct)
207     w->flags |= W_NOSPLIT;
208
209   tlist1 = make_word_list (w, (WORD_LIST *)NULL);
210   tlist2 = expand_words_no_vars (tlist1);
211   dispose_words (tlist1);
212
213   if (!tlist2 || tlist2->next)
214     {
215       /* We expanded to no words, or to more than a single word.
216          Dispose of the word list and return NULL. */
217       if (tlist2)
218         dispose_words (tlist2);
219       return ((char *)NULL);
220     }
221   result = string_list (tlist2);  /* XXX savestring (tlist2->word->word)? */
222   dispose_words (tlist2);
223   return (result);
224 }
225
226 /* Write the text of the here document pointed to by REDIRECTEE to the file
227    descriptor FD, which is already open to a temp file.  Return 0 if the
228    write is successful, otherwise return errno. */
229 static int
230 write_here_document (fd, redirectee)
231      int fd;
232      WORD_DESC *redirectee;
233 {
234   char *document;
235   int document_len, fd2;
236   FILE *fp;
237   register WORD_LIST *t, *tlist;
238
239   /* Expand the text if the word that was specified had
240      no quoting.  The text that we expand is treated
241      exactly as if it were surrounded by double quotes. */
242
243   if (redirectee->flags & W_QUOTED)
244     {
245       document = redirectee->word;
246       document_len = strlen (document);
247       /* Set errno to something reasonable if the write fails. */
248       if (write (fd, document, document_len) < document_len)
249         {
250           if (errno == 0)
251             errno = ENOSPC;
252           return (errno);
253         }
254       else
255         return 0;
256     }
257
258   tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
259   if (tlist)
260     {
261       /* Try using buffered I/O (stdio) and writing a word
262          at a time, letting stdio do the work of buffering
263          for us rather than managing our own strings.  Most
264          stdios are not particularly fast, however -- this
265          may need to be reconsidered later. */
266       if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)
267         {
268           if (fd2 >= 0)
269             close (fd2);
270           return (errno);
271         }
272       errno = 0;
273       for (t = tlist; t; t = t->next)
274         {
275           /* This is essentially the body of
276              string_list_internal expanded inline. */
277           document = t->word->word;
278           document_len = strlen (document);
279           if (t != tlist)
280             putc (' ', fp);     /* separator */
281           fwrite (document, document_len, 1, fp);
282           if (ferror (fp))
283             {
284               if (errno == 0)
285                 errno = ENOSPC;
286               fd2 = errno;
287               fclose(fp);
288               dispose_words (tlist);
289               return (fd2);
290             }
291         }
292       fclose (fp);
293       dispose_words (tlist);
294     }
295   return 0;
296 }
297
298 /* Create a temporary file holding the text of the here document pointed to
299    by REDIRECTEE, and return a file descriptor open for reading to the temp
300    file.  Return -1 on any error, and make sure errno is set appropriately. */
301 static int
302 here_document_to_fd (redirectee)
303      WORD_DESC *redirectee;
304 {
305   char filename[24];
306   int r, fd, fd2;
307   static int fnum = 0;
308
309   do
310     {
311       /* Make the filename for the temp file. */
312       sprintf (filename, "/tmp/t%d-%d-sh", (int)getpid (), fnum++);
313
314       /* Make sure we open it exclusively. */
315       fd = open (filename, O_TRUNC | O_WRONLY | O_CREAT | O_EXCL, 0600);
316     }
317   while (fd < 0 && errno == EEXIST);
318
319   /* If we failed for some reason other than the file existing, abort */
320   if (fd < 0)
321     return (fd);
322
323   errno = r = 0;                /* XXX */
324   /* write_here_document returns 0 on success, errno on failure. */
325   if (redirectee->word)
326     r = write_here_document (fd, redirectee);
327
328   if (r)
329     {
330       close (fd);
331       unlink (filename);
332       errno = r;
333       return (-1);
334     }
335
336   /* In an attempt to avoid races, we close the first fd only after opening
337      the second. */
338   /* Make the document really temporary.  Also make it the input. */
339   fd2 = open (filename, O_RDONLY, 0600);
340
341   if (fd2 < 0)
342     {
343       r = errno;
344       unlink (filename);
345       close (fd);
346       errno = r;
347       return -1;
348     }
349
350   close (fd);
351   if (unlink (filename) < 0)
352     {
353       r = errno;
354       close (fd2);
355       errno = r;
356       return (-1);
357     }
358
359   return (fd2);
360 }
361
362 #define RF_DEVFD        1
363 #define RF_DEVSTDERR    2
364 #define RF_DEVSTDIN     3
365 #define RF_DEVSTDOUT    4
366 #define RF_DEVTCP       5
367 #define RF_DEVUDP       6
368
369 /* A list of pattern/value pairs for filenames that the redirection
370    code handles specially. */
371 static STRING_INT_ALIST _redir_special_filenames[] = {
372 #if !defined (HAVE_DEV_FD)
373   { "/dev/fd/[0-9]*", RF_DEVFD },
374 #endif
375 #if !defined (HAVE_DEV_STDIN)
376   { "/dev/stderr", RF_DEVSTDERR },
377   { "/dev/stdin", RF_DEVSTDIN },
378   { "/dev/stdout", RF_DEVSTDOUT },
379 #endif
380 #if defined (NETWORK_REDIRECTIONS)
381   { "/dev/tcp/*/*", RF_DEVTCP },
382   { "/dev/udp/*/*", RF_DEVUDP },
383 #endif
384   { (char *)NULL, -1 }
385 };
386
387 static int
388 redir_special_open (spec, filename, flags, mode, ri)
389      int spec;
390      char *filename;
391      int flags, mode;
392      enum r_instruction ri;
393 {
394   int fd;
395   long lfd;
396
397   fd = -1;
398   switch (spec)
399     {
400 #if !defined (HAVE_DEV_FD)
401     case RF_DEVFD:
402       if (legal_number, filename+8, &lfd)
403         fd = fcntl ((int)lfd, F_DUPFD, 10);
404       else
405         fd = AMBIGUOUS_REDIRECT;
406       break;
407 #endif
408
409 #if !defined (HAVE_DEV_STDIN)
410     case RF_DEVSTDIN:
411       fd = fcntl (0, F_DUPFD, 10);
412       break;
413     case RF_DEVSTDOUT:
414       fd = fcntl (1, F_DUPFD, 10);
415       break;
416     case RF_DEVSTDERR:
417       fd = fcntl (2, F_DUPFD, 10);
418       break;
419 #endif
420
421 #if defined (NETWORK_REDIRECTIONS)
422     case RF_DEVTCP:
423     case RF_DEVUDP:
424 #if defined (HAVE_NETWORK)
425       fd = netopen (filename);
426 #else
427       internal_warning ("/dev/(tcp|udp)/host/port not supported without networking");
428       fd = open (filename, flags, mode);
429 #endif
430       break;
431 #endif /* NETWORK_REDIRECTIONS */
432     }
433
434   return fd;
435 }
436       
437 /* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
438    race conditions and avoiding the problem where the file is replaced
439    between the stat(2) and open(2). */
440 static int
441 noclobber_open (filename, flags, mode, ri)
442      char *filename;
443      int flags, mode;
444      enum r_instruction ri;
445 {
446   int r, fd;
447   struct stat finfo, finfo2;
448
449   /* If the file exists and is a regular file, return an error
450      immediately. */
451   r = stat (filename, &finfo);
452   if (r == 0 && (S_ISREG (finfo.st_mode)))
453     return (NOCLOBBER_REDIRECT);
454
455   /* If the file was not present (r != 0), make sure we open it
456      exclusively so that if it is created before we open it, our open
457      will fail.  Make sure that we do not truncate an existing file.
458      Note that we don't turn on O_EXCL unless the stat failed -- if
459      the file was not a regular file, we leave O_EXCL off. */
460   flags &= ~O_TRUNC;
461   if (r != 0)
462     {
463       fd = open (filename, flags|O_EXCL, mode);
464       return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
465     }
466   fd = open (filename, flags, mode);
467
468   /* If the open failed, return the file descriptor right away. */
469   if (fd < 0)
470     return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
471
472   /* OK, the open succeeded, but the file may have been changed from a
473      non-regular file to a regular file between the stat and the open.
474      We are assuming that the O_EXCL open handles the case where FILENAME
475      did not exist and is symlinked to an existing file between the stat
476      and open. */
477
478   /* If we can open it and fstat the file descriptor, and neither check
479      revealed that it was a regular file, and the file has not been replaced,
480      return the file descriptor. */
481   if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) &&
482       r == 0 && (S_ISREG (finfo.st_mode) == 0) &&
483       same_file (filename, filename, &finfo, &finfo2))
484     return fd;
485
486   /* The file has been replaced.  badness. */
487   close (fd);  
488   errno = EEXIST;
489   return (NOCLOBBER_REDIRECT);
490 }
491
492 static int
493 redir_open (filename, flags, mode, ri)
494      char *filename;
495      int flags, mode;
496      enum r_instruction ri;
497 {
498   int fd, r;
499
500   r = find_string_in_alist (filename, _redir_special_filenames, 1);
501   if (r >= 0)
502     return (redir_special_open (r, filename, flags, mode, ri));
503
504   /* If we are in noclobber mode, you are not allowed to overwrite
505      existing files.  Check before opening. */
506   if (noclobber && OUTPUT_REDIRECT (ri))
507     {
508       fd = noclobber_open (filename, flags, mode, ri);
509       if (fd == NOCLOBBER_REDIRECT)
510         return (NOCLOBBER_REDIRECT);
511     }
512   else
513     {
514       fd = open (filename, flags, mode);
515 #if defined (AFS)
516       if ((fd < 0) && (errno == EACCES))
517         fd = open (filename, flags & ~O_CREAT, mode);
518 #endif /* AFS */
519     }
520
521   return fd;
522 }
523
524 /* Do the specific redirection requested.  Returns errno or one of the
525    special redirection errors (*_REDIRECT) in case of error, 0 on success.
526    If FOR_REAL is zero, then just do whatever is neccessary to produce the
527    appropriate side effects.   REMEMBERING, if non-zero, says to remember
528    how to undo each redirection.  If SET_CLEXEC is non-zero, then
529    we set all file descriptors > 2 that we open to be close-on-exec.  */
530 static int
531 do_redirection_internal (redirect, for_real, remembering, set_clexec)
532      REDIRECT *redirect;
533      int for_real, remembering, set_clexec;
534 {
535   WORD_DESC *redirectee;
536   int redir_fd, fd, redirector, r, oflags;
537   char *redirectee_word;
538   enum r_instruction ri;
539   REDIRECT *new_redirect;
540
541   redirectee = redirect->redirectee.filename;
542   redir_fd = redirect->redirectee.dest;
543   redirector = redirect->redirector;
544   ri = redirect->instruction;
545
546   if (ri == r_duplicating_input_word || ri == r_duplicating_output_word)
547     {
548       /* We have [N]>&WORD or [N]<&WORD.  Expand WORD, then translate
549          the redirection into a new one and continue. */
550       redirectee_word = redirection_expand (redirectee);
551
552       if (redirectee_word == 0)
553         return (AMBIGUOUS_REDIRECT);
554       else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
555         {
556           rd.dest = 0L;
557           new_redirect = make_redirection (redirector, r_close_this, rd);
558         }
559       else if (all_digits (redirectee_word))
560         {
561           if (ri == r_duplicating_input_word)
562             {
563               rd.dest = atol (redirectee_word);
564               new_redirect = make_redirection (redirector, r_duplicating_input, rd);
565             }
566           else
567             {
568               rd.dest = atol (redirectee_word);
569               new_redirect = make_redirection (redirector, r_duplicating_output, rd);
570             }
571         }
572       else if (ri == r_duplicating_output_word && redirector == 1)
573         {
574           if (posixly_correct == 0)
575             {
576               rd.filename = make_bare_word (redirectee_word);
577               new_redirect = make_redirection (1, r_err_and_out, rd);
578             }
579           else
580             new_redirect = copy_redirect (redirect);
581         }
582       else
583         {
584           free (redirectee_word);
585           return (AMBIGUOUS_REDIRECT);
586         }
587
588       free (redirectee_word);
589
590       /* Set up the variables needed by the rest of the function from the
591          new redirection. */
592       if (new_redirect->instruction == r_err_and_out)
593         {
594           char *alloca_hack;
595
596           /* Copy the word without allocating any memory that must be
597              explicitly freed. */
598           redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
599           xbcopy ((char *)new_redirect->redirectee.filename,
600                  (char *)redirectee, sizeof (WORD_DESC));
601
602           alloca_hack = (char *)
603             alloca (1 + strlen (new_redirect->redirectee.filename->word));
604           redirectee->word = alloca_hack;
605           strcpy (redirectee->word, new_redirect->redirectee.filename->word);
606         }
607       else
608         /* It's guaranteed to be an integer, and shouldn't be freed. */
609         redirectee = new_redirect->redirectee.filename;
610
611       redir_fd = new_redirect->redirectee.dest;
612       redirector = new_redirect->redirector;
613       ri = new_redirect->instruction;
614
615       /* Overwrite the flags element of the old redirect with the new value. */
616       redirect->flags = new_redirect->flags;
617       dispose_redirects (new_redirect);
618     }
619
620   switch (ri)
621     {
622     case r_output_direction:
623     case r_appending_to:
624     case r_input_direction:
625     case r_inputa_direction:
626     case r_err_and_out:         /* command &>filename */
627     case r_input_output:
628     case r_output_force:
629       if (posixly_correct && interactive_shell == 0)
630         {
631           oflags = redirectee->flags;
632           redirectee->flags |= W_NOGLOB;
633         }
634       redirectee_word = redirection_expand (redirectee);
635       if (posixly_correct && interactive_shell == 0)
636         redirectee->flags = oflags;
637
638       if (redirectee_word == 0)
639         return (AMBIGUOUS_REDIRECT);
640
641 #if defined (RESTRICTED_SHELL)
642       if (restricted && (WRITE_REDIRECT (ri)))
643         {
644           free (redirectee_word);
645           return (RESTRICTED_REDIRECT);
646         }
647 #endif /* RESTRICTED_SHELL */
648
649       fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
650       free (redirectee_word);
651
652       if (fd == NOCLOBBER_REDIRECT)
653         return (fd);
654
655       if (fd < 0)
656         return (errno);
657
658       if (for_real)
659         {
660           if (remembering)
661             /* Only setup to undo it if the thing to undo is active. */
662             if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
663               add_undo_redirect (redirector);
664             else
665               add_undo_close_redirect (redirector);
666
667 #if defined (BUFFERED_INPUT)
668           check_bash_input (redirector);
669 #endif
670
671           if ((fd != redirector) && (dup2 (fd, redirector) < 0))
672             return (errno);
673
674 #if defined (BUFFERED_INPUT)
675           /* Do not change the buffered stream for an implicit redirection
676              of /dev/null to fd 0 for asynchronous commands without job
677              control (r_inputa_direction). */
678           if (ri == r_input_direction || ri == r_input_output)
679             duplicate_buffered_stream (fd, redirector);
680 #endif /* BUFFERED_INPUT */
681
682           /*
683            * If we're remembering, then this is the result of a while, for
684            * or until loop with a loop redirection, or a function/builtin
685            * executing in the parent shell with a redirection.  In the
686            * function/builtin case, we want to set all file descriptors > 2
687            * to be close-on-exec to duplicate the effect of the old
688            * for i = 3 to NOFILE close(i) loop.  In the case of the loops,
689            * both sh and ksh leave the file descriptors open across execs.
690            * The Posix standard mentions only the exec builtin.
691            */
692           if (set_clexec && (redirector > 2))
693             SET_CLOSE_ON_EXEC (redirector);
694         }
695
696       if (fd != redirector)
697         {
698 #if defined (BUFFERED_INPUT)
699           if (INPUT_REDIRECT (ri))
700             close_buffered_fd (fd);
701           else
702 #endif /* !BUFFERED_INPUT */
703             close (fd);         /* Don't close what we just opened! */
704         }
705
706       /* If we are hacking both stdout and stderr, do the stderr
707          redirection here. */
708       if (ri == r_err_and_out)
709         {
710           if (for_real)
711             {
712               if (remembering)
713                 add_undo_redirect (2);
714               if (dup2 (1, 2) < 0)
715                 return (errno);
716             }
717         }
718       break;
719
720     case r_reading_until:
721     case r_deblank_reading_until:
722       /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
723          the new input.  Place it in a temporary file. */
724       if (redirectee)
725         {
726           fd = here_document_to_fd (redirectee);
727
728           if (fd < 0)
729             {
730               heredoc_errno = errno;
731               return (HEREDOC_REDIRECT);
732             }
733
734           if (for_real)
735             {
736               if (remembering)
737                 /* Only setup to undo it if the thing to undo is active. */
738                 if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
739                   add_undo_redirect (redirector);
740                 else
741                   add_undo_close_redirect (redirector);
742
743 #if defined (BUFFERED_INPUT)
744               check_bash_input (redirector);
745 #endif
746               if (fd != redirector && dup2 (fd, redirector) < 0)
747                 {
748                   r = errno;
749                   close (fd);
750                   return (r);
751                 }
752
753 #if defined (BUFFERED_INPUT)
754               duplicate_buffered_stream (fd, redirector);
755 #endif
756
757               if (set_clexec && (redirector > 2))
758                 SET_CLOSE_ON_EXEC (redirector);
759             }
760
761           if (fd != redirector)
762 #if defined (BUFFERED_INPUT)
763             close_buffered_fd (fd);
764 #else
765             close (fd);
766 #endif
767         }
768       break;
769
770     case r_duplicating_input:
771     case r_duplicating_output:
772       if (for_real && (redir_fd != redirector))
773         {
774           if (remembering)
775             /* Only setup to undo it if the thing to undo is active. */
776             if (fcntl (redirector, F_GETFD, 0) != -1)
777               add_undo_redirect (redirector);
778             else
779               add_undo_close_redirect (redirector);
780
781 #if defined (BUFFERED_INPUT)
782           check_bash_input (redirector);
783 #endif
784
785           /* This is correct.  2>&1 means dup2 (1, 2); */
786           if (dup2 (redir_fd, redirector) < 0)
787             return (errno);
788
789 #if defined (BUFFERED_INPUT)
790           if (ri == r_duplicating_input)
791             duplicate_buffered_stream (redir_fd, redirector);
792 #endif /* BUFFERED_INPUT */
793
794           /* First duplicate the close-on-exec state of redirectee.  dup2
795              leaves the flag unset on the new descriptor, which means it
796              stays open.  Only set the close-on-exec bit for file descriptors
797              greater than 2 in any case, since 0-2 should always be open
798              unless closed by something like `exec 2<&-'. */
799           /* if ((already_set || set_unconditionally) && (ok_to_set))
800                 set_it () */
801           if (((fcntl (redir_fd, F_GETFD, 0) == 1) || set_clexec) &&
802                (redirector > 2))
803             SET_CLOSE_ON_EXEC (redirector);
804         }
805       break;
806
807     case r_close_this:
808       if (for_real)
809         {
810           if (remembering && (fcntl (redirector, F_GETFD, 0) != -1))
811             add_undo_redirect (redirector);
812
813 #if defined (BUFFERED_INPUT)
814           check_bash_input (redirector);
815           close_buffered_fd (redirector);
816 #else /* !BUFFERED_INPUT */
817           close (redirector);
818 #endif /* !BUFFERED_INPUT */
819         }
820       break;
821
822     case r_duplicating_input_word:
823     case r_duplicating_output_word:
824       break;
825     }
826   return (0);
827 }
828
829 #define SHELL_FD_BASE   10
830
831 /* Remember the file descriptor associated with the slot FD,
832    on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
833    before it is executed.  Any redirections that need to be undone
834    even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
835    are also saved on EXEC_REDIRECTION_UNDO_LIST. */
836 static int
837 add_undo_redirect (fd)
838      int fd;
839 {
840   int new_fd, clexec_flag;
841   REDIRECT *new_redirect, *closer, *dummy_redirect;
842
843   new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
844
845   if (new_fd < 0)
846     {
847       sys_error ("redirection error");
848       return (-1);
849     }
850
851   clexec_flag = fcntl (fd, F_GETFD, 0);
852
853   rd.dest = 0L;
854   closer = make_redirection (new_fd, r_close_this, rd);
855   dummy_redirect = copy_redirects (closer);
856
857   rd.dest = (long)new_fd;
858   new_redirect = make_redirection (fd, r_duplicating_output, rd);
859   new_redirect->next = closer;
860
861   closer->next = redirection_undo_list;
862   redirection_undo_list = new_redirect;
863
864   /* Save redirections that need to be undone even if the undo list
865      is thrown away by the `exec' builtin. */
866   add_exec_redirect (dummy_redirect);
867
868   /* File descriptors used only for saving others should always be
869      marked close-on-exec.  Unfortunately, we have to preserve the
870      close-on-exec state of the file descriptor we are saving, since
871      fcntl (F_DUPFD) sets the new file descriptor to remain open
872      across execs.  If, however, the file descriptor whose state we
873      are saving is <= 2, we can just set the close-on-exec flag,
874      because file descriptors 0-2 should always be open-on-exec,
875      and the restore above in do_redirection() will take care of it. */
876   if (clexec_flag || fd < 3)
877     SET_CLOSE_ON_EXEC (new_fd);
878
879   return (0);
880 }
881
882 /* Set up to close FD when we are finished with the current command
883    and its redirections. */
884 static void
885 add_undo_close_redirect (fd)
886      int fd;
887 {
888   REDIRECT *closer;
889
890   rd.dest = 0L;
891   closer = make_redirection (fd, r_close_this, rd);
892   closer->next = redirection_undo_list;
893   redirection_undo_list = closer;
894 }
895
896 static void
897 add_exec_redirect (dummy_redirect)
898      REDIRECT *dummy_redirect;
899 {
900   dummy_redirect->next = exec_redirection_undo_list;
901   exec_redirection_undo_list = dummy_redirect;
902 }
903
904 /* Return 1 if the redirection specified by RI and REDIRECTOR alters the
905    standard input. */
906 static int
907 stdin_redirection (ri, redirector)
908      enum r_instruction ri;
909      int redirector;
910 {
911   switch (ri)
912     {
913     case r_input_direction:
914     case r_inputa_direction:
915     case r_input_output:
916     case r_reading_until:
917     case r_deblank_reading_until:
918       return (1);
919     case r_duplicating_input:
920     case r_duplicating_input_word:
921     case r_close_this:
922       return (redirector == 0);
923     case r_output_direction:
924     case r_appending_to:
925     case r_duplicating_output:
926     case r_err_and_out:
927     case r_output_force:
928     case r_duplicating_output_word:
929       return (0);
930     }
931   return (0);
932 }
933
934 /* Return non-zero if any of the redirections in REDIRS alter the standard
935    input. */
936 int
937 stdin_redirects (redirs)
938      REDIRECT *redirs;
939 {
940   REDIRECT *rp;
941   int n;
942
943   for (n = 0, rp = redirs; rp; rp = rp->next)
944     n += stdin_redirection (rp->instruction, rp->redirector);
945   return n;
946 }