xref: /dragonfly/share/man/man7/script.7 (revision 0db87cb7)
1.\"	$OpenBSD: script.7,v 1.4 2007/05/31 19:19:58 jmc Exp $
2.\"
3.\"	$NetBSD: script.7,v 1.1 2005/05/07 02:20:34 perry Exp $
4.\"	$DragonFly: src/share/man/man7/script.7,v 1.2 2007/12/22 19:07:00 swildner Exp $
5.\"
6.\" Copyright (c) 2005 The NetBSD Foundation, Inc.
7.\" All rights reserved.
8.\"
9.\" This document was originally contributed to The NetBSD Foundation
10.\" by Perry E. Metzger of Metzger, Dowdeswell & Co. LLC.
11.\"
12.\" Redistribution and use in source and binary forms, with or without
13.\" modification, are permitted provided that the following conditions
14.\" are met:
15.\" 1. Redistributions of source code must retain the above copyright
16.\"    notice, this list of conditions and the following disclaimer.
17.\" 2. Redistributions in binary form must reproduce the above copyright
18.\"    notice, this list of conditions and the following disclaimer in the
19.\"    documentation and/or other materials provided with the distribution.
20.\" 3. All advertising materials mentioning features or use of this software
21.\"    must display the following acknowledgement:
22.\"        This product includes software developed by the NetBSD
23.\"        Foundation, Inc. and its contributors.
24.\" 4. Neither the name of The NetBSD Foundation nor the names of its
25.\"    contributors may be used to endorse or promote products derived
26.\"    from this software without specific prior written permission.
27.\"
28.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38.\" POSSIBILITY OF SUCH DAMAGE.
39.\"
40.Dd December 21, 2007
41.Dt SCRIPT 7
42.Os
43.Sh NAME
44.Nm script
45.Nd interpreter script execution
46.Sh DESCRIPTION
47The system is capable of treating a text file containing commands
48intended for an interpreter, such as
49.Xr sh 1
50or
51.Xr awk 1 ,
52as an executable program.
53.Pp
54An
55.Dq interpreter script
56is a file which has been set executable (see
57.Xr chmod 2 )
58and which has a first line of the form:
59.Pp
60.D1 Li #! Ar pathname Op Ar argument
61.Pp
62The
63.Sq #!
64must appear as the first two characters of the file.
65A space between the
66.Sq #!
67and
68.Ar pathname
69is optional.
70At most one
71.Ar argument
72may follow
73.Ar pathname ,
74and the length of the entire line is limited (see below).
75.Pp
76If such a file is executed (such as via the
77.Xr execve 2
78system call), the interpreter specified by the
79.Ar pathname
80is executed by the system.
81(The
82.Ar pathname
83is executed without regard to the
84.Ev PATH
85variable, so in general
86.Ar pathname
87should be an absolute path.)
88.Pp
89The arguments passed to the interpreter will be as follows.
90.Va argv[0]
91will be the path to the interpreter itself, as specified on the first
92line of the script.
93If there is an
94.Ar argument
95following
96.Ar pathname
97on the first line of the script, it will be passed as
98.Va argv[1] .
99The subsequent elements of
100.Va argv
101will be the path to the interpreter script file itself (i.e. the
102original
103.Va argv[0] )
104followed by any further arguments passed when
105.Xr execve 2
106was invoked to execute the script file.
107.Pp
108By convention, it is expected that an interpreter will open the script
109file passed as an argument and process the commands within it.
110Typical interpreters treat
111.Sq #
112as a comment character, and thus will ignore the initial line of the script
113because it begins
114.Sq #! ,
115but there is no requirement for this per se.
116.Pp
117On
118.Dx ,
119the length of the
120.Sq #!
121line, excluding the
122.Sq #!
123itself, is limited to
124.Dv PATH_MAX
125(as defined in
126.In limits.h ) .
127Other operating systems impose different limits on the length of
128the
129.Sq #!
130line (see below).
131.Pp
132Note that the interpreter may not itself be an interpreter script.
133If
134.Ar pathname
135does not point to an executable binary, execution of the interpreter
136script will fail.
137.Ss Trampolines and Portable Scripts
138Different operating systems often have interpreters located in
139different locations, and the kernel executes the passed interpreter
140without regard to the setting of environment variables such as
141.Ev PATH .
142This makes it somewhat challenging to set the
143.Sq #!
144line of a script so that it will run identically on different systems.
145.Pp
146Since the
147.Xr env 1
148utility executes a command passed to it on its command line, it is
149often used as a
150.Dq trampoline
151to render scripts portable.
152If the leading line of a script reads
153.Pp
154.Dl #! /usr/bin/env interp
155.Pp
156then the
157.Xr env 1
158command will execute the
159.Dq interp
160command it finds in its
161.Ev PATH ,
162passing on to it all subsequent arguments with which it itself was called.
163Since
164.Pa /usr/bin/env
165is found on almost all
166.Tn POSIX
167style systems, this trick is frequently exploited by authors who need
168a script to execute without change on multiple systems.
169.Ss Historical Note: Scripts without `#!'
170Shell scripts predate the invention of the
171.Sq #!
172convention, which is implemented in the kernel.
173In the days of
174.At v7 ,
175there was only one interpreter used on the system,
176.Pa /bin/sh ,
177and the shell treated any file that failed to execute with an
178.Er ENOEXEC
179error
180(see
181.Xr intro 2 )
182as a shell script.
183.Pp
184Most shells (such as
185.Xr sh 1 )
186and certain other facilities (including
187.Xr execlp 3
188and
189.Xr execvp 3
190but not other types of
191.Xr exec 3
192calls) still pass
193interpreter scripts that do not include the
194.Sq #!
195(and thus fail to execute with
196.Er ENOEXEC )
197to
198.Pa /bin/sh .
199.Pp
200As this behavior is implemented outside the kernel, there is no
201mechanism that forces it to be respected by all programs that execute
202other programs.
203It is thus not completely reliable.
204It is therefore important to always include
205.Pp
206.Dl #!/bin/sh
207.Pp
208in front of Bourne shell scripts, and to treat the traditional
209behavior as obsolete.
210.Sh EXAMPLES
211Suppose that an executable binary exists in
212.Pa /bin/interp
213and that the file
214.Pa /tmp/script
215contains:
216.Bd -literal -offset indent
217#!/bin/interp -arg
218
219[...]
220.Ed
221.Pp
222and that
223.Pa /tmp/script
224is set mode 755.
225.Pp
226Executing
227.Pp
228.Dl $ /tmp/script one two three
229.Pp
230at the shell will result in
231.Pa /bin/interp
232being executed, receiving the following arguments in
233.Va argv
234(numbered from 0):
235.Bd -ragged -offset indent
236.Qq /bin/interp ,
237.Qq "-arg" ,
238.Qq /tmp/script ,
239.Qq one ,
240.Qq two ,
241.Qq three
242.Ed
243.Ss Portability Note: Multiple arguments
244The behavior of multiple arguments on the
245.Sq #!
246line is highly non-portable between different systems.
247In general, only one argument can be assumed to work consistently.
248.Pp
249Consider the following variation on the previous example.
250Suppose that an executable binary exists in
251.Pa /bin/interp
252and that the file
253.Pa /tmp/script
254contains:
255.Bd -literal -offset indent
256#!/bin/interp -x -y
257
258[...]
259.Ed
260.Pp
261and that
262.Pa /tmp/script
263is set mode 755.
264.Pp
265Executing
266.Pp
267.Dl $ /tmp/script one two three
268.Pp
269at the shell will result in
270.Pa /bin/interp
271being executed, receiving the following arguments in
272.Va argv
273(numbered from 0):
274.Bd -ragged -offset indent
275.Qq /bin/interp ,
276.Qq "-x -y" ,
277.Qq /tmp/script ,
278.Qq one ,
279.Qq two ,
280.Qq three
281.Ed
282.Pp
283Note that
284.Qq "-x -y"
285will be passed on
286.Dx
287as a single argument.
288.Pp
289Although most
290.Tn POSIX
291style operating systems will pass only one
292.Ar argument ,
293the behavior when multiple arguments are included is not
294consistent between platforms.
295Some, such as
296.Dx ,
297will concatenate multiple arguments into a single argument (as above),
298some will truncate them, and at least one will pass them as multiple
299arguments.
300.Pp
301The
302.Dx
303behavior is common but not universal.
304Sun's
305.Tn Solaris
306would present the above argument as
307.Qq -x ,
308dropping the
309.Qq " -y"
310entirely.
311Perhaps uniquely, recent versions of Apple's
312.Tn OS X
313will actually pass multiple arguments properly, i.e.:
314.Bd -ragged -offset indent
315.Qq /bin/interp ,
316.Qq -x ,
317.Qq -y ,
318.Qq /tmp/script ,
319.Qq one ,
320.Qq two ,
321.Qq three
322.Ed
323.Pp
324The behavior of the system in the face of multiple arguments is thus
325not currently standardized, should not be relied on, and may be
326changed in future releases.
327In general, pass at most one argument, and do not rely on multiple
328arguments being concatenated.
329.Sh SEE ALSO
330.Xr awk 1 ,
331.Xr csh 1 ,
332.Xr sh 1 ,
333.Xr chmod 2 ,
334.Xr execve 2 ,
335.Xr intro 2 ,
336.Xr execlp 3 ,
337.Xr execvp 3
338.Sh STANDARDS
339The behavior of interpreter scripts is obliquely referred to, but
340never actually described in,
341.St -p1003.1-2004 .
342.Pp
343The behavior is partially (but not completely) described in the
344.St -svid4 .
345.Pp
346Although it has never been formally standardized, the behavior
347described is largely portable across
348.Tn POSIX
349style systems, with two significant exceptions: the maximum length of the
350.Sq #!
351line, and the behavior if multiple arguments are passed.
352Please be aware that the behavior in the
353face of multiple arguments is not consistent across systems.
354.Sh HISTORY
355The behavior of the kernel when encountering scripts that start in
356.Sq #!
357was not present in
358.At v7 .
359A Usenet posting to net.unix by Guy Harris on October 16, 1984 claims
360that the idea for the
361.Sq #!
362behavior was first proposed by Dennis Ritchie but that the first
363implementation was on
364.Bx .
365.Pp
366Historical manuals (specifically the exec man page) indicate that the
367behavior was present in
368.Bx 4
369at least as early as April, 1981.
370Information on precisely when it was first implemented, and in which
371version of
372.Ux ,
373is solicited.
374.Sh CAVEATS
375Numerous security problems are associated with setuid interpreter
376scripts.
377.Pp
378In addition to the fact that many interpreters (and scripts) are
379simply not designed to be robust in a setuid context, a race condition
380exists between the moment that the kernel examines the interpreter
381script file and the moment that the newly invoked interpreter opens
382the file itself.
383.Pp
384Subtle techniques can be used to subvert even seemingly well written scripts.
385Scripts executed by Bourne type shells can be subverted in numerous
386ways, such as by setting the
387.Ev IFS
388variable before executing the script.
389Other interpreters possess their own vulnerabilities.
390Setting the Set-user-ID on execution (SUID) bit
391is therefore very dangerous, and should not be done lightly, if at all.
392