I have attached a patch.  It's pretty lame, though:  what it does is read the
fifo file into a buffer (and execute it).  On the other hand, bash already
read the sourced file into a buffer, so I guess I'm no worse at working around
crufty design than the average bash hacker.

I also added two test cases which check that bash DTRT WRT sourcing fifos.

I also added the --norc and --noprofile flags to an invocation in a test case
(my output differed, because I eat fortune cookies in my ~/.bashrc), something
which is unrelated to fifo sourcing, but needed doing :)

-- 
An OS is like god, but without the beard

Jonas Kölker <[EMAIL PROTECTED]> <URL:http://jonaskoelker.homeunix.org/>
diff -ru orig/bash-3.1/bash-3.1/builtins/evalfile.c 
patched/bash-3.1/bash-3.1/builtins/evalfile.c
--- orig/bash-3.1/bash-3.1/builtins/evalfile.c  2004-11-27 20:07:12.000000000 
+0100
+++ patched/bash-3.1/bash-3.1/builtins/evalfile.c       2006-11-17 
21:34:35.000000000 +0100
@@ -103,7 +103,7 @@
   GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
 #  endif
 #endif
-  
+
   fd = open (filename, O_RDONLY);
 
   if (fd < 0 || (fstat (fd, &finfo) == -1))
@@ -139,6 +139,7 @@
   /* Check for overflow with large files. */
   if (file_size != finfo.st_size || file_size + 1 < file_size)
     {
+    file_too_large:
       (*errfunc) (_("%s: file is too large"), filename);
       return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
     }      
@@ -147,13 +148,51 @@
   setmode (fd, O_TEXT);
 #endif
 
-  string = (char *)xmalloc (1 + file_size);
-  result = read (fd, string, file_size);
-  string[result] = '\0';
-
-  return_val = errno;
-  close (fd);
-  errno = return_val;
+  if (S_ISFIFO (finfo.st_mode) == 0)
+    {
+      string = (char *)xmalloc (1 + file_size);
+      result = read (fd, string, file_size);
+      string[result] = '\0';
+
+    close_with_errno:
+      return_val = errno;
+      close (fd);
+      errno = return_val;
+    }
+  /* we can't slurp a fifo (linux sez 5Bfile_size is zero) so we ask
+   * read instead of stat;  this requires a growing buffer. */
+  else
+    {
+      size_t used = 0;
+      size_t buffer_size = 3;
+      string = xmalloc (buffer_size);
+      string[0] = '\0';
+      while (1)
+       {
+         errno = 0;
+         result = read (fd, string + used, buffer_size - used - 1);
+         if (result < 0)
+           goto close_with_errno;
+         else if (result == 0)
+           {
+             string[used] = '\0';
+             close (fd);
+             break;
+           }
+         used += result;
+         if (used + 1 == buffer_size) /* buffer full: grow it */
+           {
+             const size_t newsize = 2 * buffer_size + 1;
+             if (buffer_size >= newsize)
+               {
+                 free(string);
+                 goto file_too_large;
+               }
+             buffer_size = newsize;
+             string = xrealloc(string, buffer_size);
+           }
+       }
+    }
 
   if (result < 0)              /* XXX was != file_size, not < 0 */
     {
@@ -161,7 +200,7 @@
       goto file_error_and_exit;
     }
 
-  if (result == 0)
+  if (result == 0 && S_ISFIFO (finfo.st_mode) == 0)
     {
       free (string);
       return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
Only in patched/bash-3.1/bash-3.1/builtins: evalfile.c~
diff -ru orig/bash-3.1/bash-3.1/tests/builtins.right 
patched/bash-3.1/bash-3.1/tests/builtins.right
--- orig/bash-3.1/bash-3.1/tests/builtins.right 2005-02-28 15:12:27.000000000 
+0100
+++ patched/bash-3.1/bash-3.1/tests/builtins.right      2006-11-17 
21:32:58.000000000 +0100
@@ -108,6 +108,8 @@
 ./source5.sub: line 10: /tmp/source-notthere: No such file or directory
 after bad source 1
 ./source5.sub: line 17: /tmp/source-notthere: No such file or directory
+sourcing a pipe: success (this is echoed)
+sourcing a pipe: success (I got no sigpipe)
 AVAR
 foo
 foo
@@ -118,15 +120,15 @@
 foo
 declare -x foo=""
 declare -x FOO="\$\$"
-./builtins.tests: line 207: declare: FOO: not found
+./builtins.tests: line 229: declare: FOO: not found
 declare -x FOO="\$\$"
 ok
 ok
-./builtins.tests: line 239: kill: 4096: invalid signal specification
+./builtins.tests: line 261: kill: 4096: invalid signal specification
 1
 a\n\n\nb
 a
 
 
 b
-./builtins.tests: line 248: exit: status: numeric argument required
+./builtins.tests: line 270: exit: status: numeric argument required
diff -ru orig/bash-3.1/bash-3.1/tests/builtins.tests 
patched/bash-3.1/bash-3.1/tests/builtins.tests
--- orig/bash-3.1/bash-3.1/tests/builtins.tests 2003-01-14 17:09:26.000000000 
+0100
+++ patched/bash-3.1/bash-3.1/tests/builtins.tests      2006-11-17 
21:32:52.000000000 +0100
@@ -108,8 +108,8 @@
 esac
 
 # test options to exec
-(exec -a specialname ${THIS_SH} -c 'echo $0' )
-(exec -l -a specialname ${THIS_SH} -c 'echo $0' )
+(exec -a specialname ${THIS_SH} --norc --noprofile -c 'echo $0' )
+(exec -l -a specialname ${THIS_SH} --norc --noprofile -c 'echo $0' )
 # test `clean' environment.  if /bin/sh is bash, and the script version of
 # printenv is run, there will be variables in the environment that bash
 # sets on startup.  Also test code that prefixes argv[0] with a dash.
@@ -176,6 +176,28 @@
 # test behavior of `.' when given a non-existant file argument
 ${THIS_SH} ./source5.sub
 
+# test behavior of `.' when trying to source a fifo file
+PIPE=/tmp/fifo-for-testing-bash-$$
+if mkfifo $PIPE; then trap "rm $PIPE" exit; else exit; fi
+
+# this doesn't cause sigpipe in version (n - 1)
+echo 'echo sourcing a pipe: success "(this is echoed)"' > $PIPE &
+source $PIPE
+wait
+
+# this *does* cause sigpipe in version (n - 1)
+write_or_sigpipe() {
+       trap 'echo sourcing a pipe: failure "(sigpipe recieved)"' SIGPIPE
+       echo 'echo sourcing a pipe: success "(I got no sigpipe)"' > $PIPE
+}
+
+# n = 1 + "GNU bash, version 3.1.17(1)-release (i486-pc-linux-gnu)"
+# (apt-get source bash; `dpkg -l bash' says version is "3.1-5")
+
+write_or_sigpipe &
+source $PIPE
+wait
+
 # in posix mode, assignment statements preceding special builtins are
 # reflected in the shell environment.  `.' and `eval' need special-case
 # code.

Attachment: signature.asc
Description: Digital signature

Reply via email to