1
2 ## compare_shells: bash dash mksh zsh ash
3 ## oils_failures_allowed: 0
4
5 #### echo keyword
6 echo done
7 ## stdout: done
8
9 #### if/else
10 if false; then
11 echo THEN
12 else
13 echo ELSE
14 fi
15 ## stdout: ELSE
16
17 #### Turn an array into an integer.
18 a=(1 2 3)
19 (( a = 42 ))
20 echo $a
21 ## stdout: 42
22 ## N-I dash/ash stdout-json: ""
23 ## N-I dash/ash status: 2
24
25
26 #### assign readonly -- one line
27 readonly x=1; x=2; echo hi
28 ## status: 1
29 ## OK dash/mksh/ash status: 2
30 ## STDOUT:
31 ## END
32
33 #### assign readonly -- multiple lines
34 readonly x=1
35 x=2
36 echo hi
37 ## status: 1
38 ## OK dash/mksh/ash status: 2
39 ## STDOUT:
40 ## END
41 ## BUG bash status: 0
42 ## BUG bash STDOUT:
43 hi
44 ## END
45
46 #### assign readonly -- multiple lines -- set -o posix
47 set -o posix
48 readonly x=1
49 x=2
50 echo hi
51 ## status: 1
52 ## OK dash/mksh/ash status: 2
53 ## STDOUT:
54 ## END
55
56 #### unset readonly -- one line
57 readonly x=1; unset x; echo hi
58 ## STDOUT:
59 hi
60 ## END
61 ## OK dash/ash status: 2
62 ## OK zsh status: 1
63 ## OK dash/ash stdout-json: ""
64 ## OK zsh stdout-json: ""
65
66 #### unset readonly -- multiple lines
67 readonly x=1
68 unset x
69 echo hi
70 ## OK dash/ash status: 2
71 ## OK zsh status: 1
72 ## OK dash/ash stdout-json: ""
73 ## OK zsh stdout-json: ""
74
75 #### First word like foo$x() and foo$[1+2] (regression)
76
77 # Problem: $x() func call broke this error message
78 foo$identity('z')
79
80 foo$[1+2]
81
82 echo DONE
83
84 ## status: 2
85 ## OK mksh/zsh status: 1
86 ## STDOUT:
87 ## END
88
89 #### Function names
90 foo$x() {
91 echo hi
92 }
93
94 foo $x() {
95 echo hi
96 }
97
98 ## status: 2
99 ## OK mksh/zsh status: 1
100 ## BUG zsh status: 0
101 ## STDOUT:
102 ## END
103
104
105 #### file with NUL byte
106 echo -e 'echo one \0 echo two' > tmp.sh
107 $SH tmp.sh
108 ## STDOUT:
109 one echo two
110 ## END
111 ## OK osh STDOUT:
112 one
113 ## END
114 ## N-I dash stdout-json: ""
115 ## N-I dash status: 127
116 ## OK bash stdout-json: ""
117 ## OK bash status: 126
118 ## OK zsh stdout-json: "one \u0000echo two\n"
119
120 #### fastlex: PS1 format string that's incomplete / with NUL byte
121 case $SH in bash) exit ;; esac
122
123 x=$'\\D{%H:%M' # leave off trailing }
124 echo x=${x@P}
125
126 ## STDOUT:
127 x=\D{%H:%M
128 ## END
129
130 # bash just ignores the missing }
131 ## BUG bash stdout-json: ""
132
133 # These shells don't understand @P
134
135 ## N-I dash/ash stdout-json: ""
136 ## N-I dash/ash status: 2
137
138 ## N-I zsh stdout-json: ""
139 ## N-I zsh status: 1
140
141
142 #### 'echo' and printf fail on writing to full disk
143
144 # Inspired by https://blog.sunfishcode.online/bugs-in-hello-world/
145
146 echo hi > /dev/full
147 echo status=$?
148
149 printf '%s\n' hi > /dev/full
150 echo status=$?
151
152 ## STDOUT:
153 status=1
154 status=1
155 ## END
156
157 #### other builtins fail on writing to full disk
158
159 type echo > /dev/full
160 echo status=$?
161
162 # other random builtin
163 ulimit -a > /dev/full
164 echo status=$?
165
166 ## STDOUT:
167 status=1
168 status=1
169 ## END
170
171 ## BUG mksh/zsh STDOUT:
172 status=0
173 status=0
174 ## END
175
176 #### subshell while running a script (regression)
177 # Ensures that spawning a subshell doesn't cause a seek on the file input stream
178 # representing the current script (issue #1233).
179 cat >tmp.sh <<'EOF'
180 echo start
181 (:)
182 echo end
183 EOF
184 $SH tmp.sh
185 ## STDOUT:
186 start
187 end
188 ## END
189
190 #### for loop (issue #1446)
191 case $SH in (dash|mksh|ash) exit ;; esac
192
193 for (( n=0; n<(3-(1)); n++ )) ; do echo $n; done
194
195 ## STDOUT:
196 0
197 1
198 ## END
199 ## N-I dash/mksh/ash STDOUT:
200 ## END
201
202
203
204 #### for loop 2 (issue #1446)
205 case $SH in (dash|mksh|ash) exit ;; esac
206
207
208 for (( n=0; n<(3- (1)); n++ )) ; do echo $n; done
209
210 ## STDOUT:
211 0
212 1
213 ## END
214 ## N-I dash/mksh/ash STDOUT:
215 ## END
216
217 #### autoconf word split (#1449)
218
219 mysed() {
220 for line in "$@"; do
221 echo "[$line]"
222 done
223 }
224
225 sedinputs="f1 f2"
226 sedscript='my sed command'
227
228 # Parsed and evaluated correctly: with word_part.EscapedLiteral \"
229
230 x=$(eval "mysed -n \"\$sedscript\" $sedinputs")
231 echo '--- $()'
232 echo "$x"
233
234 # With backticks, the \" gets lost somehow
235
236 x=`eval "mysed -n \"\$sedscript\" $sedinputs"`
237 echo '--- backticks'
238 echo "$x"
239
240
241 # Test it in a case statement
242
243 case `eval "mysed -n \"\$sedscript\" $sedinputs"` in
244 (*'[my sed command]'*)
245 echo 'NOT SPLIT'
246 ;;
247 esac
248
249 ## STDOUT:
250 --- $()
251 [-n]
252 [my sed command]
253 [f1]
254 [f2]
255 --- backticks
256 [-n]
257 [my sed command]
258 [f1]
259 [f2]
260 NOT SPLIT
261 ## END
262
263 #### autoconf arithmetic - relaxed eval_unsafe_arith (#1450)
264
265 as_fn_arith ()
266 {
267 as_val=$(( $* ))
268 }
269 as_fn_arith 1 + 1
270 echo $as_val
271
272 ## STDOUT:
273 2
274 ## END
275
276 #### command execution $(echo 42 | tee PWNED) not allowed
277
278 rm -f PWNED
279
280 x='a[$(echo 42 | tee PWNED)]=1'
281 echo $(( x ))
282
283 if test -f PWNED; then
284 cat PWNED
285 else
286 echo NOPE
287 fi
288
289 ## status: 1
290 ## OK dash/ash status: 2
291 ## stdout-json: ""
292 ## BUG bash/mksh/zsh status: 0
293 ## BUG bash/mksh/zsh STDOUT:
294 1
295 42
296 ## END
297
298 #### process sub <(echo 42 | tee PWNED) not allowed
299
300 rm -f PWNED
301
302 x='a[<(echo 42 | tee PWNED)]=1'
303 echo $(( x ))
304
305 if test -f PWNED; then
306 cat PWNED
307 else
308 echo NOPE
309 fi
310
311 ## status: 1
312 ## stdout-json: ""
313
314 ## OK dash/ash status: 2
315
316 # bash keeps going
317 ## BUG bash status: 0
318 ## BUG bash STDOUT:
319 NOPE
320 ## END
321
322
323 #### unset doesn't allow command execution
324
325 typeset -a a # for mksh
326 a=(42)
327 echo len=${#a[@]}
328
329 unset -v 'a[$(echo 0 | tee PWNED)]'
330 echo len=${#a[@]}
331
332 if test -f PWNED; then
333 echo PWNED
334 cat PWNED
335 else
336 echo NOPE
337 fi
338
339 ## status: 1
340 ## STDOUT:
341 len=1
342 ## END
343
344 ## N-I dash/ash status: 2
345 ## N-I dash/ash stdout-json: ""
346
347 ## BUG bash/mksh status: 0
348 ## BUG bash/mksh STDOUT:
349 len=1
350 len=0
351 PWNED
352 0
353 ## END
354
355 ## BUG zsh status: 0
356 ## BUG zsh STDOUT:
357 len=1
358 len=1
359 PWNED
360 0
361 ## END
362