From deb63bfb0b6f1eb3b14b2a2adb33a6f90d11095a Mon Sep 17 00:00:00 2001
From: Apple <opensource@apple.com>
Date: Fri, 28 Apr 2017 04:11:12 +0000
Subject: [PATCH] shell_cmds-203.tar.gz

---
 .gitignore                           |    1 +
 lastcomm/lastcomm.c                  |    3 +-
 locate/locate/locate.rc              |    2 +-
 locate/locate/updatedb.sh            |    8 +-
 printf/printf.1                      |    2 +-
 printf/printf.c                      |    2 +-
 printf/tests/Makefile                |   22 +
 printf/tests/Makefile.depend         |   11 +
 printf/tests/legacy_test.sh          |    6 +
 printf/tests/regress.b.out           |    1 +
 printf/tests/regress.d.out           |    1 +
 printf/tests/regress.f.out           |    1 +
 printf/tests/regress.l1.out          |    1 +
 printf/tests/regress.l2.out          |    1 +
 printf/tests/regress.m1.out          |  Bin 0 -> 7 bytes
 printf/tests/regress.m2.out          |    2 +
 printf/tests/regress.m3.out          |    4 +
 printf/tests/regress.m4.out          |    1 +
 printf/tests/regress.m5.out          |    1 +
 printf/tests/regress.missingpos1.out |    1 +
 printf/tests/regress.s.out           |    1 +
 printf/tests/regress.sh              |   33 +
 printf/tests/regress.zero.out        |    1 +
 sh/Makefile                          |   16 +-
 sh/Makefile.depend                   |   96 +--
 sh/TOUR                              |    2 +-
 sh/alias.c                           |    8 +-
 sh/alias.h                           |    2 +-
 sh/arith.h                           |    2 +-
 sh/arith_yacc.c                      |    2 +-
 sh/arith_yacc.h                      |    2 +-
 sh/arith_yylex.c                     |    2 +-
 sh/bltin/bltin.h                     |    2 +-
 sh/bltin/echo.c                      |    2 +-
 sh/builtins.def                      |    3 +-
 sh/cd.c                              |   50 +-
 sh/cd.h                              |    2 +-
 sh/error.c                           |    2 +-
 sh/error.h                           |    2 +-
 sh/eval.c                            |  112 +--
 sh/eval.h                            |    4 +-
 sh/exec.c                            |   19 +-
 sh/exec.h                            |    2 +-
 sh/expand.c                          | 1034 ++++++++++++--------------
 sh/expand.h                          |   21 +-
 sh/funcs/cmv                         |    2 +-
 sh/funcs/dirs                        |    2 +-
 sh/funcs/login                       |    2 +-
 sh/funcs/newgrp                      |    2 +-
 sh/funcs/popd                        |    2 +-
 sh/funcs/pushd                       |    2 +-
 sh/funcs/suspend                     |    2 +-
 sh/histedit.c                        |    4 +-
 sh/input.c                           |   73 +-
 sh/input.h                           |    2 +-
 sh/jobs.c                            |   38 +-
 sh/jobs.h                            |    2 +-
 sh/mail.c                            |    2 +-
 sh/mail.h                            |    2 +-
 sh/main.c                            |    2 +-
 sh/main.h                            |    2 +-
 sh/memalloc.c                        |    2 +-
 sh/memalloc.h                        |    2 +-
 sh/miscbltin.c                       |   45 +-
 sh/mkbuiltins                        |   17 +-
 sh/mknodes.c                         |   40 +-
 sh/mksyntax.c                        |    2 +-
 sh/mktokens                          |    2 +-
 sh/myhistedit.h                      |    2 +-
 sh/mystring.c                        |    2 +-
 sh/mystring.h                        |    2 +-
 sh/nodes.c.pat                       |   68 +-
 sh/nodetypes                         |    2 +-
 sh/options.c                         |   95 +--
 sh/options.h                         |   99 ++-
 sh/output.c                          |    2 +-
 sh/output.h                          |    2 +-
 sh/parser.c                          |   96 ++-
 sh/parser.h                          |    3 +-
 sh/redir.c                           |   31 +-
 sh/redir.h                           |    2 +-
 sh/sh.1                              |   51 +-
 sh/sh.plist.part                     |    5 +-
 sh/shell.h                           |    2 +-
 sh/show.c                            |    2 +-
 sh/show.h                            |    2 +-
 sh/tests/Makefile                    |    4 +-
 sh/tests/Makefile.depend             |   11 +
 sh/tests/builtins/Makefile           |  324 ++++----
 sh/tests/builtins/Makefile.depend    |   11 +
 sh/tests/builtins/alias.0            |    2 +-
 sh/tests/builtins/alias.1            |    2 +-
 sh/tests/builtins/alias3.0           |    2 +-
 sh/tests/builtins/alias4.0           |    2 +-
 sh/tests/builtins/break1.0           |    2 +-
 sh/tests/builtins/break2.0           |    2 +-
 sh/tests/builtins/break3.0           |    2 +-
 sh/tests/builtins/break4.4           |    2 +-
 sh/tests/builtins/break5.4           |    2 +-
 sh/tests/builtins/break6.0           |    2 +-
 sh/tests/builtins/builtin1.0         |    2 +-
 sh/tests/builtins/case1.0            |    2 +-
 sh/tests/builtins/case10.0           |    2 +-
 sh/tests/builtins/case11.0           |    2 +-
 sh/tests/builtins/case12.0           |    2 +-
 sh/tests/builtins/case13.0           |    2 +-
 sh/tests/builtins/case14.0           |    2 +-
 sh/tests/builtins/case15.0           |    2 +-
 sh/tests/builtins/case16.0           |    2 +-
 sh/tests/builtins/case17.0           |    2 +-
 sh/tests/builtins/case18.0           |    2 +-
 sh/tests/builtins/case19.0           |    2 +-
 sh/tests/builtins/case2.0            |    2 +-
 sh/tests/builtins/case20.0           |    9 +
 sh/tests/builtins/case3.0            |    2 +-
 sh/tests/builtins/case4.0            |    2 +-
 sh/tests/builtins/case5.0            |    2 +-
 sh/tests/builtins/case6.0            |    2 +-
 sh/tests/builtins/case7.0            |    2 +-
 sh/tests/builtins/case8.0            |    2 +-
 sh/tests/builtins/case9.0            |    2 +-
 sh/tests/builtins/cd1.0              |    2 +-
 sh/tests/builtins/cd2.0              |    2 +-
 sh/tests/builtins/cd3.0              |    2 +-
 sh/tests/builtins/cd4.0              |    2 +-
 sh/tests/builtins/cd5.0              |    2 +-
 sh/tests/builtins/cd6.0              |    2 +-
 sh/tests/builtins/cd7.0              |    2 +-
 sh/tests/builtins/cd8.0              |    2 +-
 sh/tests/builtins/cd9.0              |    8 +
 sh/tests/builtins/cd9.0.stdout       |    2 +
 sh/tests/builtins/command1.0         |    2 +-
 sh/tests/builtins/command10.0        |    2 +-
 sh/tests/builtins/command11.0        |    2 +-
 sh/tests/builtins/command12.0        |    2 +-
 sh/tests/builtins/command2.0         |    2 +-
 sh/tests/builtins/command3.0         |    2 +-
 sh/tests/builtins/command4.0         |    2 +-
 sh/tests/builtins/command5.0         |    2 +-
 sh/tests/builtins/command6.0         |    2 +-
 sh/tests/builtins/command7.0         |    2 +-
 sh/tests/builtins/command8.0         |    2 +-
 sh/tests/builtins/command9.0         |    2 +-
 sh/tests/builtins/dot1.0             |    2 +-
 sh/tests/builtins/dot2.0             |    2 +-
 sh/tests/builtins/dot3.0             |    2 +-
 sh/tests/builtins/dot4.0             |    2 +-
 sh/tests/builtins/echo1.0            |    6 +
 sh/tests/builtins/echo2.0            |    7 +
 sh/tests/builtins/echo3.0            |    5 +
 sh/tests/builtins/eval1.0            |    2 +-
 sh/tests/builtins/eval2.0            |    2 +-
 sh/tests/builtins/eval3.0            |    2 +-
 sh/tests/builtins/eval4.0            |    2 +-
 sh/tests/builtins/eval5.0            |    2 +-
 sh/tests/builtins/eval6.0            |    2 +-
 sh/tests/builtins/eval7.0            |    2 +-
 sh/tests/builtins/eval8.7            |    2 +-
 sh/tests/builtins/exec1.0            |    2 +-
 sh/tests/builtins/exec2.0            |    2 +-
 sh/tests/builtins/exit1.0            |    2 +-
 sh/tests/builtins/exit2.8            |    2 +-
 sh/tests/builtins/exit3.0            |    2 +-
 sh/tests/builtins/export1.0          |    2 +-
 sh/tests/builtins/fc1.0              |    2 +-
 sh/tests/builtins/fc2.0              |    2 +-
 sh/tests/builtins/for1.0             |    2 +-
 sh/tests/builtins/for2.0             |    2 +-
 sh/tests/builtins/for3.0             |    2 +-
 sh/tests/builtins/getopts1.0         |   10 +-
 sh/tests/builtins/getopts10.0        |   11 +
 sh/tests/builtins/getopts2.0         |    4 +-
 sh/tests/builtins/getopts3.0         |    2 +-
 sh/tests/builtins/getopts4.0         |    2 +-
 sh/tests/builtins/getopts5.0         |    2 +-
 sh/tests/builtins/getopts6.0         |    2 +-
 sh/tests/builtins/getopts7.0         |    2 +-
 sh/tests/builtins/getopts8.0         |    2 +-
 sh/tests/builtins/getopts9.0         |    6 +-
 sh/tests/builtins/hash1.0            |    2 +-
 sh/tests/builtins/hash2.0            |    2 +-
 sh/tests/builtins/hash3.0            |    2 +-
 sh/tests/builtins/hash4.0            |    2 +-
 sh/tests/builtins/jobid1.0           |    2 +-
 sh/tests/builtins/jobid2.0           |    2 +-
 sh/tests/builtins/kill1.0            |    2 +-
 sh/tests/builtins/kill2.0            |    2 +-
 sh/tests/builtins/lineno.0           |    2 +-
 sh/tests/builtins/lineno2.0          |    2 +-
 sh/tests/builtins/lineno3.0          |    2 +-
 sh/tests/builtins/local1.0           |    2 +-
 sh/tests/builtins/local2.0           |    2 +-
 sh/tests/builtins/local3.0           |    2 +-
 sh/tests/builtins/local4.0           |    2 +-
 sh/tests/builtins/local5.0           |   15 +
 sh/tests/builtins/local6.0           |   10 +
 sh/tests/builtins/local7.0           |   10 +
 sh/tests/builtins/locale1.0          |    2 +-
 sh/tests/builtins/printf1.0          |    2 +-
 sh/tests/builtins/printf2.0          |    2 +-
 sh/tests/builtins/printf3.0          |    2 +-
 sh/tests/builtins/printf4.0          |    2 +-
 sh/tests/builtins/read1.0            |    2 +-
 sh/tests/builtins/read2.0            |    2 +-
 sh/tests/builtins/read3.0            |    2 +-
 sh/tests/builtins/read4.0            |    2 +-
 sh/tests/builtins/read5.0            |    2 +-
 sh/tests/builtins/read6.0            |    2 +-
 sh/tests/builtins/read7.0            |    2 +-
 sh/tests/builtins/read8.0            |   17 +
 sh/tests/builtins/read9.0            |   10 +
 sh/tests/builtins/return1.0          |    2 +-
 sh/tests/builtins/return2.1          |    2 +-
 sh/tests/builtins/return3.1          |    2 +-
 sh/tests/builtins/return4.0          |    2 +-
 sh/tests/builtins/return5.0          |    2 +-
 sh/tests/builtins/return6.4          |    2 +-
 sh/tests/builtins/return7.4          |    2 +-
 sh/tests/builtins/return8.0          |    2 +-
 sh/tests/builtins/set2.0             |    2 +-
 sh/tests/builtins/set3.0             |    4 +
 sh/tests/builtins/trap1.0            |    2 +-
 sh/tests/builtins/trap10.0           |    2 +-
 sh/tests/builtins/trap11.0           |    2 +-
 sh/tests/builtins/trap12.0           |    2 +-
 sh/tests/builtins/trap13.0           |    2 +-
 sh/tests/builtins/trap14.0           |    2 +-
 sh/tests/builtins/trap15.0           |    2 +-
 sh/tests/builtins/trap16.0           |    2 +-
 sh/tests/builtins/trap17.0           |   10 +
 sh/tests/builtins/trap2.0            |    2 +-
 sh/tests/builtins/trap3.0            |    2 +-
 sh/tests/builtins/trap4.0            |    2 +-
 sh/tests/builtins/trap5.0            |    2 +-
 sh/tests/builtins/trap6.0            |    2 +-
 sh/tests/builtins/trap7.0            |    2 +-
 sh/tests/builtins/trap8.0            |    2 +-
 sh/tests/builtins/trap9.0            |    2 +-
 sh/tests/builtins/type1.0            |    2 +-
 sh/tests/builtins/type2.0            |    2 +-
 sh/tests/builtins/type3.0            |    2 +-
 sh/tests/builtins/unalias.0          |    2 +-
 sh/tests/builtins/var-assign.0       |    2 +-
 sh/tests/builtins/var-assign2.0      |    2 +-
 sh/tests/builtins/wait1.0            |    2 +-
 sh/tests/builtins/wait10.0           |    2 +-
 sh/tests/builtins/wait2.0            |    2 +-
 sh/tests/builtins/wait3.0            |    2 +-
 sh/tests/builtins/wait4.0            |    2 +-
 sh/tests/builtins/wait5.0            |    2 +-
 sh/tests/builtins/wait6.0            |    2 +-
 sh/tests/builtins/wait7.0            |    2 +-
 sh/tests/builtins/wait8.0            |    2 +-
 sh/tests/builtins/wait9.127          |    2 +-
 sh/tests/errors/Makefile             |   50 +-
 sh/tests/errors/Makefile.depend      |   11 +
 sh/tests/errors/assignment-error1.0  |    2 +-
 sh/tests/errors/assignment-error2.0  |    2 +-
 sh/tests/errors/backquote-error1.0   |    2 +-
 sh/tests/errors/backquote-error2.0   |    2 +-
 sh/tests/errors/bad-binary1.126      |    2 +-
 sh/tests/errors/bad-keyword1.0       |    2 +-
 sh/tests/errors/bad-parm-exp1.0      |    2 +-
 sh/tests/errors/bad-parm-exp2.2      |    2 +-
 sh/tests/errors/bad-parm-exp3.2      |    2 +-
 sh/tests/errors/bad-parm-exp4.2      |    2 +-
 sh/tests/errors/bad-parm-exp5.2      |    2 +-
 sh/tests/errors/bad-parm-exp6.2      |    2 +-
 sh/tests/errors/bad-parm-exp7.0      |    4 +
 sh/tests/errors/bad-parm-exp8.0      |    4 +
 sh/tests/errors/option-error.0       |    2 +-
 sh/tests/errors/redirection-error.0  |    2 +-
 sh/tests/errors/redirection-error2.2 |    2 +-
 sh/tests/errors/redirection-error3.0 |    2 +-
 sh/tests/errors/redirection-error4.0 |    2 +-
 sh/tests/errors/redirection-error5.0 |    2 +-
 sh/tests/errors/redirection-error6.0 |    2 +-
 sh/tests/errors/redirection-error7.0 |    2 +-
 sh/tests/errors/write-error1.0       |    2 +-
 sh/tests/execution/Makefile          |   96 +--
 sh/tests/execution/Makefile.depend   |   11 +
 sh/tests/execution/bg1.0             |    2 +-
 sh/tests/execution/bg10.0            |    2 +-
 sh/tests/execution/bg2.0             |    2 +-
 sh/tests/execution/bg3.0             |    2 +-
 sh/tests/execution/bg4.0             |    2 +-
 sh/tests/execution/bg5.0             |    2 +-
 sh/tests/execution/bg6.0             |    2 +-
 sh/tests/execution/bg7.0             |    2 +-
 sh/tests/execution/bg8.0             |    2 +-
 sh/tests/execution/bg9.0             |    2 +-
 sh/tests/execution/fork1.0           |    2 +-
 sh/tests/execution/fork2.0           |    2 +-
 sh/tests/execution/fork3.0           |    2 +-
 sh/tests/execution/func1.0           |    2 +-
 sh/tests/execution/func2.0           |    2 +-
 sh/tests/execution/func3.0           |    2 +-
 sh/tests/execution/hash1.0           |    2 +-
 sh/tests/execution/int-cmd1.0        |    2 +-
 sh/tests/execution/killed1.0         |    2 +-
 sh/tests/execution/killed2.0         |    2 +-
 sh/tests/execution/not1.0            |    2 +-
 sh/tests/execution/not2.0            |    2 +-
 sh/tests/execution/path1.0           |    2 +-
 sh/tests/execution/redir1.0          |    2 +-
 sh/tests/execution/redir2.0          |    2 +-
 sh/tests/execution/redir3.0          |    2 +-
 sh/tests/execution/redir4.0          |    2 +-
 sh/tests/execution/redir5.0          |    2 +-
 sh/tests/execution/redir6.0          |    2 +-
 sh/tests/execution/redir7.0          |    2 +-
 sh/tests/execution/set-n1.0          |    2 +-
 sh/tests/execution/set-n2.0          |    2 +-
 sh/tests/execution/set-n3.0          |    2 +-
 sh/tests/execution/set-n4.0          |    2 +-
 sh/tests/execution/set-x1.0          |    2 +-
 sh/tests/execution/set-x2.0          |    2 +-
 sh/tests/execution/set-x3.0          |    2 +-
 sh/tests/execution/set-x4.0          |    2 +-
 sh/tests/execution/shellproc1.0      |    2 +-
 sh/tests/execution/subshell1.0       |    2 +-
 sh/tests/execution/subshell2.0       |    2 +-
 sh/tests/execution/subshell3.0       |    2 +-
 sh/tests/execution/subshell4.0       |    2 +-
 sh/tests/execution/unknown1.0        |    2 +-
 sh/tests/execution/var-assign1.0     |    2 +-
 sh/tests/expansion/Makefile          |  174 ++---
 sh/tests/expansion/Makefile.depend   |   11 +
 sh/tests/expansion/arith1.0          |    2 +-
 sh/tests/expansion/arith10.0         |    2 +-
 sh/tests/expansion/arith11.0         |    2 +-
 sh/tests/expansion/arith12.0         |    2 +-
 sh/tests/expansion/arith13.0         |    2 +-
 sh/tests/expansion/arith14.0         |    2 +-
 sh/tests/expansion/arith2.0          |    2 +-
 sh/tests/expansion/arith3.0          |    2 +-
 sh/tests/expansion/arith4.0          |    2 +-
 sh/tests/expansion/arith5.0          |    2 +-
 sh/tests/expansion/arith6.0          |    2 +-
 sh/tests/expansion/arith7.0          |    2 +-
 sh/tests/expansion/arith8.0          |    2 +-
 sh/tests/expansion/arith9.0          |    2 +-
 sh/tests/expansion/assign1.0         |    2 +-
 sh/tests/expansion/cmdsubst1.0       |    2 +-
 sh/tests/expansion/cmdsubst10.0      |    2 +-
 sh/tests/expansion/cmdsubst11.0      |    2 +-
 sh/tests/expansion/cmdsubst12.0      |    2 +-
 sh/tests/expansion/cmdsubst13.0      |    2 +-
 sh/tests/expansion/cmdsubst14.0      |    2 +-
 sh/tests/expansion/cmdsubst15.0      |    2 +-
 sh/tests/expansion/cmdsubst16.0      |    2 +-
 sh/tests/expansion/cmdsubst17.0      |    2 +-
 sh/tests/expansion/cmdsubst2.0       |    2 +-
 sh/tests/expansion/cmdsubst3.0       |    2 +-
 sh/tests/expansion/cmdsubst4.0       |    2 +-
 sh/tests/expansion/cmdsubst5.0       |    2 +-
 sh/tests/expansion/cmdsubst6.0       |    2 +-
 sh/tests/expansion/cmdsubst7.0       |    2 +-
 sh/tests/expansion/cmdsubst8.0       |    2 +-
 sh/tests/expansion/cmdsubst9.0       |    2 +-
 sh/tests/expansion/export1.0         |    2 +-
 sh/tests/expansion/export2.0         |    2 +-
 sh/tests/expansion/export3.0         |    2 +-
 sh/tests/expansion/heredoc1.0        |    2 +-
 sh/tests/expansion/heredoc2.0        |    2 +-
 sh/tests/expansion/ifs1.0            |    2 +-
 sh/tests/expansion/ifs2.0            |    2 +-
 sh/tests/expansion/ifs3.0            |    2 +-
 sh/tests/expansion/ifs4.0            |    2 +-
 sh/tests/expansion/ifs5.0            |    2 +-
 sh/tests/expansion/ifs6.0            |    2 +-
 sh/tests/expansion/ifs7.0            |    2 +-
 sh/tests/expansion/length1.0         |    2 +-
 sh/tests/expansion/length2.0         |    2 +-
 sh/tests/expansion/length3.0         |    2 +-
 sh/tests/expansion/length4.0         |    2 +-
 sh/tests/expansion/length5.0         |    2 +-
 sh/tests/expansion/length6.0         |    2 +-
 sh/tests/expansion/length7.0         |    2 +-
 sh/tests/expansion/length8.0         |    2 +-
 sh/tests/expansion/local1.0          |    2 +-
 sh/tests/expansion/local2.0          |    2 +-
 sh/tests/expansion/pathname1.0       |    6 +-
 sh/tests/expansion/pathname2.0       |    6 +-
 sh/tests/expansion/pathname3.0       |    2 +-
 sh/tests/expansion/pathname4.0       |    2 +-
 sh/tests/expansion/pathname5.0       |    2 +-
 sh/tests/expansion/pathname6.0       |   29 +
 sh/tests/expansion/plus-minus1.0     |    2 +-
 sh/tests/expansion/plus-minus2.0     |    2 +-
 sh/tests/expansion/plus-minus3.0     |    2 +-
 sh/tests/expansion/plus-minus4.0     |    2 +-
 sh/tests/expansion/plus-minus5.0     |    2 +-
 sh/tests/expansion/plus-minus6.0     |    2 +-
 sh/tests/expansion/plus-minus7.0     |    2 +-
 sh/tests/expansion/plus-minus8.0     |    2 +-
 sh/tests/expansion/question1.0       |    2 +-
 sh/tests/expansion/readonly1.0       |    2 +-
 sh/tests/expansion/redir1.0          |    2 +-
 sh/tests/expansion/set-u1.0          |    2 +-
 sh/tests/expansion/set-u2.0          |    2 +-
 sh/tests/expansion/set-u3.0          |    2 +-
 sh/tests/expansion/tilde1.0          |    2 +-
 sh/tests/expansion/tilde2.0          |    2 +-
 sh/tests/expansion/trim1.0           |    2 +-
 sh/tests/expansion/trim2.0           |    2 +-
 sh/tests/expansion/trim3.0           |    2 +-
 sh/tests/expansion/trim4.0           |    2 +-
 sh/tests/expansion/trim5.0           |    2 +-
 sh/tests/expansion/trim6.0           |    2 +-
 sh/tests/expansion/trim7.0           |    2 +-
 sh/tests/expansion/trim8.0           |    2 +-
 sh/tests/expansion/trim9.0           |   61 ++
 sh/tests/functional_test.sh          |    2 +-
 sh/tests/parameters/Makefile         |   39 +-
 sh/tests/parameters/Makefile.depend  |   11 +
 sh/tests/parameters/env1.0           |    2 +-
 sh/tests/parameters/exitstatus1.0    |    2 +-
 sh/tests/parameters/ifs1.0           |   10 +
 sh/tests/parameters/mail1.0          |    2 +-
 sh/tests/parameters/mail2.0          |    2 +-
 sh/tests/parameters/optind1.0        |    2 +-
 sh/tests/parameters/optind2.0        |    2 +-
 sh/tests/parameters/positional1.0    |    2 +-
 sh/tests/parameters/positional2.0    |    2 +-
 sh/tests/parameters/positional3.0    |    2 +-
 sh/tests/parameters/positional4.0    |    2 +-
 sh/tests/parameters/positional5.0    |    2 +-
 sh/tests/parameters/positional6.0    |    2 +-
 sh/tests/parameters/positional7.0    |    2 +-
 sh/tests/parameters/positional8.0    |   31 +
 sh/tests/parameters/positional9.0    |   18 +
 sh/tests/parameters/pwd1.0           |    2 +-
 sh/tests/parameters/pwd2.0           |    2 +-
 sh/tests/parser/Makefile             |  147 ++--
 sh/tests/parser/Makefile.depend      |   11 +
 sh/tests/parser/alias1.0             |    2 +-
 sh/tests/parser/alias10.0            |    2 +-
 sh/tests/parser/alias11.0            |    2 +-
 sh/tests/parser/alias12.0            |    2 +-
 sh/tests/parser/alias13.0            |    2 +-
 sh/tests/parser/alias14.0            |    2 +-
 sh/tests/parser/alias15.0            |    2 +-
 sh/tests/parser/alias2.0             |    2 +-
 sh/tests/parser/alias3.0             |    2 +-
 sh/tests/parser/alias4.0             |    2 +-
 sh/tests/parser/alias5.0             |    2 +-
 sh/tests/parser/alias6.0             |    2 +-
 sh/tests/parser/alias7.0             |    2 +-
 sh/tests/parser/alias8.0             |    2 +-
 sh/tests/parser/alias9.0             |    2 +-
 sh/tests/parser/and-pipe-not.0       |    2 +-
 sh/tests/parser/case1.0              |    2 +-
 sh/tests/parser/case2.0              |    2 +-
 sh/tests/parser/comment1.0           |    3 +
 sh/tests/parser/comment2.42          |    4 +
 sh/tests/parser/dollar-quote10.0     |    2 +-
 sh/tests/parser/dollar-quote11.0     |    2 +-
 sh/tests/parser/dollar-quote12.0     |    7 +
 sh/tests/parser/dollar-quote13.0     |    8 +
 sh/tests/parser/empty-braces1.0      |    2 +-
 sh/tests/parser/empty-cmd1.0         |    2 +-
 sh/tests/parser/for1.0               |    2 +-
 sh/tests/parser/for2.0               |    2 +-
 sh/tests/parser/func1.0              |    2 +-
 sh/tests/parser/func2.0              |    2 +-
 sh/tests/parser/func3.0              |    2 +-
 sh/tests/parser/heredoc1.0           |    2 +-
 sh/tests/parser/heredoc10.0          |    2 +-
 sh/tests/parser/heredoc11.0          |    2 +-
 sh/tests/parser/heredoc12.0          |    2 +-
 sh/tests/parser/heredoc13.0          |   21 +
 sh/tests/parser/heredoc2.0           |    2 +-
 sh/tests/parser/heredoc3.0           |    2 +-
 sh/tests/parser/heredoc4.0           |    2 +-
 sh/tests/parser/heredoc5.0           |    2 +-
 sh/tests/parser/heredoc6.0           |    2 +-
 sh/tests/parser/heredoc7.0           |    2 +-
 sh/tests/parser/heredoc8.0           |    2 +-
 sh/tests/parser/heredoc9.0           |    2 +-
 sh/tests/parser/line-cont1.0         |    2 +-
 sh/tests/parser/line-cont10.0        |    2 +-
 sh/tests/parser/line-cont11.0        |    2 +-
 sh/tests/parser/line-cont2.0         |    2 +-
 sh/tests/parser/line-cont3.0         |    2 +-
 sh/tests/parser/line-cont4.0         |    2 +-
 sh/tests/parser/line-cont5.0         |    2 +-
 sh/tests/parser/line-cont6.0         |    2 +-
 sh/tests/parser/line-cont7.0         |    2 +-
 sh/tests/parser/line-cont8.0         |    2 +-
 sh/tests/parser/line-cont9.0         |    2 +-
 sh/tests/parser/no-space1.0          |    2 +-
 sh/tests/parser/no-space2.0          |    2 +-
 sh/tests/parser/nul1.0               |   12 +
 sh/tests/parser/only-redir1.0        |    2 +-
 sh/tests/parser/only-redir2.0        |    2 +-
 sh/tests/parser/only-redir3.0        |    2 +-
 sh/tests/parser/only-redir4.0        |    2 +-
 sh/tests/parser/pipe-not1.0          |    2 +-
 sh/tests/parser/set-v1.0             |    8 +
 sh/tests/parser/set-v1.0.stderr      |    5 +
 sh/tests/parser/var-assign1.0        |    2 +-
 sh/tests/set-e/Makefile              |   76 +-
 sh/tests/set-e/Makefile.depend       |   11 +
 sh/tests/set-e/and1.0                |    2 +-
 sh/tests/set-e/and2.1                |    2 +-
 sh/tests/set-e/and3.0                |    2 +-
 sh/tests/set-e/and4.0                |    2 +-
 sh/tests/set-e/background1.0         |    2 +-
 sh/tests/set-e/cmd1.0                |    2 +-
 sh/tests/set-e/cmd2.1                |    2 +-
 sh/tests/set-e/elif1.0               |    2 +-
 sh/tests/set-e/elif2.0               |    2 +-
 sh/tests/set-e/eval1.0               |    2 +-
 sh/tests/set-e/eval2.1               |    2 +-
 sh/tests/set-e/for1.0                |    2 +-
 sh/tests/set-e/func1.0               |    2 +-
 sh/tests/set-e/func2.1               |    2 +-
 sh/tests/set-e/if1.0                 |    2 +-
 sh/tests/set-e/if2.0                 |    2 +-
 sh/tests/set-e/if3.0                 |    2 +-
 sh/tests/set-e/not1.0                |    2 +-
 sh/tests/set-e/not2.0                |    2 +-
 sh/tests/set-e/or1.0                 |    2 +-
 sh/tests/set-e/or2.0                 |    2 +-
 sh/tests/set-e/or3.1                 |    2 +-
 sh/tests/set-e/pipe1.1               |    2 +-
 sh/tests/set-e/pipe2.0               |    2 +-
 sh/tests/set-e/return1.0             |    2 +-
 sh/tests/set-e/semi1.1               |    2 +-
 sh/tests/set-e/semi2.1               |    2 +-
 sh/tests/set-e/subshell1.0           |    2 +-
 sh/tests/set-e/subshell2.1           |    2 +-
 sh/tests/set-e/until1.0              |    2 +-
 sh/tests/set-e/until2.0              |    2 +-
 sh/tests/set-e/until3.0              |    2 +-
 sh/tests/set-e/while1.0              |    2 +-
 sh/tests/set-e/while2.0              |    2 +-
 sh/tests/set-e/while3.0              |    2 +-
 sh/trap.c                            |    7 +-
 sh/trap.h                            |    2 +-
 sh/var.c                             |   51 +-
 sh/var.h                             |    6 +-
 shell_cmds.xcodeproj/project.pbxproj |  100 +++
 test/tests/legacy_test.sh            |    7 +
 tests/regress.m4                     |   59 ++
 tests/shell_cmds.plist               |   43 ++
 which/which.1                        |   12 +-
 which/which.c                        |    6 +-
 xcodescripts/install-files.sh        |    6 +
 550 files changed, 2708 insertions(+), 1988 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 printf/tests/Makefile
 create mode 100644 printf/tests/Makefile.depend
 create mode 100644 printf/tests/legacy_test.sh
 create mode 100644 printf/tests/regress.b.out
 create mode 100644 printf/tests/regress.d.out
 create mode 100644 printf/tests/regress.f.out
 create mode 100644 printf/tests/regress.l1.out
 create mode 100644 printf/tests/regress.l2.out
 create mode 100644 printf/tests/regress.m1.out
 create mode 100644 printf/tests/regress.m2.out
 create mode 100644 printf/tests/regress.m3.out
 create mode 100644 printf/tests/regress.m4.out
 create mode 100644 printf/tests/regress.m5.out
 create mode 100644 printf/tests/regress.missingpos1.out
 create mode 100644 printf/tests/regress.s.out
 create mode 100644 printf/tests/regress.sh
 create mode 100644 printf/tests/regress.zero.out
 create mode 100644 sh/tests/Makefile.depend
 create mode 100644 sh/tests/builtins/Makefile.depend
 create mode 100644 sh/tests/builtins/case20.0
 create mode 100644 sh/tests/builtins/cd9.0
 create mode 100644 sh/tests/builtins/cd9.0.stdout
 create mode 100644 sh/tests/builtins/echo1.0
 create mode 100644 sh/tests/builtins/echo2.0
 create mode 100644 sh/tests/builtins/echo3.0
 create mode 100644 sh/tests/builtins/getopts10.0
 create mode 100644 sh/tests/builtins/local5.0
 create mode 100644 sh/tests/builtins/local6.0
 create mode 100644 sh/tests/builtins/local7.0
 create mode 100644 sh/tests/builtins/read8.0
 create mode 100644 sh/tests/builtins/read9.0
 create mode 100644 sh/tests/builtins/set3.0
 create mode 100644 sh/tests/builtins/trap17.0
 create mode 100644 sh/tests/errors/Makefile.depend
 create mode 100644 sh/tests/errors/bad-parm-exp7.0
 create mode 100644 sh/tests/errors/bad-parm-exp8.0
 create mode 100644 sh/tests/execution/Makefile.depend
 create mode 100644 sh/tests/expansion/Makefile.depend
 create mode 100644 sh/tests/expansion/pathname6.0
 create mode 100644 sh/tests/expansion/trim9.0
 create mode 100644 sh/tests/parameters/Makefile.depend
 create mode 100644 sh/tests/parameters/ifs1.0
 create mode 100644 sh/tests/parameters/positional8.0
 create mode 100644 sh/tests/parameters/positional9.0
 create mode 100644 sh/tests/parser/Makefile.depend
 create mode 100644 sh/tests/parser/comment1.0
 create mode 100644 sh/tests/parser/comment2.42
 create mode 100644 sh/tests/parser/dollar-quote12.0
 create mode 100644 sh/tests/parser/dollar-quote13.0
 create mode 100644 sh/tests/parser/heredoc13.0
 create mode 100644 sh/tests/parser/nul1.0
 create mode 100644 sh/tests/parser/set-v1.0
 create mode 100644 sh/tests/parser/set-v1.0.stderr
 create mode 100644 sh/tests/set-e/Makefile.depend
 create mode 100644 tests/regress.m4
 create mode 100644 tests/shell_cmds.plist

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9bce6af
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+xcuserdata
diff --git a/lastcomm/lastcomm.c b/lastcomm/lastcomm.c
index e712874..e1d9b66 100644
--- a/lastcomm/lastcomm.c
+++ b/lastcomm/lastcomm.c
@@ -134,6 +134,7 @@ main(int argc, char *argv[])
 					*p = '?';
 		if (!*argv || requested(argv, &ab)) {
 
+			time_t timelong = ab.ac_btime;
 			t = expand(ab.ac_utime) + expand(ab.ac_stime);
 			(void)printf(
 			    "%-*.*s %-7s %-*.*s %-*.*s %6.2f secs %.16s",
@@ -143,7 +144,7 @@ main(int argc, char *argv[])
 			     UT_NAMESIZE, UT_NAMESIZE,
 			     user_from_uid(ab.ac_uid, 0), UT_LINESIZE,
 			     UT_LINESIZE, getdev(ab.ac_tty),
-			     t / (double)AHZ, ctime(&ab.ac_btime));
+			     t / (double)AHZ, ctime(&timelong));
 			delta = expand(ab.ac_etime) / (double)AHZ;
 			printf(" (%1.0f:%02.0f:%05.2f)\n",
 			       floor(delta / SECSPERHOUR),
diff --git a/locate/locate/locate.rc b/locate/locate/locate.rc
index fdf099b..09fbf0e 100644
--- a/locate/locate/locate.rc
+++ b/locate/locate/locate.rc
@@ -23,4 +23,4 @@
 # an empty database.
 #
 # be careful if you add 'nfs'
-#FILESYSTEMS="hfs ufs"
+#FILESYSTEMS="hfs ufs apfs"
diff --git a/locate/locate/updatedb.sh b/locate/locate/updatedb.sh
index 131b1f4..3bbddea 100644
--- a/locate/locate/updatedb.sh
+++ b/locate/locate/updatedb.sh
@@ -56,11 +56,11 @@ PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
 # 6497475
 set -o noglob
 
-: ${mklocatedb:=locate.mklocatedb}	 # make locate database program
-: ${FCODES:=/var/db/locate.database}	 # the database
-: ${SEARCHPATHS:="/"}		# directories to be put in the database
+: ${mklocatedb:=locate.mklocatedb}      # make locate database program
+: ${FCODES:=/var/db/locate.database}    # the database
+: ${SEARCHPATHS:="/"}                   # directories to be put in the database
 : ${PRUNEPATHS:="/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb"} # unwanted directories
-: ${FILESYSTEMS:="hfs ufs"}			 # allowed filesystems 
+: ${FILESYSTEMS:="hfs ufs apfs"}        # allowed filesystems
 : ${find:=find}
 
 case X"$SEARCHPATHS" in 
diff --git a/printf/printf.1 b/printf/printf.1
index 7256b53..59643b5 100644
--- a/printf/printf.1
+++ b/printf/printf.1
@@ -29,7 +29,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)printf.1	8.1 (Berkeley) 6/6/93
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.bin/printf/printf.1 264743 2014-04-21 22:47:18Z pfg $
 .\"
 .Dd April 21, 2014
 .Dt PRINTF 1
diff --git a/printf/printf.c b/printf/printf.c
index 8636cc1..438b85e 100644
--- a/printf/printf.c
+++ b/printf/printf.c
@@ -46,7 +46,7 @@ static char const copyright[] =
 static char const sccsid[] = "@(#)printf.c	8.1 (Berkeley) 7/20/93";
 #endif
 static const char rcsid[] =
-  "$FreeBSD$";
+  "$FreeBSD: head/usr.bin/printf/printf.c 279503 2015-03-01 21:46:55Z jilles $";
 #endif /* not lint */
 
 #include <sys/types.h>
diff --git a/printf/tests/Makefile b/printf/tests/Makefile
new file mode 100644
index 0000000..7d014a5
--- /dev/null
+++ b/printf/tests/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD: head/usr.bin/printf/tests/Makefile 299094 2016-05-04 23:20:53Z ngie $
+
+PACKAGE=	tests
+
+TAP_TESTS_SH=	legacy_test
+
+${PACKAGE}FILES+=		regress.b.out
+${PACKAGE}FILES+=		regress.d.out
+${PACKAGE}FILES+=		regress.f.out
+${PACKAGE}FILES+=		regress.l1.out
+${PACKAGE}FILES+=		regress.l2.out
+${PACKAGE}FILES+=		regress.m1.out
+${PACKAGE}FILES+=		regress.m2.out
+${PACKAGE}FILES+=		regress.m3.out
+${PACKAGE}FILES+=		regress.m4.out
+${PACKAGE}FILES+=		regress.m5.out
+${PACKAGE}FILES+=		regress.missingpos1.out
+${PACKAGE}FILES+=		regress.s.out
+${PACKAGE}FILES+=		regress.sh
+${PACKAGE}FILES+=		regress.zero.out
+
+.include <bsd.test.mk>
diff --git a/printf/tests/Makefile.depend b/printf/tests/Makefile.depend
new file mode 100644
index 0000000..0fd1616
--- /dev/null
+++ b/printf/tests/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.bin/printf/tests/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/printf/tests/legacy_test.sh b/printf/tests/legacy_test.sh
new file mode 100644
index 0000000..7b1f694
--- /dev/null
+++ b/printf/tests/legacy_test.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+# $FreeBSD: head/usr.bin/printf/tests/legacy_test.sh 263227 2014-03-16 08:04:06Z jmmv $
+
+SRCDIR="$(dirname "${0}")"; export SRCDIR
+
+m4 /AppleInternal/Tests/shell_cmds/regress.m4 "${SRCDIR}/regress.sh" | sh
diff --git a/printf/tests/regress.b.out b/printf/tests/regress.b.out
new file mode 100644
index 0000000..0373d93
--- /dev/null
+++ b/printf/tests/regress.b.out
@@ -0,0 +1 @@
+abcdef
diff --git a/printf/tests/regress.d.out b/printf/tests/regress.d.out
new file mode 100644
index 0000000..da83c08
--- /dev/null
+++ b/printf/tests/regress.d.out
@@ -0,0 +1 @@
+123,  123,00123,00123,00123
diff --git a/printf/tests/regress.f.out b/printf/tests/regress.f.out
new file mode 100644
index 0000000..127cb8a
--- /dev/null
+++ b/printf/tests/regress.f.out
@@ -0,0 +1 @@
+42.250000,-42.250 ,inf,nan
diff --git a/printf/tests/regress.l1.out b/printf/tests/regress.l1.out
new file mode 100644
index 0000000..9be0dc9
--- /dev/null
+++ b/printf/tests/regress.l1.out
@@ -0,0 +1 @@
+228
diff --git a/printf/tests/regress.l2.out b/printf/tests/regress.l2.out
new file mode 100644
index 0000000..9be0dc9
--- /dev/null
+++ b/printf/tests/regress.l2.out
@@ -0,0 +1 @@
+228
diff --git a/printf/tests/regress.m1.out b/printf/tests/regress.m1.out
new file mode 100644
index 0000000000000000000000000000000000000000..a9e063ee970985630d155823ab1d70330fd2b6d5
GIT binary patch
literal 7
OcmYdPwKQi?<pKZ&*#Ra1

literal 0
HcmV?d00001

diff --git a/printf/tests/regress.m2.out b/printf/tests/regress.m2.out
new file mode 100644
index 0000000..cf14915
--- /dev/null
+++ b/printf/tests/regress.m2.out
@@ -0,0 +1,2 @@
+abc
+cdef
\ No newline at end of file
diff --git a/printf/tests/regress.m3.out b/printf/tests/regress.m3.out
new file mode 100644
index 0000000..bbe4e70
--- /dev/null
+++ b/printf/tests/regress.m3.out
@@ -0,0 +1,4 @@
+%abc
+%def
+%ghi
+%jkl
diff --git a/printf/tests/regress.m4.out b/printf/tests/regress.m4.out
new file mode 100644
index 0000000..5e0b5d4
--- /dev/null
+++ b/printf/tests/regress.m4.out
@@ -0,0 +1 @@
+0,0.000000,,
diff --git a/printf/tests/regress.m5.out b/printf/tests/regress.m5.out
new file mode 100644
index 0000000..2838468
--- /dev/null
+++ b/printf/tests/regress.m5.out
@@ -0,0 +1 @@
+-d
diff --git a/printf/tests/regress.missingpos1.out b/printf/tests/regress.missingpos1.out
new file mode 100644
index 0000000..3b04f03
--- /dev/null
+++ b/printf/tests/regress.missingpos1.out
@@ -0,0 +1 @@
+printf: incomplete use of n$
diff --git a/printf/tests/regress.s.out b/printf/tests/regress.s.out
new file mode 100644
index 0000000..3d572b9
--- /dev/null
+++ b/printf/tests/regress.s.out
@@ -0,0 +1 @@
+abc,abc  
diff --git a/printf/tests/regress.sh b/printf/tests/regress.sh
new file mode 100644
index 0000000..2f68c7d
--- /dev/null
+++ b/printf/tests/regress.sh
@@ -0,0 +1,33 @@
+# $FreeBSD: head/usr.bin/printf/tests/regress.sh 266854 2014-05-29 19:48:18Z pfg $
+
+enable -n printf
+
+REGRESSION_START($1)
+
+echo '1..23'
+
+REGRESSION_TEST(`b', `printf "abc%b%b" "def\n" "\cghi"')
+REGRESSION_TEST(`d', `printf "%d,%5d,%.5d,%0*d,%.*d\n" 123 123 123 5 123 5 123')
+REGRESSION_TEST(`f', `printf "%f,%-8.3f,%f,%f\n" +42.25 -42.25 inf nan')
+REGRESSION_TEST(`l1', `LC_ALL=en_US.ISO8859-1 printf "%d\n" $(printf \"\\344)')
+REGRESSION_TEST(`l2', `LC_ALL=en_US.UTF-8 printf "%d\n" $(printf \"\\303\\244)')
+REGRESSION_TEST(`m1', `printf "%c%%%d\0\045\n" abc \"abc')
+REGRESSION_TEST(`m2', `printf "abc\n\cdef"')
+REGRESSION_TEST(`m3', `printf "%%%s\n" abc def ghi jkl')
+REGRESSION_TEST(`m4', `printf "%d,%f,%c,%s\n"')
+REGRESSION_TEST(`m5', `printf -- "-d\n"')
+REGRESSION_TEST(`s', `printf "%.3s,%-5s\n" abcd abc')
+REGRESSION_TEST('zero', `printf "%u%u\n" 15')
+REGRESSION_TEST('zero', `printf "%d%d\n" 15')
+REGRESSION_TEST('zero', `printf "%d%u\n" 15')
+REGRESSION_TEST('zero', `printf "%u%d\n" 15')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*s" 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*1\$s" 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*.*s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*1\$.*s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*.*1\$s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*2\$.*s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%*1\$.*2\$s" 1 1 1 2>&1')
+REGRESSION_TEST(`missingpos1', `printf "%1\$*.*2\$s" 1 1 1 2>&1')
+
+REGRESSION_END()
diff --git a/printf/tests/regress.zero.out b/printf/tests/regress.zero.out
new file mode 100644
index 0000000..fa8f08c
--- /dev/null
+++ b/printf/tests/regress.zero.out
@@ -0,0 +1 @@
+150
diff --git a/sh/Makefile b/sh/Makefile
index 3f28a12..08fa278 100644
--- a/sh/Makefile
+++ b/sh/Makefile
@@ -1,8 +1,9 @@
 #	@(#)Makefile	8.4 (Berkeley) 5/5/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/Makefile 301285 2016-06-03 19:25:41Z bdrewery $
 
 .include <src.opts.mk>
 
+PACKAGE=runtime
 PROG=	sh
 INSTALLFLAGS= -S
 SHSRCS=	alias.c arith_yacc.c arith_yylex.c cd.c echo.c error.c eval.c \
@@ -38,24 +39,27 @@ CLEANFILES+= ${GENSRCS} ${GENHDRS}
 build-tools: mknodes mksyntax
 
 .ORDER: builtins.c builtins.h
+builtins.h: .NOMETA
 builtins.c builtins.h: mkbuiltins builtins.def
 	sh ${.CURDIR}/mkbuiltins ${.CURDIR}
 
 # XXX this is just to stop the default .c rule being used, so that the
 # intermediate object has a fixed name.
 # XXX we have a default .c rule, but no default .o rule.
-.o:
+mknodes.o mksyntax.o: ${BUILD_TOOLS_META}
 	${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET}
-mknodes: mknodes.o
-mksyntax: mksyntax.o
+mknodes: mknodes.o ${BUILD_TOOLS_META}
+mksyntax: mksyntax.o ${BUILD_TOOLS_META}
 
 .ORDER: nodes.c nodes.h
+nodes.h: .NOMETA
 nodes.c nodes.h: mknodes nodetypes nodes.c.pat
-	./mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat
+	${BTOOLSPATH:U.}/mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat
 
 .ORDER: syntax.c syntax.h
+syntax.h: .NOMETA
 syntax.c syntax.h: mksyntax
-	./mksyntax
+	${BTOOLSPATH:U.}/mksyntax
 
 token.h: mktokens
 	sh ${.CURDIR}/mktokens
diff --git a/sh/Makefile.depend b/sh/Makefile.depend
index 9eb4fba..e33ea1e 100644
--- a/sh/Makefile.depend
+++ b/sh/Makefile.depend
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/Makefile.depend 295989 2016-02-24 17:20:11Z bdrewery $
 # Autogenerated - do NOT edit!
 
 DIRDEPS = \
@@ -17,98 +17,4 @@ DIRDEPS = \
 
 .if ${DEP_RELDIR} == ${_DEP_RELDIR}
 # local dependencies - needed for -jN in clean tree
-alias.o: builtins.h
-alias.po: builtins.h
-arith_yylex.o: syntax.h
-arith_yylex.po: syntax.h
-builtins.o: builtins.c
-builtins.o: builtins.h
-builtins.po: builtins.c
-builtins.po: builtins.h
-cd.o: builtins.h
-cd.o: nodes.h
-cd.po: builtins.h
-cd.po: nodes.h
-echo.o: builtins.h
-echo.po: builtins.h
-error.o: nodes.h
-error.po: nodes.h
-eval.o: builtins.h
-eval.o: nodes.h
-eval.o: syntax.h
-eval.po: builtins.h
-eval.po: nodes.h
-eval.po: syntax.h
-exec.o: builtins.h
-exec.o: nodes.h
-exec.o: syntax.h
-exec.po: builtins.h
-exec.po: nodes.h
-exec.po: syntax.h
-expand.o: builtins.h
-expand.o: nodes.h
-expand.o: syntax.h
-expand.po: builtins.h
-expand.po: nodes.h
-expand.po: syntax.h
-histedit.o: builtins.h
-histedit.po: builtins.h
-input.o: syntax.h
-input.po: syntax.h
-jobs.o: builtins.h
-jobs.o: nodes.h
-jobs.o: syntax.h
-jobs.po: builtins.h
-jobs.po: nodes.h
-jobs.po: syntax.h
-kill.o: builtins.h
-kill.po: builtins.h
-main.o: builtins.h
-main.o: nodes.h
-main.po: builtins.h
-main.po: nodes.h
-miscbltin.o: syntax.h
-miscbltin.po: syntax.h
-mystring.o: syntax.h
-mystring.po: syntax.h
-nodes.o: nodes.c
-nodes.o: nodes.h
-nodes.po: nodes.c
-nodes.po: nodes.h
-options.o: builtins.h
-options.o: nodes.h
-options.po: builtins.h
-options.po: nodes.h
-output.o: syntax.h
-output.po: syntax.h
-parser.o: nodes.h
-parser.o: syntax.h
-parser.o: token.h
-parser.po: nodes.h
-parser.po: syntax.h
-parser.po: token.h
-printf.o: builtins.h
-printf.po: builtins.h
-redir.o: nodes.h
-redir.po: nodes.h
-show.o: nodes.h
-show.po: nodes.h
-syntax.o: syntax.c
-syntax.o: syntax.h
-syntax.po: syntax.c
-syntax.po: syntax.h
-test.o: builtins.h
-test.po: builtins.h
-trap.o: builtins.h
-trap.o: nodes.h
-trap.o: syntax.h
-trap.po: builtins.h
-trap.po: nodes.h
-trap.po: syntax.h
-var.o: builtins.h
-var.o: nodes.h
-var.o: syntax.h
-var.po: builtins.h
-var.po: nodes.h
-var.po: syntax.h
 .endif
diff --git a/sh/TOUR b/sh/TOUR
index e9bbe9b..6d180ed 100644
--- a/sh/TOUR
+++ b/sh/TOUR
@@ -1,5 +1,5 @@
 #	@(#)TOUR	8.1 (Berkeley) 5/31/93
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/TOUR 253650 2013-07-25 15:08:41Z jilles $
 
 NOTE -- This is the original TOUR paper distributed with ash and
 does not represent the current state of the shell.  It is provided anyway
diff --git a/sh/alias.c b/sh/alias.c
index a77ce99..4eb6f9e 100644
--- a/sh/alias.c
+++ b/sh/alias.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/alias.c 295868 2016-02-21 20:58:24Z jilles $");
 
 #include <stdlib.h>
 #include "shell.h"
@@ -144,9 +144,11 @@ rmaliases(void)
 struct alias *
 lookupalias(const char *name, int check)
 {
-	struct alias *ap = *hashalias(name);
+	struct alias *ap;
 
-	for (; ap; ap = ap->next) {
+	if (aliases == 0)
+		return (NULL);
+	for (ap = *hashalias(name); ap; ap = ap->next) {
 		if (equal(name, ap->name)) {
 			if (check && (ap->flag & ALIASINUSE))
 				return (NULL);
diff --git a/sh/alias.h b/sh/alias.h
index 546e91a..95a20ea 100644
--- a/sh/alias.h
+++ b/sh/alias.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)alias.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/alias.h 223060 2011-06-13 21:03:27Z jilles $
  */
 
 #define ALIASINUSE	1
diff --git a/sh/arith.h b/sh/arith.h
index 5b18bd6..3771fe1 100644
--- a/sh/arith.h
+++ b/sh/arith.h
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)arith.h	1.1 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/arith.h 223060 2011-06-13 21:03:27Z jilles $
  */
 
 #include "shell.h"
diff --git a/sh/arith_yacc.c b/sh/arith_yacc.c
index 5000c6b..20e1e43 100644
--- a/sh/arith_yacc.c
+++ b/sh/arith_yacc.c
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/arith_yacc.c 270246 2014-08-20 20:15:43Z jilles $");
 
 #include <limits.h>
 #include <errno.h>
diff --git a/sh/arith_yacc.h b/sh/arith_yacc.h
index ca92e6f..d386886 100644
--- a/sh/arith_yacc.h
+++ b/sh/arith_yacc.h
@@ -31,7 +31,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/arith_yacc.h 279503 2015-03-01 21:46:55Z jilles $
  */
 
 #define ARITH_ASS 1
diff --git a/sh/arith_yylex.c b/sh/arith_yylex.c
index f7eaf3e..9936852 100644
--- a/sh/arith_yylex.c
+++ b/sh/arith_yylex.c
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/arith_yylex.c 279503 2015-03-01 21:46:55Z jilles $");
 
 #include <inttypes.h>
 #include <stdlib.h>
diff --git a/sh/bltin/bltin.h b/sh/bltin/bltin.h
index a530ab7..b79cc43 100644
--- a/sh/bltin/bltin.h
+++ b/sh/bltin/bltin.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)bltin.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/bltin/bltin.h 279503 2015-03-01 21:46:55Z jilles $
  */
 
 /*
diff --git a/sh/bltin/echo.c b/sh/bltin/echo.c
index 457a4c7..3de6589 100644
--- a/sh/bltin/echo.c
+++ b/sh/bltin/echo.c
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/bltin/echo.c 127958 2004-04-06 20:06:54Z markm $");
 
 /*
  * Echo command.
diff --git a/sh/builtins.def b/sh/builtins.def
index 1cbeea9..dd113b6 100644
--- a/sh/builtins.def
+++ b/sh/builtins.def
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)builtins.def	8.4 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/builtins.def 288430 2015-09-30 21:32:29Z jilles $
 
 #
 # This file lists all the builtin commands.  The first column is the name
@@ -65,6 +65,7 @@ exportcmd	-s export -s readonly
 #exprcmd		expr
 falsecmd	false
 fgcmd -j	fg
+freebsd_wordexpcmd	freebsd_wordexp
 getoptscmd	getopts
 hashcmd		hash
 histcmd -h	fc
diff --git a/sh/cd.c b/sh/cd.c
index 88f03f5..67a80bd 100644
--- a/sh/cd.c
+++ b/sh/cd.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)cd.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/cd.c 294667 2016-01-24 17:01:34Z jilles $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -68,15 +68,13 @@ __FBSDID("$FreeBSD$");
 static int cdlogical(char *);
 static int cdphysical(char *);
 static int docd(char *, int, int);
-static char *getcomponent(void);
+static char *getcomponent(char **);
 static char *findcwd(char *);
 static void updatepwd(char *);
 static char *getpwd(void);
 static char *getpwd2(void);
 
 static char *curdir = NULL;	/* current working directory */
-static char *prevdir;		/* previous working directory */
-static char *cdcomppath;
 
 int
 cdcmd(int argc __unused, char **argv __unused)
@@ -112,11 +110,10 @@ cdcmd(int argc __unused, char **argv __unused)
 	if (*dest == '\0')
 		dest = ".";
 	if (dest[0] == '-' && dest[1] == '\0') {
-		dest = prevdir ? prevdir : curdir;
-		if (dest)
-			print = 1;
-		else
-			dest = ".";
+		dest = bltinlookup("OLDPWD", 1);
+		if (dest == NULL)
+			error("OLDPWD not set");
+		print = 1;
 	}
 	if (dest[0] == '/' ||
 	    (dest[0] == '.' && (dest[1] == '/' || dest[1] == '\0')) ||
@@ -179,6 +176,7 @@ cdlogical(char *dest)
 	char *p;
 	char *q;
 	char *component;
+	char *path;
 	struct stat statb;
 	int first;
 	int badstat;
@@ -189,14 +187,14 @@ cdlogical(char *dest)
 	 *  next time we get the value of the current directory.
 	 */
 	badstat = 0;
-	cdcomppath = stsavestr(dest);
+	path = stsavestr(dest);
 	STARTSTACKSTR(p);
 	if (*dest == '/') {
 		STPUTC('/', p);
-		cdcomppath++;
+		path++;
 	}
 	first = 1;
-	while ((q = getcomponent()) != NULL) {
+	while ((q = getcomponent(&path)) != NULL) {
 		if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
 			continue;
 		if (! first)
@@ -245,25 +243,25 @@ cdphysical(char *dest)
 }
 
 /*
- * Get the next component of the path name pointed to by cdcomppath.
- * This routine overwrites the string pointed to by cdcomppath.
+ * Get the next component of the path name pointed to by *path.
+ * This routine overwrites *path and the string pointed to by it.
  */
 static char *
-getcomponent(void)
+getcomponent(char **path)
 {
 	char *p;
 	char *start;
 
-	if ((p = cdcomppath) == NULL)
+	if ((p = *path) == NULL)
 		return NULL;
-	start = cdcomppath;
+	start = *path;
 	while (*p != '/' && *p != '\0')
 		p++;
 	if (*p == '\0') {
-		cdcomppath = NULL;
+		*path = NULL;
 	} else {
 		*p++ = '\0';
-		cdcomppath = p;
+		*path = p;
 	}
 	return start;
 }
@@ -274,6 +272,7 @@ findcwd(char *dir)
 {
 	char *new;
 	char *p;
+	char *path;
 
 	/*
 	 * If our argument is NULL, we don't know the current directory
@@ -282,14 +281,14 @@ findcwd(char *dir)
 	 */
 	if (dir == NULL || curdir == NULL)
 		return getpwd2();
-	cdcomppath = stsavestr(dir);
+	path = stsavestr(dir);
 	STARTSTACKSTR(new);
 	if (*dir != '/') {
 		STPUTS(curdir, new);
 		if (STTOPC(new) == '/')
 			STUNPUTC(new);
 	}
-	while ((p = getcomponent()) != NULL) {
+	while ((p = getcomponent(&path)) != NULL) {
 		if (equal(p, "..")) {
 			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
 		} else if (*p != '\0' && ! equal(p, ".")) {
@@ -311,14 +310,15 @@ findcwd(char *dir)
 static void
 updatepwd(char *dir)
 {
+	char *prevdir;
+
 	hashcd();				/* update command hash table */
 
-	if (prevdir)
-		ckfree(prevdir);
+	setvar("PWD", dir, VEXPORT);
+	setvar("OLDPWD", curdir, VEXPORT);
 	prevdir = curdir;
 	curdir = dir ? savestr(dir) : NULL;
-	setvar("PWD", curdir, VEXPORT);
-	setvar("OLDPWD", prevdir, VEXPORT);
+	ckfree(prevdir);
 }
 
 int
diff --git a/sh/cd.h b/sh/cd.h
index 91fbc2b..6a2c5d3 100644
--- a/sh/cd.h
+++ b/sh/cd.h
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/cd.h 223060 2011-06-13 21:03:27Z jilles $
  */
 
 void	 pwd_init(int);
diff --git a/sh/error.c b/sh/error.c
index 6057226..65198dd 100644
--- a/sh/error.c
+++ b/sh/error.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/error.c 279569 2015-03-03 21:21:43Z jilles $");
 
 /*
  * Errors and exceptions.
diff --git a/sh/error.h b/sh/error.h
index a60b1fa..4aa7f37 100644
--- a/sh/error.h
+++ b/sh/error.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)error.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/error.h 276038 2014-12-21 23:09:59Z jilles $
  */
 
 /*
diff --git a/sh/eval.c b/sh/eval.c
index 51206d9..4184c06 100644
--- a/sh/eval.c
+++ b/sh/eval.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/eval.c 293635 2016-01-10 16:31:28Z jilles $");
 
 #include <paths.h>
 #include <signal.h>
@@ -82,7 +82,7 @@ static int builtin_flags;	/* evalcommand flags for builtins */
 
 
 char *commandname;
-struct strlist *cmdenviron;
+struct arglist *cmdenviron;
 int exitstatus;			/* exit status of last command */
 int oexitstatus;		/* saved exit status */
 
@@ -352,20 +352,19 @@ evalfor(union node *n, int flags)
 {
 	struct arglist arglist;
 	union node *argp;
-	struct strlist *sp;
+	int i;
 	int status;
 
-	arglist.lastp = &arglist.list;
+	emptyarglist(&arglist);
 	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
 		oexitstatus = exitstatus;
 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
 	}
-	*arglist.lastp = NULL;
 
 	loopnest++;
 	status = 0;
-	for (sp = arglist.list ; sp ; sp = sp->next) {
-		setvar(n->nfor.var, sp->text, 0);
+	for (i = 0; i < arglist.count; i++) {
+		setvar(n->nfor.var, arglist.args[i], 0);
 		evaltree(n->nfor.body, flags);
 		status = exitstatus;
 		if (evalskip) {
@@ -396,12 +395,12 @@ evalcase(union node *n)
 	union node *patp;
 	struct arglist arglist;
 
-	arglist.lastp = &arglist.list;
+	emptyarglist(&arglist);
 	oexitstatus = exitstatus;
 	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
 	for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) {
 		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
-			if (casematch(patp, arglist.list->text)) {
+			if (casematch(patp, arglist.args[0])) {
 				while (cp->nclist.next &&
 				    cp->type == NCLISTFALLTHRU &&
 				    cp->nclist.body == NULL)
@@ -497,10 +496,12 @@ exphere(union node *redir, struct arglist *fn)
 	struct jmploc *savehandler;
 	struct localvar *savelocalvars;
 	int need_longjmp = 0;
+	unsigned char saveoptreset;
 
 	redir->nhere.expdoc = "";
 	savelocalvars = localvars;
 	localvars = NULL;
+	saveoptreset = shellparam.reset;
 	forcelocal++;
 	savehandler = handler;
 	if (setjmp(jmploc.loc))
@@ -508,13 +509,14 @@ exphere(union node *redir, struct arglist *fn)
 	else {
 		handler = &jmploc;
 		expandarg(redir->nhere.doc, fn, 0);
-		redir->nhere.expdoc = fn->list->text;
+		redir->nhere.expdoc = fn->args[0];
 		INTOFF;
 	}
 	handler = savehandler;
 	forcelocal--;
 	poplocalvars();
 	localvars = savelocalvars;
+	shellparam.reset = saveoptreset;
 	if (need_longjmp)
 		longjmp(handler->loc, 1);
 	INTON;
@@ -532,7 +534,7 @@ expredir(union node *n)
 
 	for (redir = n ; redir ; redir = redir->nfile.next) {
 		struct arglist fn;
-		fn.lastp = &fn.list;
+		emptyarglist(&fn);
 		switch (redir->type) {
 		case NFROM:
 		case NTO:
@@ -540,13 +542,13 @@ expredir(union node *n)
 		case NAPPEND:
 		case NCLOBBER:
 			expandarg(redir->nfile.fname, &fn, EXP_TILDE);
-			redir->nfile.expfname = fn.list->text;
+			redir->nfile.expfname = fn.args[0];
 			break;
 		case NFROMFD:
 		case NTOFD:
 			if (redir->ndup.vname) {
 				expandarg(redir->ndup.vname, &fn, EXP_TILDE);
-				fixredir(redir, fn.list->text, 1);
+				fixredir(redir, fn.args[0], 1);
 			}
 			break;
 		case NXHERE:
@@ -648,6 +650,7 @@ evalbackcmd(union node *n, struct backcmd *result)
 	struct jmploc jmploc;
 	struct jmploc *savehandler;
 	struct localvar *savelocalvars;
+	unsigned char saveoptreset;
 
 	result->fd = -1;
 	result->buf = NULL;
@@ -662,6 +665,7 @@ evalbackcmd(union node *n, struct backcmd *result)
 	if (is_valid_fast_cmdsubst(n)) {
 		savelocalvars = localvars;
 		localvars = NULL;
+		saveoptreset = shellparam.reset;
 		forcelocal++;
 		savehandler = handler;
 		if (setjmp(jmploc.loc)) {
@@ -672,6 +676,7 @@ evalbackcmd(union node *n, struct backcmd *result)
 				forcelocal--;
 				poplocalvars();
 				localvars = savelocalvars;
+				shellparam.reset = saveoptreset;
 				longjmp(handler->loc, 1);
 			}
 		} else {
@@ -682,6 +687,7 @@ evalbackcmd(union node *n, struct backcmd *result)
 		forcelocal--;
 		poplocalvars();
 		localvars = savelocalvars;
+		shellparam.reset = saveoptreset;
 	} else {
 		if (pipe(pip) < 0)
 			error("Pipe call failed: %s", strerror(errno));
@@ -751,30 +757,32 @@ isdeclarationcmd(struct narg *arg)
 }
 
 static void
-xtracecommand(struct arglist *varlist, struct arglist *arglist)
+xtracecommand(struct arglist *varlist, int argc, char **argv)
 {
-	struct strlist *sp;
 	char sep = 0;
-	const char *p, *ps4;
+	const char *text, *p, *ps4;
+	int i;
 
 	ps4 = expandstr(ps4val());
 	out2str(ps4 != NULL ? ps4 : ps4val());
-	for (sp = varlist->list ; sp ; sp = sp->next) {
+	for (i = 0; i < varlist->count; i++) {
+		text = varlist->args[i];
 		if (sep != 0)
 			out2c(' ');
-		p = strchr(sp->text, '=');
+		p = strchr(text, '=');
 		if (p != NULL) {
 			p++;
-			outbin(sp->text, p - sp->text, out2);
+			outbin(text, p - text, out2);
 			out2qstr(p);
 		} else
-			out2qstr(sp->text);
+			out2qstr(text);
 		sep = ' ';
 	}
-	for (sp = arglist->list ; sp ; sp = sp->next) {
+	for (i = 0; i < argc; i++) {
+		text = argv[i];
 		if (sep != 0)
 			out2c(' ');
-		out2qstr(sp->text);
+		out2qstr(text);
 		sep = ' ';
 	}
 	out2c('\n');
@@ -822,7 +830,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 	int argc;
 	char **envp;
 	int varflag;
-	struct strlist *sp;
 	int mode;
 	int pip[2];
 	struct cmdentry cmdentry;
@@ -838,16 +845,19 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 	int realstatus;
 	int do_clearcmdentry;
 	const char *path = pathval();
+	int i;
 
 	/* First expand the arguments. */
 	TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
-	arglist.lastp = &arglist.list;
-	varlist.lastp = &varlist.list;
+	emptyarglist(&arglist);
+	emptyarglist(&varlist);
 	varflag = 1;
 	jp = NULL;
 	do_clearcmdentry = 0;
 	oexitstatus = exitstatus;
 	exitstatus = 0;
+	/* Add one slot at the beginning for tryexec(). */
+	appendarglist(&arglist, nullstr);
 	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
 		if (varflag && isassignment(argp->narg.text)) {
 			expandarg(argp, varflag == 1 ? &varlist : &arglist,
@@ -857,29 +867,19 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 			varflag = isdeclarationcmd(&argp->narg) ? 2 : 0;
 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
 	}
-	*arglist.lastp = NULL;
-	*varlist.lastp = NULL;
+	appendarglist(&arglist, nullstr);
 	expredir(cmd->ncmd.redirect);
-	argc = 0;
-	for (sp = arglist.list ; sp ; sp = sp->next)
-		argc++;
-	/* Add one slot at the beginning for tryexec(). */
-	argv = stalloc(sizeof (char *) * (argc + 2));
-	argv++;
+	argc = arglist.count - 2;
+	argv = &arglist.args[1];
 
-	for (sp = arglist.list ; sp ; sp = sp->next) {
-		TRACE(("evalcommand arg: %s\n", sp->text));
-		*argv++ = sp->text;
-	}
-	*argv = NULL;
+	argv[argc] = NULL;
 	lastarg = NULL;
 	if (iflag && funcnest == 0 && argc > 0)
-		lastarg = argv[-1];
-	argv -= argc;
+		lastarg = argv[argc - 1];
 
 	/* Print the command if xflag is set. */
 	if (xflag)
-		xtracecommand(&varlist, &arglist);
+		xtracecommand(&varlist, argc, argv);
 
 	/* Now locate the command. */
 	if (argc == 0) {
@@ -895,9 +895,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 		 * Modify the command lookup path, if a PATH= assignment
 		 * is present
 		 */
-		for (sp = varlist.list ; sp ; sp = sp->next)
-			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
-				path = sp->text + sizeof(PATH) - 1;
+		for (i = 0; i < varlist.count; i++)
+			if (strncmp(varlist.args[i], PATH, sizeof(PATH) - 1) == 0) {
+				path = varlist.args[i] + sizeof(PATH) - 1;
 				/*
 				 * On `PATH=... command`, we need to make
 				 * sure that the command isn't using the
@@ -999,7 +999,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 		}
 		if (cmdentry.cmdtype == CMDNORMAL &&
 		    cmd->ncmd.redirect == NULL &&
-		    varlist.list == NULL &&
+		    varlist.count == 0 &&
 		    (mode == FORK_FG || mode == FORK_NOJOB) &&
 		    !disvforkset() && !iflag && !mflag) {
 			vforkexecshell(jp, argv, environment(), path,
@@ -1039,12 +1039,12 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 		reffunc(cmdentry.u.func);
 		savehandler = handler;
 		if (setjmp(jmploc.loc)) {
-			freeparam(&shellparam);
-			shellparam = saveparam;
 			popredir();
 			unreffunc(cmdentry.u.func);
 			poplocalvars();
 			localvars = savelocalvars;
+			freeparam(&shellparam);
+			shellparam = saveparam;
 			funcnest--;
 			handler = savehandler;
 			longjmp(handler->loc, 1);
@@ -1053,8 +1053,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 		funcnest++;
 		redirect(cmd->ncmd.redirect, REDIR_PUSH);
 		INTON;
-		for (sp = varlist.list ; sp ; sp = sp->next)
-			mklocal(sp->text);
+		for (i = 0; i < varlist.count; i++)
+			mklocal(varlist.args[i]);
 		exitstatus = oexitstatus;
 		evaltree(getfuncnode(cmdentry.u.func),
 		    flags & (EV_TESTED | EV_EXIT));
@@ -1087,7 +1087,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 		}
 		savecmdname = commandname;
 		savetopfile = getcurrentfile();
-		cmdenviron = varlist.list;
+		cmdenviron = &varlist;
 		e = -1;
 		savehandler = handler;
 		if (setjmp(jmploc.loc)) {
@@ -1152,8 +1152,8 @@ cmddone:
 		trputs("normal command:  ");  trargs(argv);
 #endif
 		redirect(cmd->ncmd.redirect, 0);
-		for (sp = varlist.list ; sp ; sp = sp->next)
-			setvareq(sp->text, VEXPORT|VSTACK);
+		for (i = 0; i < varlist.count; i++)
+			setvareq(varlist.args[i], VEXPORT|VSTACK);
 		envp = environment();
 		shellexec(argv, envp, path, cmdentry.u.index);
 		/*NOTREACHED*/
@@ -1336,6 +1336,8 @@ truecmd(int argc __unused, char **argv __unused)
 int
 execcmd(int argc, char **argv)
 {
+	int i;
+
 	/*
 	 * Because we have historically not supported any options,
 	 * only treat "--" specially.
@@ -1343,13 +1345,11 @@ execcmd(int argc, char **argv)
 	if (argc > 1 && strcmp(argv[1], "--") == 0)
 		argc--, argv++;
 	if (argc > 1) {
-		struct strlist *sp;
-
 		iflag = 0;		/* exit on error */
 		mflag = 0;
 		optschanged();
-		for (sp = cmdenviron; sp ; sp = sp->next)
-			setvareq(sp->text, VEXPORT|VSTACK);
+		for (i = 0; i < cmdenviron->count; i++)
+			setvareq(cmdenviron->args[i], VEXPORT|VSTACK);
 		shellexec(argv + 1, environment(), pathval(), 0);
 
 	}
diff --git a/sh/eval.h b/sh/eval.h
index d4092be..c1045e3 100644
--- a/sh/eval.h
+++ b/sh/eval.h
@@ -30,13 +30,13 @@
  * SUCH DAMAGE.
  *
  *	@(#)eval.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/eval.h 289159 2015-10-11 21:33:00Z jilles $
  */
 
 extern char *commandname;	/* currently executing command */
 extern int exitstatus;		/* exit status of last command */
 extern int oexitstatus;		/* saved exit status */
-extern struct strlist *cmdenviron;  /* environment for builtin command */
+extern struct arglist *cmdenviron;  /* environment for builtin command */
 
 
 struct backcmd {		/* result of evalbackcmd */
diff --git a/sh/exec.c b/sh/exec.c
index b6ffe5c..6544d70 100644
--- a/sh/exec.c
+++ b/sh/exec.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)exec.c	8.4 (Berkeley) 6/8/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/exec.c 296813 2016-03-13 22:54:14Z jilles $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -335,6 +335,7 @@ find_command(const char *name, struct cmdentry *entry, int act,
 	if (strchr(name, '/') != NULL) {
 		entry->cmdtype = CMDNORMAL;
 		entry->u.index = 0;
+		entry->special = 0;
 		return;
 	}
 
@@ -411,6 +412,7 @@ find_command(const char *name, struct cmdentry *entry, int act,
 			cmdp = &loc_cmd;
 		cmdp->cmdtype = CMDNORMAL;
 		cmdp->param.index = idx;
+		cmdp->special = 0;
 		INTON;
 		goto success;
 	}
@@ -423,6 +425,7 @@ find_command(const char *name, struct cmdentry *entry, int act,
 	}
 	entry->cmdtype = CMDUNKNOWN;
 	entry->u.index = 0;
+	entry->special = 0;
 	return;
 
 success:
@@ -442,12 +445,14 @@ success:
 int
 find_builtin(const char *name, int *special)
 {
-	const struct builtincmd *bp;
+	const unsigned char *bp;
+	size_t len;
 
-	for (bp = builtincmd ; bp->name ; bp++) {
-		if (*bp->name == *name && equal(bp->name, name)) {
-			*special = bp->special;
-			return bp->code;
+	len = strlen(name);
+	for (bp = builtincmd ; *bp ; bp += 2 + bp[0]) {
+		if (bp[0] == len && memcmp(bp + 2, name, len) == 0) {
+			*special = (bp[1] & BUILTIN_SPECIAL) != 0;
+			return bp[1] & ~BUILTIN_SPECIAL;
 		}
 	}
 	return -1;
@@ -589,6 +594,7 @@ addcmdentry(const char *name, struct cmdentry *entry)
 	}
 	cmdp->cmdtype = entry->cmdtype;
 	cmdp->param = entry->u;
+	cmdp->special = entry->special;
 	INTON;
 }
 
@@ -605,6 +611,7 @@ defun(const char *name, union node *func)
 	INTOFF;
 	entry.cmdtype = CMDFUNCTION;
 	entry.u.func = copyfunc(func);
+	entry.special = 0;
 	addcmdentry(name, &entry);
 	INTON;
 }
diff --git a/sh/exec.h b/sh/exec.h
index b57b2d5..0bd6df3 100644
--- a/sh/exec.h
+++ b/sh/exec.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)exec.h	8.3 (Berkeley) 6/8/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/exec.h 238468 2012-07-15 10:19:43Z jilles $
  */
 
 /* values of cmdtype */
diff --git a/sh/expand.c b/sh/expand.c
index 193d651..d29237b 100644
--- a/sh/expand.c
+++ b/sh/expand.c
@@ -3,6 +3,8 @@
  *	The Regents of the University of California.  All rights reserved.
  * Copyright (c) 1997-2005
  *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ * Copyright (c) 2010-2015
+ *	Jilles Tjoelker <jilles@stack.nl>.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
@@ -38,7 +40,7 @@ static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/expand.c 303586 2016-07-31 13:11:34Z jilles $");
 
 #include <sys/types.h>
 #include <sys/time.h>
@@ -79,46 +81,63 @@ __FBSDID("$FreeBSD$");
 #include "show.h"
 #include "builtins.h"
 
-/*
- * Structure specifying which parts of the string should be searched
- * for IFS characters.
- */
+enum wordstate { WORD_IDLE, WORD_WS_DELIMITED, WORD_QUOTEMARK };
 
-struct ifsregion {
-	struct ifsregion *next;	/* next region in list */
-	int begoff;		/* offset of start of region */
-	int endoff;		/* offset of end of region */
-	int inquotes;		/* search for nul bytes only */
+struct worddest {
+	struct arglist *list;
+	enum wordstate state;
 };
 
-
 static char *expdest;			/* output of current string */
 static struct nodelist *argbackq;	/* list of back quote expressions */
-static struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
-static struct ifsregion *ifslastp;	/* last struct in list */
-static struct arglist exparg;		/* holds expanded arg list */
-
-static char *argstr(char *, int);
-static char *exptilde(char *, int);
-static char *expari(char *);
-static void expbackq(union node *, int, int);
-static int subevalvar(char *, char *, int, int, int, int, int);
-static char *evalvar(char *, int);
+
+static const char *argstr(const char *, int, struct worddest *);
+static const char *exptilde(const char *, int);
+static const char *expari(const char *, int, struct worddest *);
+static void expbackq(union node *, int, int, struct worddest *);
+static void subevalvar_trim(const char *, int, int, int);
+static int subevalvar_misc(const char *, const char *, int, int, int);
+static const char *evalvar(const char *, int, struct worddest *);
 static int varisset(const char *, int);
-static void strtodest(const char *, int, int, int);
-static void varvalue(const char *, int, int, int);
-static void recordregion(int, int, int);
-static void removerecordregions(int);
-static void ifsbreakup(char *, struct arglist *);
-static void expandmeta(struct strlist *);
-static void expmeta(char *, char *);
-static void addfname(char *);
-static struct strlist *expsort(struct strlist *);
-static struct strlist *msort(struct strlist *, int);
-static int patmatch(const char *, const char *, int);
-static char *cvtnum(int, char *);
+static void strtodest(const char *, int, int, int, struct worddest *);
+static void reprocess(int, int, int, int, struct worddest *);
+static void varvalue(const char *, int, int, int, struct worddest *);
+static void expandmeta(char *, struct arglist *);
+static void expmeta(char *, char *, struct arglist *);
+static int expsortcmp(const void *, const void *);
+static int patmatch(const char *, const char *);
+static void cvtnum(int, char *);
 static int collate_range_cmp(wchar_t, wchar_t);
 
+void
+emptyarglist(struct arglist *list)
+{
+
+	list->args = list->smallarg;
+	list->count = 0;
+	list->capacity = sizeof(list->smallarg) / sizeof(list->smallarg[0]);
+}
+
+void
+appendarglist(struct arglist *list, char *str)
+{
+	char **newargs;
+	int newcapacity;
+
+	if (list->count >= list->capacity) {
+		newcapacity = list->capacity * 2;
+		if (newcapacity < 16)
+			newcapacity = 16;
+		if (newcapacity > INT_MAX / (int)sizeof(newargs[0]))
+			error("Too many entries in arglist");
+		newargs = stalloc(newcapacity * sizeof(newargs[0]));
+		memcpy(newargs, list->args, list->count * sizeof(newargs[0]));
+		list->args = newargs;
+		list->capacity = newcapacity;
+	}
+	list->args[list->count++] = str;
+}
+
 static int
 collate_range_cmp(wchar_t c1, wchar_t c2)
 {
@@ -142,6 +161,53 @@ stputs_quotes(const char *data, const char *syntax, char *p)
 }
 #define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p)
 
+static char *
+nextword(char c, int flag, char *p, struct worddest *dst)
+{
+	int is_ws;
+
+	is_ws = c == '\t' || c == '\n' || c == ' ';
+	if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK :
+	    dst->state != WORD_WS_DELIMITED) || c == '\0') {
+		STPUTC('\0', p);
+		if (flag & EXP_GLOB)
+			expandmeta(grabstackstr(p), dst->list);
+		else
+			appendarglist(dst->list, grabstackstr(p));
+		dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE;
+	} else if (!is_ws && dst->state == WORD_WS_DELIMITED)
+		dst->state = WORD_IDLE;
+	/* Reserve space while the stack string is empty. */
+	appendarglist(dst->list, NULL);
+	dst->list->count--;
+	STARTSTACKSTR(p);
+	return p;
+}
+#define NEXTWORD(c, flag, p, dstlist) p = nextword(c, flag, p, dstlist)
+
+static char *
+stputs_split(const char *data, const char *syntax, int flag, char *p,
+    struct worddest *dst)
+{
+	const char *ifs;
+	char c;
+
+	ifs = ifsset() ? ifsval() : " \t\n";
+	while (*data) {
+		CHECKSTRSPACE(2, p);
+		c = *data++;
+		if (strchr(ifs, c) != NULL) {
+			NEXTWORD(c, flag, p, dst);
+			continue;
+		}
+		if (flag & EXP_GLOB && syntax[(int)c] == CCTL)
+			USTPUTC(CTLESC, p);
+		USTPUTC(c, p);
+	}
+	return (p);
+}
+#define STPUTS_SPLIT(data, syntax, flag, p, dst) p = stputs_split((data), syntax, flag, p, dst)
+
 /*
  * Perform expansions on an argument, placing the resulting list of arguments
  * in arglist.  Parameter expansion, command substitution and arithmetic
@@ -157,45 +223,31 @@ stputs_quotes(const char *data, const char *syntax, char *p)
 void
 expandarg(union node *arg, struct arglist *arglist, int flag)
 {
-	struct strlist *sp;
-	char *p;
+	struct worddest exparg;
 
+	if (fflag)
+		flag &= ~EXP_GLOB;
 	argbackq = arg->narg.backquote;
+	exparg.list = arglist;
+	exparg.state = WORD_IDLE;
 	STARTSTACKSTR(expdest);
-	ifsfirst.next = NULL;
-	ifslastp = NULL;
-	argstr(arg->narg.text, flag);
+	argstr(arg->narg.text, flag, &exparg);
 	if (arglist == NULL) {
 		STACKSTRNUL(expdest);
 		return;			/* here document expanded */
 	}
-	STPUTC('\0', expdest);
-	p = grabstackstr(expdest);
-	exparg.lastp = &exparg.list;
-	if (flag & EXP_FULL) {
-		ifsbreakup(p, &exparg);
-		*exparg.lastp = NULL;
-		exparg.lastp = &exparg.list;
-		expandmeta(exparg.list);
-	} else {
-		sp = (struct strlist *)stalloc(sizeof (struct strlist));
-		sp->text = p;
-		*exparg.lastp = sp;
-		exparg.lastp = &sp->next;
-	}
-	while (ifsfirst.next != NULL) {
-		struct ifsregion *ifsp;
-		INTOFF;
-		ifsp = ifsfirst.next->next;
-		ckfree(ifsfirst.next);
-		ifsfirst.next = ifsp;
-		INTON;
-	}
-	*exparg.lastp = NULL;
-	if (exparg.list) {
-		*arglist->lastp = exparg.list;
-		arglist->lastp = exparg.lastp;
+	if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() ||
+	    exparg.state == WORD_QUOTEMARK) {
+		STPUTC('\0', expdest);
+		if (flag & EXP_SPLIT) {
+			if (flag & EXP_GLOB)
+				expandmeta(grabstackstr(expdest), exparg.list);
+			else
+				appendarglist(exparg.list, grabstackstr(expdest));
+		}
 	}
+	if ((flag & EXP_SPLIT) == 0)
+		appendarglist(arglist, grabstackstr(expdest));
 }
 
 
@@ -205,15 +257,16 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
  * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE.
  * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'.
  * This is used to expand word in ${var+word} etc.
- * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC
+ * If EXP_GLOB or EXP_CASE are set, keep and/or generate CTLESC
  * characters to allow for further processing.
- * If EXP_FULL is set, also preserve CTLQUOTEMARK characters.
+ *
+ * If EXP_SPLIT is set, dst receives any complete words produced.
  */
-static char *
-argstr(char *p, int flag)
+static const char *
+argstr(const char *p, int flag, struct worddest *dst)
 {
 	char c;
-	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
+	int quotes = flag & (EXP_GLOB | EXP_CASE);	/* do CTLESC */
 	int firsteq = 1;
 	int split_lit;
 	int lit_quoted;
@@ -234,34 +287,36 @@ argstr(char *p, int flag)
 		case CTLQUOTEMARK:
 			lit_quoted = 1;
 			/* "$@" syntax adherence hack */
-			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
+			if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 &&
+			    p[2] == '@' && p[3] == '=')
 				break;
-			if ((flag & EXP_FULL) != 0)
-				USTPUTC(c, expdest);
+			if ((flag & EXP_SPLIT) != 0 && expdest == stackblock())
+				dst->state = WORD_QUOTEMARK;
 			break;
 		case CTLQUOTEEND:
 			lit_quoted = 0;
 			break;
 		case CTLESC:
-			if (quotes)
-				USTPUTC(c, expdest);
 			c = *p++;
+			if (split_lit && !lit_quoted &&
+			    strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) {
+				NEXTWORD(c, flag, expdest, dst);
+				break;
+			}
+			if (quotes)
+				USTPUTC(CTLESC, expdest);
 			USTPUTC(c, expdest);
-			if (split_lit && !lit_quoted)
-				recordregion(expdest - stackblock() -
-				    (quotes ? 2 : 1),
-				    expdest - stackblock(), 0);
 			break;
 		case CTLVAR:
-			p = evalvar(p, flag);
+			p = evalvar(p, flag, dst);
 			break;
 		case CTLBACKQ:
 		case CTLBACKQ|CTLQUOTE:
-			expbackq(argbackq->n, c & CTLQUOTE, flag);
+			expbackq(argbackq->n, c & CTLQUOTE, flag, dst);
 			argbackq = argbackq->next;
 			break;
 		case CTLARI:
-			p = expari(p);
+			p = expari(p, flag, dst);
 			break;
 		case ':':
 		case '=':
@@ -269,10 +324,12 @@ argstr(char *p, int flag)
 			 * sort of a hack - expand tildes in variable
 			 * assignments (after the first '=' and after ':'s).
 			 */
+			if (split_lit && !lit_quoted &&
+			    strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) {
+				NEXTWORD(c, flag, expdest, dst);
+				break;
+			}
 			USTPUTC(c, expdest);
-			if (split_lit && !lit_quoted)
-				recordregion(expdest - stackblock() - 1,
-				    expdest - stackblock(), 0);
 			if (flag & EXP_VARTILDE && *p == '~' &&
 			    (c != '=' || firsteq)) {
 				if (c == '=')
@@ -281,10 +338,12 @@ argstr(char *p, int flag)
 			}
 			break;
 		default:
+			if (split_lit && !lit_quoted &&
+			    strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) {
+				NEXTWORD(c, flag, expdest, dst);
+				break;
+			}
 			USTPUTC(c, expdest);
-			if (split_lit && !lit_quoted)
-				recordregion(expdest - stackblock() - 1,
-				    expdest - stackblock(), 0);
 		}
 	}
 }
@@ -293,12 +352,15 @@ argstr(char *p, int flag)
  * Perform tilde expansion, placing the result in the stack string and
  * returning the next position in the input string to process.
  */
-static char *
-exptilde(char *p, int flag)
+static const char *
+exptilde(const char *p, int flag)
 {
-	char c, *startp = p;
+	char c;
+	const char *startp = p;
+	const char *user;
 	struct passwd *pw;
 	char *home;
+	int len;
 
 	for (;;) {
 		c = *p;
@@ -318,17 +380,20 @@ exptilde(char *p, int flag)
 		case '\0':
 		case '/':
 		case CTLENDVAR:
-			*p = '\0';
-			if (*(startp+1) == '\0') {
+			len = p - startp - 1;
+			STPUTBIN(startp + 1, len, expdest);
+			STACKSTRNUL(expdest);
+			user = expdest - len;
+			if (*user == '\0') {
 				home = lookupvar("HOME");
 			} else {
-				pw = getpwnam(startp+1);
+				pw = getpwnam(user);
 				home = pw != NULL ? pw->pw_dir : NULL;
 			}
-			*p = c;
+			STADJUST(-len, expdest);
 			if (home == NULL || *home == '\0')
 				return (startp);
-			strtodest(home, flag, VSNORMAL, 1);
+			strtodest(home, flag, VSNORMAL, 1, NULL);
 			return (p);
 		}
 		p++;
@@ -336,51 +401,11 @@ exptilde(char *p, int flag)
 }
 
 
-static void
-removerecordregions(int endoff)
-{
-	if (ifslastp == NULL)
-		return;
-
-	if (ifsfirst.endoff > endoff) {
-		while (ifsfirst.next != NULL) {
-			struct ifsregion *ifsp;
-			INTOFF;
-			ifsp = ifsfirst.next->next;
-			ckfree(ifsfirst.next);
-			ifsfirst.next = ifsp;
-			INTON;
-		}
-		if (ifsfirst.begoff > endoff)
-			ifslastp = NULL;
-		else {
-			ifslastp = &ifsfirst;
-			ifsfirst.endoff = endoff;
-		}
-		return;
-	}
-
-	ifslastp = &ifsfirst;
-	while (ifslastp->next && ifslastp->next->begoff < endoff)
-		ifslastp=ifslastp->next;
-	while (ifslastp->next != NULL) {
-		struct ifsregion *ifsp;
-		INTOFF;
-		ifsp = ifslastp->next->next;
-		ckfree(ifslastp->next);
-		ifslastp->next = ifsp;
-		INTON;
-	}
-	if (ifslastp->endoff > endoff)
-		ifslastp->endoff = endoff;
-}
-
 /*
  * Expand arithmetic expression.
- * Note that flag is not required as digits never require CTLESC characters.
  */
-static char *
-expari(char *p)
+static const char *
+expari(const char *p, int flag, struct worddest *dst)
 {
 	char *q, *start;
 	arith_t result;
@@ -390,8 +415,7 @@ expari(char *p)
 
 	quoted = *p++ == '"';
 	begoff = expdest - stackblock();
-	p = argstr(p, 0);
-	removerecordregions(begoff);
+	p = argstr(p, 0, NULL);
 	STPUTC('\0', expdest);
 	start = stackblock() + begoff;
 
@@ -408,7 +432,7 @@ expari(char *p)
 	adj = strlen(expdest);
 	STADJUST(adj, expdest);
 	if (!quoted)
-		recordregion(begoff, expdest - stackblock(), 0);
+		reprocess(expdest - adj - stackblock(), flag, VSNORMAL, 0, dst);
 	return p;
 }
 
@@ -417,41 +441,40 @@ expari(char *p)
  * Perform command substitution.
  */
 static void
-expbackq(union node *cmd, int quoted, int flag)
+expbackq(union node *cmd, int quoted, int flag, struct worddest *dst)
 {
 	struct backcmd in;
 	int i;
 	char buf[128];
 	char *p;
 	char *dest = expdest;
-	struct ifsregion saveifs, *savelastp;
 	struct nodelist *saveargbackq;
 	char lastc;
-	int startloc = dest - stackblock();
 	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
+	int quotes = flag & (EXP_GLOB | EXP_CASE);
 	size_t nnl;
+	const char *ifs;
 
 	INTOFF;
-	saveifs = ifsfirst;
-	savelastp = ifslastp;
 	saveargbackq = argbackq;
 	p = grabstackstr(dest);
 	evalbackcmd(cmd, &in);
 	ungrabstackstr(p, dest);
-	ifsfirst = saveifs;
-	ifslastp = savelastp;
 	argbackq = saveargbackq;
 
 	p = in.buf;
-	lastc = '\0';
 	nnl = 0;
+	if (!quoted && flag & EXP_SPLIT)
+		ifs = ifsset() ? ifsval() : " \t\n";
+	else
+		ifs = "";
 	/* Don't copy trailing newlines */
 	for (;;) {
 		if (--in.nleft < 0) {
 			if (in.fd < 0)
 				break;
-			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
+			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR)
+				;
 			TRACE(("expbackq: read returns %d\n", i));
 			if (i <= 0)
 				break;
@@ -459,15 +482,27 @@ expbackq(union node *cmd, int quoted, int flag)
 			in.nleft = i - 1;
 		}
 		lastc = *p++;
-		if (lastc != '\0') {
-			if (lastc == '\n') {
-				nnl++;
-			} else {
-				CHECKSTRSPACE(nnl + 2, dest);
-				while (nnl > 0) {
-					nnl--;
-					USTPUTC('\n', dest);
+		if (lastc == '\0')
+			continue;
+		if (lastc == '\n') {
+			nnl++;
+		} else {
+			if (nnl > 0) {
+				if (strchr(ifs, '\n') != NULL) {
+					NEXTWORD('\n', flag, dest, dst);
+					nnl = 0;
+				} else {
+					CHECKSTRSPACE(nnl + 2, dest);
+					while (nnl > 0) {
+						nnl--;
+						USTPUTC('\n', dest);
+					}
 				}
+			}
+			if (strchr(ifs, lastc) != NULL)
+				NEXTWORD(lastc, flag, dest, dst);
+			else {
+				CHECKSTRSPACE(2, dest);
 				if (quotes && syntax[(int)lastc] == CCTL)
 					USTPUTC(CTLESC, dest);
 				USTPUTC(lastc, dest);
@@ -481,8 +516,6 @@ expbackq(union node *cmd, int quoted, int flag)
 		ckfree(in.buf);
 	if (in.jp)
 		exitstatus = waitforjob(in.jp, (int *)NULL);
-	if (quoted == 0)
-		recordregion(startloc, dest - stackblock(), 0);
 	TRACE(("expbackq: size=%td: \"%.*s\"\n",
 		((dest - stackblock()) - startloc),
 		(int)((dest - stackblock()) - startloc),
@@ -504,109 +537,108 @@ recordleft(const char *str, const char *loc, char *startp)
 		*startp++ = *loc++;
 }
 
-static int
-subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
-  int varflags, int quotes)
+static void
+subevalvar_trim(const char *p, int strloc, int subtype, int startloc)
 {
 	char *startp;
 	char *loc = NULL;
-	char *q;
+	char *str;
 	int c = 0;
 	struct nodelist *saveargbackq = argbackq;
 	int amount;
 
-	argstr(p, (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX ||
-	    subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX ?
-	    EXP_CASE : 0) | EXP_TILDE);
+	argstr(p, EXP_CASE | EXP_TILDE, NULL);
 	STACKSTRNUL(expdest);
 	argbackq = saveargbackq;
 	startp = stackblock() + startloc;
-	if (str == NULL)
-	    str = stackblock() + strloc;
+	str = stackblock() + strloc;
 
 	switch (subtype) {
-	case VSASSIGN:
-		setvar(str, startp, 0);
-		amount = startp - expdest;
-		STADJUST(amount, expdest);
-		varflags &= ~VSNUL;
-		return 1;
-
-	case VSQUESTION:
-		if (*p != CTLENDVAR) {
-			outfmt(out2, "%s\n", startp);
-			error((char *)NULL);
-		}
-		error("%.*s: parameter %snot set", (int)(p - str - 1),
-		      str, (varflags & VSNUL) ? "null or " : "");
-		return 0;
-
 	case VSTRIMLEFT:
 		for (loc = startp; loc < str; loc++) {
 			c = *loc;
 			*loc = '\0';
-			if (patmatch(str, startp, quotes)) {
+			if (patmatch(str, startp)) {
 				*loc = c;
 				recordleft(str, loc, startp);
-				return 1;
+				return;
 			}
 			*loc = c;
-			if (quotes && *loc == CTLESC)
-				loc++;
 		}
-		return 0;
+		break;
 
 	case VSTRIMLEFTMAX:
 		for (loc = str - 1; loc >= startp;) {
 			c = *loc;
 			*loc = '\0';
-			if (patmatch(str, startp, quotes)) {
+			if (patmatch(str, startp)) {
 				*loc = c;
 				recordleft(str, loc, startp);
-				return 1;
+				return;
 			}
 			*loc = c;
 			loc--;
-			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
-				for (q = startp; q < loc; q++)
-					if (*q == CTLESC)
-						q++;
-				if (q > loc)
-					loc--;
-			}
 		}
-		return 0;
+		break;
 
 	case VSTRIMRIGHT:
 		for (loc = str - 1; loc >= startp;) {
-			if (patmatch(str, loc, quotes)) {
+			if (patmatch(str, loc)) {
 				amount = loc - expdest;
 				STADJUST(amount, expdest);
-				return 1;
+				return;
 			}
 			loc--;
-			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
-				for (q = startp; q < loc; q++)
-					if (*q == CTLESC)
-						q++;
-				if (q > loc)
-					loc--;
-			}
 		}
-		return 0;
+		break;
 
 	case VSTRIMRIGHTMAX:
 		for (loc = startp; loc < str - 1; loc++) {
-			if (patmatch(str, loc, quotes)) {
+			if (patmatch(str, loc)) {
 				amount = loc - expdest;
 				STADJUST(amount, expdest);
-				return 1;
+				return;
 			}
-			if (quotes && *loc == CTLESC)
-				loc++;
 		}
-		return 0;
+		break;
+
+
+	default:
+		abort();
+	}
+	amount = (expdest - stackblock() - strloc) + 1;
+	STADJUST(-amount, expdest);
+}
+
+
+static int
+subevalvar_misc(const char *p, const char *var, int subtype, int startloc,
+  int varflags)
+{
+	char *startp;
+	struct nodelist *saveargbackq = argbackq;
+	int amount;
 
+	argstr(p, EXP_TILDE, NULL);
+	STACKSTRNUL(expdest);
+	argbackq = saveargbackq;
+	startp = stackblock() + startloc;
+
+	switch (subtype) {
+	case VSASSIGN:
+		setvar(var, startp, 0);
+		amount = startp - expdest;
+		STADJUST(amount, expdest);
+		return 1;
+
+	case VSQUESTION:
+		if (*p != CTLENDVAR) {
+			outfmt(out2, "%s\n", startp);
+			error((char *)NULL);
+		}
+		error("%.*s: parameter %snot set", (int)(p - var - 1),
+		      var, (varflags & VSNUL) ? "null or " : "");
+		return 0;
 
 	default:
 		abort();
@@ -619,12 +651,12 @@ subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
  * input string.
  */
 
-static char *
-evalvar(char *p, int flag)
+static const char *
+evalvar(const char *p, int flag, struct worddest *dst)
 {
 	int subtype;
 	int varflags;
-	char *var;
+	const char *var;
 	const char *val;
 	int patloc;
 	int c;
@@ -633,9 +665,7 @@ evalvar(char *p, int flag)
 	int startloc;
 	int varlen;
 	int varlenb;
-	int easy;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
-	int record = 0;
+	char buf[21];
 
 	varflags = (unsigned char)*p++;
 	subtype = varflags & VSTYPE;
@@ -677,10 +707,16 @@ again: /* jump here after setting a variable with ${var=text} */
 	if (set && subtype != VSPLUS) {
 		/* insert the value of the variable */
 		if (special) {
-			if (varflags & VSLINENO)
-				STPUTBIN(var, p - var - 1, expdest);
-			else
-				varvalue(var, varflags & VSQUOTE, subtype, flag);
+			if (varflags & VSLINENO) {
+				if (p - var > (ptrdiff_t)sizeof(buf))
+					abort();
+				memcpy(buf, var, p - var - 1);
+				buf[p - var - 1] = '\0';
+				strtodest(buf, flag, subtype,
+				    varflags & VSQUOTE, dst);
+			} else
+				varvalue(var, varflags & VSQUOTE, subtype, flag,
+				    dst);
 			if (subtype == VSLENGTH) {
 				varlenb = expdest - stackblock() - startloc;
 				varlen = varlenb;
@@ -701,35 +737,29 @@ again: /* jump here after setting a variable with ${var=text} */
 			}
 			else
 				strtodest(val, flag, subtype,
-				    varflags & VSQUOTE);
+				    varflags & VSQUOTE, dst);
 		}
 	}
 
 	if (subtype == VSPLUS)
 		set = ! set;
 
-	easy = ((varflags & VSQUOTE) == 0 ||
-		(*var == '@' && shellparam.nparam != 1));
-
-
 	switch (subtype) {
 	case VSLENGTH:
-		expdest = cvtnum(varlen, expdest);
-		record = 1;
+		cvtnum(varlen, buf);
+		strtodest(buf, flag, VSNORMAL, varflags & VSQUOTE, dst);
 		break;
 
 	case VSNORMAL:
-		record = easy;
 		break;
 
 	case VSPLUS:
 	case VSMINUS:
 		if (!set) {
-			argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) |
-			    (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0));
+			argstr(p, flag | (flag & EXP_SPLIT ? EXP_SPLIT_LIT : 0) |
+			    (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0), dst);
 			break;
 		}
-		record = easy;
 		break;
 
 	case VSTRIMLEFT:
@@ -744,32 +774,22 @@ again: /* jump here after setting a variable with ${var=text} */
 		 */
 		STPUTC('\0', expdest);
 		patloc = expdest - stackblock();
-		if (subevalvar(p, NULL, patloc, subtype,
-		    startloc, varflags, quotes) == 0) {
-			int amount = (expdest - stackblock() - patloc) + 1;
-			STADJUST(-amount, expdest);
-		}
-		/* Remove any recorded regions beyond start of variable */
-		removerecordregions(startloc);
-		record = 1;
+		subevalvar_trim(p, patloc, subtype, startloc);
+		reprocess(startloc, flag, VSNORMAL, varflags & VSQUOTE, dst);
+		if (flag & EXP_SPLIT && *var == '@' && varflags & VSQUOTE)
+			dst->state = WORD_QUOTEMARK;
 		break;
 
 	case VSASSIGN:
 	case VSQUESTION:
 		if (!set) {
-			if (subevalvar(p, var, 0, subtype, startloc, varflags,
-			    quotes)) {
+			if (subevalvar_misc(p, var, subtype, startloc,
+			    varflags)) {
 				varflags &= ~VSNUL;
-				/*
-				 * Remove any recorded regions beyond
-				 * start of variable
-				 */
-				removerecordregions(startloc);
 				goto again;
 			}
 			break;
 		}
-		record = easy;
 		break;
 
 	case VSERROR:
@@ -781,11 +801,6 @@ again: /* jump here after setting a variable with ${var=text} */
 		abort();
 	}
 
-	if (record)
-		recordregion(startloc, expdest - stackblock(),
-		    varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' &&
-		    (*var == '@' || *var == '*')));
-
 	if (subtype != VSNORMAL) {	/* skip to end of alternative */
 		int nesting = 1;
 		for (;;) {
@@ -851,26 +866,80 @@ varisset(const char *name, int nulok)
 }
 
 static void
-strtodest(const char *p, int flag, int subtype, int quoted)
+strtodest(const char *p, int flag, int subtype, int quoted,
+    struct worddest *dst)
 {
-	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH)
+	if (subtype == VSLENGTH || subtype == VSTRIMLEFT ||
+	    subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT ||
+	    subtype == VSTRIMRIGHTMAX)
+		STPUTS(p, expdest);
+	else if (flag & EXP_SPLIT && !quoted && dst != NULL)
+		STPUTS_SPLIT(p, BASESYNTAX, flag, expdest, dst);
+	else if (flag & (EXP_GLOB | EXP_CASE))
 		STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest);
 	else
 		STPUTS(p, expdest);
 }
 
+static void
+reprocess(int startloc, int flag, int subtype, int quoted,
+    struct worddest *dst)
+{
+	static char *buf = NULL;
+	static size_t buflen = 0;
+	char *startp;
+	size_t len, zpos, zlen;
+
+	startp = stackblock() + startloc;
+	len = expdest - startp;
+	if (len >= SIZE_MAX / 2)
+		abort();
+	INTOFF;
+	if (len >= buflen) {
+		ckfree(buf);
+		buf = NULL;
+	}
+	if (buflen < 128)
+		buflen = 128;
+	while (len >= buflen)
+		buflen <<= 1;
+	if (buf == NULL)
+		buf = ckmalloc(buflen);
+	INTON;
+	memcpy(buf, startp, len);
+	buf[len] = '\0';
+	STADJUST(-len, expdest);
+	for (zpos = 0;;) {
+		zlen = strlen(buf + zpos);
+		strtodest(buf + zpos, flag, subtype, quoted, dst);
+		zpos += zlen + 1;
+		if (zpos == len + 1)
+			break;
+		if (flag & EXP_SPLIT && (quoted || (zlen > 0 && zpos < len)))
+			NEXTWORD('\0', flag, expdest, dst);
+	}
+}
+
 /*
  * Add the value of a specialized variable to the stack string.
  */
 
 static void
-varvalue(const char *name, int quoted, int subtype, int flag)
+varvalue(const char *name, int quoted, int subtype, int flag,
+    struct worddest *dst)
 {
 	int num;
 	char *p;
 	int i;
+	int splitlater;
 	char sep[2];
 	char **ap;
+	char buf[(NSHORTOPTS > 10 ? NSHORTOPTS : 10) + 1];
+
+	if (subtype == VSLENGTH)
+		flag &= ~EXP_FULL;
+	splitlater = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX ||
+		subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX;
 
 	switch (*name) {
 	case '$':
@@ -886,18 +955,28 @@ varvalue(const char *name, int quoted, int subtype, int flag)
 		num = backgndpidval();
 		break;
 	case '-':
-		for (i = 0 ; i < NOPTS ; i++) {
-			if (optlist[i].val)
-				STPUTC(optlist[i].letter, expdest);
+		p = buf;
+		for (i = 0 ; i < NSHORTOPTS ; i++) {
+			if (optval[i])
+				*p++ = optletter[i];
 		}
+		*p = '\0';
+		strtodest(buf, flag, subtype, quoted, dst);
 		return;
 	case '@':
-		if (flag & EXP_FULL && quoted) {
+		if (flag & EXP_SPLIT && quoted) {
 			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
-				strtodest(p, flag, subtype, quoted);
-				if (*ap)
-					STPUTC('\0', expdest);
+				strtodest(p, flag, subtype, quoted, dst);
+				if (*ap) {
+					if (splitlater)
+						STPUTC('\0', expdest);
+					else
+						NEXTWORD('\0', flag, expdest,
+						    dst);
+				}
 			}
+			if (shellparam.nparam > 0)
+				dst->state = WORD_QUOTEMARK;
 			return;
 		}
 		/* FALLTHROUGH */
@@ -908,13 +987,17 @@ varvalue(const char *name, int quoted, int subtype, int flag)
 			sep[0] = ' ';
 		sep[1] = '\0';
 		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
-			strtodest(p, flag, subtype, quoted);
+			strtodest(p, flag, subtype, quoted, dst);
 			if (!*ap)
 				break;
 			if (sep[0])
-				strtodest(sep, flag, subtype, quoted);
-			else if (flag & EXP_FULL && !quoted && **ap != '\0')
-				STPUTC('\0', expdest);
+				strtodest(sep, flag, subtype, quoted, dst);
+			else if (flag & EXP_SPLIT && !quoted && **ap != '\0') {
+				if (splitlater)
+					STPUTC('\0', expdest);
+				else
+					NEXTWORD('\0', flag, expdest, dst);
+			}
 		}
 		return;
 	default:
@@ -926,205 +1009,52 @@ varvalue(const char *name, int quoted, int subtype, int flag)
 				p = shellparam.p[num - 1];
 			else
 				return;
-			strtodest(p, flag, subtype, quoted);
+			strtodest(p, flag, subtype, quoted, dst);
 		}
 		return;
 	}
-	expdest = cvtnum(num, expdest);
+	cvtnum(num, buf);
+	strtodest(buf, flag, subtype, quoted, dst);
 }
 
 
 
-/*
- * Record the fact that we have to scan this region of the
- * string for IFS characters.
- */
-
-static void
-recordregion(int start, int end, int inquotes)
-{
-	struct ifsregion *ifsp;
-
-	INTOFF;
-	if (ifslastp == NULL) {
-		ifsp = &ifsfirst;
-	} else {
-		if (ifslastp->endoff == start
-		    && ifslastp->inquotes == inquotes) {
-			/* extend previous area */
-			ifslastp->endoff = end;
-			INTON;
-			return;
-		}
-		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
-		ifslastp->next = ifsp;
-	}
-	ifslastp = ifsp;
-	ifslastp->next = NULL;
-	ifslastp->begoff = start;
-	ifslastp->endoff = end;
-	ifslastp->inquotes = inquotes;
-	INTON;
-}
-
-
-
-/*
- * Break the argument string into pieces based upon IFS and add the
- * strings to the argument list.  The regions of the string to be
- * searched for IFS characters have been stored by recordregion.
- * CTLESC characters are preserved but have little effect in this pass
- * other than escaping CTL* characters.  In particular, they do not escape
- * IFS characters: that should be done with the ifsregion mechanism.
- * CTLQUOTEMARK characters are used to preserve empty quoted strings.
- * This pass treats them as a regular character, making the string non-empty.
- * Later, they are removed along with the other CTL* characters.
- */
-static void
-ifsbreakup(char *string, struct arglist *arglist)
-{
-	struct ifsregion *ifsp;
-	struct strlist *sp;
-	char *start;
-	char *p;
-	char *q;
-	const char *ifs;
-	const char *ifsspc;
-	int had_param_ch = 0;
-
-	start = string;
-
-	if (ifslastp == NULL) {
-		/* Return entire argument, IFS doesn't apply to any of it */
-		sp = (struct strlist *)stalloc(sizeof *sp);
-		sp->text = start;
-		*arglist->lastp = sp;
-		arglist->lastp = &sp->next;
-		return;
-	}
-
-	ifs = ifsset() ? ifsval() : " \t\n";
-
-	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
-		p = string + ifsp->begoff;
-		while (p < string + ifsp->endoff) {
-			q = p;
-			if (*p == CTLESC)
-				p++;
-			if (ifsp->inquotes) {
-				/* Only NULs (should be from "$@") end args */
-				had_param_ch = 1;
-				if (*p != 0) {
-					p++;
-					continue;
-				}
-				ifsspc = NULL;
-			} else {
-				if (!strchr(ifs, *p)) {
-					had_param_ch = 1;
-					p++;
-					continue;
-				}
-				ifsspc = strchr(" \t\n", *p);
-
-				/* Ignore IFS whitespace at start */
-				if (q == start && ifsspc != NULL) {
-					p++;
-					start = p;
-					continue;
-				}
-				had_param_ch = 0;
-			}
-
-			/* Save this argument... */
-			*q = '\0';
-			sp = (struct strlist *)stalloc(sizeof *sp);
-			sp->text = start;
-			*arglist->lastp = sp;
-			arglist->lastp = &sp->next;
-			p++;
-
-			if (ifsspc != NULL) {
-				/* Ignore further trailing IFS whitespace */
-				for (; p < string + ifsp->endoff; p++) {
-					q = p;
-					if (*p == CTLESC)
-						p++;
-					if (strchr(ifs, *p) == NULL) {
-						p = q;
-						break;
-					}
-					if (strchr(" \t\n", *p) == NULL) {
-						p++;
-						break;
-					}
-				}
-			}
-			start = p;
-		}
-	}
-
-	/*
-	 * Save anything left as an argument.
-	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
-	 * generating 2 arguments, the second of which is empty.
-	 * Some recent clarification of the Posix spec say that it
-	 * should only generate one....
-	 */
-	if (had_param_ch || *start != 0) {
-		sp = (struct strlist *)stalloc(sizeof *sp);
-		sp->text = start;
-		*arglist->lastp = sp;
-		arglist->lastp = &sp->next;
-	}
-}
-
-
 static char expdir[PATH_MAX];
 #define expdir_end (expdir + sizeof(expdir))
 
 /*
  * Perform pathname generation and remove control characters.
- * At this point, the only control characters should be CTLESC and CTLQUOTEMARK.
- * The results are stored in the list exparg.
+ * At this point, the only control characters should be CTLESC.
+ * The results are stored in the list dstlist.
  */
 static void
-expandmeta(struct strlist *str)
+expandmeta(char *pattern, struct arglist *dstlist)
 {
 	char *p;
-	struct strlist **savelastp;
-	struct strlist *sp;
+	int firstmatch;
 	char c;
 
-	while (str) {
-		savelastp = exparg.lastp;
-		if (!fflag) {
-			p = str->text;
-			for (; (c = *p) != '\0'; p++) {
-				/* fast check for meta chars */
-				if (c == '*' || c == '?' || c == '[') {
-					INTOFF;
-					expmeta(expdir, str->text);
-					INTON;
-					break;
-				}
-			}
-		}
-		if (exparg.lastp == savelastp) {
-			/*
-			 * no matches
-			 */
-			*exparg.lastp = str;
-			rmescapes(str->text);
-			exparg.lastp = &str->next;
-		} else {
-			*exparg.lastp = NULL;
-			*savelastp = sp = expsort(*savelastp);
-			while (sp->next != NULL)
-				sp = sp->next;
-			exparg.lastp = &sp->next;
+	firstmatch = dstlist->count;
+	p = pattern;
+	for (; (c = *p) != '\0'; p++) {
+		/* fast check for meta chars */
+		if (c == '*' || c == '?' || c == '[') {
+			INTOFF;
+			expmeta(expdir, pattern, dstlist);
+			INTON;
+			break;
 		}
-		str = str->next;
+	}
+	if (dstlist->count == firstmatch) {
+		/*
+		 * no matches
+		 */
+		rmescapes(pattern);
+		appendarglist(dstlist, pattern);
+	} else {
+		qsort(&dstlist->args[firstmatch],
+		    dstlist->count - firstmatch,
+		    sizeof(dstlist->args[0]), expsortcmp);
 	}
 }
 
@@ -1134,7 +1064,7 @@ expandmeta(struct strlist *str)
  */
 
 static void
-expmeta(char *enddir, char *name)
+expmeta(char *enddir, char *name, struct arglist *arglist)
 {
 	const char *p;
 	const char *q;
@@ -1159,8 +1089,6 @@ expmeta(char *enddir, char *name)
 			if (*q == '!' || *q == '^')
 				q++;
 			for (;;) {
-				while (*q == CTLQUOTEMARK)
-					q++;
 				if (*q == CTLESC)
 					q++;
 				if (*q == '/' || *q == '\0')
@@ -1172,8 +1100,6 @@ expmeta(char *enddir, char *name)
 			}
 		} else if (*p == '\0')
 			break;
-		else if (*p == CTLQUOTEMARK)
-			continue;
 		else {
 			if (*p == CTLESC)
 				esc++;
@@ -1188,8 +1114,6 @@ expmeta(char *enddir, char *name)
 		if (enddir != expdir)
 			metaflag++;
 		for (p = name ; ; p++) {
-			if (*p == CTLQUOTEMARK)
-				continue;
 			if (*p == CTLESC)
 				p++;
 			*enddir++ = *p;
@@ -1199,15 +1123,13 @@ expmeta(char *enddir, char *name)
 				return;
 		}
 		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
-			addfname(expdir);
+			appendarglist(arglist, stsavestr(expdir));
 		return;
 	}
 	endname = name + (p - name);
 	if (start != name) {
 		p = name;
 		while (p < start) {
-			while (*p == CTLQUOTEMARK)
-				p++;
 			if (*p == CTLESC)
 				p++;
 			*enddir++ = *p++;
@@ -1236,8 +1158,6 @@ expmeta(char *enddir, char *name)
 	}
 	matchdot = 0;
 	p = start;
-	while (*p == CTLQUOTEMARK)
-		p++;
 	if (*p == CTLESC)
 		p++;
 	if (*p == '.')
@@ -1245,13 +1165,13 @@ expmeta(char *enddir, char *name)
 	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
 		if (dp->d_name[0] == '.' && ! matchdot)
 			continue;
-		if (patmatch(start, dp->d_name, 0)) {
+		if (patmatch(start, dp->d_name)) {
 			namlen = dp->d_namlen;
 			if (enddir + namlen + 1 > expdir_end)
 				continue;
 			memcpy(enddir, dp->d_name, namlen + 1);
 			if (atend)
-				addfname(expdir);
+				appendarglist(arglist, stsavestr(expdir));
 			else {
 				if (dp->d_type != DT_UNKNOWN &&
 				    dp->d_type != DT_DIR &&
@@ -1261,7 +1181,7 @@ expmeta(char *enddir, char *name)
 					continue;
 				enddir[namlen] = '/';
 				enddir[namlen + 1] = '\0';
-				expmeta(enddir + namlen + 1, endname);
+				expmeta(enddir + namlen + 1, endname, arglist);
 			}
 		}
 	}
@@ -1271,81 +1191,13 @@ expmeta(char *enddir, char *name)
 }
 
 
-/*
- * Add a file name to the list.
- */
-
-static void
-addfname(char *name)
+static int
+expsortcmp(const void *p1, const void *p2)
 {
-	char *p;
-	struct strlist *sp;
+	const char *s1 = *(const char * const *)p1;
+	const char *s2 = *(const char * const *)p2;
 
-	p = stsavestr(name);
-	sp = (struct strlist *)stalloc(sizeof *sp);
-	sp->text = p;
-	*exparg.lastp = sp;
-	exparg.lastp = &sp->next;
-}
-
-
-/*
- * Sort the results of file name expansion.  It calculates the number of
- * strings to sort and then calls msort (short for merge sort) to do the
- * work.
- */
-
-static struct strlist *
-expsort(struct strlist *str)
-{
-	int len;
-	struct strlist *sp;
-
-	len = 0;
-	for (sp = str ; sp ; sp = sp->next)
-		len++;
-	return msort(str, len);
-}
-
-
-static struct strlist *
-msort(struct strlist *list, int len)
-{
-	struct strlist *p, *q = NULL;
-	struct strlist **lpp;
-	int half;
-	int n;
-
-	if (len <= 1)
-		return list;
-	half = len >> 1;
-	p = list;
-	for (n = half ; --n >= 0 ; ) {
-		q = p;
-		p = p->next;
-	}
-	q->next = NULL;			/* terminate first half of list */
-	q = msort(list, half);		/* sort first half of list */
-	p = msort(p, len - half);		/* sort second half */
-	lpp = &list;
-	for (;;) {
-		if (strcmp(p->text, q->text) < 0) {
-			*lpp = p;
-			lpp = &p->next;
-			if ((p = *lpp) == NULL) {
-				*lpp = q;
-				break;
-			}
-		} else {
-			*lpp = q;
-			lpp = &q->next;
-			if ((q = *lpp) == NULL) {
-				*lpp = p;
-				break;
-			}
-		}
-	}
-	return list;
+	return (strcoll(s1, s2));
 }
 
 
@@ -1403,7 +1255,7 @@ match_charclass(const char *p, wchar_t chr, const char **end)
  */
 
 static int
-patmatch(const char *pattern, const char *string, int squoted)
+patmatch(const char *pattern, const char *string)
 {
 	const char *p, *q, *end;
 	const char *bt_p, *bt_q;
@@ -1421,16 +1273,10 @@ patmatch(const char *pattern, const char *string, int squoted)
 				goto backtrack;
 			return 1;
 		case CTLESC:
-			if (squoted && *q == CTLESC)
-				q++;
 			if (*q++ != *p++)
 				goto backtrack;
 			break;
-		case CTLQUOTEMARK:
-			continue;
 		case '?':
-			if (squoted && *q == CTLESC)
-				q++;
 			if (*q == '\0')
 				return 0;
 			if (localeisutf8) {
@@ -1442,11 +1288,11 @@ patmatch(const char *pattern, const char *string, int squoted)
 				if (wc == 0)
 					goto backtrack;
 			} else
-				wc = (unsigned char)*q++;
+				q++;
 			break;
 		case '*':
 			c = *p;
-			while (c == CTLQUOTEMARK || c == '*')
+			while (c == '*')
 				c = *++p;
 			/*
 			 * If the pattern ends here, we know the string
@@ -1464,29 +1310,17 @@ patmatch(const char *pattern, const char *string, int squoted)
 			bt_q = q;
 			break;
 		case '[': {
-			const char *endp;
+			const char *savep, *saveq;
 			int invert, found;
 			wchar_t chr;
 
-			endp = p;
-			if (*endp == '!' || *endp == '^')
-				endp++;
-			do {
-				while (*endp == CTLQUOTEMARK)
-					endp++;
-				if (*endp == 0)
-					goto dft;		/* no matching ] */
-				if (*endp == CTLESC)
-					endp++;
-			} while (*++endp != ']');
+			savep = p, saveq = q;
 			invert = 0;
 			if (*p == '!' || *p == '^') {
 				invert++;
 				p++;
 			}
 			found = 0;
-			if (squoted && *q == CTLESC)
-				q++;
 			if (*q == '\0')
 				return 0;
 			if (localeisutf8) {
@@ -1497,8 +1331,11 @@ patmatch(const char *pattern, const char *string, int squoted)
 				chr = (unsigned char)*q++;
 			c = *p++;
 			do {
-				if (c == CTLQUOTEMARK)
-					continue;
+				if (c == '\0') {
+					p = savep, q = saveq;
+					c = '[';
+					goto dft;
+				}
 				if (c == '[' && *p == ':') {
 					found |= match_charclass(p, chr, &end);
 					if (end != NULL)
@@ -1515,8 +1352,6 @@ patmatch(const char *pattern, const char *string, int squoted)
 					wc = (unsigned char)c;
 				if (*p == '-' && p[1] != ']') {
 					p++;
-					while (*p == CTLQUOTEMARK)
-						p++;
 					if (*p == CTLESC)
 						p++;
 					if (localeisutf8) {
@@ -1539,8 +1374,6 @@ patmatch(const char *pattern, const char *string, int squoted)
 			break;
 		}
 dft:	        default:
-			if (squoted && *q == CTLESC)
-				q++;
 			if (*q == '\0')
 				return 0;
 			if (*q++ == c)
@@ -1553,8 +1386,6 @@ backtrack:
 			 */
 			if (bt_p == NULL)
 				return 0;
-			if (squoted && *bt_q == CTLESC)
-				bt_q++;
 			if (*bt_q == '\0')
 				return 0;
 			bt_q++;
@@ -1610,11 +1441,10 @@ casematch(union node *pattern, const char *val)
 	setstackmark(&smark);
 	argbackq = pattern->narg.backquote;
 	STARTSTACKSTR(expdest);
-	ifslastp = NULL;
-	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
+	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE, NULL);
 	STPUTC('\0', expdest);
 	p = grabstackstr(expdest);
-	result = patmatch(p, val, 0);
+	result = patmatch(p, val);
 	popstackmark(&smark);
 	return result;
 }
@@ -1623,7 +1453,7 @@ casematch(union node *pattern, const char *val)
  * Our own itoa().
  */
 
-static char *
+static void
 cvtnum(int num, char *buf)
 {
 	char temp[32];
@@ -1639,8 +1469,7 @@ cvtnum(int num, char *buf)
 	if (neg)
 		*--p = '-';
 
-	STPUTS(p, buf);
-	return buf;
+	memcpy(buf, p, temp + 32 - p);
 }
 
 /*
@@ -1661,3 +1490,56 @@ wordexpcmd(int argc, char **argv)
 		outbin(argv[i], strlen(argv[i]) + 1, out1);
         return (0);
 }
+
+/*
+ * Do most of the work for wordexp(3), new version.
+ */
+
+int
+freebsd_wordexpcmd(int argc __unused, char **argv __unused)
+{
+	struct arglist arglist;
+	union node *args, *n;
+	size_t len;
+	int ch;
+	int protected = 0;
+	int fd = -1;
+	int i;
+
+	while ((ch = nextopt("f:p")) != '\0') {
+		switch (ch) {
+		case 'f':
+			fd = number(shoptarg);
+			break;
+		case 'p':
+			protected = 1;
+			break;
+		}
+	}
+	if (*argptr != NULL)
+		error("wrong number of arguments");
+	if (fd < 0)
+		error("missing fd");
+	INTOFF;
+	setinputfd(fd, 1);
+	INTON;
+	args = parsewordexp();
+	popfile(); /* will also close fd */
+	if (protected)
+		for (n = args; n != NULL; n = n->narg.next) {
+			if (n->narg.backquote != NULL) {
+				outcslow('C', out1);
+				error("command substitution disabled");
+			}
+		}
+	outcslow(' ', out1);
+	emptyarglist(&arglist);
+	for (n = args; n != NULL; n = n->narg.next)
+		expandarg(n, &arglist, EXP_FULL | EXP_TILDE);
+	for (i = 0, len = 0; i < arglist.count; i++)
+		len += strlen(arglist.args[i]);
+	out1fmt("%016x %016zx", arglist.count, len);
+	for (i = 0; i < arglist.count; i++)
+		outbin(arglist.args[i], strlen(arglist.args[i]) + 1, out1);
+	return (0);
+}
diff --git a/sh/expand.h b/sh/expand.h
index 93c80f3..0de4c02 100644
--- a/sh/expand.h
+++ b/sh/expand.h
@@ -30,31 +30,32 @@
  * SUCH DAMAGE.
  *
  *	@(#)expand.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/expand.h 292994 2015-12-31 18:47:54Z jilles $
  */
 
-struct strlist {
-	struct strlist *next;
-	char *text;
-};
-
-
 struct arglist {
-	struct strlist *list;
-	struct strlist **lastp;
+	char **args;
+	int count;
+	int capacity;
+	char *smallarg[1];
 };
 
 /*
  * expandarg() flags
  */
-#define EXP_FULL	0x1	/* perform word splitting & file globbing */
+#define EXP_SPLIT	0x1	/* perform word splitting */
 #define EXP_TILDE	0x2	/* do normal tilde expansion */
 #define	EXP_VARTILDE	0x4	/* expand tildes in an assignment */
 #define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
 #define EXP_SPLIT_LIT	0x20	/* IFS split literal text ${v+-a b c} */
 #define EXP_LIT_QUOTED	0x40	/* for EXP_SPLIT_LIT, start off quoted */
+#define EXP_GLOB	0x80	/* perform file globbing */
+
+#define EXP_FULL	(EXP_SPLIT | EXP_GLOB)
 
 
+void emptyarglist(struct arglist *);
+void appendarglist(struct arglist *, char *);
 union node;
 void expandarg(union node *, struct arglist *, int);
 void rmescapes(char *);
diff --git a/sh/funcs/cmv b/sh/funcs/cmv
index 2b92c60..307e32f 100644
--- a/sh/funcs/cmv
+++ b/sh/funcs/cmv
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)cmv	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/cmv 139969 2005-01-10 08:39:26Z imp $
 
 # Conditional move--don't replace an existing file.
 
diff --git a/sh/funcs/dirs b/sh/funcs/dirs
index 95f6857..2a1fba5 100644
--- a/sh/funcs/dirs
+++ b/sh/funcs/dirs
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)dirs	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/dirs 139969 2005-01-10 08:39:26Z imp $
 
 # pushd, popd, and dirs --- written by Chris Bertin
 # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
diff --git a/sh/funcs/login b/sh/funcs/login
index 68802a0..9ca88ec 100644
--- a/sh/funcs/login
+++ b/sh/funcs/login
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)login	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/login 139969 2005-01-10 08:39:26Z imp $
 
 # replaces the login builtin in the BSD shell
 login () exec login "$@"
diff --git a/sh/funcs/newgrp b/sh/funcs/newgrp
index 57ac1ce..b99c3fe 100644
--- a/sh/funcs/newgrp
+++ b/sh/funcs/newgrp
@@ -32,6 +32,6 @@
 # SUCH DAMAGE.
 #
 #	@(#)newgrp	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/newgrp 139969 2005-01-10 08:39:26Z imp $
 
 newgrp() exec newgrp "$@"
diff --git a/sh/funcs/popd b/sh/funcs/popd
index bc1cd5c..9787800 100644
--- a/sh/funcs/popd
+++ b/sh/funcs/popd
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)popd	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/popd 139969 2005-01-10 08:39:26Z imp $
 
 # pushd, popd, and dirs --- written by Chris Bertin
 # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
diff --git a/sh/funcs/pushd b/sh/funcs/pushd
index 9e31f2a..465dd31 100644
--- a/sh/funcs/pushd
+++ b/sh/funcs/pushd
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)pushd	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/pushd 139969 2005-01-10 08:39:26Z imp $
 
 # pushd, popd, and dirs --- written by Chris Bertin
 # Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
diff --git a/sh/funcs/suspend b/sh/funcs/suspend
index 1749298..2b0b51c 100644
--- a/sh/funcs/suspend
+++ b/sh/funcs/suspend
@@ -30,7 +30,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)suspend	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/funcs/suspend 215268 2010-11-13 22:20:46Z jilles $
 
 suspend() {
 	local -
diff --git a/sh/histedit.c b/sh/histedit.c
index 7295c3f..e2017b0 100644
--- a/sh/histedit.c
+++ b/sh/histedit.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)histedit.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/histedit.c 296429 2016-03-06 17:24:02Z jilles $");
 
 #include <sys/param.h>
 #include <limits.h>
@@ -359,7 +359,7 @@ histcmd(int argc, char **argv __unused)
 					 * cursor, set it back to the current
 					 * entry.
 					 */
-					retval = history(hist, &he,
+					history(hist, &he,
 					    H_NEXT_EVENT, oldhistnum);
 				}
 			} else
diff --git a/sh/input.c b/sh/input.c
index a0fd01d..15edb67 100644
--- a/sh/input.c
+++ b/sh/input.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/input.c 295937 2016-02-23 22:44:01Z jilles $");
 
 #include <stdio.h>	/* defines BUFSIZ */
 #include <fcntl.h>
@@ -110,6 +110,22 @@ static void pushfile(void);
 static int preadfd(void);
 static void popstring(void);
 
+#ifdef __APPLE__
+// Remove when 28988691 is fixed. Added _ to avoid conflict with future libc definition.
+static char *
+strchrnul_(const char *p, int ch)
+{
+	char c;
+
+	c = ch;
+	for (;; ++p) {
+		if (*p == c || *p == '\0')
+			return ((char *)p);
+	}
+	/* NOTREACHED */
+}
+#endif /* __APPLE__ */
+
 void
 resetinput(void)
 {
@@ -197,8 +213,7 @@ retry:
 int
 preadbuffer(void)
 {
-	char *p, *q;
-	int more;
+	char *p, *q, *r, *end;
 	char savec;
 
 	while (parsefile->strpush) {
@@ -215,8 +230,6 @@ preadbuffer(void)
 	}
 	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
 		return PEOF;
-	flushout(&output);
-	flushout(&errout);
 
 again:
 	if (parselleft <= 0) {
@@ -226,34 +239,32 @@ again:
 		}
 	}
 
-	q = p = parsefile->buf + (parsenextc - parsefile->buf);
-
-	/* delete nul characters */
-	for (more = 1; more;) {
-		switch (*p) {
-		case '\0':
-			p++;	/* Skip nul */
-			goto check;
-
-		case '\n':
-			parsenleft = q - parsenextc;
-			more = 0; /* Stop processing here */
-			break;
-
-		default:
-			break;
-		}
-
-		*q++ = *p++;
-check:
-		if (--parselleft <= 0) {
-			parsenleft = q - parsenextc - 1;
-			if (parsenleft < 0)
-				goto again;
-			*q = '\0';
-			more = 0;
+	p = parsefile->buf + (parsenextc - parsefile->buf);
+	end = p + parselleft;
+	*end = '\0';
+	q = strchrnul_(p, '\n');
+	if (q != end && *q == '\0') {
+		/* delete nul characters */
+		for (r = q; q != end; q++) {
+			if (*q != '\0')
+				*r++ = *q;
 		}
+		parselleft -= end - r;
+		if (parselleft == 0)
+			goto again;
+		end = p + parselleft;
+		*end = '\0';
+		q = strchrnul_(p, '\n');
+	}
+	if (q == end) {
+		parsenleft = parselleft;
+		parselleft = 0;
+	} else /* *q == '\n' */ {
+		q++;
+		parsenleft = q - parsenextc;
+		parselleft -= parsenleft;
 	}
+	parsenleft--;
 
 	savec = *q;
 	*q = '\0';
diff --git a/sh/input.h b/sh/input.h
index cb0af77..1c3ece9 100644
--- a/sh/input.h
+++ b/sh/input.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)input.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/input.h 271593 2014-09-14 16:46:30Z jilles $
  */
 
 /* PEOF (the end of file marker) is defined in syntax.h */
diff --git a/sh/jobs.c b/sh/jobs.c
index b531231..28baa0c 100644
--- a/sh/jobs.c
+++ b/sh/jobs.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/jobs.c 296326 2016-03-02 21:24:46Z jilles $");
 
 #include <sys/ioctl.h>
 #include <sys/param.h>
@@ -322,8 +322,8 @@ static void
 showjob(struct job *jp, int mode)
 {
 	char s[64];
-	char statestr[64];
-	const char *sigstr;
+	char statebuf[16];
+	const char *statestr, *coredump;
 	struct procstat *ps;
 	struct job *j;
 	int col, curr, i, jobno, prev, procno;
@@ -339,9 +339,10 @@ showjob(struct job *jp, int mode)
 			prev = j - jobtab + 1;
 	}
 #endif
+	coredump = "";
 	ps = jp->ps + jp->nprocs - 1;
 	if (jp->state == 0) {
-		strcpy(statestr, "Running");
+		statestr = "Running";
 #if JOBS
 	} else if (jp->state == JOBSTOPPED) {
 		while (!WIFSTOPPED(ps->status) && ps > jp->ps)
@@ -350,27 +351,25 @@ showjob(struct job *jp, int mode)
 			i = WSTOPSIG(ps->status);
 		else
 			i = -1;
-		sigstr = strsignal(i);
-		if (sigstr != NULL)
-			strcpy(statestr, sigstr);
-		else
-			strcpy(statestr, "Suspended");
+		statestr = strsignal(i);
+		if (statestr == NULL)
+			statestr = "Suspended";
 #endif
 	} else if (WIFEXITED(ps->status)) {
 		if (WEXITSTATUS(ps->status) == 0)
-			strcpy(statestr, "Done");
-		else
-			fmtstr(statestr, 64, "Done(%d)",
+			statestr = "Done";
+		else {
+			fmtstr(statebuf, sizeof(statebuf), "Done(%d)",
 			    WEXITSTATUS(ps->status));
+			statestr = statebuf;
+		}
 	} else {
 		i = WTERMSIG(ps->status);
-		sigstr = strsignal(i);
-		if (sigstr != NULL)
-			strcpy(statestr, sigstr);
-		else
-			strcpy(statestr, "Unknown signal");
+		statestr = strsignal(i);
+		if (statestr == NULL)
+			statestr = "Unknown signal";
 		if (WCOREDUMP(ps->status))
-			strcat(statestr, " (core dumped)");
+			coredump = " (core dumped)";
 	}
 
 	for (ps = jp->ps ; procno > 0 ; ps++, procno--) { /* for each process */
@@ -399,7 +398,8 @@ showjob(struct job *jp, int mode)
 		}
 		if (ps == jp->ps) {
 			out1str(statestr);
-			col += strlen(statestr);
+			out1str(coredump);
+			col += strlen(statestr) + strlen(coredump);
 		}
 		do {
 			out1c(' ');
diff --git a/sh/jobs.h b/sh/jobs.h
index 892f129..f9978de 100644
--- a/sh/jobs.h
+++ b/sh/jobs.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/jobs.h 255157 2013-09-02 21:57:46Z jilles $
  */
 
 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
diff --git a/sh/mail.c b/sh/mail.c
index 720cab0..b6de32b 100644
--- a/sh/mail.c
+++ b/sh/mail.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)mail.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/mail.c 278820 2015-02-15 21:47:43Z jilles $");
 
 /*
  * Routines to check for mail.  (Perhaps make part of main.c?)
diff --git a/sh/mail.h b/sh/mail.h
index f88324c..fb5f908 100644
--- a/sh/mail.h
+++ b/sh/mail.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)mail.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/mail.h 127958 2004-04-06 20:06:54Z markm $
  */
 
 void chkmail(int);
diff --git a/sh/main.c b/sh/main.c
index 08f234e..452ed35 100644
--- a/sh/main.c
+++ b/sh/main.c
@@ -42,7 +42,7 @@ static char sccsid[] = "@(#)main.c	8.6 (Berkeley) 5/28/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/main.c 265772 2014-05-09 13:27:30Z jilles $");
 
 #include <stdio.h>
 #include <signal.h>
diff --git a/sh/main.h b/sh/main.h
index 3c48e33..1e1b499 100644
--- a/sh/main.h
+++ b/sh/main.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)main.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/main.h 229220 2012-01-01 22:17:12Z jilles $
  */
 
 extern int rootpid;	/* pid of main shell */
diff --git a/sh/memalloc.c b/sh/memalloc.c
index a04020f..32e3838 100644
--- a/sh/memalloc.c
+++ b/sh/memalloc.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)memalloc.c	8.3 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/memalloc.c 278818 2015-02-15 21:41:29Z jilles $");
 
 #include <sys/param.h>
 #include "shell.h"
diff --git a/sh/memalloc.h b/sh/memalloc.h
index e8df7cb..ee86a92 100644
--- a/sh/memalloc.h
+++ b/sh/memalloc.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/memalloc.h 278818 2015-02-15 21:41:29Z jilles $
  */
 
 #include <string.h>
diff --git a/sh/miscbltin.c b/sh/miscbltin.c
index 789da25..1950ebc 100644
--- a/sh/miscbltin.c
+++ b/sh/miscbltin.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/miscbltin.c 301452 2016-06-05 16:09:31Z jilles $");
 
 /*
  * Miscellaneous builtins.
@@ -100,6 +100,7 @@ readcmd(int argc __unused, char **argv __unused)
 	int i;
 	int is_ifs;
 	int saveall = 0;
+	ptrdiff_t lastnonifs, lastnonifsws;
 	struct timeval tv;
 	char *tvptr;
 	fd_set ifds;
@@ -169,6 +170,7 @@ readcmd(int argc __unused, char **argv __unused)
 	startword = 2;
 	backslash = 0;
 	STARTSTACKSTR(p);
+	lastnonifs = lastnonifsws = -1;
 	for (;;) {
 		nread = read(STDIN_FILENO, &c, 1);
 		if (nread == -1) {
@@ -191,9 +193,11 @@ readcmd(int argc __unused, char **argv __unused)
 		CHECKSTRSPACE(1, p);
 		if (backslash) {
 			backslash = 0;
-			startword = 0;
-			if (c != '\n')
+			if (c != '\n') {
+				startword = 0;
+				lastnonifs = lastnonifsws = p - stackblock();
 				USTPUTC(c, p);
+			}
 			continue;
 		}
 		if (!rflag && c == '\\') {
@@ -217,8 +221,10 @@ readcmd(int argc __unused, char **argv __unused)
 			if (is_ifs == 2 && startword == 1) {
 				/* Only one non-whitespace IFS per word */
 				startword = 2;
-				if (saveall)
+				if (saveall) {
+					lastnonifsws = p - stackblock();
 					USTPUTC(c, p);
+				}
 				continue;
 			}
 		}
@@ -229,6 +235,7 @@ readcmd(int argc __unused, char **argv __unused)
 			if (saveall)
 				/* Not just a spare terminator */
 				saveall++;
+			lastnonifs = lastnonifsws = p - stackblock();
 			USTPUTC(c, p);
 			continue;
 		}
@@ -239,6 +246,8 @@ readcmd(int argc __unused, char **argv __unused)
 		if (ap[1] == NULL) {
 			/* Last variable needs all IFS chars */
 			saveall++;
+			if (is_ifs == 2)
+				lastnonifsws = p - stackblock();
 			USTPUTC(c, p);
 			continue;
 		}
@@ -247,20 +256,17 @@ readcmd(int argc __unused, char **argv __unused)
 		setvar(*ap, stackblock(), 0);
 		ap++;
 		STARTSTACKSTR(p);
+		lastnonifs = lastnonifsws = -1;
 	}
 	STACKSTRNUL(p);
 
-	/* Remove trailing IFS chars */
-	for (; stackblock() <= --p; *p = 0) {
-		if (!strchr(ifs, *p))
-			break;
-		if (strchr(" \t\n", *p))
-			/* Always remove whitespace */
-			continue;
-		if (saveall > 1)
-			/* Don't remove non-whitespace unless it was naked */
-			break;
-	}
+	/*
+	 * Remove trailing IFS chars: always remove whitespace, don't remove
+	 * non-whitespace unless it was naked
+	 */
+	if (saveall <= 1)
+		lastnonifsws = lastnonifs;
+	stackblock()[lastnonifsws + 1] = '\0';
 	setvar(*ap, stackblock(), 0);
 
 	/* Set any remaining args to "" */
@@ -335,7 +341,7 @@ umaskcmd(int argc __unused, char **argv __unused)
 		} else {
 			void *set;
 			INTOFF;
-			if ((set = setmode (ap)) == 0)
+			if ((set = setmode (ap)) == NULL)
 				error("Illegal number: %s", ap);
 
 			mask = getmode (set, ~mask & 0777);
@@ -400,13 +406,16 @@ static const struct limits limits[] = {
 	{ "swap limit",		"kbytes",	RLIMIT_SWAP,	1024, 'w' },
 #endif
 #ifdef RLIMIT_SBSIZE
-	{ "sbsize",		"bytes",	RLIMIT_SBSIZE,	   1, 'b' },
+	{ "socket buffer size",	"bytes",	RLIMIT_SBSIZE,	   1, 'b' },
 #endif
 #ifdef RLIMIT_NPTS
 	{ "pseudo-terminals",	(char *)0,	RLIMIT_NPTS,	   1, 'p' },
 #endif
 #ifdef RLIMIT_KQUEUES
 	{ "kqueues",		(char *)0,	RLIMIT_KQUEUES,	   1, 'k' },
+#endif
+#ifdef RLIMIT_UMTXP
+	{ "umtx shared locks",	(char *)0,	RLIMIT_UMTXP,	   1, 'o' },
 #endif
 	{ (char *) 0,		(char *)0,	0,		   0, '\0' }
 };
@@ -443,7 +452,7 @@ ulimitcmd(int argc __unused, char **argv __unused)
 	struct rlimit	limit;
 
 	what = 'f';
-	while ((optc = nextopt("HSatfdsmcnuvlbpwk")) != '\0')
+	while ((optc = nextopt("HSatfdsmcnuvlbpwko")) != '\0')
 		switch (optc) {
 		case 'H':
 			how = HARD;
diff --git a/sh/mkbuiltins b/sh/mkbuiltins
index 1be7ff1..dd0adc8 100755
--- a/sh/mkbuiltins
+++ b/sh/mkbuiltins
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/mkbuiltins 293118 2016-01-03 21:30:22Z jilles $
 
 temp=`/usr/bin/mktemp -t ka`
 havehist=1
@@ -62,17 +62,16 @@ echo 'int (*const builtinfunc[])(int, char **) = {'
 awk '/^[^#]/ {	printf "\t%s,\n", $1}' $temp
 echo '};
 
-const struct builtincmd builtincmd[] = {'
+const unsigned char builtincmd[] = {'
 awk '{	for (i = 2 ; i <= NF ; i++) {
 		if ($i == "-s") {
 			spc = 1;
 		} else {
-			printf "\t{ \"%s\", %d, %d },\n",  $i, NR-1, spc
+			printf "\t\"\\%03o\\%03o%s\"\n", length($i), (spc ? 128 : 0) + NR-1, $i
 			spc = 0;
 		}
 	}}' $temp
-echo '	{ NULL, 0, 0 }
-};'
+echo '};'
 
 exec > builtins.h
 cat <<\!
@@ -85,14 +84,10 @@ cat <<\!
 tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ < $temp |
 	awk '{	printf "#define %s %d\n", $1, NR-1}'
 echo '
-struct builtincmd {
-      const char *name;
-      int code;
-      int special;
-};
+#define BUILTIN_SPECIAL 0x80
 
 extern int (*const builtinfunc[])(int, char **);
-extern const struct builtincmd builtincmd[];
+extern const unsigned char builtincmd[];
 '
 awk '{	printf "int %s(int, char **);\n", $1}' $temp
 rm -f $temp
diff --git a/sh/mknodes.c b/sh/mknodes.c
index d2fed0d..4694460 100644
--- a/sh/mknodes.c
+++ b/sh/mknodes.c
@@ -42,7 +42,7 @@ static char sccsid[] = "@(#)mknodes.c	8.2 (Berkeley) 5/4/95";
 #endif /* not lint */
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/mknodes.c 292517 2015-12-20 16:40:36Z jilles $");
 
 /*
  * This program reads the nodetypes file and nodes.c.pat file.  It generates
@@ -95,7 +95,6 @@ static struct str *nodestr[MAXTYPES];	/* type of structure used by the node */
 static int nstr;			/* number of structures */
 static struct str str[MAXTYPES];	/* the structures */
 static struct str *curstr;		/* current structure */
-static FILE *infp;
 static char line[1024];
 static int linno;
 static char *linep;
@@ -108,7 +107,7 @@ static void outfunc(FILE *, int);
 static void indent(int, FILE *);
 static int nextfield(char *);
 static void skipbl(void);
-static int readline(void);
+static int readline(FILE *);
 static void error(const char *, ...) __printf0like(1, 2) __dead2;
 static char *savestr(const char *);
 
@@ -116,17 +115,19 @@ static char *savestr(const char *);
 int
 main(int argc, char *argv[])
 {
+	FILE *infp;
+
 	if (argc != 3)
 		error("usage: mknodes file");
-	infp = stdin;
 	if ((infp = fopen(argv[1], "r")) == NULL)
 		error("Can't open %s: %s", argv[1], strerror(errno));
-	while (readline()) {
+	while (readline(infp)) {
 		if (line[0] == ' ' || line[0] == '\t')
 			parsefield();
 		else if (line[0] != '\0')
 			parsenode();
 	}
+	fclose(infp);
 	output(argv[2]);
 	exit(0);
 }
@@ -259,6 +260,10 @@ output(char *file)
 	fputs("union node *getfuncnode(struct funcdef *);\n", hfile);
 	fputs("void reffunc(struct funcdef *);\n", hfile);
 	fputs("void unreffunc(struct funcdef *);\n", hfile);
+	if (ferror(hfile))
+		error("Can't write to nodes.h");
+	if (fclose(hfile))
+		error("Can't close nodes.h");
 
 	fputs(writer, cfile);
 	while (fgets(line, sizeof line, patfile) != NULL) {
@@ -272,6 +277,11 @@ output(char *file)
 		else
 			fputs(line, cfile);
 	}
+	fclose(patfile);
+	if (ferror(cfile))
+		error("Can't write to nodes.c");
+	if (fclose(cfile))
+		error("Can't close nodes.c");
 }
 
 
@@ -302,10 +312,10 @@ outfunc(FILE *cfile, int calcsize)
 	else
 		fputs("	    return NULL;\n", cfile);
 	if (calcsize)
-		fputs("      funcblocksize += nodesize[n->type];\n", cfile);
+		fputs("      result->blocksize += nodesize[n->type];\n", cfile);
 	else {
-		fputs("      new = funcblock;\n", cfile);
-		fputs("      funcblock = (char *)funcblock + nodesize[n->type];\n", cfile);
+		fputs("      new = state->block;\n", cfile);
+		fputs("      state->block = (char *)state->block + nodesize[n->type];\n", cfile);
 	}
 	fputs("      switch (n->type) {\n", cfile);
 	for (sp = str ; sp < &str[nstr] ; sp++) {
@@ -319,33 +329,33 @@ outfunc(FILE *cfile, int calcsize)
 			case T_NODE:
 				if (calcsize) {
 					indent(12, cfile);
-					fprintf(cfile, "calcsize(n->%s.%s);\n",
+					fprintf(cfile, "calcsize(n->%s.%s, result);\n",
 						sp->tag, fp->name);
 				} else {
 					indent(12, cfile);
-					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
+					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s, state);\n",
 						sp->tag, fp->name, sp->tag, fp->name);
 				}
 				break;
 			case T_NODELIST:
 				if (calcsize) {
 					indent(12, cfile);
-					fprintf(cfile, "sizenodelist(n->%s.%s);\n",
+					fprintf(cfile, "sizenodelist(n->%s.%s, result);\n",
 						sp->tag, fp->name);
 				} else {
 					indent(12, cfile);
-					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
+					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s, state);\n",
 						sp->tag, fp->name, sp->tag, fp->name);
 				}
 				break;
 			case T_STRING:
 				if (calcsize) {
 					indent(12, cfile);
-					fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
+					fprintf(cfile, "result->stringsize += strlen(n->%s.%s) + 1;\n",
 						sp->tag, fp->name);
 				} else {
 					indent(12, cfile);
-					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
+					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s, state);\n",
 						sp->tag, fp->name, sp->tag, fp->name);
 				}
 				break;
@@ -407,7 +417,7 @@ skipbl(void)
 
 
 static int
-readline(void)
+readline(FILE *infp)
 {
 	char *p;
 
diff --git a/sh/mksyntax.c b/sh/mksyntax.c
index 1f81828..8f9c8fd 100644
--- a/sh/mksyntax.c
+++ b/sh/mksyntax.c
@@ -42,7 +42,7 @@ static char sccsid[] = "@(#)mksyntax.c	8.2 (Berkeley) 5/4/95";
 #endif /* not lint */
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/mksyntax.c 279569 2015-03-03 21:21:43Z jilles $");
 
 /*
  * This program creates syntax.h and syntax.c.
diff --git a/sh/mktokens b/sh/mktokens
index b6f5f97..7dd8080 100644
--- a/sh/mktokens
+++ b/sh/mktokens
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)mktokens	8.1 (Berkeley) 5/31/93
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/mktokens 279503 2015-03-01 21:46:55Z jilles $
 
 # The following is a list of tokens.  The second column is nonzero if the
 # token marks the end of a list.  The third column is the name to print in
diff --git a/sh/myhistedit.h b/sh/myhistedit.h
index e31276d..1d21f46 100644
--- a/sh/myhistedit.h
+++ b/sh/myhistedit.h
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)myhistedit.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/myhistedit.h 229220 2012-01-01 22:17:12Z jilles $
  */
 
 #include <histedit.h>
diff --git a/sh/mystring.c b/sh/mystring.c
index 19de78d..60349d7 100644
--- a/sh/mystring.c
+++ b/sh/mystring.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)mystring.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/mystring.c 270102 2014-08-17 16:40:29Z jilles $");
 
 /*
  * String functions.
diff --git a/sh/mystring.h b/sh/mystring.h
index 919fc86..3876bab 100644
--- a/sh/mystring.h
+++ b/sh/mystring.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)mystring.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/mystring.h 268920 2014-07-20 12:06:52Z jilles $
  */
 
 #include <string.h>
diff --git a/sh/nodes.c.pat b/sh/nodes.c.pat
index e99e3ab..d114d0e 100644
--- a/sh/nodes.c.pat
+++ b/sh/nodes.c.pat
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/nodes.c.pat 291267 2015-11-24 22:47:19Z jilles $
  */
 
 #include <sys/param.h>
@@ -46,19 +46,24 @@
 #include "mystring.h"
 
 
-static int     funcblocksize;	/* size of structures in function */
-static int     funcstringsize;	/* size of strings in node */
-static pointer funcblock;	/* block to allocate function from */
-static char   *funcstring;	/* block to allocate strings from */
+struct nodesize {
+	int     blocksize;	/* size of structures in function */
+	int     stringsize;	/* size of strings in node */
+};
+
+struct nodecopystate {
+	pointer block;		/* block to allocate function from */
+	char   *string;		/* block to allocate strings from */
+};
 
 %SIZES
 
 
-static void calcsize(union node *);
-static void sizenodelist(struct nodelist *);
-static union node *copynode(union node *);
-static struct nodelist *copynodelist(struct nodelist *);
-static char *nodesavestr(const char *);
+static void calcsize(union node *, struct nodesize *);
+static void sizenodelist(struct nodelist *, struct nodesize *);
+static union node *copynode(union node *, struct nodecopystate *);
+static struct nodelist *copynodelist(struct nodelist *, struct nodecopystate *);
+static char *nodesavestr(const char *, struct nodecopystate *);
 
 
 struct funcdef {
@@ -73,18 +78,20 @@ struct funcdef {
 struct funcdef *
 copyfunc(union node *n)
 {
+	struct nodesize sz;
+	struct nodecopystate st;
 	struct funcdef *fn;
 
 	if (n == NULL)
 		return NULL;
-	funcblocksize = offsetof(struct funcdef, n);
-	funcstringsize = 0;
-	calcsize(n);
-	fn = ckmalloc(funcblocksize + funcstringsize);
+	sz.blocksize = offsetof(struct funcdef, n);
+	sz.stringsize = 0;
+	calcsize(n, &sz);
+	fn = ckmalloc(sz.blocksize + sz.stringsize);
 	fn->refcount = 1;
-	funcblock = (char *)fn + offsetof(struct funcdef, n);
-	funcstring = (char *)fn + funcblocksize;
-	copynode(n);
+	st.block = (char *)fn + offsetof(struct funcdef, n);
+	st.string = (char *)fn + sz.blocksize;
+	copynode(n, &st);
 	return fn;
 }
 
@@ -97,7 +104,7 @@ getfuncnode(struct funcdef *fn)
 
 
 static void
-calcsize(union node *n)
+calcsize(union node *n, struct nodesize *result)
 {
 	%CALCSIZE
 }
@@ -105,11 +112,11 @@ calcsize(union node *n)
 
 
 static void
-sizenodelist(struct nodelist *lp)
+sizenodelist(struct nodelist *lp, struct nodesize *result)
 {
 	while (lp) {
-		funcblocksize += ALIGN(sizeof(struct nodelist));
-		calcsize(lp->n);
+		result->blocksize += ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n, result);
 		lp = lp->next;
 	}
 }
@@ -117,7 +124,7 @@ sizenodelist(struct nodelist *lp)
 
 
 static union node *
-copynode(union node *n)
+copynode(union node *n, struct nodecopystate *state)
 {
 	union node *new;
 
@@ -127,16 +134,17 @@ copynode(union node *n)
 
 
 static struct nodelist *
-copynodelist(struct nodelist *lp)
+copynodelist(struct nodelist *lp, struct nodecopystate *state)
 {
 	struct nodelist *start;
 	struct nodelist **lpp;
 
 	lpp = &start;
 	while (lp) {
-		*lpp = funcblock;
-		funcblock = (char *)funcblock + ALIGN(sizeof(struct nodelist));
-		(*lpp)->n = copynode(lp->n);
+		*lpp = state->block;
+		state->block = (char *)state->block +
+		    ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n, state);
 		lp = lp->next;
 		lpp = &(*lpp)->next;
 	}
@@ -147,15 +155,15 @@ copynodelist(struct nodelist *lp)
 
 
 static char *
-nodesavestr(const char *s)
+nodesavestr(const char *s, struct nodecopystate *state)
 {
 	const char *p = s;
-	char *q = funcstring;
-	char   *rtn = funcstring;
+	char *q = state->string;
+	char   *rtn = state->string;
 
 	while ((*q++ = *p++) != '\0')
 		continue;
-	funcstring = q;
+	state->string = q;
 	return rtn;
 }
 
diff --git a/sh/nodetypes b/sh/nodetypes
index d480093..7fb3417 100644
--- a/sh/nodetypes
+++ b/sh/nodetypes
@@ -30,7 +30,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)nodetypes	8.2 (Berkeley) 5/4/95
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/nodetypes 278820 2015-02-15 21:47:43Z jilles $
 
 # This file describes the nodes used in parse trees.  Unindented lines
 # contain a node type followed by a structure tag.  Subsequent indented
diff --git a/sh/options.c b/sh/options.c
index 2d0ddce..25056b2 100644
--- a/sh/options.c
+++ b/sh/options.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/options.c 296577 2016-03-09 21:00:57Z jilles $");
 
 #include <signal.h>
 #include <unistd.h>
@@ -73,6 +73,8 @@ char *minusc;			/* argument to -c option */
 static void options(int);
 static void minus_o(char *, int);
 static void setoption(int, int);
+static void setoptionbyindex(int, int);
+static void setparam(int, char **);
 static int getopts(char *, char *, char **, char ***, char **);
 
 
@@ -90,7 +92,7 @@ procargs(int argc, char **argv)
 	if (argc > 0)
 		argptr++;
 	for (i = 0; i < NOPTS; i++)
-		optlist[i].val = 2;
+		optval[i] = 2;
 	privileged = (getuid() != geteuid() || getgid() != getegid());
 	options(1);
 	if (*argptr == NULL && minusc == NULL)
@@ -103,8 +105,8 @@ procargs(int argc, char **argv)
 	if (mflag == 2)
 		mflag = iflag;
 	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].val == 2)
-			optlist[i].val = 0;
+		if (optval[i] == 2)
+			optval[i] = 0;
 	arg0 = argv[0];
 	if (sflag == 0 && minusc == NULL) {
 		scriptname = *argptr++;
@@ -223,7 +225,7 @@ end_options1:
 end_options2:
 	if (!cmdline) {
 		if (*argptr == NULL)
-			setparam(argptr);
+			setparam(0, argptr);
 		return;
 	}
 
@@ -249,27 +251,30 @@ static void
 minus_o(char *name, int val)
 {
 	int i;
+	const unsigned char *on;
+	size_t len;
 
 	if (name == NULL) {
 		if (val) {
 			/* "Pretty" output. */
 			out1str("Current option settings\n");
-			for (i = 0; i < NOPTS; i++)
-				out1fmt("%-16s%s\n", optlist[i].name,
-					optlist[i].val ? "on" : "off");
+			for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1)
+				out1fmt("%-16.*s%s\n", *on, on + 1,
+					optval[i] ? "on" : "off");
 		} else {
 			/* Output suitable for re-input to shell. */
-			for (i = 0; i < NOPTS; i++)
-				out1fmt("%s %co %s%s",
+			for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1)
+				out1fmt("%s %co %.*s%s",
 				    i % 6 == 0 ? "set" : "",
-				    optlist[i].val ? '-' : '+',
-				    optlist[i].name,
+				    optval[i] ? '-' : '+',
+				    *on, on + 1,
 				    i % 6 == 5 || i == NOPTS - 1 ? "\n" : "");
 		}
 	} else {
-		for (i = 0; i < NOPTS; i++)
-			if (equal(name, optlist[i].name)) {
-				setoption(optlist[i].letter, val);
+		len = strlen(name);
+		for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1)
+			if (*on == len && memcmp(on + 1, name, len) == 0) {
+				setoptionbyindex(i, val);
 				return;
 			}
 		error("Illegal option -o %s", name);
@@ -278,26 +283,32 @@ minus_o(char *name, int val)
 
 
 static void
-setoption(int flag, int val)
+setoptionbyindex(int idx, int val)
 {
-	int i;
-
-	if (flag == 'p' && !val && privileged) {
+	if (&optval[idx] == &privileged && !val && privileged) {
 		if (setgid(getgid()) == -1)
 			error("setgid");
 		if (setuid(getuid()) == -1)
 			error("setuid");
 	}
-	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].letter == flag) {
-			optlist[i].val = val;
-			if (val) {
-				/* #%$ hack for ksh semantics */
-				if (flag == 'V')
-					Eflag = 0;
-				else if (flag == 'E')
-					Vflag = 0;
-			}
+	optval[idx] = val;
+	if (val) {
+		/* #%$ hack for ksh semantics */
+		if (&optval[idx] == &Vflag)
+			Eflag = 0;
+		else if (&optval[idx] == &Eflag)
+			Vflag = 0;
+	}
+}
+
+static void
+setoption(int flag, int val)
+{
+	int i;
+
+	for (i = 0; i < NSHORTOPTS; i++)
+		if (optletter[i] == flag) {
+			setoptionbyindex(i, val);
 			return;
 		}
 	error("Illegal option -%c", flag);
@@ -308,22 +319,20 @@ setoption(int flag, int val)
  * Set the shell parameters.
  */
 
-void
-setparam(char **argv)
+static void
+setparam(int argc, char **argv)
 {
 	char **newparam;
 	char **ap;
-	int nparam;
 
-	for (nparam = 0 ; argv[nparam] ; nparam++);
-	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
+	ap = newparam = ckmalloc((argc + 1) * sizeof *ap);
 	while (*argv) {
 		*ap++ = savestr(*argv++);
 	}
 	*ap = NULL;
 	freeparam(&shellparam);
 	shellparam.malloc = 1;
-	shellparam.nparam = nparam;
+	shellparam.nparam = argc;
 	shellparam.p = newparam;
 	shellparam.optp = NULL;
 	shellparam.reset = 1;
@@ -361,8 +370,7 @@ freeparam(struct shparam *param)
 int
 shiftcmd(int argc, char **argv)
 {
-	int n;
-	char **ap1, **ap2;
+	int i, n;
 
 	n = 1;
 	if (argc > 1)
@@ -371,12 +379,11 @@ shiftcmd(int argc, char **argv)
 		return 1;
 	INTOFF;
 	shellparam.nparam -= n;
-	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
-		if (shellparam.malloc)
-			ckfree(*ap1);
-	}
-	ap2 = shellparam.p;
-	while ((*ap2++ = *ap1++) != NULL);
+	if (shellparam.malloc)
+		for (i = 0; i < n; i++)
+			ckfree(shellparam.p[i]);
+	memmove(shellparam.p, shellparam.p + n,
+	    (shellparam.nparam + 1) * sizeof(shellparam.p[0]));
 	shellparam.reset = 1;
 	INTON;
 	return 0;
@@ -397,7 +404,7 @@ setcmd(int argc, char **argv)
 	options(0);
 	optschanged();
 	if (*argptr != NULL) {
-		setparam(argptr);
+		setparam(argc - (argptr - argv), argptr);
 	}
 	INTON;
 	return 0;
diff --git a/sh/options.h b/sh/options.h
index 2048a35..8910df9 100644
--- a/sh/options.h
+++ b/sh/options.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)options.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/options.h 294348 2016-01-19 22:41:26Z jilles $
  */
 
 struct shparam {
@@ -45,57 +45,57 @@ struct shparam {
 
 
 
-#define eflag optlist[0].val
-#define fflag optlist[1].val
-#define Iflag optlist[2].val
-#define iflag optlist[3].val
-#define mflag optlist[4].val
-#define nflag optlist[5].val
-#define sflag optlist[6].val
-#define xflag optlist[7].val
-#define vflag optlist[8].val
-#define Vflag optlist[9].val
-#define	Eflag optlist[10].val
-#define	Cflag optlist[11].val
-#define	aflag optlist[12].val
-#define	bflag optlist[13].val
-#define	uflag optlist[14].val
-#define	privileged optlist[15].val
-#define	Tflag optlist[16].val
-#define	Pflag optlist[17].val
-#define	hflag optlist[18].val
+#define eflag optval[0]
+#define fflag optval[1]
+#define Iflag optval[2]
+#define iflag optval[3]
+#define mflag optval[4]
+#define nflag optval[5]
+#define sflag optval[6]
+#define xflag optval[7]
+#define vflag optval[8]
+#define Vflag optval[9]
+#define	Eflag optval[10]
+#define	Cflag optval[11]
+#define	aflag optval[12]
+#define	bflag optval[13]
+#define	uflag optval[14]
+#define	privileged optval[15]
+#define	Tflag optval[16]
+#define	Pflag optval[17]
+#define	hflag optval[18]
+#define	nologflag optval[19]
 
-#define NOPTS	19
+#define NSHORTOPTS	19
+#define NOPTS		20
 
-struct optent {
-	const char *name;
-	const char letter;
-	char val;
-};
-
-extern struct optent optlist[NOPTS];
+extern char optval[NOPTS];
+extern const char optletter[NSHORTOPTS];
 #ifdef DEFINE_OPTIONS
-struct optent optlist[NOPTS] = {
-	{ "errexit",	'e',	0 },
-	{ "noglob",	'f',	0 },
-	{ "ignoreeof",	'I',	0 },
-	{ "interactive",'i',	0 },
-	{ "monitor",	'm',	0 },
-	{ "noexec",	'n',	0 },
-	{ "stdin",	's',	0 },
-	{ "xtrace",	'x',	0 },
-	{ "verbose",	'v',	0 },
-	{ "vi",		'V',	0 },
-	{ "emacs",	'E',	0 },
-	{ "noclobber",	'C',	0 },
-	{ "allexport",	'a',	0 },
-	{ "notify",	'b',	0 },
-	{ "nounset",	'u',	0 },
-	{ "privileged",	'p',	0 },
-	{ "trapsasync",	'T',	0 },
-	{ "physical",	'P',	0 },
-	{ "trackall",	'h',	0 },
-};
+char optval[NOPTS];
+const char optletter[NSHORTOPTS] = "efIimnsxvVECabupTPh";
+static const unsigned char optname[] =
+	"\007errexit"
+	"\006noglob"
+	"\011ignoreeof"
+	"\013interactive"
+	"\007monitor"
+	"\006noexec"
+	"\005stdin"
+	"\006xtrace"
+	"\007verbose"
+	"\002vi"
+	"\005emacs"
+	"\011noclobber"
+	"\011allexport"
+	"\006notify"
+	"\007nounset"
+	"\012privileged"
+	"\012trapsasync"
+	"\010physical"
+	"\010trackall"
+	"\005nolog"
+;
 #endif
 
 
@@ -108,7 +108,6 @@ extern char *nextopt_optptr;	/* used by nextopt */
 
 void procargs(int, char **);
 void optschanged(void);
-void setparam(char **);
 void freeparam(struct shparam *);
 int nextopt(const char *);
 void getoptsreset(const char *);
diff --git a/sh/output.c b/sh/output.c
index 39b722f..7718603 100644
--- a/sh/output.c
+++ b/sh/output.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/output.c 275766 2014-12-14 16:26:19Z jilles $");
 
 /*
  * Shell output routines.  We use our own output routines because:
diff --git a/sh/output.h b/sh/output.h
index 51974d8..227db2d 100644
--- a/sh/output.h
+++ b/sh/output.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)output.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/output.h 244162 2012-12-12 22:01:10Z jilles $
  */
 
 #ifndef OUTPUT_INCL
diff --git a/sh/parser.c b/sh/parser.c
index 2bba84e..3dc0d15 100644
--- a/sh/parser.c
+++ b/sh/parser.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/parser.c 301139 2016-06-01 16:56:29Z truckman $");
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -106,6 +106,8 @@ static int startlinno;		/* line # where last token started */
 static int funclinno;		/* line # where the current function started */
 static struct parser_temp *parser_temp;
 
+#define NOEOFMARK ((const char *)&heredoclist)
+
 
 static union node *list(int);
 static union node *andor(void);
@@ -229,6 +231,39 @@ parsecmd(int interact)
 }
 
 
+/*
+ * Read and parse words for wordexp.
+ * Returns a list of NARG nodes; NULL if there are no words.
+ */
+union node *
+parsewordexp(void)
+{
+	union node *n, *first = NULL, **pnext;
+	int t;
+
+	/* This assumes the parser is not re-entered,
+	 * which could happen if we add command substitution on PS1/PS2.
+	 */
+	parser_temp_free_all();
+	heredoclist = NULL;
+
+	tokpushback = 0;
+	checkkwd = 0;
+	doprompt = 0;
+	setprompt(0);
+	needprompt = 0;
+	pnext = &first;
+	while ((t = readtoken()) != TEOF) {
+		if (t != TWORD)
+			synexpect(TWORD);
+		n = makename();
+		*pnext = n;
+		pnext = &n->narg.next;
+	}
+	return first;
+}
+
+
 static union node *
 list(int nlflag)
 {
@@ -593,7 +628,7 @@ simplecmd(union node **rpp, union node *redir)
 
 	/* If we don't have any redirections already, then we must reset */
 	/* rpp to be the address of the local redir variable.  */
-	if (redir == 0)
+	if (redir == NULL)
 		rpp = &redir;
 
 	args = NULL;
@@ -972,6 +1007,10 @@ checkend(int c, const char *eofmark, int striptabs)
 			pungetc();
 			pushstring(eofmark + 1, q - (eofmark + 1), NULL);
 		}
+	} else if (c == '\n' && *eofmark == '\0') {
+		c = PEOF;
+		plinno++;
+		needprompt = doprompt;
 	}
 	return (c);
 }
@@ -1195,7 +1234,8 @@ parsebackq(char *out, struct nodelist **pbqlist,
 static char *
 readcstyleesc(char *out)
 {
-	int c, v, i, n;
+	int c, vc, i, n;
+	unsigned int v;
 
 	c = pgetc();
 	switch (c) {
@@ -1310,12 +1350,12 @@ readcstyleesc(char *out)
 	default:
 		  synerror("Bad escape sequence");
 	}
-	v = (char)v;
+	vc = (char)v;
 	/*
 	 * We can't handle NUL bytes.
 	 * POSIX says we should skip till the closing quote.
 	 */
-	if (v == '\0') {
+	if (vc == '\0') {
 		while ((c = pgetc()) != '\'') {
 			if (c == '\\')
 				c = pgetc();
@@ -1332,9 +1372,9 @@ readcstyleesc(char *out)
 		pungetc();
 		return out;
 	}
-	if (SQSYNTAX[v] == CCTL)
+	if (SQSYNTAX[vc] == CCTL)
 		USTPUTC(CTLESC, out);
-	USTPUTC(v, out);
+	USTPUTC(vc, out);
 	return out;
 }
 
@@ -1382,7 +1422,7 @@ readtoken1(int firstc, char const *initialsyntax, const char *eofmark,
 
 	STARTSTACKSTR(out);
 	loop: {	/* for each line, until end of word */
-		if (eofmark)
+		if (eofmark && eofmark != NOEOFMARK)
 			/* set c to PEOF if at end of here document */
 			c = checkend(c, eofmark, striptabs);
 		for (;;) {	/* until end of line or end of word */
@@ -1570,13 +1610,11 @@ endword:
  */
 
 parsesub: {
-	char buf[10];
 	int subtype;
 	int typeloc;
 	int flags;
 	char *p;
 	static const char types[] = "}-+?=";
-	int bracketed_name = 0; /* used to handle ${[0-9]*} variables */
 	int linno;
 	int length;
 	int c1;
@@ -1600,7 +1638,6 @@ parsesub: {
 		subtype = VSNORMAL;
 		flags = 0;
 		if (c == '{') {
-			bracketed_name = 1;
 			c = pgetc_linecont();
 			subtype = 0;
 		}
@@ -1616,22 +1653,25 @@ varname:
 			    strncmp(out - length, "LINENO", length) == 0) {
 				/* Replace the variable name with the
 				 * current line number. */
+				STADJUST(-6, out);
+				CHECKSTRSPACE(11, out);
 				linno = plinno;
 				if (funclinno != 0)
 					linno -= funclinno - 1;
-				snprintf(buf, sizeof(buf), "%d", linno);
-				STADJUST(-6, out);
-				STPUTS(buf, out);
+				length = snprintf(out, 11, "%d", linno);
+				if (length > 10)
+					length = 10;
+				out += length;
 				flags |= VSLINENO;
 			}
 		} else if (is_digit(c)) {
-			if (bracketed_name) {
+			if (subtype != VSNORMAL) {
 				do {
 					STPUTC(c, out);
 					c = pgetc_linecont();
 				} while (is_digit(c));
 			} else {
-				STPUTC(c, out);
+				USTPUTC(c, out);
 				c = pgetc_linecont();
 			}
 		} else if (is_special(c)) {
@@ -1661,7 +1701,7 @@ varname:
 				pungetc();
 			else if (c == '\n' || c == PEOF)
 				synerror("Unexpected end of line in substitution");
-			else
+			else if (BASESYNTAX[c] != CCTL)
 				USTPUTC(c, out);
 		}
 		if (subtype == 0) {
@@ -1677,7 +1717,8 @@ varname:
 						synerror("Unexpected end of line in substitution");
 					if (flags == VSNUL)
 						STPUTC(':', out);
-					STPUTC(c, out);
+					if (BASESYNTAX[c] != CCTL)
+						STPUTC(c, out);
 					subtype = VSERROR;
 				} else
 					subtype = p - types + VSNORMAL;
@@ -1889,6 +1930,8 @@ static void
 setprompt(int which)
 {
 	whichprompt = which;
+	if (which == 0)
+		return;
 
 #ifndef NO_HISTORY
 	if (!el)
@@ -1955,7 +1998,7 @@ getprompt(void *unused __unused)
 	/*
 	 * Format prompt string.
 	 */
-	for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++)
+	for (i = 0; (i < PROMPTLEN - 1) && (*fmt != '\0'); i++, fmt++)
 		if (*fmt == '\\')
 			switch (*++fmt) {
 
@@ -1968,11 +2011,13 @@ getprompt(void *unused __unused)
 			case 'h':
 			case 'H':
 				ps[i] = '\0';
-				gethostname(&ps[i], PROMPTLEN - i);
+				gethostname(&ps[i], PROMPTLEN - i - 1);
+				ps[PROMPTLEN - 1] = '\0';
 				/* Skip to end of hostname. */
 				trim = (*fmt == 'h') ? '.' : '\0';
-				while ((ps[i+1] != '\0') && (ps[i+1] != trim))
+				while ((ps[i] != '\0') && (ps[i] != trim))
 					i++;
+				--i;
 				break;
 
 				/*
@@ -1984,7 +2029,7 @@ getprompt(void *unused __unused)
 			case 'W':
 			case 'w':
 				pwd = lookupvar("PWD");
-				if (pwd == NULL)
+				if (pwd == NULL || *pwd == '\0')
 					pwd = "?";
 				if (*fmt == 'W' &&
 				    *pwd == '/' && pwd[1] != '\0')
@@ -2017,8 +2062,9 @@ getprompt(void *unused __unused)
 				 * Emit unrecognized formats verbatim.
 				 */
 			default:
-				ps[i++] = '\\';
-				ps[i] = *fmt;
+				ps[i] = '\\';
+				if (i < PROMPTLEN - 2)
+					ps[++i] = *fmt;
 				break;
 			}
 		else
@@ -2044,7 +2090,7 @@ expandstr(const char *ps)
 		parser_temp = NULL;
 		setinputstring(ps, 1);
 		doprompt = 0;
-		readtoken1(pgetc(), DQSYNTAX, "", 0);
+		readtoken1(pgetc(), DQSYNTAX, NOEOFMARK, 0);
 		if (backquotelist != NULL)
 			error("Command substitution not allowed here");
 
diff --git a/sh/parser.h b/sh/parser.h
index 5982594..0a42f4e 100644
--- a/sh/parser.h
+++ b/sh/parser.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)parser.h	8.3 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/parser.h 288430 2015-09-30 21:32:29Z jilles $
  */
 
 /* control characters in argument strings */
@@ -76,6 +76,7 @@ extern const char *const parsekwd[];
 
 
 union node *parsecmd(int);
+union node *parsewordexp(void);
 void forcealias(void);
 void fixredir(union node *, const char *, int);
 int goodname(const char *);
diff --git a/sh/redir.c b/sh/redir.c
index 95d3238..d0b4535 100644
--- a/sh/redir.c
+++ b/sh/redir.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)redir.c	8.2 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/redir.c 295085 2016-01-30 21:21:25Z jilles $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -70,6 +70,7 @@ struct redirtab {
 	struct redirtab *next;
 	int renamed[10];
 	int fd0_redirected;
+	unsigned int empty_redirs;
 };
 
 
@@ -82,6 +83,9 @@ static struct redirtab *redirlist;
 */
 static int fd0_redirected = 0;
 
+/* Number of redirtabs that have not been allocated. */
+static unsigned int empty_redirs = 0;
+
 static void openredirect(union node *, char[10 ]);
 static int openhere(union node *);
 
@@ -115,12 +119,17 @@ redirect(union node *redir, int flags)
 		memory[i] = 0;
 	memory[1] = flags & REDIR_BACKQ;
 	if (flags & REDIR_PUSH) {
-		sv = ckmalloc(sizeof (struct redirtab));
-		for (i = 0 ; i < 10 ; i++)
-			sv->renamed[i] = EMPTY;
-		sv->fd0_redirected = fd0_redirected;
-		sv->next = redirlist;
-		redirlist = sv;
+		empty_redirs++;
+		if (redir != NULL) {
+			sv = ckmalloc(sizeof (struct redirtab));
+			for (i = 0 ; i < 10 ; i++)
+				sv->renamed[i] = EMPTY;
+			sv->fd0_redirected = fd0_redirected;
+			sv->empty_redirs = empty_redirs - 1;
+			sv->next = redirlist;
+			redirlist = sv;
+			empty_redirs = 0;
+		}
 	}
 	for (n = redir ; n ; n = n->nfile.next) {
 		fd = n->nfile.fd;
@@ -303,6 +312,12 @@ popredir(void)
 	struct redirtab *rp = redirlist;
 	int i;
 
+	INTOFF;
+	if (empty_redirs > 0) {
+		empty_redirs--;
+		INTON;
+		return;
+	}
 	for (i = 0 ; i < 10 ; i++) {
 		if (rp->renamed[i] != EMPTY) {
 			if (rp->renamed[i] >= 0) {
@@ -313,8 +328,8 @@ popredir(void)
 			}
 		}
 	}
-	INTOFF;
 	fd0_redirected = rp->fd0_redirected;
+	empty_redirs = rp->empty_redirs;
 	redirlist = rp->next;
 	ckfree(rp);
 	INTON;
diff --git a/sh/redir.h b/sh/redir.h
index ad44c4e..7146dd1 100644
--- a/sh/redir.h
+++ b/sh/redir.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)redir.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/redir.h 254426 2013-08-16 20:24:41Z jilles $
  */
 
 /* flags passed to redirect */
diff --git a/sh/sh.1 b/sh/sh.1
index e193d5d..cbfd925 100644
--- a/sh/sh.1
+++ b/sh/sh.1
@@ -30,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	from: @(#)sh.1	8.6 (Berkeley) 5/4/95
-.\" $FreeBSD$
+.\" $FreeBSD: head/bin/sh/sh.1 306843 2016-10-08 13:40:12Z jilles $
 .\"
-.Dd July 11, 2015
+.Dd October 8, 2016
 .Dt SH 1
 .Os
 .Sh NAME
@@ -343,6 +343,11 @@ Write each command
 variable subjected to parameter expansion and arithmetic expansion)
 to standard error before it is executed.
 Useful for debugging.
+.It nolog
+Another do-nothing option for
+.Tn POSIX
+compliance.
+It only has a long name.
 .El
 .Pp
 The
@@ -1173,7 +1178,9 @@ The only special parameter that can be made local is
 .Ql - .
 Making
 .Ql -
-local causes any shell options that are
+local causes any shell options
+(including those that only have long names)
+that are
 changed via the
 .Ic set
 command inside the function to be
@@ -1342,13 +1349,13 @@ used in tilde expansion and as a default directory for the
 built-in.
 .It Va IFS
 Input Field Separators.
-The default value is
+This is initialized at startup to
 .Aq space ,
 .Aq tab ,
 and
 .Aq newline
 in that order.
-This default also applies if
+This value also applies if
 .Va IFS
 is unset, but not if it is set to the empty string.
 See the
@@ -1396,9 +1403,9 @@ may include any of the following formatting sequences,
 which are replaced by the given information:
 .Bl -tag -width indent
 .It Li \eH
-The local hostname.
+This system's fully-qualified hostname (FQDN).
 .It Li \eh
-The fully-qualified hostname.
+This system's hostname.
 .It Li \eW
 The final component of the current working directory.
 .It Li \ew
@@ -1945,13 +1952,20 @@ Execute the specified built-in command,
 This is useful when the user wishes to override a shell function
 with the same name as a built-in command.
 .It Ic cd Oo Fl L | P Oc Oo Fl e Oc Op Ar directory
+.It Ic cd Fl
 Switch to the specified
 .Ar directory ,
-or to the directory specified in the
+to the directory specified in the
 .Va HOME
 environment variable if no
 .Ar directory
-is specified.
+is specified or
+to the directory specified in the
+.Va OLDPWD
+environment variable if
+.Ar directory
+is
+.Fl .
 If
 .Ar directory
 does not begin with
@@ -1975,10 +1989,12 @@ the
 .Ic cd
 command will print out the name of the directory
 that it actually switched to
-if this is different from the name that the user gave.
-These may be different either because the
+if the
 .Va CDPATH
-mechanism was used or because a symbolic link was crossed.
+mechanism was used or if
+.Ar directory
+was
+.Fl .
 .Pp
 If the
 .Fl P
@@ -2599,7 +2615,7 @@ and not found.
 For aliases the alias expansion is printed;
 for commands and tracked aliases
 the complete pathname of the command is printed.
-.It Ic ulimit Oo Fl HSabcdfklmnpstuvw Oc Op Ar limit
+.It Ic ulimit Oo Fl HSabcdfklmnopstuvw Oc Op Ar limit
 Set or display resource limits (see
 .Xr getrlimit 2 ) .
 If
@@ -2658,6 +2674,11 @@ kilobytes.
 The maximal resident set size of a process, in kilobytes.
 .It Fl n Ar nofiles
 The maximal number of descriptors that could be opened by a process.
+.It Fl o Ar umtxp
+The maximal number of process-shared locks
+(see
+.Xr pthread 3 )
+for this user ID.
 .It Fl p Ar pseudoterminals
 The maximal number of pseudo-terminals for this user ID.
 .It Fl s Ar stacksize
@@ -2767,6 +2788,10 @@ Initialization file for interactive shells.
 Locale settings.
 These are inherited by children of the shell,
 and is used in a limited manner by the shell itself.
+.It Ev OLDPWD
+The previous current directory.
+This is used and updated by
+.Ic cd .
 .It Ev PWD
 An absolute pathname for the current directory,
 possibly containing symbolic links.
diff --git a/sh/sh.plist.part b/sh/sh.plist.part
index f1fb688..f023fca 100644
--- a/sh/sh.plist.part
+++ b/sh/sh.plist.part
@@ -2,17 +2,18 @@
 		<key>OpenSourceProject</key>
 		<string>sh</string>
 		<key>OpenSourceVersion</key>
-		<string>2015-07-11</string>
+		<string>2016-10-08</string>
 		<key>OpenSourceWebsiteURL</key>
 		<string>http://svnweb.freebsd.org/base/head/bin/sh/</string>
 		<key>OpenSourceSCM</key>
 		<string>svn co http://svn.freebsd.org/base/head/bin/sh/</string>
 		<key>OpenSourceImportDate</key>
-		<string>2015-08-13</string>
+		<string>2016-10-27</string>
 		<key>OpenSourceModifications</key>
 		<array>
 		    <string>exec.c: eaccess</string>
 		    <string>input.c: remove multiple definition</string>
+		    <string>input.c: strchrnul</string>
 		    <string>miscbltin.c: warning fix</string>
 		    <string>mknodes.c: __printf0like</string>
 		    <string>trap.c: sys_nsig</string>
diff --git a/sh/shell.h b/sh/shell.h
index 679efc7..add2bd8 100644
--- a/sh/shell.h
+++ b/sh/shell.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)shell.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/shell.h 253658 2013-07-25 19:48:15Z jilles $
  */
 
 #ifndef SHELL_H_
diff --git a/sh/show.c b/sh/show.c
index db18ae9..0e8cf43 100644
--- a/sh/show.c
+++ b/sh/show.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/show.c 258776 2013-11-30 21:27:11Z jilles $");
 
 #include <fcntl.h>
 #include <stdio.h>
diff --git a/sh/show.h b/sh/show.h
index 4528fb1..d9b1666 100644
--- a/sh/show.h
+++ b/sh/show.h
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)show.h	1.1 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/show.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 void showtree(union node *);
diff --git a/sh/tests/Makefile b/sh/tests/Makefile
index c092962..27932f2 100644
--- a/sh/tests/Makefile
+++ b/sh/tests/Makefile
@@ -1,9 +1,7 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/Makefile 299094 2016-05-04 23:20:53Z ngie $
 
 .include <bsd.own.mk>
 
-TESTSDIR=	${TESTSBASE}/bin/sh
-
 TESTS_SUBDIRS+=	builtins
 TESTS_SUBDIRS+=	errors
 TESTS_SUBDIRS+=	execution
diff --git a/sh/tests/Makefile.depend b/sh/tests/Makefile.depend
new file mode 100644
index 0000000..9ff4aed
--- /dev/null
+++ b/sh/tests/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/builtins/Makefile b/sh/tests/builtins/Makefile
index ad39aac..0e6258f 100644
--- a/sh/tests/builtins/Makefile
+++ b/sh/tests/builtins/Makefile
@@ -1,4 +1,6 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/Makefile 305305 2016-09-02 21:13:46Z jilles $
+
+PACKAGE=	tests
 
 .include <src.opts.mk>
 
@@ -7,161 +9,173 @@ TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		alias.0 alias.0.stdout
-FILES+=		alias.1 alias.1.stderr
-FILES+=		alias3.0 alias3.0.stdout
-FILES+=		alias4.0
-FILES+=		break1.0
-FILES+=		break2.0 break2.0.stdout
-FILES+=		break3.0
-FILES+=		break4.4
-FILES+=		break5.4
-FILES+=		break6.0
-FILES+=		builtin1.0
-FILES+=		case1.0
-FILES+=		case2.0
-FILES+=		case3.0
-FILES+=		case4.0
-FILES+=		case5.0
-FILES+=		case6.0
-FILES+=		case7.0
-FILES+=		case8.0
-FILES+=		case9.0
-FILES+=		case10.0
-FILES+=		case11.0
-FILES+=		case12.0
-FILES+=		case13.0
-FILES+=		case14.0
-FILES+=		case15.0
-FILES+=		case16.0
-FILES+=		case17.0
-FILES+=		case18.0
-FILES+=		case19.0
-FILES+=		cd1.0
-FILES+=		cd2.0
-FILES+=		cd3.0
-FILES+=		cd4.0
-FILES+=		cd5.0
-FILES+=		cd6.0
-FILES+=		cd7.0
-FILES+=		cd8.0
-FILES+=		command1.0
-FILES+=		command2.0
-FILES+=		command3.0
-FILES+=		command3.0.stdout
-FILES+=		command4.0
-FILES+=		command5.0
-FILES+=		command5.0.stdout
-FILES+=		command6.0
-FILES+=		command6.0.stdout
-FILES+=		command7.0
-FILES+=		command8.0
-FILES+=		command9.0
-FILES+=		command10.0
-FILES+=		command11.0
-FILES+=		command12.0
-FILES+=		dot1.0
-FILES+=		dot2.0
-FILES+=		dot3.0
-FILES+=		dot4.0
-FILES+=		eval1.0
-FILES+=		eval2.0
-FILES+=		eval3.0
-FILES+=		eval4.0
-FILES+=		eval5.0
-FILES+=		eval6.0
-FILES+=		eval7.0
-FILES+=		eval8.7
-FILES+=		exec1.0
-FILES+=		exec2.0
-FILES+=		exit1.0
-FILES+=		exit2.8
-FILES+=		exit3.0
-FILES+=		export1.0
-FILES+=		fc1.0
-FILES+=		fc2.0
-FILES+=		for1.0
-FILES+=		for2.0
-FILES+=		for3.0
-FILES+=		getopts1.0 getopts1.0.stdout
-FILES+=		getopts2.0 getopts2.0.stdout
-FILES+=		getopts3.0
-FILES+=		getopts4.0
-FILES+=		getopts5.0
-FILES+=		getopts6.0
-FILES+=		getopts7.0
-FILES+=		getopts8.0 getopts8.0.stdout
-FILES+=		hash1.0 hash1.0.stdout
-FILES+=		hash2.0 hash2.0.stdout
-FILES+=		hash3.0 hash3.0.stdout
-FILES+=		hash4.0
-FILES+=		jobid1.0
-FILES+=		jobid2.0
-FILES+=		kill1.0 kill2.0
-FILES+=		lineno.0 lineno.0.stdout
-FILES+=		lineno2.0
-FILES+=		lineno3.0 lineno3.0.stdout
-FILES+=		local1.0
-FILES+=		local2.0
-FILES+=		local3.0
-FILES+=		local4.0
+${PACKAGE}FILES+=		alias.0 alias.0.stdout
+${PACKAGE}FILES+=		alias.1 alias.1.stderr
+${PACKAGE}FILES+=		alias3.0 alias3.0.stdout
+${PACKAGE}FILES+=		alias4.0
+${PACKAGE}FILES+=		break1.0
+${PACKAGE}FILES+=		break2.0 break2.0.stdout
+${PACKAGE}FILES+=		break3.0
+${PACKAGE}FILES+=		break4.4
+${PACKAGE}FILES+=		break5.4
+${PACKAGE}FILES+=		break6.0
+${PACKAGE}FILES+=		builtin1.0
+${PACKAGE}FILES+=		case1.0
+${PACKAGE}FILES+=		case2.0
+${PACKAGE}FILES+=		case3.0
+${PACKAGE}FILES+=		case4.0
+${PACKAGE}FILES+=		case5.0
+${PACKAGE}FILES+=		case6.0
+${PACKAGE}FILES+=		case7.0
+${PACKAGE}FILES+=		case8.0
+${PACKAGE}FILES+=		case9.0
+${PACKAGE}FILES+=		case10.0
+${PACKAGE}FILES+=		case11.0
+${PACKAGE}FILES+=		case12.0
+${PACKAGE}FILES+=		case13.0
+${PACKAGE}FILES+=		case14.0
+${PACKAGE}FILES+=		case15.0
+${PACKAGE}FILES+=		case16.0
+${PACKAGE}FILES+=		case17.0
+${PACKAGE}FILES+=		case18.0
+${PACKAGE}FILES+=		case19.0
+${PACKAGE}FILES+=		case20.0
+${PACKAGE}FILES+=		cd1.0
+${PACKAGE}FILES+=		cd2.0
+${PACKAGE}FILES+=		cd3.0
+${PACKAGE}FILES+=		cd4.0
+${PACKAGE}FILES+=		cd5.0
+${PACKAGE}FILES+=		cd6.0
+${PACKAGE}FILES+=		cd7.0
+${PACKAGE}FILES+=		cd8.0
+${PACKAGE}FILES+=		cd9.0 cd9.0.stdout
+${PACKAGE}FILES+=		command1.0
+${PACKAGE}FILES+=		command2.0
+${PACKAGE}FILES+=		command3.0
+${PACKAGE}FILES+=		command3.0.stdout
+${PACKAGE}FILES+=		command4.0
+${PACKAGE}FILES+=		command5.0
+${PACKAGE}FILES+=		command5.0.stdout
+${PACKAGE}FILES+=		command6.0
+${PACKAGE}FILES+=		command6.0.stdout
+${PACKAGE}FILES+=		command7.0
+${PACKAGE}FILES+=		command8.0
+${PACKAGE}FILES+=		command9.0
+${PACKAGE}FILES+=		command10.0
+${PACKAGE}FILES+=		command11.0
+${PACKAGE}FILES+=		command12.0
+${PACKAGE}FILES+=		dot1.0
+${PACKAGE}FILES+=		dot2.0
+${PACKAGE}FILES+=		dot3.0
+${PACKAGE}FILES+=		dot4.0
+${PACKAGE}FILES+=		echo1.0
+${PACKAGE}FILES+=		echo2.0
+${PACKAGE}FILES+=		echo3.0
+${PACKAGE}FILES+=		eval1.0
+${PACKAGE}FILES+=		eval2.0
+${PACKAGE}FILES+=		eval3.0
+${PACKAGE}FILES+=		eval4.0
+${PACKAGE}FILES+=		eval5.0
+${PACKAGE}FILES+=		eval6.0
+${PACKAGE}FILES+=		eval7.0
+${PACKAGE}FILES+=		eval8.7
+${PACKAGE}FILES+=		exec1.0
+${PACKAGE}FILES+=		exec2.0
+${PACKAGE}FILES+=		exit1.0
+${PACKAGE}FILES+=		exit2.8
+${PACKAGE}FILES+=		exit3.0
+${PACKAGE}FILES+=		export1.0
+${PACKAGE}FILES+=		fc1.0
+${PACKAGE}FILES+=		fc2.0
+${PACKAGE}FILES+=		for1.0
+${PACKAGE}FILES+=		for2.0
+${PACKAGE}FILES+=		for3.0
+${PACKAGE}FILES+=		getopts1.0 getopts1.0.stdout
+${PACKAGE}FILES+=		getopts2.0 getopts2.0.stdout
+${PACKAGE}FILES+=		getopts3.0
+${PACKAGE}FILES+=		getopts4.0
+${PACKAGE}FILES+=		getopts5.0
+${PACKAGE}FILES+=		getopts6.0
+${PACKAGE}FILES+=		getopts7.0
+${PACKAGE}FILES+=		getopts8.0 getopts8.0.stdout
+${PACKAGE}FILES+=		getopts9.0 getopts9.0.stdout
+${PACKAGE}FILES+=		getopts10.0
+${PACKAGE}FILES+=		hash1.0 hash1.0.stdout
+${PACKAGE}FILES+=		hash2.0 hash2.0.stdout
+${PACKAGE}FILES+=		hash3.0 hash3.0.stdout
+${PACKAGE}FILES+=		hash4.0
+${PACKAGE}FILES+=		jobid1.0
+${PACKAGE}FILES+=		jobid2.0
+${PACKAGE}FILES+=		kill1.0 kill2.0
+${PACKAGE}FILES+=		lineno.0 lineno.0.stdout
+${PACKAGE}FILES+=		lineno2.0
+${PACKAGE}FILES+=		lineno3.0 lineno3.0.stdout
+${PACKAGE}FILES+=		local1.0
+${PACKAGE}FILES+=		local2.0
+${PACKAGE}FILES+=		local3.0
+${PACKAGE}FILES+=		local4.0
+${PACKAGE}FILES+=		local5.0
+${PACKAGE}FILES+=		local6.0
+${PACKAGE}FILES+=		local7.0
 .if ${MK_NLS} != "no"
-FILES+=		locale1.0
+${PACKAGE}FILES+=		locale1.0
 .endif
-FILES+=		printf1.0
-FILES+=		printf2.0
-FILES+=		printf3.0
-FILES+=		printf4.0
-FILES+=		read1.0 read1.0.stdout
-FILES+=		read2.0
-FILES+=		read3.0 read3.0.stdout
-FILES+=		read4.0 read4.0.stdout
-FILES+=		read5.0
-FILES+=		read6.0
-FILES+=		read7.0
-FILES+=		return1.0
-FILES+=		return2.1
-FILES+=		return3.1
-FILES+=		return4.0
-FILES+=		return5.0
-FILES+=		return6.4
-FILES+=		return7.4
-FILES+=		return8.0
-FILES+=		set1.0
-FILES+=		set2.0
-FILES+=		trap1.0
-FILES+=		trap10.0
-FILES+=		trap11.0
-FILES+=		trap12.0
-FILES+=		trap13.0
-FILES+=		trap14.0
-FILES+=		trap15.0
-FILES+=		trap16.0
-FILES+=		trap2.0
-FILES+=		trap3.0
-FILES+=		trap4.0
-FILES+=		trap5.0
-FILES+=		trap6.0
-FILES+=		trap7.0
-FILES+=		trap8.0
-FILES+=		trap9.0
-FILES+=		type1.0 type1.0.stderr
-FILES+=		type2.0
-FILES+=		type3.0
-FILES+=		unalias.0
-FILES+=		var-assign.0
-FILES+=		var-assign2.0
-FILES+=		wait1.0
-FILES+=		wait2.0
-FILES+=		wait3.0
-FILES+=		wait4.0
-FILES+=		wait5.0
-FILES+=		wait6.0
-FILES+=		wait7.0
-FILES+=		wait8.0
-FILES+=		wait9.127
-FILES+=		wait10.0
+${PACKAGE}FILES+=		printf1.0
+${PACKAGE}FILES+=		printf2.0
+${PACKAGE}FILES+=		printf3.0
+${PACKAGE}FILES+=		printf4.0
+${PACKAGE}FILES+=		read1.0 read1.0.stdout
+${PACKAGE}FILES+=		read2.0
+${PACKAGE}FILES+=		read3.0 read3.0.stdout
+${PACKAGE}FILES+=		read4.0 read4.0.stdout
+${PACKAGE}FILES+=		read5.0
+${PACKAGE}FILES+=		read6.0
+${PACKAGE}FILES+=		read7.0
+${PACKAGE}FILES+=		read8.0
+${PACKAGE}FILES+=		read9.0
+${PACKAGE}FILES+=		return1.0
+${PACKAGE}FILES+=		return2.1
+${PACKAGE}FILES+=		return3.1
+${PACKAGE}FILES+=		return4.0
+${PACKAGE}FILES+=		return5.0
+${PACKAGE}FILES+=		return6.4
+${PACKAGE}FILES+=		return7.4
+${PACKAGE}FILES+=		return8.0
+${PACKAGE}FILES+=		set1.0
+${PACKAGE}FILES+=		set2.0
+${PACKAGE}FILES+=		set3.0
+${PACKAGE}FILES+=		trap1.0
+${PACKAGE}FILES+=		trap10.0
+${PACKAGE}FILES+=		trap11.0
+${PACKAGE}FILES+=		trap12.0
+${PACKAGE}FILES+=		trap13.0
+${PACKAGE}FILES+=		trap14.0
+${PACKAGE}FILES+=		trap15.0
+${PACKAGE}FILES+=		trap16.0
+${PACKAGE}FILES+=		trap17.0
+${PACKAGE}FILES+=		trap2.0
+${PACKAGE}FILES+=		trap3.0
+${PACKAGE}FILES+=		trap4.0
+${PACKAGE}FILES+=		trap5.0
+${PACKAGE}FILES+=		trap6.0
+${PACKAGE}FILES+=		trap7.0
+${PACKAGE}FILES+=		trap8.0
+${PACKAGE}FILES+=		trap9.0
+${PACKAGE}FILES+=		type1.0 type1.0.stderr
+${PACKAGE}FILES+=		type2.0
+${PACKAGE}FILES+=		type3.0
+${PACKAGE}FILES+=		unalias.0
+${PACKAGE}FILES+=		var-assign.0
+${PACKAGE}FILES+=		var-assign2.0
+${PACKAGE}FILES+=		wait1.0
+${PACKAGE}FILES+=		wait2.0
+${PACKAGE}FILES+=		wait3.0
+${PACKAGE}FILES+=		wait4.0
+${PACKAGE}FILES+=		wait5.0
+${PACKAGE}FILES+=		wait6.0
+${PACKAGE}FILES+=		wait7.0
+${PACKAGE}FILES+=		wait8.0
+${PACKAGE}FILES+=		wait9.127
+${PACKAGE}FILES+=		wait10.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/builtins/Makefile.depend b/sh/tests/builtins/Makefile.depend
new file mode 100644
index 0000000..21c5642
--- /dev/null
+++ b/sh/tests/builtins/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/builtins/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/builtins/alias.0 b/sh/tests/builtins/alias.0
index d9b2796..067a890 100644
--- a/sh/tests/builtins/alias.0
+++ b/sh/tests/builtins/alias.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/alias.0 190285 2009-03-22 21:12:00Z stefanf $
 set -e
 
 unalias -a
diff --git a/sh/tests/builtins/alias.1 b/sh/tests/builtins/alias.1
index 31403dc..22093dd 100644
--- a/sh/tests/builtins/alias.1
+++ b/sh/tests/builtins/alias.1
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/alias.1 149781 2005-09-04 11:59:59Z stefanf $
 unalias -a
 alias foo
diff --git a/sh/tests/builtins/alias3.0 b/sh/tests/builtins/alias3.0
index fe65e31..e2e215a 100644
--- a/sh/tests/builtins/alias3.0
+++ b/sh/tests/builtins/alias3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/alias3.0 242767 2012-11-08 13:36:19Z jilles $
 set -e
 
 unalias -a
diff --git a/sh/tests/builtins/alias4.0 b/sh/tests/builtins/alias4.0
index 3d5efec..d86559b 100644
--- a/sh/tests/builtins/alias4.0
+++ b/sh/tests/builtins/alias4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/alias4.0 254849 2013-08-25 11:42:53Z jilles $
 
 unalias -a
 alias --
diff --git a/sh/tests/builtins/break1.0 b/sh/tests/builtins/break1.0
index ba0cbb4..219cbf2 100644
--- a/sh/tests/builtins/break1.0
+++ b/sh/tests/builtins/break1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/break1.0 211349 2010-08-15 21:06:53Z jilles $
 
 if [ "$1" != nested ]; then
 	while :; do
diff --git a/sh/tests/builtins/break2.0 b/sh/tests/builtins/break2.0
index ff52dd3..f836e31 100644
--- a/sh/tests/builtins/break2.0
+++ b/sh/tests/builtins/break2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/break2.0 211467 2010-08-18 20:26:50Z jilles $
 
 # It is not immediately obvious that this should work, and someone probably
 # relies on it.
diff --git a/sh/tests/builtins/break3.0 b/sh/tests/builtins/break3.0
index 10a5ca8..1a6985c 100644
--- a/sh/tests/builtins/break3.0
+++ b/sh/tests/builtins/break3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/break3.0 211612 2010-08-22 11:07:46Z jilles $
 
 # We accept this and people might rely on it.
 # However, various other shells do not accept it.
diff --git a/sh/tests/builtins/break4.4 b/sh/tests/builtins/break4.4
index d52ff52..3b1bb0c 100644
--- a/sh/tests/builtins/break4.4
+++ b/sh/tests/builtins/break4.4
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/break4.4 251180 2013-05-31 14:45:25Z jilles $
 
 # Although this is not specified by POSIX, some configure scripts (gawk 4.1.0)
 # appear to depend on it.
diff --git a/sh/tests/builtins/break5.4 b/sh/tests/builtins/break5.4
index 7df8e18..a29f317 100644
--- a/sh/tests/builtins/break5.4
+++ b/sh/tests/builtins/break5.4
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/break5.4 251180 2013-05-31 14:45:25Z jilles $
 
 # Although this is not specified by POSIX, some configure scripts (gawk 4.1.0)
 # appear to depend on it.
diff --git a/sh/tests/builtins/break6.0 b/sh/tests/builtins/break6.0
index 09fc0d8..b5fc63b 100644
--- a/sh/tests/builtins/break6.0
+++ b/sh/tests/builtins/break6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/break6.0 268927 2014-07-20 20:29:09Z jilles $
 # Per POSIX, this need only work if LONG_MAX > 4294967295.
 
 while :; do
diff --git a/sh/tests/builtins/builtin1.0 b/sh/tests/builtins/builtin1.0
index b608385..dd77422 100644
--- a/sh/tests/builtins/builtin1.0
+++ b/sh/tests/builtins/builtin1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/builtin1.0 201431 2010-01-03 15:01:38Z jilles $
 
 failures=0
 
diff --git a/sh/tests/builtins/case1.0 b/sh/tests/builtins/case1.0
index 860fc67..b8e8d9b 100644
--- a/sh/tests/builtins/case1.0
+++ b/sh/tests/builtins/case1.0
@@ -1,4 +1,4 @@
-#$FreeBSD$
+#$FreeBSD: head/bin/sh/tests/builtins/case1.0 172440 2007-10-04 16:14:48Z stefanf $
 f()
 {
 	false
diff --git a/sh/tests/builtins/case10.0 b/sh/tests/builtins/case10.0
index a627b5c..e8cd933 100644
--- a/sh/tests/builtins/case10.0
+++ b/sh/tests/builtins/case10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case10.0 223546 2011-06-25 20:37:43Z jilles $
 
 case ! in
 [\!!]) ;;
diff --git a/sh/tests/builtins/case11.0 b/sh/tests/builtins/case11.0
index 0e66e11..afcfa43 100644
--- a/sh/tests/builtins/case11.0
+++ b/sh/tests/builtins/case11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case11.0 228007 2011-11-26 22:28:25Z jilles $
 
 false
 case x in
diff --git a/sh/tests/builtins/case12.0 b/sh/tests/builtins/case12.0
index 2a442ba..630bee5 100644
--- a/sh/tests/builtins/case12.0
+++ b/sh/tests/builtins/case12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case12.0 228007 2011-11-26 22:28:25Z jilles $
 
 false
 case x in
diff --git a/sh/tests/builtins/case13.0 b/sh/tests/builtins/case13.0
index 78f4e9b..669ce62 100644
--- a/sh/tests/builtins/case13.0
+++ b/sh/tests/builtins/case13.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case13.0 228943 2011-12-28 23:51:17Z jilles $
 
 case ^ in
 [\^^]) ;;
diff --git a/sh/tests/builtins/case14.0 b/sh/tests/builtins/case14.0
index 0338e8a..f6a68cb 100644
--- a/sh/tests/builtins/case14.0
+++ b/sh/tests/builtins/case14.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case14.0 230154 2012-01-15 20:04:05Z jilles $
 
 case `false` in
 no) exit 3 ;;
diff --git a/sh/tests/builtins/case15.0 b/sh/tests/builtins/case15.0
index 09b0e11..083aaa6 100644
--- a/sh/tests/builtins/case15.0
+++ b/sh/tests/builtins/case15.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case15.0 230154 2012-01-15 20:04:05Z jilles $
 
 case x in
 `false`) exit 3 ;;
diff --git a/sh/tests/builtins/case16.0 b/sh/tests/builtins/case16.0
index 2430302..7031a92 100644
--- a/sh/tests/builtins/case16.0
+++ b/sh/tests/builtins/case16.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case16.0 230154 2012-01-15 20:04:05Z jilles $
 
 f() { return 42; }
 f
diff --git a/sh/tests/builtins/case17.0 b/sh/tests/builtins/case17.0
index ed1d25f..10d8d9c 100644
--- a/sh/tests/builtins/case17.0
+++ b/sh/tests/builtins/case17.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case17.0 230161 2012-01-15 21:39:38Z jilles $
 
 ! case x in x) false ;& y) esac
diff --git a/sh/tests/builtins/case18.0 b/sh/tests/builtins/case18.0
index 470253f..b0e601f 100644
--- a/sh/tests/builtins/case18.0
+++ b/sh/tests/builtins/case18.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case18.0 230161 2012-01-15 21:39:38Z jilles $
 
 case x$(false) in
 x)	;&
diff --git a/sh/tests/builtins/case19.0 b/sh/tests/builtins/case19.0
index 215066a..1a9b09a 100644
--- a/sh/tests/builtins/case19.0
+++ b/sh/tests/builtins/case19.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case19.0 230161 2012-01-15 21:39:38Z jilles $
 
 [ "`case x in
 x)	false ;&
diff --git a/sh/tests/builtins/case2.0 b/sh/tests/builtins/case2.0
index e319148..ae3f356 100644
--- a/sh/tests/builtins/case2.0
+++ b/sh/tests/builtins/case2.0
@@ -1,5 +1,5 @@
 # Generated by ./test-fnmatch -s 1, do not edit.
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case2.0 207821 2010-05-09 16:15:40Z jilles $
 failures=
 failed() { printf '%s\n' "Failed: $1 '$2' '$3'"; failures=x$failures; }
 testmatch() { eval "case \$2 in ''$1) ;; *) failed testmatch \"\$@\";; esac"; }
diff --git a/sh/tests/builtins/case20.0 b/sh/tests/builtins/case20.0
new file mode 100644
index 0000000..bd91e5b
--- /dev/null
+++ b/sh/tests/builtins/case20.0
@@ -0,0 +1,9 @@
+# $FreeBSD: head/bin/sh/tests/builtins/case20.0 287148 2015-08-25 21:55:15Z jilles $
+
+# Shells do not agree about what this pattern should match, but it is
+# certain that it must not crash and the missing close bracket must not
+# be simply ignored.
+
+case B in
+[[:alpha:]) echo bad ;;
+esac
diff --git a/sh/tests/builtins/case3.0 b/sh/tests/builtins/case3.0
index 42e53d6..a2efd87 100644
--- a/sh/tests/builtins/case3.0
+++ b/sh/tests/builtins/case3.0
@@ -1,5 +1,5 @@
 # Generated by ./test-fnmatch -s 2, do not edit.
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case3.0 207821 2010-05-09 16:15:40Z jilles $
 failures=
 failed() { printf '%s\n' "Failed: $1 '$2' '$3'"; failures=x$failures; }
 # We do not treat a backslash specially in this case,
diff --git a/sh/tests/builtins/case4.0 b/sh/tests/builtins/case4.0
index 18219f5..7ba29ee 100644
--- a/sh/tests/builtins/case4.0
+++ b/sh/tests/builtins/case4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case4.0 220654 2011-04-15 15:14:58Z jilles $
 
 set -- "*"
 case x in
diff --git a/sh/tests/builtins/case5.0 b/sh/tests/builtins/case5.0
index 8c6db5a..e8b141a 100644
--- a/sh/tests/builtins/case5.0
+++ b/sh/tests/builtins/case5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case5.0 221646 2011-05-08 11:32:20Z jilles $
 
 unset LC_ALL
 LC_CTYPE=en_US.UTF-8
diff --git a/sh/tests/builtins/case6.0 b/sh/tests/builtins/case6.0
index 8d79183..7bc1da8 100644
--- a/sh/tests/builtins/case6.0
+++ b/sh/tests/builtins/case6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case6.0 223007 2011-06-12 12:27:17Z jilles $
 
 unset LC_ALL
 LC_CTYPE=de_DE.ISO8859-1
diff --git a/sh/tests/builtins/case7.0 b/sh/tests/builtins/case7.0
index 96b9de6..b351ad5 100644
--- a/sh/tests/builtins/case7.0
+++ b/sh/tests/builtins/case7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case7.0 302829 2016-07-14 09:34:42Z ache $
 
 # Character ranges in a locale other than the POSIX locale, not specified
 # by POSIX.
diff --git a/sh/tests/builtins/case8.0 b/sh/tests/builtins/case8.0
index 8d9f8b6..c63c6e7 100644
--- a/sh/tests/builtins/case8.0
+++ b/sh/tests/builtins/case8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case8.0 223120 2011-06-15 21:48:10Z jilles $
 
 case aZ_ in
 [[:alpha:]_][[:upper:]_][[:alpha:]_]) ;;
diff --git a/sh/tests/builtins/case9.0 b/sh/tests/builtins/case9.0
index 476caec..e374ef0 100644
--- a/sh/tests/builtins/case9.0
+++ b/sh/tests/builtins/case9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/case9.0 223186 2011-06-17 13:03:49Z jilles $
 
 errors=0
 
diff --git a/sh/tests/builtins/cd1.0 b/sh/tests/builtins/cd1.0
index bc5108e..d797157 100644
--- a/sh/tests/builtins/cd1.0
+++ b/sh/tests/builtins/cd1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd1.0 228975 2011-12-30 00:04:11Z uqs $
 set -e
 
 P=${TMPDIR:-/tmp}
diff --git a/sh/tests/builtins/cd2.0 b/sh/tests/builtins/cd2.0
index f2b6416..b7d39f3 100644
--- a/sh/tests/builtins/cd2.0
+++ b/sh/tests/builtins/cd2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd2.0 216019 2010-11-28 22:49:58Z jilles $
 set -e
 
 L=$(getconf PATH_MAX / 2>/dev/null) || L=4096
diff --git a/sh/tests/builtins/cd3.0 b/sh/tests/builtins/cd3.0
index 7729c54..aab8bc0 100644
--- a/sh/tests/builtins/cd3.0
+++ b/sh/tests/builtins/cd3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd3.0 222154 2011-05-20 22:55:18Z jilles $
 
 # If fully successful, cd -Pe must be like cd -P.
 
diff --git a/sh/tests/builtins/cd4.0 b/sh/tests/builtins/cd4.0
index df3a9a4..da01b31 100644
--- a/sh/tests/builtins/cd4.0
+++ b/sh/tests/builtins/cd4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd4.0 222154 2011-05-20 22:55:18Z jilles $
 
 # This test assumes that whatever mechanism cd -P uses to determine the
 # pathname to the current directory if it is longer than PATH_MAX requires
diff --git a/sh/tests/builtins/cd5.0 b/sh/tests/builtins/cd5.0
index 3dff604..8a285e0 100644
--- a/sh/tests/builtins/cd5.0
+++ b/sh/tests/builtins/cd5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd5.0 222379 2011-05-27 19:36:07Z jilles $
 
 set -e
 T=$(mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXX")
diff --git a/sh/tests/builtins/cd6.0 b/sh/tests/builtins/cd6.0
index 083a061..171c996 100644
--- a/sh/tests/builtins/cd6.0
+++ b/sh/tests/builtins/cd6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd6.0 222381 2011-05-27 20:01:46Z jilles $
 
 set -e
 cd -P /bin
diff --git a/sh/tests/builtins/cd7.0 b/sh/tests/builtins/cd7.0
index 9adda86..d4cae39 100644
--- a/sh/tests/builtins/cd7.0
+++ b/sh/tests/builtins/cd7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd7.0 222381 2011-05-27 20:01:46Z jilles $
 
 set -e
 cd /usr/bin
diff --git a/sh/tests/builtins/cd8.0 b/sh/tests/builtins/cd8.0
index a68f77f..ab17d38 100644
--- a/sh/tests/builtins/cd8.0
+++ b/sh/tests/builtins/cd8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/cd8.0 230095 2012-01-13 23:32:27Z jilles $
 
 # The exact wording of the error message is not standardized, but giving
 # a description of the errno is useful.
diff --git a/sh/tests/builtins/cd9.0 b/sh/tests/builtins/cd9.0
new file mode 100644
index 0000000..e929878
--- /dev/null
+++ b/sh/tests/builtins/cd9.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/builtins/cd9.0 293371 2016-01-07 21:46:07Z jilles $
+
+cd /dev
+cd /bin
+cd - >/dev/null
+pwd
+cd - >/dev/null
+pwd
diff --git a/sh/tests/builtins/cd9.0.stdout b/sh/tests/builtins/cd9.0.stdout
new file mode 100644
index 0000000..dac16a7
--- /dev/null
+++ b/sh/tests/builtins/cd9.0.stdout
@@ -0,0 +1,2 @@
+/dev
+/bin
diff --git a/sh/tests/builtins/command1.0 b/sh/tests/builtins/command1.0
index fd0afdf..5454c3f 100644
--- a/sh/tests/builtins/command1.0
+++ b/sh/tests/builtins/command1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command1.0 151797 2005-10-28 14:02:42Z stefanf $
 true() {
 	false
 }
diff --git a/sh/tests/builtins/command10.0 b/sh/tests/builtins/command10.0
index 2c1adf1..08bddaf 100644
--- a/sh/tests/builtins/command10.0
+++ b/sh/tests/builtins/command10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command10.0 204802 2010-03-06 17:31:09Z jilles $
 
 failures=0
 
diff --git a/sh/tests/builtins/command11.0 b/sh/tests/builtins/command11.0
index 10c8647..0eb2047 100644
--- a/sh/tests/builtins/command11.0
+++ b/sh/tests/builtins/command11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command11.0 205154 2010-03-14 14:24:35Z jilles $
 
 failures=0
 
diff --git a/sh/tests/builtins/command12.0 b/sh/tests/builtins/command12.0
index f981db3..6d9e8e7 100644
--- a/sh/tests/builtins/command12.0
+++ b/sh/tests/builtins/command12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command12.0 257929 2013-11-10 23:00:39Z jilles $
 
 alias aa=echo\ \'\"\'
 cmd=$(command -v aa)
diff --git a/sh/tests/builtins/command2.0 b/sh/tests/builtins/command2.0
index ff7b5f2..7b49092 100644
--- a/sh/tests/builtins/command2.0
+++ b/sh/tests/builtins/command2.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command2.0 151797 2005-10-28 14:02:42Z stefanf $
 PATH=
 command -p cat < /dev/null
diff --git a/sh/tests/builtins/command3.0 b/sh/tests/builtins/command3.0
index 9d4ae89..6d6355d 100644
--- a/sh/tests/builtins/command3.0
+++ b/sh/tests/builtins/command3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command3.0 211399 2010-08-16 17:18:08Z jilles $
 command -v ls
 command -v true
 command -v /bin/ls
diff --git a/sh/tests/builtins/command4.0 b/sh/tests/builtins/command4.0
index 3e49613..2349669 100644
--- a/sh/tests/builtins/command4.0
+++ b/sh/tests/builtins/command4.0
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command4.0 211973 2010-08-29 20:53:24Z jilles $
 ! command -v nonexisting
diff --git a/sh/tests/builtins/command5.0 b/sh/tests/builtins/command5.0
index 13b3fe1..7c99b52 100644
--- a/sh/tests/builtins/command5.0
+++ b/sh/tests/builtins/command5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command5.0 211399 2010-08-16 17:18:08Z jilles $
 command -V ls
 command -V true
 command -V /bin/ls
diff --git a/sh/tests/builtins/command6.0 b/sh/tests/builtins/command6.0
index 5b63bfe..d1902ed 100644
--- a/sh/tests/builtins/command6.0
+++ b/sh/tests/builtins/command6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command6.0 218356 2011-02-05 23:00:24Z jilles $
 PATH=/var/empty
 case $(command -pV ls) in
 */var/empty/ls*)
diff --git a/sh/tests/builtins/command7.0 b/sh/tests/builtins/command7.0
index fc652f2..b8351f2 100644
--- a/sh/tests/builtins/command7.0
+++ b/sh/tests/builtins/command7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command7.0 218356 2011-02-05 23:00:24Z jilles $
 
 failures=0
 
diff --git a/sh/tests/builtins/command8.0 b/sh/tests/builtins/command8.0
index 9e3a2b6..54848d1 100644
--- a/sh/tests/builtins/command8.0
+++ b/sh/tests/builtins/command8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command8.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break,\
diff --git a/sh/tests/builtins/command9.0 b/sh/tests/builtins/command9.0
index 212e52a..40f98c1 100644
--- a/sh/tests/builtins/command9.0
+++ b/sh/tests/builtins/command9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/command9.0 204801 2010-03-06 17:09:22Z jilles $
 
 failures=0
 
diff --git a/sh/tests/builtins/dot1.0 b/sh/tests/builtins/dot1.0
index 43eab0d..0aa69a8 100644
--- a/sh/tests/builtins/dot1.0
+++ b/sh/tests/builtins/dot1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/dot1.0 208629 2010-05-28 22:08:34Z jilles $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/dot2.0 b/sh/tests/builtins/dot2.0
index ed6379b..dba591e 100644
--- a/sh/tests/builtins/dot2.0
+++ b/sh/tests/builtins/dot2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/dot2.0 208630 2010-05-28 22:40:24Z jilles $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/dot3.0 b/sh/tests/builtins/dot3.0
index b337f0f..d1589a0 100644
--- a/sh/tests/builtins/dot3.0
+++ b/sh/tests/builtins/dot3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/dot3.0 219390 2011-03-07 23:52:23Z jilles $
 
 # . should return 0 if no command was executed.
 
diff --git a/sh/tests/builtins/dot4.0 b/sh/tests/builtins/dot4.0
index b898131..d280f35 100644
--- a/sh/tests/builtins/dot4.0
+++ b/sh/tests/builtins/dot4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/dot4.0 222174 2011-05-22 12:15:14Z jilles $
 
 v=abcd
 v=$v$v$v$v
diff --git a/sh/tests/builtins/echo1.0 b/sh/tests/builtins/echo1.0
new file mode 100644
index 0000000..34d75a6
--- /dev/null
+++ b/sh/tests/builtins/echo1.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/builtins/echo1.0 305305 2016-09-02 21:13:46Z jilles $
+
+# Not specified by POSIX.
+
+[ "`echo -n a b; echo c d; echo e f`" = "a bc d
+e f" ]
diff --git a/sh/tests/builtins/echo2.0 b/sh/tests/builtins/echo2.0
new file mode 100644
index 0000000..3eae51b
--- /dev/null
+++ b/sh/tests/builtins/echo2.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/builtins/echo2.0 305305 2016-09-02 21:13:46Z jilles $
+
+# Not specified by POSIX.
+
+a=`echo -e '\a\b\e\f\n\r\t\v\\\\\0041\c'; echo .`
+b=`printf '\a\b\033\f\n\r\t\v\\\\!.'`
+[ "$a" = "$b" ]
diff --git a/sh/tests/builtins/echo3.0 b/sh/tests/builtins/echo3.0
new file mode 100644
index 0000000..aa86443
--- /dev/null
+++ b/sh/tests/builtins/echo3.0
@@ -0,0 +1,5 @@
+# $FreeBSD: head/bin/sh/tests/builtins/echo3.0 305305 2016-09-02 21:13:46Z jilles $
+
+# Not specified by POSIX.
+
+[ "`echo -e 'a\cb' c; echo d`" = "ad" ]
diff --git a/sh/tests/builtins/eval1.0 b/sh/tests/builtins/eval1.0
index 04606a4..ad099ce 100644
--- a/sh/tests/builtins/eval1.0
+++ b/sh/tests/builtins/eval1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval1.0 193178 2009-05-31 17:23:27Z stefanf $
 set -e
 
 eval
diff --git a/sh/tests/builtins/eval2.0 b/sh/tests/builtins/eval2.0
index bf06b6e..4df41ea 100644
--- a/sh/tests/builtins/eval2.0
+++ b/sh/tests/builtins/eval2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval2.0 194897 2009-06-24 20:22:54Z jilles $
 
 eval '
 false
diff --git a/sh/tests/builtins/eval3.0 b/sh/tests/builtins/eval3.0
index dfb8357..04f9720 100644
--- a/sh/tests/builtins/eval3.0
+++ b/sh/tests/builtins/eval3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval3.0 196607 2009-08-27 22:23:23Z jilles $
 
 eval 'false;' && exit 1
 eval 'true;' || exit 1
diff --git a/sh/tests/builtins/eval4.0 b/sh/tests/builtins/eval4.0
index 67da2f5..82c3ea9 100644
--- a/sh/tests/builtins/eval4.0
+++ b/sh/tests/builtins/eval4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval4.0 210738 2010-08-01 22:39:07Z jilles $
 
 # eval should preserve $? from command substitutions when starting
 # the parsed command.
diff --git a/sh/tests/builtins/eval5.0 b/sh/tests/builtins/eval5.0
index 3e86de9..89e79b8 100644
--- a/sh/tests/builtins/eval5.0
+++ b/sh/tests/builtins/eval5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval5.0 210829 2010-08-03 22:17:29Z jilles $
 
 # eval should return 0 if no command was executed.
 eval $(false)
diff --git a/sh/tests/builtins/eval6.0 b/sh/tests/builtins/eval6.0
index 6752bb6..bfce89f 100644
--- a/sh/tests/builtins/eval6.0
+++ b/sh/tests/builtins/eval6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval6.0 249220 2013-04-06 22:30:46Z jilles $
 
 # eval should preserve $? from command substitutions when starting
 # the parsed command.
diff --git a/sh/tests/builtins/eval7.0 b/sh/tests/builtins/eval7.0
index a309c91..f694e73 100644
--- a/sh/tests/builtins/eval7.0
+++ b/sh/tests/builtins/eval7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval7.0 272983 2014-10-12 13:12:06Z jilles $
 # Assumes that break can break out of a loop outside eval.
 
 while :; do
diff --git a/sh/tests/builtins/eval8.7 b/sh/tests/builtins/eval8.7
index af6064c..30902cc 100644
--- a/sh/tests/builtins/eval8.7
+++ b/sh/tests/builtins/eval8.7
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/eval8.7 272983 2014-10-12 13:12:06Z jilles $
 
 f() {
 	eval "return 7
diff --git a/sh/tests/builtins/exec1.0 b/sh/tests/builtins/exec1.0
index dd30a4c..8c5bb01 100644
--- a/sh/tests/builtins/exec1.0
+++ b/sh/tests/builtins/exec1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/exec1.0 213738 2010-10-12 18:20:38Z obrien $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/exec2.0 b/sh/tests/builtins/exec2.0
index 3dcb6c4..5395ba6 100644
--- a/sh/tests/builtins/exec2.0
+++ b/sh/tests/builtins/exec2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/exec2.0 213738 2010-10-12 18:20:38Z obrien $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/exit1.0 b/sh/tests/builtins/exit1.0
index 496d448..4c378f2 100644
--- a/sh/tests/builtins/exit1.0
+++ b/sh/tests/builtins/exit1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/exit1.0 216871 2011-01-01 15:25:15Z jilles $
 
 # exit with an argument should overwrite the exit status in an EXIT trap.
 
diff --git a/sh/tests/builtins/exit2.8 b/sh/tests/builtins/exit2.8
index 124c32e..51d38f7 100644
--- a/sh/tests/builtins/exit2.8
+++ b/sh/tests/builtins/exit2.8
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/exit2.8 217172 2011-01-08 23:00:38Z jilles $
 
 # exit without arguments is the same as exit $? outside a trap.
 
diff --git a/sh/tests/builtins/exit3.0 b/sh/tests/builtins/exit3.0
index 80655ac..4e0c96c 100644
--- a/sh/tests/builtins/exit3.0
+++ b/sh/tests/builtins/exit3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/exit3.0 217175 2011-01-08 23:08:13Z jilles $
 
 # exit without arguments differs from exit $? in an EXIT trap.
 
diff --git a/sh/tests/builtins/export1.0 b/sh/tests/builtins/export1.0
index 7b08c9d..a09263a 100644
--- a/sh/tests/builtins/export1.0
+++ b/sh/tests/builtins/export1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/export1.0 223183 2011-06-17 10:21:24Z jilles $
 
 env @badness=1 ${SH} -c 'v=`export -p`; eval "$v"'
diff --git a/sh/tests/builtins/fc1.0 b/sh/tests/builtins/fc1.0
index ab7a387..042cb33 100644
--- a/sh/tests/builtins/fc1.0
+++ b/sh/tests/builtins/fc1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/fc1.0 213738 2010-10-12 18:20:38Z obrien $
 set -e
 trap 'echo Broken pipe -- test failed' PIPE
 
diff --git a/sh/tests/builtins/fc2.0 b/sh/tests/builtins/fc2.0
index 7eb92ac..a6151f7 100644
--- a/sh/tests/builtins/fc2.0
+++ b/sh/tests/builtins/fc2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/fc2.0 213738 2010-10-12 18:20:38Z obrien $
 set -e
 trap 'echo Broken pipe -- test failed' PIPE
 
diff --git a/sh/tests/builtins/for1.0 b/sh/tests/builtins/for1.0
index cd55e2c..276cb0a 100644
--- a/sh/tests/builtins/for1.0
+++ b/sh/tests/builtins/for1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/for1.0 226892 2011-10-28 23:02:21Z jilles $
 
 false
 for i in `false`; do exit 3; done
diff --git a/sh/tests/builtins/for2.0 b/sh/tests/builtins/for2.0
index 48c22ce..2b702ce 100644
--- a/sh/tests/builtins/for2.0
+++ b/sh/tests/builtins/for2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/for2.0 230463 2012-01-22 14:00:33Z jilles $
 
 r=x
 f() { return 42; }
diff --git a/sh/tests/builtins/for3.0 b/sh/tests/builtins/for3.0
index cc37238..a345caa 100644
--- a/sh/tests/builtins/for3.0
+++ b/sh/tests/builtins/for3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/for3.0 230463 2012-01-22 14:00:33Z jilles $
 
 r=x
 f() { return 42; }
diff --git a/sh/tests/builtins/getopts1.0 b/sh/tests/builtins/getopts1.0
index 64763bc..d3e7415 100644
--- a/sh/tests/builtins/getopts1.0
+++ b/sh/tests/builtins/getopts1.0
@@ -1,9 +1,9 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts1.0 297752 2016-04-09 16:06:13Z jilles $
 
 printf -- '-1-\n'
 set -- -abc
 getopts "ab:" OPTION
-echo ${OPTION}
+printf '%s\n' "${OPTION}"
 
 # In this case 'getopts' should realize that we have not provided the
 # required argument for "-b".
@@ -14,12 +14,12 @@ echo ${OPTION}
 printf -- '-2-\n'
 set -- -ab
 getopts "ab:" OPTION
-echo ${OPTION}
+printf '%s\n' "${OPTION}"
 getopts "ab:" OPTION 3>&2 2>&1 >&3 3>&-
-echo ${OPTION}
+printf '%s\n' "${OPTION}"
 
 # The 'shift' is aimed at causing an error.
 printf -- '-3-\n'
 shift 1
 getopts "ab:" OPTION
-echo ${OPTION}
+printf '%s\n' "${OPTION}"
diff --git a/sh/tests/builtins/getopts10.0 b/sh/tests/builtins/getopts10.0
new file mode 100644
index 0000000..7d34ddc
--- /dev/null
+++ b/sh/tests/builtins/getopts10.0
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/builtins/getopts10.0 293359 2016-01-07 20:48:24Z jilles $
+
+set -- -x arg
+opt=not
+getopts x opt
+r1=$? OPTIND1=$OPTIND opt1=$opt
+: $(: $((OPTIND = 1)))
+getopts x opt
+r2=$? OPTIND2=$OPTIND
+[ "$r1" = 0 ] && [ "$OPTIND1" = 2 ] && [ "$opt1" = x ] && [ "$r2" != 0 ] &&
+	[ "$OPTIND2" = 2 ]
diff --git a/sh/tests/builtins/getopts2.0 b/sh/tests/builtins/getopts2.0
index 5a5dbe2..607d35e 100644
--- a/sh/tests/builtins/getopts2.0
+++ b/sh/tests/builtins/getopts2.0
@@ -1,6 +1,6 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts2.0 297752 2016-04-09 16:06:13Z jilles $
 set - -ax
 getopts ax option
 set -C
 getopts ax option
-echo $option
+printf '%s\n' "$option"
diff --git a/sh/tests/builtins/getopts3.0 b/sh/tests/builtins/getopts3.0
index d02469b..6087d73 100644
--- a/sh/tests/builtins/getopts3.0
+++ b/sh/tests/builtins/getopts3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts3.0 265616 2014-05-07 21:45:25Z jilles $
 
 shift $#
 getopts x opt
diff --git a/sh/tests/builtins/getopts4.0 b/sh/tests/builtins/getopts4.0
index 61d5c2b..ea8cc3f 100644
--- a/sh/tests/builtins/getopts4.0
+++ b/sh/tests/builtins/getopts4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts4.0 265616 2014-05-07 21:45:25Z jilles $
 
 set -- -x
 opt=not
diff --git a/sh/tests/builtins/getopts5.0 b/sh/tests/builtins/getopts5.0
index 666ee76..cd4eca6 100644
--- a/sh/tests/builtins/getopts5.0
+++ b/sh/tests/builtins/getopts5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts5.0 265616 2014-05-07 21:45:25Z jilles $
 
 set -- -x arg
 opt=not
diff --git a/sh/tests/builtins/getopts6.0 b/sh/tests/builtins/getopts6.0
index 1d3c39b..c415eda 100644
--- a/sh/tests/builtins/getopts6.0
+++ b/sh/tests/builtins/getopts6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts6.0 265844 2014-05-10 17:42:21Z jilles $
 
 set -- -x -y
 getopts :x var || echo "First getopts bad: $?"
diff --git a/sh/tests/builtins/getopts7.0 b/sh/tests/builtins/getopts7.0
index 3745555..58afa50 100644
--- a/sh/tests/builtins/getopts7.0
+++ b/sh/tests/builtins/getopts7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts7.0 265844 2014-05-10 17:42:21Z jilles $
 
 set -- -x
 getopts :x: var
diff --git a/sh/tests/builtins/getopts8.0 b/sh/tests/builtins/getopts8.0
index da4af6b..35814b9 100644
--- a/sh/tests/builtins/getopts8.0
+++ b/sh/tests/builtins/getopts8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts8.0 265849 2014-05-10 19:18:49Z jilles $
 
 set -- -yz -wx
 opt=wrong1 OPTARG=wrong2
diff --git a/sh/tests/builtins/getopts9.0 b/sh/tests/builtins/getopts9.0
index d23fc43..aa4abbc 100644
--- a/sh/tests/builtins/getopts9.0
+++ b/sh/tests/builtins/getopts9.0
@@ -1,9 +1,9 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/getopts9.0 297752 2016-04-09 16:06:13Z jilles $
 
 args='-ab'
 getopts ab opt $args
-echo $?:$opt:$OPTARG
+printf '%s\n' "$?:$opt:$OPTARG"
 for dummy in dummy1 dummy2; do
 	getopts ab opt $args
-	echo $?:$opt:$OPTARG
+	printf '%s\n' "$?:$opt:$OPTARG"
 done
diff --git a/sh/tests/builtins/hash1.0 b/sh/tests/builtins/hash1.0
index 45cc300..a5cae20 100644
--- a/sh/tests/builtins/hash1.0
+++ b/sh/tests/builtins/hash1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/hash1.0 149791 2005-09-05 09:42:10Z stefanf $
 cat /dev/null
 hash
 hash -r
diff --git a/sh/tests/builtins/hash2.0 b/sh/tests/builtins/hash2.0
index e5cd21b..4ef151a 100644
--- a/sh/tests/builtins/hash2.0
+++ b/sh/tests/builtins/hash2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/hash2.0 149791 2005-09-05 09:42:10Z stefanf $
 hash
 hash cat
 hash
diff --git a/sh/tests/builtins/hash3.0 b/sh/tests/builtins/hash3.0
index eade0b3..6a155f4 100644
--- a/sh/tests/builtins/hash3.0
+++ b/sh/tests/builtins/hash3.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/hash3.0 149791 2005-09-05 09:42:10Z stefanf $
 hash -v cat
 hash
diff --git a/sh/tests/builtins/hash4.0 b/sh/tests/builtins/hash4.0
index dec584c..9e85f92 100644
--- a/sh/tests/builtins/hash4.0
+++ b/sh/tests/builtins/hash4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/hash4.0 231535 2012-02-11 21:06:45Z jilles $
 
 exec 3>&1
 m=`hash nosuchtool 2>&1 >&3`
diff --git a/sh/tests/builtins/jobid1.0 b/sh/tests/builtins/jobid1.0
index 483fda2..8ba11c1 100644
--- a/sh/tests/builtins/jobid1.0
+++ b/sh/tests/builtins/jobid1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/jobid1.0 254412 2013-08-16 13:48:11Z jilles $
 # Non-standard builtin.
 
 : &
diff --git a/sh/tests/builtins/jobid2.0 b/sh/tests/builtins/jobid2.0
index 101831a..4aca7d5 100644
--- a/sh/tests/builtins/jobid2.0
+++ b/sh/tests/builtins/jobid2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/jobid2.0 254413 2013-08-16 13:56:43Z jilles $
 
 : &
 p1=$(jobid)
diff --git a/sh/tests/builtins/kill1.0 b/sh/tests/builtins/kill1.0
index c1b8550..c15c86d 100644
--- a/sh/tests/builtins/kill1.0
+++ b/sh/tests/builtins/kill1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/kill1.0 262931 2014-03-08 19:44:34Z jilles $
 
 : &
 p1=$!
diff --git a/sh/tests/builtins/kill2.0 b/sh/tests/builtins/kill2.0
index 31e0ba3..3b2360b 100644
--- a/sh/tests/builtins/kill2.0
+++ b/sh/tests/builtins/kill2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/kill2.0 263206 2014-03-15 14:58:48Z jilles $
 
 sleep 1 | sleep 1 &
 kill %+
diff --git a/sh/tests/builtins/lineno.0 b/sh/tests/builtins/lineno.0
index c9311f8..e678ad8 100644
--- a/sh/tests/builtins/lineno.0
+++ b/sh/tests/builtins/lineno.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/lineno.0 179023 2008-05-15 19:58:44Z stefanf $
 echo $LINENO
 echo $LINENO
 
diff --git a/sh/tests/builtins/lineno2.0 b/sh/tests/builtins/lineno2.0
index ddbd104..f60ed11 100644
--- a/sh/tests/builtins/lineno2.0
+++ b/sh/tests/builtins/lineno2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/lineno2.0 262565 2014-02-27 16:54:43Z jilles $
 
 f() {
 	: ${LINENO+${x?}}
diff --git a/sh/tests/builtins/lineno3.0 b/sh/tests/builtins/lineno3.0
index eb8f9ab..3271262 100644
--- a/sh/tests/builtins/lineno3.0
+++ b/sh/tests/builtins/lineno3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/lineno3.0 272482 2014-10-03 20:24:56Z jilles $
 
 echo before: $LINENO
 dummy=$'a\0
diff --git a/sh/tests/builtins/local1.0 b/sh/tests/builtins/local1.0
index b28837e..6100274 100644
--- a/sh/tests/builtins/local1.0
+++ b/sh/tests/builtins/local1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/local1.0 238469 2012-07-15 10:22:13Z jilles $
 # A commonly used but non-POSIX builtin.
 
 f() {
diff --git a/sh/tests/builtins/local2.0 b/sh/tests/builtins/local2.0
index cc8c10f..ed78d93 100644
--- a/sh/tests/builtins/local2.0
+++ b/sh/tests/builtins/local2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/local2.0 251797 2013-06-15 22:22:03Z jilles $
 
 f() {
 	local -
diff --git a/sh/tests/builtins/local3.0 b/sh/tests/builtins/local3.0
index 39ee370..f1d135d 100644
--- a/sh/tests/builtins/local3.0
+++ b/sh/tests/builtins/local3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/local3.0 251797 2013-06-15 22:22:03Z jilles $
 
 f() {
 	local "$@"
diff --git a/sh/tests/builtins/local4.0 b/sh/tests/builtins/local4.0
index 3955aaa..7d35e6e 100644
--- a/sh/tests/builtins/local4.0
+++ b/sh/tests/builtins/local4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/local4.0 254339 2013-08-14 21:59:48Z jilles $
 
 f() {
 	local -- x
diff --git a/sh/tests/builtins/local5.0 b/sh/tests/builtins/local5.0
new file mode 100644
index 0000000..912a77b
--- /dev/null
+++ b/sh/tests/builtins/local5.0
@@ -0,0 +1,15 @@
+# $FreeBSD: head/bin/sh/tests/builtins/local5.0 293635 2016-01-10 16:31:28Z jilles $
+
+f() {
+	local PATH IFS elem
+	IFS=:
+	for elem in ''$PATH''; do
+		PATH=/var/empty/$elem:$PATH
+	done
+	ls -d / >/dev/null
+}
+
+p1=$(command -v ls)
+f
+p2=$(command -v ls)
+[ "$p1" = "$p2" ]
diff --git a/sh/tests/builtins/local6.0 b/sh/tests/builtins/local6.0
new file mode 100644
index 0000000..b2e4c68
--- /dev/null
+++ b/sh/tests/builtins/local6.0
@@ -0,0 +1,10 @@
+# $FreeBSD: head/bin/sh/tests/builtins/local6.0 294582 2016-01-22 18:10:36Z jilles $
+
+f() {
+	local x
+	readonly x=2
+}
+x=3
+f
+x=4
+[ "$x" = 4 ]
diff --git a/sh/tests/builtins/local7.0 b/sh/tests/builtins/local7.0
new file mode 100644
index 0000000..3819442
--- /dev/null
+++ b/sh/tests/builtins/local7.0
@@ -0,0 +1,10 @@
+# $FreeBSD: head/bin/sh/tests/builtins/local7.0 294593 2016-01-22 20:10:08Z jilles $
+
+f() {
+	local x
+	readonly x=2
+}
+unset x
+f
+x=4
+[ "$x" = 4 ]
diff --git a/sh/tests/builtins/locale1.0 b/sh/tests/builtins/locale1.0
index 90b1094..a560232 100644
--- a/sh/tests/builtins/locale1.0
+++ b/sh/tests/builtins/locale1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/locale1.0 218819 2011-02-18 20:37:09Z jilles $
 # Note: this test depends on strerror() using locale.
 
 failures=0
diff --git a/sh/tests/builtins/printf1.0 b/sh/tests/builtins/printf1.0
index 99a82d0..5730c5b 100644
--- a/sh/tests/builtins/printf1.0
+++ b/sh/tests/builtins/printf1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/printf1.0 214853 2010-11-05 21:47:58Z jilles $
 
 [ "$(printf '%c\0%s%d' x '\' 010 | tr '\0' Z)" = 'xZ\8' ]
diff --git a/sh/tests/builtins/printf2.0 b/sh/tests/builtins/printf2.0
index 7763d6f..7084db7 100644
--- a/sh/tests/builtins/printf2.0
+++ b/sh/tests/builtins/printf2.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/printf2.0 214853 2010-11-05 21:47:58Z jilles $
 
 [ "$(printf '%cZ%s%d' x '\' 010)" = 'xZ\8' ]
diff --git a/sh/tests/builtins/printf3.0 b/sh/tests/builtins/printf3.0
index 0e7ea85..ba54866 100644
--- a/sh/tests/builtins/printf3.0
+++ b/sh/tests/builtins/printf3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/printf3.0 216606 2010-12-20 23:06:57Z jilles $
 
 set -e
 v=$(! printf "%d" @wrong 2>/dev/null)
diff --git a/sh/tests/builtins/printf4.0 b/sh/tests/builtins/printf4.0
index 2dd3e72..5213dd6 100644
--- a/sh/tests/builtins/printf4.0
+++ b/sh/tests/builtins/printf4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/printf4.0 216606 2010-12-20 23:06:57Z jilles $
 
 set -e
 v=$(! printf "%d" 4wrong 2>/dev/null)
diff --git a/sh/tests/builtins/read1.0 b/sh/tests/builtins/read1.0
index 06a68fa..b32272c 100644
--- a/sh/tests/builtins/read1.0
+++ b/sh/tests/builtins/read1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read1.0 190300 2009-03-22 23:00:52Z stefanf $
 set -e
 
 echo "1 2 3"		| { read a; echo "x${a}x"; }
diff --git a/sh/tests/builtins/read2.0 b/sh/tests/builtins/read2.0
index fc74511..3255a48 100644
--- a/sh/tests/builtins/read2.0
+++ b/sh/tests/builtins/read2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read2.0 212187 2010-09-03 21:17:33Z jilles $
 
 set -e
 {
diff --git a/sh/tests/builtins/read3.0 b/sh/tests/builtins/read3.0
index c6ae9c1..7cd5b4b 100644
--- a/sh/tests/builtins/read3.0
+++ b/sh/tests/builtins/read3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read3.0 212330 2010-09-08 18:32:23Z jilles $
 
 printf '%s\n' 'a\ b c'	| { read a b; printf '%s\n' "x${a}x${b}x"; }
 printf '%s\n' 'a b\ c'	| { read a b; printf '%s\n' "x${a}x${b}x"; }
diff --git a/sh/tests/builtins/read4.0 b/sh/tests/builtins/read4.0
index 7204a35..abd08af 100644
--- a/sh/tests/builtins/read4.0
+++ b/sh/tests/builtins/read4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read4.0 212339 2010-09-08 20:35:43Z jilles $
 
 printf '%s\n' '\a\ b c'	| { read a b; printf '%s\n' "x${a}x${b}x"; }
 printf '%s\n' '\a b\ c'	| { read a b; printf '%s\n' "x${a}x${b}x"; }
diff --git a/sh/tests/builtins/read5.0 b/sh/tests/builtins/read5.0
index 7d83391..659aebb 100644
--- a/sh/tests/builtins/read5.0
+++ b/sh/tests/builtins/read5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read5.0 218821 2011-02-18 20:51:13Z jilles $
 
 unset LC_ALL
 LC_CTYPE=en_US.ISO8859-1
diff --git a/sh/tests/builtins/read6.0 b/sh/tests/builtins/read6.0
index 2168e10..3f78ee1 100644
--- a/sh/tests/builtins/read6.0
+++ b/sh/tests/builtins/read6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read6.0 247190 2013-02-23 15:15:41Z jilles $
 
 : | read x
 r=$?
diff --git a/sh/tests/builtins/read7.0 b/sh/tests/builtins/read7.0
index e78f887..a01082d 100644
--- a/sh/tests/builtins/read7.0
+++ b/sh/tests/builtins/read7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/read7.0 250214 2013-05-03 15:28:31Z jilles $
 
 { errmsg=`read x <&- 2>&1 >&3`; } 3>&1
 r=$?
diff --git a/sh/tests/builtins/read8.0 b/sh/tests/builtins/read8.0
new file mode 100644
index 0000000..b488279
--- /dev/null
+++ b/sh/tests/builtins/read8.0
@@ -0,0 +1,17 @@
+# $FreeBSD: head/bin/sh/tests/builtins/read8.0 286826 2015-08-16 12:57:17Z jilles $
+
+read a b c <<\EOF
+\
+A\
+ \
+ \
+ \
+B\
+ \
+ \
+C\
+ \
+ \
+ \
+EOF
+[ "$a.$b.$c" = "A.B.C" ]
diff --git a/sh/tests/builtins/read9.0 b/sh/tests/builtins/read9.0
new file mode 100644
index 0000000..16f0687
--- /dev/null
+++ b/sh/tests/builtins/read9.0
@@ -0,0 +1,10 @@
+# $FreeBSD: head/bin/sh/tests/builtins/read9.0 287308 2015-08-30 17:24:22Z jilles $
+
+empty=''
+read a b c <<EOF
+\ \ A B\ \ B C\ \ $empty
+EOF
+read d e <<EOF
+D\ $empty
+EOF
+[ "$a.$b.$c.$d.$e" = "  A.B  B.C  .D ." ]
diff --git a/sh/tests/builtins/return1.0 b/sh/tests/builtins/return1.0
index 787e892..46de0ae 100644
--- a/sh/tests/builtins/return1.0
+++ b/sh/tests/builtins/return1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return1.0 149791 2005-09-05 09:42:10Z stefanf $
 f() {
 	return 0
 	exit 1
diff --git a/sh/tests/builtins/return2.1 b/sh/tests/builtins/return2.1
index 0ef8171..4da86f5 100644
--- a/sh/tests/builtins/return2.1
+++ b/sh/tests/builtins/return2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return2.1 149791 2005-09-05 09:42:10Z stefanf $
 f() {
 	true && return 1
 	return 0
diff --git a/sh/tests/builtins/return3.1 b/sh/tests/builtins/return3.1
index 605ec68..bc65c1f 100644
--- a/sh/tests/builtins/return3.1
+++ b/sh/tests/builtins/return3.1
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return3.1 149791 2005-09-05 09:42:10Z stefanf $
 return 1
 exit 0
diff --git a/sh/tests/builtins/return4.0 b/sh/tests/builtins/return4.0
index be5582b..1a702ef 100644
--- a/sh/tests/builtins/return4.0
+++ b/sh/tests/builtins/return4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return4.0 208629 2010-05-28 22:08:34Z jilles $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/return5.0 b/sh/tests/builtins/return5.0
index 6e4b7bd..476ae7b 100644
--- a/sh/tests/builtins/return5.0
+++ b/sh/tests/builtins/return5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return5.0 211349 2010-08-15 21:06:53Z jilles $
 
 if [ "$1" != nested ]; then
 	f() {
diff --git a/sh/tests/builtins/return6.4 b/sh/tests/builtins/return6.4
index e4d8e0d..1bddbeb 100644
--- a/sh/tests/builtins/return6.4
+++ b/sh/tests/builtins/return6.4
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return6.4 212475 2010-09-11 15:07:40Z jilles $
 
 while return 4; do exit 3; done
diff --git a/sh/tests/builtins/return7.4 b/sh/tests/builtins/return7.4
index 2047373..3efdd7f 100644
--- a/sh/tests/builtins/return7.4
+++ b/sh/tests/builtins/return7.4
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return7.4 212475 2010-09-11 15:07:40Z jilles $
 
 f() {
 	while return 4; do exit 3; done
diff --git a/sh/tests/builtins/return8.0 b/sh/tests/builtins/return8.0
index f00e859..025f068 100644
--- a/sh/tests/builtins/return8.0
+++ b/sh/tests/builtins/return8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/return8.0 255215 2013-09-04 22:10:16Z jilles $
 
 if [ "$1" = nested ]; then
 	return 17
diff --git a/sh/tests/builtins/set2.0 b/sh/tests/builtins/set2.0
index ad13eab..844da91 100644
--- a/sh/tests/builtins/set2.0
+++ b/sh/tests/builtins/set2.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/set2.0 223183 2011-06-17 10:21:24Z jilles $
 
 ! env @badness=1 ${SH} -c 'v=`set`; eval "$v"' 2>&1 | grep @badness
diff --git a/sh/tests/builtins/set3.0 b/sh/tests/builtins/set3.0
new file mode 100644
index 0000000..419f702
--- /dev/null
+++ b/sh/tests/builtins/set3.0
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/builtins/set3.0 296578 2016-03-09 21:05:21Z jilles $
+
+settings1=$(set +o) && set -o nolog && settings2=$(set +o) &&
+[ "$settings1" != "$settings2" ]
diff --git a/sh/tests/builtins/trap1.0 b/sh/tests/builtins/trap1.0
index 313f6a3..9f60be4 100644
--- a/sh/tests/builtins/trap1.0
+++ b/sh/tests/builtins/trap1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap1.0 213738 2010-10-12 18:20:38Z obrien $
 
 test "$(trap 'echo trapped' EXIT; :)" = trapped || exit 1
 
diff --git a/sh/tests/builtins/trap10.0 b/sh/tests/builtins/trap10.0
index fa0e35d..66c5106 100644
--- a/sh/tests/builtins/trap10.0
+++ b/sh/tests/builtins/trap10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap10.0 230212 2012-01-16 11:07:46Z dumbbell $
 
 # Check that the return statement will not break the EXIT trap, ie. all
 # trap commands are executed before the script exits.
diff --git a/sh/tests/builtins/trap11.0 b/sh/tests/builtins/trap11.0
index cfeea9e..acb4d0f 100644
--- a/sh/tests/builtins/trap11.0
+++ b/sh/tests/builtins/trap11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap11.0 230212 2012-01-16 11:07:46Z dumbbell $
 
 # Check that the return statement will not break the USR1 trap, ie. all
 # trap commands are executed before the script resumes.
diff --git a/sh/tests/builtins/trap12.0 b/sh/tests/builtins/trap12.0
index 8c62ffd..a7a953c 100644
--- a/sh/tests/builtins/trap12.0
+++ b/sh/tests/builtins/trap12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap12.0 247720 2013-03-03 17:33:59Z jilles $
 
 f() {
 	trap 'return 42' USR1
diff --git a/sh/tests/builtins/trap13.0 b/sh/tests/builtins/trap13.0
index d90eb08..1069b8f 100644
--- a/sh/tests/builtins/trap13.0
+++ b/sh/tests/builtins/trap13.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap13.0 257399 2013-10-30 21:36:15Z jilles $
 
 {
 	trap 'exit 0' INT
diff --git a/sh/tests/builtins/trap14.0 b/sh/tests/builtins/trap14.0
index 97cce8d..8c982b2 100644
--- a/sh/tests/builtins/trap14.0
+++ b/sh/tests/builtins/trap14.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap14.0 257399 2013-10-30 21:36:15Z jilles $
 
 {
 	trap - INT
diff --git a/sh/tests/builtins/trap15.0 b/sh/tests/builtins/trap15.0
index 6b9857d..eaf8e8e 100644
--- a/sh/tests/builtins/trap15.0
+++ b/sh/tests/builtins/trap15.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap15.0 281718 2015-04-18 23:49:57Z bdrewery $
 
 (${SH} -c 'term(){ exit 5;}; trap term TERM; kill -TERM $$') &
 wait >/dev/null 2>&1 $!
diff --git a/sh/tests/builtins/trap16.0 b/sh/tests/builtins/trap16.0
index 3d70cce..b72fa11 100644
--- a/sh/tests/builtins/trap16.0
+++ b/sh/tests/builtins/trap16.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap16.0 281718 2015-04-18 23:49:57Z bdrewery $
 
 traps=$(${SH} -c 'trap "echo bad" 0; trap - 0; trap')
 [ -z "$traps" ] || exit 1
diff --git a/sh/tests/builtins/trap17.0 b/sh/tests/builtins/trap17.0
new file mode 100644
index 0000000..35aafe7
--- /dev/null
+++ b/sh/tests/builtins/trap17.0
@@ -0,0 +1,10 @@
+# $FreeBSD: head/bin/sh/tests/builtins/trap17.0 297360 2016-03-28 18:58:40Z jilles $
+# This use-after-free bug probably needs non-default settings to show up.
+
+v1=nothing v2=nothing
+trap 'trap "echo bad" USR1
+v1=trap_received
+v2=trap_invoked
+:' USR1
+kill -USR1 "$$"
+[ "$v1.$v2" = trap_received.trap_invoked ]
diff --git a/sh/tests/builtins/trap2.0 b/sh/tests/builtins/trap2.0
index a05287a..b64bb24 100644
--- a/sh/tests/builtins/trap2.0
+++ b/sh/tests/builtins/trap2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap2.0 194517 2009-06-19 22:15:59Z jilles $
 # This is really a test for outqstr(), which is readily accessible via trap.
 
 runtest()
diff --git a/sh/tests/builtins/trap3.0 b/sh/tests/builtins/trap3.0
index 8160729..d442f8b 100644
--- a/sh/tests/builtins/trap3.0
+++ b/sh/tests/builtins/trap3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap3.0 218889 2011-02-20 14:18:58Z jilles $
 
 {
 	trap '' garbage && exit 3
diff --git a/sh/tests/builtins/trap4.0 b/sh/tests/builtins/trap4.0
index 7f2080e..9fdab81 100644
--- a/sh/tests/builtins/trap4.0
+++ b/sh/tests/builtins/trap4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap4.0 217035 2011-01-05 23:17:29Z jilles $
 
 T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX)
 trap 'rm -rf $T' 0
diff --git a/sh/tests/builtins/trap5.0 b/sh/tests/builtins/trap5.0
index 56e0fb1..26eeb50 100644
--- a/sh/tests/builtins/trap5.0
+++ b/sh/tests/builtins/trap5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap5.0 217461 2011-01-15 21:09:00Z jilles $
 
 set -e
 trap - USR1
diff --git a/sh/tests/builtins/trap6.0 b/sh/tests/builtins/trap6.0
index bd2bf7e..1e79ae7 100644
--- a/sh/tests/builtins/trap6.0
+++ b/sh/tests/builtins/trap6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap6.0 217472 2011-01-16 13:56:41Z jilles $
 
 v=$(
 	${SH} -c 'trap "echo ok; exit" USR1; kill -USR1 $$' &
diff --git a/sh/tests/builtins/trap7.0 b/sh/tests/builtins/trap7.0
index 35529b8..b62ffb7 100644
--- a/sh/tests/builtins/trap7.0
+++ b/sh/tests/builtins/trap7.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap7.0 217996 2011-01-27 23:08:20Z jilles $
 
 [ "$(trap 'echo trapped' EXIT)" = trapped ]
diff --git a/sh/tests/builtins/trap8.0 b/sh/tests/builtins/trap8.0
index cdce976..24752b1 100644
--- a/sh/tests/builtins/trap8.0
+++ b/sh/tests/builtins/trap8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap8.0 218889 2011-02-20 14:18:58Z jilles $
 
 # I am not sure if POSIX requires the shell to continue processing
 # further trap names in the same trap command after an invalid one.
diff --git a/sh/tests/builtins/trap9.0 b/sh/tests/builtins/trap9.0
index 0f584ec..bbc35e9 100644
--- a/sh/tests/builtins/trap9.0
+++ b/sh/tests/builtins/trap9.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/trap9.0 230211 2012-01-16 10:59:44Z dumbbell $
 
 test "$(trap 'printf trap; echo ped' EXIT; f() { :; }; f)" = trapped || exit 1
diff --git a/sh/tests/builtins/type1.0 b/sh/tests/builtins/type1.0
index c5e4564..2f04997 100644
--- a/sh/tests/builtins/type1.0
+++ b/sh/tests/builtins/type1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/type1.0 165931 2007-01-11 00:25:20Z stefanf $
 command -v not-here && exit 1
 command -v /not-here && exit 1
 command -V not-here && exit 1
diff --git a/sh/tests/builtins/type2.0 b/sh/tests/builtins/type2.0
index fe44d95..7e0581e 100644
--- a/sh/tests/builtins/type2.0
+++ b/sh/tests/builtins/type2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/type2.0 201344 2009-12-31 17:44:24Z jilles $
 
 failures=0
 
diff --git a/sh/tests/builtins/type3.0 b/sh/tests/builtins/type3.0
index 87cccdd..dad07e9 100644
--- a/sh/tests/builtins/type3.0
+++ b/sh/tests/builtins/type3.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/type3.0 255072 2013-08-30 12:09:59Z jilles $
 
 [ "$(type type)" = "$(type -- type)" ]
diff --git a/sh/tests/builtins/unalias.0 b/sh/tests/builtins/unalias.0
index 34d8d6e..ffdc756 100644
--- a/sh/tests/builtins/unalias.0
+++ b/sh/tests/builtins/unalias.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/unalias.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 
 alias false=true
diff --git a/sh/tests/builtins/var-assign.0 b/sh/tests/builtins/var-assign.0
index ace39c0..d3766bb 100644
--- a/sh/tests/builtins/var-assign.0
+++ b/sh/tests/builtins/var-assign.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/var-assign.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break,\
diff --git a/sh/tests/builtins/var-assign2.0 b/sh/tests/builtins/var-assign2.0
index eafec89..b9afb55 100644
--- a/sh/tests/builtins/var-assign2.0
+++ b/sh/tests/builtins/var-assign2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/var-assign2.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break,\
diff --git a/sh/tests/builtins/wait1.0 b/sh/tests/builtins/wait1.0
index 1ca8530..8538415 100644
--- a/sh/tests/builtins/wait1.0
+++ b/sh/tests/builtins/wait1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait1.0 208476 2010-05-23 22:10:20Z jilles $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/wait10.0 b/sh/tests/builtins/wait10.0
index 864fc78..c7e3975 100644
--- a/sh/tests/builtins/wait10.0
+++ b/sh/tests/builtins/wait10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait10.0 251430 2013-06-05 19:40:52Z jilles $
 # Init cannot be a child of the shell.
 exit 49 & p49=$!
 wait 1 "$p49"
diff --git a/sh/tests/builtins/wait2.0 b/sh/tests/builtins/wait2.0
index e61455c..71adfde 100644
--- a/sh/tests/builtins/wait2.0
+++ b/sh/tests/builtins/wait2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait2.0 208476 2010-05-23 22:10:20Z jilles $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/wait3.0 b/sh/tests/builtins/wait3.0
index 1ed5299..d3561ae 100644
--- a/sh/tests/builtins/wait3.0
+++ b/sh/tests/builtins/wait3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait3.0 236771 2012-06-08 22:54:25Z jilles $
 
 failures=
 failure() {
diff --git a/sh/tests/builtins/wait4.0 b/sh/tests/builtins/wait4.0
index 7935131..358513c 100644
--- a/sh/tests/builtins/wait4.0
+++ b/sh/tests/builtins/wait4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait4.0 247206 2013-02-23 22:50:57Z jilles $
 
 T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX`
 trap 'rm -rf $T' 0
diff --git a/sh/tests/builtins/wait5.0 b/sh/tests/builtins/wait5.0
index 6874bf6..48e1d2e 100644
--- a/sh/tests/builtins/wait5.0
+++ b/sh/tests/builtins/wait5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait5.0 247206 2013-02-23 22:50:57Z jilles $
 
 T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX`
 trap 'rm -rf $T' 0
diff --git a/sh/tests/builtins/wait6.0 b/sh/tests/builtins/wait6.0
index 20e3c68..e87b9c9 100644
--- a/sh/tests/builtins/wait6.0
+++ b/sh/tests/builtins/wait6.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait6.0 248349 2013-03-15 20:29:31Z jilles $
 
 wait --
diff --git a/sh/tests/builtins/wait7.0 b/sh/tests/builtins/wait7.0
index 0fb092f..2c50674 100644
--- a/sh/tests/builtins/wait7.0
+++ b/sh/tests/builtins/wait7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait7.0 248349 2013-03-15 20:29:31Z jilles $
 
 : &
 wait -- $!
diff --git a/sh/tests/builtins/wait8.0 b/sh/tests/builtins/wait8.0
index b59ff59..15e23b7 100644
--- a/sh/tests/builtins/wait8.0
+++ b/sh/tests/builtins/wait8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait8.0 251429 2013-06-05 19:08:22Z jilles $
 
 exit 44 & p44=$!
 exit 45 & p45=$!
diff --git a/sh/tests/builtins/wait9.127 b/sh/tests/builtins/wait9.127
index 661f275..9bed737 100644
--- a/sh/tests/builtins/wait9.127
+++ b/sh/tests/builtins/wait9.127
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/builtins/wait9.127 251430 2013-06-05 19:40:52Z jilles $
 # Init cannot be a child of the shell.
 wait 1
diff --git a/sh/tests/errors/Makefile b/sh/tests/errors/Makefile
index ace9a01..d690409 100644
--- a/sh/tests/errors/Makefile
+++ b/sh/tests/errors/Makefile
@@ -1,32 +1,34 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/Makefile 299094 2016-05-04 23:20:53Z ngie $
+
+PACKAGE=	tests
 
 TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		assignment-error1.0
-FILES+=		assignment-error2.0
-FILES+=		backquote-error1.0
-FILES+=		backquote-error2.0
-FILES+=		bad-binary1.126
-FILES+=		bad-keyword1.0
-FILES+=		bad-parm-exp1.0
-FILES+=		bad-parm-exp2.2 bad-parm-exp2.2.stderr
-FILES+=		bad-parm-exp3.2 bad-parm-exp3.2.stderr
-FILES+=		bad-parm-exp4.2 bad-parm-exp4.2.stderr
-FILES+=		bad-parm-exp5.2 bad-parm-exp5.2.stderr
-FILES+=		bad-parm-exp6.2 bad-parm-exp6.2.stderr
-FILES+=		option-error.0
-FILES+=		redirection-error.0
-FILES+=		redirection-error2.2
-FILES+=		redirection-error3.0
-FILES+=		redirection-error4.0
-FILES+=		redirection-error5.0
-FILES+=		redirection-error6.0
-FILES+=		redirection-error7.0
-FILES+=		write-error1.0
+${PACKAGE}FILES+=		assignment-error1.0
+${PACKAGE}FILES+=		assignment-error2.0
+${PACKAGE}FILES+=		backquote-error1.0
+${PACKAGE}FILES+=		backquote-error2.0
+${PACKAGE}FILES+=		bad-binary1.126
+${PACKAGE}FILES+=		bad-keyword1.0
+${PACKAGE}FILES+=		bad-parm-exp1.0
+${PACKAGE}FILES+=		bad-parm-exp2.2 bad-parm-exp2.2.stderr
+${PACKAGE}FILES+=		bad-parm-exp3.2 bad-parm-exp3.2.stderr
+${PACKAGE}FILES+=		bad-parm-exp4.2 bad-parm-exp4.2.stderr
+${PACKAGE}FILES+=		bad-parm-exp5.2 bad-parm-exp5.2.stderr
+${PACKAGE}FILES+=		bad-parm-exp6.2 bad-parm-exp6.2.stderr
+${PACKAGE}FILES+=		bad-parm-exp7.0
+${PACKAGE}FILES+=		bad-parm-exp8.0
+${PACKAGE}FILES+=		option-error.0
+${PACKAGE}FILES+=		redirection-error.0
+${PACKAGE}FILES+=		redirection-error2.2
+${PACKAGE}FILES+=		redirection-error3.0
+${PACKAGE}FILES+=		redirection-error4.0
+${PACKAGE}FILES+=		redirection-error5.0
+${PACKAGE}FILES+=		redirection-error6.0
+${PACKAGE}FILES+=		redirection-error7.0
+${PACKAGE}FILES+=		write-error1.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/errors/Makefile.depend b/sh/tests/errors/Makefile.depend
new file mode 100644
index 0000000..dbfdc34
--- /dev/null
+++ b/sh/tests/errors/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/errors/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/errors/assignment-error1.0 b/sh/tests/errors/assignment-error1.0
index 00eaed9..2106b5a 100644
--- a/sh/tests/errors/assignment-error1.0
+++ b/sh/tests/errors/assignment-error1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/assignment-error1.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break,\
diff --git a/sh/tests/errors/assignment-error2.0 b/sh/tests/errors/assignment-error2.0
index ff4e629..68f2d48 100644
--- a/sh/tests/errors/assignment-error2.0
+++ b/sh/tests/errors/assignment-error2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/assignment-error2.0 216870 2011-01-01 13:26:18Z jilles $
 
 set -e
 HOME=/
diff --git a/sh/tests/errors/backquote-error1.0 b/sh/tests/errors/backquote-error1.0
index 43e3303..d35d0b7 100644
--- a/sh/tests/errors/backquote-error1.0
+++ b/sh/tests/errors/backquote-error1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/backquote-error1.0 213738 2010-10-12 18:20:38Z obrien $
 
 echo 'echo `for` echo ".BAD"CODE.' | ${SH} +m -i 2>&1 | grep -q BADCODE && exit 1
 exit 0
diff --git a/sh/tests/errors/backquote-error2.0 b/sh/tests/errors/backquote-error2.0
index 5b49e2b..a5955dd 100644
--- a/sh/tests/errors/backquote-error2.0
+++ b/sh/tests/errors/backquote-error2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/backquote-error2.0 213738 2010-10-12 18:20:38Z obrien $
 
 ${SH} -c 'echo `echo .BA"DCODE.`
 echo ".BAD"CODE.' 2>&1 | grep -q BADCODE && exit 1
diff --git a/sh/tests/errors/bad-binary1.126 b/sh/tests/errors/bad-binary1.126
index d92e9de..7c7c67f 100644
--- a/sh/tests/errors/bad-binary1.126
+++ b/sh/tests/errors/bad-binary1.126
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-binary1.126 218320 2011-02-05 12:54:59Z jilles $
 # Checking for binary "scripts" without magic number is permitted but not
 # required by POSIX. However, it is preferable to getting errors like
 # Syntax error: word unexpected (expecting ")")
diff --git a/sh/tests/errors/bad-keyword1.0 b/sh/tests/errors/bad-keyword1.0
index ac01536..d2680d6 100644
--- a/sh/tests/errors/bad-keyword1.0
+++ b/sh/tests/errors/bad-keyword1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-keyword1.0 216398 2010-12-12 21:18:16Z jilles $
 
 echo ':; fi' | ${SH} -n 2>/dev/null && exit 1
 exit 0
diff --git a/sh/tests/errors/bad-parm-exp1.0 b/sh/tests/errors/bad-parm-exp1.0
index 6e94994..f288294 100644
--- a/sh/tests/errors/bad-parm-exp1.0
+++ b/sh/tests/errors/bad-parm-exp1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp1.0 164004 2006-11-05 18:41:23Z stefanf $
 false && {
 	${}
 	${foo/}
diff --git a/sh/tests/errors/bad-parm-exp2.2 b/sh/tests/errors/bad-parm-exp2.2
index a0826ec..7424840 100644
--- a/sh/tests/errors/bad-parm-exp2.2
+++ b/sh/tests/errors/bad-parm-exp2.2
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp2.2 270101 2014-08-17 14:26:12Z jilles $
 eval '${}'
diff --git a/sh/tests/errors/bad-parm-exp3.2 b/sh/tests/errors/bad-parm-exp3.2
index bb41208..56a52df 100644
--- a/sh/tests/errors/bad-parm-exp3.2
+++ b/sh/tests/errors/bad-parm-exp3.2
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp3.2 270101 2014-08-17 14:26:12Z jilles $
 eval '${foo/}'
diff --git a/sh/tests/errors/bad-parm-exp4.2 b/sh/tests/errors/bad-parm-exp4.2
index 2837f9b..e0a7099 100644
--- a/sh/tests/errors/bad-parm-exp4.2
+++ b/sh/tests/errors/bad-parm-exp4.2
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp4.2 270101 2014-08-17 14:26:12Z jilles $
 eval '${foo:@abc}'
diff --git a/sh/tests/errors/bad-parm-exp5.2 b/sh/tests/errors/bad-parm-exp5.2
index 1ba343b..fa26259 100644
--- a/sh/tests/errors/bad-parm-exp5.2
+++ b/sh/tests/errors/bad-parm-exp5.2
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp5.2 270101 2014-08-17 14:26:12Z jilles $
 eval '${/}'
diff --git a/sh/tests/errors/bad-parm-exp6.2 b/sh/tests/errors/bad-parm-exp6.2
index b53a91b..51858e8 100644
--- a/sh/tests/errors/bad-parm-exp6.2
+++ b/sh/tests/errors/bad-parm-exp6.2
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp6.2 270101 2014-08-17 14:26:12Z jilles $
 eval '${#foo^}'
diff --git a/sh/tests/errors/bad-parm-exp7.0 b/sh/tests/errors/bad-parm-exp7.0
new file mode 100644
index 0000000..d7bff92
--- /dev/null
+++ b/sh/tests/errors/bad-parm-exp7.0
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp7.0 287081 2015-08-23 20:44:53Z jilles $
+
+v=1
+eval ": $(printf '${v-${\372}}')"
diff --git a/sh/tests/errors/bad-parm-exp8.0 b/sh/tests/errors/bad-parm-exp8.0
new file mode 100644
index 0000000..24f6bff
--- /dev/null
+++ b/sh/tests/errors/bad-parm-exp8.0
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/errors/bad-parm-exp8.0 287081 2015-08-23 20:44:53Z jilles $
+
+v=1
+eval ": $(printf '${v-${w\372}}')"
diff --git a/sh/tests/errors/option-error.0 b/sh/tests/errors/option-error.0
index b4b44c4..473c0b9 100644
--- a/sh/tests/errors/option-error.0
+++ b/sh/tests/errors/option-error.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/option-error.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break abc,\
diff --git a/sh/tests/errors/redirection-error.0 b/sh/tests/errors/redirection-error.0
index cb8c0b1..2a67698 100644
--- a/sh/tests/errors/redirection-error.0
+++ b/sh/tests/errors/redirection-error.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break,\
diff --git a/sh/tests/errors/redirection-error2.2 b/sh/tests/errors/redirection-error2.2
index 32bccd8..595e959 100644
--- a/sh/tests/errors/redirection-error2.2
+++ b/sh/tests/errors/redirection-error2.2
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error2.2 213738 2010-10-12 18:20:38Z obrien $
 
 # sh should fail gracefully on this bad redirect
 ${SH} -c 'echo 1 >&$a' 2>/dev/null
diff --git a/sh/tests/errors/redirection-error3.0 b/sh/tests/errors/redirection-error3.0
index 8a07d03..fd7a334 100644
--- a/sh/tests/errors/redirection-error3.0
+++ b/sh/tests/errors/redirection-error3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error3.0 213738 2010-10-12 18:20:38Z obrien $
 IFS=,
 
 SPECIAL="break,\
diff --git a/sh/tests/errors/redirection-error4.0 b/sh/tests/errors/redirection-error4.0
index 2060974..ed58499 100644
--- a/sh/tests/errors/redirection-error4.0
+++ b/sh/tests/errors/redirection-error4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error4.0 205138 2010-03-13 22:53:17Z jilles $
 # A redirection error should not abort the shell if there is no command word.
 exec 2>/dev/null
 </var/empty/x
diff --git a/sh/tests/errors/redirection-error5.0 b/sh/tests/errors/redirection-error5.0
index 1fcd47e..b96c14e 100644
--- a/sh/tests/errors/redirection-error5.0
+++ b/sh/tests/errors/redirection-error5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error5.0 205153 2010-03-14 13:51:12Z jilles $
 # A redirection error on a subshell should not abort the shell.
 exec 2>/dev/null
 ( echo bad ) </var/empty/x
diff --git a/sh/tests/errors/redirection-error6.0 b/sh/tests/errors/redirection-error6.0
index 17d1109..1d84e6c 100644
--- a/sh/tests/errors/redirection-error6.0
+++ b/sh/tests/errors/redirection-error6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error6.0 205154 2010-03-14 14:24:35Z jilles $
 # A redirection error on a compound command should not abort the shell.
 exec 2>/dev/null
 { echo bad; } </var/empty/x
diff --git a/sh/tests/errors/redirection-error7.0 b/sh/tests/errors/redirection-error7.0
index 5b20f04..ef56434 100644
--- a/sh/tests/errors/redirection-error7.0
+++ b/sh/tests/errors/redirection-error7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/redirection-error7.0 216851 2010-12-31 18:20:17Z jilles $
 
 ! dummy=$(
 	exec 3>&1 >&2 2>&3
diff --git a/sh/tests/errors/write-error1.0 b/sh/tests/errors/write-error1.0
index fcb52e7..3001e5c 100644
--- a/sh/tests/errors/write-error1.0
+++ b/sh/tests/errors/write-error1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/errors/write-error1.0 244924 2013-01-01 12:48:24Z jilles $
 
 ! echo >&- 2>/dev/null
diff --git a/sh/tests/execution/Makefile b/sh/tests/execution/Makefile
index 638492b..b3e99ee 100644
--- a/sh/tests/execution/Makefile
+++ b/sh/tests/execution/Makefile
@@ -1,56 +1,56 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/Makefile 299094 2016-05-04 23:20:53Z ngie $
+
+PACKAGE=	tests
 
 TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		bg1.0
-FILES+=		bg2.0
-FILES+=		bg3.0
-FILES+=		bg4.0
-FILES+=		bg5.0
-FILES+=		bg6.0 bg6.0.stdout
-FILES+=		bg7.0
-FILES+=		bg8.0
-FILES+=		bg9.0
-FILES+=		bg10.0 bg10.0.stdout
-FILES+=		fork1.0
-FILES+=		fork2.0
-FILES+=		fork3.0
-FILES+=		func1.0
-FILES+=		func2.0
-FILES+=		func3.0
-FILES+=		hash1.0
-FILES+=		int-cmd1.0
-FILES+=		killed1.0
-FILES+=		killed2.0
-FILES+=		not1.0
-FILES+=		not2.0
-FILES+=		path1.0
-FILES+=		redir1.0
-FILES+=		redir2.0
-FILES+=		redir3.0
-FILES+=		redir4.0
-FILES+=		redir5.0
-FILES+=		redir6.0
-FILES+=		redir7.0
-FILES+=		set-n1.0
-FILES+=		set-n2.0
-FILES+=		set-n3.0
-FILES+=		set-n4.0
-FILES+=		set-x1.0
-FILES+=		set-x2.0
-FILES+=		set-x3.0
-FILES+=		set-x4.0
-FILES+=		shellproc1.0
-FILES+=		subshell1.0 subshell1.0.stdout
-FILES+=		subshell2.0
-FILES+=		subshell3.0
-FILES+=		subshell4.0
-FILES+=		unknown1.0
-FILES+=		var-assign1.0
+${PACKAGE}FILES+=		bg1.0
+${PACKAGE}FILES+=		bg2.0
+${PACKAGE}FILES+=		bg3.0
+${PACKAGE}FILES+=		bg4.0
+${PACKAGE}FILES+=		bg5.0
+${PACKAGE}FILES+=		bg6.0 bg6.0.stdout
+${PACKAGE}FILES+=		bg7.0
+${PACKAGE}FILES+=		bg8.0
+${PACKAGE}FILES+=		bg9.0
+${PACKAGE}FILES+=		bg10.0 bg10.0.stdout
+${PACKAGE}FILES+=		fork1.0
+${PACKAGE}FILES+=		fork2.0
+${PACKAGE}FILES+=		fork3.0
+${PACKAGE}FILES+=		func1.0
+${PACKAGE}FILES+=		func2.0
+${PACKAGE}FILES+=		func3.0
+${PACKAGE}FILES+=		hash1.0
+${PACKAGE}FILES+=		int-cmd1.0
+${PACKAGE}FILES+=		killed1.0
+${PACKAGE}FILES+=		killed2.0
+${PACKAGE}FILES+=		not1.0
+${PACKAGE}FILES+=		not2.0
+${PACKAGE}FILES+=		path1.0
+${PACKAGE}FILES+=		redir1.0
+${PACKAGE}FILES+=		redir2.0
+${PACKAGE}FILES+=		redir3.0
+${PACKAGE}FILES+=		redir4.0
+${PACKAGE}FILES+=		redir5.0
+${PACKAGE}FILES+=		redir6.0
+${PACKAGE}FILES+=		redir7.0
+${PACKAGE}FILES+=		set-n1.0
+${PACKAGE}FILES+=		set-n2.0
+${PACKAGE}FILES+=		set-n3.0
+${PACKAGE}FILES+=		set-n4.0
+${PACKAGE}FILES+=		set-x1.0
+${PACKAGE}FILES+=		set-x2.0
+${PACKAGE}FILES+=		set-x3.0
+${PACKAGE}FILES+=		set-x4.0
+${PACKAGE}FILES+=		shellproc1.0
+${PACKAGE}FILES+=		subshell1.0 subshell1.0.stdout
+${PACKAGE}FILES+=		subshell2.0
+${PACKAGE}FILES+=		subshell3.0
+${PACKAGE}FILES+=		subshell4.0
+${PACKAGE}FILES+=		unknown1.0
+${PACKAGE}FILES+=		var-assign1.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/execution/Makefile.depend b/sh/tests/execution/Makefile.depend
new file mode 100644
index 0000000..fac3607
--- /dev/null
+++ b/sh/tests/execution/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/execution/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/execution/bg1.0 b/sh/tests/execution/bg1.0
index edb92ae..95b51c6 100644
--- a/sh/tests/execution/bg1.0
+++ b/sh/tests/execution/bg1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg1.0 221027 2011-04-25 20:54:12Z jilles $
 
 : `false` &
diff --git a/sh/tests/execution/bg10.0 b/sh/tests/execution/bg10.0
index 44a25dc..06a27f4 100644
--- a/sh/tests/execution/bg10.0
+++ b/sh/tests/execution/bg10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg10.0 258535 2013-11-24 23:12:13Z jilles $
 # The redirection overrides the </dev/null implicit in a background command.
 
 echo yes | ${SH} -c '{ cat & wait; } <&0'
diff --git a/sh/tests/execution/bg2.0 b/sh/tests/execution/bg2.0
index 2e2fbc5..74ee54a 100644
--- a/sh/tests/execution/bg2.0
+++ b/sh/tests/execution/bg2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg2.0 221027 2011-04-25 20:54:12Z jilles $
 
 f() { return 42; }
 f
diff --git a/sh/tests/execution/bg3.0 b/sh/tests/execution/bg3.0
index 359fc6f..95f37d3 100644
--- a/sh/tests/execution/bg3.0
+++ b/sh/tests/execution/bg3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg3.0 221027 2011-04-25 20:54:12Z jilles $
 
 f() { return 42; }
 f
diff --git a/sh/tests/execution/bg4.0 b/sh/tests/execution/bg4.0
index 25e4f4e..1220fd3 100644
--- a/sh/tests/execution/bg4.0
+++ b/sh/tests/execution/bg4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg4.0 223283 2011-06-19 00:00:36Z jilles $
 
 x=''
 : ${x:=1} &
diff --git a/sh/tests/execution/bg5.0 b/sh/tests/execution/bg5.0
index cc9ceaa..e820035 100644
--- a/sh/tests/execution/bg5.0
+++ b/sh/tests/execution/bg5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg5.0 258489 2013-11-22 21:50:13Z jilles $
 # A background command has an implicit </dev/null redirection.
 
 echo bad | ${SH} -c '{ cat & wait; }'
diff --git a/sh/tests/execution/bg6.0 b/sh/tests/execution/bg6.0
index b0faf9e..466adc2 100644
--- a/sh/tests/execution/bg6.0
+++ b/sh/tests/execution/bg6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg6.0 258489 2013-11-22 21:50:13Z jilles $
 # The redirection overrides the </dev/null implicit in a background command.
 
 echo yes | ${SH} -c '{ cat & wait; } </dev/stdin'
diff --git a/sh/tests/execution/bg7.0 b/sh/tests/execution/bg7.0
index f771edc..788161e 100644
--- a/sh/tests/execution/bg7.0
+++ b/sh/tests/execution/bg7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg7.0 258533 2013-11-24 22:45:49Z jilles $
 # The redirection does not apply to the background command, and therefore
 # does not override the implicit </dev/null.
 
diff --git a/sh/tests/execution/bg8.0 b/sh/tests/execution/bg8.0
index 33667cb..aa571dc 100644
--- a/sh/tests/execution/bg8.0
+++ b/sh/tests/execution/bg8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg8.0 258533 2013-11-24 22:45:49Z jilles $
 # The redirection does not apply to the background command, and therefore
 # does not override the implicit </dev/null.
 
diff --git a/sh/tests/execution/bg9.0 b/sh/tests/execution/bg9.0
index 64fde3e..4af1bae 100644
--- a/sh/tests/execution/bg9.0
+++ b/sh/tests/execution/bg9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/bg9.0 258533 2013-11-24 22:45:49Z jilles $
 # The redirection does not apply to the background command, and therefore
 # does not override the implicit </dev/null.
 
diff --git a/sh/tests/execution/fork1.0 b/sh/tests/execution/fork1.0
index 2eeac79..80b013b 100644
--- a/sh/tests/execution/fork1.0
+++ b/sh/tests/execution/fork1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/fork1.0 218850 2011-02-19 13:22:18Z jilles $
 
 shname=${SH%% *}
 shname=${shname##*/}
diff --git a/sh/tests/execution/fork2.0 b/sh/tests/execution/fork2.0
index 62a2537..2639165 100644
--- a/sh/tests/execution/fork2.0
+++ b/sh/tests/execution/fork2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/fork2.0 213738 2010-10-12 18:20:38Z obrien $
 
 result=$(${SH} -c '(/bin/sleep 1)& sleep 0.1; ps -p $! -o comm=; kill $!')
 test "$result" = sleep || exit 1
diff --git a/sh/tests/execution/fork3.0 b/sh/tests/execution/fork3.0
index 3cb678c..008be7b 100644
--- a/sh/tests/execution/fork3.0
+++ b/sh/tests/execution/fork3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/fork3.0 220978 2011-04-23 22:28:56Z jilles $
 
 result=$(${SH} -c 'f() { ps -p $$ -o comm=; }; f')
 test "$result" = "ps"
diff --git a/sh/tests/execution/func1.0 b/sh/tests/execution/func1.0
index 29fcc07..1af5495 100644
--- a/sh/tests/execution/func1.0
+++ b/sh/tests/execution/func1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/func1.0 213738 2010-10-12 18:20:38Z obrien $
 
 MALLOC_OPTIONS=J ${SH} -c 'g() { g() { :; }; :; }; g' &&
 MALLOC_OPTIONS=J ${SH} -c 'g() { unset -f g; :; }; g'
diff --git a/sh/tests/execution/func2.0 b/sh/tests/execution/func2.0
index 9830b5e..eb48cc8 100644
--- a/sh/tests/execution/func2.0
+++ b/sh/tests/execution/func2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/func2.0 211399 2010-08-16 17:18:08Z jilles $
 # The empty pairs of braces here are to test that this does not cause a crash.
 
 f() { }
diff --git a/sh/tests/execution/func3.0 b/sh/tests/execution/func3.0
index e0ed581..209e255 100644
--- a/sh/tests/execution/func3.0
+++ b/sh/tests/execution/func3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/func3.0 216398 2010-12-12 21:18:16Z jilles $
 
 # This may fail when parsing or when defining the function, or the definition
 # may silently do nothing. In no event may the function be executed.
diff --git a/sh/tests/execution/hash1.0 b/sh/tests/execution/hash1.0
index a645c2a..d019296 100644
--- a/sh/tests/execution/hash1.0
+++ b/sh/tests/execution/hash1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/hash1.0 218323 2011-02-05 14:01:46Z jilles $
 
 T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
 trap 'rm -rf "${T}"' 0
diff --git a/sh/tests/execution/int-cmd1.0 b/sh/tests/execution/int-cmd1.0
index a1f097b..e980461 100644
--- a/sh/tests/execution/int-cmd1.0
+++ b/sh/tests/execution/int-cmd1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/int-cmd1.0 253271 2013-07-12 15:29:41Z jilles $
 
 ! echo echo bad | $SH -ic 'fi' 2>/dev/null
diff --git a/sh/tests/execution/killed1.0 b/sh/tests/execution/killed1.0
index 41d3e05..ef9221d 100644
--- a/sh/tests/execution/killed1.0
+++ b/sh/tests/execution/killed1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/killed1.0 217557 2011-01-18 21:18:31Z jilles $
 # Sometimes the "Killed" message is not flushed soon enough and it
 # is redirected along with the output of a builtin.
 # Do not change the semicolon to a newline as it would hide the bug.
diff --git a/sh/tests/execution/killed2.0 b/sh/tests/execution/killed2.0
index 7ff3fe2..4d6de16 100644
--- a/sh/tests/execution/killed2.0
+++ b/sh/tests/execution/killed2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/killed2.0 218105 2011-01-30 22:57:52Z jilles $
 # Most shells print a message when a foreground job is killed by a signal.
 # POSIX allows this, provided the message is sent to stderr, not stdout.
 # Some trickery is needed to capture the message as redirecting stderr of
diff --git a/sh/tests/execution/not1.0 b/sh/tests/execution/not1.0
index 12c6265..c825e13 100644
--- a/sh/tests/execution/not1.0
+++ b/sh/tests/execution/not1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/not1.0 249407 2013-04-12 15:19:35Z jilles $
 
 f() { ! return $1; }
 f 0 && ! f 1
diff --git a/sh/tests/execution/not2.0 b/sh/tests/execution/not2.0
index 1b128d0..e4155a9 100644
--- a/sh/tests/execution/not2.0
+++ b/sh/tests/execution/not2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/not2.0 249407 2013-04-12 15:19:35Z jilles $
 
 while :; do
 	! break
diff --git a/sh/tests/execution/path1.0 b/sh/tests/execution/path1.0
index 50829d6..3d5c67b 100644
--- a/sh/tests/execution/path1.0
+++ b/sh/tests/execution/path1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/path1.0 217206 2011-01-09 21:07:30Z jilles $
 # Some builtins should not be overridable via PATH.
 
 set -e
diff --git a/sh/tests/execution/redir1.0 b/sh/tests/execution/redir1.0
index dd0011f..6310478 100644
--- a/sh/tests/execution/redir1.0
+++ b/sh/tests/execution/redir1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir1.0 211408 2010-08-16 22:23:19Z jilles $
 trap ': $((brokenpipe+=1))' PIPE
 
 P=${TMPDIR:-/tmp}
diff --git a/sh/tests/execution/redir2.0 b/sh/tests/execution/redir2.0
index 1588105..27509c7 100644
--- a/sh/tests/execution/redir2.0
+++ b/sh/tests/execution/redir2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir2.0 213738 2010-10-12 18:20:38Z obrien $
 trap ': $((brokenpipe+=1))' PIPE
 
 P=${TMPDIR:-/tmp}
diff --git a/sh/tests/execution/redir3.0 b/sh/tests/execution/redir3.0
index d68e450..1b72098 100644
--- a/sh/tests/execution/redir3.0
+++ b/sh/tests/execution/redir3.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir3.0 214289 2010-10-24 19:56:34Z jilles $
 
 3>&- 3>&-
diff --git a/sh/tests/execution/redir4.0 b/sh/tests/execution/redir4.0
index 57054c1..01b1f87 100644
--- a/sh/tests/execution/redir4.0
+++ b/sh/tests/execution/redir4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir4.0 214290 2010-10-24 20:09:49Z jilles $
 
 { echo bad 0>&3; } 2>/dev/null 3>/dev/null 3>&-
 exit 0
diff --git a/sh/tests/execution/redir5.0 b/sh/tests/execution/redir5.0
index 707ca68..346c132 100644
--- a/sh/tests/execution/redir5.0
+++ b/sh/tests/execution/redir5.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir5.0 218325 2011-02-05 15:02:19Z jilles $
 
 { (echo bad) >/dev/null; } </dev/null
diff --git a/sh/tests/execution/redir6.0 b/sh/tests/execution/redir6.0
index 4e3ac0c..f663e51 100644
--- a/sh/tests/execution/redir6.0
+++ b/sh/tests/execution/redir6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir6.0 220978 2011-04-23 22:28:56Z jilles $
 
 failures=0
 
diff --git a/sh/tests/execution/redir7.0 b/sh/tests/execution/redir7.0
index 2487bcf..0e309a7 100644
--- a/sh/tests/execution/redir7.0
+++ b/sh/tests/execution/redir7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/redir7.0 220978 2011-04-23 22:28:56Z jilles $
 
 failures=0
 
diff --git a/sh/tests/execution/set-n1.0 b/sh/tests/execution/set-n1.0
index 14c9b93..95eb98c 100644
--- a/sh/tests/execution/set-n1.0
+++ b/sh/tests/execution/set-n1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-n1.0 222661 2011-06-03 21:17:42Z jilles $
 
 v=$( ($SH -n <<'EOF'
 for
diff --git a/sh/tests/execution/set-n2.0 b/sh/tests/execution/set-n2.0
index c7f3162..d64fcca 100644
--- a/sh/tests/execution/set-n2.0
+++ b/sh/tests/execution/set-n2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-n2.0 222661 2011-06-03 21:17:42Z jilles $
 
 $SH -n <<'EOF'
 echo bad
diff --git a/sh/tests/execution/set-n3.0 b/sh/tests/execution/set-n3.0
index 24a9159..5af1bc4 100644
--- a/sh/tests/execution/set-n3.0
+++ b/sh/tests/execution/set-n3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-n3.0 222661 2011-06-03 21:17:42Z jilles $
 
 v=$( ($SH -nc 'for') 2>&1 >/dev/null)
 [ $? -ne 0 ] && [ -n "$v" ]
diff --git a/sh/tests/execution/set-n4.0 b/sh/tests/execution/set-n4.0
index 3698508..2904a34 100644
--- a/sh/tests/execution/set-n4.0
+++ b/sh/tests/execution/set-n4.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-n4.0 222676 2011-06-04 11:28:42Z jilles $
 
 $SH -nc 'echo bad'
diff --git a/sh/tests/execution/set-x1.0 b/sh/tests/execution/set-x1.0
index 7fe1dbf..e498a3f 100644
--- a/sh/tests/execution/set-x1.0
+++ b/sh/tests/execution/set-x1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-x1.0 222882 2011-06-08 21:58:19Z jilles $
 
 key='must_contain_this'
 { r=`set -x; { : "$key"; } 2>&1 >/dev/null`; } 2>/dev/null
diff --git a/sh/tests/execution/set-x2.0 b/sh/tests/execution/set-x2.0
index 56d54e3..42c66a6 100644
--- a/sh/tests/execution/set-x2.0
+++ b/sh/tests/execution/set-x2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-x2.0 222882 2011-06-08 21:58:19Z jilles $
 
 key='must contain this'
 PS4="$key+ "
diff --git a/sh/tests/execution/set-x3.0 b/sh/tests/execution/set-x3.0
index 1ca57ac..29a917e 100644
--- a/sh/tests/execution/set-x3.0
+++ b/sh/tests/execution/set-x3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-x3.0 222907 2011-06-09 23:12:23Z jilles $
 
 key='must contain this'
 PS4='$key+ '
diff --git a/sh/tests/execution/set-x4.0 b/sh/tests/execution/set-x4.0
index 0904766..90dd59a 100644
--- a/sh/tests/execution/set-x4.0
+++ b/sh/tests/execution/set-x4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/set-x4.0 275766 2014-12-14 16:26:19Z jilles $
 
 key=`printf '\r\t\001\200\300'`
 r=`{ set -x; : "$key"; } 2>&1 >/dev/null`
diff --git a/sh/tests/execution/shellproc1.0 b/sh/tests/execution/shellproc1.0
index 1326bc2..5150b73 100644
--- a/sh/tests/execution/shellproc1.0
+++ b/sh/tests/execution/shellproc1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/shellproc1.0 218205 2011-02-02 22:03:18Z jilles $
 
 T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
 trap 'rm -rf "${T}"' 0
diff --git a/sh/tests/execution/subshell1.0 b/sh/tests/execution/subshell1.0
index 347806e..68b0123 100644
--- a/sh/tests/execution/subshell1.0
+++ b/sh/tests/execution/subshell1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/subshell1.0 245383 2013-01-13 19:39:13Z jilles $
 
 (eval "cd /
 v=$(printf %0100000d 1)
diff --git a/sh/tests/execution/subshell2.0 b/sh/tests/execution/subshell2.0
index 3216449..2d87730 100644
--- a/sh/tests/execution/subshell2.0
+++ b/sh/tests/execution/subshell2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/subshell2.0 245383 2013-01-13 19:39:13Z jilles $
 
 f() {
 	x=2
diff --git a/sh/tests/execution/subshell3.0 b/sh/tests/execution/subshell3.0
index 9a87acb..697ee0b 100644
--- a/sh/tests/execution/subshell3.0
+++ b/sh/tests/execution/subshell3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/subshell3.0 245383 2013-01-13 19:39:13Z jilles $
 
 (false; exit) && exit 3
 exit 0
diff --git a/sh/tests/execution/subshell4.0 b/sh/tests/execution/subshell4.0
index b39edb1..009db3d 100644
--- a/sh/tests/execution/subshell4.0
+++ b/sh/tests/execution/subshell4.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/subshell4.0 245383 2013-01-13 19:39:13Z jilles $
 
 (eval "set v=1"; false) && echo bad; :
diff --git a/sh/tests/execution/unknown1.0 b/sh/tests/execution/unknown1.0
index 45f541e..dd4149e 100644
--- a/sh/tests/execution/unknown1.0
+++ b/sh/tests/execution/unknown1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/unknown1.0 197820 2009-10-06 22:00:14Z jilles $
 
 nosuchtool 2>/dev/null
 [ $? -ne 127 ] && exit 1
diff --git a/sh/tests/execution/var-assign1.0 b/sh/tests/execution/var-assign1.0
index 26e5424..b75f969 100644
--- a/sh/tests/execution/var-assign1.0
+++ b/sh/tests/execution/var-assign1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/execution/var-assign1.0 212467 2010-09-11 14:15:50Z jilles $
 
 [ "$(HOME=/etc HOME=/ cd && pwd)" = / ]
diff --git a/sh/tests/expansion/Makefile b/sh/tests/expansion/Makefile
index e359ae7..734d4f3 100644
--- a/sh/tests/expansion/Makefile
+++ b/sh/tests/expansion/Makefile
@@ -1,94 +1,96 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/Makefile 302937 2016-07-16 13:26:18Z ache $
+
+PACKAGE=	tests
 
 TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		arith1.0
-FILES+=		arith2.0
-FILES+=		arith3.0
-FILES+=		arith4.0
-FILES+=		arith5.0
-FILES+=		arith6.0
-FILES+=		arith7.0
-FILES+=		arith8.0
-FILES+=		arith9.0
-FILES+=		arith10.0
-FILES+=		arith11.0
-FILES+=		arith12.0
-FILES+=		arith13.0
-FILES+=		arith14.0
-FILES+=		assign1.0
-FILES+=		cmdsubst1.0
-FILES+=		cmdsubst2.0
-FILES+=		cmdsubst3.0
-FILES+=		cmdsubst4.0
-FILES+=		cmdsubst5.0
-FILES+=		cmdsubst6.0
-FILES+=		cmdsubst7.0
-FILES+=		cmdsubst8.0
-FILES+=		cmdsubst9.0
-FILES+=		cmdsubst10.0
-FILES+=		cmdsubst11.0
-FILES+=		cmdsubst12.0
-FILES+=		cmdsubst13.0
-FILES+=		cmdsubst14.0
-FILES+=		cmdsubst15.0
-FILES+=		cmdsubst16.0
-FILES+=		cmdsubst17.0
-FILES+=		export1.0
-FILES+=		export2.0
-FILES+=		export3.0
-FILES+=		heredoc1.0
-FILES+=		heredoc2.0
-FILES+=		ifs1.0
-FILES+=		ifs2.0
-FILES+=		ifs3.0
-FILES+=		ifs4.0
-FILES+=		ifs5.0
-FILES+=		ifs6.0
-FILES+=		ifs7.0
-FILES+=		length1.0
-FILES+=		length2.0
-FILES+=		length3.0
-FILES+=		length4.0
-FILES+=		length5.0
-FILES+=		length6.0
-FILES+=		length7.0
-FILES+=		length8.0
-FILES+=		local1.0
-FILES+=		local2.0
-FILES+=		pathname1.0
-FILES+=		pathname2.0
-FILES+=		pathname3.0
-FILES+=		pathname4.0
-FILES+=		pathname5.0
-FILES+=		plus-minus1.0
-FILES+=		plus-minus2.0
-FILES+=		plus-minus3.0
-FILES+=		plus-minus4.0
-FILES+=		plus-minus5.0
-FILES+=		plus-minus6.0
-FILES+=		plus-minus7.0
-FILES+=		plus-minus8.0
-FILES+=		question1.0
-FILES+=		readonly1.0
-FILES+=		redir1.0
-FILES+=		set-u1.0
-FILES+=		set-u2.0
-FILES+=		set-u3.0
-FILES+=		tilde1.0
-FILES+=		tilde2.0
-FILES+=		trim1.0
-FILES+=		trim2.0
-FILES+=		trim3.0
-FILES+=		trim4.0
-FILES+=		trim5.0
-FILES+=		trim6.0
-FILES+=		trim7.0
-FILES+=		trim8.0
+${PACKAGE}FILES+=	arith1.0
+${PACKAGE}FILES+=	arith2.0
+${PACKAGE}FILES+=	arith3.0
+${PACKAGE}FILES+=	arith4.0
+${PACKAGE}FILES+=	arith5.0
+${PACKAGE}FILES+=	arith6.0
+${PACKAGE}FILES+=	arith7.0
+${PACKAGE}FILES+=	arith8.0
+${PACKAGE}FILES+=	arith9.0
+${PACKAGE}FILES+=	arith10.0
+${PACKAGE}FILES+=	arith11.0
+${PACKAGE}FILES+=	arith12.0
+${PACKAGE}FILES+=	arith13.0
+${PACKAGE}FILES+=	arith14.0
+${PACKAGE}FILES+=	assign1.0
+${PACKAGE}FILES+=	cmdsubst1.0
+${PACKAGE}FILES+=	cmdsubst2.0
+${PACKAGE}FILES+=	cmdsubst3.0
+${PACKAGE}FILES+=	cmdsubst4.0
+${PACKAGE}FILES+=	cmdsubst5.0
+${PACKAGE}FILES+=	cmdsubst6.0
+${PACKAGE}FILES+=	cmdsubst7.0
+${PACKAGE}FILES+=	cmdsubst8.0
+${PACKAGE}FILES+=	cmdsubst9.0
+${PACKAGE}FILES+=	cmdsubst10.0
+${PACKAGE}FILES+=	cmdsubst11.0
+${PACKAGE}FILES+=	cmdsubst12.0
+${PACKAGE}FILES+=	cmdsubst13.0
+${PACKAGE}FILES+=	cmdsubst14.0
+${PACKAGE}FILES+=	cmdsubst15.0
+${PACKAGE}FILES+=	cmdsubst16.0
+${PACKAGE}FILES+=	cmdsubst17.0
+${PACKAGE}FILES+=	export1.0
+${PACKAGE}FILES+=	export2.0
+${PACKAGE}FILES+=	export3.0
+${PACKAGE}FILES+=	heredoc1.0
+${PACKAGE}FILES+=	heredoc2.0
+${PACKAGE}FILES+=	ifs1.0
+${PACKAGE}FILES+=	ifs2.0
+${PACKAGE}FILES+=	ifs3.0
+${PACKAGE}FILES+=	ifs4.0
+${PACKAGE}FILES+=	ifs5.0
+${PACKAGE}FILES+=	ifs6.0
+${PACKAGE}FILES+=	ifs7.0
+${PACKAGE}FILES+=	length1.0
+${PACKAGE}FILES+=	length2.0
+${PACKAGE}FILES+=	length3.0
+${PACKAGE}FILES+=	length4.0
+${PACKAGE}FILES+=	length5.0
+${PACKAGE}FILES+=	length6.0
+${PACKAGE}FILES+=	length7.0
+${PACKAGE}FILES+=	length8.0
+${PACKAGE}FILES+=	local1.0
+${PACKAGE}FILES+=	local2.0
+${PACKAGE}FILES+=	pathname1.0
+${PACKAGE}FILES+=	pathname2.0
+${PACKAGE}FILES+=	pathname3.0
+${PACKAGE}FILES+=	pathname4.0
+${PACKAGE}FILES+=	pathname5.0
+${PACKAGE}FILES+=	pathname6.0
+${PACKAGE}FILES+=	plus-minus1.0
+${PACKAGE}FILES+=	plus-minus2.0
+${PACKAGE}FILES+=	plus-minus3.0
+${PACKAGE}FILES+=	plus-minus4.0
+${PACKAGE}FILES+=	plus-minus5.0
+${PACKAGE}FILES+=	plus-minus6.0
+${PACKAGE}FILES+=	plus-minus7.0
+${PACKAGE}FILES+=	plus-minus8.0
+${PACKAGE}FILES+=	question1.0
+${PACKAGE}FILES+=	readonly1.0
+${PACKAGE}FILES+=	redir1.0
+${PACKAGE}FILES+=	set-u1.0
+${PACKAGE}FILES+=	set-u2.0
+${PACKAGE}FILES+=	set-u3.0
+${PACKAGE}FILES+=	tilde1.0
+${PACKAGE}FILES+=	tilde2.0
+${PACKAGE}FILES+=	trim1.0
+${PACKAGE}FILES+=	trim2.0
+${PACKAGE}FILES+=	trim3.0
+${PACKAGE}FILES+=	trim4.0
+${PACKAGE}FILES+=	trim5.0
+${PACKAGE}FILES+=	trim6.0
+${PACKAGE}FILES+=	trim7.0
+${PACKAGE}FILES+=	trim8.0
+${PACKAGE}FILES+=	trim9.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/expansion/Makefile.depend b/sh/tests/expansion/Makefile.depend
new file mode 100644
index 0000000..547cbb3
--- /dev/null
+++ b/sh/tests/expansion/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/expansion/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/expansion/arith1.0 b/sh/tests/expansion/arith1.0
index 118ba22..c301600 100644
--- a/sh/tests/expansion/arith1.0
+++ b/sh/tests/expansion/arith1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith1.0 201259 2009-12-30 15:59:40Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/arith10.0 b/sh/tests/expansion/arith10.0
index 1aaf619..9e3db28 100644
--- a/sh/tests/expansion/arith10.0
+++ b/sh/tests/expansion/arith10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith10.0 218469 2011-02-08 23:23:55Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/arith11.0 b/sh/tests/expansion/arith11.0
index 6bc7369..4a33831 100644
--- a/sh/tests/expansion/arith11.0
+++ b/sh/tests/expansion/arith11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith11.0 218626 2011-02-12 23:44:05Z jilles $
 # Try to divide the smallest integer by -1.
 # On amd64 this causes SIGFPE, so make sure the shell checks.
 
diff --git a/sh/tests/expansion/arith12.0 b/sh/tests/expansion/arith12.0
index cb7da3b..7d79d7e 100644
--- a/sh/tests/expansion/arith12.0
+++ b/sh/tests/expansion/arith12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith12.0 232839 2012-03-11 22:12:05Z jilles $
 
 _x=4 y_=5 z_z=6
 [ "$((_x*100+y_*10+z_z))" = 456 ]
diff --git a/sh/tests/expansion/arith13.0 b/sh/tests/expansion/arith13.0
index 207e488..5421cb0 100644
--- a/sh/tests/expansion/arith13.0
+++ b/sh/tests/expansion/arith13.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith13.0 254806 2013-08-24 20:06:00Z jilles $
 # Pre-increment and pre-decrement in arithmetic expansion are not in POSIX.
 # Require either an error or a correct implementation.
 
diff --git a/sh/tests/expansion/arith14.0 b/sh/tests/expansion/arith14.0
index 8369043..a51e916 100644
--- a/sh/tests/expansion/arith14.0
+++ b/sh/tests/expansion/arith14.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith14.0 270029 2014-08-15 22:36:41Z jilles $
 # Check that <</>> use the low bits of the shift count.
 
 if [ $((1<<16<<16)) = 0 ]; then
diff --git a/sh/tests/expansion/arith2.0 b/sh/tests/expansion/arith2.0
index 95b48a0..b5874e5 100644
--- a/sh/tests/expansion/arith2.0
+++ b/sh/tests/expansion/arith2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith2.0 209652 2010-07-02 21:31:24Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/arith3.0 b/sh/tests/expansion/arith3.0
index b69159d..6b60b51 100644
--- a/sh/tests/expansion/arith3.0
+++ b/sh/tests/expansion/arith3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith3.0 204017 2010-02-17 22:25:22Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/arith4.0 b/sh/tests/expansion/arith4.0
index 610dad8..a41a0f7 100644
--- a/sh/tests/expansion/arith4.0
+++ b/sh/tests/expansion/arith4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith4.0 206167 2010-04-04 16:29:48Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/arith5.0 b/sh/tests/expansion/arith5.0
index d0f2331..1cd021f 100644
--- a/sh/tests/expansion/arith5.0
+++ b/sh/tests/expansion/arith5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith5.0 206168 2010-04-04 16:48:33Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/arith6.0 b/sh/tests/expansion/arith6.0
index fc4589c..528f4e8 100644
--- a/sh/tests/expansion/arith6.0
+++ b/sh/tests/expansion/arith6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith6.0 215550 2010-11-19 22:25:32Z jilles $
 
 v1=1\ +\ 1
 v2=D
diff --git a/sh/tests/expansion/arith7.0 b/sh/tests/expansion/arith7.0
index 5aada2b..f31dba1 100644
--- a/sh/tests/expansion/arith7.0
+++ b/sh/tests/expansion/arith7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith7.0 216395 2010-12-12 16:56:16Z jilles $
 
 v=1+
 v=$v$v$v$v
diff --git a/sh/tests/expansion/arith8.0 b/sh/tests/expansion/arith8.0
index 2d03e50..e0739f8 100644
--- a/sh/tests/expansion/arith8.0
+++ b/sh/tests/expansion/arith8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith8.0 216547 2010-12-18 23:03:51Z jilles $
 
 v=$( (eval ': $((08))') 2>&1 >/dev/null)
 [ $? -ne 0 ] && [ -n "$v" ]
diff --git a/sh/tests/expansion/arith9.0 b/sh/tests/expansion/arith9.0
index cc8b597..e47d003 100644
--- a/sh/tests/expansion/arith9.0
+++ b/sh/tests/expansion/arith9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/arith9.0 218469 2011-02-08 23:23:55Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/assign1.0 b/sh/tests/expansion/assign1.0
index d4fa772..ee4c0d8 100644
--- a/sh/tests/expansion/assign1.0
+++ b/sh/tests/expansion/assign1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/assign1.0 204842 2010-03-07 18:43:29Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/cmdsubst1.0 b/sh/tests/expansion/cmdsubst1.0
index 515c7da..ea89f42 100644
--- a/sh/tests/expansion/cmdsubst1.0
+++ b/sh/tests/expansion/cmdsubst1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst1.0 201366 2010-01-01 18:17:46Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/cmdsubst10.0 b/sh/tests/expansion/cmdsubst10.0
index 7cf17a3..dc13d39 100644
--- a/sh/tests/expansion/cmdsubst10.0
+++ b/sh/tests/expansion/cmdsubst10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst10.0 216826 2010-12-30 22:33:55Z jilles $
 
 a1=$(alias)
 : $(alias testalias=abcd)
diff --git a/sh/tests/expansion/cmdsubst11.0 b/sh/tests/expansion/cmdsubst11.0
index f1af547..cb035ae 100644
--- a/sh/tests/expansion/cmdsubst11.0
+++ b/sh/tests/expansion/cmdsubst11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst11.0 223163 2011-06-16 21:50:28Z jilles $
 
 # Not required by POSIX but useful for efficiency.
 
diff --git a/sh/tests/expansion/cmdsubst12.0 b/sh/tests/expansion/cmdsubst12.0
index 50394db..4d330ef 100644
--- a/sh/tests/expansion/cmdsubst12.0
+++ b/sh/tests/expansion/cmdsubst12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst12.0 230121 2012-01-14 23:10:18Z jilles $
 
 f() {
 	echo x$(printf foo >&2)y
diff --git a/sh/tests/expansion/cmdsubst13.0 b/sh/tests/expansion/cmdsubst13.0
index 7fdc5b2..d3fc399 100644
--- a/sh/tests/expansion/cmdsubst13.0
+++ b/sh/tests/expansion/cmdsubst13.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst13.0 230121 2012-01-14 23:10:18Z jilles $
 
 x=1 y=2
 [ "$(
diff --git a/sh/tests/expansion/cmdsubst14.0 b/sh/tests/expansion/cmdsubst14.0
index bdbbb82..8a916af 100644
--- a/sh/tests/expansion/cmdsubst14.0
+++ b/sh/tests/expansion/cmdsubst14.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst14.0 245381 2013-01-13 19:19:40Z jilles $
 
 ! v=`false
 
diff --git a/sh/tests/expansion/cmdsubst15.0 b/sh/tests/expansion/cmdsubst15.0
index 31d85d4..9599ef8 100644
--- a/sh/tests/expansion/cmdsubst15.0
+++ b/sh/tests/expansion/cmdsubst15.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst15.0 245381 2013-01-13 19:19:40Z jilles $
 
 ! v=`false;
 
diff --git a/sh/tests/expansion/cmdsubst16.0 b/sh/tests/expansion/cmdsubst16.0
index 71df562..2483601 100644
--- a/sh/tests/expansion/cmdsubst16.0
+++ b/sh/tests/expansion/cmdsubst16.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst16.0 245392 2013-01-13 22:35:51Z jilles $
 
 f() { return 3; }
 f
diff --git a/sh/tests/expansion/cmdsubst17.0 b/sh/tests/expansion/cmdsubst17.0
index 8c29e83..d3a2b54 100644
--- a/sh/tests/expansion/cmdsubst17.0
+++ b/sh/tests/expansion/cmdsubst17.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst17.0 245422 2013-01-14 12:20:55Z jilles $
 
 f() { return 3; }
 f
diff --git a/sh/tests/expansion/cmdsubst2.0 b/sh/tests/expansion/cmdsubst2.0
index b86776e..35453be 100644
--- a/sh/tests/expansion/cmdsubst2.0
+++ b/sh/tests/expansion/cmdsubst2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst2.0 205105 2010-03-12 23:23:46Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/cmdsubst3.0 b/sh/tests/expansion/cmdsubst3.0
index abb6b22..221b11b 100644
--- a/sh/tests/expansion/cmdsubst3.0
+++ b/sh/tests/expansion/cmdsubst3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst3.0 218819 2011-02-18 20:37:09Z jilles $
 
 unset LC_ALL
 export LC_CTYPE=en_US.ISO8859-1
diff --git a/sh/tests/expansion/cmdsubst4.0 b/sh/tests/expansion/cmdsubst4.0
index ee1ce73..4d5a134 100644
--- a/sh/tests/expansion/cmdsubst4.0
+++ b/sh/tests/expansion/cmdsubst4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst4.0 216747 2010-12-27 23:56:03Z jilles $
 
 exec 2>/dev/null
 ! y=$(: </var/empty/nonexistent)
diff --git a/sh/tests/expansion/cmdsubst5.0 b/sh/tests/expansion/cmdsubst5.0
index afca371..70b4298 100644
--- a/sh/tests/expansion/cmdsubst5.0
+++ b/sh/tests/expansion/cmdsubst5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst5.0 216761 2010-12-28 13:28:24Z jilles $
 
 unset v
 exec 2>/dev/null
diff --git a/sh/tests/expansion/cmdsubst6.0 b/sh/tests/expansion/cmdsubst6.0
index 6586f33..0e47bce 100644
--- a/sh/tests/expansion/cmdsubst6.0
+++ b/sh/tests/expansion/cmdsubst6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst6.0 216763 2010-12-28 14:58:08Z jilles $
 # This tests if the cmdsubst optimization is still used if possible.
 
 failures=''
diff --git a/sh/tests/expansion/cmdsubst7.0 b/sh/tests/expansion/cmdsubst7.0
index dbd1aec..6b4cd1d 100644
--- a/sh/tests/expansion/cmdsubst7.0
+++ b/sh/tests/expansion/cmdsubst7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst7.0 216778 2010-12-28 21:27:08Z jilles $
 
 failures=''
 ok=''
diff --git a/sh/tests/expansion/cmdsubst8.0 b/sh/tests/expansion/cmdsubst8.0
index 52adaea..19ff803 100644
--- a/sh/tests/expansion/cmdsubst8.0
+++ b/sh/tests/expansion/cmdsubst8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst8.0 216819 2010-12-30 15:04:59Z jilles $
 # Not required by POSIX (although referenced in a non-normative section),
 # but possibly useful.
 
diff --git a/sh/tests/expansion/cmdsubst9.0 b/sh/tests/expansion/cmdsubst9.0
index 0b1f81f..8bbf2b9 100644
--- a/sh/tests/expansion/cmdsubst9.0
+++ b/sh/tests/expansion/cmdsubst9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/cmdsubst9.0 216819 2010-12-30 15:04:59Z jilles $
 
 set -e
 
diff --git a/sh/tests/expansion/export1.0 b/sh/tests/expansion/export1.0
index 4ee3ef4..3286fb9 100644
--- a/sh/tests/expansion/export1.0
+++ b/sh/tests/expansion/export1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/export1.0 238430 2012-07-13 22:29:02Z jilles $
 
 w='@ vv=6'
 
diff --git a/sh/tests/expansion/export2.0 b/sh/tests/expansion/export2.0
index 57f64e7..e8862b8 100644
--- a/sh/tests/expansion/export2.0
+++ b/sh/tests/expansion/export2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/export2.0 238468 2012-07-15 10:19:43Z jilles $
 
 w='@ @'
 check() {
diff --git a/sh/tests/expansion/export3.0 b/sh/tests/expansion/export3.0
index a1a0e66..b82fcc1 100644
--- a/sh/tests/expansion/export3.0
+++ b/sh/tests/expansion/export3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/export3.0 238468 2012-07-15 10:19:43Z jilles $
 
 w='@ @'
 check() {
diff --git a/sh/tests/expansion/heredoc1.0 b/sh/tests/expansion/heredoc1.0
index a67b2da..94328c0 100644
--- a/sh/tests/expansion/heredoc1.0
+++ b/sh/tests/expansion/heredoc1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/heredoc1.0 222715 2011-06-05 12:46:26Z jilles $
 
 f() { return $1; }
 
diff --git a/sh/tests/expansion/heredoc2.0 b/sh/tests/expansion/heredoc2.0
index 2551432..24c4cc6 100644
--- a/sh/tests/expansion/heredoc2.0
+++ b/sh/tests/expansion/heredoc2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/heredoc2.0 222716 2011-06-05 14:13:15Z jilles $
 
 f() { return $1; }
 
diff --git a/sh/tests/expansion/ifs1.0 b/sh/tests/expansion/ifs1.0
index e7f53c7..4d5157a 100644
--- a/sh/tests/expansion/ifs1.0
+++ b/sh/tests/expansion/ifs1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs1.0 194981 2009-06-25 17:36:08Z jilles $
 
 c=: e= s=' '
 failures=''
diff --git a/sh/tests/expansion/ifs2.0 b/sh/tests/expansion/ifs2.0
index e91b867..3d71b52 100644
--- a/sh/tests/expansion/ifs2.0
+++ b/sh/tests/expansion/ifs2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs2.0 211341 2010-08-15 17:14:05Z jilles $
 
 failures=0
 i=1
diff --git a/sh/tests/expansion/ifs3.0 b/sh/tests/expansion/ifs3.0
index 0569b57..d034654 100644
--- a/sh/tests/expansion/ifs3.0
+++ b/sh/tests/expansion/ifs3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs3.0 211622 2010-08-22 13:09:12Z jilles $
 
 failures=0
 unset LC_ALL
diff --git a/sh/tests/expansion/ifs4.0 b/sh/tests/expansion/ifs4.0
index 5b896a2..a307ec5 100644
--- a/sh/tests/expansion/ifs4.0
+++ b/sh/tests/expansion/ifs4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs4.0 222361 2011-05-27 15:56:13Z jilles $
 
 c=: e= s=' '
 failures=''
diff --git a/sh/tests/expansion/ifs5.0 b/sh/tests/expansion/ifs5.0
index ab0e646..fc5b4b7 100644
--- a/sh/tests/expansion/ifs5.0
+++ b/sh/tests/expansion/ifs5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs5.0 278806 2015-02-15 19:48:29Z jilles $
 
 set -- $(echo a b c d)
 [ "$#" = 4 ]
diff --git a/sh/tests/expansion/ifs6.0 b/sh/tests/expansion/ifs6.0
index be77945..3ec5dbc 100644
--- a/sh/tests/expansion/ifs6.0
+++ b/sh/tests/expansion/ifs6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs6.0 280920 2015-03-31 20:59:37Z jilles $
 
 IFS=': '
 x=': :'
diff --git a/sh/tests/expansion/ifs7.0 b/sh/tests/expansion/ifs7.0
index 0cc0834..a59f313 100644
--- a/sh/tests/expansion/ifs7.0
+++ b/sh/tests/expansion/ifs7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/ifs7.0 280920 2015-03-31 20:59:37Z jilles $
 
 IFS=2
 set -- $((123))
diff --git a/sh/tests/expansion/length1.0 b/sh/tests/expansion/length1.0
index 2aaebf9..cee5808 100644
--- a/sh/tests/expansion/length1.0
+++ b/sh/tests/expansion/length1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length1.0 219611 2011-03-13 16:20:38Z jilles $
 
 v=abcd
 [ "${#v}" = 4 ] || echo '${#v} wrong'
diff --git a/sh/tests/expansion/length2.0 b/sh/tests/expansion/length2.0
index d749b51..77fd6ad 100644
--- a/sh/tests/expansion/length2.0
+++ b/sh/tests/expansion/length2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length2.0 219611 2011-03-13 16:20:38Z jilles $
 
 v=$-
 [ "${#-}" = "${#v}" ] || echo '${#-} wrong'
diff --git a/sh/tests/expansion/length3.0 b/sh/tests/expansion/length3.0
index 2093eed..27045b7 100644
--- a/sh/tests/expansion/length3.0
+++ b/sh/tests/expansion/length3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length3.0 219611 2011-03-13 16:20:38Z jilles $
 
 set -- 1 2 3 4 5 6 7 8 9 10 11 12 13
 [ "$#" = 13 ] || echo '$# wrong'
diff --git a/sh/tests/expansion/length4.0 b/sh/tests/expansion/length4.0
index 5348be5..c1ff021 100644
--- a/sh/tests/expansion/length4.0
+++ b/sh/tests/expansion/length4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length4.0 220655 2011-04-15 15:26:05Z jilles $
 
 # The construct ${#?} is ambiguous in POSIX.1-2008: it could be the length
 # of $? or it could be $# giving an error in the (impossible) case that it
diff --git a/sh/tests/expansion/length5.0 b/sh/tests/expansion/length5.0
index 322ca16..da8ebb5 100644
--- a/sh/tests/expansion/length5.0
+++ b/sh/tests/expansion/length5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length5.0 220656 2011-04-15 15:33:24Z jilles $
 
 unset LC_ALL
 LC_CTYPE=en_US.ISO8859-1
diff --git a/sh/tests/expansion/length6.0 b/sh/tests/expansion/length6.0
index 6b78309..8da2da8 100644
--- a/sh/tests/expansion/length6.0
+++ b/sh/tests/expansion/length6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length6.0 220903 2011-04-20 22:24:54Z jilles $
 
 x='!@#$%^&*()[]'
 [ ${#x} = 12 ] || echo bad 1
diff --git a/sh/tests/expansion/length7.0 b/sh/tests/expansion/length7.0
index b79b116..500b7e7 100644
--- a/sh/tests/expansion/length7.0
+++ b/sh/tests/expansion/length7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length7.0 221602 2011-05-07 14:32:16Z jilles $
 
 unset LC_ALL
 LC_CTYPE=en_US.UTF-8
diff --git a/sh/tests/expansion/length8.0 b/sh/tests/expansion/length8.0
index 3cc6c15..d4f91d8 100644
--- a/sh/tests/expansion/length8.0
+++ b/sh/tests/expansion/length8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/length8.0 221602 2011-05-07 14:32:16Z jilles $
 
 unset LC_ALL
 LC_CTYPE=en_US.ISO8859-1
diff --git a/sh/tests/expansion/local1.0 b/sh/tests/expansion/local1.0
index 3477835..9f16eb0 100644
--- a/sh/tests/expansion/local1.0
+++ b/sh/tests/expansion/local1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/local1.0 238468 2012-07-15 10:19:43Z jilles $
 
 run_test() {
 	w='@ @'
diff --git a/sh/tests/expansion/local2.0 b/sh/tests/expansion/local2.0
index 1984290..9d1a38a 100644
--- a/sh/tests/expansion/local2.0
+++ b/sh/tests/expansion/local2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/local2.0 238468 2012-07-15 10:19:43Z jilles $
 
 run_test() {
 	w='@ @'
diff --git a/sh/tests/expansion/pathname1.0 b/sh/tests/expansion/pathname1.0
index 8c6b01c..6f40004 100644
--- a/sh/tests/expansion/pathname1.0
+++ b/sh/tests/expansion/pathname1.0
@@ -1,4 +1,8 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/pathname1.0 302937 2016-07-16 13:26:18Z ache $
+
+unset LC_ALL
+LC_COLLATE=C
+export LC_COLLATE
 
 failures=0
 
diff --git a/sh/tests/expansion/pathname2.0 b/sh/tests/expansion/pathname2.0
index 8a884ff..3efffb7 100644
--- a/sh/tests/expansion/pathname2.0
+++ b/sh/tests/expansion/pathname2.0
@@ -1,4 +1,8 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/pathname2.0 302937 2016-07-16 13:26:18Z ache $
+
+unset LC_ALL
+LC_COLLATE=C
+export LC_COLLATE
 
 failures=0
 
diff --git a/sh/tests/expansion/pathname3.0 b/sh/tests/expansion/pathname3.0
index d1672e0..80d6478 100644
--- a/sh/tests/expansion/pathname3.0
+++ b/sh/tests/expansion/pathname3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/pathname3.0 211155 2010-08-10 22:45:59Z jilles $
 
 v=12345678
 v=$v$v$v$v
diff --git a/sh/tests/expansion/pathname4.0 b/sh/tests/expansion/pathname4.0
index 18269c4..d316c0a 100644
--- a/sh/tests/expansion/pathname4.0
+++ b/sh/tests/expansion/pathname4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/pathname4.0 211646 2010-08-22 21:18:21Z jilles $
 
 failures=0
 
diff --git a/sh/tests/expansion/pathname5.0 b/sh/tests/expansion/pathname5.0
index bc27812..42cd119 100644
--- a/sh/tests/expansion/pathname5.0
+++ b/sh/tests/expansion/pathname5.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/pathname5.0 278806 2015-02-15 19:48:29Z jilles $
 
 [ `echo '/[e]tc'` = /etc ]
diff --git a/sh/tests/expansion/pathname6.0 b/sh/tests/expansion/pathname6.0
new file mode 100644
index 0000000..e763c6a
--- /dev/null
+++ b/sh/tests/expansion/pathname6.0
@@ -0,0 +1,29 @@
+# $FreeBSD: head/bin/sh/tests/expansion/pathname6.0 302937 2016-07-16 13:26:18Z ache $
+
+unset LC_ALL
+LC_COLLATE=en_US.US-ASCII
+export LC_COLLATE
+
+failures=0
+
+check() {
+	testcase=$1
+	expect=$2
+	eval "set -- $testcase"
+	actual="$*"
+	if [ "$actual" != "$expect" ]; then
+		failures=$((failures+1))
+		printf '%s\n' "For $testcase, expected $expect actual $actual"
+	fi
+}
+
+set -e
+T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX)
+trap 'rm -rf $T' 0
+cd -P $T
+
+touch A B a b
+
+check '*' 'a A b B'
+
+exit $((failures != 0))
diff --git a/sh/tests/expansion/plus-minus1.0 b/sh/tests/expansion/plus-minus1.0
index 9a6a53a..088ed7f 100644
--- a/sh/tests/expansion/plus-minus1.0
+++ b/sh/tests/expansion/plus-minus1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus1.0 216738 2010-12-27 15:57:41Z emaste $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/plus-minus2.0 b/sh/tests/expansion/plus-minus2.0
index f5a8752..2f22988 100644
--- a/sh/tests/expansion/plus-minus2.0
+++ b/sh/tests/expansion/plus-minus2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus2.0 206145 2010-04-03 20:55:56Z jilles $
 
 e=
 test "${e:-\}}" = '}'
diff --git a/sh/tests/expansion/plus-minus3.0 b/sh/tests/expansion/plus-minus3.0
index 49fcdc2..d7fc923 100644
--- a/sh/tests/expansion/plus-minus3.0
+++ b/sh/tests/expansion/plus-minus3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus3.0 206817 2010-04-18 22:13:45Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/plus-minus4.0 b/sh/tests/expansion/plus-minus4.0
index 66dea38..4d2d37d 100644
--- a/sh/tests/expansion/plus-minus4.0
+++ b/sh/tests/expansion/plus-minus4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus4.0 211080 2010-08-08 17:03:23Z jilles $
 
 # These may be a bit unclear in the POSIX spec or the proposed revisions,
 # and conflict with bash's interpretation, but I think ksh93's interpretation
diff --git a/sh/tests/expansion/plus-minus5.0 b/sh/tests/expansion/plus-minus5.0
index 0b25e53..02db26c 100644
--- a/sh/tests/expansion/plus-minus5.0
+++ b/sh/tests/expansion/plus-minus5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus5.0 214492 2010-10-28 22:34:49Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/plus-minus6.0 b/sh/tests/expansion/plus-minus6.0
index bc66805..1bd3f7a 100644
--- a/sh/tests/expansion/plus-minus6.0
+++ b/sh/tests/expansion/plus-minus6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus6.0 214512 2010-10-29 13:42:18Z jilles $
 
 failures=0
 unset LC_ALL
diff --git a/sh/tests/expansion/plus-minus7.0 b/sh/tests/expansion/plus-minus7.0
index 9e81f58..440cfdd 100644
--- a/sh/tests/expansion/plus-minus7.0
+++ b/sh/tests/expansion/plus-minus7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus7.0 216738 2010-12-27 15:57:41Z emaste $
 
 e= s='foo'
 failures=''
diff --git a/sh/tests/expansion/plus-minus8.0 b/sh/tests/expansion/plus-minus8.0
index beba009..dd7e770 100644
--- a/sh/tests/expansion/plus-minus8.0
+++ b/sh/tests/expansion/plus-minus8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/plus-minus8.0 219623 2011-03-13 20:02:39Z jilles $
 
 set -- 1 2 3 4 5 6 7 8 9 10 11 12 13
 [ "${#+hi}" = hi ] || echo '${#+hi} wrong'
diff --git a/sh/tests/expansion/question1.0 b/sh/tests/expansion/question1.0
index 663c68d..2f07597 100644
--- a/sh/tests/expansion/question1.0
+++ b/sh/tests/expansion/question1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/question1.0 213738 2010-10-12 18:20:38Z obrien $
 
 x=a\ b
 [ "$x" = "${x?}" ] || exit 1
diff --git a/sh/tests/expansion/readonly1.0 b/sh/tests/expansion/readonly1.0
index 5ad0e14..e1e950a 100644
--- a/sh/tests/expansion/readonly1.0
+++ b/sh/tests/expansion/readonly1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/readonly1.0 238468 2012-07-15 10:19:43Z jilles $
 
 w='@ @'
 
diff --git a/sh/tests/expansion/redir1.0 b/sh/tests/expansion/redir1.0
index aa13e15..fd5c981 100644
--- a/sh/tests/expansion/redir1.0
+++ b/sh/tests/expansion/redir1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/redir1.0 273920 2014-10-31 22:28:10Z jilles $
 
 bad=0
 for i in 0 1 2 3; do
diff --git a/sh/tests/expansion/set-u1.0 b/sh/tests/expansion/set-u1.0
index 763eb7d..045d6ad 100644
--- a/sh/tests/expansion/set-u1.0
+++ b/sh/tests/expansion/set-u1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/set-u1.0 213738 2010-10-12 18:20:38Z obrien $
 
 ${SH} -uc 'unset foo; echo $foo' 2>/dev/null && exit 1
 ${SH} -uc 'foo=; echo $foo' >/dev/null || exit 1
diff --git a/sh/tests/expansion/set-u2.0 b/sh/tests/expansion/set-u2.0
index f81aa62..55da8aa 100644
--- a/sh/tests/expansion/set-u2.0
+++ b/sh/tests/expansion/set-u2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/set-u2.0 198454 2009-10-24 21:20:04Z jilles $
 
 set -u
 : $* $@ "$@" "$*"
diff --git a/sh/tests/expansion/set-u3.0 b/sh/tests/expansion/set-u3.0
index 7f199b4..ea848f7 100644
--- a/sh/tests/expansion/set-u3.0
+++ b/sh/tests/expansion/set-u3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/set-u3.0 221463 2011-05-04 22:12:22Z jilles $
 
 set -u
 unset x
diff --git a/sh/tests/expansion/tilde1.0 b/sh/tests/expansion/tilde1.0
index 7d8581b..c0a7f5b 100644
--- a/sh/tests/expansion/tilde1.0
+++ b/sh/tests/expansion/tilde1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/tilde1.0 206149 2010-04-03 21:56:24Z jilles $
 
 HOME=/tmp
 roothome=~root
diff --git a/sh/tests/expansion/tilde2.0 b/sh/tests/expansion/tilde2.0
index 4f8ed9b..7827c22 100644
--- a/sh/tests/expansion/tilde2.0
+++ b/sh/tests/expansion/tilde2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/tilde2.0 206150 2010-04-03 22:04:44Z jilles $
 
 HOME=/tmp
 roothome=~root
diff --git a/sh/tests/expansion/trim1.0 b/sh/tests/expansion/trim1.0
index b548e52..16dd838 100644
--- a/sh/tests/expansion/trim1.0
+++ b/sh/tests/expansion/trim1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim1.0 206143 2010-04-03 20:14:10Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/trim2.0 b/sh/tests/expansion/trim2.0
index 619ef65..15651b9 100644
--- a/sh/tests/expansion/trim2.0
+++ b/sh/tests/expansion/trim2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim2.0 206147 2010-04-03 21:07:50Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/trim3.0 b/sh/tests/expansion/trim3.0
index b89a041..28c59ae 100644
--- a/sh/tests/expansion/trim3.0
+++ b/sh/tests/expansion/trim3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim3.0 207127 2010-04-23 17:26:49Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##' c='\\\\'
diff --git a/sh/tests/expansion/trim4.0 b/sh/tests/expansion/trim4.0
index 1000bd3..f79b6fd 100644
--- a/sh/tests/expansion/trim4.0
+++ b/sh/tests/expansion/trim4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim4.0 213814 2010-10-13 23:29:09Z obrien $
 
 v1=/homes/SOME_USER
 v2=
diff --git a/sh/tests/expansion/trim5.0 b/sh/tests/expansion/trim5.0
index 937ec9a..8045eb6 100644
--- a/sh/tests/expansion/trim5.0
+++ b/sh/tests/expansion/trim5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim5.0 214490 2010-10-28 21:51:14Z jilles $
 
 e= q='?' a='*' t=texttext s='ast*que?non' p='/et[c]/' w='a b c' b='{{(#)}}'
 h='##'
diff --git a/sh/tests/expansion/trim6.0 b/sh/tests/expansion/trim6.0
index 3f753c4..e34a09f 100644
--- a/sh/tests/expansion/trim6.0
+++ b/sh/tests/expansion/trim6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim6.0 214524 2010-10-29 19:34:57Z jilles $
 
 e=
 for i in 0 1 2 3; do
diff --git a/sh/tests/expansion/trim7.0 b/sh/tests/expansion/trim7.0
index 352bdea..4f237cc 100644
--- a/sh/tests/expansion/trim7.0
+++ b/sh/tests/expansion/trim7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim7.0 219623 2011-03-13 20:02:39Z jilles $
 
 set -- 1 2 3 4 5 6 7 8 9 10 11 12 13
 [ "${##1}" = 3 ] || echo '${##1} wrong'
diff --git a/sh/tests/expansion/trim8.0 b/sh/tests/expansion/trim8.0
index f7272f3..c4b6ce4 100644
--- a/sh/tests/expansion/trim8.0
+++ b/sh/tests/expansion/trim8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/expansion/trim8.0 221646 2011-05-08 11:32:20Z jilles $
 
 unset LC_ALL
 LC_CTYPE=en_US.UTF-8
diff --git a/sh/tests/expansion/trim9.0 b/sh/tests/expansion/trim9.0
new file mode 100644
index 0000000..f0b08ab
--- /dev/null
+++ b/sh/tests/expansion/trim9.0
@@ -0,0 +1,61 @@
+# $FreeBSD: head/bin/sh/tests/expansion/trim9.0 292758 2015-12-26 22:27:48Z jilles $
+
+# POSIX does not specify these but they occasionally occur in the wild.
+# This just serves to keep working what currently works.
+
+failures=''
+ok=''
+
+testcase() {
+	code="$1"
+	expected="$2"
+	oIFS="$IFS"
+	eval "$code"
+	IFS='|'
+	result="$#|$*"
+	IFS="$oIFS"
+	if [ "x$result" = "x$expected" ]; then
+		ok=x$ok
+	else
+		failures=x$failures
+		echo "For $code, expected $expected actual $result"
+	fi
+}
+
+testcase 'shift $#; set -- "${*#Q}"'		'1|'
+testcase 'shift $#; set -- "${*##Q}"'		'1|'
+testcase 'shift $#; set -- "${*%Q}"'		'1|'
+testcase 'shift $#; set -- "${*%%Q}"'		'1|'
+testcase 'set -- Q R; set -- "${*#Q}"'		'1| R'
+testcase 'set -- Q R; set -- "${*##Q}"'		'1| R'
+testcase 'set -- Q R; set -- "${*%R}"'		'1|Q '
+testcase 'set -- Q R; set -- "${*%%R}"'		'1|Q '
+testcase 'set -- Q R; set -- "${*#S}"'		'1|Q R'
+testcase 'set -- Q R; set -- "${*##S}"'		'1|Q R'
+testcase 'set -- Q R; set -- "${*%S}"'		'1|Q R'
+testcase 'set -- Q R; set -- "${*%%S}"'		'1|Q R'
+testcase 'set -- Q R; set -- ${*#Q}'		'1|R'
+testcase 'set -- Q R; set -- ${*##Q}'		'1|R'
+testcase 'set -- Q R; set -- ${*%R}'		'1|Q'
+testcase 'set -- Q R; set -- ${*%%R}'		'1|Q'
+testcase 'set -- Q R; set -- ${*#S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${*##S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${*%S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${*%%S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${@#Q}'		'1|R'
+testcase 'set -- Q R; set -- ${@##Q}'		'1|R'
+testcase 'set -- Q R; set -- ${@%R}'		'1|Q'
+testcase 'set -- Q R; set -- ${@%%R}'		'1|Q'
+testcase 'set -- Q R; set -- ${@#S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${@##S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${@%S}'		'2|Q|R'
+testcase 'set -- Q R; set -- ${@%%S}'		'2|Q|R'
+testcase 'set -- Q R; set -- "${@#Q}"'		'2||R'
+testcase 'set -- Q R; set -- "${@%R}"'		'2|Q|'
+testcase 'set -- Q R; set -- "${@%%R}"'		'2|Q|'
+testcase 'set -- Q R; set -- "${@#S}"'		'2|Q|R'
+testcase 'set -- Q R; set -- "${@##S}"'		'2|Q|R'
+testcase 'set -- Q R; set -- "${@%S}"'		'2|Q|R'
+testcase 'set -- Q R; set -- "${@%%S}"'		'2|Q|R'
+
+test "x$failures" = x
diff --git a/sh/tests/functional_test.sh b/sh/tests/functional_test.sh
index 6980538..c2a1f81 100755
--- a/sh/tests/functional_test.sh
+++ b/sh/tests/functional_test.sh
@@ -24,7 +24,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/functional_test.sh 270101 2014-08-17 14:26:12Z jilles $
 
 SRCDIR=$(atf_get_srcdir)
 
diff --git a/sh/tests/parameters/Makefile b/sh/tests/parameters/Makefile
index 231ed4d..30708db 100644
--- a/sh/tests/parameters/Makefile
+++ b/sh/tests/parameters/Makefile
@@ -1,26 +1,29 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/Makefile 306843 2016-10-08 13:40:12Z jilles $
+
+PACKAGE=	tests
 
 TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		env1.0
-FILES+=		exitstatus1.0
-FILES+=		mail1.0
-FILES+=		mail2.0
-FILES+=		optind1.0
-FILES+=		optind2.0
-FILES+=		positional1.0
-FILES+=		positional2.0
-FILES+=		positional3.0
-FILES+=		positional4.0
-FILES+=		positional5.0
-FILES+=		positional6.0
-FILES+=		positional7.0
-FILES+=		pwd1.0
-FILES+=		pwd2.0
+${PACKAGE}FILES+=	env1.0
+${PACKAGE}FILES+=	exitstatus1.0
+${PACKAGE}FILES+=	ifs1.0
+${PACKAGE}FILES+=	mail1.0
+${PACKAGE}FILES+=	mail2.0
+${PACKAGE}FILES+=	optind1.0
+${PACKAGE}FILES+=	optind2.0
+${PACKAGE}FILES+=	positional1.0
+${PACKAGE}FILES+=	positional2.0
+${PACKAGE}FILES+=	positional3.0
+${PACKAGE}FILES+=	positional4.0
+${PACKAGE}FILES+=	positional5.0
+${PACKAGE}FILES+=	positional6.0
+${PACKAGE}FILES+=	positional7.0
+${PACKAGE}FILES+=	positional8.0
+${PACKAGE}FILES+=	positional9.0
+${PACKAGE}FILES+=	pwd1.0
+${PACKAGE}FILES+=	pwd2.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/parameters/Makefile.depend b/sh/tests/parameters/Makefile.depend
new file mode 100644
index 0000000..41114a3
--- /dev/null
+++ b/sh/tests/parameters/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/parameters/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/parameters/env1.0 b/sh/tests/parameters/env1.0
index c0d4a2c..0842856 100644
--- a/sh/tests/parameters/env1.0
+++ b/sh/tests/parameters/env1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/env1.0 222957 2011-06-10 22:42:00Z jilles $
 
 export key='must contain this'
 unset x
diff --git a/sh/tests/parameters/exitstatus1.0 b/sh/tests/parameters/exitstatus1.0
index 696823d..709600e 100644
--- a/sh/tests/parameters/exitstatus1.0
+++ b/sh/tests/parameters/exitstatus1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/exitstatus1.0 185232 2008-11-23 20:27:03Z stefanf $
 f() {
 	[ $? = $1 ] || exit 1
 }
diff --git a/sh/tests/parameters/ifs1.0 b/sh/tests/parameters/ifs1.0
new file mode 100644
index 0000000..e88d7a4
--- /dev/null
+++ b/sh/tests/parameters/ifs1.0
@@ -0,0 +1,10 @@
+# $FreeBSD: head/bin/sh/tests/parameters/ifs1.0 306843 2016-10-08 13:40:12Z jilles $
+
+env IFS=_ ${SH} -c '
+rc=2
+nosuchtool_function() {
+	rc=0
+}
+v=nosuchtool_function
+$v && exit "$rc"
+'
diff --git a/sh/tests/parameters/mail1.0 b/sh/tests/parameters/mail1.0
index 5791a5a..af69211 100644
--- a/sh/tests/parameters/mail1.0
+++ b/sh/tests/parameters/mail1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/mail1.0 213738 2010-10-12 18:20:38Z obrien $
 # Test that a non-interactive shell does not access $MAIL.
 
 goodfile=/var/empty/sh-test-goodfile
diff --git a/sh/tests/parameters/mail2.0 b/sh/tests/parameters/mail2.0
index 343c99d..74dc416 100644
--- a/sh/tests/parameters/mail2.0
+++ b/sh/tests/parameters/mail2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/mail2.0 213738 2010-10-12 18:20:38Z obrien $
 # Test that an interactive shell accesses $MAIL.
 
 goodfile=/var/empty/sh-test-goodfile
diff --git a/sh/tests/parameters/optind1.0 b/sh/tests/parameters/optind1.0
index 33e0288..30fc9d8 100644
--- a/sh/tests/parameters/optind1.0
+++ b/sh/tests/parameters/optind1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/optind1.0 227773 2011-11-20 21:48:50Z jilles $
 
 unset OPTIND && [ -z "$OPTIND" ]
diff --git a/sh/tests/parameters/optind2.0 b/sh/tests/parameters/optind2.0
index a7689f6..0837a17 100644
--- a/sh/tests/parameters/optind2.0
+++ b/sh/tests/parameters/optind2.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/optind2.0 259846 2013-12-24 22:38:24Z jilles $
 
 [ "$(OPTIND=42 ${SH} -c 'printf %s "$OPTIND"')" = 1 ]
diff --git a/sh/tests/parameters/positional1.0 b/sh/tests/parameters/positional1.0
index 67d1951..ef95be3 100644
--- a/sh/tests/parameters/positional1.0
+++ b/sh/tests/parameters/positional1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional1.0 222158 2011-05-21 14:52:26Z jilles $
 
 set -- a b c d e f g h i j
 [ "$1" = a ] || echo "error at line $LINENO"
diff --git a/sh/tests/parameters/positional2.0 b/sh/tests/parameters/positional2.0
index fcec2a4..ea29250 100644
--- a/sh/tests/parameters/positional2.0
+++ b/sh/tests/parameters/positional2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional2.0 228873 2011-12-25 13:24:48Z jilles $
 
 failures=''
 ok=''
diff --git a/sh/tests/parameters/positional3.0 b/sh/tests/parameters/positional3.0
index 1200469..d164ed9 100644
--- a/sh/tests/parameters/positional3.0
+++ b/sh/tests/parameters/positional3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional3.0 268436 2014-07-08 22:04:44Z jilles $
 
 r=$(${SH} -c 'echo ${01:+yes}${010:+yes}' '' a '' '' '' '' '' '' '' '' b)
 [ "$r" = yesyes ]
diff --git a/sh/tests/parameters/positional4.0 b/sh/tests/parameters/positional4.0
index c1c380c..48c2f01 100644
--- a/sh/tests/parameters/positional4.0
+++ b/sh/tests/parameters/positional4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional4.0 268568 2014-07-12 10:27:30Z jilles $
 
 set -- "x$0" 2 3 4 5 6 7 8 9 "y$0"
 [ "${01}.${010}" = "$1.${10}" ]
diff --git a/sh/tests/parameters/positional5.0 b/sh/tests/parameters/positional5.0
index eeaaba5..80ef805 100644
--- a/sh/tests/parameters/positional5.0
+++ b/sh/tests/parameters/positional5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional5.0 268576 2014-07-12 21:54:11Z jilles $
 
 i=1
 r=0
diff --git a/sh/tests/parameters/positional6.0 b/sh/tests/parameters/positional6.0
index 1410668..c1d5e4c 100644
--- a/sh/tests/parameters/positional6.0
+++ b/sh/tests/parameters/positional6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional6.0 273802 2014-10-28 22:14:31Z jilles $
 
 IFS=?
 set p r
diff --git a/sh/tests/parameters/positional7.0 b/sh/tests/parameters/positional7.0
index f170ad3..df36b6f 100644
--- a/sh/tests/parameters/positional7.0
+++ b/sh/tests/parameters/positional7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/positional7.0 273802 2014-10-28 22:14:31Z jilles $
 
 set -- / ''
 IFS=*
diff --git a/sh/tests/parameters/positional8.0 b/sh/tests/parameters/positional8.0
new file mode 100644
index 0000000..69717ce
--- /dev/null
+++ b/sh/tests/parameters/positional8.0
@@ -0,0 +1,31 @@
+# $FreeBSD: head/bin/sh/tests/parameters/positional8.0 291025 2015-11-18 21:09:03Z jilles $
+
+failures=''
+ok=''
+
+testcase() {
+	code="$1"
+	expected="$2"
+	oIFS="$IFS"
+	eval "$code"
+	IFS='|'
+	result="$#|$*"
+	IFS="$oIFS"
+	if [ "x$result" = "x$expected" ]; then
+		ok=x$ok
+	else
+		failures=x$failures
+		echo "For $code, expected $expected actual $result"
+	fi
+}
+
+testcase 'shift $#; set -- ""$*'		'1|'
+testcase 'shift $#; set -- $*""'		'1|'
+testcase 'shift $#; set -- ""$@'		'1|'
+testcase 'shift $#; set -- $@""'		'1|'
+testcase 'shift $#; set -- """$*"'		'1|'
+testcase 'shift $#; set -- "$*"""'		'1|'
+testcase 'shift $#; set -- """$@"'		'1|'
+testcase 'shift $#; set -- "$@"""'		'1|'
+
+test "x$failures" = x
diff --git a/sh/tests/parameters/positional9.0 b/sh/tests/parameters/positional9.0
new file mode 100644
index 0000000..c353e85
--- /dev/null
+++ b/sh/tests/parameters/positional9.0
@@ -0,0 +1,18 @@
+# $FreeBSD: head/bin/sh/tests/parameters/positional9.0 291903 2015-12-06 14:09:31Z jilles $
+# Although POSIX leaves the result of expanding ${#@} and ${#*} unspecified,
+# make sure it is at least numeric.
+
+set -- bb cc ddd
+set -f
+lengths=${#*}${#@}"${#*}${#@}"$(echo ${#*}${#@}"${#*}${#@}")
+IFS=
+lengths=$lengths${#*}${#@}"${#*}${#@}"$(echo ${#*}${#@}"${#*}${#@}")
+case $lengths in
+*[!0-9]*)
+	printf 'bad: %s\n' "$lengths"
+	exit 3 ;;
+????????????????*) ;;
+*)
+	printf 'too short: %s\n' "$lengths"
+	exit 3 ;;
+esac
diff --git a/sh/tests/parameters/pwd1.0 b/sh/tests/parameters/pwd1.0
index 0099379..8393ef6 100644
--- a/sh/tests/parameters/pwd1.0
+++ b/sh/tests/parameters/pwd1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/pwd1.0 213738 2010-10-12 18:20:38Z obrien $
 # Check that bogus PWD values are not accepted from the environment.
 
 cd / || exit 3
diff --git a/sh/tests/parameters/pwd2.0 b/sh/tests/parameters/pwd2.0
index 2297f8b..d0cecf5 100644
--- a/sh/tests/parameters/pwd2.0
+++ b/sh/tests/parameters/pwd2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parameters/pwd2.0 213738 2010-10-12 18:20:38Z obrien $
 # Check that PWD is exported and accepted from the environment.
 set -e
 
diff --git a/sh/tests/parser/Makefile b/sh/tests/parser/Makefile
index 3c9e62c..4a9c724 100644
--- a/sh/tests/parser/Makefile
+++ b/sh/tests/parser/Makefile
@@ -1,78 +1,85 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/Makefile 299094 2016-05-04 23:20:53Z ngie $
+
+PACKAGE=	tests
 
 TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		alias1.0
-FILES+=		alias2.0
-FILES+=		alias3.0
-FILES+=		alias4.0
-FILES+=		alias5.0
-FILES+=		alias6.0
-FILES+=		alias7.0
-FILES+=		alias8.0
-FILES+=		alias9.0
-FILES+=		alias10.0
-FILES+=		alias11.0
-FILES+=		alias12.0
-FILES+=		alias13.0
-FILES+=		alias14.0
-FILES+=		alias15.0 alias15.0.stdout
-FILES+=		and-pipe-not.0
-FILES+=		case1.0
-FILES+=		case2.0
-FILES+=		dollar-quote1.0
-FILES+=		dollar-quote2.0
-FILES+=		dollar-quote3.0
-FILES+=		dollar-quote4.0
-FILES+=		dollar-quote5.0
-FILES+=		dollar-quote6.0
-FILES+=		dollar-quote7.0
-FILES+=		dollar-quote8.0
-FILES+=		dollar-quote9.0
-FILES+=		dollar-quote10.0
-FILES+=		dollar-quote11.0
-FILES+=		empty-braces1.0
-FILES+=		empty-cmd1.0
-FILES+=		for1.0
-FILES+=		for2.0
-FILES+=		func1.0
-FILES+=		func2.0
-FILES+=		func3.0
-FILES+=		heredoc1.0
-FILES+=		heredoc2.0
-FILES+=		heredoc3.0
-FILES+=		heredoc4.0
-FILES+=		heredoc5.0
-FILES+=		heredoc6.0
-FILES+=		heredoc7.0
-FILES+=		heredoc8.0
-FILES+=		heredoc9.0
-FILES+=		heredoc10.0
-FILES+=		heredoc11.0
-FILES+=		heredoc12.0
-FILES+=		line-cont1.0
-FILES+=		line-cont2.0
-FILES+=		line-cont3.0
-FILES+=		line-cont4.0
-FILES+=		line-cont5.0
-FILES+=		line-cont6.0
-FILES+=		line-cont7.0
-FILES+=		line-cont8.0
-FILES+=		line-cont9.0
-FILES+=		line-cont10.0
-FILES+=		line-cont11.0
-FILES+=		no-space1.0
-FILES+=		no-space2.0
-FILES+=		only-redir1.0
-FILES+=		only-redir2.0
-FILES+=		only-redir3.0
-FILES+=		only-redir4.0
-FILES+=		pipe-not1.0
-FILES+=		var-assign1.0
+${PACKAGE}FILES+=	alias1.0
+${PACKAGE}FILES+=	alias2.0
+${PACKAGE}FILES+=	alias3.0
+${PACKAGE}FILES+=	alias4.0
+${PACKAGE}FILES+=	alias5.0
+${PACKAGE}FILES+=	alias6.0
+${PACKAGE}FILES+=	alias7.0
+${PACKAGE}FILES+=	alias8.0
+${PACKAGE}FILES+=	alias9.0
+${PACKAGE}FILES+=	alias10.0
+${PACKAGE}FILES+=	alias11.0
+${PACKAGE}FILES+=	alias12.0
+${PACKAGE}FILES+=	alias13.0
+${PACKAGE}FILES+=	alias14.0
+${PACKAGE}FILES+=	alias15.0 alias15.0.stdout
+${PACKAGE}FILES+=	and-pipe-not.0
+${PACKAGE}FILES+=	case1.0
+${PACKAGE}FILES+=	case2.0
+${PACKAGE}FILES+=	comment1.0
+${PACKAGE}FILES+=	comment2.42
+${PACKAGE}FILES+=	dollar-quote1.0
+${PACKAGE}FILES+=	dollar-quote2.0
+${PACKAGE}FILES+=	dollar-quote3.0
+${PACKAGE}FILES+=	dollar-quote4.0
+${PACKAGE}FILES+=	dollar-quote5.0
+${PACKAGE}FILES+=	dollar-quote6.0
+${PACKAGE}FILES+=	dollar-quote7.0
+${PACKAGE}FILES+=	dollar-quote8.0
+${PACKAGE}FILES+=	dollar-quote9.0
+${PACKAGE}FILES+=	dollar-quote10.0
+${PACKAGE}FILES+=	dollar-quote11.0
+${PACKAGE}FILES+=	dollar-quote12.0
+${PACKAGE}FILES+=	dollar-quote13.0
+${PACKAGE}FILES+=	empty-braces1.0
+${PACKAGE}FILES+=	empty-cmd1.0
+${PACKAGE}FILES+=	for1.0
+${PACKAGE}FILES+=	for2.0
+${PACKAGE}FILES+=	func1.0
+${PACKAGE}FILES+=	func2.0
+${PACKAGE}FILES+=	func3.0
+${PACKAGE}FILES+=	heredoc1.0
+${PACKAGE}FILES+=	heredoc2.0
+${PACKAGE}FILES+=	heredoc3.0
+${PACKAGE}FILES+=	heredoc4.0
+${PACKAGE}FILES+=	heredoc5.0
+${PACKAGE}FILES+=	heredoc6.0
+${PACKAGE}FILES+=	heredoc7.0
+${PACKAGE}FILES+=	heredoc8.0
+${PACKAGE}FILES+=	heredoc9.0
+${PACKAGE}FILES+=	heredoc10.0
+${PACKAGE}FILES+=	heredoc11.0
+${PACKAGE}FILES+=	heredoc12.0
+${PACKAGE}FILES+=	heredoc13.0
+${PACKAGE}FILES+=	line-cont1.0
+${PACKAGE}FILES+=	line-cont2.0
+${PACKAGE}FILES+=	line-cont3.0
+${PACKAGE}FILES+=	line-cont4.0
+${PACKAGE}FILES+=	line-cont5.0
+${PACKAGE}FILES+=	line-cont6.0
+${PACKAGE}FILES+=	line-cont7.0
+${PACKAGE}FILES+=	line-cont8.0
+${PACKAGE}FILES+=	line-cont9.0
+${PACKAGE}FILES+=	line-cont10.0
+${PACKAGE}FILES+=	line-cont11.0
+${PACKAGE}FILES+=	no-space1.0
+${PACKAGE}FILES+=	no-space2.0
+${PACKAGE}FILES+=	nul1.0
+${PACKAGE}FILES+=	only-redir1.0
+${PACKAGE}FILES+=	only-redir2.0
+${PACKAGE}FILES+=	only-redir3.0
+${PACKAGE}FILES+=	only-redir4.0
+${PACKAGE}FILES+=	pipe-not1.0
+${PACKAGE}FILES+=	set-v1.0 set-v1.0.stderr
+${PACKAGE}FILES+=	var-assign1.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/parser/Makefile.depend b/sh/tests/parser/Makefile.depend
new file mode 100644
index 0000000..af589a4
--- /dev/null
+++ b/sh/tests/parser/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/parser/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/parser/alias1.0 b/sh/tests/parser/alias1.0
index 75dd9ab..9b67211 100644
--- a/sh/tests/parser/alias1.0
+++ b/sh/tests/parser/alias1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias1.0 214280 2010-10-24 16:55:17Z jilles $
 
 alias alias0=exit
 eval 'alias0 0'
diff --git a/sh/tests/parser/alias10.0 b/sh/tests/parser/alias10.0
index 30d99f4..b8684f4 100644
--- a/sh/tests/parser/alias10.0
+++ b/sh/tests/parser/alias10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias10.0 243252 2012-11-18 23:15:22Z jilles $
 
 # This test may start consuming memory indefinitely if it fails.
 ulimit -t 5 2>/dev/null
diff --git a/sh/tests/parser/alias11.0 b/sh/tests/parser/alias11.0
index 522264f..10fd827 100644
--- a/sh/tests/parser/alias11.0
+++ b/sh/tests/parser/alias11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias11.0 261141 2014-01-24 23:00:35Z jilles $
 
 alias alias0=alias1
 alias alias1=exit
diff --git a/sh/tests/parser/alias12.0 b/sh/tests/parser/alias12.0
index 2e43791..52cc4b0 100644
--- a/sh/tests/parser/alias12.0
+++ b/sh/tests/parser/alias12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias12.0 261160 2014-01-25 14:59:08Z jilles $
 
 unalias -a
 alias alias0=command
diff --git a/sh/tests/parser/alias13.0 b/sh/tests/parser/alias13.0
index 53b949d..9f45067 100644
--- a/sh/tests/parser/alias13.0
+++ b/sh/tests/parser/alias13.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias13.0 261160 2014-01-25 14:59:08Z jilles $
 
 unalias -a
 alias command=command
diff --git a/sh/tests/parser/alias14.0 b/sh/tests/parser/alias14.0
index 1b92fc0..2d1bc51 100644
--- a/sh/tests/parser/alias14.0
+++ b/sh/tests/parser/alias14.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias14.0 261192 2014-01-26 21:19:33Z jilles $
 
 alias command='command '
 alias alias0=exit
diff --git a/sh/tests/parser/alias15.0 b/sh/tests/parser/alias15.0
index f0fbadb..c2e6117 100644
--- a/sh/tests/parser/alias15.0
+++ b/sh/tests/parser/alias15.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias15.0 261192 2014-01-26 21:19:33Z jilles $
 
 f_echoanddo() {
 	printf '%s\n' "$*"
diff --git a/sh/tests/parser/alias2.0 b/sh/tests/parser/alias2.0
index ae99b8a..f412756 100644
--- a/sh/tests/parser/alias2.0
+++ b/sh/tests/parser/alias2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias2.0 214280 2010-10-24 16:55:17Z jilles $
 
 alias alias0=exit
 x=alias0
diff --git a/sh/tests/parser/alias3.0 b/sh/tests/parser/alias3.0
index e0721e2..97aac19 100644
--- a/sh/tests/parser/alias3.0
+++ b/sh/tests/parser/alias3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias3.0 214709 2010-11-02 23:44:29Z jilles $
 
 alias alias0=exit
 x=alias0
diff --git a/sh/tests/parser/alias4.0 b/sh/tests/parser/alias4.0
index 19332ed..4c82c6c 100644
--- a/sh/tests/parser/alias4.0
+++ b/sh/tests/parser/alias4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias4.0 222165 2011-05-21 22:03:06Z jilles $
 
 alias alias0=exit
 eval 'x=1 alias0 0'
diff --git a/sh/tests/parser/alias5.0 b/sh/tests/parser/alias5.0
index 3d0205f..c649562 100644
--- a/sh/tests/parser/alias5.0
+++ b/sh/tests/parser/alias5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias5.0 222165 2011-05-21 22:03:06Z jilles $
 
 alias alias0=exit
 eval '</dev/null alias0 0'
diff --git a/sh/tests/parser/alias6.0 b/sh/tests/parser/alias6.0
index c723d08..86e1bfb 100644
--- a/sh/tests/parser/alias6.0
+++ b/sh/tests/parser/alias6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias6.0 224104 2011-07-16 16:14:14Z jilles $
 
 alias alias0='| cat >/dev/null'
 
diff --git a/sh/tests/parser/alias7.0 b/sh/tests/parser/alias7.0
index b26f0dd..a5b9077 100644
--- a/sh/tests/parser/alias7.0
+++ b/sh/tests/parser/alias7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias7.0 240825 2012-09-22 12:52:41Z jilles $
 
 alias echo='echo a'
 [ "`eval echo b`" = "a b" ]
diff --git a/sh/tests/parser/alias8.0 b/sh/tests/parser/alias8.0
index 7fc2f15..f22dfd4 100644
--- a/sh/tests/parser/alias8.0
+++ b/sh/tests/parser/alias8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias8.0 240825 2012-09-22 12:52:41Z jilles $
 
 alias echo='echo'
 [ "`eval echo b`" = b ]
diff --git a/sh/tests/parser/alias9.0 b/sh/tests/parser/alias9.0
index 6bd8808..bbcb4ce 100644
--- a/sh/tests/parser/alias9.0
+++ b/sh/tests/parser/alias9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/alias9.0 242721 2012-11-07 23:15:36Z jilles $
 
 alias alias0=:
 alias alias0=exit
diff --git a/sh/tests/parser/and-pipe-not.0 b/sh/tests/parser/and-pipe-not.0
index 35b125c..fffb1d4 100644
--- a/sh/tests/parser/and-pipe-not.0
+++ b/sh/tests/parser/and-pipe-not.0
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/and-pipe-not.0 191010 2009-04-13 19:12:28Z stefanf $
 true && ! true | false
diff --git a/sh/tests/parser/case1.0 b/sh/tests/parser/case1.0
index 49b4c45..d146399 100644
--- a/sh/tests/parser/case1.0
+++ b/sh/tests/parser/case1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/case1.0 207824 2010-05-09 17:10:50Z jilles $
 
 keywords='if then else elif fi while until for do done { } case esac ! in'
 
diff --git a/sh/tests/parser/case2.0 b/sh/tests/parser/case2.0
index 14610e4..df5a319 100644
--- a/sh/tests/parser/case2.0
+++ b/sh/tests/parser/case2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/case2.0 207824 2010-05-09 17:10:50Z jilles $
 
 # Pretty much only ash derivatives can parse all of this.
 
diff --git a/sh/tests/parser/comment1.0 b/sh/tests/parser/comment1.0
new file mode 100644
index 0000000..bdf9c3b
--- /dev/null
+++ b/sh/tests/parser/comment1.0
@@ -0,0 +1,3 @@
+# $FreeBSD: head/bin/sh/tests/parser/comment1.0 295818 2016-02-19 16:56:07Z jilles $
+
+${SH} -c '#'
diff --git a/sh/tests/parser/comment2.42 b/sh/tests/parser/comment2.42
new file mode 100644
index 0000000..7e623c9
--- /dev/null
+++ b/sh/tests/parser/comment2.42
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/parser/comment2.42 295818 2016-02-19 16:56:07Z jilles $
+
+${SH} -c '#
+exit 42'
diff --git a/sh/tests/parser/dollar-quote10.0 b/sh/tests/parser/dollar-quote10.0
index ad166da..745d3aa 100644
--- a/sh/tests/parser/dollar-quote10.0
+++ b/sh/tests/parser/dollar-quote10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote10.0 221669 2011-05-08 17:40:10Z jilles $
 
 # a umlaut
 s=$(printf '\303\244')
diff --git a/sh/tests/parser/dollar-quote11.0 b/sh/tests/parser/dollar-quote11.0
index 2e872ab..b9db067 100644
--- a/sh/tests/parser/dollar-quote11.0
+++ b/sh/tests/parser/dollar-quote11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote11.0 221669 2011-05-08 17:40:10Z jilles $
 
 # some sort of 't' outside BMP
 s=$s$(printf '\360\235\225\245')
diff --git a/sh/tests/parser/dollar-quote12.0 b/sh/tests/parser/dollar-quote12.0
new file mode 100644
index 0000000..bb06e3c
--- /dev/null
+++ b/sh/tests/parser/dollar-quote12.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote12.0 286971 2015-08-20 21:31:36Z jilles $
+
+# \u without any digits at all remains invalid.
+# Our choice is a parse error.
+
+v=$( (eval ": \$'\u'") 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/sh/tests/parser/dollar-quote13.0 b/sh/tests/parser/dollar-quote13.0
new file mode 100644
index 0000000..fe31d9d
--- /dev/null
+++ b/sh/tests/parser/dollar-quote13.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote13.0 286973 2015-08-20 22:05:55Z jilles $
+
+# This Unicode escape sequence that has never been in range should either
+# fail to expand or expand to a fallback.
+
+c=$(eval printf %s \$\'\\Uffffff41\' 2>/dev/null)
+r=$(($? != 0))
+[ "$r.$c" = '1.' ] || [ "$r.$c" = '0.?' ] || [ "$r.$c" = $'0.\u2222' ]
diff --git a/sh/tests/parser/empty-braces1.0 b/sh/tests/parser/empty-braces1.0
index 5ab443c..4aac806 100644
--- a/sh/tests/parser/empty-braces1.0
+++ b/sh/tests/parser/empty-braces1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/empty-braces1.0 245382 2013-01-13 19:26:33Z jilles $
 
 # Unfortunately, some scripts depend on the extension of allowing an empty
 # pair of braces.
diff --git a/sh/tests/parser/empty-cmd1.0 b/sh/tests/parser/empty-cmd1.0
index f8b01e9..60aaa00 100644
--- a/sh/tests/parser/empty-cmd1.0
+++ b/sh/tests/parser/empty-cmd1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/empty-cmd1.0 254843 2013-08-25 10:57:48Z jilles $
 
 ! (eval ': || f()') 2>/dev/null
diff --git a/sh/tests/parser/for1.0 b/sh/tests/parser/for1.0
index eb7c881..d863f0a 100644
--- a/sh/tests/parser/for1.0
+++ b/sh/tests/parser/for1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/for1.0 218889 2011-02-20 14:18:58Z jilles $
 
 nl='
 '
diff --git a/sh/tests/parser/for2.0 b/sh/tests/parser/for2.0
index 54ebfc3..8ed92dc 100644
--- a/sh/tests/parser/for2.0
+++ b/sh/tests/parser/for2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/for2.0 218889 2011-02-20 14:18:58Z jilles $
 
 # Common extensions to the 'for' syntax.
 
diff --git a/sh/tests/parser/func1.0 b/sh/tests/parser/func1.0
index 4e887b2..4e82da4 100644
--- a/sh/tests/parser/func1.0
+++ b/sh/tests/parser/func1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/func1.0 214291 2010-10-24 20:45:13Z jilles $
 # POSIX does not require these bytes to work in function names,
 # but making them all work seems a good goal.
 
diff --git a/sh/tests/parser/func2.0 b/sh/tests/parser/func2.0
index 5fd4dda..5b86522 100644
--- a/sh/tests/parser/func2.0
+++ b/sh/tests/parser/func2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/func2.0 222512 2011-05-30 21:49:59Z jilles $
 
 f() { return 42; }
 f() { return 3; } &
diff --git a/sh/tests/parser/func3.0 b/sh/tests/parser/func3.0
index dcac732..c4f4922 100644
--- a/sh/tests/parser/func3.0
+++ b/sh/tests/parser/func3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/func3.0 222512 2011-05-30 21:49:59Z jilles $
 
 name=/var/empty/nosuch
 f() { true; } <$name
diff --git a/sh/tests/parser/heredoc1.0 b/sh/tests/parser/heredoc1.0
index 5ce3897..4020249 100644
--- a/sh/tests/parser/heredoc1.0
+++ b/sh/tests/parser/heredoc1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc1.0 204836 2010-03-07 15:08:42Z jilles $
 
 failures=0
 
diff --git a/sh/tests/parser/heredoc10.0 b/sh/tests/parser/heredoc10.0
index 27369a0..f5133b9 100644
--- a/sh/tests/parser/heredoc10.0
+++ b/sh/tests/parser/heredoc10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc10.0 221887 2011-05-14 14:19:30Z jilles $
 
 # It may be argued that
 #   x=$(cat <<EOF
diff --git a/sh/tests/parser/heredoc11.0 b/sh/tests/parser/heredoc11.0
index 5839e46..3e74aea 100644
--- a/sh/tests/parser/heredoc11.0
+++ b/sh/tests/parser/heredoc11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc11.0 222134 2011-05-20 16:03:36Z jilles $
 
 failures=''
 
diff --git a/sh/tests/parser/heredoc12.0 b/sh/tests/parser/heredoc12.0
index 9648384..644cae1 100644
--- a/sh/tests/parser/heredoc12.0
+++ b/sh/tests/parser/heredoc12.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc12.0 271593 2014-09-14 16:46:30Z jilles $
 
 failures=0
 
diff --git a/sh/tests/parser/heredoc13.0 b/sh/tests/parser/heredoc13.0
new file mode 100644
index 0000000..4eb45e0
--- /dev/null
+++ b/sh/tests/parser/heredoc13.0
@@ -0,0 +1,21 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc13.0 287408 2015-09-02 19:49:55Z jilles $
+
+failures=0
+
+check() {
+	if ! eval "[ $* ]"; then
+		echo "Failed: $*"
+		: $((failures += 1))
+	fi
+}
+
+check '"$(cat <<""
+
+echo yes)" = "yes"'
+
+check '"$(cat <<""
+yes
+
+)" = "yes"'
+
+exit $((failures != 0))
diff --git a/sh/tests/parser/heredoc2.0 b/sh/tests/parser/heredoc2.0
index 4bb85ad..f07f5d4 100644
--- a/sh/tests/parser/heredoc2.0
+++ b/sh/tests/parser/heredoc2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc2.0 211405 2010-08-16 21:14:49Z jilles $
 
 failures=0
 
diff --git a/sh/tests/parser/heredoc3.0 b/sh/tests/parser/heredoc3.0
index b250272..15c0a1c 100644
--- a/sh/tests/parser/heredoc3.0
+++ b/sh/tests/parser/heredoc3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc3.0 207824 2010-05-09 17:10:50Z jilles $
 
 # This may be expected to work, but pretty much only ash derivatives allow it.
 
diff --git a/sh/tests/parser/heredoc4.0 b/sh/tests/parser/heredoc4.0
index fa3af5f..a544354 100644
--- a/sh/tests/parser/heredoc4.0
+++ b/sh/tests/parser/heredoc4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc4.0 208655 2010-05-30 14:11:27Z jilles $
 
 failures=0
 
diff --git a/sh/tests/parser/heredoc5.0 b/sh/tests/parser/heredoc5.0
index 84b0eb2..0bcc617 100644
--- a/sh/tests/parser/heredoc5.0
+++ b/sh/tests/parser/heredoc5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc5.0 208655 2010-05-30 14:11:27Z jilles $
 
 failures=0
 
diff --git a/sh/tests/parser/heredoc6.0 b/sh/tests/parser/heredoc6.0
index 3a634de..003f548 100644
--- a/sh/tests/parser/heredoc6.0
+++ b/sh/tests/parser/heredoc6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc6.0 208656 2010-05-30 14:20:32Z jilles $
 
 r=
 ! command eval ": <<EOF; )" 2>/dev/null; command eval : hi \${r:=0}
diff --git a/sh/tests/parser/heredoc7.0 b/sh/tests/parser/heredoc7.0
index a150106..28d867c 100644
--- a/sh/tests/parser/heredoc7.0
+++ b/sh/tests/parser/heredoc7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc7.0 210488 2010-07-25 22:25:52Z jilles $
 
 # Some of these created malformed parse trees with null pointers for here
 # documents, causing the here document writing process to segfault.
diff --git a/sh/tests/parser/heredoc8.0 b/sh/tests/parser/heredoc8.0
index 598358a..482c060 100644
--- a/sh/tests/parser/heredoc8.0
+++ b/sh/tests/parser/heredoc8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc8.0 211405 2010-08-16 21:14:49Z jilles $
 
 failures=0
 
diff --git a/sh/tests/parser/heredoc9.0 b/sh/tests/parser/heredoc9.0
index 125a542..bb4a04c 100644
--- a/sh/tests/parser/heredoc9.0
+++ b/sh/tests/parser/heredoc9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/heredoc9.0 221887 2011-05-14 14:19:30Z jilles $
 
 # It may be argued that
 #   x=$(cat <<EOF
diff --git a/sh/tests/parser/line-cont1.0 b/sh/tests/parser/line-cont1.0
index 7ef5eba..717c2c2 100644
--- a/sh/tests/parser/line-cont1.0
+++ b/sh/tests/parser/line-cont1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont1.0 273243 2014-10-17 21:52:57Z jilles $
 
 i\
 f
diff --git a/sh/tests/parser/line-cont10.0 b/sh/tests/parser/line-cont10.0
index 1e74108..dbb064b 100644
--- a/sh/tests/parser/line-cont10.0
+++ b/sh/tests/parser/line-cont10.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont10.0 273276 2014-10-19 11:59:15Z jilles $
 
 v=XaaaXbbbX
 [ "${v\
diff --git a/sh/tests/parser/line-cont11.0 b/sh/tests/parser/line-cont11.0
index 22e4975..f398a98 100644
--- a/sh/tests/parser/line-cont11.0
+++ b/sh/tests/parser/line-cont11.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont11.0 273276 2014-10-19 11:59:15Z jilles $
 
 T=$(mktemp "${TMPDIR:-/tmp}/sh-test.XXXXXXXX") || exit
 trap 'rm -f -- "$T"' 0
diff --git a/sh/tests/parser/line-cont2.0 b/sh/tests/parser/line-cont2.0
index 9a293fa..83928cf 100644
--- a/sh/tests/parser/line-cont2.0
+++ b/sh/tests/parser/line-cont2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont2.0 273243 2014-10-17 21:52:57Z jilles $
 
 [ "a\
 b" = ab ]
diff --git a/sh/tests/parser/line-cont3.0 b/sh/tests/parser/line-cont3.0
index 09d3aa8..cc2af7b 100644
--- a/sh/tests/parser/line-cont3.0
+++ b/sh/tests/parser/line-cont3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont3.0 273243 2014-10-17 21:52:57Z jilles $
 
 v=`printf %s 'a\
 b'`
diff --git a/sh/tests/parser/line-cont4.0 b/sh/tests/parser/line-cont4.0
index 5803276..7d59c19 100644
--- a/sh/tests/parser/line-cont4.0
+++ b/sh/tests/parser/line-cont4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont4.0 273276 2014-10-19 11:59:15Z jilles $
 
 v=abcd
 [ "$\
diff --git a/sh/tests/parser/line-cont5.0 b/sh/tests/parser/line-cont5.0
index a7aa026..23a4d94 100644
--- a/sh/tests/parser/line-cont5.0
+++ b/sh/tests/parser/line-cont5.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont5.0 273276 2014-10-19 11:59:15Z jilles $
 
 bad=1
 case x in
diff --git a/sh/tests/parser/line-cont6.0 b/sh/tests/parser/line-cont6.0
index b12125b..66838e1 100644
--- a/sh/tests/parser/line-cont6.0
+++ b/sh/tests/parser/line-cont6.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont6.0 273276 2014-10-19 11:59:15Z jilles $
 
 v0\
 =abc
diff --git a/sh/tests/parser/line-cont7.0 b/sh/tests/parser/line-cont7.0
index 27f8aec..6c48642 100644
--- a/sh/tests/parser/line-cont7.0
+++ b/sh/tests/parser/line-cont7.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont7.0 273276 2014-10-19 11:59:15Z jilles $
 
 [ "$(\
 (
diff --git a/sh/tests/parser/line-cont8.0 b/sh/tests/parser/line-cont8.0
index 8866776..8fc84bb 100644
--- a/sh/tests/parser/line-cont8.0
+++ b/sh/tests/parser/line-cont8.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont8.0 273276 2014-10-19 11:59:15Z jilles $
 
 set -- a b c d e f g h i j
 [ "${1\
diff --git a/sh/tests/parser/line-cont9.0 b/sh/tests/parser/line-cont9.0
index 4e73c8f..9618ae2 100644
--- a/sh/tests/parser/line-cont9.0
+++ b/sh/tests/parser/line-cont9.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/line-cont9.0 273276 2014-10-19 11:59:15Z jilles $
 
 [ "${$\
 :\
diff --git a/sh/tests/parser/no-space1.0 b/sh/tests/parser/no-space1.0
index 6df9f63..5b15bfe 100644
--- a/sh/tests/parser/no-space1.0
+++ b/sh/tests/parser/no-space1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/no-space1.0 218891 2011-02-20 17:28:58Z jilles $
 
 # These are ugly but are required to work.
 
diff --git a/sh/tests/parser/no-space2.0 b/sh/tests/parser/no-space2.0
index 4e8447b..0f63e6e 100644
--- a/sh/tests/parser/no-space2.0
+++ b/sh/tests/parser/no-space2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/no-space2.0 218891 2011-02-20 17:28:58Z jilles $
 
 # This conflicts with ksh extended patterns but occurs in the wild.
 
diff --git a/sh/tests/parser/nul1.0 b/sh/tests/parser/nul1.0
new file mode 100644
index 0000000..bb5442e
--- /dev/null
+++ b/sh/tests/parser/nul1.0
@@ -0,0 +1,12 @@
+# $FreeBSD: head/bin/sh/tests/parser/nul1.0 295825 2016-02-19 21:53:12Z jilles $
+# Although POSIX does not specify the effect of NUL bytes in scripts,
+# we ignore them.
+
+{
+	printf 'v=%03000d\0%02000d' 7 2
+	dd if=/dev/zero bs=1000 count=1 status=none
+	printf '1 w=%03000d%02000d1\0\n' 7 2
+	printf '\0l\0v\0=\0$\0{\0#\0v\0}\n'
+	printf '\0l\0w\0=\0\0$\0{\0#\0w}\0\0\0\n'
+	printf '[ "$lv.$lw.$v" = "5001.5001.$w" ]\n'
+} | ${SH}
diff --git a/sh/tests/parser/only-redir1.0 b/sh/tests/parser/only-redir1.0
index 46076c8..7aedde7 100644
--- a/sh/tests/parser/only-redir1.0
+++ b/sh/tests/parser/only-redir1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/only-redir1.0 210221 2010-07-18 12:45:31Z jilles $
 </dev/null &
 wait $!
diff --git a/sh/tests/parser/only-redir2.0 b/sh/tests/parser/only-redir2.0
index b9e9501..b55be16 100644
--- a/sh/tests/parser/only-redir2.0
+++ b/sh/tests/parser/only-redir2.0
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/only-redir2.0 254335 2013-08-14 19:34:13Z jilles $
 </dev/null | :
diff --git a/sh/tests/parser/only-redir3.0 b/sh/tests/parser/only-redir3.0
index 128a483..f51617b 100644
--- a/sh/tests/parser/only-redir3.0
+++ b/sh/tests/parser/only-redir3.0
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/only-redir3.0 254335 2013-08-14 19:34:13Z jilles $
 case x in x) </dev/null ;; esac
diff --git a/sh/tests/parser/only-redir4.0 b/sh/tests/parser/only-redir4.0
index d804e12..a3ce893 100644
--- a/sh/tests/parser/only-redir4.0
+++ b/sh/tests/parser/only-redir4.0
@@ -1,2 +1,2 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/only-redir4.0 254335 2013-08-14 19:34:13Z jilles $
 case x in x) </dev/null ;& esac
diff --git a/sh/tests/parser/pipe-not1.0 b/sh/tests/parser/pipe-not1.0
index 9842ff0..421e235 100644
--- a/sh/tests/parser/pipe-not1.0
+++ b/sh/tests/parser/pipe-not1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/pipe-not1.0 214281 2010-10-24 17:06:49Z jilles $
 
 : | ! : | false
diff --git a/sh/tests/parser/set-v1.0 b/sh/tests/parser/set-v1.0
new file mode 100644
index 0000000..c5ed944
--- /dev/null
+++ b/sh/tests/parser/set-v1.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/set-v1.0 295937 2016-02-23 22:44:01Z jilles $
+
+${SH} <<\EOF
+echo one >&2
+set -v
+echo two >&2
+echo three >&2
+EOF
diff --git a/sh/tests/parser/set-v1.0.stderr b/sh/tests/parser/set-v1.0.stderr
new file mode 100644
index 0000000..d904fa5
--- /dev/null
+++ b/sh/tests/parser/set-v1.0.stderr
@@ -0,0 +1,5 @@
+one
+echo two >&2
+two
+echo three >&2
+three
diff --git a/sh/tests/parser/var-assign1.0 b/sh/tests/parser/var-assign1.0
index 1fd3b26..4949bfd 100644
--- a/sh/tests/parser/var-assign1.0
+++ b/sh/tests/parser/var-assign1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/parser/var-assign1.0 257920 2013-11-10 18:46:59Z jilles $
 # In a variable assignment, both the name and the equals sign must be entirely
 # unquoted. Therefore, there is only one assignment below; the other words
 # containing equals signs are command words.
diff --git a/sh/tests/set-e/Makefile b/sh/tests/set-e/Makefile
index f733b60..2f13991 100644
--- a/sh/tests/set-e/Makefile
+++ b/sh/tests/set-e/Makefile
@@ -1,46 +1,46 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/Makefile 299094 2016-05-04 23:20:53Z ngie $
+
+PACKAGE=	tests
 
 TESTSDIR=	${TESTSBASE}/bin/sh/${.CURDIR:T}
 
 .PATH: ${.CURDIR:H}
 ATF_TESTS_SH=	functional_test
 
-FILESDIR=	${TESTSDIR}
-
-FILES=		and1.0
-FILES+=		and2.1
-FILES+=		and3.0
-FILES+=		and4.0
-FILES+=		background1.0
-FILES+=		cmd1.0
-FILES+=		cmd2.1
-FILES+=		elif1.0
-FILES+=		elif2.0
-FILES+=		eval1.0
-FILES+=		eval2.1
-FILES+=		for1.0
-FILES+=		func1.0
-FILES+=		func2.1
-FILES+=		if1.0
-FILES+=		if2.0
-FILES+=		if3.0
-FILES+=		not1.0
-FILES+=		not2.0
-FILES+=		or1.0
-FILES+=		or2.0
-FILES+=		or3.1
-FILES+=		pipe1.1
-FILES+=		pipe2.0
-FILES+=		return1.0
-FILES+=		semi1.1
-FILES+=		semi2.1
-FILES+=		subshell1.0
-FILES+=		subshell2.1
-FILES+=		until1.0
-FILES+=		until2.0
-FILES+=		until3.0
-FILES+=		while1.0
-FILES+=		while2.0
-FILES+=		while3.0
+${PACKAGE}FILES+=	and1.0
+${PACKAGE}FILES+=	and2.1
+${PACKAGE}FILES+=	and3.0
+${PACKAGE}FILES+=	and4.0
+${PACKAGE}FILES+=	background1.0
+${PACKAGE}FILES+=	cmd1.0
+${PACKAGE}FILES+=	cmd2.1
+${PACKAGE}FILES+=	elif1.0
+${PACKAGE}FILES+=	elif2.0
+${PACKAGE}FILES+=	eval1.0
+${PACKAGE}FILES+=	eval2.1
+${PACKAGE}FILES+=	for1.0
+${PACKAGE}FILES+=	func1.0
+${PACKAGE}FILES+=	func2.1
+${PACKAGE}FILES+=	if1.0
+${PACKAGE}FILES+=	if2.0
+${PACKAGE}FILES+=	if3.0
+${PACKAGE}FILES+=	not1.0
+${PACKAGE}FILES+=	not2.0
+${PACKAGE}FILES+=	or1.0
+${PACKAGE}FILES+=	or2.0
+${PACKAGE}FILES+=	or3.1
+${PACKAGE}FILES+=	pipe1.1
+${PACKAGE}FILES+=	pipe2.0
+${PACKAGE}FILES+=	return1.0
+${PACKAGE}FILES+=	semi1.1
+${PACKAGE}FILES+=	semi2.1
+${PACKAGE}FILES+=	subshell1.0
+${PACKAGE}FILES+=	subshell2.1
+${PACKAGE}FILES+=	until1.0
+${PACKAGE}FILES+=	until2.0
+${PACKAGE}FILES+=	until3.0
+${PACKAGE}FILES+=	while1.0
+${PACKAGE}FILES+=	while2.0
+${PACKAGE}FILES+=	while3.0
 
 .include <bsd.test.mk>
diff --git a/sh/tests/set-e/Makefile.depend b/sh/tests/set-e/Makefile.depend
new file mode 100644
index 0000000..ea8dbbe
--- /dev/null
+++ b/sh/tests/set-e/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/set-e/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sh/tests/set-e/and1.0 b/sh/tests/set-e/and1.0
index 607b7c3..4518124 100644
--- a/sh/tests/set-e/and1.0
+++ b/sh/tests/set-e/and1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/and1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 true && true
diff --git a/sh/tests/set-e/and2.1 b/sh/tests/set-e/and2.1
index 78e203a..2067f10 100644
--- a/sh/tests/set-e/and2.1
+++ b/sh/tests/set-e/and2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/and2.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 true && false
 exit 0
diff --git a/sh/tests/set-e/and3.0 b/sh/tests/set-e/and3.0
index 9fafb1c..59dccce 100644
--- a/sh/tests/set-e/and3.0
+++ b/sh/tests/set-e/and3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/and3.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false && true
 exit 0
diff --git a/sh/tests/set-e/and4.0 b/sh/tests/set-e/and4.0
index 25d0e61..fd1cc72 100644
--- a/sh/tests/set-e/and4.0
+++ b/sh/tests/set-e/and4.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/and4.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false && false
 exit 0
diff --git a/sh/tests/set-e/background1.0 b/sh/tests/set-e/background1.0
index 21577f4..e31b7a3 100644
--- a/sh/tests/set-e/background1.0
+++ b/sh/tests/set-e/background1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/background1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false &
diff --git a/sh/tests/set-e/cmd1.0 b/sh/tests/set-e/cmd1.0
index 67fdcbc..7c6c843 100644
--- a/sh/tests/set-e/cmd1.0
+++ b/sh/tests/set-e/cmd1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/cmd1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 true
diff --git a/sh/tests/set-e/cmd2.1 b/sh/tests/set-e/cmd2.1
index 7cd8b09..05a4243 100644
--- a/sh/tests/set-e/cmd2.1
+++ b/sh/tests/set-e/cmd2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/cmd2.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false
 exit 0
diff --git a/sh/tests/set-e/elif1.0 b/sh/tests/set-e/elif1.0
index 6a5937d..38ccaec 100644
--- a/sh/tests/set-e/elif1.0
+++ b/sh/tests/set-e/elif1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/elif1.0 211399 2010-08-16 17:18:08Z jilles $
 set -e
 if false; then
 	:
diff --git a/sh/tests/set-e/elif2.0 b/sh/tests/set-e/elif2.0
index 9dbb4bf..694b3f0 100644
--- a/sh/tests/set-e/elif2.0
+++ b/sh/tests/set-e/elif2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/elif2.0 211399 2010-08-16 17:18:08Z jilles $
 set -e
 if false; then
 	:
diff --git a/sh/tests/set-e/eval1.0 b/sh/tests/set-e/eval1.0
index 9b7f67b..cefaf91 100644
--- a/sh/tests/set-e/eval1.0
+++ b/sh/tests/set-e/eval1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/eval1.0 193178 2009-05-31 17:23:27Z stefanf $
 set -e
 eval false || true
diff --git a/sh/tests/set-e/eval2.1 b/sh/tests/set-e/eval2.1
index 8bb7f3a..e396e1c 100644
--- a/sh/tests/set-e/eval2.1
+++ b/sh/tests/set-e/eval2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/eval2.1 193178 2009-05-31 17:23:27Z stefanf $
 set -e
 eval false
 exit 0
diff --git a/sh/tests/set-e/for1.0 b/sh/tests/set-e/for1.0
index 67eb718..d0f7d8f 100644
--- a/sh/tests/set-e/for1.0
+++ b/sh/tests/set-e/for1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/for1.0 149791 2005-09-05 09:42:10Z stefanf $
 set -e
 f() {
 	for i in a b c; do
diff --git a/sh/tests/set-e/func1.0 b/sh/tests/set-e/func1.0
index 3c6b704..c76d689 100644
--- a/sh/tests/set-e/func1.0
+++ b/sh/tests/set-e/func1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/func1.0 149791 2005-09-05 09:42:10Z stefanf $
 set -e
 f() {
 	false
diff --git a/sh/tests/set-e/func2.1 b/sh/tests/set-e/func2.1
index cc76d6e..267966d 100644
--- a/sh/tests/set-e/func2.1
+++ b/sh/tests/set-e/func2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/func2.1 149791 2005-09-05 09:42:10Z stefanf $
 set -e
 f() {
 	false
diff --git a/sh/tests/set-e/if1.0 b/sh/tests/set-e/if1.0
index 36aa4bd..5697e2f 100644
--- a/sh/tests/set-e/if1.0
+++ b/sh/tests/set-e/if1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/if1.0 211399 2010-08-16 17:18:08Z jilles $
 set -e
 if false; then
 	:
diff --git a/sh/tests/set-e/if2.0 b/sh/tests/set-e/if2.0
index 4955408..188361b 100644
--- a/sh/tests/set-e/if2.0
+++ b/sh/tests/set-e/if2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/if2.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 # PR 28852
 if true; then
diff --git a/sh/tests/set-e/if3.0 b/sh/tests/set-e/if3.0
index a4916a8..e3d8d6e 100644
--- a/sh/tests/set-e/if3.0
+++ b/sh/tests/set-e/if3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/if3.0 211399 2010-08-16 17:18:08Z jilles $
 set -e
 if false; false; then
 	:
diff --git a/sh/tests/set-e/not1.0 b/sh/tests/set-e/not1.0
index 21c089a..b694be8 100644
--- a/sh/tests/set-e/not1.0
+++ b/sh/tests/set-e/not1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/not1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 ! true
 exit 0
diff --git a/sh/tests/set-e/not2.0 b/sh/tests/set-e/not2.0
index 7d93b4d..d9ea5e9 100644
--- a/sh/tests/set-e/not2.0
+++ b/sh/tests/set-e/not2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/not2.0 193178 2009-05-31 17:23:27Z stefanf $
 set -e
 ! false
 ! eval false
diff --git a/sh/tests/set-e/or1.0 b/sh/tests/set-e/or1.0
index c2dcbe9..5000f0b 100644
--- a/sh/tests/set-e/or1.0
+++ b/sh/tests/set-e/or1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/or1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 true || false
diff --git a/sh/tests/set-e/or2.0 b/sh/tests/set-e/or2.0
index 934e2a6..6964220 100644
--- a/sh/tests/set-e/or2.0
+++ b/sh/tests/set-e/or2.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/or2.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false || true
diff --git a/sh/tests/set-e/or3.1 b/sh/tests/set-e/or3.1
index 7a617a1..29af2c2 100644
--- a/sh/tests/set-e/or3.1
+++ b/sh/tests/set-e/or3.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/or3.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false || false
 exit 0
diff --git a/sh/tests/set-e/pipe1.1 b/sh/tests/set-e/pipe1.1
index c0bad0f..122af07 100644
--- a/sh/tests/set-e/pipe1.1
+++ b/sh/tests/set-e/pipe1.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/pipe1.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 true | false
 exit 0
diff --git a/sh/tests/set-e/pipe2.0 b/sh/tests/set-e/pipe2.0
index 1e25566..d80fd93 100644
--- a/sh/tests/set-e/pipe2.0
+++ b/sh/tests/set-e/pipe2.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/pipe2.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false | true
diff --git a/sh/tests/set-e/return1.0 b/sh/tests/set-e/return1.0
index 961bd41..d157059 100644
--- a/sh/tests/set-e/return1.0
+++ b/sh/tests/set-e/return1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/return1.0 149788 2005-09-04 21:29:09Z stefanf $
 set -e
 
 # PR 77067, 85267
diff --git a/sh/tests/set-e/semi1.1 b/sh/tests/set-e/semi1.1
index 90476a9..5991f8d 100644
--- a/sh/tests/set-e/semi1.1
+++ b/sh/tests/set-e/semi1.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/semi1.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 false; true
 exit 0
diff --git a/sh/tests/set-e/semi2.1 b/sh/tests/set-e/semi2.1
index 8f510ac..6851700 100644
--- a/sh/tests/set-e/semi2.1
+++ b/sh/tests/set-e/semi2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/semi2.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 true; false
 exit 0
diff --git a/sh/tests/set-e/subshell1.0 b/sh/tests/set-e/subshell1.0
index 8e5831b..fa2ec82 100644
--- a/sh/tests/set-e/subshell1.0
+++ b/sh/tests/set-e/subshell1.0
@@ -1,3 +1,3 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/subshell1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 (true)
diff --git a/sh/tests/set-e/subshell2.1 b/sh/tests/set-e/subshell2.1
index 619e98a..03b09dc 100644
--- a/sh/tests/set-e/subshell2.1
+++ b/sh/tests/set-e/subshell2.1
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/subshell2.1 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 (false)
 exit 0
diff --git a/sh/tests/set-e/until1.0 b/sh/tests/set-e/until1.0
index 71ea7f2..c4d2edd 100644
--- a/sh/tests/set-e/until1.0
+++ b/sh/tests/set-e/until1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/until1.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 until false; do
 	break
diff --git a/sh/tests/set-e/until2.0 b/sh/tests/set-e/until2.0
index 24ea276..d19a740 100644
--- a/sh/tests/set-e/until2.0
+++ b/sh/tests/set-e/until2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/until2.0 149781 2005-09-04 11:59:59Z stefanf $
 set -e
 until false; false; do
 	break
diff --git a/sh/tests/set-e/until3.0 b/sh/tests/set-e/until3.0
index 597db59..2f77903 100644
--- a/sh/tests/set-e/until3.0
+++ b/sh/tests/set-e/until3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/until3.0 149791 2005-09-05 09:42:10Z stefanf $
 set -e
 f() {
 	until false; do
diff --git a/sh/tests/set-e/while1.0 b/sh/tests/set-e/while1.0
index 371c94a..6d7fe0a 100644
--- a/sh/tests/set-e/while1.0
+++ b/sh/tests/set-e/while1.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/while1.0 211399 2010-08-16 17:18:08Z jilles $
 set -e
 while false; do
 	:
diff --git a/sh/tests/set-e/while2.0 b/sh/tests/set-e/while2.0
index 124966c..fe2f2ba 100644
--- a/sh/tests/set-e/while2.0
+++ b/sh/tests/set-e/while2.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/while2.0 211399 2010-08-16 17:18:08Z jilles $
 set -e
 while false; false; do
 	:
diff --git a/sh/tests/set-e/while3.0 b/sh/tests/set-e/while3.0
index dd3c790..bf87175 100644
--- a/sh/tests/set-e/while3.0
+++ b/sh/tests/set-e/while3.0
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/bin/sh/tests/set-e/while3.0 149791 2005-09-05 09:42:10Z stefanf $
 set -e
 f() {
 	while true; do
diff --git a/sh/trap.c b/sh/trap.c
index b90fee8..7a969ed 100644
--- a/sh/trap.c
+++ b/sh/trap.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)trap.c	8.5 (Berkeley) 6/5/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/trap.c 297360 2016-03-28 18:58:40Z jilles $");
 
 #include <signal.h>
 #include <unistd.h>
@@ -415,6 +415,7 @@ onsig(int signo)
 void
 dotrap(void)
 {
+	struct stackmark smark;
 	int i;
 	int savestatus, prev_evalskip, prev_skipcount;
 
@@ -448,7 +449,9 @@ dotrap(void)
 
 					last_trapsig = i;
 					savestatus = exitstatus;
-					evalstring(trap[i], 0);
+					setstackmark(&smark);
+					evalstring(stsavestr(trap[i]), 0);
+					popstackmark(&smark);
 
 					/*
 					 * If such a command was not
diff --git a/sh/trap.h b/sh/trap.h
index a272839..a000647 100644
--- a/sh/trap.h
+++ b/sh/trap.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)trap.h	8.3 (Berkeley) 6/5/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/trap.h 276038 2014-12-21 23:09:59Z jilles $
  */
 
 extern volatile sig_atomic_t pendingsig;
diff --git a/sh/var.c b/sh/var.c
index f60dea1..5ff6d20 100644
--- a/sh/var.c
+++ b/sh/var.c
@@ -36,7 +36,7 @@ static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/bin/sh/var.c 306843 2016-10-08 13:40:12Z jilles $");
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -186,6 +186,7 @@ initvar(void)
 		}
 	}
 	setvareq_const("OPTIND=1", 0);
+	setvareq_const("IFS= \t\n", 0);
 }
 
 /*
@@ -330,7 +331,7 @@ setvareq(char *s, int flags)
 		if (vp->flags & VREADONLY) {
 			if ((flags & (VTEXTFIXED|VSTACK)) == 0)
 				ckfree(s);
-			error("%.*s: is read only", vp->name_len, s);
+			error("%.*s: is read only", vp->name_len, vp->text);
 		}
 		if (flags & VNOSET) {
 			if ((flags & (VTEXTFIXED|VSTACK)) == 0)
@@ -403,14 +404,13 @@ setvareq_const(const char *s, int flags)
  */
 
 void
-listsetvar(struct strlist *list, int flags)
+listsetvar(struct arglist *list, int flags)
 {
-	struct strlist *lp;
+	int i;
 
 	INTOFF;
-	for (lp = list ; lp ; lp = lp->next) {
-		setvareq(savestr(lp->text), flags);
-	}
+	for (i = 0; i < list->count; i++)
+		setvareq(savestr(list->args[i]), flags);
 	INTON;
 }
 
@@ -442,14 +442,14 @@ lookupvar(const char *name)
 char *
 bltinlookup(const char *name, int doall)
 {
-	struct strlist *sp;
 	struct var *v;
 	char *result;
+	int i;
 
 	result = NULL;
-	for (sp = cmdenviron ; sp ; sp = sp->next) {
-		if (varequal(sp->text, name))
-			result = strchr(sp->text, '=') + 1;
+	if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) {
+		if (varequal(cmdenviron->args[i], name))
+			result = strchr(cmdenviron->args[i], '=') + 1;
 	}
 	if (result != NULL)
 		return result;
@@ -468,13 +468,12 @@ bltinlookup(const char *name, int doall)
 void
 bltinsetlocale(void)
 {
-	struct strlist *lp;
 	int act = 0;
 	char *loc, *locdef;
 	int i;
 
-	for (lp = cmdenviron ; lp ; lp = lp->next) {
-		if (localevar(lp->text)) {
+	if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) {
+		if (localevar(cmdenviron->args[i])) {
 			act = 1;
 			break;
 		}
@@ -507,11 +506,11 @@ bltinsetlocale(void)
 void
 bltinunsetlocale(void)
 {
-	struct strlist *lp;
+	int i;
 
 	INTOFF;
-	for (lp = cmdenviron ; lp ; lp = lp->next) {
-		if (localevar(lp->text)) {
+	if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) {
+		if (localevar(cmdenviron->args[i])) {
 			setlocale(LC_ALL, "");
 			updatecharset();
 			return;
@@ -756,8 +755,8 @@ mklocal(char *name)
 	INTOFF;
 	lvp = ckmalloc(sizeof (struct localvar));
 	if (name[0] == '-' && name[1] == '\0') {
-		lvp->text = ckmalloc(sizeof optlist);
-		memcpy(lvp->text, optlist, sizeof optlist);
+		lvp->text = ckmalloc(sizeof optval);
+		memcpy(lvp->text, optval, sizeof optval);
 		vp = NULL;
 	} else {
 		vp = find_var(name, &vpp, NULL);
@@ -793,22 +792,34 @@ poplocalvars(void)
 {
 	struct localvar *lvp;
 	struct var *vp;
+	int islocalevar;
 
 	INTOFF;
 	while ((lvp = localvars) != NULL) {
 		localvars = lvp->next;
 		vp = lvp->vp;
 		if (vp == NULL) {	/* $- saved */
-			memcpy(optlist, lvp->text, sizeof optlist);
+			memcpy(optval, lvp->text, sizeof optval);
 			ckfree(lvp->text);
 			optschanged();
 		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
+			vp->flags &= ~VREADONLY;
 			(void)unsetvar(vp->text);
 		} else {
+			islocalevar = (vp->flags | lvp->flags) & VEXPORT &&
+			    localevar(lvp->text);
 			if ((vp->flags & VTEXTFIXED) == 0)
 				ckfree(vp->text);
 			vp->flags = lvp->flags;
 			vp->text = lvp->text;
+			if (vp->func)
+				(*vp->func)(vp->text + vp->name_len + 1);
+			if (islocalevar) {
+				change_env(vp->text, vp->flags & VEXPORT &&
+				    (vp->flags & VUNSET) == 0);
+				setlocale(LC_ALL, "");
+				updatecharset();
+			}
 		}
 		ckfree(lvp);
 	}
diff --git a/sh/var.h b/sh/var.h
index 6e831ae..7955c04 100644
--- a/sh/var.h
+++ b/sh/var.h
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)var.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD$
+ * $FreeBSD: head/bin/sh/var.h 289159 2015-10-11 21:33:00Z jilles $
  */
 
 /*
@@ -114,8 +114,8 @@ extern int initial_localeisutf8;
 void initvar(void);
 void setvar(const char *, const char *, int);
 void setvareq(char *, int);
-struct strlist;
-void listsetvar(struct strlist *, int);
+struct arglist;
+void listsetvar(struct arglist *, int);
 char *lookupvar(const char *);
 char *bltinlookup(const char *, int);
 void bltinsetlocale(void);
diff --git a/shell_cmds.xcodeproj/project.pbxproj b/shell_cmds.xcodeproj/project.pbxproj
index 26fdc28..ec1e231 100644
--- a/shell_cmds.xcodeproj/project.pbxproj
+++ b/shell_cmds.xcodeproj/project.pbxproj
@@ -255,6 +255,22 @@
 		FCE30EE014B536F200CC0294 /* locate.code.c in Sources */ = {isa = PBXBuildFile; fileRef = FCBA13A114A141A300AA698B /* locate.code.c */; };
 		FCE30EE114B536F800CC0294 /* locate.code.8 in CopyFiles */ = {isa = PBXBuildFile; fileRef = FCBA13B114A141A300AA698B /* locate.code.8 */; };
 		FCED3AF614B4FC1800C313C3 /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FCED3AF514B4FC1800C313C3 /* libpam.dylib */; };
+		FD155C751D6E37E5005A53CA /* legacy_test.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C721D6E37B5005A53CA /* legacy_test.sh */; };
+		FD155C891D6E38C0005A53CA /* legacy_test.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C771D6E3847005A53CA /* legacy_test.sh */; };
+		FD155C8A1D6E38C0005A53CA /* regress.b.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C7A1D6E3847005A53CA /* regress.b.out */; };
+		FD155C8B1D6E38C0005A53CA /* regress.d.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C7B1D6E3847005A53CA /* regress.d.out */; };
+		FD155C8C1D6E38C0005A53CA /* regress.f.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C7C1D6E3847005A53CA /* regress.f.out */; };
+		FD155C8D1D6E38C0005A53CA /* regress.l1.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C7D1D6E3847005A53CA /* regress.l1.out */; };
+		FD155C8E1D6E38C0005A53CA /* regress.l2.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C7E1D6E3847005A53CA /* regress.l2.out */; };
+		FD155C8F1D6E38C0005A53CA /* regress.m1.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C7F1D6E3847005A53CA /* regress.m1.out */; };
+		FD155C901D6E38C0005A53CA /* regress.m2.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C801D6E3847005A53CA /* regress.m2.out */; };
+		FD155C911D6E38C0005A53CA /* regress.m3.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C811D6E3847005A53CA /* regress.m3.out */; };
+		FD155C921D6E38C0005A53CA /* regress.m4.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C821D6E3847005A53CA /* regress.m4.out */; };
+		FD155C931D6E38C0005A53CA /* regress.m5.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C831D6E3847005A53CA /* regress.m5.out */; };
+		FD155C941D6E38C0005A53CA /* regress.missingpos1.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C841D6E3847005A53CA /* regress.missingpos1.out */; };
+		FD155C951D6E38C0005A53CA /* regress.s.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C851D6E3847005A53CA /* regress.s.out */; };
+		FD155C961D6E38C0005A53CA /* regress.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C861D6E3847005A53CA /* regress.sh */; };
+		FD155C971D6E38C0005A53CA /* regress.zero.out in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD155C871D6E3847005A53CA /* regress.zero.out */; };
 		FD6060B51B7C0388004BCA6A /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = FD6060B41B7C0388004BCA6A /* main.c */; };
 		FD6060D21B7C0471004BCA6A /* alias.c in Sources */ = {isa = PBXBuildFile; fileRef = FD6060BC1B7C0471004BCA6A /* alias.c */; };
 		FD6060D31B7C0471004BCA6A /* arith_yacc.c in Sources */ = {isa = PBXBuildFile; fileRef = FD6060BD1B7C0471004BCA6A /* arith_yacc.c */; };
@@ -1489,6 +1505,40 @@
 			);
 			runOnlyForDeploymentPostprocessing = 1;
 		};
+		FD155C741D6E37D7005A53CA /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /AppleInternal/Tests/shell_cmds/test;
+			dstSubfolderSpec = 0;
+			files = (
+				FD155C751D6E37E5005A53CA /* legacy_test.sh in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		FD155C881D6E38AB005A53CA /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /AppleInternal/Tests/shell_cmds/printf;
+			dstSubfolderSpec = 0;
+			files = (
+				FD155C891D6E38C0005A53CA /* legacy_test.sh in CopyFiles */,
+				FD155C8A1D6E38C0005A53CA /* regress.b.out in CopyFiles */,
+				FD155C8B1D6E38C0005A53CA /* regress.d.out in CopyFiles */,
+				FD155C8C1D6E38C0005A53CA /* regress.f.out in CopyFiles */,
+				FD155C8D1D6E38C0005A53CA /* regress.l1.out in CopyFiles */,
+				FD155C8E1D6E38C0005A53CA /* regress.l2.out in CopyFiles */,
+				FD155C8F1D6E38C0005A53CA /* regress.m1.out in CopyFiles */,
+				FD155C901D6E38C0005A53CA /* regress.m2.out in CopyFiles */,
+				FD155C911D6E38C0005A53CA /* regress.m3.out in CopyFiles */,
+				FD155C921D6E38C0005A53CA /* regress.m4.out in CopyFiles */,
+				FD155C931D6E38C0005A53CA /* regress.m5.out in CopyFiles */,
+				FD155C941D6E38C0005A53CA /* regress.missingpos1.out in CopyFiles */,
+				FD155C951D6E38C0005A53CA /* regress.s.out in CopyFiles */,
+				FD155C961D6E38C0005A53CA /* regress.sh in CopyFiles */,
+				FD155C971D6E38C0005A53CA /* regress.zero.out in CopyFiles */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
@@ -1686,6 +1736,22 @@
 		FCE30ED214B5368A00CC0294 /* locate.bigram */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = locate.bigram; sourceTree = BUILT_PRODUCTS_DIR; };
 		FCE30EDE14B536C900CC0294 /* locate.code */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = locate.code; sourceTree = BUILT_PRODUCTS_DIR; };
 		FCED3AF514B4FC1800C313C3 /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = /usr/lib/libpam.dylib; sourceTree = "<absolute>"; };
+		FD155C721D6E37B5005A53CA /* legacy_test.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = legacy_test.sh; sourceTree = "<group>"; };
+		FD155C771D6E3847005A53CA /* legacy_test.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = legacy_test.sh; sourceTree = "<group>"; };
+		FD155C7A1D6E3847005A53CA /* regress.b.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.b.out; sourceTree = "<group>"; };
+		FD155C7B1D6E3847005A53CA /* regress.d.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.d.out; sourceTree = "<group>"; };
+		FD155C7C1D6E3847005A53CA /* regress.f.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.f.out; sourceTree = "<group>"; };
+		FD155C7D1D6E3847005A53CA /* regress.l1.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.l1.out; sourceTree = "<group>"; };
+		FD155C7E1D6E3847005A53CA /* regress.l2.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.l2.out; sourceTree = "<group>"; };
+		FD155C7F1D6E3847005A53CA /* regress.m1.out */ = {isa = PBXFileReference; lastKnownFileType = file; path = regress.m1.out; sourceTree = "<group>"; };
+		FD155C801D6E3847005A53CA /* regress.m2.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.m2.out; sourceTree = "<group>"; };
+		FD155C811D6E3847005A53CA /* regress.m3.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.m3.out; sourceTree = "<group>"; };
+		FD155C821D6E3847005A53CA /* regress.m4.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.m4.out; sourceTree = "<group>"; };
+		FD155C831D6E3847005A53CA /* regress.m5.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.m5.out; sourceTree = "<group>"; };
+		FD155C841D6E3847005A53CA /* regress.missingpos1.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.missingpos1.out; sourceTree = "<group>"; };
+		FD155C851D6E3847005A53CA /* regress.s.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.s.out; sourceTree = "<group>"; };
+		FD155C861D6E3847005A53CA /* regress.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = regress.sh; sourceTree = "<group>"; };
+		FD155C871D6E3847005A53CA /* regress.zero.out */ = {isa = PBXFileReference; lastKnownFileType = text; path = regress.zero.out; sourceTree = "<group>"; };
 		FD6060B21B7C0388004BCA6A /* ash */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ash; sourceTree = BUILT_PRODUCTS_DIR; };
 		FD6060B41B7C0388004BCA6A /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
 		FD6060BC1B7C0471004BCA6A /* alias.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alias.c; sourceTree = "<group>"; };
@@ -2551,6 +2617,7 @@
 			children = (
 				FCBA13D414A141A300AA698B /* printf.1 */,
 				FCBA13D514A141A300AA698B /* printf.c */,
+				FD155C761D6E3847005A53CA /* tests */,
 			);
 			path = printf;
 			sourceTree = "<group>";
@@ -2635,6 +2702,7 @@
 				FCBA13F814A141A300AA698B /* [.1 */,
 				FCBA13FA14A141A300AA698B /* test.1 */,
 				FCBA13FB14A141A300AA698B /* test.c */,
+				FD155C711D6E37B5005A53CA /* tests */,
 			);
 			path = test;
 			sourceTree = "<group>";
@@ -2739,6 +2807,36 @@
 			path = yes;
 			sourceTree = "<group>";
 		};
+		FD155C711D6E37B5005A53CA /* tests */ = {
+			isa = PBXGroup;
+			children = (
+				FD155C721D6E37B5005A53CA /* legacy_test.sh */,
+			);
+			path = tests;
+			sourceTree = "<group>";
+		};
+		FD155C761D6E3847005A53CA /* tests */ = {
+			isa = PBXGroup;
+			children = (
+				FD155C771D6E3847005A53CA /* legacy_test.sh */,
+				FD155C7A1D6E3847005A53CA /* regress.b.out */,
+				FD155C7B1D6E3847005A53CA /* regress.d.out */,
+				FD155C7C1D6E3847005A53CA /* regress.f.out */,
+				FD155C7D1D6E3847005A53CA /* regress.l1.out */,
+				FD155C7E1D6E3847005A53CA /* regress.l2.out */,
+				FD155C7F1D6E3847005A53CA /* regress.m1.out */,
+				FD155C801D6E3847005A53CA /* regress.m2.out */,
+				FD155C811D6E3847005A53CA /* regress.m3.out */,
+				FD155C821D6E3847005A53CA /* regress.m4.out */,
+				FD155C831D6E3847005A53CA /* regress.m5.out */,
+				FD155C841D6E3847005A53CA /* regress.missingpos1.out */,
+				FD155C851D6E3847005A53CA /* regress.s.out */,
+				FD155C861D6E3847005A53CA /* regress.sh */,
+				FD155C871D6E3847005A53CA /* regress.zero.out */,
+			);
+			path = tests;
+			sourceTree = "<group>";
+		};
 		FD6060B31B7C0388004BCA6A /* sh */ = {
 			isa = PBXGroup;
 			children = (
@@ -3321,6 +3419,7 @@
 				FCBA159F14A1459000AA698B /* Sources */,
 				FCBA15A014A1459000AA698B /* Frameworks */,
 				FCBA15A114A1459000AA698B /* CopyFiles */,
+				FD155C881D6E38AB005A53CA /* CopyFiles */,
 			);
 			buildRules = (
 			);
@@ -3474,6 +3573,7 @@
 				FCBA15E714A145AE00AA698B /* Sources */,
 				FCBA15E814A145AE00AA698B /* Frameworks */,
 				FCBA15E914A145AE00AA698B /* CopyFiles */,
+				FD155C741D6E37D7005A53CA /* CopyFiles */,
 			);
 			buildRules = (
 			);
diff --git a/test/tests/legacy_test.sh b/test/tests/legacy_test.sh
index 9229551..21c74a8 100644
--- a/test/tests/legacy_test.sh
+++ b/test/tests/legacy_test.sh
@@ -30,6 +30,8 @@
 #
 # $FreeBSD$
 
+enable -n test
+
 # force a specified test program, e.g. `env test=/bin/test sh regress.sh'
 : ${test=test}		
 
@@ -39,20 +41,25 @@ t ()
 	# $2 -> $test expression
 
 	count=$((count+1))
+	printf "[BEGIN] test $count\n"
 	# check for syntax errors
 	syntax="`eval $test $2 2>&1`"
 	ret=$?
 	if test -n "$syntax"; then
 		printf "not ok %s - (syntax error)\n" "$count $2"
+		printf "[FAIL] test $count\n"
 	elif [ "$ret" != "$1" ]; then
 		printf "not ok %s - (got $ret, expected $1)\n" "$count $2"
+		printf "[FAIL] test $count\n"
 	else
 		printf "ok %s\n" "$count $2"
+		printf "[PASS] test $count\n"
 	fi
 }
 
 count=0
 echo "1..130"
+printf "[TEST] shell_cmds: test\n"
 
 t 0 'b = b' 
 t 0 'b == b' 
diff --git a/tests/regress.m4 b/tests/regress.m4
new file mode 100644
index 0000000..c06caa1
--- /dev/null
+++ b/tests/regress.m4
@@ -0,0 +1,59 @@
+# $FreeBSD: head/usr.bin/tests/regress.m4 263227 2014-03-16 08:04:06Z jmmv $
+
+dnl A library of routines for doing regression tests for userland utilities.
+
+dnl Start up.  We initialise the exit status to 0 (no failure) and change
+dnl into the directory specified by our first argument, which is the
+dnl directory to run the tests inside.
+define(`REGRESSION_START',
+TESTDIR=$1
+if [ -z "$TESTDIR" ]; then
+  TESTDIR=.
+fi
+cd $TESTDIR
+
+STATUS=0)
+
+dnl Check $? to see if we passed or failed.  The first parameter is the test
+dnl which passed or failed.  It may be nil.
+define(`REGRESSION_PASSFAIL',
+if [ $? -eq 0 ]; then
+  echo "ok - $1 # Test detected no regression. (in $TESTDIR)"
+else
+  STATUS=$?
+  echo "not ok - $1 # Test failed: regression detected.  See above. (in $TESTDIR)"
+fi)
+
+dnl An actual test.  The first parameter is the test name.  The second is the
+dnl command/commands to execute for the actual test.  Their exit status is
+dnl checked.  It is assumed that the test will output to stdout, and that the
+dnl output to be used to check for regression will be in regress.TESTNAME.out.
+define(`REGRESSION_TEST',
+$2 | diff -u ${SRCDIR:-.}/regress.$1.out -
+REGRESSION_PASSFAIL($1))
+
+dnl A freeform regression test.  Only exit status is checked.
+define(`REGRESSION_TEST_FREEFORM',
+$2
+REGRESSION_PASSFAIL($1))
+
+dnl A regression test like REGRESSION_TEST, except only regress.out is used
+dnl for checking output differences.  The first argument is the command, the
+dnl second argument (which may be empty) is the test name.
+define(`REGRESSION_TEST_ONE',
+$1 | diff -u ${SRCDIR:-.}/regress.out -
+REGRESSION_PASSFAIL($2))
+
+dnl A fatal error.  This will exit with the given status (first argument) and
+dnl print the message (second argument) prefixed with the string "FATAL :" to
+dnl the error stream.
+define(`REGRESSION_FATAL',
+echo "Bail out! $2 (in $TESTDIR)" > /dev/stderr
+exit $1)
+
+dnl Cleanup.  Exit with the status code of the last failure.  Should probably
+dnl be the number of failed tests, but hey presto, this is what it does.  This
+dnl could also clean up potential droppings, if some forms of regression tests
+dnl end up using mktemp(1) or such.
+define(`REGRESSION_END',
+exit $STATUS)
diff --git a/tests/shell_cmds.plist b/tests/shell_cmds.plist
new file mode 100644
index 0000000..3794d3d
--- /dev/null
+++ b/tests/shell_cmds.plist
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Project</key>
+	<string>libutil</string>
+	<key>Tests</key>
+	<array>
+		<dict>
+			<key>Command</key>
+			<array>
+				<string>/bin/sh</string>
+				<string>/AppleInternal/Tests/shell_cmds/printf/legacy_test.sh</string>
+			</array>
+			<key>IgnoreOutput</key>
+			<true/>
+			<key>TestName</key>
+			<string>shell_cmds: printf</string>
+			<key>WhenToRun</key>
+			<array>
+				<string>PRESUBMISSION</string>
+				<string>NIGHTLY</string>
+			</array>
+		</dict>
+		<dict>
+			<key>Command</key>
+			<array>
+				<string>/bin/sh</string>
+				<string>/AppleInternal/Tests/shell_cmds/test/legacy_test.sh</string>
+			</array>
+			<key>TestName</key>
+			<string>shell_cmds: test</string>
+			<key>WhenToRun</key>
+			<array>
+				<string>PRESUBMISSION</string>
+				<string>NIGHTLY</string>
+			</array>
+		</dict>
+	</array>
+	<key>Timeout</key>
+	<integer>30</integer>
+</dict>
+</plist>
diff --git a/which/which.1 b/which/which.1
index f889e09..d0f2fcb 100644
--- a/which/which.1
+++ b/which/which.1
@@ -27,9 +27,9 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.bin/which/which.1,v 1.25 2005/02/10 16:04:22 ru Exp $
+.\" $FreeBSD: head/usr.bin/which/which.1 267773 2014-06-23 08:23:05Z bapt $
 .\"
-.Dd June 21, 2002
+.Dd December 13, 2006
 .Dt WHICH 1
 .Os
 .Sh NAME
@@ -52,8 +52,8 @@ The following options are available:
 List all instances of executables found (instead of just the first one
 of each).
 .It Fl s
-No output, just return 0 if any of the executables are found, or 1 if
-none are found.
+No output, just return 0 if all of the executables are found, or 1 if
+some were not found.
 .El
 .Pp
 Some shells may provide a builtin
@@ -78,8 +78,8 @@ command first appeared in
 The
 .Nm
 utility was originally written in Perl and was contributed by
-.An Wolfram Schneider Aq wosch@FreeBSD.org .
+.An Wolfram Schneider Aq Mt wosch@FreeBSD.org .
 The current version of
 .Nm
 was rewritten in C by
-.An Daniel Papasian Aq dpapasia@andrew.cmu.edu .
+.An Daniel Papasian Aq Mt dpapasia@andrew.cmu.edu .
diff --git a/which/which.c b/which/which.c
index e8ecea2..7e9d662 100644
--- a/which/which.c
+++ b/which/which.c
@@ -26,7 +26,7 @@
 
 #include <sys/cdefs.h>
 
-__FBSDID("$FreeBSD: src/usr.bin/which/which.c,v 1.6 2005/02/10 16:04:22 ru Exp $");
+__FBSDID("$FreeBSD: head/usr.bin/which/which.c 227245 2011-11-06 18:50:26Z ed $");
 
 #include <sys/stat.h>
 #include <sys/param.h>
@@ -40,8 +40,8 @@ __FBSDID("$FreeBSD: src/usr.bin/which/which.c,v 1.6 2005/02/10 16:04:22 ru Exp $
 static void	 usage(void);
 static int	 print_matches(char *, char *);
 	
-int 	silent;
-int 	allpaths;
+static int 	 silent;
+static int 	 allpaths;
 
 int
 main(int argc, char **argv)
diff --git a/xcodescripts/install-files.sh b/xcodescripts/install-files.sh
index 7d5b69d..11dcad9 100644
--- a/xcodescripts/install-files.sh
+++ b/xcodescripts/install-files.sh
@@ -50,3 +50,9 @@ echo ".so man8/locate.updatedb.8" > "$MANDIR"/man8/locate.mklocatedb.8
 
 install -d -o root -g wheel -m 0755 "$PAMDIR"
 install -c -o root -g wheel -m 0644 "$SRCROOT"/su/su.pam "$PAMDIR"/su
+
+install -d -o root -g wheel -m 0755 "$DSTROOT"/AppleInternal/Tests/shell_cmds
+install -o root -g wheel -m 0644 "$SRCROOT"/tests/regress.m4 "$DSTROOT"/AppleInternal/Tests/shell_cmds
+
+install -d -o root -g wheel -m 0755 "$DSTROOT"/AppleInternal/CoreOS/BATS/unit_tests
+install -o root -g wheel -m 0644 "$SRCROOT"/tests/shell_cmds.plist "$DSTROOT"/AppleInternal/CoreOS/BATS/unit_tests
-- 
2.50.0

