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