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