1
2 ## compare_shells: bash dash mksh zsh ash
3 ## oils_failures_allowed: 1
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 to disk full
143
144 # Inspired by https://blog.sunfishcode.online/bugs-in-hello-world/
145
146 echo hi > /dev/full
147 echo status=$?
148 printf '%s\n' hi > /dev/full
149 echo status=$?
150
151 ## STDOUT:
152 status=1
153 status=1
154 ## END
155
156 #### subshell while running a script (regression)
157 # Ensures that spawning a subshell doesn't cause a seek on the file input stream
158 # representing the current script (issue #1233).
159 cat >tmp.sh <<'EOF'
160 echo start
161 (:)
162 echo end
163 EOF
164 $SH tmp.sh
165 ## STDOUT:
166 start
167 end
168 ## END
169
170 #### for loop (issue #1446)
171 case $SH in (dash|mksh|ash) exit ;; esac
172
173 for (( n=0; n<(3-(1)); n++ )) ; do echo $n; done
174
175 ## STDOUT:
176 0
177 1
178 ## END
179 ## N-I dash/mksh/ash STDOUT:
180 ## END
181
182
183
184 #### for loop 2 (issue #1446)
185 case $SH in (dash|mksh|ash) exit ;; esac
186
187
188 for (( n=0; n<(3- (1)); n++ )) ; do echo $n; done
189
190 ## STDOUT:
191 0
192 1
193 ## END
194 ## N-I dash/mksh/ash STDOUT:
195 ## END
196
197 #### autoconf word split (#1449)
198
199 mysed() {
200 for line in "$@"; do
201 echo "[$line]"
202 done
203 }
204
205 sedinputs="f1 f2"
206 sedscript='my sed command'
207
208 # Parsed and evaluated correctly: with word_part.EscapedLiteral \"
209
210 x=$(eval "mysed -n \"\$sedscript\" $sedinputs")
211 echo '--- $()'
212 echo "$x"
213
214 # With backticks, the \" gets lost somehow
215
216 x=`eval "mysed -n \"\$sedscript\" $sedinputs"`
217 echo '--- backticks'
218 echo "$x"
219
220
221 # Test it in a case statement
222
223 case `eval "mysed -n \"\$sedscript\" $sedinputs"` in
224 (*'[my sed command]'*)
225 echo 'NOT SPLIT'
226 ;;
227 esac
228
229 ## STDOUT:
230 --- $()
231 [-n]
232 [my sed command]
233 [f1]
234 [f2]
235 --- backticks
236 [-n]
237 [my sed command]
238 [f1]
239 [f2]
240 NOT SPLIT
241 ## END
242
243 #### autoconf arithmetic - relaxed eval_unsafe_arith (#1450)
244
245 as_fn_arith ()
246 {
247 as_val=$(( $* ))
248 }
249 as_fn_arith 1 + 1
250 echo $as_val
251
252 ## STDOUT:
253 2
254 ## END
255
256 #### command execution $(echo 42 | tee PWNED) not allowed
257
258 rm -f PWNED
259
260 x='a[$(echo 42 | tee PWNED)]=1'
261 echo $(( x ))
262
263 if test -f PWNED; then
264 cat PWNED
265 else
266 echo NOPE
267 fi
268
269 ## status: 1
270 ## OK dash/ash status: 2
271 ## stdout-json: ""
272 ## BUG bash/mksh/zsh status: 0
273 ## BUG bash/mksh/zsh STDOUT:
274 1
275 42
276 ## END
277
278 #### process sub <(echo 42 | tee PWNED) not allowed
279
280 rm -f PWNED
281
282 x='a[<(echo 42 | tee PWNED)]=1'
283 echo $(( x ))
284
285 if test -f PWNED; then
286 cat PWNED
287 else
288 echo NOPE
289 fi
290
291 ## status: 1
292 ## stdout-json: ""
293
294 ## OK dash/ash status: 2
295
296 # bash keeps going
297 ## BUG bash status: 0
298 ## BUG bash STDOUT:
299 NOPE
300 ## END
301
302
303 #### unset doesn't allow command execution
304
305 typeset -a a # for mksh
306 a=(42)
307 echo len=${#a[@]}
308
309 unset -v 'a[$(echo 0 | tee PWNED)]'
310 echo len=${#a[@]}
311
312 if test -f PWNED; then
313 echo PWNED
314 cat PWNED
315 else
316 echo NOPE
317 fi
318
319 ## status: 1
320 ## STDOUT:
321 len=1
322 ## END
323
324 ## N-I dash/ash status: 2
325 ## N-I dash/ash stdout-json: ""
326
327 ## BUG bash/mksh status: 0
328 ## BUG bash/mksh STDOUT:
329 len=1
330 len=0
331 PWNED
332 0
333 ## END
334
335 ## BUG zsh status: 0
336 ## BUG zsh STDOUT:
337 len=1
338 len=1
339 PWNED
340 0
341 ## END
342