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