1 ## compare_shells: dash bash mksh zsh
2 ## oils_failures_allowed: 2
3 ## oils_cpp_failures_allowed: 3
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 #### get umask
122 umask | grep '[0-9]\+' # check for digits
123 ## status: 0
124
125 #### set umask in octal
126 rm -f $TMP/umask-one $TMP/umask-two
127 umask 0002
128 echo one > $TMP/umask-one
129 umask 0022
130 echo two > $TMP/umask-two
131 stat -c '%a' $TMP/umask-one $TMP/umask-two
132 ## status: 0
133 ## STDOUT:
134 664
135 644
136 ## END
137 ## stderr-json: ""
138
139 #### set umask symbolically
140 umask 0002 # begin in a known state for the test
141 rm -f $TMP/umask-one $TMP/umask-two
142 echo one > $TMP/umask-one
143 umask g-w,o-w
144 echo two > $TMP/umask-two
145 stat -c '%a' $TMP/umask-one $TMP/umask-two
146 ## status: 0
147 ## STDOUT:
148 664
149 644
150 ## END
151 ## stderr-json: ""
152
153 #### ulimit with no flags is like -f
154
155 ulimit > no-flags.txt
156 echo status=$?
157
158 ulimit -f > f.txt
159 echo status=$?
160
161 diff -u no-flags.txt f.txt
162 echo diff=$?
163
164 # Print everything
165 # ulimit -a
166
167 ## STDOUT:
168 status=0
169 status=0
170 diff=0
171 ## END
172
173
174 #### ulimit too many args
175
176 ulimit 1 2
177 if test $? -ne 0; then
178 echo pass
179 else
180 echo fail
181 fi
182
183 #ulimit -f
184
185 ## STDOUT:
186 pass
187 ## END
188
189 ## BUG bash/zsh STDOUT:
190 fail
191 ## END
192
193
194 #### ulimit negative flag
195
196 ulimit -f
197
198 # interpreted as a flag
199 ulimit -f -42
200 if test $? -ne 0; then
201 echo pass
202 else
203 echo fail
204 fi
205
206 ## STDOUT:
207 unlimited
208 pass
209 ## END
210
211 #### ulimit negative arg
212
213 ulimit -f
214
215 # an arg
216 ulimit -f -- -42
217 if test $? -ne 0; then
218 echo pass
219 else
220 echo fail
221 fi
222
223 ## STDOUT:
224 unlimited
225 pass
226 ## END
227
228 ## BUG mksh STDOUT:
229 unlimited
230 fail
231 ## END
232
233
234 #### ulimit -a doesn't take arg
235 case $SH in bash) exit ;; esac
236
237 ulimit -a 42
238 if test $? -ne 0; then
239 echo 'failure that was expected'
240 fi
241
242 ## STDOUT:
243 failure that was expected
244 ## END
245 ## BUG bash STDOUT:
246 ## END
247
248
249 #### ulimit doesn't accept multiple flags - reduce confusion between shells
250
251 # - bash, zsh, busybox ash accept multiple "commands", which requires custom
252 # flag parsing, like
253
254 # ulimit -f 999 -n
255 # ulimit -f 999 -n 888
256 #
257 # - dash and mksh accept a single ARG
258 #
259 # we want to make it clear we're like the latter
260
261 # can't print all and -f
262 ulimit -f -a >/dev/null
263 echo status=$?
264
265 ulimit -f -n >/dev/null
266 echo status=$?
267
268 ulimit -f -n 999 >/dev/null
269 echo status=$?
270
271 ## STDOUT:
272 status=2
273 status=2
274 status=2
275 ## END
276
277 ## BUG dash/bash/mksh STDOUT:
278 status=0
279 status=0
280 status=0
281 ## END
282
283 # zsh is better - it checks that -a and -f are exclusive
284
285 ## BUG zsh STDOUT:
286 status=1
287 status=0
288 status=0
289 ## END
290
291
292 #### YSH readability: ulimit --all the same as ulimit -a
293
294 case $SH in bash|dash|mksh|zsh) exit ;; esac
295
296 ulimit -a > short.txt
297 ulimit --all > long.txt
298
299 wc -l short.txt long.txt
300
301 diff -u short.txt long.txt
302 echo status=$?
303
304 ## STDOUT:
305 8 short.txt
306 8 long.txt
307 16 total
308 status=0
309 ## END
310
311 ## N-I bash/dash/mksh/zsh STDOUT:
312 ## END
313
314 #### ulimit accepts 'unlimited'
315
316 for arg in zz unlimited; do
317 echo " arg $arg"
318 ulimit -f
319 echo status=$?
320 ulimit -f $arg
321 if test $? -ne 0; then
322 echo 'FAILED'
323 fi
324 echo
325 done
326 ## STDOUT:
327 arg zz
328 unlimited
329 status=0
330 FAILED
331
332 arg unlimited
333 unlimited
334 status=0
335
336 ## END
337
338
339 #### ulimit of 2**32, 2**31 (int overflow)
340
341 echo -n 'one '; ulimit -f
342
343
344 ulimit -f $(( 1 << 32 ))
345
346 echo -n 'two '; ulimit -f
347
348
349 # mksh fails because it overflows signed int, turning into negative number
350 ulimit -f $(( 1 << 31 ))
351
352 echo -n 'three '; ulimit -f
353
354 ## STDOUT:
355 one unlimited
356 two 4294967296
357 three 2147483648
358 ## END
359 ## BUG mksh STDOUT:
360 one unlimited
361 two 1
362 three 1
363 ## END
364
365
366 #### ulimit that is 64 bits
367
368 # no 64-bit integers
369 case $SH in mksh) exit ;; esac
370
371 echo -n 'before '; ulimit -f
372
373 # 1 << 63 overflows signed int
374
375 # 512 is 1 << 9, so make it 62-9 = 53 bits
376
377 lim=$(( 1 << 53 ))
378 #echo $lim
379
380 # bash says this is out of range
381 ulimit -f $lim
382
383 echo -n 'after '; ulimit -f
384
385 ## STDOUT:
386 before unlimited
387 after 9007199254740992
388 ## END
389
390 ## BUG mksh STDOUT:
391 ## END
392
393
394 #### arg that would overflow 64 bits is detected
395
396 # no 64-bit integers
397 case $SH in mksh) exit ;; esac
398
399 echo -n 'before '; ulimit -f
400
401 # 1 << 63 overflows signed int
402
403 lim=$(( (1 << 62) + 1 ))
404 #echo lim=$lim
405
406 # bash detects that this is out of range
407 # so does osh-cpp, but not osh-cpython
408
409 ulimit -f $lim
410 echo -n 'after '; ulimit -f
411
412 ## STDOUT:
413 before unlimited
414 after unlimited
415 ## END
416
417 ## BUG dash/zsh STDOUT:
418 before unlimited
419 after 1
420 ## END
421
422 ## BUG mksh STDOUT:
423 ## END
424
425
426 #### ulimit -f 1 prevents files larger 512 bytes
427 trap - XFSZ # don't handle this
428
429 rm -f err.txt
430 touch err.txt
431
432 bytes() {
433 local n=$1
434 local st=0
435 for i in $(seq $n); do
436 echo -n x
437 st=$?
438 if test $st -ne 0; then
439 echo "ERROR: echo failed with status $st" >> err.txt
440 fi
441 done
442 }
443
444 ulimit -f 1
445
446 bytes 512 > ok.txt
447 echo 512 status=$?
448
449 bytes 513 > too-big.txt
450 echo 513 status=$?
451 echo
452
453 wc --bytes ok.txt too-big.txt
454 echo
455
456 cat err.txt
457
458 ## status: -25
459 ## STDOUT:
460 512 status=0
461 ## END
462
463 ## OK disabledosh status: 0
464 ## OK disabledosh STDOUT:
465 512 status=0
466 513 status=0
467
468 512 ok.txt
469 512 too-big.txt
470 1024 total
471
472 ERROR: echo failed with status 1
473 ## END
474
475 ## BUG bash status: 0
476 ## BUG bash STDOUT:
477 512 status=0
478 513 status=0
479
480 512 ok.txt
481 513 too-big.txt
482 1025 total
483
484 ## END
485
486 #### write big file with ulimit
487
488 # I think this will test write() errors, rather than the final flush() error
489 # (which is currently skipped by C++
490
491 { echo 'ulimit -f 1'
492 # More than 8 KiB may cause a flush()
493 python2 -c 'print("echo " + "X"*9000 + " >out.txt")'
494 echo 'echo inner=$?'
495 } > big.sh
496
497 $SH big.sh
498 echo outer=$?
499
500 ## STDOUT:
501 outer=153
502 ## END
503
504 # not sure why this is different
505 ## OK osh STDOUT:
506 inner=1
507 outer=0
508 ## END
509
510
511 #### ulimit -S for soft limit (default), -H for hard limit
512 case $SH in dash|zsh) exit ;; esac
513
514 # Note: ulimit -n -S 1111 is OK in osh/dash/mksh, but not bash/zsh
515 # Mus be ulimit -S -n 1111
516
517 show_state() {
518 local msg=$1
519 echo "$msg"
520 echo -n ' '; ulimit -S -t
521 echo -n ' '; ulimit -H -t
522 echo
523 }
524
525 show_state 'init'
526
527 ulimit -S -t 123456
528 show_state '-S'
529
530 ulimit -H -t 123457
531 show_state '-H'
532
533 ulimit -t 123455
534 show_state 'no flag'
535
536 echo 'GET'
537
538 ulimit -S -t 123454
539 echo -n ' '; ulimit -t
540 echo -n ' '; ulimit -S -t
541 echo -n ' '; ulimit -H -t
542
543 ## STDOUT:
544 init
545 unlimited
546 unlimited
547
548 -S
549 123456
550 unlimited
551
552 -H
553 123456
554 123457
555
556 no flag
557 123455
558 123455
559
560 GET
561 123454
562 123454
563 123455
564 ## END
565
566 ## BUG dash/zsh STDOUT:
567 ## END
568
569 #### Changing resource limit is denied
570
571 # Not sure why these don't work
572 case $SH in dash|mksh) exit ;; esac
573
574
575 flag=-t
576
577 ulimit -S -H $flag 100
578 echo both=$?
579
580 ulimit -S $flag 90
581 echo soft=$?
582
583 ulimit -S $flag 95
584 echo soft=$?
585
586 ulimit -S $flag 105
587 if test $? -ne 0; then
588 echo soft OK
589 else
590 echo soft fail
591 fi
592
593 ulimit -H $flag 200
594 if test $? -ne 0; then
595 echo hard OK
596 else
597 echo hard fail
598 fi
599
600 ## STDOUT:
601 both=0
602 soft=0
603 soft=0
604 soft OK
605 hard OK
606 ## END
607
608 ## BUG dash/mksh STDOUT:
609 ## END
610
611 #### ulimit -n limits file descriptors
612
613 # OSH bug
614 # https://oilshell.zulipchat.com/#narrow/channel/502349-osh/topic/alpine.20build.20failures.20-.20make.20-.20ulimit.20-n.2064/with/519691301
615
616 $SH -c 'ulimit -n 64; echo hi >out'
617 echo status=$?
618
619 $SH -c 'ulimit -n 0; echo hi >out'
620 echo status=$?
621
622 ## STDOUT:
623 status=0
624 status=1
625 ## END
626
627 ## OK dash STDOUT:
628 status=0
629 status=2
630 ## END