summaryrefslogtreecommitdiff
path: root/doc/execlineb.html
blob: ff9fe5c7571b8a26b24621099bcab17ac5e96d0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-6" />
    <meta http-equiv="Content-Language" content="en" />
    <title>execline: the execlineb command</title>
    <meta name="Description" content="execline: the execlineb command" />
    <meta name="Keywords" content="execline command execlineb launcher" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">execline</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> The <tt>execlineb</tt> program </h1>

<p>
<tt>execlineb</tt> reads and executes a script. <br />
It is a command launcher: it reads a file, turns that file into a command line,
then executes into that command line.
</p>

<h2> Interface </h2>

<pre>
     execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> | -s <em>nmin</em> ] [ -e ] -c <em>script</em> [ <em>args...</em> ]
</pre>

<p>
or
</p>

<pre>
     execlineb [ -q | -w | -W ] [ -p | -P | -S <em>nmin</em> | -s <em>nmin</em> ] [ -e ] <em>scriptfile</em> [ <em>args...</em> ]
</pre>

<p>
or in an executable file:
</p>

<pre>
#!/command/execlineb [ -qwWpPS<em>nmin</em> ]
<em>script</em>
</pre>

<p>
 <em>Parsing phase</em>.
</p>

<ul>
 <li> <tt>execlineb</tt> reads and parses the script it is given.
It exits 100 on a syntax error and 111 on a temporary error.
It makes an <em>argv</em>, i.e. a system command line, with the
parsed script. If the <em>argv</em> is empty, <tt>execlineb</tt>
exits 0. </li>
</ul>

<p>
 <em>Environment management phase</em>.
</p>

<ul>
 <li> <em>Pushing the current stack frame.</em> If none of the
<tt>-p</tt>, <tt>-P</tt>, <tt>-S</tt> or <tt>-s</tt> options are set:
<tt>execlineb</tt> <a href="el_pushenv.html">pushes</a>
the current positional parameters, i.e. environment variables that
start with <tt>#</tt>, <tt>0</tt>, <tt>1</tt>, ..., <tt>9</tt>.
To get the previous values back, use
<a href="emptyenv.html"><tt>emptyenv&nbsp;-P</tt></a>. </li>
 <li> <em>Setting the new stack frame.</em> If none of the <tt>-P</tt>,
<tt>-S</tt> or <tt>-s</tt> options are set:
 <ul>
  <li> <tt>execlineb</tt> sets the <tt>#</tt> environment variable to
the number <em>n</em> of <em>args</em> it is given. </li>
  <li> It sets the <tt>0</tt> environment variable to the name
of the script - or to the <tt>execlineb</tt> invocation name
if the <tt>-c</tt> option is used. </li>
  <li> It sets the <tt>1</tt>, <tt>2</tt>, ... <tt><em>n</em></tt>
environment variables to the different <em>args</em>. </li>
 </ul> </li>
</ul>

<p>
 <em>Execution phase</em>.
</p>

<ul>
 <li> <tt>execlineb</tt> executes into the <em>argv</em> it
has built from the script.
There is only one command line for the
whole script: the <tt>execlineb</tt> binary is a <em>launcher</em>,
whose sole purpose is to execute into that command line. It does
not stay in memory like a traditional <em>interpreter</em> would. </li>
</ul>

<h2> Options </h2>

<ul>
 <li> <tt>-e</tt>&nbsp;: this option is ignored. This is meant to support
the use of execlineb in conjuction with programs that invoke
<tt>$SHELL -ec <em>script</em></tt>; the effect of <tt>/bin/sh -e</tt>
can be natively replicated in execline scripts if you use the
<a href="if.html">if</a> command instead of the
<a href="foreground.html">foreground</a> command. </li>
 <li> <tt>-c&nbsp;<em>script</em></tt>&nbsp;: execute <em>script</em>, do not
look for a file. </li>
</ul>

<p>
 See below for the other options.
</p>

<h2> Syntax of scripts </h2>

