1 /* redir.c -- Functions to perform input and output redirection. */
2 
3 /* Copyright (C) 1997-2020 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
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    Bash is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "config.h"
22 
23 #if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
24   #pragma alloca
25 #endif /* _AIX && RISC6000 && !__GNUC__ */
26 
27 #include <stdio.h>
28 #include "bashtypes.h"
29 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
30 #  include <sys/file.h>
31 #endif
32 #include "filecntl.h"
33 #include "posixstat.h"
34 
35 #if defined (HAVE_UNISTD_H)
36 #  include <unistd.h>
37 #endif
38 
39 #include <errno.h>
40 
41 #if !defined (errno)
42 extern int errno;
43 #endif
44 
45 #include "bashansi.h"
46 #include "bashintl.h"
47 #include "memalloc.h"
48 
49 #define NEED_FPURGE_DECL
50 
51 #include "shell.h"
52 #include "flags.h"
53 #include "execute_cmd.h"
54 #include "redir.h"
55 #include "trap.h"
56 
57 #if defined (BUFFERED_INPUT)
58 #  include "input.h"
59 #endif
60 
61 #include "builtins/pipesize.h"
62 
63 /* FreeBSD 13 can reliably handle atomic writes at this capacity without
64    hanging. */
65 #if __FreeBSD__ && !defined (HEREDOC_PIPESIZE)
66 #  define HEREDOC_PIPESIZE 4096
67 #endif
68 
69 /* Normally set by a build process command that computes pipe capacity */
70 #ifndef PIPESIZE
71 #  ifdef PIPE_BUF
72 #    define PIPESIZE PIPE_BUF
73 #  else
74 #    define PIPESIZE 4096
75 #  endif
76 #endif
77 
78 #ifndef HEREDOC_PIPESIZE
79 #  define HEREDOC_PIPESIZE PIPESIZE
80 #endif
81 
82 #if defined (HEREDOC_PIPEMAX)
83 #  if HEREDOC_PIPESIZE > HEREDOC_PIPEMAX
84 #    define HEREDOC_PIPESIZE HEREDOC_PIPEMAX
85 #  endif
86 #endif
87 
88 #define SHELL_FD_BASE	10
89 
90 int expanding_redir;
91 
92 extern REDIRECT *redirection_undo_list;
93 extern REDIRECT *exec_redirection_undo_list;
94 
95 /* Static functions defined and used in this file. */
96 static void add_exec_redirect PARAMS((REDIRECT *));
97 static int add_undo_redirect PARAMS((int, enum r_instruction, int));
98 static int add_undo_close_redirect PARAMS((int));
99 static int expandable_redirection_filename PARAMS((REDIRECT *));
100 static int stdin_redirection PARAMS((enum r_instruction, int));
101 static int undoablefd PARAMS((int));
102 static int do_redirection_internal PARAMS((REDIRECT *, int, char **));
103 
104 static char *heredoc_expand PARAMS((WORD_DESC *, enum r_instruction, size_t *));
105 static int heredoc_write PARAMS((int, char *, size_t));
106 static int here_document_to_fd PARAMS((WORD_DESC *, enum r_instruction));
107 
108 static int redir_special_open PARAMS((int, char *, int, int, enum r_instruction));
109 static int noclobber_open PARAMS((char *, int, int, enum r_instruction));
110 static int redir_open PARAMS((char *, int, int, enum r_instruction));
111 
112 static int redir_varassign PARAMS((REDIRECT *, int));
113 static int redir_varvalue PARAMS((REDIRECT *));
114 
115 /* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
116    a new redirection and when creating the redirection undo list. */
117 static REDIRECTEE rd;
118 
119 /* Set to errno when a here document cannot be created for some reason.
120    Used to print a reasonable error message. */
121 static int heredoc_errno;
122 
123 #define REDIRECTION_ERROR(r, e, fd) \
124 do { \
125   if ((r) < 0) \
126     { \
127       if (fd >= 0) \
128 	close (fd); \
129       set_exit_status (EXECUTION_FAILURE);\
130       return ((e) == 0 ? EINVAL : (e));\
131     } \
132 } while (0)
133 
134 void
redirection_error(temp,error,fn)135 redirection_error (temp, error, fn)
136      REDIRECT *temp;
137      int error;
138      char *fn;		/* already-expanded filename */
139 {
140   char *filename, *allocname;
141   int oflags;
142 
143   allocname = 0;
144   if ((temp->rflags & REDIR_VARASSIGN) && error < 0)
145     filename = allocname = savestring (temp->redirector.filename->word);
146   else if ((temp->rflags & REDIR_VARASSIGN) == 0 && temp->redirector.dest < 0)
147     /* This can happen when read_token_word encounters overflow, like in
148        exec 4294967297>x */
149     filename = _("file descriptor out of range");
150 #ifdef EBADF
151   /* This error can never involve NOCLOBBER */
152   else if (error != NOCLOBBER_REDIRECT && temp->redirector.dest >= 0 && error == EBADF)
153     {
154       /* If we're dealing with two file descriptors, we have to guess about
155          which one is invalid; in the cases of r_{duplicating,move}_input and
156          r_{duplicating,move}_output we're here because dup2() failed. */
157       switch (temp->instruction)
158         {
159         case r_duplicating_input:
160         case r_duplicating_output:
161         case r_move_input:
162         case r_move_output:
163 	  filename = allocname = itos (temp->redirectee.dest);
164 	  break;
165 	case r_duplicating_input_word:
166 	  if (temp->redirector.dest == 0)	/* Guess */
167 	    filename = temp->redirectee.filename->word;	/* XXX */
168 	  else
169 	    filename = allocname = itos (temp->redirector.dest);
170 	  break;
171 	case r_duplicating_output_word:
172 	  if (temp->redirector.dest == 1)	/* Guess */
173 	    filename = temp->redirectee.filename->word;	/* XXX */
174 	  else
175 	    filename = allocname = itos (temp->redirector.dest);
176 	  break;
177 	default:
178 	  filename = allocname = itos (temp->redirector.dest);
179 	  break;
180         }
181     }
182 #endif
183   else if (fn)
184     filename = fn;
185   else if (expandable_redirection_filename (temp))
186     {
187       oflags = temp->redirectee.filename->flags;
188       if (posixly_correct && interactive_shell == 0)
189 	temp->redirectee.filename->flags |= W_NOGLOB;
190       temp->redirectee.filename->flags |= W_NOCOMSUB;
191       filename = allocname = redirection_expand (temp->redirectee.filename);
192       temp->redirectee.filename->flags = oflags;
193       if (filename == 0)
194 	filename = temp->redirectee.filename->word;
195     }
196   else if (temp->redirectee.dest < 0)
197     filename = _("file descriptor out of range");
198   else
199     filename = allocname = itos (temp->redirectee.dest);
200 
201   switch (error)
202     {
203     case AMBIGUOUS_REDIRECT:
204       internal_error (_("%s: ambiguous redirect"), filename);
205       break;
206 
207     case NOCLOBBER_REDIRECT:
208       internal_error (_("%s: cannot overwrite existing file"), filename);
209       break;
210 
211 #if defined (RESTRICTED_SHELL)
212     case RESTRICTED_REDIRECT:
213       internal_error (_("%s: restricted: cannot redirect output"), filename);
214       break;
215 #endif /* RESTRICTED_SHELL */
216 
217     case HEREDOC_REDIRECT:
218       internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));
219       break;
220 
221     case BADVAR_REDIRECT:
222       internal_error (_("%s: cannot assign fd to variable"), filename);
223       break;
224 
225     default:
226       internal_error ("%s: %s", filename, strerror (error));
227       break;
228     }
229 
230   FREE (allocname);
231 }
232 
233 /* Perform the redirections on LIST.  If flags & RX_ACTIVE, then actually
234    make input and output file descriptors, otherwise just do whatever is
235    necessary for side effecting.  flags & RX_UNDOABLE says to remember
236    how to undo the redirections later, if non-zero.  If flags & RX_CLEXEC
237    is non-zero, file descriptors opened in do_redirection () have their
238    close-on-exec flag set. */
239 int
do_redirections(list,flags)240 do_redirections (list, flags)
241      REDIRECT *list;
242      int flags;
243 {
244   int error;
245   REDIRECT *temp;
246   char *fn;
247 
248   if (flags & RX_UNDOABLE)
249     {
250       if (redirection_undo_list)
251 	{
252 	  dispose_redirects (redirection_undo_list);
253 	  redirection_undo_list = (REDIRECT *)NULL;
254 	}
255       if (exec_redirection_undo_list)
256 	dispose_exec_redirects ();
257     }
258 
259   for (temp = list; temp; temp = temp->next)
260     {
261       fn = 0;
262       error = do_redirection_internal (temp, flags, &fn);
263       if (error)
264 	{
265 	  redirection_error (temp, error, fn);
266 	  FREE (fn);
267 	  return (error);
268 	}
269       FREE (fn);
270     }
271   return (0);
272 }
273 
274 /* Return non-zero if the redirection pointed to by REDIRECT has a
275    redirectee.filename that can be expanded. */
276 static int
expandable_redirection_filename(redirect)277 expandable_redirection_filename (redirect)
278      REDIRECT *redirect;
279 {
280   switch (redirect->instruction)
281     {
282     case r_output_direction:
283     case r_appending_to:
284     case r_input_direction:
285     case r_inputa_direction:
286     case r_err_and_out:
287     case r_append_err_and_out:
288     case r_input_output:
289     case r_output_force:
290     case r_duplicating_input_word:
291     case r_duplicating_output_word:
292     case r_move_input_word:
293     case r_move_output_word:
294       return 1;
295 
296     default:
297       return 0;
298     }
299 }
300 
301 /* Expand the word in WORD returning a string.  If WORD expands to
302    multiple words (or no words), then return NULL. */
303 char *
redirection_expand(word)304 redirection_expand (word)
305      WORD_DESC *word;
306 {
307   char *result;
308   WORD_LIST *tlist1, *tlist2;
309   WORD_DESC *w;
310   int old;
311 
312   w = copy_word (word);
313   if (posixly_correct)
314     w->flags |= W_NOSPLIT;
315 
316   tlist1 = make_word_list (w, (WORD_LIST *)NULL);
317   expanding_redir = 1;
318   /* Now that we've changed the variable search order to ignore the temp
319      environment, see if we need to change the cached IFS values. */
320   sv_ifs ("IFS");
321   tlist2 = expand_words_no_vars (tlist1);
322   expanding_redir = 0;
323   /* Now we need to change the variable search order back to include the temp
324      environment.  We force the temp environment search by forcing
325      executing_builtin to 1.  This is what makes `read' get the right values
326      for the IFS-related cached variables, for example. */
327   old = executing_builtin;
328   executing_builtin = 1;
329   sv_ifs ("IFS");
330   executing_builtin = old;
331   dispose_words (tlist1);
332 
333   if (tlist2 == 0 || tlist2->next)
334     {
335       /* We expanded to no words, or to more than a single word.
336 	 Dispose of the word list and return NULL. */
337       if (tlist2)
338 	dispose_words (tlist2);
339       return ((char *)NULL);
340     }
341   result = string_list (tlist2);  /* XXX savestring (tlist2->word->word)? */
342   dispose_words (tlist2);
343   return (result);
344 }
345 
346 /* Expand a here-document or here-string (determined by RI) contained in
347    REDIRECTEE and return the expanded document. If LENP is non-zero, put
348    the length of the returned string into *LENP.
349 
350    This captures everything about expanding here-documents and here-strings:
351    the returned document should be written directly to whatever file
352    descriptor is specified. In particular, it adds a newline to the end of
353    a here-string to preserve previous semantics. */
354 static char *
heredoc_expand(redirectee,ri,lenp)355 heredoc_expand (redirectee, ri, lenp)
356      WORD_DESC *redirectee;
357      enum r_instruction ri;
358      size_t *lenp;
359 {
360   char *document;
361   size_t dlen;
362   int old;
363 
364   if (redirectee->word == 0 || redirectee->word[0] == '\0')
365     {
366       if (lenp)
367         *lenp = 0;
368       return (redirectee->word);
369     }
370 
371   /* Quoted here documents are not expanded */
372   if (ri != r_reading_string && (redirectee->flags & W_QUOTED))
373     {
374       if (lenp)
375         *lenp = STRLEN (redirectee->word);
376       return (redirectee->word);
377     }
378 
379   expanding_redir = 1;
380   /* Now that we've changed the variable search order to ignore the temp
381      environment, see if we need to change the cached IFS values. */
382   sv_ifs ("IFS");
383   document = (ri == r_reading_string) ? expand_assignment_string_to_string (redirectee->word, 0)
384   				      : expand_string_to_string (redirectee->word, Q_HERE_DOCUMENT);
385   expanding_redir = 0;
386   /* Now we need to change the variable search order back to include the temp
387      environment.  We force the temp environment search by forcing
388      executing_builtin to 1.  This is what makes `read' get the right values
389      for the IFS-related cached variables, for example. */
390   old = executing_builtin;
391   executing_builtin = 1;
392   sv_ifs ("IFS");
393   executing_builtin = old;
394 
395   dlen = STRLEN (document);
396   /* XXX - Add trailing newline to here-string */
397   if (ri == r_reading_string)
398     {
399       document = xrealloc (document, dlen + 2);
400       document[dlen++] = '\n';
401       document[dlen] = '\0';
402     }
403   if (lenp)
404     *lenp = dlen;
405 
406   return document;
407 }
408 
409 /* Write HEREDOC (of length HDLEN) to FD, returning 0 on success and ERRNO on
410    error. Don't handle interrupts. */
411 static int
heredoc_write(fd,heredoc,herelen)412 heredoc_write (fd, heredoc, herelen)
413      int fd;
414      char *heredoc;
415      size_t herelen;
416 {
417   ssize_t nw;
418   int e;
419 
420   errno = 0;
421   nw = write (fd, heredoc, herelen);
422   e = errno;
423   if (nw != herelen)
424     {
425       if (e == 0)
426 	e = ENOSPC;
427       return e;
428     }
429   return 0;
430 }
431 
432 /* Create a temporary file or pipe holding the text of the here document
433    pointed to by REDIRECTEE, and return a file descriptor open for reading
434    to it. Return -1 on any error, and make sure errno is set appropriately. */
435 static int
here_document_to_fd(redirectee,ri)436 here_document_to_fd (redirectee, ri)
437      WORD_DESC *redirectee;
438      enum r_instruction ri;
439 {
440   char *filename;
441   int r, fd, fd2, herepipe[2];
442   char *document;
443   size_t document_len;
444 #if HEREDOC_PARANOID
445   struct stat st1, st2;
446 #endif
447 
448   /* Expand the here-document/here-string first and then decide what to do. */
449   document = heredoc_expand (redirectee, ri, &document_len);
450 
451   /* If we have a zero-length document, don't mess with a temp file */
452   if (document_len == 0)
453     {
454       fd = open ("/dev/null", O_RDONLY);
455       r = errno;
456       if (document != redirectee->word)
457 	FREE (document);
458       errno = r;
459       return fd;
460     }
461 
462 #if defined (HEREDOC_PIPESIZE)
463   /* Try to use a pipe internal to this process if the document is shorter
464      than the system's pipe capacity (computed at build time). We want to
465      write the entire document without write blocking. */
466   if (document_len <= HEREDOC_PIPESIZE)
467     {
468       if (pipe (herepipe) < 0)
469 	{
470 	  r = errno;
471 	  if (document != redirectee->word)
472 	    free (document);
473 	  errno = r;
474 	  return (-1);
475 	}
476 
477 #if defined (F_GETPIPE_SZ)
478       if (fcntl (herepipe[1], F_GETPIPE_SZ, 0) < document_len)
479 	goto use_tempfile;
480 #endif
481 
482       r = heredoc_write (herepipe[1], document, document_len);
483       if (document != redirectee->word)
484 	free (document);
485       close (herepipe[1]);
486       if (r)			/* write error */
487 	{
488 	  close (herepipe[0]);
489 	  errno = r;
490 	  return (-1);
491 	}
492       return (herepipe[0]);
493     }
494 #endif
495 
496 use_tempfile:
497 
498   fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename);
499 
500   /* If we failed for some reason other than the file existing, abort */
501   if (fd < 0)
502     {
503       r = errno;
504       FREE (filename);
505       if (document != redirectee->word)
506 	FREE (document);
507       errno = r;
508       return (fd);
509     }
510 
511   fchmod (fd, S_IRUSR | S_IWUSR);
512   SET_CLOSE_ON_EXEC (fd);
513 
514   errno = r = 0;		/* XXX */
515   r = heredoc_write (fd, document, document_len);
516   if (document != redirectee->word)
517     FREE (document);
518 
519   if (r)
520     {
521       close (fd);
522       unlink (filename);
523       free (filename);
524       errno = r;
525       return (-1);
526     }
527 
528   /* In an attempt to avoid races, we close the first fd only after opening
529      the second. */
530   /* Make the document really temporary.  Also make it the input. */
531   fd2 = open (filename, O_RDONLY|O_BINARY, 0600);
532 
533   if (fd2 < 0)
534     {
535       r = errno;
536       unlink (filename);
537       free (filename);
538       close (fd);
539       errno = r;
540       return -1;
541     }
542 
543 #if HEREDOC_PARANOID
544   /* We can use same_file here to check whether or not fd and fd2 refer to
545      the same file, but we don't do that unless HEREDOC_PARANOID is defined. */
546   if (fstat (fd, &st1) < 0 || S_ISREG (st1.st_mode) == 0 ||
547       fstat (fd2, &st2) < 0 || S_ISREG (st2.st_mode) == 0 ||
548       same_file (filename, filename, &st1, &st2) == 0)
549     {
550       unlink (filename);
551       free (filename);
552       close (fd);
553       close (fd2);
554       errno = EEXIST;
555       return -1;
556     }
557 #endif
558 
559   close (fd);
560   if (unlink (filename) < 0)
561     {
562       r = errno;
563       close (fd2);
564       free (filename);
565       errno = r;
566       return (-1);
567     }
568 
569   free (filename);
570 
571   fchmod (fd2, S_IRUSR);
572   return (fd2);
573 }
574 
575 #define RF_DEVFD	1
576 #define RF_DEVSTDERR	2
577 #define RF_DEVSTDIN	3
578 #define RF_DEVSTDOUT	4
579 #define RF_DEVTCP	5
580 #define RF_DEVUDP	6
581 
582 /* A list of pattern/value pairs for filenames that the redirection
583    code handles specially. */
584 static STRING_INT_ALIST _redir_special_filenames[] = {
585 #if !defined (HAVE_DEV_FD)
586   { "/dev/fd/[0-9]*", RF_DEVFD },
587 #endif
588 #if !defined (HAVE_DEV_STDIN)
589   { "/dev/stderr", RF_DEVSTDERR },
590   { "/dev/stdin", RF_DEVSTDIN },
591   { "/dev/stdout", RF_DEVSTDOUT },
592 #endif
593 #if defined (NETWORK_REDIRECTIONS)
594   { "/dev/tcp/*/*", RF_DEVTCP },
595   { "/dev/udp/*/*", RF_DEVUDP },
596 #endif
597   { (char *)NULL, -1 }
598 };
599 
600 static int
redir_special_open(spec,filename,flags,mode,ri)601 redir_special_open (spec, filename, flags, mode, ri)
602      int spec;
603      char *filename;
604      int flags, mode;
605      enum r_instruction ri;
606 {
607   int fd;
608 #if !defined (HAVE_DEV_FD)
609   intmax_t lfd;
610 #endif
611 
612   fd = -1;
613   switch (spec)
614     {
615 #if !defined (HAVE_DEV_FD)
616     case RF_DEVFD:
617       if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
618 	{
619 	  fd = lfd;
620 	  fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
621 	}
622       else
623 	fd = AMBIGUOUS_REDIRECT;
624       break;
625 #endif
626 
627 #if !defined (HAVE_DEV_STDIN)
628     case RF_DEVSTDIN:
629       fd = fcntl (0, F_DUPFD, SHELL_FD_BASE);
630       break;
631     case RF_DEVSTDOUT:
632       fd = fcntl (1, F_DUPFD, SHELL_FD_BASE);
633       break;
634     case RF_DEVSTDERR:
635       fd = fcntl (2, F_DUPFD, SHELL_FD_BASE);
636       break;
637 #endif
638 
639 #if defined (NETWORK_REDIRECTIONS)
640     case RF_DEVTCP:
641     case RF_DEVUDP:
642 #if defined (RESTRICTED_SHELL)
643       if (restricted)
644 	return (RESTRICTED_REDIRECT);
645 #endif
646 #if defined (HAVE_NETWORK)
647       fd = netopen (filename);
648 #else
649       internal_warning (_("/dev/(tcp|udp)/host/port not supported without networking"));
650       fd = open (filename, flags, mode);
651 #endif
652       break;
653 #endif /* NETWORK_REDIRECTIONS */
654     }
655 
656   return fd;
657 }
658 
659 /* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
660    race conditions and avoiding the problem where the file is replaced
661    between the stat(2) and open(2). */
662 static int
noclobber_open(filename,flags,mode,ri)663 noclobber_open (filename, flags, mode, ri)
664      char *filename;
665      int flags, mode;
666      enum r_instruction ri;
667 {
668   int r, fd;
669   struct stat finfo, finfo2;
670 
671   /* If the file exists and is a regular file, return an error
672      immediately. */
673   r = stat (filename, &finfo);
674   if (r == 0 && (S_ISREG (finfo.st_mode)))
675     return (NOCLOBBER_REDIRECT);
676 
677   /* If the file was not present (r != 0), make sure we open it
678      exclusively so that if it is created before we open it, our open
679      will fail.  Make sure that we do not truncate an existing file.
680      Note that we don't turn on O_EXCL unless the stat failed -- if
681      the file was not a regular file, we leave O_EXCL off. */
682   flags &= ~O_TRUNC;
683   if (r != 0)
684     {
685       fd = open (filename, flags|O_EXCL, mode);
686       return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
687     }
688   fd = open (filename, flags, mode);
689 
690   /* If the open failed, return the file descriptor right away. */
691   if (fd < 0)
692     return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
693 
694   /* OK, the open succeeded, but the file may have been changed from a
695      non-regular file to a regular file between the stat and the open.
696      We are assuming that the O_EXCL open handles the case where FILENAME
697      did not exist and is symlinked to an existing file between the stat
698      and open. */
699 
700   /* If we can open it and fstat the file descriptor, and neither check
701      revealed that it was a regular file, and the file has not been replaced,
702      return the file descriptor. */
703   if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) &&
704       r == 0 && (S_ISREG (finfo.st_mode) == 0) &&
705       same_file (filename, filename, &finfo, &finfo2))
706     return fd;
707 
708   /* The file has been replaced.  badness. */
709   close (fd);
710   errno = EEXIST;
711   return (NOCLOBBER_REDIRECT);
712 }
713 
714 static int
redir_open(filename,flags,mode,ri)715 redir_open (filename, flags, mode, ri)
716      char *filename;
717      int flags, mode;
718      enum r_instruction ri;
719 {
720   int fd, r, e;
721 
722   r = find_string_in_alist (filename, _redir_special_filenames, 1);
723   if (r >= 0)
724     return (redir_special_open (r, filename, flags, mode, ri));
725 
726   /* If we are in noclobber mode, you are not allowed to overwrite
727      existing files.  Check before opening. */
728   if (noclobber && CLOBBERING_REDIRECT (ri))
729     {
730       fd = noclobber_open (filename, flags, mode, ri);
731       if (fd == NOCLOBBER_REDIRECT)
732 	return (NOCLOBBER_REDIRECT);
733     }
734   else
735     {
736       do
737 	{
738 	  fd = open (filename, flags, mode);
739 	  e = errno;
740 	  if (fd < 0 && e == EINTR)
741 	    {
742 	      QUIT;
743 	      run_pending_traps ();
744 	    }
745 	  errno = e;
746 	}
747       while (fd < 0 && errno == EINTR);
748 
749 #if defined (AFS)
750       if ((fd < 0) && (errno == EACCES))
751 	{
752 	  fd = open (filename, flags & ~O_CREAT, mode);
753 	  errno = EACCES;	/* restore errno */
754 	}
755 #endif /* AFS */
756     }
757 
758   return fd;
759 }
760 
761 static int
undoablefd(fd)762 undoablefd (fd)
763      int fd;
764 {
765   int clexec;
766 
767   clexec = fcntl (fd, F_GETFD, 0);
768   if (clexec == -1 || (fd >= SHELL_FD_BASE && clexec == 1))
769     return 0;
770   return 1;
771 }
772 
773 /* Do the specific redirection requested.  Returns errno or one of the
774    special redirection errors (*_REDIRECT) in case of error, 0 on success.
775    If flags & RX_ACTIVE is zero, then just do whatever is necessary to
776    produce the appropriate side effects.   flags & RX_UNDOABLE, if non-zero,
777    says to remember how to undo each redirection.  If flags & RX_CLEXEC is
778    non-zero, then we set all file descriptors > 2 that we open to be
779    close-on-exec. FNP, if non-null is a pointer to a location where the
780    expanded filename is stored. The caller will free it. */
781 static int
do_redirection_internal(redirect,flags,fnp)782 do_redirection_internal (redirect, flags, fnp)
783      REDIRECT *redirect;
784      int flags;
785      char **fnp;
786 {
787   WORD_DESC *redirectee;
788   int redir_fd, fd, redirector, r, oflags;
789   intmax_t lfd;
790   char *redirectee_word;
791   enum r_instruction ri;
792   REDIRECT *new_redirect;
793   REDIRECTEE sd;
794 
795   redirectee = redirect->redirectee.filename;
796   redir_fd = redirect->redirectee.dest;
797   redirector = redirect->redirector.dest;
798   ri = redirect->instruction;
799 
800   if (redirect->flags & RX_INTERNAL)
801     flags |= RX_INTERNAL;
802 
803   if (TRANSLATE_REDIRECT (ri))
804     {
805       /* We have [N]>&WORD[-] or [N]<&WORD[-] (or {V}>&WORD[-] or {V}<&WORD-).
806          and WORD, then translate the redirection into a new one and
807 	 continue. */
808       redirectee_word = redirection_expand (redirectee);
809 
810       /* XXX - what to do with [N]<&$w- where w is unset or null?  ksh93
811 	       closes N. */
812       if (redirectee_word == 0)
813 	return (AMBIGUOUS_REDIRECT);
814       else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
815 	{
816 	  sd = redirect->redirector;
817 	  rd.dest = 0;
818 	  new_redirect = make_redirection (sd, r_close_this, rd, 0);
819 	}
820       else if (all_digits (redirectee_word))
821 	{
822 	  sd = redirect->redirector;
823 	  if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
824 	    rd.dest = lfd;
825 	  else
826 	    rd.dest = -1;	/* XXX */
827 	  switch (ri)
828 	    {
829 	    case r_duplicating_input_word:
830 	      new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
831 	      break;
832 	    case r_duplicating_output_word:
833 	      new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
834 	      break;
835 	    case r_move_input_word:
836 	      new_redirect = make_redirection (sd, r_move_input, rd, 0);
837 	      break;
838 	    case r_move_output_word:
839 	      new_redirect = make_redirection (sd, r_move_output, rd, 0);
840 	      break;
841 	    default:
842 	      break;	/* shut up gcc */
843 	    }
844 	}
845       else if (ri == r_duplicating_output_word && (redirect->rflags & REDIR_VARASSIGN) == 0 && redirector == 1)
846 	{
847 	  sd = redirect->redirector;
848 	  rd.filename = make_bare_word (redirectee_word);
849 	  new_redirect = make_redirection (sd, r_err_and_out, rd, 0);
850 	}
851       else
852 	{
853 	  free (redirectee_word);
854 	  return (AMBIGUOUS_REDIRECT);
855 	}
856 
857       free (redirectee_word);
858 
859       /* Set up the variables needed by the rest of the function from the
860 	 new redirection. */
861       if (new_redirect->instruction == r_err_and_out)
862 	{
863 	  char *alloca_hack;
864 
865 	  /* Copy the word without allocating any memory that must be
866 	     explicitly freed. */
867 	  redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
868 	  xbcopy ((char *)new_redirect->redirectee.filename,
869 		 (char *)redirectee, sizeof (WORD_DESC));
870 
871 	  alloca_hack = (char *)
872 	    alloca (1 + strlen (new_redirect->redirectee.filename->word));
873 	  redirectee->word = alloca_hack;
874 	  strcpy (redirectee->word, new_redirect->redirectee.filename->word);
875 	}
876       else
877 	/* It's guaranteed to be an integer, and shouldn't be freed. */
878 	redirectee = new_redirect->redirectee.filename;
879 
880       redir_fd = new_redirect->redirectee.dest;
881       redirector = new_redirect->redirector.dest;
882       ri = new_redirect->instruction;
883 
884       /* Overwrite the flags element of the old redirect with the new value. */
885       redirect->flags = new_redirect->flags;
886       dispose_redirects (new_redirect);
887     }
888 
889   switch (ri)
890     {
891     case r_output_direction:
892     case r_appending_to:
893     case r_input_direction:
894     case r_inputa_direction:
895     case r_err_and_out:		/* command &>filename */
896     case r_append_err_and_out:	/* command &>> filename */
897     case r_input_output:
898     case r_output_force:
899       if (posixly_correct && interactive_shell == 0)
900 	{
901 	  oflags = redirectee->flags;
902 	  redirectee->flags |= W_NOGLOB;
903 	}
904       redirectee_word = redirection_expand (redirectee);
905       if (posixly_correct && interactive_shell == 0)
906 	redirectee->flags = oflags;
907 
908       if (redirectee_word == 0)
909 	return (AMBIGUOUS_REDIRECT);
910 
911 #if defined (RESTRICTED_SHELL)
912       if (restricted && (WRITE_REDIRECT (ri)))
913 	{
914 	  free (redirectee_word);
915 	  return (RESTRICTED_REDIRECT);
916 	}
917 #endif /* RESTRICTED_SHELL */
918 
919       fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
920       if (fnp)
921 	*fnp = redirectee_word;
922       else
923 	free (redirectee_word);
924 
925       if (fd == NOCLOBBER_REDIRECT || fd == RESTRICTED_REDIRECT)
926 	return (fd);
927 
928       if (fd < 0)
929 	return (errno);
930 
931       if (flags & RX_ACTIVE)
932 	{
933 	  if (redirect->rflags & REDIR_VARASSIGN)
934 	    {
935 	      redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE);		/* XXX try this for now */
936 	      r = errno;
937 	      if (redirector < 0)
938 		sys_error (_("redirection error: cannot duplicate fd"));
939 	      REDIRECTION_ERROR (redirector, r, fd);
940 	    }
941 
942 	  if ((flags & RX_UNDOABLE) && (redirect->rflags & REDIR_VARASSIGN) == 0)
943 	    {
944 	      /* Only setup to undo it if the thing to undo is active. */
945 	      if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
946 		r = add_undo_redirect (redirector, ri, -1);
947 	      else
948 		r = add_undo_close_redirect (redirector);
949 	      REDIRECTION_ERROR (r, errno, fd);
950 	    }
951 
952 #if defined (BUFFERED_INPUT)
953 	  /* inhibit call to sync_buffered_stream() for async processes */
954 	  if (redirector != 0 || (subshell_environment & SUBSHELL_ASYNC) == 0)
955 	    check_bash_input (redirector);
956 #endif
957 
958 	  /* Make sure there is no pending output before we change the state
959 	     of the underlying file descriptor, since the builtins use stdio
960 	     for output. */
961 	  if (redirector == 1 && fileno (stdout) == redirector)
962 	    {
963 	      fflush (stdout);
964 	      fpurge (stdout);
965 	    }
966 	  else if (redirector == 2 && fileno (stderr) == redirector)
967 	    {
968 	      fflush (stderr);
969 	      fpurge (stderr);
970 	    }
971 
972 	  if (redirect->rflags & REDIR_VARASSIGN)
973 	    {
974 	      if ((r = redir_varassign (redirect, redirector)) < 0)
975 		{
976 		  close (redirector);
977 		  close (fd);
978 		  return (r);	/* XXX */
979 		}
980 	    }
981 	  else if ((fd != redirector) && (dup2 (fd, redirector) < 0))
982 	    {
983 	      close (fd);	/* dup2 failed? must be fd limit issue */
984 	      return (errno);
985 	    }
986 
987 #if defined (BUFFERED_INPUT)
988 	  /* Do not change the buffered stream for an implicit redirection
989 	     of /dev/null to fd 0 for asynchronous commands without job
990 	     control (r_inputa_direction). */
991 	  if (ri == r_input_direction || ri == r_input_output)
992 	    duplicate_buffered_stream (fd, redirector);
993 #endif /* BUFFERED_INPUT */
994 
995 	  /*
996 	   * If we're remembering, then this is the result of a while, for
997 	   * or until loop with a loop redirection, or a function/builtin
998 	   * executing in the parent shell with a redirection.  In the
999 	   * function/builtin case, we want to set all file descriptors > 2
1000 	   * to be close-on-exec to duplicate the effect of the old
1001 	   * for i = 3 to NOFILE close(i) loop.  In the case of the loops,
1002 	   * both sh and ksh leave the file descriptors open across execs.
1003 	   * The Posix standard mentions only the exec builtin.
1004 	   */
1005 	  if ((flags & RX_CLEXEC) && (redirector > 2))
1006 	    SET_CLOSE_ON_EXEC (redirector);
1007 	}
1008 
1009       if (fd != redirector)
1010 	{
1011 #if defined (BUFFERED_INPUT)
1012 	  if (INPUT_REDIRECT (ri))
1013 	    close_buffered_fd (fd);
1014 	  else
1015 #endif /* !BUFFERED_INPUT */
1016 	    close (fd);		/* Don't close what we just opened! */
1017 	}
1018 
1019       /* If we are hacking both stdout and stderr, do the stderr
1020 	 redirection here.  XXX - handle {var} here? */
1021       if (ri == r_err_and_out || ri == r_append_err_and_out)
1022 	{
1023 	  if (flags & RX_ACTIVE)
1024 	    {
1025 	      if (flags & RX_UNDOABLE)
1026 		add_undo_redirect (2, ri, -1);
1027 	      if (dup2 (1, 2) < 0)
1028 		return (errno);
1029 	    }
1030 	}
1031       break;
1032 
1033     case r_reading_until:
1034     case r_deblank_reading_until:
1035     case r_reading_string:
1036       /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
1037 	 the new input.  Place it in a temporary file. */
1038       if (redirectee)
1039 	{
1040 	  fd = here_document_to_fd (redirectee, ri);
1041 
1042 	  if (fd < 0)
1043 	    {
1044 	      heredoc_errno = errno;
1045 	      return (HEREDOC_REDIRECT);
1046 	    }
1047 
1048 	  if (redirect->rflags & REDIR_VARASSIGN)
1049 	    {
1050 	      redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE);		/* XXX try this for now */
1051 	      r = errno;
1052 	      if (redirector < 0)
1053 		sys_error (_("redirection error: cannot duplicate fd"));
1054 	      REDIRECTION_ERROR (redirector, r, fd);
1055 	    }
1056 
1057 	  if (flags & RX_ACTIVE)
1058 	    {
1059 	      if ((flags & RX_UNDOABLE) && (redirect->rflags & REDIR_VARASSIGN) == 0)
1060 	        {
1061 		  /* Only setup to undo it if the thing to undo is active. */
1062 		  if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
1063 		    r = add_undo_redirect (redirector, ri, -1);
1064 		  else
1065 		    r = add_undo_close_redirect (redirector);
1066 		  REDIRECTION_ERROR (r, errno, fd);
1067 	        }
1068 
1069 #if defined (BUFFERED_INPUT)
1070 	      check_bash_input (redirector);
1071 #endif
1072 	      if (redirect->rflags & REDIR_VARASSIGN)
1073 		{
1074 		  if ((r = redir_varassign (redirect, redirector)) < 0)
1075 		    {
1076 		      close (redirector);
1077 		      close (fd);
1078 		      return (r);	/* XXX */
1079 		    }
1080 		}
1081 	      else if (fd != redirector && dup2 (fd, redirector) < 0)
1082 		{
1083 		  r = errno;
1084 		  close (fd);
1085 		  return (r);
1086 		}
1087 
1088 #if defined (BUFFERED_INPUT)
1089 	      duplicate_buffered_stream (fd, redirector);
1090 #endif
1091 
1092 	      if ((flags & RX_CLEXEC) && (redirector > 2))
1093 		SET_CLOSE_ON_EXEC (redirector);
1094 	    }
1095 
1096 	  if (fd != redirector)
1097 #if defined (BUFFERED_INPUT)
1098 	    close_buffered_fd (fd);
1099 #else
1100 	    close (fd);
1101 #endif
1102 	}
1103       break;
1104 
1105     case r_duplicating_input:
1106     case r_duplicating_output:
1107     case r_move_input:
1108     case r_move_output:
1109       if ((flags & RX_ACTIVE) && (redirect->rflags & REDIR_VARASSIGN))
1110         {
1111 	  redirector = fcntl (redir_fd, F_DUPFD, SHELL_FD_BASE);		/* XXX try this for now */
1112 	  r = errno;
1113 	  if (redirector < 0)
1114 	    sys_error (_("redirection error: cannot duplicate fd"));
1115 	  REDIRECTION_ERROR (redirector, r, -1);
1116         }
1117 
1118       if ((flags & RX_ACTIVE) && (redir_fd != redirector))
1119 	{
1120 	  if ((flags & RX_UNDOABLE) && (redirect->rflags & REDIR_VARASSIGN) == 0)
1121 	    {
1122 	      /* Only setup to undo it if the thing to undo is active. */
1123 	      if (fcntl (redirector, F_GETFD, 0) != -1)
1124 		r = add_undo_redirect (redirector, ri, redir_fd);
1125 	      else
1126 		r = add_undo_close_redirect (redirector);
1127 	      REDIRECTION_ERROR (r, errno, -1);
1128 	    }
1129 	  if ((flags & RX_UNDOABLE) && (ri == r_move_input || ri == r_move_output))
1130 	    {
1131 	      /* r_move_input and r_move_output add an additional close()
1132 		 that needs to be undone */
1133 	      if (fcntl (redirector, F_GETFD, 0) != -1)
1134 		{
1135 		  r = add_undo_redirect (redir_fd, r_close_this, -1);
1136 		  REDIRECTION_ERROR (r, errno, -1);
1137 		}
1138 	    }
1139 #if defined (BUFFERED_INPUT)
1140 	  /* inhibit call to sync_buffered_stream() for async processes */
1141 	  if (redirector != 0 || (subshell_environment & SUBSHELL_ASYNC) == 0)
1142 	    check_bash_input (redirector);
1143 #endif
1144 	  if (redirect->rflags & REDIR_VARASSIGN)
1145 	    {
1146 	      if ((r = redir_varassign (redirect, redirector)) < 0)
1147 		{
1148 		  close (redirector);
1149 		  return (r);	/* XXX */
1150 		}
1151 	    }
1152 	  /* This is correct.  2>&1 means dup2 (1, 2); */
1153 	  else if (dup2 (redir_fd, redirector) < 0)
1154 	    return (errno);
1155 
1156 #if defined (BUFFERED_INPUT)
1157 	  if (ri == r_duplicating_input || ri == r_move_input)
1158 	    duplicate_buffered_stream (redir_fd, redirector);
1159 #endif /* BUFFERED_INPUT */
1160 
1161 	  /* First duplicate the close-on-exec state of redirectee.  dup2
1162 	     leaves the flag unset on the new descriptor, which means it
1163 	     stays open.  Only set the close-on-exec bit for file descriptors
1164 	     greater than 2 in any case, since 0-2 should always be open
1165 	     unless closed by something like `exec 2<&-'.  It should always
1166 	     be safe to set fds > 2 to close-on-exec if they're being used to
1167 	     save file descriptors < 2, since we don't need to preserve the
1168 	     state of the close-on-exec flag for those fds -- they should
1169 	     always be open. */
1170 	  /* if ((already_set || set_unconditionally) && (ok_to_set))
1171 		set_it () */
1172 #if 0
1173 	  if (((fcntl (redir_fd, F_GETFD, 0) == 1) || redir_fd < 2 || (flags & RX_CLEXEC)) &&
1174 	       (redirector > 2))
1175 #else
1176 	  if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (redir_fd < 2 && (flags & RX_INTERNAL)) || (flags & RX_CLEXEC)) &&
1177 	       (redirector > 2))
1178 #endif
1179 	    SET_CLOSE_ON_EXEC (redirector);
1180 
1181 	  /* When undoing saving of non-standard file descriptors (>=3) using
1182 	     file descriptors >= SHELL_FD_BASE, we set the saving fd to be
1183 	     close-on-exec and use a flag to decide how to set close-on-exec
1184 	     when the fd is restored. */
1185 	  if ((redirect->flags & RX_INTERNAL) && (redirect->flags & RX_SAVCLEXEC) && redirector >= 3 && (redir_fd >= SHELL_FD_BASE || (redirect->flags & RX_SAVEFD)))
1186 	    SET_OPEN_ON_EXEC (redirector);
1187 
1188 	  /* dup-and-close redirection */
1189 	  if (ri == r_move_input || ri == r_move_output)
1190 	    {
1191 	      xtrace_fdchk (redir_fd);
1192 
1193 	      close (redir_fd);
1194 #if defined (COPROCESS_SUPPORT)
1195 	      coproc_fdchk (redir_fd);	/* XXX - loses coproc fds */
1196 #endif
1197 	    }
1198 	}
1199       break;
1200 
1201     case r_close_this:
1202       if (flags & RX_ACTIVE)
1203 	{
1204 	  if (redirect->rflags & REDIR_VARASSIGN)
1205 	    {
1206 	      redirector = redir_varvalue (redirect);
1207 	      if (redirector < 0)
1208 		return AMBIGUOUS_REDIRECT;
1209 	    }
1210 
1211 	  r = 0;
1212 	  /* XXX - only if REDIR_VARASSIGN not set? */
1213 	  if (flags & RX_UNDOABLE)
1214 	    {
1215 	      if (fcntl (redirector, F_GETFD, 0) != -1)
1216 		r = add_undo_redirect (redirector, ri, -1);
1217 	      else
1218 		r = add_undo_close_redirect (redirector);
1219 	      REDIRECTION_ERROR (r, errno, redirector);
1220 	    }
1221 
1222 #if defined (COPROCESS_SUPPORT)
1223 	  coproc_fdchk (redirector);
1224 #endif
1225 	  xtrace_fdchk (redirector);
1226 
1227 #if defined (BUFFERED_INPUT)
1228 	  /* inhibit call to sync_buffered_stream() for async processes */
1229 	  if (redirector != 0 || (subshell_environment & SUBSHELL_ASYNC) == 0)
1230 	    check_bash_input (redirector);
1231 	  r = close_buffered_fd (redirector);
1232 #else /* !BUFFERED_INPUT */
1233 	  r = close (redirector);
1234 #endif /* !BUFFERED_INPUT */
1235 
1236 	  if (r < 0 && (flags & RX_INTERNAL) && (errno == EIO || errno == ENOSPC))
1237 	    REDIRECTION_ERROR (r, errno, -1);
1238 	}
1239       break;
1240 
1241     case r_duplicating_input_word:
1242     case r_duplicating_output_word:
1243     case r_move_input_word:
1244     case r_move_output_word:
1245       break;
1246     }
1247   return (0);
1248 }
1249 
1250 /* Remember the file descriptor associated with the slot FD,
1251    on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
1252    before it is executed.  Any redirections that need to be undone
1253    even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
1254    are also saved on EXEC_REDIRECTION_UNDO_LIST.  FDBASE says where to
1255    start the duplicating.  If it's less than SHELL_FD_BASE, we're ok,
1256    and can use SHELL_FD_BASE (-1 == don't care).  If it's >= SHELL_FD_BASE,
1257    we have to make sure we don't use fdbase to save a file descriptor,
1258    since we're going to use it later (e.g., make sure we don't save fd 0
1259    to fd 10 if we have a redirection like 0<&10).  If the value of fdbase
1260    puts the process over its fd limit, causing fcntl to fail, we try
1261    again with SHELL_FD_BASE.  Return 0 on success, -1 on error. */
1262 static int
add_undo_redirect(fd,ri,fdbase)1263 add_undo_redirect (fd, ri, fdbase)
1264      int fd;
1265      enum r_instruction ri;
1266      int fdbase;
1267 {
1268   int new_fd, clexec_flag, savefd_flag;
1269   REDIRECT *new_redirect, *closer, *dummy_redirect;
1270   REDIRECTEE sd;
1271 
1272   savefd_flag = 0;
1273   new_fd = fcntl (fd, F_DUPFD, (fdbase < SHELL_FD_BASE) ? SHELL_FD_BASE : fdbase+1);
1274   if (new_fd < 0)
1275     new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
1276   if (new_fd < 0)
1277     {
1278       new_fd = fcntl (fd, F_DUPFD, 0);
1279       savefd_flag = 1;
1280     }
1281 
1282   if (new_fd < 0)
1283     {
1284       sys_error (_("redirection error: cannot duplicate fd"));
1285       return (-1);
1286     }
1287 
1288   clexec_flag = fcntl (fd, F_GETFD, 0);
1289 
1290   sd.dest = new_fd;
1291   rd.dest = 0;
1292   closer = make_redirection (sd, r_close_this, rd, 0);
1293   closer->flags |= RX_INTERNAL;
1294   dummy_redirect = copy_redirects (closer);
1295 
1296   sd.dest = fd;
1297   rd.dest = new_fd;
1298   if (fd == 0)
1299     new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
1300   else
1301     new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
1302   new_redirect->flags |= RX_INTERNAL;
1303   if (savefd_flag)
1304     new_redirect->flags |= RX_SAVEFD;
1305   if (clexec_flag == 0 && fd >= 3 && (new_fd >= SHELL_FD_BASE || savefd_flag))
1306     new_redirect->flags |= RX_SAVCLEXEC;
1307   new_redirect->next = closer;
1308 
1309   closer->next = redirection_undo_list;
1310   redirection_undo_list = new_redirect;
1311 
1312   /* Save redirections that need to be undone even if the undo list
1313      is thrown away by the `exec' builtin. */
1314   add_exec_redirect (dummy_redirect);
1315 
1316   /* experimental:  if we're saving a redirection to undo for a file descriptor
1317      above SHELL_FD_BASE, add a redirection to be undone if the exec builtin
1318      causes redirections to be discarded.  There needs to be a difference
1319      between fds that are used to save other fds and then are the target of
1320      user redirections and fds that are just the target of user redirections.
1321      We use the close-on-exec flag to tell the difference; fds > SHELL_FD_BASE
1322      that have the close-on-exec flag set are assumed to be fds used internally
1323      to save others. */
1324   if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)
1325     {
1326       sd.dest = fd;
1327       rd.dest = new_fd;
1328       new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
1329       new_redirect->flags |= RX_INTERNAL;
1330 
1331       add_exec_redirect (new_redirect);
1332     }
1333 
1334   /* File descriptors used only for saving others should always be
1335      marked close-on-exec.  Unfortunately, we have to preserve the
1336      close-on-exec state of the file descriptor we are saving, since
1337      fcntl (F_DUPFD) sets the new file descriptor to remain open
1338      across execs.  If, however, the file descriptor whose state we
1339      are saving is <= 2, we can just set the close-on-exec flag,
1340      because file descriptors 0-2 should always be open-on-exec,
1341      and the restore above in do_redirection() will take care of it. */
1342   if (clexec_flag || fd < 3)
1343     SET_CLOSE_ON_EXEC (new_fd);
1344   else if (redirection_undo_list->flags & RX_SAVCLEXEC)
1345     SET_CLOSE_ON_EXEC (new_fd);
1346 
1347   return (0);
1348 }
1349 
1350 /* Set up to close FD when we are finished with the current command
1351    and its redirections.  Return 0 on success, -1 on error. */
1352 static int
add_undo_close_redirect(fd)1353 add_undo_close_redirect (fd)
1354      int fd;
1355 {
1356   REDIRECT *closer;
1357   REDIRECTEE sd;
1358 
1359   sd.dest = fd;
1360   rd.dest = 0;
1361   closer = make_redirection (sd, r_close_this, rd, 0);
1362   closer->flags |= RX_INTERNAL;
1363   closer->next = redirection_undo_list;
1364   redirection_undo_list = closer;
1365 
1366   return 0;
1367 }
1368 
1369 static void
add_exec_redirect(dummy_redirect)1370 add_exec_redirect (dummy_redirect)
1371      REDIRECT *dummy_redirect;
1372 {
1373   dummy_redirect->next = exec_redirection_undo_list;
1374   exec_redirection_undo_list = dummy_redirect;
1375 }
1376 
1377 /* Return 1 if the redirection specified by RI and REDIRECTOR alters the
1378    standard input. */
1379 static int
stdin_redirection(ri,redirector)1380 stdin_redirection (ri, redirector)
1381      enum r_instruction ri;
1382      int redirector;
1383 {
1384   switch (ri)
1385     {
1386     case r_input_direction:
1387     case r_inputa_direction:
1388     case r_input_output:
1389     case r_reading_until:
1390     case r_deblank_reading_until:
1391     case r_reading_string:
1392       return (1);
1393     case r_duplicating_input:
1394     case r_duplicating_input_word:
1395     case r_close_this:
1396       return (redirector == 0);
1397     case r_output_direction:
1398     case r_appending_to:
1399     case r_duplicating_output:
1400     case r_err_and_out:
1401     case r_append_err_and_out:
1402     case r_output_force:
1403     case r_duplicating_output_word:
1404     case r_move_input:
1405     case r_move_output:
1406     case r_move_input_word:
1407     case r_move_output_word:
1408       return (0);
1409     }
1410   return (0);
1411 }
1412 
1413 /* Return non-zero if any of the redirections in REDIRS alter the standard
1414    input. */
1415 int
stdin_redirects(redirs)1416 stdin_redirects (redirs)
1417      REDIRECT *redirs;
1418 {
1419   REDIRECT *rp;
1420   int n;
1421 
1422   for (n = 0, rp = redirs; rp; rp = rp->next)
1423     if ((rp->rflags & REDIR_VARASSIGN) == 0)
1424       n += stdin_redirection (rp->instruction, rp->redirector.dest);
1425   return n;
1426 }
1427 /* bind_var_to_int handles array references */
1428 static int
redir_varassign(redir,fd)1429 redir_varassign (redir, fd)
1430      REDIRECT *redir;
1431      int fd;
1432 {
1433   WORD_DESC *w;
1434   SHELL_VAR *v;
1435 
1436   w = redir->redirector.filename;
1437   v = bind_var_to_int (w->word, fd);
1438   if (v == 0 || readonly_p (v) || noassign_p (v))
1439     return BADVAR_REDIRECT;
1440 
1441   stupidly_hack_special_variables (w->word);
1442   return 0;
1443 }
1444 
1445 /* Handles {array[ind]} for redirection words */
1446 static int
redir_varvalue(redir)1447 redir_varvalue (redir)
1448      REDIRECT *redir;
1449 {
1450   SHELL_VAR *v;
1451   char *val, *w;
1452   intmax_t vmax;
1453   int i;
1454 #if defined (ARRAY_VARS)
1455   char *sub;
1456   int len, vr;
1457 #endif
1458 
1459   w = redir->redirector.filename->word;		/* shorthand */
1460   /* XXX - handle set -u here? */
1461 #if defined (ARRAY_VARS)
1462   if (vr = valid_array_reference (w, 0))
1463     {
1464       v = array_variable_part (w, 0, &sub, &len);
1465     }
1466   else
1467 #endif
1468     {
1469       v = find_variable (w);
1470 #if defined (ARRAY_VARS)
1471       if (v == 0)
1472 	{
1473 	  v = find_variable_last_nameref (w, 0);
1474 	  if (v && nameref_p (v))
1475 	    {
1476 	      w = nameref_cell (v);
1477 	      if (vr = valid_array_reference (w, 0))
1478 		v = array_variable_part (w, 0, &sub, &len);
1479 	      else
1480 	        v = find_variable (w);
1481 	    }
1482 	}
1483 #endif
1484     }
1485 
1486   if (v == 0 || invisible_p (v))
1487     return -1;
1488 
1489 #if defined (ARRAY_VARS)
1490   /* get_variable_value handles references to array variables without
1491      subscripts */
1492   if (vr && (array_p (v) || assoc_p (v)))
1493     val = get_array_value (w, 0, (int *)NULL, (arrayind_t *)0);
1494   else
1495 #endif
1496   val = get_variable_value (v);
1497   if (val == 0 || *val == 0)
1498     return -1;
1499 
1500   if (legal_number (val, &vmax) < 0)
1501     return -1;
1502 
1503   i = vmax;	/* integer truncation */
1504   return i;
1505 }
1506