X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=input.c;h=c543ce75fbed406bb18b507be67b8eb75f9916c6;hb=ccc6cda312fea9f0468ee65b8f368e9653e1380b;hp=852d3695be0b1b63c66fe7c24e4f710596bb4ff8;hpb=726f63884db0132f01745f1fb4465e6621088ccf;p=platform%2Fupstream%2Fbash.git diff --git a/input.c b/input.c index 852d369..c543ce7 100644 --- a/input.c +++ b/input.c @@ -18,7 +18,7 @@ with Bash; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* similar to stdio, but input-only. */ +#include "config.h" #include "bashtypes.h" #include @@ -27,16 +27,69 @@ #include #include +#if defined (HAVE_UNISTD_H) +# include +#endif + #include "bashansi.h" -#include "config.h" #include "command.h" #include "general.h" #include "input.h" +#include "error.h" +#include "externs.h" #if !defined (errno) extern int errno; #endif /* !errno */ +/* Functions to handle reading input on systems that don't restart read(2) + if a signal is received. */ + +#if !defined (HAVE_RESTARTABLE_SYSCALLS) +static unsigned char localbuf[128]; +static int local_index, local_bufused; + +/* Posix and USG systems do not guarantee to restart read () if it is + interrupted by a signal. We do the read ourselves, and restart it + if it returns EINTR. */ +int +getc_with_restart (stream) + FILE *stream; +{ + /* Try local buffering to reduce the number of read(2) calls. */ + if (local_index == local_bufused || local_bufused == 0) + { + while (1) + { + local_bufused = read (fileno (stream), localbuf, sizeof(localbuf)); + if (local_bufused > 0) + break; + else if (local_bufused == 0 || errno != EINTR) + { + local_index = 0; + return EOF; + } + } + local_index = 0; + } + return (localbuf[local_index++]); +} + +int +ungetc_with_restart (c, stream) + int c; + FILE *stream; +{ + if (local_index == 0 || c == EOF) + return EOF; + return (localbuf[--local_index] = c); +} +#endif /* !HAVE_RESTARTABLE_SYSCALLS */ + +#if defined (BUFFERED_INPUT) + +/* A facility similar to stdio, but input-only. */ + #define MAX_INPUT_BUFFER_SIZE 8192 #if !defined (SEEK_CUR) @@ -45,16 +98,19 @@ extern int errno; void free_buffered_stream (); +extern int return_EOF (); + extern int interactive_shell; int bash_input_fd_changed; + /* This provides a way to map from a file descriptor to the buffer associated with that file descriptor, rather than just the other way around. This is needed so that buffers are managed properly in constructs like 3<&4. buffers[x]->b_fd == x -- that is how the correspondence is maintained. */ BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL; -static int nbuffers = 0; +static int nbuffers; #define max(a, b) (((a) > (b)) ? (a) : (b)) @@ -94,9 +150,7 @@ make_buffered_stream (fd, buffer, bufsize) bp->b_fd = fd; bp->b_buffer = buffer; bp->b_size = bufsize; - bp->b_used = 0; - bp->b_inputp = 0; - bp->b_flag = 0; + bp->b_used = bp->b_inputp = bp->b_flag = 0; if (bufsize == 1) bp->b_flag |= B_UNBUFF; return (bp); @@ -145,9 +199,7 @@ check_bash_input (fd) if (nfd == -1) { if (fcntl (fd, F_GETFD, 0) == 0) - report_error - ("cannot allocate new file descriptor for bash input from fd %d: %s", - fd, strerror (errno)); + sys_error ("cannot allocate new file descriptor for bash input from fd %d", fd); return -1; } @@ -155,7 +207,7 @@ check_bash_input (fd) { /* What's this? A stray buffer without an associated open file descriptor? Free up the buffer and report the error. */ - report_error ("check_bash_input: buffer already exists for new fd %d", nfd); + internal_error ("check_bash_input: buffer already exists for new fd %d", nfd); free_buffered_stream (buffers[nfd]); } @@ -185,6 +237,7 @@ check_bash_input (fd) BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists. BUFFERS[fd1] is copied to BUFFERS[fd2]. This is called by the redirect code for constructs like 4<&0 and 3b_fd = fd2; - if (is_bash_input) - { - if (!buffers[fd2]) - fd_to_buffered_stream (fd2); - } + if (is_bash_input && !buffers[fd2]) + fd_to_buffered_stream (fd2); + return (fd2); } @@ -256,9 +307,7 @@ open_buffered_stream (file) int fd; fd = open (file, O_RDONLY); - if (fd == -1) - return ((BUFFERED_STREAM *)NULL); - return (fd_to_buffered_stream (fd)); + return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL); } /* Deallocate a buffered stream and free up its resources. Make sure we @@ -354,7 +403,7 @@ sync_buffered_stream (bfd) int bfd; { BUFFERED_STREAM *bp; - int chars_left; + off_t chars_left; bp = buffers[bfd]; if (!bp) @@ -386,15 +435,16 @@ with_input_from_buffered_stream (bfd, name) char *name; { INPUT_STREAM location; + BUFFERED_STREAM *bp; location.buffered_fd = bfd; /* Make sure the buffered stream exists. */ - fd_to_buffered_stream (bfd); - init_yy_io (buffered_getchar, buffered_ungetchar, st_bstream, name, location); + bp = fd_to_buffered_stream (bfd); + init_yy_io (bp == 0 ? return_EOF : buffered_getchar, + buffered_ungetchar, st_bstream, name, location); } #if defined (TEST) - char * xmalloc(s) int s; @@ -461,4 +511,5 @@ char **argv; } exit(0); } -#endif +#endif /* TEST */ +#endif /* BUFFERED_INPUT */