1 #!/usr/bin/env bash
2
3 #### exec builtin
4 exec echo hi
5 ## stdout: hi
6
7 #### exec builtin with redirects
8 exec 1>&2
9 echo 'to stderr'
10 ## stdout-json: ""
11 ## stderr: to stderr
12
13 #### exec builtin with here doc
14 # This has in a separate file because both code and data can be read from
15 # stdin.
16 $SH spec/builtins-exec-here-doc-helper.sh
17 ## stdout-json: "x=one\ny=two\nDONE\n"
18
19 #### cd and $PWD
20 cd /
21 echo $PWD
22 ## stdout: /
23
24 #### $OLDPWD
25 cd /
26 cd $TMP
27 echo "old: $OLDPWD"
28 env | grep OLDPWD # It's EXPORTED too!
29 cd -
30 ## STDOUT:
31 old: /
32 OLDPWD=/
33 /
34 ## END
35 ## BUG mksh STDOUT:
36 old: /
37 /
38 ## END
39
40 #### pwd
41 cd /
42 pwd
43 ## STDOUT:
44 /
45 ## END
46
47 #### pwd after cd ..
48 dir=$TMP/dir-one/dir-two
49 mkdir -p $dir
50 cd $dir
51 echo $(basename $(pwd))
52 cd ..
53 echo $(basename $(pwd))
54 ## STDOUT:
55 dir-two
56 dir-one
57 ## END
58
59 #### pwd -P
60 tmp=$TMP/builtins-pwd-1
61 mkdir -p $tmp
62 mkdir -p $tmp/symtarg
63 ln -s $tmp/symtarg $tmp/symlink
64 cd $tmp/symlink
65 basename $(pwd -P)
66 cd $tmp
67 rmdir $tmp/symtarg
68 rm $tmp/symlink
69 ## stdout: symtarg
70
71 #### Test the current directory after 'cd ..' involving symlinks
72 dir=$TMP/symlinktest
73 mkdir -p $dir
74 cd $dir
75 mkdir -p a/b/c
76 mkdir -p a/b/d
77 ln -s -f a/b/c c > /dev/null
78 cd c
79 cd ..
80 # Expecting a c/ (since we are in symlinktest) but osh gives c d (thinks we are
81 # in b/)
82 ls
83 ## STDOUT:
84 a
85 c
86 ## END
87
88 #### cd with no arguments
89 HOME=$TMP/home
90 mkdir -p $HOME
91 cd
92 test $(pwd) = "$HOME" && echo OK
93 ## stdout: OK
94
95 #### cd to nonexistent dir
96 cd /nonexistent/dir
97 echo status=$?
98 ## stdout: status=1
99 ## OK dash/mksh stdout: status=2
100
101 #### cd away from dir that was deleted
102 dir=$TMP/cd-nonexistent
103 mkdir -p $dir
104 cd $dir
105 rmdir $dir
106 cd $TMP
107 echo $(basename $OLDPWD)
108 echo status=$?
109 ## STDOUT:
110 cd-nonexistent
111 status=0
112 ## END
113
114 #### cd permits double bare dash
115 cd -- /
116 echo $PWD
117 ## stdout: /
118
119 #### cd to symlink with -L and -P
120 targ=$TMP/cd-symtarget
121 lnk=$TMP/cd-symlink
122 mkdir -p $targ
123 ln -s $targ $lnk
124
125 # -L behavior is the default
126 cd $lnk
127 test $PWD = "$TMP/cd-symlink" && echo OK
128
129 cd -L $lnk
130 test $PWD = "$TMP/cd-symlink" && echo OK
131
132 cd -P $lnk
133 test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD
134 ## STDOUT:
135 OK
136 OK
137 OK
138 ## END
139
140 #### cd to relative path with -L and -P
141 die() { echo "$@"; exit 1; }
142
143 targ=$TMP/cd-symtarget/subdir
144 lnk=$TMP/cd-symlink
145 mkdir -p $targ
146 ln -s $targ $lnk
147
148 # -L behavior is the default
149 cd $lnk/subdir
150 test $PWD = "$TMP/cd-symlink/subdir" || die "failed"
151 cd ..
152 test $PWD = "$TMP/cd-symlink" && echo OK
153
154 cd $lnk/subdir
155 test $PWD = "$TMP/cd-symlink/subdir" || die "failed"
156 cd -L ..
157 test $PWD = "$TMP/cd-symlink" && echo OK
158
159 cd $lnk/subdir
160 test $PWD = "$TMP/cd-symlink/subdir" || die "failed"
161 cd -P ..
162 test $PWD = "$TMP/cd-symtarget" && echo OK || echo $PWD
163 ## STDOUT:
164 OK
165 OK
166 OK
167 ## END
168
169 #### Exit out of function
170 f() { exit 3; }
171 f
172 exit 4
173 ## status: 3
174
175 #### Exit builtin with invalid arg
176 exit invalid
177 # Rationale: runtime errors are 1
178 ## status: 1
179 ## OK dash/bash status: 2
180
181 #### Exit builtin with too many args
182 # This is a parse error in OSH.
183 exit 7 8 9
184 echo status=$?
185 ## status: 2
186 ## stdout-json: ""
187 ## BUG bash status: 0
188 ## BUG bash stdout: status=1
189 ## BUG dash status: 7
190 ## BUG dash stdout-json: ""
191 ## OK mksh status: 1
192 ## OK mksh stdout-json: ""
193
194 #### time block
195 # bash and mksh work; dash does't.
196 # TODO: osh needs to implement BraceGroup redirect properly.
197 err=_tmp/time-$(basename $SH).txt
198 {
199 time {
200 sleep 0.01
201 sleep 0.02
202 }
203 } 2> $err
204 cat $err | grep --only-matching real
205 # Just check that we found 'real'.
206 # This is fiddly:
207 # | sed -n -E -e 's/.*(0m0\.03).*/\1/'
208 #
209 ## status: 0
210 ## stdout: real
211 ## BUG dash status: 2
212 ## BUG dash stdout-json: ""
213
214 #### time pipeline
215 time echo hi | wc -c
216 ## stdout: 3
217 ## status: 0
218
219 #### shift
220 set -- 1 2 3 4
221 shift
222 echo "$@"
223 shift 2
224 echo "$@"
225 ## stdout-json: "2 3 4\n4\n"
226 ## status: 0
227
228 #### Shifting too far
229 set -- 1
230 shift 2
231 ## status: 1
232 ## OK dash status: 2
233
234 #### Invalid shift argument
235 shift ZZZ
236 ## status: 1
237 ## OK dash status: 2
238 ## BUG mksh status: 0
239
240 #### get umask
241 umask | grep '[0-9]\+' # check for digits
242 ## status: 0
243
244 #### set umask in octal
245 rm -f $TMP/umask-one $TMP/umask-two
246 umask 0002
247 echo one > $TMP/umask-one
248 umask 0022
249 echo two > $TMP/umask-two
250 stat -c '%a' $TMP/umask-one $TMP/umask-two
251 ## status: 0
252 ## stdout-json: "664\n644\n"
253 ## stderr-json: ""
254
255 #### set umask symbolically
256 umask 0002 # begin in a known state for the test
257 rm $TMP/umask-one $TMP/umask-two
258 echo one > $TMP/umask-one
259 umask g-w,o-w
260 echo two > $TMP/umask-two
261 stat -c '%a' $TMP/umask-one $TMP/umask-two
262 ## status: 0
263 ## STDOUT:
264 664
265 644
266 ## END
267 ## stderr-json: ""