Subject: Changing exec's #! behavior
To: None <tech-kern@netbsd.org>
From: Jason R Thorpe <thorpej@zembu.com>
List: tech-kern
Date: 06/13/2000 11:29:59
Hi folks...

A co-worker recently ran into a problem where the construct:

#!/usr/bin/env perl -w

was working on a Solaris system, but not a NetBSD system.

#! is defined to be the following on both systems (paraphrased):

	#! /path/to/interpreter [arg]

	`interpreter' is invoked with the pathname to the interpreter
	as argv[0].  If the optional `arg' is specified, it is passed
	as argv[1] to the interpreter.  The interpreter is then passed
	$0, $1, ... $n of the original exec.

That is to say:

foo.pl:
#!/usr/bin/env perl

./foo.pl one two three

env(1) gets:

argv[0] = /usr/bin/env
argv[1] = perl
argv[2] = ./foo.pl
argv[3] = one
argv[4] = two
argv[5] = three

The problem is that BSD and Solaris are defining [arg] differently
in the #! specification.  In BSD, [arg] is defined as "until the end
of the line" whereas in Solaris, it's defined as "until the first
whitespace".

This means that the following:

foo.pl:
#!/usr/bin/env perl -w

shows up as the following on Solaris:

argv[0] = /usr/bin/env
argv[1] = perl
argv[2] = ./foo.pl
argv[3] = one
argv[4] = two
argv[5] = three 

and the following on NetBSD:

argv[0] = /usr/bin/env
argv[1] = perl -w
argv[2] = ./foo.pl
argv[3] = one
argv[4] = two
argv[5] = three 

env(1) subsequently complains that it cannot exec "perl -w" because it
doesn't exist.

Now, the reason that the -w is seen by perl in the Solaris case is
because perl *itself* looks at the script for a line that has "#!" and
"perl" in it, and upon finding it, parses the command line args to
perl located there itself.

I've changed NetBSD's exec_script.c to have the Solaris behavior and
am using it that way in our environment here.  But I'd like to get
comments on this before I commit the change to the master NetBSD
sources.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>