xref: /dragonfly/share/man/man7/script.7 (revision c9c5aa9e)
1.\"	$OpenBSD: script.7,v 1.8 2019/08/11 15:48:08 deraadt Exp $
2.\"
3.\"	$NetBSD: script.7,v 1.6 2010/03/22 18:58:32 joerg 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 November 1, 2020
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.Dx ,
111the length of the
112.Sq #!
113line, excluding the
114.Sq #!
115itself, is limited to
116.Dv MAXSHELLCMDLEN
117(as defined in
118.In sys/imgact.h ) .
119Other operating systems impose different limits on the length of
120the
121.Sq #!
122line (see below).
123.Pp
124Note that the interpreter may not itself be an interpreter script.
125If
126.Ar pathname
127does not point to an executable binary, execution of the interpreter
128script will fail.
129.Ss Trampolines and Portable Scripts
130Different operating systems often have interpreters located in
131different locations, and the kernel executes the passed interpreter
132without regard to the setting of environment variables such as
133.Ev PATH .
134This makes it somewhat challenging to set the
135.Sq #!
136line of a script so that it will run identically on different systems.
137.Pp
138Since the
139.Xr env 1
140utility executes a command passed to it on its command line, it is
141often used as a
142.Dq trampoline
143to render scripts portable.
144If the leading line of a script reads
145.Pp
146.Dl #! /usr/bin/env interp
147.Pp
148then the
149.Xr env 1
150command will execute the
151.Dq interp
152command it finds in its
153.Ev PATH ,
154passing on to it all subsequent arguments with which it itself was called.
155Since
156.Pa /usr/bin/env
157is found on almost all
158.Tn POSIX
159style systems, this trick is frequently exploited by authors who need
160a script to execute without change on multiple systems.
161.Ss Historical Note: Scripts without `#!'
162Shell scripts predate the invention of the
163.Sq #!
164convention, which is implemented in the kernel.
165In the days of
166.At v7 ,
167there was only one interpreter used on the system,
168.Pa /bin/sh ,
169and the shell treated any file that failed to execute with an
170.Er ENOEXEC
171error
172(see
173.Xr intro 2 )
174as a shell script.
175.Pp
176Most shells (such as
177.Xr sh 1 )
178and certain other facilities (including
179.Xr execlp 3
180and
181.Xr execvp 3
182but not other types of
183.Xr exec 3
184calls) still pass
185interpreter scripts that do not include the
186.Sq #!
187(and thus fail to execute with
188.Er ENOEXEC )
189to
190.Pa /bin/sh .
191.Pp
192As this behavior is implemented outside the kernel, there is no
193mechanism that forces it to be respected by all programs that execute
194other programs.
195It is thus not completely reliable.
196It is therefore important to always include
197.Pp
198.Dl #!/bin/sh
199.Pp
200in front of Bourne shell scripts, and to treat the traditional
201behavior as obsolete.
202.Sh EXAMPLES
203Suppose that an executable binary exists in
204.Pa /bin/interp
205and that the file
206.Pa /tmp/script
207contains:
208.Bd -literal -offset indent
209#!/bin/interp -arg
210
211[...]
212.Ed
213.Pp
214and that
215.Pa /tmp/script
216is set mode 755.
217.Pp
218Executing
219.Pp
220.Dl $ /tmp/script one two three
221.Pp
222at the shell will result in
223.Pa /bin/interp
224being executed, receiving the following arguments in
225.Va argv
226(numbered from 0):
227.Bd -ragged -offset indent
228.Qq /bin/interp ,
229.Qq "-arg" ,
230.Qq /tmp/script ,
231.Qq one ,
232.Qq two ,
233.Qq three
234.Ed
235.Ss Portability Note: Multiple arguments
236The behavior of multiple arguments on the
237.Sq #!
238line is highly non-portable between different systems.
239In general, only one argument can be assumed to work consistently.
240.Pp
241Consider the following variation on the previous example.
242Suppose that an executable binary exists in
243.Pa /bin/interp
244and that the file
245.Pa /tmp/script
246contains:
247.Bd -literal -offset indent
248#!/bin/interp -x -y
249
250[...]
251.Ed
252.Pp
253and that
254.Pa /tmp/script
255is set mode 755.
256.Pp
257Executing
258.Pp
259.Dl $ /tmp/script one two three
260.Pp
261at the shell will result in
262.Pa /bin/interp
263being executed, receiving the following arguments in
264.Va argv
265(numbered from 0):
266.Bd -ragged -offset indent
267.Qq /bin/interp ,
268.Qq "-x -y" ,
269.Qq /tmp/script ,
270.Qq one ,
271.Qq two ,
272.Qq three
273.Ed
274.Pp
275Note that
276.Qq "-x -y"
277will be passed on
278.Dx
279as a single argument.
280.Pp
281Although most
282.Tn POSIX
283style operating systems will pass only one
284.Ar argument ,
285the behavior when multiple arguments are included is not
286consistent between platforms.
287Some, such as
288.Dx ,
289will concatenate multiple arguments into a single argument (as above),
290some will truncate them, and at least one will pass them as multiple
291arguments.
292.Pp
293The
294.Dx
295behavior is common but not universal.
296Sun's
297.Tn Solaris
298would present the above argument as
299.Qq -x ,
300dropping the
301.Qq " -y"
302entirely.
303Perhaps uniquely, recent versions of Apple's
304.Tn OS X
305will actually pass multiple arguments properly, i.e.:
306.Bd -ragged -offset indent
307.Qq /bin/interp ,
308.Qq -x ,
309.Qq -y ,
310.Qq /tmp/script ,
311.Qq one ,
312.Qq two ,
313.Qq three
314.Ed
315.Pp
316The behavior of the system in the face of multiple arguments is thus
317not currently standardized, should not be relied on, and may be
318changed in future releases.
319In general, pass at most one argument, and do not rely on multiple
320arguments being concatenated.
321.Sh SEE ALSO
322.Xr awk 1 ,
323.Xr csh 1 ,
324.Xr sh 1 ,
325.Xr chmod 2 ,
326.Xr execve 2 ,
327.Xr intro 2 ,
328.Xr execlp 3 ,
329.Xr execvp 3
330.Sh STANDARDS
331The behavior of interpreter scripts is obliquely referred to, but
332never actually described in,
333.St -p1003.1-2004 .
334.Pp
335The behavior is partially (but not completely) described in the
336.St -svid4 .
337.Pp
338Although it has never been formally standardized, the behavior
339described is largely portable across
340.Tn POSIX
341style systems, with two significant exceptions: the maximum length of the
342.Sq #!
343line, and the behavior if multiple arguments are passed.
344Please be aware that the behavior in the
345face of multiple arguments is not consistent across systems.
346.Sh HISTORY
347The behavior of the kernel when encountering scripts that start in
348.Sq #!
349was not present in
350.At v7 .
351A Usenet posting to net.unix by Guy Harris on October 16, 1984 claims
352that the idea for the
353.Sq #!
354behavior was first proposed by Dennis Ritchie but that the first
355implementation was on
356.Bx .
357.Pp
358Historical manuals (specifically the exec man page) indicate that the
359behavior was present in
360.Bx 4
361at least as early as April, 1981.
362Information on precisely when it was first implemented, and in which
363version of
364.Ux ,
365is solicited.
366.Sh CAVEATS
367Numerous security problems are associated with setuid interpreter
368scripts.
369.Pp
370In addition to the fact that many interpreters (and scripts) are
371simply not designed to be robust in a setuid context, a race condition
372exists between the moment that the kernel examines the interpreter
373script file and the moment that the newly invoked interpreter opens
374the file itself.
375.Pp
376Subtle techniques can be used to subvert even seemingly well written scripts.
377Scripts executed by Bourne type shells can be subverted in numerous
378ways, such as by setting the
379.Ev IFS
380variable before executing the script.
381Other interpreters possess their own vulnerabilities.
382Setting the Set-user-ID on execution (SUID) bit
383is therefore very dangerous, and should not be done lightly, if at all.
384