Home Man
Search
Today's Posts
Register

Linux & Unix Commands - Search Man Pages

NetBSD 6.1.5 - man page for script (netbsd section 7)

SCRIPT(7)		       BSD Miscellaneous Information Manual			SCRIPT(7)

NAME
     script -- interpreter script execution

DESCRIPTION
     The system is capable of treating a text file containing commands intended for an inter-
     preter, such as sh(1) or awk(1), as an executable program.

     An ``interpreter script'' is a file which has been set executable (see chmod(2)) and which
     has a first line of the form:

	   #! pathname [argument]

     The ``#!'' must appear as the first two characters of the file.  A space between the ``#!''
     and pathname is optional.	At most one argument may follow pathname, and the length of the
     entire line is limited (see below).

     If such a file is executed (such as via the execve(2) system call), the interpreter speci-
     fied by the pathname is executed by the system.  (The pathname is executed without regard to
     the PATH variable, so in general pathname should be an absolute path.)

     The arguments passed to the interpreter will be as follows.  argv[0] will be the path to the
     interpreter itself, as specified on the first line of the script.	If there is an argument
     following pathname on the first line of the script, it will be passed as argv[1].	The sub-
     sequent elements of argv will be the path to the interpreter script file itself (i.e. the
     original argv[0]) followed by any further arguments passed when execve(2) was invoked to
     execute the script file.

     By convention, it is expected that an interpreter will open the script file passed as an
     argument and process the commands within it.  Typical interpreters treat '#' as a comment
     character, and thus will ignore the initial line of the script because it begins ``#!'', but
     there is no requirement for this per se.

     On NetBSD, the length of the ``#!'' line, excluding the ``#!'' itself, is limited to
     PATH_MAX (as defined in <limits.h>).  Other operating systems impose much smaller limits on
     the length of the ``#!'' line (see below).

     Note that the interpreter may not itself be an interpreter script.  If pathname does not
     point to an executable binary, execution of the interpreter script will fail.

   Trampolines and Portable Scripts
     Different operating systems often have interpreters located in different locations, and the
     kernel executes the passed interpreter without regard to the setting of environment vari-
     ables such as PATH.  This makes it somewhat challenging to set the ``#!'' line of a script
     so that it will run identically on different systems.

     Since the env(1) utility executes a command passed to it on its command line, it is often
     used as a ``trampoline'' to render scripts portable.  If the leading line of a script reads
	   #! /usr/bin/env interp
     then the env(1) command will execute the ``interp'' command it finds in its PATH, passing on
     to it all subsequent arguments with which it itself was called.  Since /usr/bin/env is found
     on almost all POSIX style systems, this trick is frequently exploited by authors who need a
     script to execute without change on multiple systems.

   Historical Note: Scripts without ``#!''
     Shell scripts predate the invention of the ``#!'' convention, which is implemented in the
     kernel.  In the days of Version 7 AT&T UNIX, there was only one interpreter used on the sys-
     tem, /bin/sh, and the shell treated any file that failed to execute with an ENOEXEC error
     (see intro(2)) as a shell script.

     Most shells (such as sh(1)) and certain other facilities (including execlp(3) and execvp(3)
     but not other types of exec(3) calls) still pass interpreter scripts that do not include the
     ``#!'' (and thus fail to execute with ENOEXEC) to /bin/sh.

     As this behavior is implemented outside the kernel, there is no mechanism that forces it to
     be respected by all programs that execute other programs.	It is thus not completely reli-
     able.  It is therefore important to always include
	   #!/bin/sh
     in front of Bourne shell scripts, and to treat the traditional behavior as obsolete.

