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