<p>
 An execlineb script is a string that must not contain the null character.
<tt>execlineb</tt> parses it and divides it into <em>words</em>.

 The parser recognizes the following components:
</p>

<ul>
 <li> <em>whitespace</em> is defined as spaces, tabs, newlines and
carriage returns. Words are always separated by whitespace.</li>
 <li> A <em>quoted string</em> begins with a doublequote (<tt>"</tt>)
and ends with another doublequote. Quoted doublequotes must be prefixed
by a backslash (<tt>\</tt>). Quoted strings always evaluate to exactly
one word. For instance, <tt>""</tt> evaluates to the empty word. </li>
 <li> The <tt>\a</tt>, <tt>\b</tt>, <tt>\t</tt>, <tt>\n</tt>, <tt>\v</tt>,
<tt>\f</tt>, and <tt>\r</tt> sequences are recognized in quoted
strings, and are converted to the ASCII numbers 7, 8, 9, 10, 11, 12 and
13 respectively. </li>
 <li> Inside a quoted string, backslashed
newlines disappear completely. </li>
 <li> <tt>\0x<em>ab</em></tt> sequences are recognized in quoted strings
and evaluate to ASCII hexadecimal number <em>ab</em>. </li>
 <li> <tt>\0<em>abc</em></tt> sequences are recognized in quoted strings
and evaluate to ASCII octal number <em>abc</em>. <em>abc</em> must not
be greater than <em>377</em>, or evaluate to 0. </li>
 <li> <tt>\<em>abc</em></tt> sequences are recognized in quoted strings
and evaluate to ASCII decimal number <em>abc</em>. <em>a</em> must not
be zero. <em>abc</em> must not be greater than 255, or evaluate to 0. </li>
 <li> A comment starts with a <tt>#</tt> and ends with the line. Comments
are not recognized inside quoted strings. </li>
 <li> Anything else is an unquoted string, that can evaluate to
zero or more words. </li>
 <li> Any character can be escaped in unquoted strings by prepending
it with a backslash. It works the same way in quoted strings, except
for the special sequences described above. </li>
 <li> As a special case, an unquoted backslash at the end of a line, or at
the end of the input, is ignored. This is to make it easier to copy
execline fragments from a shell script. </li>
</ul>

<p>
 You can see an example of distinct <tt>execlineb</tt> components
<a href="componentsb.txt">here</a>.
</p>

<p>
 In addition to that simple lexing,
<tt>execlineb</tt> performs the following higher-level parsing:
</p>

<ul>
   <li> A word consisting of a single <em>opening brace</em> (<tt>{</tt>)
increments an internal level counter, <em>blevel</em>, and disappears from the
<em>argv</em>. Quoted open braces do not have that behaviour. </li>
 <li> A word consisting of a single <em>closing brace</em> (<tt>}</tt>)
decrements <em>blevel</em>, and is replaced with the empty word.
Quoted closing braces do not have that behaviour. </li>
 <li> If <tt>execlineb</tt> finds that braces are unmatched (i.e.
<em>blevel</em> goes below 0 during the parsing, or is not 0 at the end
of the script), it exits 100 with an error message. </li>
 <li> <tt>execlineb</tt> automatically quotes
<a href="el_semicolon.html">blocks</a>. Which means that every time it
finds a word, it prepends it with <em>blevel</em> spaces. </li>
</ul>

<p>
For proper execution, the sequence of words must follow
the <a href="grammar.html">execline grammar</a>.
</p>

<h2> Options for block syntax checking </h2>

<p>
 External execline commands that read blocks, like
<a href="foreground.html">foreground</a>, use the <tt>EXECLINE_STRICT</tt>
environment variable: if it is set to 1, they will print a warning message
on stderr if they find their blocks not to be properly quoted. If it is set
to 2, they will also die. If it is set to 0, or unset, they won't complain
at all.
</p>

<p>
 Normally the <tt>EXECLINE_STRICT</tt> environment variable is
inherited from the caller. You can
force it unset, set to 1, or set to 2 by giving respectively the
<tt>-q</tt>, <tt>-w</tt> or <tt>-W</tt> option to <tt>execlineb</tt>.
</p>

<p>
 The <tt>EXECLINE_STRICT</tt> variable (as well as the <tt>-q</tt>,
<tt>-w</tt> and <tt>-W</tt> options to <tt>execlineb</tt>) will also modify
the behaviour of the <tt>-S&nbsp;<em>nmin</em></tt> and <tt>-s&nbsp;<em>nmin</em></tt>
options when <tt>execlineb</tt> is called with less than <em>nmin</em>
positional parameters:
</p>

<ul>
 <li> If <tt>EXECLINE_STRICT</tt> is 0: the script will run
silently, and missing positional parameters, up to <em>nmin</em>, will
be substituted with the empty word. </li>
 <li> If <tt>EXECLINE_STRICT</tt> is 1 or unset: same, but the script will
print a warning message rather than run silently. </li>
 <li> If <tt>EXECLINE_STRICT</tt> is 2: the script will exit with an
error message. </li>
</ul>

<h2> Options for environment management </h2>

<p>
 Normally, execline scripts are <em>reentrant</em>: environment variables
potentially overwritten by <tt>execlineb</tt>, such as <tt>#</tt> or
<tt>0</tt>, are
<a href="el_pushenv.html">pushed</a>. This is the standard, safe
behaviour. Nevertheless, it is rather costly, and may be unneeded for
small scripts: for those cases, execline comes with two options
that bypass the environment management. Be warned that the purpose
of these options is <strong>optimization</strong>, and you should not
use them if you're not familiar with the way execlineb uses the
environment to store positional parameters. Alternatively, there's also
an integrated substitution mechanism that doesn't make use
of the environment at all.
</p>

<ul>
 <li> The <tt>-p</tt> option will bypass the
<a href="el_pushenv.html">push</a> phase: the current frame of positional
parameters will be <em>overwritten</em>. The script will <em>not</em> be
reentrant. </li>
 <li> The <tt>-P</tt> option will bypass positional parameter handling
<em>completely</em>: the environment will not be pushed, and positional
parameters will be ignored. <tt>execlineb -P -c "<em>script</em>"</tt> is
equivalent to, but more efficient than, <tt>execlineb -c
"emptyenv -P <em>script</em>"</tt>. You should use the <tt>-P</tt> option
only in standalone scripts that take no arguments, such as
<a href="//skarnet.org/software/s6/">s6</a>'s or 
<a href="http://smarden.org/runit/">runit</a>'s <em>run scripts</em>. </li>
 <li> The <tt>-S&nbsp;<em>nmin</em></tt> option <em>will</em> substitute the
positional parameters - up to at least <em>nmin</em> - but <em>will not</em>
push nor set environment
variables. <tt>execlineb -S3 -c "<em>script</em>"</tt> is equivalent to,
but more efficient than, <tt>execlineb -c "elgetpositionals -P3 emptyenv
-P <em>script</em>"</tt>. See
<a href="el_pushenv.html#integrated">the details</a>. </li>
 <li> The <tt>-s&nbsp;<em>nmin</em></tt> option behaves just like the
<tt>-S</tt> option, except that it defines <tt>$@</tt> as the rest of the
command line <strong>after</strong> <em>nmin</em> arguments have been
removed. </li>
</ul>

<h2> Current limitations </h2>

<p>
 <tt>execlineb</tt> builds and executes a unique
<em>argv</em> with the script: hence scripts are subject to OS-dependent
limitations such as the kernel buffer size for <em>argv</em> and <em>envp</em>
 - at least 64 kB on most systems. This means that <tt>execlineb</tt> cannot
execute arbitrarily large scripts. Be careful with deeply nested scripts too:
without the <tt>-p</tt>/<tt>-P</tt>/<tt>-S</tt>/<tt>-s</tt> option, each
execlineb invocation uses up some space in the environment.
</p>

</body>
</html>