EXAMPLES
     Suppose that an executable binary exists in /bin/interp and that the file /tmp/script con-
     tains:

	   #!/bin/interp -arg

	   [...]

     and that /tmp/script is set mode 755.

     Executing

	   $ /tmp/script one two three

     at the shell will result in /bin/interp being executed, receiving the following arguments in
     argv (numbered from 0):

	   "/bin/interp", "-arg", "/tmp/script", "one", "two", "three"

   Portability Note: Multiple arguments
     The behavior of multiple arguments on the ``#!'' line is highly non-portable between differ-
     ent systems.  In general, only one argument can be assumed to work consistently.

     Consider the following variation on the previous example.	Suppose that an executable binary
     exists in /bin/interp and that the file /tmp/script contains:

	   #!/bin/interp -x -y

	   [...]

     and that /tmp/script is set mode 755.

     Executing

	   $ /tmp/script one two three

     at the shell will result in /bin/interp being executed, receiving the following arguments in
     argv (numbered from 0):

	   "/bin/interp", "-x -y", "/tmp/script", "one", "two", "three"

     Note that "-x -y" will be passed on NetBSD as a single argument.

     Although most POSIX style operating systems will pass only one argument, the behavior when
     multiple arguments are included is not consistent between platforms.  Some, such as current
     releases of NetBSD, will concatenate multiple arguments into a single argument (as above),
     some will truncate them, and at least one will pass them as multiple arguments.

     The NetBSD behavior is common but not universal.  Sun's Solaris would present the above
     argument as "-x", dropping the " -y" entirely.  Perhaps uniquely, recent versions of Apple's
     OS X will actually pass multiple arguments properly, i.e.:

	   "/bin/interp", "-x", "-y", "/tmp/script", "one", "two", "three"

     The behavior of the system in the face of multiple arguments is thus not currently standard-
     ized, should not be relied on, and may be changed in future releases.  In general, pass at
     most one argument, and do not rely on multiple arguments being concatenated.

SEE ALSO
     awk(1), csh(1), ksh(1), sh(1), chmod(2), execve(2), intro(2), execlp(3), execvp(3), fd(4),
     options(4), setuid(7)

STANDARDS
     The behavior of interpreter scripts is obliquely referred to, but never actually described
     in, IEEE Std 1003.1-2004 (``POSIX.1'').

     The behavior is partially (but not completely) described in the System V Interface
     Definition, Fourth Edition (``SVID4'').

     Although it has never been formally standardized, the behavior described is largely portable
     across POSIX style systems, with two significant exceptions: the maximum length of the
     ``#!'' line, and the behavior if multiple arguments are passed.  Please be aware that some
     operating systems limit the line to 32 or 64 characters, and that (as described above) the
     behavior in the face of multiple arguments is not consistent across systems.

HISTORY
     The behavior of the kernel when encountering scripts that start in ``#!'' was not present in
     Version 7 AT&T UNIX.  A Usenet posting to net.unix by Guy Harris on October 16, 1984 claims
     that the idea for the ``#!'' behavior was first proposed by Dennis Ritchie but that the
     first implementation was on BSD.

     Historical manuals (specifically the exec man page) indicate that the behavior was present
     in 4BSD at least as early as April, 1981.	Information on precisely when it was first imple-
     mented, and in which version of UNIX, is solicited.

SECURITY CONSIDERATIONS
     Numerous security problems are associated with setuid interpreter scripts.

     In addition to the fact that many interpreters (and scripts) are simply not designed to be
     robust in a setuid context, a race condition exists between the moment that the kernel exam-
     ines the interpreter script file and the moment that the newly invoked interpreter opens the
     file itself.

     Because of these security issues, NetBSD does not allow setuid interpreter scripts by
     default.  In order to turn on setuid interpreter scripts,
	   options SETUIDSCRIPTS
     must be set in the configuration of the running kernel.  Setting this option implies the
     FDSCRIPTS option, which causes the kernel to open the script file on behalf of the inter-
     preter and pass it in argv as /dev/fd/[fdnum].  (See fd(4) for an explanation of the
     /dev/fd/[fdnum] devices.)	This design avoids the race condition, at the cost of denying the
     interpreter the actual name of the script file.  See options(4) for more information.

     However, the FDSCRIPTS mechanism is not a cure-all for security issues in setuid inter-
     preters and scripts.  Subtle techniques can be used to subvert even seemingly well written
     scripts.  Scripts executed by Bourne type shells can be subverted in numerous ways, such as
     by setting the IFS variable before executing the script.  Other interpreters possess their
     own vulnerabilities.  Turning on SETUIDSCRIPTS is therefore very dangerous, and should not
     be done lightly if at all.

BSD					   May 6, 2005					      BSD


All times are GMT -4. The time now is 11:13 PM.

Unix & Linux Forums Content Copyrightę1993-2018. All Rights Reserved.
UNIX.COM Login
Username:
Password:  
Show Password