Re: History of bash's support for self-modifying shell scripts?

2018-09-11 Thread Chet Ramey
On 9/10/18 5:39 PM, Josh Triplett wrote:

>> It happens in only a few cases: 1) when forking a child to run a command;
>> 2) when a redirection specifies the same file descriptor as bash is using
>> to read a script; and 3) when bash is reading a script from stdin and the
>> read builtin is used to read from that file descriptor.
>>
>> The first case is probably the one you're interested in. It's been there
>> even since I wrote the buffered input code in 1992, and it's more about
>> making sure parent and child shells have a consistent view of the script
>> in case the child expects to read from it. It's about being careful, not
>> explicitly allowing self-modifying scripts.
> 
> Interesting. I don't *think* the behavior I observed corresponds to one
> of those cases; I observed it by just having a shell script that
> carefully used `dd conv=notrunc of=$0 ...` to write code into the
> current script after the current command.

That seems to be exactly the first case: forking a child to run a command.
In this case, the command as written is a command substitution.

> 
>> Previous versions of the shell (through bash-1.12) used stdio, which has
>> behavior that varies across systems, especially across parent-child
>> boundaries and changing file descriptors due to redirection (which it can't
>> really handle at all).
>>
>> POSIX says you have to do that anyway if the shell is reading from stdin:
>>
>> "When the shell is using standard input and it invokes a command that also
>> uses standard input, the shell shall ensure that the standard input file
>> pointer points directly after the command it has read when the command
>> begins execution. It shall not read ahead in such a manner that any
>> characters intended to be read by the invoked command are consumed by the
>> shell (whether interpreted by the shell or not) or that characters that are
>> not read by the invoked command are not seen by the shell."
> 
> I did find that, but that only applies to stdin, not to shell scripts.

That's not exactly what I think you mean to say; this should certainly
produce `output' on stdout

cat
output

when fed to the shell as a script on stdin (and the `cat' should consume
the rest of the script as input).

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Unexpected "!$" history expansion after use of here-document

2018-09-11 Thread Viktor Dukhovni
Configuration Information [Automatically generated, do not change]:
Machine: amd64
OS: freebsd11.1
Compiler: cc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='amd64' 
-DCONF_OSTYPE='freebsd11.1' -DCONF_MACHTYPE='amd64-portbld-freebsd11.1' 
-DCONF_VENDOR='portbld' -DLOCALEDIR='/usr/local/share/locale' -DPACKAGE='bash' 
-DSHELL  -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib  
-DDEFAULT_PATH_VALUE='/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin'
  -DSTANDARD_UTILS_PATH='/sbin:/bin:/usr/sbin:/usr/bin' -DLIBICONV_PLUG 
-I/usr/local/include -O2 -pipe  -DLIBICONV_PLUG -fstack-protector 
-fno-strict-aliasing -Wno-parentheses -Wno-format-security
uname output: FreeBSD straasha.imrryr.org 11.1-RELEASE-p10 FreeBSD 
11.1-RELEASE-p10 #1 r75M: Sat Jun 23 17:50:31 EDT 2018 
r...@straasha.imrryr.org:/usr/obj/usr/src/sys/GENERIC  amd64
Machine Type: amd64-portbld-freebsd11.1

Bash Version: 4.4
Patch Level: 23
Release Status: release

Description:
Intuitevely, (and confirmed behaviour of "csh" whose history
substitution bash emulates), after a command of the form:

$ grep foo < /tmp/bar
foobar
abcdef
EOF

One would expect "!$" to be /tmp/bar, so that an immediate:

$ wc -l !$

should expand to "wc -l /tmp/bar" and output "1".

Instead we get:

$ PS1='$ '
$ PS2=" "
$ grep foo < /tmp/bar
 foobar
 abcdef
 EOF
$ cat !$ > /dev/tty
cat 
 > /dev/tty
abc
abc
123
123

$ history 3
3  grep foo < /tmp/bar
foobar
abcdef
EOF

4  cat 
 > /dev/tty
5  history 3

It looks like "!$" expands to the newline after the EOF in history 
entry 3.
The expansion (as in "csh") should be "/tmp/bar".

Repeat-By:

In interactive shell, expand "!$" after a command that uses a 
here-document:

$ grep foo < /tmp/bar
foo
EOF
$ echo "--!$++"
echo "--
++"
--
++