1 /* input.c -- functions to perform buffered input with synchronization. */
3 /* Copyright (C) 1992-2009 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
23 #include "bashtypes.h"
24 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
25 # include <sys/file.h>
28 #include "posixstat.h"
32 #if defined (HAVE_UNISTD_H)
51 # define X_EAGAIN EAGAIN
56 #if defined (EWOULDBLOCK)
57 # define X_EWOULDBLOCK EWOULDBLOCK
59 # define X_EWOULDBLOCK -99
62 extern void termsig_handler
__P((int));
64 /* Functions to handle reading input on systems that don't restart read(2)
65 if a signal is received. */
67 static char localbuf
[128];
68 static int local_index
= 0, local_bufused
= 0;
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. */
74 getc_with_restart (stream
)
81 /* Try local buffering to reduce the number of read(2) calls. */
82 if (local_index
== local_bufused
|| local_bufused
== 0)
87 local_bufused
= read (fileno (stream
), localbuf
, sizeof(localbuf
));
88 if (local_bufused
> 0)
90 else if (errno
== X_EAGAIN
|| errno
== X_EWOULDBLOCK
)
92 if (sh_unset_nodelay_mode (fileno (stream
)) < 0)
94 sys_error (_("cannot reset nodelay mode for fd %d"), fileno (stream
));
99 else if (local_bufused
== 0 || errno
!= EINTR
)
107 uc
= localbuf
[local_index
++];
112 ungetc_with_restart (c
, stream
)
116 if (local_index
== 0 || c
== EOF
)
118 localbuf
[--local_index
] = c
;
122 #if defined (BUFFERED_INPUT)
124 /* A facility similar to stdio, but input-only. */
126 #if defined (USING_BASH_MALLOC)
127 # define MAX_INPUT_BUFFER_SIZE 8176
129 # define MAX_INPUT_BUFFER_SIZE 8192
132 #if !defined (SEEK_CUR)
134 #endif /* !SEEK_CUR */
139 #define max(a, b) (((a) > (b)) ? (a) : (b))
143 #define min(a, b) ((a) > (b) ? (b) : (a))
145 extern int interactive_shell
;
147 int bash_input_fd_changed
;
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. */
154 static BUFFERED_STREAM
**buffers
= (BUFFERED_STREAM
**)NULL
;
157 #define ALLOCATE_BUFFERS(n) \
158 do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
160 /* Make sure `buffers' has at least N elements. */
165 register int i
, orig_nbuffers
;
167 orig_nbuffers
= nbuffers
;
169 buffers
= (BUFFERED_STREAM
**)xrealloc
170 (buffers
, nbuffers
* sizeof (BUFFERED_STREAM
*));
172 /* Zero out the new buffers. */
173 for (i
= orig_nbuffers
; i
< nbuffers
; i
++)
174 buffers
[i
] = (BUFFERED_STREAM
*)NULL
;
177 /* Construct and return a BUFFERED_STREAM corresponding to file descriptor
179 static BUFFERED_STREAM
*
180 make_buffered_stream (fd
, buffer
, bufsize
)
187 bp
= (BUFFERED_STREAM
*)xmalloc (sizeof (BUFFERED_STREAM
));
188 ALLOCATE_BUFFERS (fd
);
191 bp
->b_buffer
= buffer
;
192 bp
->b_size
= bufsize
;
193 bp
->b_used
= bp
->b_inputp
= bp
->b_flag
= 0;
195 bp
->b_flag
|= B_UNBUFF
;
199 /* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
200 static BUFFERED_STREAM
*
201 copy_buffered_stream (bp
)
204 BUFFERED_STREAM
*nbp
;
207 return ((BUFFERED_STREAM
*)NULL
);
209 nbp
= (BUFFERED_STREAM
*)xmalloc (sizeof (BUFFERED_STREAM
));
210 xbcopy ((char *)bp
, (char *)nbp
, sizeof (BUFFERED_STREAM
));
215 set_bash_input_fd (fd
)
218 if (bash_input
.type
== st_bstream
)
219 bash_input
.location
.buffered_fd
= fd
;
220 else if (interactive_shell
== 0)
221 default_buffered_input
= fd
;
226 fd_is_bash_input (fd
)
229 if (bash_input
.type
== st_bstream
&& bash_input
.location
.buffered_fd
== fd
)
231 else if (interactive_shell
== 0 && default_buffered_input
== fd
)
236 /* Save the buffered stream corresponding to file descriptor FD (which bash
237 is using to read input) to a buffered stream associated with NEW_FD. If
238 NEW_FD is -1, a new file descriptor is allocated with fcntl. The new
239 file descriptor is returned on success, -1 on error. */
241 save_bash_input (fd
, new_fd
)
246 /* Sync the stream so we can re-read from the new file descriptor. We
247 might be able to avoid this by copying the buffered stream verbatim
248 to the new file descriptor. */
250 sync_buffered_stream (fd
);
252 /* Now take care of duplicating the file descriptor that bash is
253 using for input, so we can reinitialize it later. */
254 nfd
= (new_fd
== -1) ? fcntl (fd
, F_DUPFD
, 10) : new_fd
;
257 if (fcntl (fd
, F_GETFD
, 0) == 0)
258 sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd
);
264 /* What's this? A stray buffer without an associated open file
265 descriptor? Free up the buffer and report the error. */
266 internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd
);
267 free_buffered_stream (buffers
[nfd
]);
270 /* Reinitialize bash_input.location. */
271 if (bash_input
.type
== st_bstream
)
273 bash_input
.location
.buffered_fd
= nfd
;
274 fd_to_buffered_stream (nfd
);
275 close_buffered_fd (fd
); /* XXX */
278 /* If the current input type is not a buffered stream, but the shell
279 is not interactive and therefore using a buffered stream to read
280 input (e.g. with an `eval exec 3>output' inside a script), note
281 that the input fd has been changed. pop_stream() looks at this
282 value and adjusts the input fd to the new value of
283 default_buffered_input accordingly. */
284 bash_input_fd_changed
++;
286 if (default_buffered_input
== fd
)
287 default_buffered_input
= nfd
;
289 SET_CLOSE_ON_EXEC (nfd
);
293 /* Check that file descriptor FD is not the one that bash is currently
294 using to read input from a script. FD is about to be duplicated onto,
295 which means that the kernel will close it for us. If FD is the bash
296 input file descriptor, we need to seek backwards in the script (if
297 possible and necessary -- scripts read from stdin are still unbuffered),
298 allocate a new file descriptor to use for bash input, and re-initialize
299 the buffered stream. Make sure the file descriptor used to save bash
300 input is set close-on-exec. Returns 0 on success, -1 on failure. This
301 works only if fd is > 0 -- if fd == 0 and bash is reading input from
302 fd 0, save_bash_input is used instead, to cooperate with input
303 redirection (look at redir.c:add_undo_redirect()). */
305 check_bash_input (fd
)
308 if (fd_is_bash_input (fd
))
311 return ((save_bash_input (fd
, -1) == -1) ? -1 : 0);
313 return ((sync_buffered_stream (fd
) == -1) ? -1 : 0);
318 /* This is the buffered stream analogue of dup2(fd1, fd2). The
319 BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
320 BUFFERS[fd1] is copied to BUFFERS[fd2]. This is called by the
321 redirect code for constructs like 4<&0 and 3</etc/rc.local. */
323 duplicate_buffered_stream (fd1
, fd2
)
326 int is_bash_input
, m
;
332 ALLOCATE_BUFFERS (m
);
334 /* If FD2 is the file descriptor bash is currently using for shell input,
335 we need to do some extra work to make sure that the buffered stream
336 actually exists (it might not if fd1 was not active, and the copy
337 didn't actually do anything). */
338 is_bash_input
= (bash_input
.type
== st_bstream
) &&
339 (bash_input
.location
.buffered_fd
== fd2
);
343 /* If the two objects share the same b_buffer, don't free it. */
344 if (buffers
[fd1
] && buffers
[fd1
]->b_buffer
&& buffers
[fd1
]->b_buffer
== buffers
[fd2
]->b_buffer
)
345 buffers
[fd2
] = (BUFFERED_STREAM
*)NULL
;
347 free_buffered_stream (buffers
[fd2
]);
349 buffers
[fd2
] = copy_buffered_stream (buffers
[fd1
]);
351 buffers
[fd2
]->b_fd
= fd2
;
356 fd_to_buffered_stream (fd2
);
357 buffers
[fd2
]->b_flag
|= B_WASBASHINPUT
;
363 /* Return 1 if a seek on FD will succeed. */
365 # define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
367 # define fd_is_seekable(fd) 0
368 #endif /* __CYGWIN__ */
370 /* Take FD, a file descriptor, and create and return a buffered stream
371 corresponding to it. If something is wrong and the file descriptor
372 is invalid, return a NULL stream. */
374 fd_to_buffered_stream (fd
)
381 if (fstat (fd
, &sb
) < 0)
384 return ((BUFFERED_STREAM
*)NULL
);
387 size
= (fd_is_seekable (fd
)) ? min (sb
.st_size
, MAX_INPUT_BUFFER_SIZE
) : 1;
390 buffer
= (char *)xmalloc (size
);
392 return (make_buffered_stream (fd
, buffer
, size
));
395 /* Return a buffered stream corresponding to FILE, a file name. */
397 open_buffered_stream (file
)
402 fd
= open (file
, O_RDONLY
);
403 return ((fd
>= 0) ? fd_to_buffered_stream (fd
) : (BUFFERED_STREAM
*)NULL
);
406 /* Deallocate a buffered stream and free up its resources. Make sure we
407 zero out the slot in BUFFERS that points to BP. */
409 free_buffered_stream (bp
)
421 buffers
[n
] = (BUFFERED_STREAM
*)NULL
;
424 /* Close the file descriptor associated with BP, a buffered stream, and free
425 up the stream. Return the status of closing BP's file descriptor. */
427 close_buffered_stream (bp
)
435 free_buffered_stream (bp
);
439 /* Deallocate the buffered stream associated with file descriptor FD, and
440 close FD. Return the status of the close on FD. */
442 close_buffered_fd (fd
)
450 if (fd
>= nbuffers
|| !buffers
|| !buffers
[fd
])
452 return (close_buffered_stream (buffers
[fd
]));
455 /* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
456 the old BUFFERED_STREAM. */
458 set_buffered_stream (fd
, bp
)
462 BUFFERED_STREAM
*ret
;
469 /* Read a buffer full of characters from BP, a buffered stream. */
477 nr
= zread (bp
->b_fd
, bp
->b_buffer
, bp
->b_size
);
485 bp
->b_flag
|= B_ERROR
;
489 #if defined (__CYGWIN__)
490 /* If on cygwin, translate \r\n to \n. */
491 if (nr
>= 2 && bp
->b_buffer
[nr
- 2] == '\r' && bp
->b_buffer
[nr
- 1] == '\n')
493 bp
->b_buffer
[nr
- 2] = '\n';
500 return (bp
->b_buffer
[bp
->b_inputp
++] & 0xFF);
503 /* Get a character from buffered stream BP. */
504 #define bufstream_getc(bp) \
505 (bp->b_inputp == bp->b_used || !bp->b_used) \
506 ? b_fill_buffer (bp) \
507 : bp->b_buffer[bp->b_inputp++] & 0xFF
509 /* Push C back onto buffered stream BP. */
511 bufstream_ungetc(c
, bp
)
515 if (c
== EOF
|| bp
->b_inputp
== 0)
518 bp
->b_buffer
[--bp
->b_inputp
] = c
;
522 /* Seek backwards on file BFD to synchronize what we've read so far
523 with the underlying file pointer. */
525 sync_buffered_stream (bfd
)
531 if (buffers
== 0 || (bp
= buffers
[bfd
]) == 0)
534 chars_left
= bp
->b_used
- bp
->b_inputp
;
536 lseek (bp
->b_fd
, -chars_left
, SEEK_CUR
);
537 bp
->b_used
= bp
->b_inputp
= 0;
547 return (bufstream_getc (buffers
[bash_input
.location
.buffered_fd
]));
549 /* On DJGPP, ignore \r. */
551 while ((ch
= bufstream_getc (buffers
[bash_input
.location
.buffered_fd
])) == '\r')
558 buffered_ungetchar (c
)
561 return (bufstream_ungetc (c
, buffers
[bash_input
.location
.buffered_fd
]));
564 /* Make input come from file descriptor BFD through a buffered stream. */
566 with_input_from_buffered_stream (bfd
, name
)
570 INPUT_STREAM location
;
573 location
.buffered_fd
= bfd
;
574 /* Make sure the buffered stream exists. */
575 bp
= fd_to_buffered_stream (bfd
);
576 init_yy_io (bp
== 0 ? return_EOF
: buffered_getchar
,
577 buffered_ungetchar
, st_bstream
, name
, location
);
594 return(malloc (size
));
596 return(realloc (s
, size
));
609 while ((c
= bufstream_getc(bp
)) != EOF
)
613 BASH_INPUT bash_input
;
615 struct stat dsb
; /* can be used from gdb */
617 /* imitate /bin/cat */
626 bp
= fd_to_buffered_stream (0);
630 for (i
= 1; i
< argc
; i
++) {
631 if (argv
[i
][0] == '-' && argv
[i
][1] == '\0') {
632 bp
= fd_to_buffered_stream (0);
636 free_buffered_stream (bp
);
638 bp
= open_buffered_stream (argv
[i
]);
642 close_buffered_stream (bp
);
648 #endif /* BUFFERED_INPUT */