1 /* input.c -- functions to perform buffered input with synchronization. */
2 
3 /* Copyright (C) 1992-2020 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
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    Bash is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19 */
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 "shell.h"
40 #include "input.h"
41 #include "externs.h"
42 #include "trap.h"
43 
44 #if !defined (errno)
45 extern int errno;
46 #endif /* !errno */
47 
48 #if defined (EAGAIN)
49 #  define X_EAGAIN EAGAIN
50 #else
51 #  define X_EAGAIN -99
52 #endif
53 
54 #if defined (EWOULDBLOCK)
55 #  define X_EWOULDBLOCK EWOULDBLOCK
56 #else
57 #  define X_EWOULDBLOCK -99
58 #endif
59 
60 extern void termsig_handler PARAMS((int));
61 
62 /* Functions to handle reading input on systems that don't restart read(2)
63    if a signal is received. */
64 
65 static char localbuf[1024];
66 static int local_index = 0, local_bufused = 0;
67 
68 /* Posix and USG systems do not guarantee to restart read () if it is
69    interrupted by a signal.  We do the read ourselves, and restart it
70    if it returns EINTR. */
71 int
getc_with_restart(stream)72 getc_with_restart (stream)
73      FILE *stream;
74 {
75   unsigned char uc;
76 
77   CHECK_TERMSIG;
78 
79   /* Try local buffering to reduce the number of read(2) calls. */
80   if (local_index == local_bufused || local_bufused == 0)
81     {
82       while (1)
83 	{
84 	  QUIT;
85 	  run_pending_traps ();
86 
87 	  local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
88 	  if (local_bufused > 0)
89 	    break;
90 	  else if (local_bufused == 0)
91 	    {
92 	      local_index = 0;
93 	      return EOF;
94 	    }
95 	  else if (errno == X_EAGAIN || errno == X_EWOULDBLOCK)
96 	    {
97 	      if (sh_unset_nodelay_mode (fileno (stream)) < 0)
98 		{
99 		  sys_error (_("cannot reset nodelay mode for fd %d"), fileno (stream));
100 		  local_index = local_bufused = 0;
101 		  return EOF;
102 		}
103 	      continue;
104 	    }
105 	  else if (errno != EINTR)
106 	    {
107 	      local_index = local_bufused = 0;
108 	      return EOF;
109 	    }
110 	  else if (interrupt_state || terminating_signal)	/* QUIT; */
111 	    local_index = local_bufused = 0;
112 	}
113       local_index = 0;
114     }
115   uc = localbuf[local_index++];
116   return uc;
117 }
118 
119 int
ungetc_with_restart(c,stream)120 ungetc_with_restart (c, stream)
121      int c;
122      FILE *stream;
123 {
124   if (local_index == 0 || c == EOF)
125     return EOF;
126   localbuf[--local_index] = c;
127   return c;
128 }
129 
130 #if defined (BUFFERED_INPUT)
131 
132 /* A facility similar to stdio, but input-only. */
133 
134 #if defined (USING_BASH_MALLOC)
135 #  define MAX_INPUT_BUFFER_SIZE	8172
136 #else
137 #  define MAX_INPUT_BUFFER_SIZE	8192
138 #endif
139 
140 #if !defined (SEEK_CUR)
141 #  define SEEK_CUR 1
142 #endif /* !SEEK_CUR */
143 
144 #ifdef max
145 #  undef max
146 #endif
147 #define max(a, b)	(((a) > (b)) ? (a) : (b))
148 #ifdef min
149 #  undef min
150 #endif
151 #define min(a, b)	((a) > (b) ? (b) : (a))
152 
153 int bash_input_fd_changed;
154 
155 /* This provides a way to map from a file descriptor to the buffer
156    associated with that file descriptor, rather than just the other
157    way around.  This is needed so that buffers are managed properly
158    in constructs like 3<&4.  buffers[x]->b_fd == x -- that is how the
159    correspondence is maintained. */
160 static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
161 static int nbuffers;
162 
163 #define ALLOCATE_BUFFERS(n) \
164 	do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
165 
166 /* Make sure `buffers' has at least N elements. */
167 static void
allocate_buffers(n)168 allocate_buffers (n)
169      int n;
170 {
171   register int i, orig_nbuffers;
172 
173   orig_nbuffers = nbuffers;
174   nbuffers = n + 20;
175   buffers = (BUFFERED_STREAM **)xrealloc
176     (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
177 
178   /* Zero out the new buffers. */
179   for (i = orig_nbuffers; i < nbuffers; i++)
180     buffers[i] = (BUFFERED_STREAM *)NULL;
181 }
182 
183 /* Construct and return a BUFFERED_STREAM corresponding to file descriptor
184    FD, using BUFFER. */
185 static BUFFERED_STREAM *
make_buffered_stream(fd,buffer,bufsize)186 make_buffered_stream (fd, buffer, bufsize)
187      int fd;
188      char *buffer;
189      size_t bufsize;
190 {
191   BUFFERED_STREAM *bp;
192 
193   bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
194   ALLOCATE_BUFFERS (fd);
195   buffers[fd] = bp;
196   bp->b_fd = fd;
197   bp->b_buffer = buffer;
198   bp->b_size = bufsize;
199   bp->b_used = bp->b_inputp = bp->b_flag = 0;
200   if (bufsize == 1)
201     bp->b_flag |= B_UNBUFF;
202   if (O_TEXT && (fcntl (fd, F_GETFL) & O_TEXT) != 0)
203     bp->b_flag |= B_TEXT;
204   return (bp);
205 }
206 
207 /* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
208 static BUFFERED_STREAM *
copy_buffered_stream(bp)209 copy_buffered_stream (bp)
210      BUFFERED_STREAM *bp;
211 {
212   BUFFERED_STREAM *nbp;
213 
214   if (!bp)
215     return ((BUFFERED_STREAM *)NULL);
216 
217   nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
218   xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
219   return (nbp);
220 }
221 
222 int
set_bash_input_fd(fd)223 set_bash_input_fd (fd)
224      int fd;
225 {
226   if (bash_input.type == st_bstream)
227     bash_input.location.buffered_fd = fd;
228   else if (interactive_shell == 0)
229     default_buffered_input = fd;
230   return 0;
231 }
232 
233 int
fd_is_bash_input(fd)234 fd_is_bash_input (fd)
235      int fd;
236 {
237   if (bash_input.type == st_bstream && bash_input.location.buffered_fd == fd)
238     return 1;
239   else if (interactive_shell == 0 && default_buffered_input == fd)
240     return 1;
241   return 0;
242 }
243 
244 /* Save the buffered stream corresponding to file descriptor FD (which bash
245    is using to read input) to a buffered stream associated with NEW_FD.  If
246    NEW_FD is -1, a new file descriptor is allocated with fcntl.  The new
247    file descriptor is returned on success, -1 on error. */
248 int
save_bash_input(fd,new_fd)249 save_bash_input (fd, new_fd)
250      int fd, new_fd;
251 {
252   int nfd;
253 
254   /* Sync the stream so we can re-read from the new file descriptor.  We
255      might be able to avoid this by copying the buffered stream verbatim
256      to the new file descriptor. */
257   if (buffers[fd])
258     sync_buffered_stream (fd);
259 
260   /* Now take care of duplicating the file descriptor that bash is
261      using for input, so we can reinitialize it later. */
262   nfd = (new_fd == -1) ? fcntl (fd, F_DUPFD, 10) : new_fd;
263   if (nfd == -1)
264     {
265       if (fcntl (fd, F_GETFD, 0) == 0)
266 	sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd);
267       return -1;
268     }
269 
270   if (nfd < nbuffers && buffers[nfd])
271     {
272       /* What's this?  A stray buffer without an associated open file
273 	 descriptor?  Free up the buffer and report the error. */
274       internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd);
275       if (buffers[nfd]->b_flag & B_SHAREDBUF)
276 	buffers[nfd]->b_buffer = (char *)NULL;
277       free_buffered_stream (buffers[nfd]);
278     }
279 
280   /* Reinitialize bash_input.location. */
281   if (bash_input.type == st_bstream)
282     {
283       bash_input.location.buffered_fd = nfd;
284       fd_to_buffered_stream (nfd);
285       close_buffered_fd (fd);	/* XXX */
286     }
287   else
288     /* If the current input type is not a buffered stream, but the shell
289        is not interactive and therefore using a buffered stream to read
290        input (e.g. with an `eval exec 3>output' inside a script), note
291        that the input fd has been changed.  pop_stream() looks at this
292        value and adjusts the input fd to the new value of
293        default_buffered_input accordingly. */
294     bash_input_fd_changed++;
295 
296   if (default_buffered_input == fd)
297     default_buffered_input = nfd;
298 
299   SET_CLOSE_ON_EXEC (nfd);
300   return nfd;
301 }
302 
303 /* Check that file descriptor FD is not the one that bash is currently
304    using to read input from a script.  FD is about to be duplicated onto,
305    which means that the kernel will close it for us.  If FD is the bash
306    input file descriptor, we need to seek backwards in the script (if
307    possible and necessary -- scripts read from stdin are still unbuffered),
308    allocate a new file descriptor to use for bash input, and re-initialize
309    the buffered stream.  Make sure the file descriptor used to save bash
310    input is set close-on-exec. Returns 0 on success, -1 on failure.  This
311    works only if fd is > 0 -- if fd == 0 and bash is reading input from
312    fd 0, sync_buffered_stream is used instead, to cooperate with input
313    redirection (look at redir.c:add_undo_redirect()). */
314 int
check_bash_input(fd)315 check_bash_input (fd)
316      int fd;
317 {
318   if (fd_is_bash_input (fd))
319     {
320       if (fd > 0)
321 	return ((save_bash_input (fd, -1) == -1) ? -1 : 0);
322       else if (fd == 0)
323         return ((sync_buffered_stream (fd) == -1) ? -1 : 0);
324     }
325   return 0;
326 }
327 
328 /* This is the buffered stream analogue of dup2(fd1, fd2).  The
329    BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
330    BUFFERS[fd1] is copied to BUFFERS[fd2].  This is called by the
331    redirect code for constructs like 4<&0 and 3</etc/rc.local. */
332 int
duplicate_buffered_stream(fd1,fd2)333 duplicate_buffered_stream (fd1, fd2)
334      int fd1, fd2;
335 {
336   int is_bash_input, m;
337 
338   if (fd1 == fd2)
339     return 0;
340 
341   m = max (fd1, fd2);
342   ALLOCATE_BUFFERS (m);
343 
344   /* If FD2 is the file descriptor bash is currently using for shell input,
345      we need to do some extra work to make sure that the buffered stream
346      actually exists (it might not if fd1 was not active, and the copy
347      didn't actually do anything). */
348   is_bash_input = (bash_input.type == st_bstream) &&
349 		  (bash_input.location.buffered_fd == fd2);
350 
351   if (buffers[fd2])
352     {
353       /* If the two objects share the same b_buffer, don't free it. */
354       if (buffers[fd1] && buffers[fd1]->b_buffer && buffers[fd1]->b_buffer == buffers[fd2]->b_buffer)
355 	buffers[fd2] = (BUFFERED_STREAM *)NULL;
356       /* If this buffer is shared with another fd, don't free the buffer */
357       else if (buffers[fd2]->b_flag & B_SHAREDBUF)
358 	{
359 	  buffers[fd2]->b_buffer = (char *)NULL;
360 	  free_buffered_stream (buffers[fd2]);
361 	}
362       else
363 	free_buffered_stream (buffers[fd2]);
364     }
365   buffers[fd2] = copy_buffered_stream (buffers[fd1]);
366   if (buffers[fd2])
367     buffers[fd2]->b_fd = fd2;
368 
369   if (is_bash_input)
370     {
371       if (!buffers[fd2])
372 	fd_to_buffered_stream (fd2);
373       buffers[fd2]->b_flag |= B_WASBASHINPUT;
374     }
375 
376   if (fd_is_bash_input (fd1) || (buffers[fd1] && (buffers[fd1]->b_flag & B_SHAREDBUF)))
377     buffers[fd2]->b_flag |= B_SHAREDBUF;
378 
379   return (fd2);
380 }
381 
382 /* Return 1 if a seek on FD will succeed. */
383 #define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
384 
385 /* Take FD, a file descriptor, and create and return a buffered stream
386    corresponding to it.  If something is wrong and the file descriptor
387    is invalid, return a NULL stream. */
388 BUFFERED_STREAM *
fd_to_buffered_stream(fd)389 fd_to_buffered_stream (fd)
390      int fd;
391 {
392   char *buffer;
393   size_t size;
394   struct stat sb;
395 
396   if (fstat (fd, &sb) < 0)
397     {
398       close (fd);
399       return ((BUFFERED_STREAM *)NULL);
400     }
401 
402   size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
403   if (size == 0)
404     size = 1;
405   buffer = (char *)xmalloc (size);
406 
407   return (make_buffered_stream (fd, buffer, size));
408 }
409 
410 /* Return a buffered stream corresponding to FILE, a file name. */
411 BUFFERED_STREAM *
open_buffered_stream(file)412 open_buffered_stream (file)
413      char *file;
414 {
415   int fd;
416 
417   fd = open (file, O_RDONLY);
418   return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
419 }
420 
421 /* Deallocate a buffered stream and free up its resources.  Make sure we
422    zero out the slot in BUFFERS that points to BP. */
423 void
free_buffered_stream(bp)424 free_buffered_stream (bp)
425      BUFFERED_STREAM *bp;
426 {
427   int n;
428 
429   if (!bp)
430     return;
431 
432   n = bp->b_fd;
433   if (bp->b_buffer)
434     free (bp->b_buffer);
435   free (bp);
436   buffers[n] = (BUFFERED_STREAM *)NULL;
437 }
438 
439 /* Close the file descriptor associated with BP, a buffered stream, and free
440    up the stream.  Return the status of closing BP's file descriptor. */
441 int
close_buffered_stream(bp)442 close_buffered_stream (bp)
443      BUFFERED_STREAM *bp;
444 {
445   int fd;
446 
447   if (!bp)
448     return (0);
449   fd = bp->b_fd;
450   if (bp->b_flag & B_SHAREDBUF)
451     bp->b_buffer = (char *)NULL;
452   free_buffered_stream (bp);
453   return (close (fd));
454 }
455 
456 /* Deallocate the buffered stream associated with file descriptor FD, and
457    close FD.  Return the status of the close on FD. */
458 int
close_buffered_fd(fd)459 close_buffered_fd (fd)
460      int fd;
461 {
462   if (fd < 0)
463     {
464       errno = EBADF;
465       return -1;
466     }
467   if (fd >= nbuffers || !buffers || !buffers[fd])
468     return (close (fd));
469   return (close_buffered_stream (buffers[fd]));
470 }
471 
472 /* Make the BUFFERED_STREAM associated with buffers[FD] be BP, and return
473    the old BUFFERED_STREAM. */
474 BUFFERED_STREAM *
set_buffered_stream(fd,bp)475 set_buffered_stream (fd, bp)
476      int fd;
477      BUFFERED_STREAM *bp;
478 {
479   BUFFERED_STREAM *ret;
480 
481   ret = buffers[fd];
482   buffers[fd] = bp;
483   return ret;
484 }
485 
486 /* Read a buffer full of characters from BP, a buffered stream. */
487 static int
b_fill_buffer(bp)488 b_fill_buffer (bp)
489      BUFFERED_STREAM *bp;
490 {
491   ssize_t nr;
492   off_t o;
493 
494   CHECK_TERMSIG;
495   /* In an environment where text and binary files are treated differently,
496      compensate for lseek() on text files returning an offset different from
497      the count of characters read() returns.  Text-mode streams have to be
498      treated as unbuffered. */
499   if ((bp->b_flag & (B_TEXT | B_UNBUFF)) == B_TEXT)
500     {
501       o = lseek (bp->b_fd, 0, SEEK_CUR);
502       nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
503       if (nr > 0 && nr < lseek (bp->b_fd, 0, SEEK_CUR) - o)
504 	{
505 	  lseek (bp->b_fd, o, SEEK_SET);
506 	  bp->b_flag |= B_UNBUFF;
507 	  bp->b_size = 1;
508 	  nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
509 	}
510     }
511   else
512     nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
513   if (nr <= 0)
514     {
515       bp->b_used = bp->b_inputp = 0;
516       bp->b_buffer[0] = 0;
517       if (nr == 0)
518 	bp->b_flag |= B_EOF;
519       else
520 	bp->b_flag |= B_ERROR;
521       return (EOF);
522     }
523 
524   bp->b_used = nr;
525   bp->b_inputp = 0;
526   return (bp->b_buffer[bp->b_inputp++] & 0xFF);
527 }
528 
529 /* Get a character from buffered stream BP. */
530 #define bufstream_getc(bp) \
531   (bp->b_inputp == bp->b_used || !bp->b_used) \
532   		? b_fill_buffer (bp) \
533 		: bp->b_buffer[bp->b_inputp++] & 0xFF
534 
535 /* Push C back onto buffered stream BP. */
536 static int
bufstream_ungetc(c,bp)537 bufstream_ungetc(c, bp)
538      int c;
539      BUFFERED_STREAM *bp;
540 {
541   if (c == EOF || bp == 0 || bp->b_inputp == 0)
542     return (EOF);
543 
544   bp->b_buffer[--bp->b_inputp] = c;
545   return (c);
546 }
547 
548 /* Seek backwards on file BFD to synchronize what we've read so far
549    with the underlying file pointer. */
550 int
sync_buffered_stream(bfd)551 sync_buffered_stream (bfd)
552      int bfd;
553 {
554   BUFFERED_STREAM *bp;
555   off_t chars_left;
556 
557   if (buffers == 0 || (bp = buffers[bfd]) == 0)
558     return (-1);
559 
560   chars_left = bp->b_used - bp->b_inputp;
561   if (chars_left)
562     lseek (bp->b_fd, -chars_left, SEEK_CUR);
563   bp->b_used = bp->b_inputp = 0;
564   return (0);
565 }
566 
567 int
buffered_getchar()568 buffered_getchar ()
569 {
570   CHECK_TERMSIG;
571 
572   if (bash_input.location.buffered_fd < 0 || buffers[bash_input.location.buffered_fd] == 0)
573     return EOF;
574 
575 #if !defined (DJGPP)
576   return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
577 #else
578   /* On DJGPP, ignore \r. */
579   int ch;
580   while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) == '\r')
581     ;
582   return ch;
583 #endif
584 }
585 
586 int
buffered_ungetchar(c)587 buffered_ungetchar (c)
588      int c;
589 {
590   return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
591 }
592 
593 /* Make input come from file descriptor BFD through a buffered stream. */
594 void
with_input_from_buffered_stream(bfd,name)595 with_input_from_buffered_stream (bfd, name)
596      int bfd;
597      char *name;
598 {
599   INPUT_STREAM location;
600   BUFFERED_STREAM *bp;
601 
602   location.buffered_fd = bfd;
603   /* Make sure the buffered stream exists. */
604   bp = fd_to_buffered_stream (bfd);
605   init_yy_io (bp == 0 ? return_EOF : buffered_getchar,
606 	      buffered_ungetchar, st_bstream, name, location);
607 }
608 
609 #if defined (TEST)
610 void *
xmalloc(s)611 xmalloc(s)
612 int s;
613 {
614 	return (malloc (s));
615 }
616 
617 void *
xrealloc(s,size)618 xrealloc(s, size)
619 char	*s;
620 int	size;
621 {
622 	if (!s)
623 		return(malloc (size));
624 	else
625 		return(realloc (s, size));
626 }
627 
628 void
init_yy_io()629 init_yy_io ()
630 {
631 }
632 
process(bp)633 process(bp)
634 BUFFERED_STREAM *bp;
635 {
636 	int c;
637 
638 	while ((c = bufstream_getc(bp)) != EOF)
639 		putchar(c);
640 }
641 
642 BASH_INPUT bash_input;
643 
644 struct stat dsb;		/* can be used from gdb */
645 
646 /* imitate /bin/cat */
main(argc,argv)647 main(argc, argv)
648 int	argc;
649 char	**argv;
650 {
651 	register int i;
652 	BUFFERED_STREAM *bp;
653 
654 	if (argc == 1) {
655 		bp = fd_to_buffered_stream (0);
656 		process(bp);
657 		exit(0);
658 	}
659 	for (i = 1; i < argc; i++) {
660 		if (argv[i][0] == '-' && argv[i][1] == '\0') {
661 			bp = fd_to_buffered_stream (0);
662 			if (!bp)
663 				continue;
664 			process(bp);
665 			free_buffered_stream (bp);
666 		} else {
667 			bp = open_buffered_stream (argv[i]);
668 			if (!bp)
669 				continue;
670 			process(bp);
671 			close_buffered_stream (bp);
672 		}
673 	}
674 	exit(0);
675 }
676 #endif /* TEST */
677 #endif /* BUFFERED_INPUT */
678