]> git.ipfire.org Git - thirdparty/bash.git/blob - input.c
Imported from ../bash-3.2.tar.gz.
[thirdparty/bash.git] / input.c
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
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
25 # include <sys/file.h>
26 #endif
27 #include "filecntl.h"
28 #include "posixstat.h"
29 #include <stdio.h>
30 #include <errno.h>
31
32 #if defined (HAVE_UNISTD_H)
33 # include <unistd.h>
34 #endif
35
36 #include "bashansi.h"
37 #include "bashintl.h"
38
39 #include "command.h"
40 #include "general.h"
41 #include "input.h"
42 #include "error.h"
43 #include "externs.h"
44 #include "quit.h"
45
46 #if !defined (errno)
47 extern int errno;
48 #endif /* !errno */
49
50 extern void termsig_handler __P((int));
51
52 /* Functions to handle reading input on systems that don't restart read(2)
53 if a signal is received. */
54
55 static char localbuf[128];
56 static int local_index = 0, local_bufused = 0;
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. */
61 int
62 getc_with_restart (stream)
63 FILE *stream;
64 {
65 unsigned char uc;
66
67 CHECK_TERMSIG;
68
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 {
74 CHECK_TERMSIG;
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 }
86 uc = localbuf[local_index++];
87 return uc;
88 }
89
90 int
91 ungetc_with_restart (c, stream)
92 int c;
93 FILE *stream;
94 {
95 if (local_index == 0 || c == EOF)
96 return EOF;
97 localbuf[--local_index] = c;
98 return c;
99 }
100
101 #if defined (BUFFERED_INPUT)
102
103 /* A facility similar to stdio, but input-only. */
104
105 #if defined (USING_BASH_MALLOC)
106 # define MAX_INPUT_BUFFER_SIZE 8176
107 #else
108 # define MAX_INPUT_BUFFER_SIZE 8192
109 #endif
110
111 #if !defined (SEEK_CUR)
112 # define SEEK_CUR 1
113 #endif /* !SEEK_CUR */
114
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
124 extern int interactive_shell;
125
126 int bash_input_fd_changed;
127
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;
134 static int nbuffers;
135
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. */
140 static void
141 allocate_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. */
158 static BUFFERED_STREAM *
159 make_buffered_stream (fd, buffer, bufsize)
160 int fd;
161 char *buffer;
162 size_t bufsize;
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;
172 bp->b_used = bp->b_inputp = bp->b_flag = 0;
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. */
179 static BUFFERED_STREAM *
180 copy_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
193 int
194 set_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
204 int
205 fd_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. */
219 int
220 save_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)
237 sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd);
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. */
245 internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd);
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
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()). */
283 int
284 check_bash_input (fd)
285 int fd;
286 {
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 }
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. */
301 int
302 duplicate_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])
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 }
328 buffers[fd2] = copy_buffered_stream (buffers[fd1]);
329 if (buffers[fd2])
330 buffers[fd2]->b_fd = fd2;
331
332 if (is_bash_input)
333 {
334 if (!buffers[fd2])
335 fd_to_buffered_stream (fd2);
336 buffers[fd2]->b_flag |= B_WASBASHINPUT;
337 }
338
339 return (fd2);
340 }
341
342 /* Return 1 if a seek on FD will succeed. */
343 #ifndef __CYGWIN__
344 # define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
345 #else
346 # define fd_is_seekable(fd) 0
347 #endif /* __CYGWIN__ */
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. */
352 BUFFERED_STREAM *
353 fd_to_buffered_stream (fd)
354 int fd;
355 {
356 char *buffer;
357 size_t size;
358 struct stat sb;
359
360 if (fstat (fd, &sb) < 0)
361 {
362 close (fd);
363 return ((BUFFERED_STREAM *)NULL);
364 }
365
366 size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
367 if (size == 0)
368 size = 1;
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. */
375 BUFFERED_STREAM *
376 open_buffered_stream (file)
377 char *file;
378 {
379 int fd;
380
381 fd = open (file, O_RDONLY);
382 return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
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. */
387 void
388 free_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. */
405 int
406 close_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. */
420 int
421 close_buffered_fd (fd)
422 int fd;
423 {
424 if (fd < 0)
425 {
426 errno = EBADF;
427 return -1;
428 }
429 if (fd >= nbuffers || !buffers || !buffers[fd])
430 return (close (fd));
431 return (close_buffered_stream (buffers[fd]));
432 }
433
434 /* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
435 the old BUFFERED_STREAM. */
436 BUFFERED_STREAM *
437 set_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
448 /* Read a buffer full of characters from BP, a buffered stream. */
449 static int
450 b_fill_buffer (bp)
451 BUFFERED_STREAM *bp;
452 {
453 ssize_t nr;
454
455 CHECK_TERMSIG;
456 nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
457 if (nr <= 0)
458 {
459 bp->b_used = 0;
460 bp->b_buffer[0] = 0;
461 if (nr == 0)
462 bp->b_flag |= B_EOF;
463 else
464 bp->b_flag |= B_ERROR;
465 return (EOF);
466 }
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;
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. */
489 static int
490 bufstream_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. */
503 int
504 sync_buffered_stream (bfd)
505 int bfd;
506 {
507 BUFFERED_STREAM *bp;
508 off_t chars_left;
509
510 if (buffers == 0 || (bp = buffers[bfd]) == 0)
511 return (-1);
512
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
520 int
521 buffered_getchar ()
522 {
523 CHECK_TERMSIG;
524
525 #if !defined (DJGPP)
526 return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
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
534 }
535
536 int
537 buffered_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. */
544 void
545 with_input_from_buffered_stream (bfd, name)
546 int bfd;
547 char *name;
548 {
549 INPUT_STREAM location;
550 BUFFERED_STREAM *bp;
551
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);
557 }
558
559 #if defined (TEST)
560 void *
561 xmalloc(s)
562 int s;
563 {
564 return (malloc (s));
565 }
566
567 void *
568 xrealloc(s, size)
569 char *s;
570 int size;
571 {
572 if (!s)
573 return(malloc (size));
574 else
575 return(realloc (s, size));
576 }
577
578 void
579 init_yy_io ()
580 {
581 }
582
583 process(bp)
584 BUFFERED_STREAM *bp;
585 {
586 int c;
587
588 while ((c = bufstream_getc(bp)) != EOF)
589 putchar(c);
590 }
591
592 BASH_INPUT bash_input;
593
594 struct stat dsb; /* can be used from gdb */
595
596 /* imitate /bin/cat */
597 main(argc, argv)
598 int argc;
599 char **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 }
626 #endif /* TEST */
627 #endif /* BUFFERED_INPUT */