bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Builtin read with -n0 or -N0 (nchars == 0) behaves as a read with no


From: Eduardo Bustamante
Subject: Re: Builtin read with -n0 or -N0 (nchars == 0) behaves as a read with no -n/-N argument
Date: Sun, 4 Jun 2017 01:33:33 -0500

On Sun, Jun 4, 2017 at 12:16 AM, dualbus <address@hidden> wrote:
[...]
> Although there's a problem with the solution:
>
>   address@hidden:~$ for sh in bash ~/src/gnu/bash-build/bash ksh93 mksh; do 
> $sh -c ': | read -n 0; echo $?'; done
>   1
>   0
>   1
>   1
>
> Since the read(2) system call doesn't take place, `read -n 0' doesn't detect
> the broken pipe. IMO, it should.

Err, I'm clearly wrong. SIGPIPE is sent to the writer, not to the
reader. My bad.

That doesn't mean the problem is not there though. I think this is a
better test:

  address@hidden:~$ for sh in bash ksh93 mksh
~/src/gnu/bash-build/bash; do echo $sh $($sh -c 'exec < /; read -n 0;
echo $?' 2>&1); done
  bash bash: line 0: read: read error: 0: Is a directory 1
  ksh93 1
  mksh mksh: read: Is a directory 2
  /home/dualbus/src/gnu/bash-build/bash 0

Since bash "fakes" the read, it's not able to detect errors.

I currently have this:

address@hidden:~/src/gnu/bash$ git diff
diff --git a/builtins/read.def b/builtins/read.def
index 520a2b34..4e4c1b8a 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -362,10 +362,6 @@ read_builtin (list)
   input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
   input_string[0] = '\0';

-  /* More input and options validation */
-  if (nflag == 1 && nchars == 0)
-    goto assign_vars;          /* bail early if asked to read 0 chars */
-
   /* $TMOUT, if set, is the default timeout for read. */
   if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
     {
@@ -381,6 +377,10 @@ read_builtin (list)

   begin_unwind_frame ("read_builtin");

+  /* We were asked to read 0 chars. Do error detection and bail out */
+  if (nflag == 1 && nchars == 0 && (retval=read(fd, NULL, 0)) < 0)
+    goto handle_error;
+
 #if defined (BUFFERED_INPUT)
   if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
     sync_buffered_stream (default_buffered_input);
@@ -714,6 +714,7 @@ add_char:
     free (rlbuf);
 #endif

+handle_error:
   if (retval < 0)
     {
       t_errno = errno;


But it completely ignores the signal handling code down below.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]