]> git.ipfire.org Git - thirdparty/bash.git/blame - input.c
bash-4.3-alpha release
[thirdparty/bash.git] / input.c
CommitLineData
726f6388
JA
1/* input.c -- functions to perform buffered input with synchronization. */
2
012bac39 3/* Copyright (C) 1992-2009 Free Software Foundation, Inc.
726f6388
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.
726f6388 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.
726f6388 16
2e4498b3
CR
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*/
726f6388 20
ccc6cda3 21#include "config.h"
726f6388
JA
22
23#include "bashtypes.h"
d3a24ed2 24#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
cce855bc
JA
25# include <sys/file.h>
26#endif
726f6388
JA
27#include "filecntl.h"
28#include "posixstat.h"
29#include <stdio.h>
30#include <errno.h>
31
ccc6cda3
JA
32#if defined (HAVE_UNISTD_H)
33# include <unistd.h>
34#endif
35
726f6388 36#include "bashansi.h"
5e13499c
CR
37#include "bashintl.h"
38
726f6388
JA
39#include "command.h"
40#include "general.h"
41#include "input.h"
ccc6cda3
JA
42#include "error.h"
43#include "externs.h"
ac18b312 44#include "quit.h"
726f6388
JA
45
46#if !defined (errno)
47extern int errno;
48#endif /* !errno */
49
09767ff0
CR
50#if defined (EAGAIN)
51# define X_EAGAIN EAGAIN
52#else
53# define X_EAGAIN -99
54#endif
55
56#if defined (EWOULDBLOCK)
57# define X_EWOULDBLOCK EWOULDBLOCK
58#else
59# define X_EWOULDBLOCK -99
60#endif
61
d3ad40de
CR
62extern void termsig_handler __P((int));
63
ccc6cda3
JA
64/* Functions to handle reading input on systems that don't restart read(2)
65 if a signal is received. */
66
f73dda09 67static char localbuf[128];
01ed5ba4 68static int local_index = 0, local_bufused = 0;
ccc6cda3
JA
69
70/* Posix and USG systems do not guarantee to restart read () if it is
71 interrupted by a signal. We do the read ourselves, and restart it
72 if it returns EINTR. */
73int
74getc_with_restart (stream)
75 FILE *stream;
76{
f73dda09
JA
77 unsigned char uc;
78
ac18b312
CR
79 CHECK_TERMSIG;
80
ccc6cda3
JA
81 /* Try local buffering to reduce the number of read(2) calls. */
82 if (local_index == local_bufused || local_bufused == 0)
83 {
84 while (1)
85 {
36eb585c 86 QUIT;
55a5a4ac
CR
87 run_pending_traps ();
88
ccc6cda3
JA
89 local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
90 if (local_bufused > 0)
91 break;
d9e1f41e
CR
92 else if (local_bufused == 0)
93 {
94 local_index = 0;
95 return EOF;
96 }
09767ff0
CR
97 else if (errno == X_EAGAIN || errno == X_EWOULDBLOCK)
98 {
99 if (sh_unset_nodelay_mode (fileno (stream)) < 0)
100 {
101 sys_error (_("cannot reset nodelay mode for fd %d"), fileno (stream));
102 return EOF;
103 }
104 continue;
105 }
d9e1f41e 106 else if (errno != EINTR)
ccc6cda3
JA
107 {
108 local_index = 0;
109 return EOF;
110 }
111 }
112 local_index = 0;
113 }
f73dda09
JA
114 uc = localbuf[local_index++];
115 return uc;
ccc6cda3
JA
116}
117
118int
119ungetc_with_restart (c, stream)
120 int c;
121 FILE *stream;
122{
123 if (local_index == 0 || c == EOF)
124 return EOF;
f73dda09
JA
125 localbuf[--local_index] = c;
126 return c;
ccc6cda3 127}
ccc6cda3
JA
128
129#if defined (BUFFERED_INPUT)
130
131/* A facility similar to stdio, but input-only. */
132
bb70624e
JA
133#if defined (USING_BASH_MALLOC)
134# define MAX_INPUT_BUFFER_SIZE 8176
135#else
136# define MAX_INPUT_BUFFER_SIZE 8192
137#endif
726f6388
JA
138
139#if !defined (SEEK_CUR)
140# define SEEK_CUR 1
141#endif /* !SEEK_CUR */
142
28ef6c31
JA
143#ifdef max
144# undef max
145#endif
146#define max(a, b) (((a) > (b)) ? (a) : (b))
147#ifdef min
148# undef min
149#endif
150#define min(a, b) ((a) > (b) ? (b) : (a))
151
726f6388
JA
152extern int interactive_shell;
153
154int bash_input_fd_changed;
ccc6cda3 155
726f6388
JA
156/* This provides a way to map from a file descriptor to the buffer
157 associated with that file descriptor, rather than just the other
158 way around. This is needed so that buffers are managed properly
159 in constructs like 3<&4. buffers[x]->b_fd == x -- that is how the
160 correspondence is maintained. */
cce855bc 161static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
ccc6cda3 162static int nbuffers;
726f6388 163
726f6388
JA
164#define ALLOCATE_BUFFERS(n) \
165 do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
166
167/* Make sure `buffers' has at least N elements. */
168static void
169allocate_buffers (n)
170 int n;
171{
172 register int i, orig_nbuffers;
173
174 orig_nbuffers = nbuffers;
175 nbuffers = n + 20;
176 buffers = (BUFFERED_STREAM **)xrealloc
177 (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
178
179 /* Zero out the new buffers. */
180 for (i = orig_nbuffers; i < nbuffers; i++)
181 buffers[i] = (BUFFERED_STREAM *)NULL;
182}
183
184/* Construct and return a BUFFERED_STREAM corresponding to file descriptor
185 FD, using BUFFER. */
186static BUFFERED_STREAM *
187make_buffered_stream (fd, buffer, bufsize)
188 int fd;
189 char *buffer;
cce855bc 190 size_t bufsize;
726f6388
JA
191{
192 BUFFERED_STREAM *bp;
193
194 bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
195 ALLOCATE_BUFFERS (fd);
196 buffers[fd] = bp;
197 bp->b_fd = fd;
198 bp->b_buffer = buffer;
199 bp->b_size = bufsize;
ccc6cda3 200 bp->b_used = bp->b_inputp = bp->b_flag = 0;
726f6388
JA
201 if (bufsize == 1)
202 bp->b_flag |= B_UNBUFF;
54a1fa7c
CR
203 if (O_TEXT && (fcntl (fd, F_GETFL) & O_TEXT) != 0)
204 bp->b_flag |= O_TEXT;
726f6388
JA
205 return (bp);
206}
207
208/* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
209static BUFFERED_STREAM *
210copy_buffered_stream (bp)
211 BUFFERED_STREAM *bp;
212{
213 BUFFERED_STREAM *nbp;
214
215 if (!bp)
216 return ((BUFFERED_STREAM *)NULL);
217
218 nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
219 xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
220 return (nbp);
221}
222
28ef6c31
JA
223int
224set_bash_input_fd (fd)
225 int fd;
226{
227 if (bash_input.type == st_bstream)
228 bash_input.location.buffered_fd = fd;
229 else if (interactive_shell == 0)
230 default_buffered_input = fd;
231 return 0;
232}
233
234int
235fd_is_bash_input (fd)
236 int fd;
237{
238 if (bash_input.type == st_bstream && bash_input.location.buffered_fd == fd)
239 return 1;
240 else if (interactive_shell == 0 && default_buffered_input == fd)
241 return 1;
242 return 0;
243}
244
245/* Save the buffered stream corresponding to file descriptor FD (which bash
246 is using to read input) to a buffered stream associated with NEW_FD. If
247 NEW_FD is -1, a new file descriptor is allocated with fcntl. The new
248 file descriptor is returned on success, -1 on error. */
249int
250save_bash_input (fd, new_fd)
251 int fd, new_fd;
252{
253 int nfd;
254
255 /* Sync the stream so we can re-read from the new file descriptor. We
256 might be able to avoid this by copying the buffered stream verbatim
257 to the new file descriptor. */
258 if (buffers[fd])
259 sync_buffered_stream (fd);
260
261 /* Now take care of duplicating the file descriptor that bash is
262 using for input, so we can reinitialize it later. */
263 nfd = (new_fd == -1) ? fcntl (fd, F_DUPFD, 10) : new_fd;
264 if (nfd == -1)
265 {
266 if (fcntl (fd, F_GETFD, 0) == 0)
5e13499c 267 sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd);
28ef6c31
JA
268 return -1;
269 }
270
271 if (buffers[nfd])
272 {
273 /* What's this? A stray buffer without an associated open file
274 descriptor? Free up the buffer and report the error. */
5e13499c 275 internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd);
28ef6c31
JA
276 free_buffered_stream (buffers[nfd]);
277 }
278
279 /* Reinitialize bash_input.location. */
280 if (bash_input.type == st_bstream)
281 {
282 bash_input.location.buffered_fd = nfd;
283 fd_to_buffered_stream (nfd);
284 close_buffered_fd (fd); /* XXX */
285 }
286 else
287 /* If the current input type is not a buffered stream, but the shell
288 is not interactive and therefore using a buffered stream to read
289 input (e.g. with an `eval exec 3>output' inside a script), note
290 that the input fd has been changed. pop_stream() looks at this
291 value and adjusts the input fd to the new value of
292 default_buffered_input accordingly. */
293 bash_input_fd_changed++;
294
295 if (default_buffered_input == fd)
296 default_buffered_input = nfd;
297
298 SET_CLOSE_ON_EXEC (nfd);
299 return nfd;
300}
301
726f6388
JA
302/* Check that file descriptor FD is not the one that bash is currently
303 using to read input from a script. FD is about to be duplicated onto,
304 which means that the kernel will close it for us. If FD is the bash
305 input file descriptor, we need to seek backwards in the script (if
306 possible and necessary -- scripts read from stdin are still unbuffered),
307 allocate a new file descriptor to use for bash input, and re-initialize
28ef6c31
JA
308 the buffered stream. Make sure the file descriptor used to save bash
309 input is set close-on-exec. Returns 0 on success, -1 on failure. This
310 works only if fd is > 0 -- if fd == 0 and bash is reading input from
311 fd 0, save_bash_input is used instead, to cooperate with input
312 redirection (look at redir.c:add_undo_redirect()). */
726f6388
JA
313int
314check_bash_input (fd)
315 int fd;
316{
d3a24ed2
CR
317 if (fd_is_bash_input (fd))
318 {
319 if (fd > 0)
320 return ((save_bash_input (fd, -1) == -1) ? -1 : 0);
321 else if (fd == 0)
322 return ((sync_buffered_stream (fd) == -1) ? -1 : 0);
323 }
726f6388
JA
324 return 0;
325}
326
327/* This is the buffered stream analogue of dup2(fd1, fd2). The
328 BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
329 BUFFERS[fd1] is copied to BUFFERS[fd2]. This is called by the
330 redirect code for constructs like 4<&0 and 3</etc/rc.local. */
ccc6cda3 331int
726f6388
JA
332duplicate_buffered_stream (fd1, fd2)
333 int fd1, fd2;
334{
335 int is_bash_input, m;
336
337 if (fd1 == fd2)
338 return 0;
339
340 m = max (fd1, fd2);
341 ALLOCATE_BUFFERS (m);
342
343 /* If FD2 is the file descriptor bash is currently using for shell input,
344 we need to do some extra work to make sure that the buffered stream
345 actually exists (it might not if fd1 was not active, and the copy
346 didn't actually do anything). */
347 is_bash_input = (bash_input.type == st_bstream) &&
348 (bash_input.location.buffered_fd == fd2);
349
350 if (buffers[fd2])
fd3925f1
CR
351 {
352 /* If the two objects share the same b_buffer, don't free it. */
353 if (buffers[fd1] && buffers[fd1]->b_buffer && buffers[fd1]->b_buffer == buffers[fd2]->b_buffer)
354 buffers[fd2] = (BUFFERED_STREAM *)NULL;
355 else
356 free_buffered_stream (buffers[fd2]);
357 }
726f6388
JA
358 buffers[fd2] = copy_buffered_stream (buffers[fd1]);
359 if (buffers[fd2])
360 buffers[fd2]->b_fd = fd2;
361
28ef6c31
JA
362 if (is_bash_input)
363 {
364 if (!buffers[fd2])
365 fd_to_buffered_stream (fd2);
366 buffers[fd2]->b_flag |= B_WASBASHINPUT;
367 }
ccc6cda3 368
726f6388
JA
369 return (fd2);
370}
371
372/* Return 1 if a seek on FD will succeed. */
54a1fa7c 373#define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
726f6388
JA
374
375/* Take FD, a file descriptor, and create and return a buffered stream
376 corresponding to it. If something is wrong and the file descriptor
377 is invalid, return a NULL stream. */
378BUFFERED_STREAM *
379fd_to_buffered_stream (fd)
380 int fd;
381{
382 char *buffer;
cce855bc 383 size_t size;
726f6388
JA
384 struct stat sb;
385
386 if (fstat (fd, &sb) < 0)
387 {
388 close (fd);
389 return ((BUFFERED_STREAM *)NULL);
390 }
391
28ef6c31
JA
392 size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
393 if (size == 0)
726f6388 394 size = 1;
726f6388
JA
395 buffer = (char *)xmalloc (size);
396
397 return (make_buffered_stream (fd, buffer, size));
398}
399
400/* Return a buffered stream corresponding to FILE, a file name. */
401BUFFERED_STREAM *
402open_buffered_stream (file)
403 char *file;
404{
405 int fd;
406
407 fd = open (file, O_RDONLY);
ccc6cda3 408 return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
726f6388
JA
409}
410
411/* Deallocate a buffered stream and free up its resources. Make sure we
412 zero out the slot in BUFFERS that points to BP. */
413void
414free_buffered_stream (bp)
415 BUFFERED_STREAM *bp;
416{
417 int n;
418
419 if (!bp)
420 return;
421
422 n = bp->b_fd;
423 if (bp->b_buffer)
424 free (bp->b_buffer);
425 free (bp);
426 buffers[n] = (BUFFERED_STREAM *)NULL;
427}
428
429/* Close the file descriptor associated with BP, a buffered stream, and free
430 up the stream. Return the status of closing BP's file descriptor. */
431int
432close_buffered_stream (bp)
433 BUFFERED_STREAM *bp;
434{
435 int fd;
436
437 if (!bp)
438 return (0);
439 fd = bp->b_fd;
440 free_buffered_stream (bp);
441 return (close (fd));
442}
443
444/* Deallocate the buffered stream associated with file descriptor FD, and
445 close FD. Return the status of the close on FD. */
446int
447close_buffered_fd (fd)
448 int fd;
449{
f73dda09
JA
450 if (fd < 0)
451 {
452 errno = EBADF;
453 return -1;
454 }
726f6388
JA
455 if (fd >= nbuffers || !buffers || !buffers[fd])
456 return (close (fd));
457 return (close_buffered_stream (buffers[fd]));
458}
459
cce855bc
JA
460/* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
461 the old BUFFERED_STREAM. */
462BUFFERED_STREAM *
463set_buffered_stream (fd, bp)
464 int fd;
465 BUFFERED_STREAM *bp;
466{
467 BUFFERED_STREAM *ret;
468
469 ret = buffers[fd];
470 buffers[fd] = bp;
471 return ret;
472}
473
726f6388
JA
474/* Read a buffer full of characters from BP, a buffered stream. */
475static int
476b_fill_buffer (bp)
477 BUFFERED_STREAM *bp;
478{
f73dda09 479 ssize_t nr;
54a1fa7c 480 off_t o;
f73dda09 481
ac18b312 482 CHECK_TERMSIG;
54a1fa7c
CR
483 /* In an environment where text and binary files are treated differently,
484 compensate for lseek() on text files returning an offset different from
485 the count of characters read() returns. Text-mode streams have to be
486 treated as unbuffered. */
487 if ((bp->b_flag & (B_TEXT | B_UNBUFF)) == B_TEXT)
488 {
489 o = lseek (bp->b_fd, 0, SEEK_CUR);
490 nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
491 if (nr > 0 && nr < lseek (bp->b_fd, 0, SEEK_CUR) - o)
492 {
493 lseek (bp->b_fd, o, SEEK_SET);
494 bp->b_flag |= B_UNBUFF;
495 bp->b_size = 1;
496 nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
497 }
498 }
499 else
500 nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
f73dda09 501 if (nr <= 0)
726f6388 502 {
f73dda09 503 bp->b_used = 0;
726f6388 504 bp->b_buffer[0] = 0;
f73dda09 505 if (nr == 0)
726f6388
JA
506 bp->b_flag |= B_EOF;
507 else
508 bp->b_flag |= B_ERROR;
509 return (EOF);
510 }
f73dda09 511
f73dda09 512 bp->b_used = nr;
726f6388
JA
513 bp->b_inputp = 0;
514 return (bp->b_buffer[bp->b_inputp++] & 0xFF);
515}
516
517/* Get a character from buffered stream BP. */
518#define bufstream_getc(bp) \
519 (bp->b_inputp == bp->b_used || !bp->b_used) \
520 ? b_fill_buffer (bp) \
521 : bp->b_buffer[bp->b_inputp++] & 0xFF
522
523/* Push C back onto buffered stream BP. */
524static int
525bufstream_ungetc(c, bp)
526 int c;
527 BUFFERED_STREAM *bp;
528{
529 if (c == EOF || bp->b_inputp == 0)
530 return (EOF);
531
532 bp->b_buffer[--bp->b_inputp] = c;
533 return (c);
534}
535
536/* Seek backwards on file BFD to synchronize what we've read so far
537 with the underlying file pointer. */
538int
539sync_buffered_stream (bfd)
540 int bfd;
541{
542 BUFFERED_STREAM *bp;
ccc6cda3 543 off_t chars_left;
726f6388 544
28ef6c31 545 if (buffers == 0 || (bp = buffers[bfd]) == 0)
726f6388 546 return (-1);
28ef6c31 547
726f6388
JA
548 chars_left = bp->b_used - bp->b_inputp;
549 if (chars_left)
550 lseek (bp->b_fd, -chars_left, SEEK_CUR);
551 bp->b_used = bp->b_inputp = 0;
552 return (0);
553}
554
555int
556buffered_getchar ()
557{
ac18b312
CR
558 CHECK_TERMSIG;
559
28ef6c31 560#if !defined (DJGPP)
726f6388 561 return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
28ef6c31
JA
562#else
563 /* On DJGPP, ignore \r. */
564 int ch;
565 while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) == '\r')
566 ;
567 return ch;
568#endif
726f6388
JA
569}
570
571int
572buffered_ungetchar (c)
573 int c;
574{
575 return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
576}
577
578/* Make input come from file descriptor BFD through a buffered stream. */
579void
580with_input_from_buffered_stream (bfd, name)
581 int bfd;
582 char *name;
583{
584 INPUT_STREAM location;
ccc6cda3 585 BUFFERED_STREAM *bp;
726f6388
JA
586
587 location.buffered_fd = bfd;
588 /* Make sure the buffered stream exists. */
ccc6cda3
JA
589 bp = fd_to_buffered_stream (bfd);
590 init_yy_io (bp == 0 ? return_EOF : buffered_getchar,
591 buffered_ungetchar, st_bstream, name, location);
726f6388
JA
592}
593
594#if defined (TEST)
f73dda09 595void *
726f6388
JA
596xmalloc(s)
597int s;
598{
f73dda09 599 return (malloc (s));
726f6388
JA
600}
601
f73dda09 602void *
726f6388
JA
603xrealloc(s, size)
604char *s;
605int size;
606{
607 if (!s)
f73dda09 608 return(malloc (size));
726f6388 609 else
f73dda09 610 return(realloc (s, size));
726f6388
JA
611}
612
613void
614init_yy_io ()
615{
616}
617
618process(bp)
619BUFFERED_STREAM *bp;
620{
621 int c;
622
623 while ((c = bufstream_getc(bp)) != EOF)
624 putchar(c);
625}
626
627BASH_INPUT bash_input;
628
629struct stat dsb; /* can be used from gdb */
630
631/* imitate /bin/cat */
632main(argc, argv)
633int argc;
634char **argv;
635{
636 register int i;
637 BUFFERED_STREAM *bp;
638
639 if (argc == 1) {
640 bp = fd_to_buffered_stream (0);
641 process(bp);
642 exit(0);
643 }
644 for (i = 1; i < argc; i++) {
645 if (argv[i][0] == '-' && argv[i][1] == '\0') {
646 bp = fd_to_buffered_stream (0);
647 if (!bp)
648 continue;
649 process(bp);
650 free_buffered_stream (bp);
651 } else {
652 bp = open_buffered_stream (argv[i]);
653 if (!bp)
654 continue;
655 process(bp);
656 close_buffered_stream (bp);
657 }
658 }
659 exit(0);
660}
ccc6cda3
JA
661#endif /* TEST */
662#endif /* BUFFERED_INPUT */