source: trunk/third/bash/redir.c @ 21276

Revision 21276, 28.1 KB checked in by zacheiss, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21275, which included commits to RCS files with non-trunk default branches.
Line 
1/* redir.c -- Functions to perform input and output redirection. */
2
3/* Copyright (C) 1997-2002 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#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
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)
41extern int errno;
42#endif
43
44#include "bashansi.h"
45#include "bashintl.h"
46
47#include "memalloc.h"
48#include "shell.h"
49#include "flags.h"
50#include "execute_cmd.h"
51#include "redir.h"
52
53#if defined (BUFFERED_INPUT)
54#  include "input.h"
55#endif
56
57int expanding_redir;
58
59extern int posixly_correct;
60extern REDIRECT *redirection_undo_list;
61extern REDIRECT *exec_redirection_undo_list;
62
63/* Static functions defined and used in this file. */
64static void add_undo_close_redirect __P((int));
65static void add_exec_redirect __P((REDIRECT *));
66static int add_undo_redirect __P((int));
67static int expandable_redirection_filename __P((REDIRECT *));
68static int stdin_redirection __P((enum r_instruction, int));
69static int do_redirection_internal __P((REDIRECT *, int));
70
71static int write_here_document __P((int, WORD_DESC *));
72static int write_here_string __P((int, WORD_DESC *));
73static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));
74
75static int redir_special_open __P((int, char *, int, int, enum r_instruction));
76static int noclobber_open __P((char *, int, int, enum r_instruction));
77static int redir_open __P((char *, int, int, enum r_instruction));
78
79/* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
80   a new redirection and when creating the redirection undo list. */
81static REDIRECTEE rd;
82
83/* Set to errno when a here document cannot be created for some reason.
84   Used to print a reasonable error message. */
85static int heredoc_errno;
86
87void
88redirection_error (temp, error)
89     REDIRECT *temp;
90     int error;
91{
92  char *filename, *allocname;
93  int oflags;
94
95  allocname = 0;
96  if (temp->redirector < 0)
97    /* This can happen when read_token_word encounters overflow, like in
98       exec 4294967297>x */
99    filename = _("file descriptor out of range");
100#ifdef EBADF
101  else if (temp->redirector >= 0 && errno == EBADF)
102    {
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)
107        {
108        case r_duplicating_input:
109        case r_duplicating_output:
110        case r_move_input:
111        case r_move_output:
112          filename = allocname = itos (temp->redirectee.dest);
113          break;
114        default:
115          filename = allocname = itos (temp->redirector);
116          break;
117        }
118    }
119#endif
120  else if (expandable_redirection_filename (temp))
121    {
122      if (posixly_correct && interactive_shell == 0)
123        {
124          oflags = temp->redirectee.filename->flags;
125          temp->redirectee.filename->flags |= W_NOGLOB;
126        }
127      filename = allocname = redirection_expand (temp->redirectee.filename);
128      if (posixly_correct && interactive_shell == 0)
129        temp->redirectee.filename->flags = oflags;
130      if (filename == 0)
131        filename = temp->redirectee.filename->word;
132    }
133  else if (temp->redirectee.dest < 0)
134    filename = "file descriptor out of range";
135  else
136    filename = allocname = itos (temp->redirectee.dest);
137
138  switch (error)
139    {
140    case AMBIGUOUS_REDIRECT:
141      internal_error (_("%s: ambiguous redirect"), filename);
142      break;
143
144    case NOCLOBBER_REDIRECT:
145      internal_error (_("%s: cannot overwrite existing file"), filename);
146      break;
147
148#if defined (RESTRICTED_SHELL)
149    case RESTRICTED_REDIRECT:
150      internal_error (_("%s: restricted: cannot redirect output"), filename);
151      break;
152#endif /* RESTRICTED_SHELL */
153
154    case HEREDOC_REDIRECT:
155      internal_error (_("cannot create temp file for here document: %s"), strerror (heredoc_errno));
156      break;
157
158    default:
159      internal_error ("%s: %s", filename, strerror (error));
160      break;
161    }
162
163  FREE (allocname);
164}
165
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. */
172int
173do_redirections (list, flags)
174     REDIRECT *list;
175     int flags;
176{
177  int error;
178  REDIRECT *temp;
179
180  if (flags & RX_UNDOABLE)
181    {
182      if (redirection_undo_list)
183        {
184          dispose_redirects (redirection_undo_list);
185          redirection_undo_list = (REDIRECT *)NULL;
186        }
187      if (exec_redirection_undo_list)
188        dispose_exec_redirects ();
189    }
190
191  for (temp = list; temp; temp = temp->next)
192    {
193      error = do_redirection_internal (temp, flags);
194      if (error)
195        {
196          redirection_error (temp, error);
197          return (error);
198        }
199    }
200  return (0);
201}
202
203/* Return non-zero if the redirection pointed to by REDIRECT has a
204   redirectee.filename that can be expanded. */
205static int
206expandable_redirection_filename (redirect)
207     REDIRECT *redirect;
208{
209  switch (redirect->instruction)
210    {
211    case r_output_direction:
212    case r_appending_to:
213    case r_input_direction:
214    case r_inputa_direction:
215    case r_err_and_out:
216    case r_input_output:
217    case r_output_force:
218    case r_duplicating_input_word:
219    case r_duplicating_output_word:
220    case r_move_input_word:
221    case r_move_output_word:
222      return 1;
223
224    default:
225      return 0;
226    }
227}
228
229/* Expand the word in WORD returning a string.  If WORD expands to
230   multiple words (or no words), then return NULL. */
231char *
232redirection_expand (word)
233     WORD_DESC *word;
234{
235  char *result;
236  WORD_LIST *tlist1, *tlist2;
237  WORD_DESC *w;
238
239  w = copy_word (word);
240  if (posixly_correct)
241    w->flags |= W_NOSPLIT;
242
243  tlist1 = make_word_list (w, (WORD_LIST *)NULL);
244  expanding_redir = 1;
245  tlist2 = expand_words_no_vars (tlist1);
246  expanding_redir = 0;
247  dispose_words (tlist1);
248
249  if (!tlist2 || tlist2->next)
250    {
251      /* We expanded to no words, or to more than a single word.
252         Dispose of the word list and return NULL. */
253      if (tlist2)
254        dispose_words (tlist2);
255      return ((char *)NULL);
256    }
257  result = string_list (tlist2);  /* XXX savestring (tlist2->word->word)? */
258  dispose_words (tlist2);
259  return (result);
260}
261
262static int
263write_here_string (fd, redirectee)
264     int fd;
265     WORD_DESC *redirectee;
266{
267  char *herestr;
268  int herelen, n, e;
269
270  herestr = expand_string_to_string (redirectee->word, 0);
271  herelen = STRLEN (herestr);
272
273  n = write (fd, herestr, herelen);
274  if (n == herelen)
275    {
276      n = write (fd, "\n", 1);
277      herelen = 1;
278    }
279  e = errno;
280  FREE (herestr);
281  if (n != herelen)
282    {
283      if (e == 0)
284        e = ENOSPC;
285      return e;
286    }
287  return 0;
288
289
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. */
293static int
294write_here_document (fd, redirectee)
295     int fd;
296     WORD_DESC *redirectee;
297{
298  char *document;
299  int document_len, fd2;
300  FILE *fp;
301  register WORD_LIST *t, *tlist;
302
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. */
306
307  if (redirectee->flags & W_QUOTED)
308    {
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)
313        {
314          if (errno == 0)
315            errno = ENOSPC;
316          return (errno);
317        }
318      else
319        return 0;
320    }
321
322  tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
323  if (tlist)
324    {
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)
331        {
332          if (fd2 >= 0)
333            close (fd2);
334          return (errno);
335        }
336      errno = 0;
337      for (t = tlist; t; t = t->next)
338        {
339          /* This is essentially the body of
340             string_list_internal expanded inline. */
341          document = t->word->word;
342          document_len = strlen (document);
343          if (t != tlist)
344            putc (' ', fp);     /* separator */
345          fwrite (document, document_len, 1, fp);
346          if (ferror (fp))
347            {
348              if (errno == 0)
349                errno = ENOSPC;
350              fd2 = errno;
351              fclose(fp);
352              dispose_words (tlist);
353              return (fd2);
354            }
355        }
356      dispose_words (tlist);
357      if (fclose (fp) != 0)
358        {
359          if (errno == 0)
360            errno = ENOSPC;
361          return (errno);
362        }
363    }
364  return 0;
365}
366
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. */
370static int
371here_document_to_fd (redirectee, ri)
372     WORD_DESC *redirectee;
373     enum r_instruction ri;
374{
375  char *filename;
376  int r, fd, fd2;
377
378  fd = sh_mktmpfd ("sh-thd", MT_USERANDOM, &filename);
379
380  /* If we failed for some reason other than the file existing, abort */
381  if (fd < 0)
382    {
383      FREE (filename);
384      return (fd);
385    }
386
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);
392
393  if (r)
394    {
395      close (fd);
396      unlink (filename);
397      free (filename);
398      errno = r;
399      return (-1);
400    }
401
402  /* In an attempt to avoid races, we close the first fd only after opening
403     the second. */
404  /* Make the document really temporary.  Also make it the input. */
405  fd2 = open (filename, O_RDONLY, 0600);
406
407  if (fd2 < 0)
408    {
409      r = errno;
410      unlink (filename);
411      free (filename);
412      close (fd);
413      errno = r;
414      return -1;
415    }
416
417  close (fd);
418  if (unlink (filename) < 0)
419    {
420      r = errno;
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. */
426      if (r == EACCES)
427        return (fd2);
428#endif /* __CYGWIN__ */
429      close (fd2);
430      free (filename);
431      errno = r;
432      return (-1);
433    }
434
435  free (filename);
436  return (fd2);
437}
438
439#define RF_DEVFD        1
440#define RF_DEVSTDERR    2
441#define RF_DEVSTDIN     3
442#define RF_DEVSTDOUT    4
443#define RF_DEVTCP       5
444#define RF_DEVUDP       6
445
446/* A list of pattern/value pairs for filenames that the redirection
447   code handles specially. */
448static STRING_INT_ALIST _redir_special_filenames[] = {
449#if !defined (HAVE_DEV_FD)
450  { "/dev/fd/[0-9]*", RF_DEVFD },
451#endif
452#if !defined (HAVE_DEV_STDIN)
453  { "/dev/stderr", RF_DEVSTDERR },
454  { "/dev/stdin", RF_DEVSTDIN },
455  { "/dev/stdout", RF_DEVSTDOUT },
456#endif
457#if defined (NETWORK_REDIRECTIONS)
458  { "/dev/tcp/*/*", RF_DEVTCP },
459  { "/dev/udp/*/*", RF_DEVUDP },
460#endif
461  { (char *)NULL, -1 }
462};
463
464static int
465redir_special_open (spec, filename, flags, mode, ri)
466     int spec;
467     char *filename;
468     int flags, mode;
469     enum r_instruction ri;
470{
471  int fd;
472#if !defined (HAVE_DEV_FD)
473  intmax_t lfd;
474#endif
475
476  fd = -1;
477  switch (spec)
478    {
479#if !defined (HAVE_DEV_FD)
480    case RF_DEVFD:
481      if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
482        {
483          fd = lfd;
484          fd = fcntl (fd, F_DUPFD, 10);
485        }
486      else
487        fd = AMBIGUOUS_REDIRECT;
488      break;
489#endif
490
491#if !defined (HAVE_DEV_STDIN)
492    case RF_DEVSTDIN:
493      fd = fcntl (0, F_DUPFD, 10);
494      break;
495    case RF_DEVSTDOUT:
496      fd = fcntl (1, F_DUPFD, 10);
497      break;
498    case RF_DEVSTDERR:
499      fd = fcntl (2, F_DUPFD, 10);
500      break;
501#endif
502
503#if defined (NETWORK_REDIRECTIONS)
504    case RF_DEVTCP:
505    case RF_DEVUDP:
506#if defined (HAVE_NETWORK)
507      fd = netopen (filename);
508#else
509      internal_warning (_("/dev/(tcp|udp)/host/port not supported without networking"));
510      fd = open (filename, flags, mode);
511#endif
512      break;
513#endif /* NETWORK_REDIRECTIONS */
514    }
515
516  return fd;
517}
518     
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). */
522static int
523noclobber_open (filename, flags, mode, ri)
524     char *filename;
525     int flags, mode;
526     enum r_instruction ri;
527{
528  int r, fd;
529  struct stat finfo, finfo2;
530
531  /* If the file exists and is a regular file, return an error
532     immediately. */
533  r = stat (filename, &finfo);
534  if (r == 0 && (S_ISREG (finfo.st_mode)))
535    return (NOCLOBBER_REDIRECT);
536
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. */
542  flags &= ~O_TRUNC;
543  if (r != 0)
544    {
545      fd = open (filename, flags|O_EXCL, mode);
546      return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
547    }
548  fd = open (filename, flags, mode);
549
550  /* If the open failed, return the file descriptor right away. */
551  if (fd < 0)
552    return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
553
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
558     and open. */
559
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))
566    return fd;
567
568  /* The file has been replaced.  badness. */
569  close (fd); 
570  errno = EEXIST;
571  return (NOCLOBBER_REDIRECT);
572}
573
574static int
575redir_open (filename, flags, mode, ri)
576     char *filename;
577     int flags, mode;
578     enum r_instruction ri;
579{
580  int fd, r;
581
582  r = find_string_in_alist (filename, _redir_special_filenames, 1);
583  if (r >= 0)
584    return (redir_special_open (r, filename, flags, mode, ri));
585
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))
589    {
590      fd = noclobber_open (filename, flags, mode, ri);
591      if (fd == NOCLOBBER_REDIRECT)
592        return (NOCLOBBER_REDIRECT);
593    }
594  else
595    {
596      fd = open (filename, flags, mode);
597#if defined (AFS)
598      if ((fd < 0) && (errno == EACCES))
599        fd = open (filename, flags & ~O_CREAT, mode);
600#endif /* AFS */
601    }
602
603  return fd;
604}
605
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
612   close-on-exec.  */
613static int
614do_redirection_internal (redirect, flags)
615     REDIRECT *redirect;
616     int flags;
617{
618  WORD_DESC *redirectee;
619  int redir_fd, fd, redirector, r, oflags;
620  intmax_t lfd;
621  char *redirectee_word;
622  enum r_instruction ri;
623  REDIRECT *new_redirect;
624
625  redirectee = redirect->redirectee.filename;
626  redir_fd = redirect->redirectee.dest;
627  redirector = redirect->redirector;
628  ri = redirect->instruction;
629
630  if (TRANSLATE_REDIRECT (ri))
631    {
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);
635
636      /* XXX - what to do with [N]<&$w- where w is unset or null?  ksh93
637               closes N. */
638      if (redirectee_word == 0)
639        return (AMBIGUOUS_REDIRECT);
640      else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
641        {
642          rd.dest = 0;
643          new_redirect = make_redirection (redirector, r_close_this, rd);
644        }
645      else if (all_digits (redirectee_word))
646        {
647          if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
648            rd.dest = lfd;
649          else
650            rd.dest = -1;       /* XXX */
651          switch (ri)
652            {
653            case r_duplicating_input_word:
654              new_redirect = make_redirection (redirector, r_duplicating_input, rd);
655              break;
656            case r_duplicating_output_word:
657              new_redirect = make_redirection (redirector, r_duplicating_output, rd);
658              break;
659            case r_move_input_word:
660              new_redirect = make_redirection (redirector, r_move_input, rd);
661              break;
662            case r_move_output_word:
663              new_redirect = make_redirection (redirector, r_move_output, rd);
664              break;
665            }
666        }
667      else if (ri == r_duplicating_output_word && redirector == 1)
668        {
669          rd.filename = make_bare_word (redirectee_word);
670          new_redirect = make_redirection (1, r_err_and_out, rd);
671        }
672      else
673        {
674          free (redirectee_word);
675          return (AMBIGUOUS_REDIRECT);
676        }
677
678      free (redirectee_word);
679
680      /* Set up the variables needed by the rest of the function from the
681         new redirection. */
682      if (new_redirect->instruction == r_err_and_out)
683        {
684          char *alloca_hack;
685
686          /* Copy the word without allocating any memory that must be
687             explicitly freed. */
688          redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
689          xbcopy ((char *)new_redirect->redirectee.filename,
690                 (char *)redirectee, sizeof (WORD_DESC));
691
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);
696        }
697      else
698        /* It's guaranteed to be an integer, and shouldn't be freed. */
699        redirectee = new_redirect->redirectee.filename;
700
701      redir_fd = new_redirect->redirectee.dest;
702      redirector = new_redirect->redirector;
703      ri = new_redirect->instruction;
704
705      /* Overwrite the flags element of the old redirect with the new value. */
706      redirect->flags = new_redirect->flags;
707      dispose_redirects (new_redirect);
708    }
709
710  switch (ri)
711    {
712    case r_output_direction:
713    case r_appending_to:
714    case r_input_direction:
715    case r_inputa_direction:
716    case r_err_and_out:         /* command &>filename */
717    case r_input_output:
718    case r_output_force:
719      if (posixly_correct && interactive_shell == 0)
720        {
721          oflags = redirectee->flags;
722          redirectee->flags |= W_NOGLOB;
723        }
724      redirectee_word = redirection_expand (redirectee);
725      if (posixly_correct && interactive_shell == 0)
726        redirectee->flags = oflags;
727
728      if (redirectee_word == 0)
729        return (AMBIGUOUS_REDIRECT);
730
731#if defined (RESTRICTED_SHELL)
732      if (restricted && (WRITE_REDIRECT (ri)))
733        {
734          free (redirectee_word);
735          return (RESTRICTED_REDIRECT);
736        }
737#endif /* RESTRICTED_SHELL */
738
739      fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
740      free (redirectee_word);
741
742      if (fd == NOCLOBBER_REDIRECT)
743        return (fd);
744
745      if (fd < 0)
746        return (errno);
747
748      if (flags & RX_ACTIVE)
749        {
750          if (flags & RX_UNDOABLE)
751            {
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);
755              else
756                add_undo_close_redirect (redirector);
757            }
758
759#if defined (BUFFERED_INPUT)
760          check_bash_input (redirector);
761#endif
762
763          if ((fd != redirector) && (dup2 (fd, redirector) < 0))
764            return (errno);
765
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 */
773
774          /*
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.
783           */
784          if ((flags & RX_CLEXEC) && (redirector > 2))
785            SET_CLOSE_ON_EXEC (redirector);
786        }
787
788      if (fd != redirector)
789        {
790#if defined (BUFFERED_INPUT)
791          if (INPUT_REDIRECT (ri))
792            close_buffered_fd (fd);
793          else
794#endif /* !BUFFERED_INPUT */
795            close (fd);         /* Don't close what we just opened! */
796        }
797
798      /* If we are hacking both stdout and stderr, do the stderr
799         redirection here. */
800      if (ri == r_err_and_out)
801        {
802          if (flags & RX_ACTIVE)
803            {
804              if (flags & RX_UNDOABLE)
805                add_undo_redirect (2);
806              if (dup2 (1, 2) < 0)
807                return (errno);
808            }
809        }
810      break;
811
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. */
817      if (redirectee)
818        {
819          fd = here_document_to_fd (redirectee, ri);
820
821          if (fd < 0)
822            {
823              heredoc_errno = errno;
824              return (HEREDOC_REDIRECT);
825            }
826
827          if (flags & RX_ACTIVE)
828            {
829              if (flags & RX_UNDOABLE)
830                {
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);
834                  else
835                    add_undo_close_redirect (redirector);
836                }
837
838#if defined (BUFFERED_INPUT)
839              check_bash_input (redirector);
840#endif
841              if (fd != redirector && dup2 (fd, redirector) < 0)
842                {
843                  r = errno;
844                  close (fd);
845                  return (r);
846                }
847
848#if defined (BUFFERED_INPUT)
849              duplicate_buffered_stream (fd, redirector);
850#endif
851
852              if ((flags & RX_CLEXEC) && (redirector > 2))
853                SET_CLOSE_ON_EXEC (redirector);
854            }
855
856          if (fd != redirector)
857#if defined (BUFFERED_INPUT)
858            close_buffered_fd (fd);
859#else
860            close (fd);
861#endif
862        }
863      break;
864
865    case r_duplicating_input:
866    case r_duplicating_output:
867    case r_move_input:
868    case r_move_output:
869      if ((flags & RX_ACTIVE) && (redir_fd != redirector))
870        {
871          if (flags & RX_UNDOABLE)
872            {
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);
876              else
877                add_undo_close_redirect (redirector);
878            }
879
880#if defined (BUFFERED_INPUT)
881          check_bash_input (redirector);
882#endif
883          /* This is correct.  2>&1 means dup2 (1, 2); */
884          if (dup2 (redir_fd, redirector) < 0)
885            return (errno);
886
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 */
891
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))
898                set_it () */
899          if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (flags & RX_CLEXEC)) &&
900               (redirector > 2))
901            SET_CLOSE_ON_EXEC (redirector);
902
903          /* dup-and-close redirection */
904          if (ri == r_move_input || ri == r_move_output)
905            close (redir_fd);
906        }
907      break;
908
909    case r_close_this:
910      if (flags & RX_ACTIVE)
911        {
912          if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
913            add_undo_redirect (redirector);
914
915#if defined (BUFFERED_INPUT)
916          check_bash_input (redirector);
917          close_buffered_fd (redirector);
918#else /* !BUFFERED_INPUT */
919          close (redirector);
920#endif /* !BUFFERED_INPUT */
921        }
922      break;
923
924    case r_duplicating_input_word:
925    case r_duplicating_output_word:
926      break;
927    }
928  return (0);
929}
930
931#define SHELL_FD_BASE   10
932
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. */
938static int
939add_undo_redirect (fd)
940     int fd;
941{
942  int new_fd, clexec_flag;
943  REDIRECT *new_redirect, *closer, *dummy_redirect;
944
945  new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
946
947  if (new_fd < 0)
948    {
949      sys_error (_("redirection error: cannot duplicate fd"));
950      return (-1);
951    }
952
953  clexec_flag = fcntl (fd, F_GETFD, 0);
954
955  rd.dest = 0;
956  closer = make_redirection (new_fd, r_close_this, rd);
957  dummy_redirect = copy_redirects (closer);
958
959  rd.dest = new_fd;
960  if (fd == 0)
961    new_redirect = make_redirection (fd, r_duplicating_input, rd);
962  else
963    new_redirect = make_redirection (fd, r_duplicating_output, rd);
964  new_redirect->next = closer;
965
966  closer->next = redirection_undo_list;
967  redirection_undo_list = new_redirect;
968
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);
972
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);
983
984  return (0);
985}
986
987/* Set up to close FD when we are finished with the current command
988   and its redirections. */
989static void
990add_undo_close_redirect (fd)
991     int fd;
992{
993  REDIRECT *closer;
994
995  rd.dest = 0;
996  closer = make_redirection (fd, r_close_this, rd);
997  closer->next = redirection_undo_list;
998  redirection_undo_list = closer;
999}
1000
1001static void
1002add_exec_redirect (dummy_redirect)
1003     REDIRECT *dummy_redirect;
1004{
1005  dummy_redirect->next = exec_redirection_undo_list;
1006  exec_redirection_undo_list = dummy_redirect;
1007}
1008
1009/* Return 1 if the redirection specified by RI and REDIRECTOR alters the
1010   standard input. */
1011static int
1012stdin_redirection (ri, redirector)
1013     enum r_instruction ri;
1014     int redirector;
1015{
1016  switch (ri)
1017    {
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:
1024      return (1);
1025    case r_duplicating_input:
1026    case r_duplicating_input_word:
1027    case r_close_this:
1028      return (redirector == 0);
1029    case r_output_direction:
1030    case r_appending_to:
1031    case r_duplicating_output:
1032    case r_err_and_out:
1033    case r_output_force:
1034    case r_duplicating_output_word:
1035      return (0);
1036    }
1037  return (0);
1038}
1039
1040/* Return non-zero if any of the redirections in REDIRS alter the standard
1041   input. */
1042int
1043stdin_redirects (redirs)
1044     REDIRECT *redirs;
1045{
1046  REDIRECT *rp;
1047  int n;
1048
1049  for (n = 0, rp = redirs; rp; rp = rp->next)
1050    n += stdin_redirection (rp->instruction, rp->redirector);
1051  return n;
1052}
Note: See TracBrowser for help on using the repository browser.