Guess what this will do


#1

Without cheating (trying to run it) what will this pair of files do
under Linux…

Here is a little script we want to be interpreted by the “flashbang”
interpreter…
===/home/johnc/foo/hashbang===========================================
#!/home/johnc/foo/flashbang

puts ARGV[0]

======================================================================

So we expect
./hashbang “Hello World”
to be formally equivalent to running…

/home/johnc/foo/flashbang ./hashbang “Hello World”

Now assume…

===/home/johnc/foo/flashbang==========================================
#!/bin/sh

echo flashbanger
echo $0
echo “$@”

/usr/bin/ruby “$@”

Let’s try…
/home/johnc/foo/flashbang -e ‘puts “Hello World”’

On my system the result is…
flashbanger
/home/johnc/foo/flashbang
puts “Hello World”
Hello World

No surprise…

Now what do you think happens if you say…?

./hashbang “Hello World”

Now what do you think happens if you say…?

/home/johnc/foo/flashbang ./hashbang “Hello World”

Scroll down for the answers…
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
./hashbang “Hello World”
./hashbang: line 4: puts: command not found

Surprise Number 1 : The binfmt look up code looks up flashbang and
finds it’s also a #! freaks out and just uses sh as the interpreter…

To check that lets try…
==hashcat=============================================================
#!/home/johnc/foo/flashcat

puts ARGV[0]

echo “Look, we must be running $SHELL”

and
==flashcat============================================================
#!/bin/cat

echo flashbanger
echo $0
echo “$@”

/usr/bin/ruby “$@”

Then…

./hashcat “Hello World”
./hashcat: line 4: puts: command not found
Look, we must be running /bin/bash

and…
/home/johnc/foo/flashcat ./hashbang “Hello World”

Comes out as …
/bin/cat /home/johnc/foo/flashcat ./hashcat “Hello World”

Which results, no surprise as…

#!/bin/cat

echo flashbanger
echo $0
echo “$@”

/usr/bin/ruby “$@”
#!/home/johnc/foo/flashbang

puts ARGV[0]

/bin/cat: Hello World: No such file or directory

Now for Surprise #2

/home/johnc/foo/flashbang ./hashbang “Hello World” | head -20
flashbanger
/home/johnc/foo/flashbang
./hashbang Hello World
flashbanger
/home/johnc/foo/flashbang
./hashbang Hello World
flashbanger
/home/johnc/foo/flashbang
./hashbang Hello World
flashbanger
/home/johnc/foo/flashbang
./hashbang Hello World
flashbanger
/home/johnc/foo/flashbang
./hashbang Hello World
flashbanger
/home/johnc/foo/flashbang
./hashbang Hello World
flashbanger
/home/johnc/foo/flashbang

WHAT THE HELL!? Why?

Well, deep within ruby/ruby.c is a chunk of code that looks for a #!
on the first line. If it contains the word “ruby” anywhere, it ignores
it. If it doesn’t it says, Oh dear. This one wasn’t actually for me. I
better be gnice and exec that interpreter and feed it this script…

All in all, you can tell I have a had rather exotic and frustrating
day or three.

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : removed_email_address@domain.invalid
New Zealand


#2

On Wed, Jun 27, 2007 at 08:28:07AM +0900, John C. wrote:

Without cheating (trying to run it) what will this pair of files do under Linux…

[lots of stuff snipped]

WHAT THE HELL!? Why?

Well, deep within ruby/ruby.c is a chunk of code that looks for a #!
on the first line. If it contains the word “ruby” anywhere, it ignores
it. If it doesn’t it says, Oh dear. This one wasn’t actually for me. I
better be gnice and exec that interpreter and feed it this script…

That’s a Perlism. man perlrun says:
If the #! line does not contain the word “perl”, the program named
after the #! is executed instead of the Perl interpreter. This is
slightly bizarre, but it helps people on machines that don’t do #!,
because they can tell a program that their SHELL is /usr/bin/perl,
and Perl will then dispatch the program to the correct interpreter
for them.

I’m a bit surprised that ruby mimicks this behavior! Does it even
build on systems that don’t do ``#!’’?