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
;
196 if (O_TEXT
&& (fcntl (fd
, F_GETFL
) & O_TEXT
) != 0)
197 bp
->b_flag
|= O_TEXT
;
201 /* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
202 static BUFFERED_STREAM
*
203 copy_buffered_stream (bp
)
206 BUFFERED_STREAM
*nbp
;
209 return ((BUFFERED_STREAM
*)NULL
);
211 nbp
= (BUFFERED_STREAM
*)xmalloc (sizeof (BUFFERED_STREAM
));
212 xbcopy ((char *)bp
, (char *)nbp
, sizeof (BUFFERED_STREAM
));
217 set_bash_input_fd (fd
)
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
;
228 fd_is_bash_input (fd
)
231 if (bash_input
.type
== st_bstream
&& bash_input
.location
.buffered_fd
== fd
)
233 else if (interactive_shell
== 0 && default_buffered_input
== fd
)
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. */
243 save_bash_input (fd
, new_fd
)
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. */
252 sync_buffered_stream (fd
);
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
;
259 if (fcntl (fd
, F_GETFD
, 0) == 0)
260 sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd
);
266 /* What's this? A stray buffer without an associated open file
267 descriptor? Free up the buffer and report the error. */
268 internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd
);
269 free_buffered_stream (buffers
[nfd
]);
272 /* Reinitialize bash_input.location. */
273 if (bash_input
.type
== st_bstream
)
275 bash_input
.location
.buffered_fd
= nfd
;
276 fd_to_buffered_stream (nfd
);
277 close_buffered_fd (fd
); /* XXX */
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
++;
288 if (default_buffered_input
== fd
)
289 default_buffered_input
= nfd
;
291 SET_CLOSE_ON_EXEC (nfd
);
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
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()). */
307 check_bash_input (fd
)
310 if (fd_is_bash_input (fd
))
313 return ((save_bash_input (fd
, -1) == -1) ? -1 : 0);
315 return ((sync_buffered_stream (fd
) == -1) ? -1 : 0);
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. */
325 duplicate_buffered_stream (fd1
, fd2
)
328 int is_bash_input
, m
;
334 ALLOCATE_BUFFERS (m
);
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
);
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
;
349 free_buffered_stream (buffers
[fd2
]);
351 buffers
[fd2
] = copy_buffered_stream (buffers
[fd1
]);
353 buffers
[fd2
]->b_fd
= fd2
;
358 fd_to_buffered_stream (fd2
);
359 buffers
[fd2
]->b_flag
|= B_WASBASHINPUT
;
365 /* Return 1 if a seek on FD will succeed. */
366 #define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
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. */
372 fd_to_buffered_stream (fd
)
379 if (fstat (fd
, &sb
) < 0)
382 return ((BUFFERED_STREAM
*)NULL
);
385 size
= (fd_is_seekable (fd
)) ? min (sb
.st_size
, MAX_INPUT_BUFFER_SIZE
) : 1;
388 buffer
= (char *)xmalloc (size
);
390 return (make_buffered_stream (fd
, buffer
, size
));
393 /* Return a buffered stream corresponding to FILE, a file name. */
395 open_buffered_stream (file
)
400 fd
= open (file
, O_RDONLY
);
401 return ((fd
>= 0) ? fd_to_buffered_stream (fd
) : (BUFFERED_STREAM
*)NULL
);
404 /* Deallocate a buffered stream and free up its resources. Make sure we
405 zero out the slot in BUFFERS that points to BP. */
407 free_buffered_stream (bp
)
419 buffers
[n
] = (BUFFERED_STREAM
*)NULL
;
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. */
425 close_buffered_stream (bp
)
433 free_buffered_stream (bp
);
437 /* Deallocate the buffered stream associated with file descriptor FD, and
438 close FD. Return the status of the close on FD. */
440 close_buffered_fd (fd
)
448 if (fd
>= nbuffers
|| !buffers
|| !buffers
[fd
])
450 return (close_buffered_stream (buffers
[fd
]));
453 /* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
454 the old BUFFERED_STREAM. */
456 set_buffered_stream (fd
, bp
)
460 BUFFERED_STREAM
*ret
;
467 /* Read a buffer full of characters from BP, a buffered stream. */
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
)
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
)
486 lseek (bp
->b_fd
, o
, SEEK_SET
);
487 bp
->b_flag
|= B_UNBUFF
;
489 nr
= zread (bp
->b_fd
, bp
->b_buffer
, bp
->b_size
);
493 nr
= zread (bp
->b_fd
, bp
->b_buffer
, bp
->b_size
);
501 bp
->b_flag
|= B_ERROR
;
507 return (bp
->b_buffer
[bp
->b_inputp
++] & 0xFF);
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
516 /* Push C back onto buffered stream BP. */
518 bufstream_ungetc(c
, bp
)
522 if (c
== EOF
|| bp
->b_inputp
== 0)
525 bp
->b_buffer
[--bp
->b_inputp
] = c
;
529 /* Seek backwards on file BFD to synchronize what we've read so far
530 with the underlying file pointer. */
532 sync_buffered_stream (bfd
)
538 if (buffers
== 0 || (bp
= buffers
[bfd
]) == 0)
541 chars_left
= bp
->b_used
- bp
->b_inputp
;
543 lseek (bp
->b_fd
, -chars_left
, SEEK_CUR
);
544 bp
->b_used
= bp
->b_inputp
= 0;
554 return (bufstream_getc (buffers
[bash_input
.location
.buffered_fd
]));
556 /* On DJGPP, ignore \r. */
558 while ((ch
= bufstream_getc (buffers
[bash_input
.location
.buffered_fd
])) == '\r')
565 buffered_ungetchar (c
)
568 return (bufstream_ungetc (c
, buffers
[bash_input
.location
.buffered_fd
]));
571 /* Make input come from file descriptor BFD through a buffered stream. */
573 with_input_from_buffered_stream (bfd
, name
)
577 INPUT_STREAM location
;
580 location
.buffered_fd
= bfd
;
581 /* Make sure the buffered stream exists. */
582 bp
= fd_to_buffered_stream (bfd
);
583 init_yy_io (bp
== 0 ? return_EOF
: buffered_getchar
,
584 buffered_ungetchar
, st_bstream
, name
, location
);
601 return(malloc (size
));
603 return(realloc (s
, size
));
616 while ((c
= bufstream_getc(bp
)) != EOF
)
620 BASH_INPUT bash_input
;
622 struct stat dsb
; /* can be used from gdb */
624 /* imitate /bin/cat */
633 bp
= fd_to_buffered_stream (0);
637 for (i
= 1; i
< argc
; i
++) {
638 if (argv
[i
][0] == '-' && argv
[i
][1] == '\0') {
639 bp
= fd_to_buffered_stream (0);
643 free_buffered_stream (bp
);
645 bp
= open_buffered_stream (argv
[i
]);
649 close_buffered_stream (bp
);
655 #endif /* BUFFERED_INPUT */