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