]> git.ipfire.org Git - thirdparty/bash.git/blame - input.c
Imported from ../bash-3.2.tar.gz.
[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"
b80f6443 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"
b80f6443
JA
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"
0628567a 44#include "quit.h"
726f6388
JA
45
46#if !defined (errno)
47extern int errno;
48#endif /* !errno */
49
0628567a
JA
50extern void termsig_handler __P((int));
51
ccc6cda3
JA
52/* Functions to handle reading input on systems that don't restart read(2)
53 if a signal is received. */
54
f73dda09 55static char localbuf[128];
95732b49 56static int local_index = 0, local_bufused = 0;
ccc6cda3
JA
57
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. */
61int
62getc_with_restart (stream)
63 FILE *stream;
64{
f73dda09
JA
65 unsigned char uc;
66
0628567a
JA
67 CHECK_TERMSIG;
68
ccc6cda3
JA
69 /* Try local buffering to reduce the number of read(2) calls. */
70 if (local_index == local_bufused || local_bufused == 0)
71 {
72 while (1)
73 {
0628567a 74 CHECK_TERMSIG;
ccc6cda3
JA
75 local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
76 if (local_bufused > 0)
77 break;
78 else if (local_bufused == 0 || errno != EINTR)
79 {
80 local_index = 0;
81 return EOF;
82 }
83 }
84 local_index = 0;
85 }
f73dda09
JA
86 uc = localbuf[local_index++];
87 return uc;
ccc6cda3
JA
88}
89
90int
91ungetc_with_restart (c, stream)
92 int c;
93 FILE *stream;
94{
95 if (local_index == 0 || c == EOF)
96 return EOF;
f73dda09
JA
97 localbuf[--local_index] = c;
98 return c;
ccc6cda3 99}
ccc6cda3
JA
100
101#if defined (BUFFERED_INPUT)
102
103/* A facility similar to stdio, but input-only. */
104
bb70624e
JA
105#if defined (USING_BASH_MALLOC)
106# define MAX_INPUT_BUFFER_SIZE 8176
107#else
108# define MAX_INPUT_BUFFER_SIZE 8192
109#endif
726f6388
JA
110
111#if !defined (SEEK_CUR)
112# define SEEK_CUR 1
113#endif /* !SEEK_CUR */
114
28ef6c31
JA
115#ifdef max
116# undef max
117#endif
118#define max(a, b) (((a) > (b)) ? (a) : (b))
119#ifdef min
120# undef min
121#endif
122#define min(a, b) ((a) > (b) ? (b) : (a))
123
726f6388
JA
124extern int interactive_shell;
125
126int bash_input_fd_changed;
ccc6cda3 127
726f6388
JA
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. */
cce855bc 133static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
ccc6cda3 134static int nbuffers;
726f6388 135
726f6388
JA
136#define ALLOCATE_BUFFERS(n) \
137 do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
138
139/* Make sure `buffers' has at least N elements. */
140static void
141allocate_buffers (n)
142 int n;
143{
144 register int i, orig_nbuffers;
145
146 orig_nbuffers = nbuffers;
147 nbuffers = n + 20;
148 buffers = (BUFFERED_STREAM **)xrealloc
149 (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
150
151 /* Zero out the new buffers. */
152 for (i = orig_nbuffers; i < nbuffers; i++)
153 buffers[i] = (BUFFERED_STREAM *)NULL;
154}
155
156/* Construct and return a BUFFERED_STREAM corresponding to file descriptor
157 FD, using BUFFER. */
158static BUFFERED_STREAM *
159make_buffered_stream (fd, buffer, bufsize)
160 int fd;
161 char *buffer;
cce855bc 162 size_t bufsize;
726f6388
JA
163{
164 BUFFERED_STREAM *bp;
165
166 bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
167 ALLOCATE_BUFFERS (fd);
168 buffers[fd] = bp;
169 bp->b_fd = fd;
170 bp->b_buffer = buffer;
171 bp->b_size = bufsize;
ccc6cda3 172 bp->b_used = bp->b_inputp = bp->b_flag = 0;
726f6388
JA
173 if (bufsize == 1)
174 bp->b_flag |= B_UNBUFF;
175 return (bp);
176}
177
178/* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
179static BUFFERED_STREAM *
180copy_buffered_stream (bp)
181 BUFFERED_STREAM *bp;
182{
183 BUFFERED_STREAM *nbp;
184
185 if (!bp)
186 return ((BUFFERED_STREAM *)NULL);
187
188 nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
189 xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
190 return (nbp);
191}
192
28ef6c31
JA
193int
194set_bash_input_fd (fd)
195 int fd;
196{
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;
201 return 0;
202}
203
204int
205fd_is_bash_input (fd)
206 int fd;
207{
208 if (bash_input.type == st_bstream && bash_input.location.buffered_fd == fd)
209 return 1;
210 else if (interactive_shell == 0 && default_buffered_input == fd)
211 return 1;
212 return 0;
213}
214
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. */
219int
220save_bash_input (fd, new_fd)
221 int fd, new_fd;
222{
223 int nfd;
224
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. */
228 if (buffers[fd])
229 sync_buffered_stream (fd);
230
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;
234 if (nfd == -1)
235 {
236 if (fcntl (fd, F_GETFD, 0) == 0)
b80f6443 237 sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd);
28ef6c31
JA
238 return -1;
239 }
240
241 if (buffers[nfd])
242 {
243 /* What's this? A stray buffer without an associated open file
244 descriptor? Free up the buffer and report the error. */
b80f6443 245 internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd);
28ef6c31
JA
246 free_buffered_stream (buffers[nfd]);
247 }
248
249 /* Reinitialize bash_input.location. */
250 if (bash_input.type == st_bstream)
251 {
252 bash_input.location.buffered_fd = nfd;
253 fd_to_buffered_stream (nfd);
254 close_buffered_fd (fd); /* XXX */
255 }
256 else
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++;
264
265 if (default_buffered_input == fd)
266 default_buffered_input = nfd;
267
268 SET_CLOSE_ON_EXEC (nfd);
269 return nfd;
270}
271
726f6388
JA
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
28ef6c31
JA
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()). */
726f6388
JA
283int
284check_bash_input (fd)
285 int fd;
286{
b80f6443
JA
287 if (fd_is_bash_input (fd))
288 {
289 if (fd > 0)
290 return ((save_bash_input (fd, -1) == -1) ? -1 : 0);
291 else if (fd == 0)
292 return ((sync_buffered_stream (fd) == -1) ? -1 : 0);
293 }
726f6388
JA
294 return 0;
295}
296
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. */
ccc6cda3 301int
726f6388
JA
302duplicate_buffered_stream (fd1, fd2)
303 int fd1, fd2;
304{
305 int is_bash_input, m;
306
307 if (fd1 == fd2)
308 return 0;
309
310 m = max (fd1, fd2);
311 ALLOCATE_BUFFERS (m);
312
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);
319
320 if (buffers[fd2])
95732b49
JA
321 {
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;
325 else
326 free_buffered_stream (buffers[fd2]);
327 }
726f6388
JA
328 buffers[fd2] = copy_buffered_stream (buffers[fd1]);
329 if (buffers[fd2])
330 buffers[fd2]->b_fd = fd2;
331
28ef6c31
JA
332 if (is_bash_input)
333 {
334 if (!buffers[fd2])
335 fd_to_buffered_stream (fd2);
336 buffers[fd2]->b_flag |= B_WASBASHINPUT;
337 }
ccc6cda3 338
726f6388
JA
339 return (fd2);
340}
341
342/* Return 1 if a seek on FD will succeed. */
28ef6c31 343#ifndef __CYGWIN__
cce855bc
JA
344# define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
345#else
346# define fd_is_seekable(fd) 0
28ef6c31 347#endif /* __CYGWIN__ */
726f6388
JA
348
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. */
352BUFFERED_STREAM *
353fd_to_buffered_stream (fd)
354 int fd;
355{
356 char *buffer;
cce855bc 357 size_t size;
726f6388
JA
358 struct stat sb;
359
360 if (fstat (fd, &sb) < 0)
361 {
362 close (fd);
363 return ((BUFFERED_STREAM *)NULL);
364 }
365
28ef6c31
JA
366 size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
367 if (size == 0)
726f6388 368 size = 1;
726f6388
JA
369 buffer = (char *)xmalloc (size);
370
371 return (make_buffered_stream (fd, buffer, size));
372}
373
374/* Return a buffered stream corresponding to FILE, a file name. */
375BUFFERED_STREAM *
376open_buffered_stream (file)
377 char *file;
378{
379 int fd;
380
381 fd = open (file, O_RDONLY);
ccc6cda3 382 return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
726f6388
JA
383}
384
385/* Deallocate a buffered stream and free up its resources. Make sure we
386 zero out the slot in BUFFERS that points to BP. */
387void
388free_buffered_stream (bp)
389 BUFFERED_STREAM *bp;
390{
391 int n;
392
393 if (!bp)
394 return;
395
396 n = bp->b_fd;
397 if (bp->b_buffer)
398 free (bp->b_buffer);
399 free (bp);
400 buffers[n] = (BUFFERED_STREAM *)NULL;
401}
402
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. */
405int
406close_buffered_stream (bp)
407 BUFFERED_STREAM *bp;
408{
409 int fd;
410
411 if (!bp)
412 return (0);
413 fd = bp->b_fd;
414 free_buffered_stream (bp);
415 return (close (fd));
416}
417
418/* Deallocate the buffered stream associated with file descriptor FD, and
419 close FD. Return the status of the close on FD. */
420int
421close_buffered_fd (fd)
422 int fd;
423{
f73dda09
JA
424 if (fd < 0)
425 {
426 errno = EBADF;
427 return -1;
428 }
726f6388
JA
429 if (fd >= nbuffers || !buffers || !buffers[fd])
430 return (close (fd));
431 return (close_buffered_stream (buffers[fd]));
432}
433
cce855bc
JA
434/* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
435 the old BUFFERED_STREAM. */
436BUFFERED_STREAM *
437set_buffered_stream (fd, bp)
438 int fd;
439 BUFFERED_STREAM *bp;
440{
441 BUFFERED_STREAM *ret;
442
443 ret = buffers[fd];
444 buffers[fd] = bp;
445 return ret;
446}
447
726f6388
JA
448/* Read a buffer full of characters from BP, a buffered stream. */
449static int
450b_fill_buffer (bp)
451 BUFFERED_STREAM *bp;
452{
f73dda09
JA
453 ssize_t nr;
454
0628567a 455 CHECK_TERMSIG;
f73dda09
JA
456 nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
457 if (nr <= 0)
726f6388 458 {
f73dda09 459 bp->b_used = 0;
726f6388 460 bp->b_buffer[0] = 0;
f73dda09 461 if (nr == 0)
726f6388
JA
462 bp->b_flag |= B_EOF;
463 else
464 bp->b_flag |= B_ERROR;
465 return (EOF);
466 }
f73dda09
JA
467
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')
471 {
472 bp->b_buffer[nr - 2] = '\n';
473 nr--;
474 }
475#endif
476
477 bp->b_used = nr;
726f6388
JA
478 bp->b_inputp = 0;
479 return (bp->b_buffer[bp->b_inputp++] & 0xFF);
480}
481
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
487
488/* Push C back onto buffered stream BP. */
489static int
490bufstream_ungetc(c, bp)
491 int c;
492 BUFFERED_STREAM *bp;
493{
494 if (c == EOF || bp->b_inputp == 0)
495 return (EOF);
496
497 bp->b_buffer[--bp->b_inputp] = c;
498 return (c);
499}
500
501/* Seek backwards on file BFD to synchronize what we've read so far
502 with the underlying file pointer. */
503int
504sync_buffered_stream (bfd)
505 int bfd;
506{
507 BUFFERED_STREAM *bp;
ccc6cda3 508 off_t chars_left;
726f6388 509
28ef6c31 510 if (buffers == 0 || (bp = buffers[bfd]) == 0)
726f6388 511 return (-1);
28ef6c31 512
726f6388
JA
513 chars_left = bp->b_used - bp->b_inputp;
514 if (chars_left)
515 lseek (bp->b_fd, -chars_left, SEEK_CUR);
516 bp->b_used = bp->b_inputp = 0;
517 return (0);
518}
519
520int
521buffered_getchar ()
522{
0628567a
JA
523 CHECK_TERMSIG;
524
28ef6c31 525#if !defined (DJGPP)
726f6388 526 return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
28ef6c31
JA
527#else
528 /* On DJGPP, ignore \r. */
529 int ch;
530 while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) == '\r')
531 ;
532 return ch;
533#endif
726f6388
JA
534}
535
536int
537buffered_ungetchar (c)
538 int c;
539{
540 return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
541}
542
543/* Make input come from file descriptor BFD through a buffered stream. */
544void
545with_input_from_buffered_stream (bfd, name)
546 int bfd;
547 char *name;
548{
549 INPUT_STREAM location;
ccc6cda3 550 BUFFERED_STREAM *bp;
726f6388
JA
551
552 location.buffered_fd = bfd;
553 /* Make sure the buffered stream exists. */
ccc6cda3
JA
554 bp = fd_to_buffered_stream (bfd);
555 init_yy_io (bp == 0 ? return_EOF : buffered_getchar,
556 buffered_ungetchar, st_bstream, name, location);
726f6388
JA
557}
558
559#if defined (TEST)
f73dda09 560void *
726f6388
JA
561xmalloc(s)
562int s;
563{
f73dda09 564 return (malloc (s));
726f6388
JA
565}
566
f73dda09 567void *
726f6388
JA
568xrealloc(s, size)
569char *s;
570int size;
571{
572 if (!s)
f73dda09 573 return(malloc (size));
726f6388 574 else
f73dda09 575 return(realloc (s, size));
726f6388
JA
576}
577
578void
579init_yy_io ()
580{
581}
582
583process(bp)
584BUFFERED_STREAM *bp;
585{
586 int c;
587
588 while ((c = bufstream_getc(bp)) != EOF)
589 putchar(c);
590}
591
592BASH_INPUT bash_input;
593
594struct stat dsb; /* can be used from gdb */
595
596/* imitate /bin/cat */
597main(argc, argv)
598int argc;
599char **argv;
600{
601 register int i;
602 BUFFERED_STREAM *bp;
603
604 if (argc == 1) {
605 bp = fd_to_buffered_stream (0);
606 process(bp);
607 exit(0);
608 }
609 for (i = 1; i < argc; i++) {
610 if (argv[i][0] == '-' && argv[i][1] == '\0') {
611 bp = fd_to_buffered_stream (0);
612 if (!bp)
613 continue;
614 process(bp);
615 free_buffered_stream (bp);
616 } else {
617 bp = open_buffered_stream (argv[i]);
618 if (!bp)
619 continue;
620 process(bp);
621 close_buffered_stream (bp);
622 }
623 }
624 exit(0);
625}
ccc6cda3
JA
626#endif /* TEST */
627#endif /* BUFFERED_INPUT */