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