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