]> git.ipfire.org Git - thirdparty/bash.git/blob - redir.c
Bash-5.1 patch 3: fix command substitution in here-document from child process in...
[thirdparty/bash.git] / redir.c
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }