1 ## compare_shells: dash bash mksh zsh
2 ## oils_failures_allowed: 1
3 ## oils_cpp_failures_allowed: 2
4 # case #24 with ulimit -f 1 is different under C++ for some reason - could be due to the python2
5 # intepreter and SIGXFSZ
6
7 #### exec builtin
8 exec echo hi
9 ## stdout: hi
10
11 #### exec builtin with redirects
12 exec 1>&2
13 echo 'to stderr'
14 ## stdout-json: ""
15 ## stderr: to stderr
16
17 #### exec builtin with here doc
18 # This has in a separate file because both code and data can be read from
19 # stdin.
20 $SH $REPO_ROOT/spec/bin/builtins-exec-here-doc-helper.sh
21 ## STDOUT:
22 x=one
23 y=two
24 DONE
25 ## END
26
27 #### exec builtin accepts --
28 exec -- echo hi
29 ## STDOUT:
30 hi
31 ## END
32 ## BUG dash status: 127
33 ## BUG dash stdout-json: ""
34
35 #### exec -- 2>&1
36 exec -- 3>&1
37 echo stdout 1>&3
38 ## STDOUT:
39 stdout
40 ## END
41 ## BUG dash status: 127
42 ## BUG dash stdout-json: ""
43 ## BUG mksh status: -11
44 ## BUG mksh stdout-json: ""
45
46 #### exec -a sets argv[0]
47 exec -a FOOPROC sh -c 'echo $0'
48 ## STDOUT:
49 FOOPROC
50 ## END
51 ## N-I dash status: 127
52 ## N-I dash stdout-json: ""
53
54 #### Exit out of function
55 f() { exit 3; }
56 f
57 exit 4
58 ## status: 3
59
60 #### Exit builtin with invalid arg
61 exit invalid
62 # Rationale: runtime errors are 1
63 ## status: 1
64 ## OK dash/bash status: 2
65 ## BUG zsh status: 0
66
67 #### Exit builtin with too many args
68 # This is a parse error in OSH.
69 exit 7 8 9
70 echo status=$?
71 ## status: 2
72 ## stdout-json: ""
73 ## BUG bash/zsh status: 0
74 ## BUG bash/zsh stdout: status=1
75 ## BUG dash status: 7
76 ## BUG dash stdout-json: ""
77 ## OK mksh status: 1
78 ## OK mksh stdout-json: ""
79
80 #### time with brace group argument
81
82 err=time-$(basename $SH).txt
83 {
84 time {
85 sleep 0.01
86 sleep 0.02
87 }
88 } 2> $err
89
90 grep --only-matching user $err
91 echo result=$?
92
93 # Regression: check fractional seconds
94 gawk '
95 BEGIN { ok = 0 }
96 match( $0, /\.([0-9]+)/, m) {
97 if (m[1] > 0) { # check fractional seconds
98 ok = 1
99 }
100 }
101 END { if (ok) { print "non-zero" } }
102 ' $err
103
104 ## status: 0
105 ## STDOUT:
106 user
107 result=0
108 non-zero
109 ## END
110
111 # time doesn't accept a block?
112 ## BUG zsh STDOUT:
113 result=1
114 ## END
115
116 # dash doesn't have time keyword
117 ## N-I dash status: 2
118 ## N-I dash stdout-json: ""
119
120
121
122 #### ulimit with no flags is like -f
123
124 ulimit > no-flags.txt
125 echo status=$?
126
127 ulimit -f > f.txt
128 echo status=$?
129
130 diff -u no-flags.txt f.txt
131 echo diff=$?
132
133 # Print everything
134 # ulimit -a
135
136 ## STDOUT:
137 status=0
138 status=0
139 diff=0
140 ## END
141
142
143 #### ulimit too many args
144
145 ulimit 1 2
146 if test $? -ne 0; then
147 echo pass
148 else
149 echo fail
150 fi
151
152 #ulimit -f
153
154 ## STDOUT:
155 pass
156 ## END
157
158 ## BUG bash/zsh STDOUT:
159 fail
160 ## END
161
162
163 #### ulimit negative flag
164
165 ulimit -f
166
167 # interpreted as a flag
168 ulimit -f -42
169 if test $? -ne 0; then
170 echo pass
171 else
172 echo fail
173 fi
174
175 ## STDOUT:
176 unlimited
177 pass
178 ## END
179
180 #### ulimit negative arg
181
182 ulimit -f
183
184 # an arg
185 ulimit -f -- -42
186 if test $? -ne 0; then
187 echo pass
188 else
189 echo fail
190 fi
191
192 ## STDOUT:
193 unlimited
194 pass
195 ## END
196
197 ## BUG mksh STDOUT:
198 unlimited
199 fail
200 ## END
201
202
203 #### ulimit -a doesn't take arg
204 case $SH in bash) exit ;; esac
205
206 ulimit -a 42
207 if test $? -ne 0; then
208 echo 'failure that was expected'
209 fi
210
211 ## STDOUT:
212 failure that was expected
213 ## END
214 ## BUG bash STDOUT:
215 ## END
216
217
218 #### ulimit doesn't accept multiple flags - reduce confusion between shells
219
220 # - bash, zsh, busybox ash accept multiple "commands", which requires custom
221 # flag parsing, like
222
223 # ulimit -f 999 -n
224 # ulimit -f 999 -n 888
225 #
226 # - dash and mksh accept a single ARG
227 #
228 # we want to make it clear we're like the latter
229
230 # can't print all and -f
231 ulimit -f -a >/dev/null
232 echo status=$?
233
234 ulimit -f -n >/dev/null
235 echo status=$?
236
237 ulimit -f -n 999 >/dev/null
238 echo status=$?
239
240 ## STDOUT:
241 status=2
242 status=2
243 status=2
244 ## END
245
246 ## BUG dash/bash/mksh STDOUT:
247 status=0
248 status=0
249 status=0
250 ## END
251
252 # zsh is better - it checks that -a and -f are exclusive
253
254 ## BUG zsh STDOUT:
255 status=1
256 status=0
257 status=0
258 ## END
259
260
261 #### YSH readability: ulimit --all the same as ulimit -a
262
263 case $SH in bash|dash|mksh|zsh) exit ;; esac
264
265 ulimit -a > short.txt
266 ulimit --all > long.txt
267
268 wc -l short.txt long.txt
269
270 diff -u short.txt long.txt
271 echo status=$?
272
273 ## STDOUT:
274 8 short.txt
275 8 long.txt
276 16 total
277 status=0
278 ## END
279
280 ## N-I bash/dash/mksh/zsh STDOUT:
281 ## END
282
283 #### ulimit accepts 'unlimited'
284
285 for arg in zz unlimited; do
286 echo " arg $arg"
287 ulimit -f
288 echo status=$?
289 ulimit -f $arg
290 if test $? -ne 0; then
291 echo 'FAILED'
292 fi
293 echo
294 done
295 ## STDOUT:
296 arg zz
297 unlimited
298 status=0
299 FAILED
300
301 arg unlimited
302 unlimited
303 status=0
304
305 ## END
306
307
308 #### ulimit of 2**32, 2**31 (int overflow)
309
310 echo -n 'one '; ulimit -f
311
312
313 ulimit -f $(( 1 << 32 ))
314
315 echo -n 'two '; ulimit -f
316
317
318 # mksh fails because it overflows signed int, turning into negative number
319 ulimit -f $(( 1 << 31 ))
320
321 echo -n 'three '; ulimit -f
322
323 ## STDOUT:
324 one unlimited
325 two 4294967296
326 three 2147483648
327 ## END
328 ## BUG mksh STDOUT:
329 one unlimited
330 two 1
331 three 1
332 ## END
333
334
335 #### ulimit that is 64 bits
336
337 # no 64-bit integers
338 case $SH in mksh) exit ;; esac
339
340 echo -n 'before '; ulimit -f
341
342 # 1 << 63 overflows signed int
343
344 # 512 is 1 << 9, so make it 62-9 = 53 bits
345
346 lim=$(( 1 << 53 ))
347 #echo $lim
348
349 # bash says this is out of range
350 ulimit -f $lim
351
352 echo -n 'after '; ulimit -f
353
354 ## STDOUT:
355 before unlimited
356 after 9007199254740992
357 ## END
358
359 ## BUG mksh STDOUT:
360 ## END
361
362
363 #### arg that would overflow 64 bits is detected
364
365 # no 64-bit integers
366 case $SH in mksh) exit ;; esac
367
368 echo -n 'before '; ulimit -f
369
370 # 1 << 63 overflows signed int
371
372 lim=$(( (1 << 62) + 1 ))
373 #echo lim=$lim
374
375 # bash detects that this is out of range
376 # so does osh-cpp, but not osh-cpython
377
378 ulimit -f $lim
379 echo -n 'after '; ulimit -f
380
381 ## STDOUT:
382 before unlimited
383 after unlimited
384 ## END
385
386 ## BUG dash/zsh STDOUT:
387 before unlimited
388 after 1
389 ## END
390
391 ## BUG mksh STDOUT:
392 ## END
393
394
395 #### ulimit -f 1 prevents files larger 512 bytes
396 trap - XFSZ # don't handle this
397
398 rm -f err.txt
399 touch err.txt
400
401 bytes() {
402 local n=$1
403 local st=0
404 for i in $(seq $n); do
405 echo -n x
406 st=$?
407 if test $st -ne 0; then
408 echo "ERROR: echo failed with status $st" >> err.txt
409 fi
410 done
411 }
412
413 ulimit -f 1
414
415 bytes 512 > ok.txt
416 echo 512 status=$?
417
418 bytes 513 > too-big.txt
419 echo 513 status=$?
420 echo
421
422 wc --bytes ok.txt too-big.txt
423 echo
424
425 cat err.txt
426
427 ## status: -25
428 ## STDOUT:
429 512 status=0
430 ## END
431
432 ## OK disabledosh status: 0
433 ## OK disabledosh STDOUT:
434 512 status=0
435 513 status=0
436
437 512 ok.txt
438 512 too-big.txt
439 1024 total
440
441 ERROR: echo failed with status 1
442 ## END
443
444 ## BUG bash status: 0
445 ## BUG bash STDOUT:
446 512 status=0
447 513 status=0
448
449 512 ok.txt
450 513 too-big.txt
451 1025 total
452
453 ## END
454
455 #### write big file with ulimit
456
457 # I think this will test write() errors, rather than the final flush() error
458 # (which is currently skipped by C++
459
460 { echo 'ulimit -f 1'
461 # More than 8 KiB may cause a flush()
462 python2 -c 'print("echo " + "X"*9000 + " >out.txt")'
463 echo 'echo inner=$?'
464 } > big.sh
465
466 $SH big.sh
467 echo outer=$?
468
469 ## STDOUT:
470 outer=153
471 ## END
472
473 # not sure why this is different
474 ## OK osh STDOUT:
475 inner=1
476 outer=0
477 ## END
478
479
480 #### ulimit -S for soft limit (default), -H for hard limit
481 case $SH in dash|zsh) exit ;; esac
482
483 # Note: ulimit -n -S 1111 is OK in osh/dash/mksh, but not bash/zsh
484 # Mus be ulimit -S -n 1111
485
486 show_state() {
487 local msg=$1
488 echo "$msg"
489 echo -n ' '; ulimit -S -t
490 echo -n ' '; ulimit -H -t
491 echo
492 }
493
494 show_state 'init'
495
496 ulimit -S -t 123456
497 show_state '-S'
498
499 ulimit -H -t 123457
500 show_state '-H'
501
502 ulimit -t 123455
503 show_state 'no flag'
504
505 echo 'GET'
506
507 ulimit -S -t 123454
508 echo -n ' '; ulimit -t
509 echo -n ' '; ulimit -S -t
510 echo -n ' '; ulimit -H -t
511
512 ## STDOUT:
513 init
514 unlimited
515 unlimited
516
517 -S
518 123456
519 unlimited
520
521 -H
522 123456
523 123457
524
525 no flag
526 123455
527 123455
528
529 GET
530 123454
531 123454
532 123455
533 ## END
534
535 ## BUG dash/zsh STDOUT:
536 ## END
537
538 #### Changing resource limit is denied
539
540 # Not sure why these don't work
541 case $SH in dash|mksh) exit ;; esac
542
543
544 flag=-t
545
546 ulimit -S -H $flag 100
547 echo both=$?
548
549 ulimit -S $flag 90
550 echo soft=$?
551
552 ulimit -S $flag 95
553 echo soft=$?
554
555 ulimit -S $flag 105
556 if test $? -ne 0; then
557 echo soft OK
558 else
559 echo soft fail
560 fi
561
562 ulimit -H $flag 200
563 if test $? -ne 0; then
564 echo hard OK
565 else
566 echo hard fail
567 fi
568
569 ## STDOUT:
570 both=0
571 soft=0
572 soft=0
573 soft OK
574 hard OK
575 ## END
576
577 ## BUG dash/mksh STDOUT:
578 ## END
579
580 #### ulimit -n limits file descriptors
581
582 # OSH bug
583 # https://oilshell.zulipchat.com/#narrow/channel/502349-osh/topic/alpine.20build.20failures.20-.20make.20-.20ulimit.20-n.2064/with/519691301
584
585 $SH -c 'ulimit -n 64; echo hi >out'
586 echo status=$?
587
588 $SH -c 'ulimit -n 0; echo hi >out'
589 echo status=$?
590
591 ## STDOUT:
592 status=0
593 status=1
594 ## END
595
596 ## OK dash STDOUT:
597 status=0
598 status=2
599 ## END