1 /* input.c -- functions to perform buffered input with synchronization. */
3 /* Copyright (C) 1992 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 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
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
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
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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)
50 extern void termsig_handler
__P((int));
52 /* Functions to handle reading input on systems that don't restart read(2)
53 if a signal is received. */
55 static char localbuf
[128];
56 static int local_index
= 0, local_bufused
= 0;
58 /* Posix and USG systems do not guarantee to restart read () if it is
59 interrupted by a signal. We do the read ourselves, and restart it
60 if it returns EINTR. */
62 getc_with_restart (stream
)
69 /* Try local buffering to reduce the number of read(2) calls. */
70 if (local_index
== local_bufused
|| local_bufused
== 0)
75 local_bufused
= read (fileno (stream
), localbuf
, sizeof(localbuf
));
76 if (local_bufused
> 0)
78 else if (local_bufused
== 0 || errno
!= EINTR
)
86 uc
= localbuf
[local_index
++];
91 ungetc_with_restart (c
, stream
)
95 if (local_index
== 0 || c
== EOF
)
97 localbuf
[--local_index
] = c
;
101 #if defined (BUFFERED_INPUT)
103 /* A facility similar to stdio, but input-only. */
105 #if defined (USING_BASH_MALLOC)
106 # define MAX_INPUT_BUFFER_SIZE 8176
108 # define MAX_INPUT_BUFFER_SIZE 8192
111 #if !defined (SEEK_CUR)
113 #endif /* !SEEK_CUR */
118 #define max(a, b) (((a) > (b)) ? (a) : (b))
122 #define min(a, b) ((a) > (b) ? (b) : (a))
124 extern int interactive_shell
;
126 int bash_input_fd_changed
;
128 /* This provides a way to map from a file descriptor to the buffer
129 associated with that file descriptor, rather than just the other
130 way around. This is needed so that buffers are managed properly
131 in constructs like 3<&4. buffers[x]->b_fd == x -- that is how the
132 correspondence is maintained. */
133 static BUFFERED_STREAM
**buffers
= (BUFFERED_STREAM
**)NULL
;
136 #define ALLOCATE_BUFFERS(n) \
137 do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
139 /* Make sure `buffers' has at least N elements. */
144 register int i
, orig_nbuffers
;
146 orig_nbuffers
= nbuffers
;
148 buffers
= (BUFFERED_STREAM
**)xrealloc
149 (buffers
, nbuffers
* sizeof (BUFFERED_STREAM
*));
151 /* Zero out the new buffers. */
152 for (i
= orig_nbuffers
; i
< nbuffers
; i
++)
153 buffers
[i
] = (BUFFERED_STREAM
*)NULL
;
156 /* Construct and return a BUFFERED_STREAM corresponding to file descriptor
158 static BUFFERED_STREAM
*
159 make_buffered_stream (fd
, buffer
, bufsize
)
166 bp
= (BUFFERED_STREAM
*)xmalloc (sizeof (BUFFERED_STREAM
));
167 ALLOCATE_BUFFERS (fd
);
170 bp
->b_buffer
= buffer
;
171 bp
->b_size
= bufsize
;
172 bp
->b_used
= bp
->b_inputp
= bp
->b_flag
= 0;
174 bp
->b_flag
|= B_UNBUFF
;
178 /* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
179 static BUFFERED_STREAM
*
180 copy_buffered_stream (bp
)
183 BUFFERED_STREAM
*nbp
;
186 return ((BUFFERED_STREAM
*)NULL
);
188 nbp
= (BUFFERED_STREAM
*)xmalloc (sizeof (BUFFERED_STREAM
));
189 xbcopy ((char *)bp
, (char *)nbp
, sizeof (BUFFERED_STREAM
));
194 set_bash_input_fd (fd
)
197 if (bash_input
.type
== st_bstream
)
198 bash_input
.location
.buffered_fd
= fd
;
199 else if (interactive_shell
== 0)
200 default_buffered_input
= fd
;
205 fd_is_bash_input (fd
)
208 if (bash_input
.type
== st_bstream
&& bash_input
.location
.buffered_fd
== fd
)
210 else if (interactive_shell
== 0 && default_buffered_input
== fd
)
215 /* Save the buffered stream corresponding to file descriptor FD (which bash
216 is using to read input) to a buffered stream associated with NEW_FD. If
217 NEW_FD is -1, a new file descriptor is allocated with fcntl. The new
218 file descriptor is returned on success, -1 on error. */
220 save_bash_input (fd
, new_fd
)
225 /* Sync the stream so we can re-read from the new file descriptor. We
226 might be able to avoid this by copying the buffered stream verbatim
227 to the new file descriptor. */
229 sync_buffered_stream (fd
);
231 /* Now take care of duplicating the file descriptor that bash is
232 using for input, so we can reinitialize it later. */
233 nfd
= (new_fd
== -1) ? fcntl (fd
, F_DUPFD
, 10) : new_fd
;
236 if (fcntl (fd
, F_GETFD
, 0) == 0)
237 sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd
);
243 /* What's this? A stray buffer without an associated open file
244 descriptor? Free up the buffer and report the error. */
245 internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd
);
246 free_buffered_stream (buffers
[nfd
]);
249 /* Reinitialize bash_input.location. */
250 if (bash_input
.type
== st_bstream
)
252 bash_input
.location
.buffered_fd
= nfd
;
253 fd_to_buffered_stream (nfd
);
254 close_buffered_fd (fd
); /* XXX */
257 /* If the current input type is not a buffered stream, but the shell
258 is not interactive and therefore using a buffered stream to read
259 input (e.g. with an `eval exec 3>output' inside a script), note
260 that the input fd has been changed. pop_stream() looks at this
261 value and adjusts the input fd to the new value of
262 default_buffered_input accordingly. */
263 bash_input_fd_changed
++;
265 if (default_buffered_input
== fd
)
266 default_buffered_input
= nfd
;
268 SET_CLOSE_ON_EXEC (nfd
);
272 /* Check that file descriptor FD is not the one that bash is currently
273 using to read input from a script. FD is about to be duplicated onto,
274 which means that the kernel will close it for us. If FD is the bash
275 input file descriptor, we need to seek backwards in the script (if
276 possible and necessary -- scripts read from stdin are still unbuffered),
277 allocate a new file descriptor to use for bash input, and re-initialize
278 the buffered stream. Make sure the file descriptor used to save bash
279 input is set close-on-exec. Returns 0 on success, -1 on failure. This
280 works only if fd is > 0 -- if fd == 0 and bash is reading input from
281 fd 0, save_bash_input is used instead, to cooperate with input
282 redirection (look at redir.c:add_undo_redirect()). */
284 check_bash_input (fd
)
287 if (fd_is_bash_input (fd
))
290 return ((save_bash_input (fd
, -1) == -1) ? -1 : 0);
292 return ((sync_buffered_stream (fd
) == -1) ? -1 : 0);
297 /* This is the buffered stream analogue of dup2(fd1, fd2). The
298 BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
299 BUFFERS[fd1] is copied to BUFFERS[fd2]. This is called by the
300 redirect code for constructs like 4<&0 and 3</etc/rc.local. */
302 duplicate_buffered_stream (fd1
, fd2
)
305 int is_bash_input
, m
;
311 ALLOCATE_BUFFERS (m
);
313 /* If FD2 is the file descriptor bash is currently using for shell input,
314 we need to do some extra work to make sure that the buffered stream
315 actually exists (it might not if fd1 was not active, and the copy
316 didn't actually do anything). */
317 is_bash_input
= (bash_input
.type
== st_bstream
) &&
318 (bash_input
.location
.buffered_fd
== fd2
);
322 /* If the two objects share the same b_buffer, don't free it. */
323 if (buffers
[fd1
] && buffers
[fd1
]->b_buffer
&& buffers
[fd1
]->b_buffer
== buffers
[fd2
]->b_buffer
)
324 buffers
[fd2
] = (BUFFERED_STREAM
*)NULL
;
326 free_buffered_stream (buffers
[fd2
]);
328 buffers
[fd2
] = copy_buffered_stream (buffers
[fd1
]);
330 buffers
[fd2
]->b_fd
= fd2
;
335 fd_to_buffered_stream (fd2
);
336 buffers
[fd2
]->b_flag
|= B_WASBASHINPUT
;
342 /* Return 1 if a seek on FD will succeed. */
344 # define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
346 # define fd_is_seekable(fd) 0
347 #endif /* __CYGWIN__ */
349 /* Take FD, a file descriptor, and create and return a buffered stream
350 corresponding to it. If something is wrong and the file descriptor
351 is invalid, return a NULL stream. */
353 fd_to_buffered_stream (fd
)
360 if (fstat (fd
, &sb
) < 0)
363 return ((BUFFERED_STREAM
*)NULL
);
366 size
= (fd_is_seekable (fd
)) ? min (sb
.st_size
, MAX_INPUT_BUFFER_SIZE
) : 1;
369 buffer
= (char *)xmalloc (size
);
371 return (make_buffered_stream (fd
, buffer
, size
));
374 /* Return a buffered stream corresponding to FILE, a file name. */
376 open_buffered_stream (file
)
381 fd
= open (file
, O_RDONLY
);
382 return ((fd
>= 0) ? fd_to_buffered_stream (fd
) : (BUFFERED_STREAM
*)NULL
);
385 /* Deallocate a buffered stream and free up its resources. Make sure we
386 zero out the slot in BUFFERS that points to BP. */
388 free_buffered_stream (bp
)
400 buffers
[n
] = (BUFFERED_STREAM
*)NULL
;
403 /* Close the file descriptor associated with BP, a buffered stream, and free
404 up the stream. Return the status of closing BP's file descriptor. */
406 close_buffered_stream (bp
)
414 free_buffered_stream (bp
);
418 /* Deallocate the buffered stream associated with file descriptor FD, and
419 close FD. Return the status of the close on FD. */
421 close_buffered_fd (fd
)
429 if (fd
>= nbuffers
|| !buffers
|| !buffers
[fd
])
431 return (close_buffered_stream (buffers
[fd
]));
434 /* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
435 the old BUFFERED_STREAM. */
437 set_buffered_stream (fd
, bp
)
441 BUFFERED_STREAM
*ret
;
448 /* Read a buffer full of characters from BP, a buffered stream. */
456 nr
= zread (bp
->b_fd
, bp
->b_buffer
, bp
->b_size
);
464 bp
->b_flag
|= B_ERROR
;
468 #if defined (__CYGWIN__)
469 /* If on cygwin, translate \r\n to \n. */
470 if (nr
>= 2 && bp
->b_buffer
[nr
- 2] == '\r' && bp
->b_buffer
[nr
- 1] == '\n')
472 bp
->b_buffer
[nr
- 2] = '\n';
479 return (bp
->b_buffer
[bp
->b_inputp
++] & 0xFF);
482 /* Get a character from buffered stream BP. */
483 #define bufstream_getc(bp) \
484 (bp->b_inputp == bp->b_used || !bp->b_used) \
485 ? b_fill_buffer (bp) \
486 : bp->b_buffer[bp->b_inputp++] & 0xFF
488 /* Push C back onto buffered stream BP. */
490 bufstream_ungetc(c
, bp
)
494 if (c
== EOF
|| bp
->b_inputp
== 0)
497 bp
->b_buffer
[--bp
->b_inputp
] = c
;
501 /* Seek backwards on file BFD to synchronize what we've read so far
502 with the underlying file pointer. */
504 sync_buffered_stream (bfd
)
510 if (buffers
== 0 || (bp
= buffers
[bfd
]) == 0)
513 chars_left
= bp
->b_used
- bp
->b_inputp
;
515 lseek (bp
->b_fd
, -chars_left
, SEEK_CUR
);
516 bp
->b_used
= bp
->b_inputp
= 0;
526 return (bufstream_getc (buffers
[bash_input
.location
.buffered_fd
]));
528 /* On DJGPP, ignore \r. */
530 while ((ch
= bufstream_getc (buffers
[bash_input
.location
.buffered_fd
])) == '\r')
537 buffered_ungetchar (c
)
540 return (bufstream_ungetc (c
, buffers
[bash_input
.location
.buffered_fd
]));
543 /* Make input come from file descriptor BFD through a buffered stream. */
545 with_input_from_buffered_stream (bfd
, name
)
549 INPUT_STREAM location
;
552 location
.buffered_fd
= bfd
;
553 /* Make sure the buffered stream exists. */
554 bp
= fd_to_buffered_stream (bfd
);
555 init_yy_io (bp
== 0 ? return_EOF
: buffered_getchar
,
556 buffered_ungetchar
, st_bstream
, name
, location
);
573 return(malloc (size
));
575 return(realloc (s
, size
));
588 while ((c
= bufstream_getc(bp
)) != EOF
)
592 BASH_INPUT bash_input
;
594 struct stat dsb
; /* can be used from gdb */
596 /* imitate /bin/cat */
605 bp
= fd_to_buffered_stream (0);
609 for (i
= 1; i
< argc
; i
++) {
610 if (argv
[i
][0] == '-' && argv
[i
][1] == '\0') {
611 bp
= fd_to_buffered_stream (0);
615 free_buffered_stream (bp
);
617 bp
= open_buffered_stream (argv
[i
]);
621 close_buffered_stream (bp
);
627 #endif /* BUFFERED_INPUT */