Imported from ../bash-2.04.tar.gz.
[platform/upstream/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 #ifndef _MINIX
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 "command.h"
38 #include "general.h"
39 #include "input.h"
40 #include "error.h"
41 #include "externs.h"
42
43 #if !defined (errno)
44 extern int errno;
45 #endif /* !errno */
46
47 /* Functions to handle reading input on systems that don't restart read(2)
48    if a signal is received. */
49
50 static unsigned char localbuf[128];
51 static int local_index, local_bufused;
52
53 /* Posix and USG systems do not guarantee to restart read () if it is
54    interrupted by a signal.  We do the read ourselves, and restart it
55    if it returns EINTR. */
56 int
57 getc_with_restart (stream)
58      FILE *stream;
59 {
60   /* Try local buffering to reduce the number of read(2) calls. */
61   if (local_index == local_bufused || local_bufused == 0)
62     {
63       while (1)
64         {
65           local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
66           if (local_bufused > 0)
67             break;
68           else if (local_bufused == 0 || errno != EINTR)
69             {
70               local_index = 0;
71               return EOF;
72             }
73         }
74       local_index = 0;
75     }
76   return (localbuf[local_index++]);
77 }
78
79 int
80 ungetc_with_restart (c, stream)
81      int c;
82      FILE *stream;
83 {
84   if (local_index == 0 || c == EOF)
85     return EOF;
86   return (localbuf[--local_index] = c);
87 }
88
89 #if defined (BUFFERED_INPUT)
90
91 /* A facility similar to stdio, but input-only. */
92
93 #if defined (USING_BASH_MALLOC)
94 #  define MAX_INPUT_BUFFER_SIZE 8176
95 #else
96 #  define MAX_INPUT_BUFFER_SIZE 8192
97 #endif
98
99 #if !defined (SEEK_CUR)
100 #  define SEEK_CUR 1
101 #endif /* !SEEK_CUR */
102
103 extern int return_EOF ();
104
105 extern int interactive_shell;
106
107 int bash_input_fd_changed;
108
109 /* This provides a way to map from a file descriptor to the buffer
110    associated with that file descriptor, rather than just the other
111    way around.  This is needed so that buffers are managed properly
112    in constructs like 3<&4.  buffers[x]->b_fd == x -- that is how the
113    correspondence is maintained. */
114 static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
115 static int nbuffers;
116
117 #define max(a, b)  (((a) > (b)) ? (a) : (b))
118
119 #define ALLOCATE_BUFFERS(n) \
120         do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
121
122 /* Make sure `buffers' has at least N elements. */
123 static void
124 allocate_buffers (n)
125      int n;
126 {
127   register int i, orig_nbuffers;
128
129   orig_nbuffers = nbuffers;
130   nbuffers = n + 20;
131   buffers = (BUFFERED_STREAM **)xrealloc
132     (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
133
134   /* Zero out the new buffers. */
135   for (i = orig_nbuffers; i < nbuffers; i++)
136     buffers[i] = (BUFFERED_STREAM *)NULL;
137 }
138
139 /* Construct and return a BUFFERED_STREAM corresponding to file descriptor
140    FD, using BUFFER. */
141 static BUFFERED_STREAM *
142 make_buffered_stream (fd, buffer, bufsize)
143      int fd;
144      char *buffer;
145      size_t bufsize;
146 {
147   BUFFERED_STREAM *bp;
148
149   bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
150   ALLOCATE_BUFFERS (fd);
151   buffers[fd] = bp;
152   bp->b_fd = fd;
153   bp->b_buffer = buffer;
154   bp->b_size = bufsize;
155   bp->b_used = bp->b_inputp = bp->b_flag = 0;
156   if (bufsize == 1)
157     bp->b_flag |= B_UNBUFF;
158   return (bp);
159 }
160
161 /* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
162 static BUFFERED_STREAM *
163 copy_buffered_stream (bp)
164      BUFFERED_STREAM *bp;
165 {
166   BUFFERED_STREAM *nbp;
167
168   if (!bp)
169     return ((BUFFERED_STREAM *)NULL);
170
171   nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
172   xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
173   return (nbp);
174 }
175
176 /* Check that file descriptor FD is not the one that bash is currently
177    using to read input from a script.  FD is about to be duplicated onto,
178    which means that the kernel will close it for us.  If FD is the bash
179    input file descriptor, we need to seek backwards in the script (if
180    possible and necessary -- scripts read from stdin are still unbuffered),
181    allocate a new file descriptor to use for bash input, and re-initialize
182    the buffered stream. */
183 int
184 check_bash_input (fd)
185      int fd;
186 {
187   int nfd;
188
189   if (fd > 0 && ((bash_input.type == st_bstream && bash_input.location.buffered_fd == fd) ||
190                  (interactive_shell == 0 && default_buffered_input == fd)))
191     {
192       /* Sync the stream so we can re-read from the new file descriptor.  We
193          might be able to avoid this by copying the buffered stream verbatim
194          to the new file descriptor. */
195       if (buffers[fd])
196         sync_buffered_stream (fd);
197
198       /* Now take care of duplicating the file descriptor that bash is
199          using for input, so we can reinitialize it later. */
200       nfd = fcntl (fd, F_DUPFD, 10);
201       if (nfd == -1)
202         {
203           if (fcntl (fd, F_GETFD, 0) == 0)
204             sys_error ("cannot allocate new file descriptor for bash input from fd %d", fd);
205           return -1;
206         }
207
208       if (buffers[nfd])
209         {
210           /* What's this?  A stray buffer without an associated open file
211              descriptor?  Free up the buffer and report the error. */
212           internal_error ("check_bash_input: buffer already exists for new fd %d", nfd);
213           free_buffered_stream (buffers[nfd]);
214         }
215
216       /* Reinitialize bash_input.location. */
217       if (bash_input.type == st_bstream)
218         {
219           bash_input.location.buffered_fd = nfd;
220           fd_to_buffered_stream (nfd);
221           close_buffered_fd (fd);       /* XXX */
222         }
223       else
224         /* If the current input type is not a buffered stream, but the shell
225            is not interactive and therefore using a buffered stream to read
226            input (e.g. with an `eval exec 3>output' inside a script), note
227            that the input fd has been changed.  pop_stream() looks at this
228            value and adjusts the input fd to the new value of
229            default_buffered_input accordingly. */
230         bash_input_fd_changed++;
231
232       if (default_buffered_input == fd)
233         default_buffered_input = nfd;
234     }
235   return 0;
236 }
237       
238 /* This is the buffered stream analogue of dup2(fd1, fd2).  The
239    BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
240    BUFFERS[fd1] is copied to BUFFERS[fd2].  This is called by the
241    redirect code for constructs like 4<&0 and 3</etc/rc.local. */
242 int
243 duplicate_buffered_stream (fd1, fd2)
244      int fd1, fd2;
245 {
246   int is_bash_input, m;
247
248   if (fd1 == fd2)
249     return 0;
250
251   m = max (fd1, fd2);
252   ALLOCATE_BUFFERS (m);
253
254   /* If FD2 is the file descriptor bash is currently using for shell input,
255      we need to do some extra work to make sure that the buffered stream
256      actually exists (it might not if fd1 was not active, and the copy
257      didn't actually do anything). */
258   is_bash_input = (bash_input.type == st_bstream) &&
259                   (bash_input.location.buffered_fd == fd2);
260
261   if (buffers[fd2])
262     free_buffered_stream (buffers[fd2]);
263   buffers[fd2] = copy_buffered_stream (buffers[fd1]);
264   if (buffers[fd2])
265     buffers[fd2]->b_fd = fd2;
266
267   if (is_bash_input && !buffers[fd2])
268     fd_to_buffered_stream (fd2);
269
270   return (fd2);
271 }
272
273 /* Return 1 if a seek on FD will succeed. */
274 #ifndef __CYGWIN32__
275 #  define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
276 #else
277 #  define fd_is_seekable(fd) 0
278 #endif /* __CYGWIN32__ */
279
280 /* Take FD, a file descriptor, and create and return a buffered stream
281    corresponding to it.  If something is wrong and the file descriptor
282    is invalid, return a NULL stream. */
283 BUFFERED_STREAM *
284 fd_to_buffered_stream (fd)
285      int fd;
286 {
287   char *buffer;
288   size_t size;
289   struct stat sb;
290
291   if (fstat (fd, &sb) < 0)
292     {
293       close (fd);
294       return ((BUFFERED_STREAM *)NULL);
295     }
296
297   if (fd_is_seekable (fd) == 0)
298     size = 1;
299   else
300     size = (size_t)((sb.st_size > MAX_INPUT_BUFFER_SIZE)
301                                 ? MAX_INPUT_BUFFER_SIZE
302                                 : sb.st_size);
303       
304   buffer = (char *)xmalloc (size);
305
306   return (make_buffered_stream (fd, buffer, size));
307 }
308
309 /* Return a buffered stream corresponding to FILE, a file name. */
310 BUFFERED_STREAM *
311 open_buffered_stream (file)
312      char *file;
313 {
314   int fd;
315
316   fd = open (file, O_RDONLY);
317   return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
318 }
319
320 /* Deallocate a buffered stream and free up its resources.  Make sure we
321    zero out the slot in BUFFERS that points to BP. */
322 void
323 free_buffered_stream (bp)
324      BUFFERED_STREAM *bp;
325 {
326   int n;
327
328   if (!bp)
329     return;
330
331   n = bp->b_fd;
332   if (bp->b_buffer)
333     free (bp->b_buffer);
334   free (bp);
335   buffers[n] = (BUFFERED_STREAM *)NULL;
336 }
337
338 /* Close the file descriptor associated with BP, a buffered stream, and free
339    up the stream.  Return the status of closing BP's file descriptor. */
340 int
341 close_buffered_stream (bp)
342      BUFFERED_STREAM *bp;
343 {
344   int fd;
345
346   if (!bp)
347     return (0);
348   fd = bp->b_fd;
349   free_buffered_stream (bp);
350   return (close (fd));
351 }
352
353 /* Deallocate the buffered stream associated with file descriptor FD, and
354    close FD.  Return the status of the close on FD. */
355 int
356 close_buffered_fd (fd)
357      int fd;
358 {
359   if (fd >= nbuffers || !buffers || !buffers[fd])
360     return (close (fd));
361   return (close_buffered_stream (buffers[fd]));
362 }
363
364 /* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
365    the old BUFFERED_STREAM. */
366 BUFFERED_STREAM *
367 set_buffered_stream (fd, bp)
368      int fd;
369      BUFFERED_STREAM *bp;
370 {
371   BUFFERED_STREAM *ret;
372
373   ret = buffers[fd];
374   buffers[fd] = bp;
375   return ret;
376 }
377
378 /* Read a buffer full of characters from BP, a buffered stream. */
379 static int
380 b_fill_buffer (bp)
381      BUFFERED_STREAM *bp;
382 {
383   bp->b_used = zread (bp->b_fd, bp->b_buffer, bp->b_size);
384   if (bp->b_used <= 0)
385     {
386       bp->b_buffer[0] = 0;
387       if (bp->b_used == 0)
388         bp->b_flag |= B_EOF;
389       else
390         bp->b_flag |= B_ERROR;
391       return (EOF);
392     }
393   bp->b_inputp = 0;
394   return (bp->b_buffer[bp->b_inputp++] & 0xFF);
395 }
396
397 /* Get a character from buffered stream BP. */
398 #define bufstream_getc(bp) \
399   (bp->b_inputp == bp->b_used || !bp->b_used) \
400                 ? b_fill_buffer (bp) \
401                 : bp->b_buffer[bp->b_inputp++] & 0xFF
402
403 /* Push C back onto buffered stream BP. */
404 static int
405 bufstream_ungetc(c, bp)
406      int c;
407      BUFFERED_STREAM *bp;
408 {
409   if (c == EOF || bp->b_inputp == 0)
410     return (EOF);
411
412   bp->b_buffer[--bp->b_inputp] = c;
413   return (c);
414 }
415
416 /* Seek backwards on file BFD to synchronize what we've read so far
417    with the underlying file pointer. */
418 int
419 sync_buffered_stream (bfd)
420      int bfd;
421 {
422   BUFFERED_STREAM *bp;
423   off_t chars_left;
424
425   bp = buffers[bfd];
426   if (!bp)
427     return (-1);
428   chars_left = bp->b_used - bp->b_inputp;
429   if (chars_left)
430     lseek (bp->b_fd, -chars_left, SEEK_CUR);
431   bp->b_used = bp->b_inputp = 0;
432   return (0);
433 }
434
435 int
436 buffered_getchar ()
437 {
438   return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
439 }
440
441 int
442 buffered_ungetchar (c)
443      int c;
444 {
445   return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
446 }
447
448 /* Make input come from file descriptor BFD through a buffered stream. */
449 void
450 with_input_from_buffered_stream (bfd, name)
451      int bfd;
452      char *name;
453 {
454   INPUT_STREAM location;
455   BUFFERED_STREAM *bp;
456
457   location.buffered_fd = bfd;
458   /* Make sure the buffered stream exists. */
459   bp = fd_to_buffered_stream (bfd);
460   init_yy_io (bp == 0 ? return_EOF : buffered_getchar,
461               buffered_ungetchar, st_bstream, name, location);
462 }
463
464 #if defined (TEST)
465 char *
466 xmalloc(s)
467 int s;
468 {
469         return ((char *)malloc (s));
470 }
471
472 char *
473 xrealloc(s, size)
474 char    *s;
475 int     size;
476 {
477         if (!s)
478                 return((char *)malloc (size));
479         else
480                 return((char *)realloc (s, size));
481 }
482
483 void
484 init_yy_io ()
485 {
486 }
487
488 process(bp)
489 BUFFERED_STREAM *bp;
490 {
491         int c;
492
493         while ((c = bufstream_getc(bp)) != EOF)
494                 putchar(c);
495 }
496
497 BASH_INPUT bash_input;
498
499 struct stat dsb;                /* can be used from gdb */
500
501 /* imitate /bin/cat */
502 main(argc, argv)
503 int     argc;
504 char    **argv;
505 {
506         register int i;
507         BUFFERED_STREAM *bp;
508
509         if (argc == 1) {
510                 bp = fd_to_buffered_stream (0);
511                 process(bp);
512                 exit(0);
513         }
514         for (i = 1; i < argc; i++) {
515                 if (argv[i][0] == '-' && argv[i][1] == '\0') {
516                         bp = fd_to_buffered_stream (0);
517                         if (!bp)
518                                 continue;
519                         process(bp);
520                         free_buffered_stream (bp);
521                 } else {
522                         bp = open_buffered_stream (argv[i]);
523                         if (!bp)
524                                 continue;
525                         process(bp);
526                         close_buffered_stream (bp);
527                 }
528         }
529         exit(0);
530 }
531 #endif /* TEST */
532 #endif /* BUFFERED_INPUT */