Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Jun 2010 08:13:35 -0400
From:      jhell <jhell@dataix.net>
To:        =?UTF-8?B?RGFnLUVybGluZyBTbcO4cmdyYXY=?= <des@des.no>
Cc:        "Sam Fourman Jr." <sfourman@gmail.com>, Brandon Gooch <jamesbrandongooch@gmail.com>, FreeBSD Current <freebsd-current@freebsd.org>, jilles@stack.nl
Subject:   Re: [MFC REQUEST] Filename completion in sh(1)
Message-ID:  <4C1F576F.9090901@dataix.net>
In-Reply-To: <86wrtz5mk6.fsf@ds4.des.no>
References:  <AANLkTilp7vQWC1Ae-ttAUusrT2Pb_-VsM4Ms3YbEo88G@mail.gmail.com> <4C18304A.1080601@dataix.net> <4C18322A.6050007@dataix.net> <AANLkTillAajdePsc635p9r2jRAjhppF-aNhdrFilXoV9@mail.gmail.com> <AANLkTileO47fQqUpaRKj55uqi8o65Ju8WV7crtyRizgf@mail.gmail.com> <AANLkTik7tUdJ1Im9dRQZt6FZw7sCId0a8qwJgGQKjPyf@mail.gmail.com> <86wrtz5mk6.fsf@ds4.des.no>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------020203000205020600080704
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 06/16/2010 05:55, Dag-Erling Smørgrav wrote:
> "Sam Fourman Jr." <sfourman@gmail.com> writes:
>> I would be very interested in a diff for FreeBSD 8.1
> 
> See attached patch.
> 
> DES
> 

Because SVN in both our patches for tab completion missed filecomplete.h
and filecomplete.c I generated a new patch using ( diff -urN ) since
these files do not exist on stable/8.

Since the above files do not exist, the previous patches from des@ &
myself will break world builds.

This is the full patch:
sh-tab-complete-stable8.diff

These are the individual patches:
head_lib_libedit_filecomplete.c
head_lib_libedit_filecomplete.h

Again, apply these with:
cd /usr/src && patch -p1 </path/to/patchfile


Regards,

- -- 

 jhell

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.15 (FreeBSD)

iQEcBAEBAgAGBQJMH1duAAoJEJBXh4mJ2FR+XdQH/3Pl/cg10/BpZQdcJELhvj71
tVlHPjEwo/3fyRrtItJTG1Kb3oCHmXfnOM+uoVEzqrh6FRv7h3P3/xvAWM0V72XI
ftIUsWKbfRF5Gi0/9x/sWwsSovJmeA0Fk1g1OxQkrxAyQ4iergs589fV+vlSQKQQ
qNh0GXkZLBFGepmzaZUkOJZRlTt94ZGO033vYph62AI4Q2MugK7YlRquTBdmcb0A
ZFst066Ju6P7EHaRhakYSkwhpe475Cgo6eRTpac0gfc/Q9voTQhjplELqPdS4MIK
GD1MQqgj+YilonKG6TvNEX4XeQOQoTQ+/crJ3XAM/sapxBsxRrpvQww+lDidsBo=
=TJ/I
-----END PGP SIGNATURE-----

--------------020203000205020600080704
Content-Type: text/plain;
 name="head_lib_libedit_filecomplete.c"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="head_lib_libedit_filecomplete.c"

ZGlmZiAtdXJOIHN0YWJsZS84L2xpYi9saWJlZGl0L2ZpbGVjb21wbGV0ZS5jIGhlYWQvbGli
L2xpYmVkaXQvZmlsZWNvbXBsZXRlLmMKLS0tIHN0YWJsZS84L2xpYi9saWJlZGl0L2ZpbGVj
b21wbGV0ZS5jCTE5NjktMTItMzEgMTk6MDA6MDAuMDAwMDAwMDAwIC0wNTAwCisrKyBoZWFk
L2xpYi9saWJlZGl0L2ZpbGVjb21wbGV0ZS5jCTIwMTAtMDYtMTUgMTg6MjM6MjEuNTY1OTky
MDAwIC0wNDAwCkBAIC0wLDAgKzEsNjY3IEBACisvKi0KKyAqIENvcHlyaWdodCAoYykgMTk5
NyBUaGUgTmV0QlNEIEZvdW5kYXRpb24sIEluYy4KKyAqIEFsbCByaWdodHMgcmVzZXJ2ZWQu
CisgKgorICogVGhpcyBjb2RlIGlzIGRlcml2ZWQgZnJvbSBzb2Z0d2FyZSBjb250cmlidXRl
ZCB0byBUaGUgTmV0QlNEIEZvdW5kYXRpb24KKyAqIGJ5IEphcm9taXIgRG9sZWNlay4KKyAq
CisgKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1z
LCB3aXRoIG9yIHdpdGhvdXQKKyAqIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92
aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucworICogYXJlIG1ldDoKKyAqIDEu
IFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUg
Y29weXJpZ2h0CisgKiAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0
aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCisgKiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmlu
YXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodAorICogICAgbm90
aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFp
bWVyIGluIHRoZQorICogICAgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxz
IHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KKyAqCisgKiBUSElTIFNPRlRXQVJF
IElTIFBST1ZJREVEIEJZIFRIRSBORVRCU0QgRk9VTkRBVElPTiwgSU5DLiBBTkQgQ09OVFJJ
QlVUT1JTCisgKiBgYEFTIElTJycgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFO
VElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQKKyAqIFRPLCBUSEUgSU1QTElFRCBX
QVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNV
TEFSCisgKiBQVVJQT1NFIEFSRSBESVNDTEFJTUVELiAgSU4gTk8gRVZFTlQgU0hBTEwgVEhF
IEZPVU5EQVRJT04gT1IgQ09OVFJJQlVUT1JTCisgKiBCRSBMSUFCTEUgRk9SIEFOWSBESVJF
Q1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SCisgKiBD
T05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQ
Uk9DVVJFTUVOVCBPRgorICogU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBP
RiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTCisgKiBJTlRFUlJVUFRJT04p
IEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhF
UiBJTgorICogQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElO
RyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkKKyAqIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQg
T0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFCisg
KiBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KKyAqCisgKgkkTmV0QlNEOiBmaWxlY29t
cGxldGUuYyx2IDEuMTkgMjAxMC8wNi8wMSAxODoyMDoyNiBjaHJpc3RvcyBFeHAgJAorICov
CisKKyNpbmNsdWRlIDxzeXMvY2RlZnMuaD4KK19fRkJTRElEKCIkRnJlZUJTRDogaGVhZC9s
aWIvbGliZWRpdC9maWxlY29tcGxldGUuYyAyMDkyMjQgMjAxMC0wNi0xNSAyMjoyMzoyMVog
amlsbGVzICQiKTsKKworI2luY2x1ZGUgPHN5cy90eXBlcy5oPgorI2luY2x1ZGUgPHN5cy9z
dGF0Lmg+CisjaW5jbHVkZSA8c3RkaW8uaD4KKyNpbmNsdWRlIDxkaXJlbnQuaD4KKyNpbmNs
dWRlIDxzdHJpbmcuaD4KKyNpbmNsdWRlIDxwd2QuaD4KKyNpbmNsdWRlIDxjdHlwZS5oPgor
I2luY2x1ZGUgPHN0ZGxpYi5oPgorI2luY2x1ZGUgPHVuaXN0ZC5oPgorI2luY2x1ZGUgPGxp
bWl0cy5oPgorI2luY2x1ZGUgPGVycm5vLmg+CisjaW5jbHVkZSA8ZmNudGwuaD4KKyNpbmNs
dWRlIDx2aXMuaD4KKyNpbmNsdWRlICJlbC5oIgorI2luY2x1ZGUgImZjbnMuaCIJCS8qIGZv
ciBFTF9OVU1fRkNOUyAqLworI2luY2x1ZGUgImhpc3RlZGl0LmgiCisjaW5jbHVkZSAiZmls
ZWNvbXBsZXRlLmgiCisKK3N0YXRpYyBjaGFyIGJyZWFrX2NoYXJzW10gPSB7ICcgJywgJ1x0
JywgJ1xuJywgJyInLCAnXFwnLCAnXCcnLCAnYCcsCisgICAgJz4nLCAnPCcsICc9JywgJzsn
LCAnfCcsICcmJywgJ3snLCAnKCcsICdcMCcgfTsKKy8qIFRpbGRlIGlzIGRlbGliZXJhdGVs
eSBvbWl0dGVkIGhlcmUsIHdlIHRyZWF0IGl0IHNwZWNpYWxseS4gKi8KK3N0YXRpYyBjaGFy
IGV4dHJhX3F1b3RlX2NoYXJzW10gPSB7ICcpJywgJ30nLCAnKicsICc/JywgJ1snLCAnJCcs
ICdcMCcgfTsKKworCisvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCisvKiBj
b21wbGV0aW9uIGZ1bmN0aW9ucyAqLworCisvKgorICogZG9lcyB0aWxkZSBleHBhbnNpb24g
b2Ygc3RyaW5ncyBvZiB0eXBlIGBgfnVzZXIvZm9vJycKKyAqIGlmIGBgdXNlcicnIGlzbid0
IHZhbGlkIHVzZXIgbmFtZSBvciBgYHR4dCcnIGRvZXNuJ3Qgc3RhcnQKKyAqIHcvICd+Jywg
cmV0dXJucyBwb2ludGVyIHRvIHN0cmR1cCgpZWQgY29weSBvZiBgYHR4dCcnCisgKgorICog
aXQncyBjYWxsZXJzJ3MgcmVzcG9uc2liaWxpdHkgdG8gZnJlZSgpIHJldHVybmVkIHN0cmlu
ZworICovCitjaGFyICoKK2ZuX3RpbGRlX2V4cGFuZChjb25zdCBjaGFyICp0eHQpCit7CisJ
c3RydWN0IHBhc3N3ZCBwd3JlcywgKnBhc3M7CisJY2hhciAqdGVtcDsKKwlzaXplX3QgbGVu
ID0gMDsKKwljaGFyIHB3YnVmWzEwMjRdOworCisJaWYgKHR4dFswXSAhPSAnficpCisJCXJl
dHVybiAoc3RyZHVwKHR4dCkpOworCisJdGVtcCA9IHN0cmNocih0eHQgKyAxLCAnLycpOwor
CWlmICh0ZW1wID09IE5VTEwpIHsKKwkJdGVtcCA9IHN0cmR1cCh0eHQgKyAxKTsKKwkJaWYg
KHRlbXAgPT0gTlVMTCkKKwkJCXJldHVybiBOVUxMOworCX0gZWxzZSB7CisJCWxlbiA9IHRl
bXAgLSB0eHQgKyAxOwkvKiB0ZXh0IHVudGlsIHN0cmluZyBhZnRlciBzbGFzaCAqLworCQl0
ZW1wID0gbWFsbG9jKGxlbik7CisJCWlmICh0ZW1wID09IE5VTEwpCisJCQlyZXR1cm4gTlVM
TDsKKwkJKHZvaWQpc3RybmNweSh0ZW1wLCB0eHQgKyAxLCBsZW4gLSAyKTsKKwkJdGVtcFts
ZW4gLSAyXSA9ICdcMCc7CisJfQorCWlmICh0ZW1wWzBdID09IDApIHsKKwkJaWYgKGdldHB3
dWlkX3IoZ2V0dWlkKCksICZwd3JlcywgcHdidWYsIHNpemVvZihwd2J1ZiksICZwYXNzKSAh
PSAwKQorCQkJcGFzcyA9IE5VTEw7CisJfSBlbHNlIHsKKwkJaWYgKGdldHB3bmFtX3IodGVt
cCwgJnB3cmVzLCBwd2J1Ziwgc2l6ZW9mKHB3YnVmKSwgJnBhc3MpICE9IDApCisJCQlwYXNz
ID0gTlVMTDsKKwl9CisJZnJlZSh0ZW1wKTsJCS8qIHZhbHVlIG5vIG1vcmUgbmVlZGVkICov
CisJaWYgKHBhc3MgPT0gTlVMTCkKKwkJcmV0dXJuIChzdHJkdXAodHh0KSk7CisKKwkvKiB1
cGRhdGUgcG9pbnRlciB0eHQgdG8gcG9pbnQgYXQgc3RyaW5nIGltbWVkaWF0ZWx5IGZvbGxv
d2luZyAqLworCS8qIGZpcnN0IHNsYXNoICovCisJdHh0ICs9IGxlbjsKKworCXRlbXAgPSBt
YWxsb2Moc3RybGVuKHBhc3MtPnB3X2RpcikgKyAxICsgc3RybGVuKHR4dCkgKyAxKTsKKwlp
ZiAodGVtcCA9PSBOVUxMKQorCQlyZXR1cm4gTlVMTDsKKwkodm9pZClzcHJpbnRmKHRlbXAs
ICIlcy8lcyIsIHBhc3MtPnB3X2RpciwgdHh0KTsKKworCXJldHVybiAodGVtcCk7Cit9CisK
KworLyoKKyAqIHJldHVybiBmaXJzdCBmb3VuZCBmaWxlIG5hbWUgc3RhcnRpbmcgYnkgdGhl
IGBgdGV4dCcnIG9yIE5VTEwgaWYgbm8KKyAqIHN1Y2ggZmlsZSBjYW4gYmUgZm91bmQKKyAq
IHZhbHVlIG9mIGBgc3RhdGUnJyBpcyBpZ25vcmVkCisgKgorICogaXQncyBjYWxsZXIncyBy
ZXNwb25zaWJpbGl0eSB0byBmcmVlIHJldHVybmVkIHN0cmluZworICovCitjaGFyICoKK2Zu
X2ZpbGVuYW1lX2NvbXBsZXRpb25fZnVuY3Rpb24oY29uc3QgY2hhciAqdGV4dCwgaW50IHN0
YXRlKQoreworCXN0YXRpYyBESVIgKmRpciA9IE5VTEw7CisJc3RhdGljIGNoYXIgKmZpbGVu
YW1lID0gTlVMTCwgKmRpcm5hbWUgPSBOVUxMLCAqZGlycGF0aCA9IE5VTEw7CisJc3RhdGlj
IHNpemVfdCBmaWxlbmFtZV9sZW4gPSAwOworCXN0cnVjdCBkaXJlbnQgKmVudHJ5OworCWNo
YXIgKnRlbXA7CisJc2l6ZV90IGxlbjsKKworCWlmIChzdGF0ZSA9PSAwIHx8IGRpciA9PSBO
VUxMKSB7CisJCXRlbXAgPSBzdHJyY2hyKHRleHQsICcvJyk7CisJCWlmICh0ZW1wKSB7CisJ
CQljaGFyICpucHRyOworCQkJdGVtcCsrOworCQkJbnB0ciA9IHJlYWxsb2MoZmlsZW5hbWUs
IHN0cmxlbih0ZW1wKSArIDEpOworCQkJaWYgKG5wdHIgPT0gTlVMTCkgeworCQkJCWZyZWUo
ZmlsZW5hbWUpOworCQkJCWZpbGVuYW1lID0gTlVMTDsKKwkJCQlyZXR1cm4gTlVMTDsKKwkJ
CX0KKwkJCWZpbGVuYW1lID0gbnB0cjsKKwkJCSh2b2lkKXN0cmNweShmaWxlbmFtZSwgdGVt
cCk7CisJCQlsZW4gPSB0ZW1wIC0gdGV4dDsJLyogaW5jbHVkaW5nIGxhc3Qgc2xhc2ggKi8K
KworCQkJbnB0ciA9IHJlYWxsb2MoZGlybmFtZSwgbGVuICsgMSk7CisJCQlpZiAobnB0ciA9
PSBOVUxMKSB7CisJCQkJZnJlZShkaXJuYW1lKTsKKwkJCQlkaXJuYW1lID0gTlVMTDsKKwkJ
CQlyZXR1cm4gTlVMTDsKKwkJCX0KKwkJCWRpcm5hbWUgPSBucHRyOworCQkJKHZvaWQpc3Ry
bmNweShkaXJuYW1lLCB0ZXh0LCBsZW4pOworCQkJZGlybmFtZVtsZW5dID0gJ1wwJzsKKwkJ
fSBlbHNlIHsKKwkJCWZyZWUoZmlsZW5hbWUpOworCQkJaWYgKCp0ZXh0ID09IDApCisJCQkJ
ZmlsZW5hbWUgPSBOVUxMOworCQkJZWxzZSB7CisJCQkJZmlsZW5hbWUgPSBzdHJkdXAodGV4
dCk7CisJCQkJaWYgKGZpbGVuYW1lID09IE5VTEwpCisJCQkJCXJldHVybiBOVUxMOworCQkJ
fQorCQkJZnJlZShkaXJuYW1lKTsKKwkJCWRpcm5hbWUgPSBOVUxMOworCQl9CisKKwkJaWYg
KGRpciAhPSBOVUxMKSB7CisJCQkodm9pZCljbG9zZWRpcihkaXIpOworCQkJZGlyID0gTlVM
TDsKKwkJfQorCisJCS8qIHN1cHBvcnQgZm9yIGBgfnVzZXInJyBzeW50YXggKi8KKworCQlm
cmVlKGRpcnBhdGgpOworCQlkaXJwYXRoID0gTlVMTDsKKwkJaWYgKGRpcm5hbWUgPT0gTlVM
TCkgeworCQkJaWYgKChkaXJuYW1lID0gc3RyZHVwKCIiKSkgPT0gTlVMTCkKKwkJCQlyZXR1
cm4gTlVMTDsKKwkJCWRpcnBhdGggPSBzdHJkdXAoIi4vIik7CisJCX0gZWxzZSBpZiAoKmRp
cm5hbWUgPT0gJ34nKQorCQkJZGlycGF0aCA9IGZuX3RpbGRlX2V4cGFuZChkaXJuYW1lKTsK
KwkJZWxzZQorCQkJZGlycGF0aCA9IHN0cmR1cChkaXJuYW1lKTsKKworCQlpZiAoZGlycGF0
aCA9PSBOVUxMKQorCQkJcmV0dXJuIE5VTEw7CisKKwkJZGlyID0gb3BlbmRpcihkaXJwYXRo
KTsKKwkJaWYgKCFkaXIpCisJCQlyZXR1cm4gKE5VTEwpOwkvKiBjYW5ub3Qgb3BlbiB0aGUg
ZGlyZWN0b3J5ICovCisKKwkJLyogd2lsbCBiZSB1c2VkIGluIGN5Y2xlICovCisJCWZpbGVu
YW1lX2xlbiA9IGZpbGVuYW1lID8gc3RybGVuKGZpbGVuYW1lKSA6IDA7CisJfQorCisJLyog
ZmluZCB0aGUgbWF0Y2ggKi8KKwl3aGlsZSAoKGVudHJ5ID0gcmVhZGRpcihkaXIpKSAhPSBO
VUxMKSB7CisJCS8qIHNraXAgLiBhbmQgLi4gKi8KKwkJaWYgKGVudHJ5LT5kX25hbWVbMF0g
PT0gJy4nICYmICghZW50cnktPmRfbmFtZVsxXQorCQkgICAgfHwgKGVudHJ5LT5kX25hbWVb
MV0gPT0gJy4nICYmICFlbnRyeS0+ZF9uYW1lWzJdKSkpCisJCQljb250aW51ZTsKKwkJaWYg
KGZpbGVuYW1lX2xlbiA9PSAwKQorCQkJYnJlYWs7CisJCS8qIG90aGVyd2lzZSwgZ2V0IGZp
cnN0IGVudHJ5IHdoZXJlIGZpcnN0ICovCisJCS8qIGZpbGVuYW1lX2xlbiBjaGFyYWN0ZXJz
IGFyZSBlcXVhbAkgICovCisJCWlmIChlbnRyeS0+ZF9uYW1lWzBdID09IGZpbGVuYW1lWzBd
CisJCSAgICAmJiBlbnRyeS0+ZF9uYW1sZW4gPj0gZmlsZW5hbWVfbGVuCisJCSAgICAmJiBz
dHJuY21wKGVudHJ5LT5kX25hbWUsIGZpbGVuYW1lLAorCQkJZmlsZW5hbWVfbGVuKSA9PSAw
KQorCQkJYnJlYWs7CisJfQorCisJaWYgKGVudHJ5KSB7CQkvKiBtYXRjaCBmb3VuZCAqLwor
CQlsZW4gPSBlbnRyeS0+ZF9uYW1sZW47CisKKwkJdGVtcCA9IG1hbGxvYyhzdHJsZW4oZGly
bmFtZSkgKyBsZW4gKyAxKTsKKwkJaWYgKHRlbXAgPT0gTlVMTCkKKwkJCXJldHVybiBOVUxM
OworCQkodm9pZClzcHJpbnRmKHRlbXAsICIlcyVzIiwgZGlybmFtZSwgZW50cnktPmRfbmFt
ZSk7CisJfSBlbHNlIHsKKwkJKHZvaWQpY2xvc2VkaXIoZGlyKTsKKwkJZGlyID0gTlVMTDsK
KwkJdGVtcCA9IE5VTEw7CisJfQorCisJcmV0dXJuICh0ZW1wKTsKK30KKworCitzdGF0aWMg
Y29uc3QgY2hhciAqCithcHBlbmRfY2hhcl9mdW5jdGlvbihjb25zdCBjaGFyICpuYW1lKQor
eworCXN0cnVjdCBzdGF0IHN0YnVmOworCWNoYXIgKmV4cG5hbWUgPSAqbmFtZSA9PSAnficg
PyBmbl90aWxkZV9leHBhbmQobmFtZSkgOiBOVUxMOworCWNvbnN0IGNoYXIgKnJzID0gIiAi
OworCisJaWYgKHN0YXQoZXhwbmFtZSA/IGV4cG5hbWUgOiBuYW1lLCAmc3RidWYpID09IC0x
KQorCQlnb3RvIG91dDsKKwlpZiAoU19JU0RJUihzdGJ1Zi5zdF9tb2RlKSkKKwkJcnMgPSAi
LyI7CitvdXQ6CisJaWYgKGV4cG5hbWUpCisJCWZyZWUoZXhwbmFtZSk7CisJcmV0dXJuIHJz
OworfQorCisKKy8qCisgKiByZXR1cm5zIGxpc3Qgb2YgY29tcGxldGlvbnMgZm9yIHRleHQg
Z2l2ZW4KKyAqIG5vbi1zdGF0aWMgZm9yIHJlYWRsaW5lLgorICovCitjaGFyICoqIGNvbXBs
ZXRpb25fbWF0Y2hlcyhjb25zdCBjaGFyICosIGNoYXIgKigqKShjb25zdCBjaGFyICosIGlu
dCkpOworY2hhciAqKgorY29tcGxldGlvbl9tYXRjaGVzKGNvbnN0IGNoYXIgKnRleHQsIGNo
YXIgKigqZ2VuZnVuYykoY29uc3QgY2hhciAqLCBpbnQpKQoreworCWNoYXIgKiptYXRjaF9s
aXN0ID0gTlVMTCwgKnJldHN0ciwgKnByZXZzdHI7CisJc2l6ZV90IG1hdGNoX2xpc3RfbGVu
LCBtYXhfZXF1YWwsIHdoaWNoLCBpOworCXNpemVfdCBtYXRjaGVzOworCisJbWF0Y2hlcyA9
IDA7CisJbWF0Y2hfbGlzdF9sZW4gPSAxOworCXdoaWxlICgocmV0c3RyID0gKCpnZW5mdW5j
KSAodGV4dCwgKGludCltYXRjaGVzKSkgIT0gTlVMTCkgeworCQkvKiBhbGxvdyBmb3IgbGlz
dCB0ZXJtaW5hdG9yIGhlcmUgKi8KKwkJaWYgKG1hdGNoZXMgKyAzID49IG1hdGNoX2xpc3Rf
bGVuKSB7CisJCQljaGFyICoqbm1hdGNoX2xpc3Q7CisJCQl3aGlsZSAobWF0Y2hlcyArIDMg
Pj0gbWF0Y2hfbGlzdF9sZW4pCisJCQkJbWF0Y2hfbGlzdF9sZW4gPDw9IDE7CisJCQlubWF0
Y2hfbGlzdCA9IHJlYWxsb2MobWF0Y2hfbGlzdCwKKwkJCSAgICBtYXRjaF9saXN0X2xlbiAq
IHNpemVvZihjaGFyICopKTsKKwkJCWlmIChubWF0Y2hfbGlzdCA9PSBOVUxMKSB7CisJCQkJ
ZnJlZShtYXRjaF9saXN0KTsKKwkJCQlyZXR1cm4gTlVMTDsKKwkJCX0KKwkJCW1hdGNoX2xp
c3QgPSBubWF0Y2hfbGlzdDsKKworCQl9CisJCW1hdGNoX2xpc3RbKyttYXRjaGVzXSA9IHJl
dHN0cjsKKwl9CisKKwlpZiAoIW1hdGNoX2xpc3QpCisJCXJldHVybiBOVUxMOwkvKiBub3Ro
aW5nIGZvdW5kICovCisKKwkvKiBmaW5kIGxlYXN0IGRlbm9taW5hdG9yIGFuZCBpbnNlcnQg
aXQgdG8gbWF0Y2hfbGlzdFswXSAqLworCXdoaWNoID0gMjsKKwlwcmV2c3RyID0gbWF0Y2hf
bGlzdFsxXTsKKwltYXhfZXF1YWwgPSBzdHJsZW4ocHJldnN0cik7CisJZm9yICg7IHdoaWNo
IDw9IG1hdGNoZXM7IHdoaWNoKyspIHsKKwkJZm9yIChpID0gMDsgaSA8IG1heF9lcXVhbCAm
JgorCQkgICAgcHJldnN0cltpXSA9PSBtYXRjaF9saXN0W3doaWNoXVtpXTsgaSsrKQorCQkJ
Y29udGludWU7CisJCW1heF9lcXVhbCA9IGk7CisJfQorCisJcmV0c3RyID0gbWFsbG9jKG1h
eF9lcXVhbCArIDEpOworCWlmIChyZXRzdHIgPT0gTlVMTCkgeworCQlmcmVlKG1hdGNoX2xp
c3QpOworCQlyZXR1cm4gTlVMTDsKKwl9CisJKHZvaWQpc3RybmNweShyZXRzdHIsIG1hdGNo
X2xpc3RbMV0sIG1heF9lcXVhbCk7CisJcmV0c3RyW21heF9lcXVhbF0gPSAnXDAnOworCW1h
dGNoX2xpc3RbMF0gPSByZXRzdHI7CisKKwkvKiBhZGQgTlVMTCBhcyBsYXN0IHBvaW50ZXIg
dG8gdGhlIGFycmF5ICovCisJbWF0Y2hfbGlzdFttYXRjaGVzICsgMV0gPSAoY2hhciAqKSBO
VUxMOworCisJcmV0dXJuIChtYXRjaF9saXN0KTsKK30KKworCisvKgorICogU29ydCBmdW5j
dGlvbiBmb3IgcXNvcnQoKS4gSnVzdCB3cmFwcGVyIGFyb3VuZCBzdHJjYXNlY21wKCkuCisg
Ki8KK3N0YXRpYyBpbnQKK19mbl9xc29ydF9zdHJpbmdfY29tcGFyZShjb25zdCB2b2lkICpp
MSwgY29uc3Qgdm9pZCAqaTIpCit7CisJY29uc3QgY2hhciAqczEgPSAoKGNvbnN0IGNoYXIg
KiBjb25zdCAqKWkxKVswXTsKKwljb25zdCBjaGFyICpzMiA9ICgoY29uc3QgY2hhciAqIGNv
bnN0ICopaTIpWzBdOworCisJcmV0dXJuIHN0cmNhc2VjbXAoczEsIHMyKTsKK30KKworCisv
KgorICogRGlzcGxheSBsaXN0IG9mIHN0cmluZ3MgaW4gY29sdW1uYXIgZm9ybWF0IG9uIHJl
YWRsaW5lJ3Mgb3V0cHV0IHN0cmVhbS4KKyAqICdtYXRjaGVzJyBpcyBsaXN0IG9mIHN0cmlu
Z3MsICdsZW4nIGlzIG51bWJlciBvZiBzdHJpbmdzIGluICdtYXRjaGVzJywKKyAqICdtYXgn
IGlzIG1heGltdW0gbGVuZ3RoIG9mIHN0cmluZyBpbiAnbWF0Y2hlcycuCisgKi8KK3ZvaWQK
K2ZuX2Rpc3BsYXlfbWF0Y2hfbGlzdChFZGl0TGluZSAqZWwsIGNoYXIgKiptYXRjaGVzLCBz
aXplX3QgbGVuLCBzaXplX3QgbWF4KQoreworCXNpemVfdCBpLCBpZHgsIGxpbWl0LCBjb3Vu
dDsKKwlpbnQgc2NyZWVud2lkdGggPSBlbC0+ZWxfdGVybS50X3NpemUuaDsKKworCS8qCisJ
ICogRmluZCBvdXQgaG93IG1hbnkgZW50cmllcyBjYW4gYmUgcHV0IG9uIG9uZSBsaW5lLCBj
b3VudAorCSAqIHdpdGggdHdvIHNwYWNlcyBiZXR3ZWVuIHN0cmluZ3MuCisJICovCisJbGlt
aXQgPSBzY3JlZW53aWR0aCAvIChtYXggKyAyKTsKKwlpZiAobGltaXQgPT0gMCkKKwkJbGlt
aXQgPSAxOworCisJLyogaG93IG1hbnkgbGluZXMgb2Ygb3V0cHV0ICovCisJY291bnQgPSBs
ZW4gLyBsaW1pdDsKKwlpZiAoY291bnQgKiBsaW1pdCA8IGxlbikKKwkJY291bnQrKzsKKwor
CS8qIFNvcnQgdGhlIGl0ZW1zIGlmIHRoZXkgYXJlIG5vdCBhbHJlYWR5IHNvcnRlZC4gKi8K
Kwlxc29ydCgmbWF0Y2hlc1sxXSwgbGVuLCBzaXplb2YoY2hhciAqKSwgX2ZuX3Fzb3J0X3N0
cmluZ19jb21wYXJlKTsKKworCWlkeCA9IDE7CisJZm9yKDsgY291bnQgPiAwOyBjb3VudC0t
KSB7CisJCWludCBtb3JlID0gbGltaXQgPiAwICYmIG1hdGNoZXNbMF07CisJCWZvcihpID0g
MDsgbW9yZTsgaWR4KyspIHsKKwkJCW1vcmUgPSArK2kgPCBsaW1pdCAmJiBtYXRjaGVzW2lk
eCArIDFdOworCQkJKHZvaWQpZnByaW50ZihlbC0+ZWxfb3V0ZmlsZSwgIiUtKnMlcyIsIChp
bnQpbWF4LAorCQkJICAgIG1hdGNoZXNbaWR4XSwgbW9yZSA/ICIgIiA6ICIiKTsKKwkJfQor
CQkodm9pZClmcHJpbnRmKGVsLT5lbF9vdXRmaWxlLCAiXG4iKTsKKwl9Cit9CisKKworLyoK
KyAqIENvbXBsZXRlIHRoZSB3b3JkIGF0IG9yIGJlZm9yZSBwb2ludCwKKyAqICd3aGF0X3Rv
X2RvJyBzYXlzIHdoYXQgdG8gZG8gd2l0aCB0aGUgY29tcGxldGlvbi4KKyAqIFx0ICAgbWVh
bnMgZG8gc3RhbmRhcmQgY29tcGxldGlvbi4KKyAqIGA/JyBtZWFucyBsaXN0IHRoZSBwb3Nz
aWJsZSBjb21wbGV0aW9ucy4KKyAqIGAqJyBtZWFucyBpbnNlcnQgYWxsIG9mIHRoZSBwb3Nz
aWJsZSBjb21wbGV0aW9ucy4KKyAqIGAhJyBtZWFucyB0byBkbyBzdGFuZGFyZCBjb21wbGV0
aW9uLCBhbmQgbGlzdCBhbGwgcG9zc2libGUgY29tcGxldGlvbnMgaWYKKyAqIHRoZXJlIGlz
IG1vcmUgdGhhbiBvbmUuCisgKgorICogTm90ZTogJyonIHN1cHBvcnQgaXMgbm90IGltcGxl
bWVudGVkCisgKiAgICAgICAnIScgY291bGQgbmV2ZXIgYmUgaW52b2tlZAorICovCitpbnQK
K2ZuX2NvbXBsZXRlKEVkaXRMaW5lICplbCwKKwljaGFyICooKmNvbXBsZXRfZnVuYykoY29u
c3QgY2hhciAqLCBpbnQpLAorCWNoYXIgKiooKmF0dGVtcHRlZF9jb21wbGV0aW9uX2Z1bmN0
aW9uKShjb25zdCBjaGFyICosIGludCwgaW50KSwKKwljb25zdCBjaGFyICp3b3JkX2JyZWFr
LCBjb25zdCBjaGFyICpzcGVjaWFsX3ByZWZpeGVzLAorCWNvbnN0IGNoYXIgKigqYXBwX2Z1
bmMpKGNvbnN0IGNoYXIgKiksIHNpemVfdCBxdWVyeV9pdGVtcywKKwlpbnQgKmNvbXBsZXRp
b25fdHlwZSwgaW50ICpvdmVyLCBpbnQgKnBvaW50LCBpbnQgKmVuZCwKKwljb25zdCBjaGFy
ICooKmZpbmRfd29yZF9zdGFydF9mdW5jKShjb25zdCBjaGFyICosIGNvbnN0IGNoYXIgKiks
CisJY2hhciAqKCpkZXF1b3RpbmdfZnVuYykoY29uc3QgY2hhciAqKSwKKwljaGFyICooKnF1
b3RpbmdfZnVuYykoY29uc3QgY2hhciAqKSkKK3sKKwljb25zdCBMaW5lSW5mbyAqbGk7CisJ
Y2hhciAqdGVtcDsKKwljaGFyICpkZXF1b3RlZF90ZW1wOworCWNoYXIgKiptYXRjaGVzOwor
CWNvbnN0IGNoYXIgKmN0ZW1wOworCXNpemVfdCBsZW47CisJaW50IHdoYXRfdG9fZG8gPSAn
XHQnOworCWludCByZXR2YWwgPSBDQ19OT1JNOworCisJaWYgKGVsLT5lbF9zdGF0ZS5sYXN0
Y21kID09IGVsLT5lbF9zdGF0ZS50aGlzY21kKQorCQl3aGF0X3RvX2RvID0gJz8nOworCisJ
LyogcmVhZGxpbmUncyBybF9jb21wbGV0ZSgpIGhhcyB0byBiZSB0b2xkIHdoYXQgd2UgZGlk
Li4uICovCisJaWYgKGNvbXBsZXRpb25fdHlwZSAhPSBOVUxMKQorCQkqY29tcGxldGlvbl90
eXBlID0gd2hhdF90b19kbzsKKworCWlmICghY29tcGxldF9mdW5jKQorCQljb21wbGV0X2Z1
bmMgPSBmbl9maWxlbmFtZV9jb21wbGV0aW9uX2Z1bmN0aW9uOworCWlmICghYXBwX2Z1bmMp
CisJCWFwcF9mdW5jID0gYXBwZW5kX2NoYXJfZnVuY3Rpb247CisKKwkvKiBXZSBub3cgbG9v
ayBiYWNrd2FyZHMgZm9yIHRoZSBzdGFydCBvZiBhIGZpbGVuYW1lL3ZhcmlhYmxlIHdvcmQg
Ki8KKwlsaSA9IGVsX2xpbmUoZWwpOworCWlmIChmaW5kX3dvcmRfc3RhcnRfZnVuYykKKwkJ
Y3RlbXAgPSBmaW5kX3dvcmRfc3RhcnRfZnVuYyhsaS0+YnVmZmVyLCBsaS0+Y3Vyc29yKTsK
KwllbHNlIHsKKwkJY3RlbXAgPSBsaS0+Y3Vyc29yOworCQl3aGlsZSAoY3RlbXAgPiBsaS0+
YnVmZmVyCisJCSAgICAmJiAhc3RyY2hyKHdvcmRfYnJlYWssIGN0ZW1wWy0xXSkKKwkJICAg
ICYmICghc3BlY2lhbF9wcmVmaXhlcyB8fCAhc3RyY2hyKHNwZWNpYWxfcHJlZml4ZXMsIGN0
ZW1wWy0xXSkgKSApCisJCQljdGVtcC0tOworCX0KKworCWxlbiA9IGxpLT5jdXJzb3IgLSBj
dGVtcDsKKyNpZiBkZWZpbmVkKF9fU1NQX18pIHx8IGRlZmluZWQoX19TU1BfQUxMX18pCisJ
dGVtcCA9IG1hbGxvYyhzaXplb2YoKnRlbXApICogKGxlbiArIDEpKTsKKwlpZiAodGVtcCA9
PSBOVUxMKQorCQlyZXR1cm4gcmV0dmFsOworI2Vsc2UKKwl0ZW1wID0gYWxsb2NhKHNpemVv
ZigqdGVtcCkgKiAobGVuICsgMSkpOworI2VuZGlmCisJKHZvaWQpc3RybmNweSh0ZW1wLCBj
dGVtcCwgbGVuKTsKKwl0ZW1wW2xlbl0gPSAnXDAnOworCisJaWYgKGRlcXVvdGluZ19mdW5j
KSB7CisJCWRlcXVvdGVkX3RlbXAgPSBkZXF1b3RpbmdfZnVuYyh0ZW1wKTsKKwkJaWYgKGRl
cXVvdGVkX3RlbXAgPT0gTlVMTCkKKwkJCXJldHVybiByZXR2YWw7CisJfSBlbHNlCisJCWRl
cXVvdGVkX3RlbXAgPSBOVUxMOworCisJLyogdGhlc2UgY2FuIGJlIHVzZWQgYnkgZnVuY3Rp
b24gY2FsbGVkIGluIGNvbXBsZXRpb25fbWF0Y2hlcygpICovCisJLyogb3IgKCphdHRlbXB0
ZWRfY29tcGxldGlvbl9mdW5jdGlvbikoKSAqLworCWlmIChwb2ludCAhPSAwKQorCQkqcG9p
bnQgPSAoaW50KShsaS0+Y3Vyc29yIC0gbGktPmJ1ZmZlcik7CisJaWYgKGVuZCAhPSBOVUxM
KQorCQkqZW5kID0gKGludCkobGktPmxhc3RjaGFyIC0gbGktPmJ1ZmZlcik7CisKKwlpZiAo
YXR0ZW1wdGVkX2NvbXBsZXRpb25fZnVuY3Rpb24pIHsKKwkJaW50IGN1cl9vZmYgPSAoaW50
KShsaS0+Y3Vyc29yIC0gbGktPmJ1ZmZlcik7CisJCW1hdGNoZXMgPSAoKmF0dGVtcHRlZF9j
b21wbGV0aW9uX2Z1bmN0aW9uKSAoZGVxdW90ZWRfdGVtcCA/IGRlcXVvdGVkX3RlbXAgOiB0
ZW1wLAorCQkgICAgKGludCkoY3VyX29mZiAtIGxlbiksIGN1cl9vZmYpOworCX0gZWxzZQor
CQltYXRjaGVzID0gMDsKKwlpZiAoIWF0dGVtcHRlZF9jb21wbGV0aW9uX2Z1bmN0aW9uIHx8
IAorCSAgICAob3ZlciAhPSBOVUxMICYmICEqb3ZlciAmJiAhbWF0Y2hlcykpCisJCW1hdGNo
ZXMgPSBjb21wbGV0aW9uX21hdGNoZXMoZGVxdW90ZWRfdGVtcCA/IGRlcXVvdGVkX3RlbXAg
OiB0ZW1wLCBjb21wbGV0X2Z1bmMpOworCisJaWYgKG92ZXIgIT0gTlVMTCkKKwkJKm92ZXIg
PSAwOworCisJaWYgKG1hdGNoZXMpIHsKKwkJaW50IGk7CisJCXNpemVfdCBtYXRjaGVzX251
bSwgbWF4bGVuLCBtYXRjaF9sZW4sIG1hdGNoX2Rpc3BsYXk9MTsKKworCQlyZXR2YWwgPSBD
Q19SRUZSRVNIOworCQkvKgorCQkgKiBPbmx5IHJlcGxhY2UgdGhlIGNvbXBsZXRlZCBzdHJp
bmcgd2l0aCBjb21tb24gcGFydCBvZgorCQkgKiBwb3NzaWJsZSBtYXRjaGVzIGlmIHRoZXJl
IGlzIHBvc3NpYmxlIGNvbXBsZXRpb24uCisJCSAqLworCQlpZiAobWF0Y2hlc1swXVswXSAh
PSAnXDAnKSB7CisJCQljaGFyICpxdW90ZWRfbWF0Y2g7CisJCQlpZiAocXVvdGluZ19mdW5j
KSB7CisJCQkJcXVvdGVkX21hdGNoID0gcXVvdGluZ19mdW5jKG1hdGNoZXNbMF0pOworCQkJ
CWlmIChxdW90ZWRfbWF0Y2ggPT0gTlVMTCkKKwkJCQkJZ290byBmcmVlX21hdGNoZXM7CisJ
CQl9IGVsc2UKKwkJCQlxdW90ZWRfbWF0Y2ggPSBOVUxMOworCisJCQllbF9kZWxldGVzdHIo
ZWwsIChpbnQpIGxlbik7CisJCQllbF9pbnNlcnRzdHIoZWwsIHF1b3RlZF9tYXRjaCA/IHF1
b3RlZF9tYXRjaCA6IG1hdGNoZXNbMF0pOworCisJCQlmcmVlKHF1b3RlZF9tYXRjaCk7CisJ
CX0KKworCQlpZiAod2hhdF90b19kbyA9PSAnPycpCisJCQlnb3RvIGRpc3BsYXlfbWF0Y2hl
czsKKworCQlpZiAobWF0Y2hlc1syXSA9PSBOVUxMICYmIHN0cmNtcChtYXRjaGVzWzBdLCBt
YXRjaGVzWzFdKSA9PSAwKSB7CisJCQkvKgorCQkJICogV2UgZm91bmQgZXhhY3QgbWF0Y2gu
IEFkZCBhIHNwYWNlIGFmdGVyCisJCQkgKiBpdCwgdW5sZXNzIHdlIGRvIGZpbGVuYW1lIGNv
bXBsZXRpb24gYW5kIHRoZQorCQkJICogb2JqZWN0IGlzIGEgZGlyZWN0b3J5LgorCQkJICov
CisJCQllbF9pbnNlcnRzdHIoZWwsICgqYXBwX2Z1bmMpKG1hdGNoZXNbMF0pKTsKKwkJfSBl
bHNlIGlmICh3aGF0X3RvX2RvID09ICchJykgeworICAgIGRpc3BsYXlfbWF0Y2hlczoKKwkJ
CS8qCisJCQkgKiBNb3JlIHRoYW4gb25lIG1hdGNoIGFuZCByZXF1ZXN0ZWQgdG8gbGlzdCBw
b3NzaWJsZQorCQkJICogbWF0Y2hlcy4KKwkJCSAqLworCisJCQlmb3IoaSA9IDEsIG1heGxl
biA9IDA7IG1hdGNoZXNbaV07IGkrKykgeworCQkJCW1hdGNoX2xlbiA9IHN0cmxlbihtYXRj
aGVzW2ldKTsKKwkJCQlpZiAobWF0Y2hfbGVuID4gbWF4bGVuKQorCQkJCQltYXhsZW4gPSBt
YXRjaF9sZW47CisJCQl9CisJCQltYXRjaGVzX251bSA9IGkgLSAxOworCQkJCQorCQkJLyog
bmV3bGluZSB0byBnZXQgb24gbmV4dCBsaW5lIGZyb20gY29tbWFuZCBsaW5lICovCisJCQko
dm9pZClmcHJpbnRmKGVsLT5lbF9vdXRmaWxlLCAiXG4iKTsKKworCQkJLyoKKwkJCSAqIElm
IHRoZXJlIGFyZSB0b28gbWFueSBpdGVtcywgYXNrIHVzZXIgZm9yIGRpc3BsYXkKKwkJCSAq
IGNvbmZpcm1hdGlvbi4KKwkJCSAqLworCQkJaWYgKG1hdGNoZXNfbnVtID4gcXVlcnlfaXRl
bXMpIHsKKwkJCQkodm9pZClmcHJpbnRmKGVsLT5lbF9vdXRmaWxlLAorCQkJCSAgICAiRGlz
cGxheSBhbGwgJXp1IHBvc3NpYmlsaXRpZXM/ICh5IG9yIG4pICIsCisJCQkJICAgIG1hdGNo
ZXNfbnVtKTsKKwkJCQkodm9pZClmZmx1c2goZWwtPmVsX291dGZpbGUpOworCQkJCWlmIChn
ZXRjKHN0ZGluKSAhPSAneScpCisJCQkJCW1hdGNoX2Rpc3BsYXkgPSAwOworCQkJCSh2b2lk
KWZwcmludGYoZWwtPmVsX291dGZpbGUsICJcbiIpOworCQkJfQorCisJCQlpZiAobWF0Y2hf
ZGlzcGxheSkKKwkJCQlmbl9kaXNwbGF5X21hdGNoX2xpc3QoZWwsIG1hdGNoZXMsIG1hdGNo
ZXNfbnVtLAorCQkJCSAgICBtYXhsZW4pOworCQkJcmV0dmFsID0gQ0NfUkVESVNQTEFZOwor
CQl9IGVsc2UgaWYgKG1hdGNoZXNbMF1bMF0pIHsKKwkJCS8qCisJCQkgKiBUaGVyZSB3YXMg
c29tZSBjb21tb24gbWF0Y2gsIGJ1dCB0aGUgbmFtZSB3YXMKKwkJCSAqIG5vdCBjb21wbGV0
ZSBlbm91Z2guIE5leHQgdGFiIHdpbGwgcHJpbnQgcG9zc2libGUKKwkJCSAqIGNvbXBsZXRp
b25zLgorCQkJICovCisJCQllbF9iZWVwKGVsKTsKKwkJfSBlbHNlIHsKKwkJCS8qIGxjZCBp
cyBub3QgYSB2YWxpZCBvYmplY3QgLSBmdXJ0aGVyIHNwZWNpZmljYXRpb24gKi8KKwkJCS8q
IGlzIG5lZWRlZCAqLworCQkJZWxfYmVlcChlbCk7CisJCQlyZXR2YWwgPSBDQ19OT1JNOwor
CQl9CisKK2ZyZWVfbWF0Y2hlczoKKwkJLyogZnJlZSBlbGVtZW50cyBvZiBhcnJheSBhbmQg
dGhlIGFycmF5IGl0c2VsZiAqLworCQlmb3IgKGkgPSAwOyBtYXRjaGVzW2ldOyBpKyspCisJ
CQlmcmVlKG1hdGNoZXNbaV0pOworCQlmcmVlKG1hdGNoZXMpOworCQltYXRjaGVzID0gTlVM
TDsKKwl9CisJZnJlZShkZXF1b3RlZF90ZW1wKTsKKyNpZiBkZWZpbmVkKF9fU1NQX18pIHx8
IGRlZmluZWQoX19TU1BfQUxMX18pCisJZnJlZSh0ZW1wKTsKKyNlbmRpZgorCXJldHVybiBy
ZXR2YWw7Cit9CisKKworLyoKKyAqIGVsLWNvbXBhdGlibGUgd3JhcHBlciBhcm91bmQgcmxf
Y29tcGxldGU7IG5lZWRlZCBmb3Iga2V5IGJpbmRpbmcKKyAqLworLyogQVJHU1VTRUQgKi8K
K3Vuc2lnbmVkIGNoYXIKK19lbF9mbl9jb21wbGV0ZShFZGl0TGluZSAqZWwsIGludCBjaCBf
X2F0dHJpYnV0ZV9fKChfX3VudXNlZF9fKSkpCit7CisJcmV0dXJuICh1bnNpZ25lZCBjaGFy
KWZuX2NvbXBsZXRlKGVsLCBOVUxMLCBOVUxMLAorCSAgICBicmVha19jaGFycywgTlVMTCwg
TlVMTCwgMTAwLAorCSAgICBOVUxMLCBOVUxMLCBOVUxMLCBOVUxMLAorCSAgICBOVUxMLCBO
VUxMLCBOVUxMKTsKK30KKworCitzdGF0aWMgY29uc3QgY2hhciAqCitzaF9maW5kX3dvcmRf
c3RhcnQoY29uc3QgY2hhciAqYnVmZmVyLCBjb25zdCBjaGFyICpjdXJzb3IpCit7CisJY29u
c3QgY2hhciAqd29yZF9zdGFydCA9IGJ1ZmZlcjsKKworCXdoaWxlIChidWZmZXIgPCBjdXJz
b3IpIHsKKwkJaWYgKCpidWZmZXIgPT0gJ1xcJykKKwkJCWJ1ZmZlcisrOworCQllbHNlIGlm
IChzdHJjaHIoYnJlYWtfY2hhcnMsICpidWZmZXIpKQorCQkJd29yZF9zdGFydCA9IGJ1ZmZl
ciArIDE7CisKKwkJYnVmZmVyKys7CisJfQorCisJcmV0dXJuIHdvcmRfc3RhcnQ7Cit9CisK
Kworc3RhdGljIGNoYXIgKgorc2hfcXVvdGUoY29uc3QgY2hhciAqc3RyKQoreworCWNvbnN0
IGNoYXIgKnNyYzsKKwlpbnQgZXh0cmFfbGVuID0gMDsKKwljaGFyICpxdW90ZWRfc3RyLCAq
ZHN0OworCisJaWYgKCpzdHIgPT0gJy0nIHx8ICpzdHIgPT0gJysnKQorCQlleHRyYV9sZW4g
Kz0gMjsKKwlmb3IgKHNyYyA9IHN0cjsgKnNyYyAhPSAnXDAnOyBzcmMrKykKKwkJaWYgKHN0
cmNocihicmVha19jaGFycywgKnNyYykgfHwKKwkJICAgIHN0cmNocihleHRyYV9xdW90ZV9j
aGFycywgKnNyYykpCisJCQlleHRyYV9sZW4rKzsKKworCXF1b3RlZF9zdHIgPSBtYWxsb2Mo
c2l6ZW9mKCpxdW90ZWRfc3RyKSAqCisJICAgIChzdHJsZW4oc3RyKSArIGV4dHJhX2xlbiAr
IDEpKTsKKwlpZiAocXVvdGVkX3N0ciA9PSBOVUxMKQorCQlyZXR1cm4gTlVMTDsKKworCWRz
dCA9IHF1b3RlZF9zdHI7CisJaWYgKCpzdHIgPT0gJy0nIHx8ICpzdHIgPT0gJysnKQorCQkq
ZHN0KysgPSAnLicsICpkc3QrKyA9ICcvJzsKKwlmb3IgKHNyYyA9IHN0cjsgKnNyYyAhPSAn
XDAnOyBzcmMrKykgeworCQlpZiAoc3RyY2hyKGJyZWFrX2NoYXJzLCAqc3JjKSB8fAorCQkg
ICAgc3RyY2hyKGV4dHJhX3F1b3RlX2NoYXJzLCAqc3JjKSkKKwkJCSpkc3QrKyA9ICdcXCc7
CisJCSpkc3QrKyA9ICpzcmM7CisJfQorCSpkc3QgPSAnXDAnOworCisJcmV0dXJuIHF1b3Rl
ZF9zdHI7Cit9CisKKworc3RhdGljIGNoYXIgKgorc2hfZGVxdW90ZShjb25zdCBjaGFyICpz
dHIpCit7CisJY2hhciAqZGVxdW90ZWRfc3RyLCAqZHN0OworCisJLyogc2F2ZSBleHRyYSBz
cGFjZSB0byByZXBsYWNlIFx+IHdpdGggLi9+ICovCisJZGVxdW90ZWRfc3RyID0gbWFsbG9j
KHNpemVvZigqZGVxdW90ZWRfc3RyKSAqIChzdHJsZW4oc3RyKSArIDEgKyAxKSk7CisJaWYg
KGRlcXVvdGVkX3N0ciA9PSBOVUxMKQorCQlyZXR1cm4gTlVMTDsKKworCWRzdCA9IGRlcXVv
dGVkX3N0cjsKKworCS8qIGRlcXVvdGUgXH4gYXQgc3RhcnQgYXMgLi9+ICovCisJaWYgKCpz
dHIgPT0gJ1xcJyAmJiBzdHJbMV0gPT0gJ34nKSB7CisJCXN0cisrOworCQkqZHN0KysgPSAn
Lic7CisJCSpkc3QrKyA9ICcvJzsKKwl9CisKKwl3aGlsZSAoKnN0cikgeworCQlpZiAoKnN0
ciA9PSAnXFwnKQorCQkJc3RyKys7CisJCWlmICgqc3RyKQorCQkJKmRzdCsrID0gKnN0cisr
OworCX0KKwkqZHN0ID0gJ1wwJzsKKworCXJldHVybiBkZXF1b3RlZF9zdHI7Cit9CisKKwor
LyoKKyAqIGNvbXBsZXRpb24gZnVuY3Rpb24gdXNpbmcgc2ggcXVvdGluZyBydWxlczsgZm9y
IGtleSBiaW5kaW5nCisgKi8KKy8qIEFSR1NVU0VEICovCit1bnNpZ25lZCBjaGFyCitfZWxf
Zm5fc2hfY29tcGxldGUoRWRpdExpbmUgKmVsLCBpbnQgY2ggX19hdHRyaWJ1dGVfXygoX191
bnVzZWRfXykpKQoreworCXJldHVybiAodW5zaWduZWQgY2hhcilmbl9jb21wbGV0ZShlbCwg
TlVMTCwgTlVMTCwKKwkgICAgYnJlYWtfY2hhcnMsIE5VTEwsIE5VTEwsIDEwMCwKKwkgICAg
TlVMTCwgTlVMTCwgTlVMTCwgTlVMTCwKKwkgICAgc2hfZmluZF93b3JkX3N0YXJ0LCBzaF9k
ZXF1b3RlLCBzaF9xdW90ZSk7Cit9Cg==
--------------020203000205020600080704
Content-Type: text/plain;
 name="head_lib_libedit_filecomplete.h"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="head_lib_libedit_filecomplete.h"

ZGlmZiAtdXJOIHN0YWJsZS84L2xpYi9saWJlZGl0L2ZpbGVjb21wbGV0ZS5oIGhlYWQvbGli
L2xpYmVkaXQvZmlsZWNvbXBsZXRlLmgKLS0tIHN0YWJsZS84L2xpYi9saWJlZGl0L2ZpbGVj
b21wbGV0ZS5oCTE5NjktMTItMzEgMTk6MDA6MDAuMDAwMDAwMDAwIC0wNTAwCisrKyBoZWFk
L2xpYi9saWJlZGl0L2ZpbGVjb21wbGV0ZS5oCTIwMTAtMDYtMTUgMTc6MzQ6NTcuNTM0MzMz
MDAwIC0wNDAwCkBAIC0wLDAgKzEsNDggQEAKKy8qLQorICogQ29weXJpZ2h0IChjKSAxOTk3
IFRoZSBOZXRCU0QgRm91bmRhdGlvbiwgSW5jLgorICogQWxsIHJpZ2h0cyByZXNlcnZlZC4K
KyAqCisgKiBUaGlzIGNvZGUgaXMgZGVyaXZlZCBmcm9tIHNvZnR3YXJlIGNvbnRyaWJ1dGVk
IHRvIFRoZSBOZXRCU0QgRm91bmRhdGlvbgorICogYnkgSmFyb21pciBEb2xlY2VrLgorICoK
KyAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMs
IHdpdGggb3Igd2l0aG91dAorICogbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3Zp
ZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCisgKiBhcmUgbWV0OgorICogMS4g
UmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBj
b3B5cmlnaHQKKyAqICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRo
ZSBmb2xsb3dpbmcgZGlzY2xhaW1lci4KKyAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5h
cnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0CisgKiAgICBub3Rp
Y2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWlt
ZXIgaW4gdGhlCisgKiAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMg
cHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgorICoKKyAqIFRISVMgU09GVFdBUkUg
SVMgUFJPVklERUQgQlkgVEhFIE5FVEJTRCBGT1VOREFUSU9OLCBJTkMuIEFORCBDT05UUklC
VVRPUlMKKyAqIGBgQVMgSVMnJyBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5U
SUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRAorICogVE8sIFRIRSBJTVBMSUVEIFdB
UlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VM
QVIKKyAqIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuICBJTiBOTyBFVkVOVCBTSEFMTCBUSEUg
Rk9VTkRBVElPTiBPUiBDT05UUklCVVRPUlMKKyAqIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVD
VCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IKKyAqIENP
TlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBS
T0NVUkVNRU5UIE9GCisgKiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOyBMT1NTIE9G
IFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MKKyAqIElOVEVSUlVQVElPTikg
SE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVS
IElOCisgKiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5H
IE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKQorICogQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBP
RiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUKKyAq
IFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLgorICoKKyAqCSROZXRCU0Q6IGZpbGVjb21w
bGV0ZS5oLHYgMS45IDIwMDkvMTIvMzAgMjI6Mzc6NDAgY2hyaXN0b3MgRXhwICQKKyAqICRG
cmVlQlNEOiBoZWFkL2xpYi9saWJlZGl0L2ZpbGVjb21wbGV0ZS5oIDIwOTIxOSAyMDEwLTA2
LTE1IDIxOjM0OjU3WiBqaWxsZXMgJAorICovCisjaWZuZGVmIF9GSUxFQ09NUExFVEVfSF8K
KyNkZWZpbmUgX0ZJTEVDT01QTEVURV9IXworCitpbnQgZm5fY29tcGxldGUoRWRpdExpbmUg
KiwKKyAgICBjaGFyICooKikoY29uc3QgY2hhciAqLCBpbnQpLAorICAgIGNoYXIgKiooKiko
Y29uc3QgY2hhciAqLCBpbnQsIGludCksCisgICAgY29uc3QgY2hhciAqLCBjb25zdCBjaGFy
ICosIGNvbnN0IGNoYXIgKigqKShjb25zdCBjaGFyICopLCBzaXplX3QsCisgICAgaW50ICos
IGludCAqLCBpbnQgKiwgaW50ICosCisgICAgY29uc3QgY2hhciAqKCopKGNvbnN0IGNoYXIg
KiwgY29uc3QgY2hhciAqKSwKKyAgICBjaGFyICooKikoY29uc3QgY2hhciAqKSwKKyAgICBj
aGFyICooKikoY29uc3QgY2hhciAqKSk7CisKK3ZvaWQgZm5fZGlzcGxheV9tYXRjaF9saXN0
KEVkaXRMaW5lICosIGNoYXIgKiosIHNpemVfdCwgc2l6ZV90KTsKK2NoYXIgKmZuX3RpbGRl
X2V4cGFuZChjb25zdCBjaGFyICopOworY2hhciAqZm5fZmlsZW5hbWVfY29tcGxldGlvbl9m
dW5jdGlvbihjb25zdCBjaGFyICosIGludCk7CisKKyNlbmRpZgo=
--------------020203000205020600080704
Content-Type: text/x-patch;
 name="sh-tab-complete-stable8.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="sh-tab-complete-stable8.diff"

diff -urN stable/8/bin/sh/Makefile head/bin/sh/Makefile
--- stable/8/bin/sh/Makefile	2007-11-17 20:53:07.000000000 -0500
+++ head/bin/sh/Makefile	2007-11-17 20:53:07.000000000 -0500
@@ -1,5 +1,5 @@
 #	@(#)Makefile	8.4 (Berkeley) 5/5/95
-# $FreeBSD: stable/8/bin/sh/Makefile 173718 2007-11-18 01:53:07Z jb $
+# $FreeBSD: head/bin/sh/Makefile 173718 2007-11-18 01:53:07Z jb $
 
 PROG=	sh
 INSTALLFLAGS= -S
diff -urN stable/8/bin/sh/TOUR head/bin/sh/TOUR
--- stable/8/bin/sh/TOUR	2006-04-16 07:54:01.000000000 -0400
+++ head/bin/sh/TOUR	2006-04-16 07:54:01.000000000 -0400
@@ -1,5 +1,5 @@
 #	@(#)TOUR	8.1 (Berkeley) 5/31/93
-# $FreeBSD: stable/8/bin/sh/TOUR 157789 2006-04-16 11:54:01Z schweikh $
+# $FreeBSD: head/bin/sh/TOUR 157789 2006-04-16 11:54:01Z schweikh $
 
 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 -urN stable/8/bin/sh/alias.c head/bin/sh/alias.c
--- stable/8/bin/sh/alias.c	2009-06-01 06:50:17.801753000 -0400
+++ head/bin/sh/alias.c	2009-12-24 13:41:14.411055000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/alias.c 193221 2009-06-01 10:50:17Z rse $");
+__FBSDID("$FreeBSD: head/bin/sh/alias.c 200956 2009-12-24 18:41:14Z jilles $");
 
 #include <stdlib.h>
 #include "shell.h"
@@ -52,13 +52,13 @@
 STATIC struct alias *atab[ATABSIZE];
 STATIC int aliases;
 
-STATIC void setalias(char *, char *);
+STATIC void setalias(const char *, const char *);
 STATIC int unalias(const char *);
 STATIC struct alias **hashalias(const char *);
 
 STATIC
 void
-setalias(char *name, char *val)
+setalias(const char *name, const char *val)
 {
 	struct alias *ap, **app;
 
@@ -176,7 +176,7 @@
 }
 
 struct alias *
-lookupalias(char *name, int check)
+lookupalias(const char *name, int check)
 {
 	struct alias *ap = *hashalias(name);
 
diff -urN stable/8/bin/sh/alias.h head/bin/sh/alias.h
--- stable/8/bin/sh/alias.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/alias.h	2009-12-24 13:41:14.411055000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)alias.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/alias.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/alias.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 #define ALIASINUSE	1
@@ -42,7 +42,7 @@
 	int flag;
 };
 
-struct alias *lookupalias(char *, int);
+struct alias *lookupalias(const char *, int);
 int aliascmd(int, char **);
 int unaliascmd(int, char **);
 void rmaliases(void);
diff -urN stable/8/bin/sh/arith.h head/bin/sh/arith.h
--- stable/8/bin/sh/arith.h	2008-04-27 16:46:45.000000000 -0400
+++ head/bin/sh/arith.h	2009-12-24 13:41:14.411055000 -0500
@@ -27,15 +27,15 @@
  * SUCH DAMAGE.
  *
  *	@(#)arith.h	1.1 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/arith.h 178625 2008-04-27 20:46:45Z stefanf $
+ * $FreeBSD: head/bin/sh/arith.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 #include "shell.h"
 
 #define DIGITS(var) (3 + (2 + CHAR_BIT * sizeof((var))) / 3)
 
-extern char *arith_buf, *arith_startbuf;
+extern const char *arith_buf, *arith_startbuf;
 
-arith_t arith(char *);
+arith_t arith(const char *);
 void arith_lex_reset(void);
 int expcmd(int, char **);
diff -urN stable/8/bin/sh/arith.y head/bin/sh/arith.y
--- stable/8/bin/sh/arith.y	2008-04-27 16:46:45.000000000 -0400
+++ head/bin/sh/arith.y	2010-04-25 16:43:19.108643000 -0400
@@ -38,7 +38,7 @@
 #endif /* not lint */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/arith.y 178625 2008-04-27 20:46:45Z stefanf $");
+__FBSDID("$FreeBSD: head/bin/sh/arith.y 207206 2010-04-25 20:43:19Z jilles $");
 
 #include <limits.h>
 #include <stdio.h>
@@ -85,9 +85,9 @@
 	ARITH_LPAREN expr ARITH_RPAREN
 		{ $$ = $2; } |
 	expr ARITH_OR expr
-		{ $$ = $1 ? $1 : $3 ? $3 : 0; } |
+		{ $$ = $1 || $3; } |
 	expr ARITH_AND expr
-		{ $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } |
+		{ $$ = $1 && $3; } |
 	expr ARITH_BOR expr
 		{ $$ = $1 | $3; } |
 	expr ARITH_BXOR expr
@@ -265,7 +265,7 @@
 #define YYPARSE_PARAM_TYPE arith_t *
 #define YYPARSE_PARAM result
 
-char *arith_buf, *arith_startbuf;
+const char *arith_buf, *arith_startbuf;
 
 int yylex(void);
 int yyparse(YYPARSE_PARAM_TYPE);
@@ -284,10 +284,12 @@
 }
 
 arith_t
-arith(char *s)
+arith(const char *s)
 {
 	arith_t result;
+	struct stackmark smark;
 
+	setstackmark(&smark);
 	arith_buf = arith_startbuf = s;
 
 	INTOFF;
@@ -295,11 +297,13 @@
 	arith_lex_reset();	/* Reprime lex. */
 	INTON;
 
+	popstackmark(&smark);
+
 	return result;
 }
 
 static void
-yyerror(char *s)
+yyerror(const char *s)
 {
 
 	yyerrok;
@@ -314,7 +318,7 @@
 int
 expcmd(int argc, char **argv)
 {
-	char *p;
+	const char *p;
 	char *concat;
 	char **ap;
 	arith_t i;
@@ -354,7 +358,7 @@
 	printf("%d\n", exp(argv[1]));
 }
 
-error(char *s)
+error(const char *s)
 {
 	fprintf(stderr, "exp: %s\n", s);
 	exit(1);
diff -urN stable/8/bin/sh/arith_lex.l head/bin/sh/arith_lex.l
--- stable/8/bin/sh/arith_lex.l	2009-12-06 17:01:45.088880000 -0500
+++ head/bin/sh/arith_lex.l	2010-04-25 16:43:19.108643000 -0400
@@ -38,7 +38,7 @@
 #endif /* not lint */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/arith_lex.l 200188 2009-12-06 22:01:45Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/arith_lex.l 207206 2010-04-25 20:43:19Z jilles $");
 
 #include <string.h>
 
@@ -51,13 +51,6 @@
 
 int yylex(void);
 
-struct varname
-{
-	struct varname *next;
-	char name[1];
-};
-static struct varname *varnames;
-
 #undef YY_INPUT
 #define YY_INPUT(buf,result,max) \
 	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
@@ -87,14 +80,11 @@
 			 * If variable doesn't exist, we should initialize
 			 * it to zero.
 			 */
-			struct varname *temp;
+			char *temp;
 			if (lookupvar(yytext) == NULL)
 				setvarsafe(yytext, "0", 0);
-			temp = ckmalloc(sizeof(struct varname) +
-			    strlen(yytext));
-			temp->next = varnames;
-			varnames = temp;
-			yylval.s_value = strcpy(temp->name, yytext);
+			temp = stalloc(strlen(yytext) + 1);
+			yylval.s_value = strcpy(temp, yytext);
 
 			return ARITH_VAR;
 		}
@@ -140,15 +130,5 @@
 void
 arith_lex_reset(void)
 {
-	struct varname *name, *next;
-
 	YY_NEW_FILE;
-
-	name = varnames;
-	while (name != NULL) {
-		next = name->next;
-		ckfree(name);
-		name = next;
-	}
-	varnames = NULL;
 }
diff -urN stable/8/bin/sh/bltin/bltin.h head/bin/sh/bltin/bltin.h
--- stable/8/bin/sh/bltin/bltin.h	2005-08-13 11:04:30.000000000 -0400
+++ head/bin/sh/bltin/bltin.h	2005-08-13 11:04:30.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)bltin.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/bltin/bltin.h 149025 2005-08-13 15:04:30Z stefanf $
+ * $FreeBSD: head/bin/sh/bltin/bltin.h 149025 2005-08-13 15:04:30Z stefanf $
  */
 
 /*
diff -urN stable/8/bin/sh/bltin/echo.1 head/bin/sh/bltin/echo.1
--- stable/8/bin/sh/bltin/echo.1	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/bltin/echo.1	2005-01-10 03:39:26.000000000 -0500
@@ -31,7 +31,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)echo.1	8.2 (Berkeley) 5/4/95
-.\" $FreeBSD: stable/8/bin/sh/bltin/echo.1 139969 2005-01-10 08:39:26Z imp $
+.\" $FreeBSD: head/bin/sh/bltin/echo.1 139969 2005-01-10 08:39:26Z imp $
 .\"
 .Dd May 4, 1995
 .Dt ECHO 1
diff -urN stable/8/bin/sh/bltin/echo.c head/bin/sh/bltin/echo.c
--- stable/8/bin/sh/bltin/echo.c	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/bltin/echo.c	2004-04-06 16:06:54.000000000 -0400
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/bltin/echo.c 127958 2004-04-06 20:06:54Z markm $");
+__FBSDID("$FreeBSD: head/bin/sh/bltin/echo.c 127958 2004-04-06 20:06:54Z markm $");
 
 /*
  * Echo command.
diff -urN stable/8/bin/sh/builtins.def head/bin/sh/builtins.def
--- stable/8/bin/sh/builtins.def	2006-04-02 14:43:33.000000000 -0400
+++ head/bin/sh/builtins.def	2006-04-02 14:43:33.000000000 -0400
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)builtins.def	8.4 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/builtins.def 157413 2006-04-02 18:43:33Z stefanf $
+# $FreeBSD: head/bin/sh/builtins.def 157413 2006-04-02 18:43:33Z stefanf $
 
 #
 # This file lists all the builtin commands.  The first column is the name
diff -urN stable/8/bin/sh/cd.c head/bin/sh/cd.c
--- stable/8/bin/sh/cd.c	2010-05-16 06:01:06.549498000 -0400
+++ head/bin/sh/cd.c	2010-04-17 10:35:46.799348000 -0400
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/cd.c 208134 2010-05-16 10:01:06Z stefanf $");
+__FBSDID("$FreeBSD: head/bin/sh/cd.c 206759 2010-04-17 14:35:46Z jilles $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -70,6 +70,7 @@
 STATIC char *getcomponent(void);
 STATIC char *findcwd(char *);
 STATIC void updatepwd(char *);
+STATIC char *getpwd(void);
 STATIC char *getpwd2(void);
 
 STATIC char *curdir = NULL;	/* current working directory */
@@ -79,8 +80,8 @@
 int
 cdcmd(int argc, char **argv)
 {
-	char *dest;
-	char *path;
+	const char *dest;
+	const char *path;
 	char *p;
 	struct stat statb;
 	int ch, phys, print = 0;
@@ -351,7 +352,7 @@
 /*
  * Get the current directory and cache the result in curdir.
  */
-char *
+STATIC char *
 getpwd(void)
 {
 	char *p;
@@ -374,7 +375,6 @@
 STATIC char *
 getpwd2(void)
 {
-	struct stat stdot, stpwd;
 	char *pwd;
 	int i;
 
@@ -387,12 +387,29 @@
 			break;
 	}
 
-	pwd = getenv("PWD");
+	return NULL;
+}
+
+/*
+ * Initialize PWD in a new shell.
+ * If the shell is interactive, we need to warn if this fails.
+ */
+void
+pwd_init(int warn)
+{
+	char *pwd;
+	struct stat stdot, stpwd;
+
+	pwd = lookupvar("PWD");
 	if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
 	    stat(pwd, &stpwd) != -1 &&
 	    stdot.st_dev == stpwd.st_dev &&
 	    stdot.st_ino == stpwd.st_ino) {
-		return pwd;
+		if (curdir)
+			ckfree(curdir);
+		curdir = savestr(pwd);
 	}
-	return NULL;
+	if (getpwd() == NULL && warn)
+		out2fmt_flush("sh: cannot determine working directory\n");
+	setvar("PWD", curdir, VEXPORT);
 }
diff -urN stable/8/bin/sh/cd.h head/bin/sh/cd.h
--- stable/8/bin/sh/cd.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/cd.h	2010-04-17 10:35:46.799348000 -0400
@@ -26,9 +26,9 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: stable/8/bin/sh/cd.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/cd.h 206759 2010-04-17 14:35:46Z jilles $
  */
 
-char	*getpwd(void);
+void	 pwd_init(int);
 int	 cdcmd (int, char **);
 int	 pwdcmd(int, char **);
diff -urN stable/8/bin/sh/error.c head/bin/sh/error.c
--- stable/8/bin/sh/error.c	2006-02-04 09:37:50.000000000 -0500
+++ head/bin/sh/error.c	2010-01-01 13:17:46.488302000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/error.c 155301 2006-02-04 14:37:50Z schweikh $");
+__FBSDID("$FreeBSD: head/bin/sh/error.c 201366 2010-01-01 18:17:46Z jilles $");
 
 /*
  * Errors and exceptions.
@@ -67,17 +67,21 @@
 char *commandname;
 
 
-static void exverror(int, const char *, va_list) __printf0like(2, 0);
+static void exverror(int, const char *, va_list) __printf0like(2, 0) __dead2;
 
 /*
  * Called to raise an exception.  Since C doesn't include exceptions, we
  * just do a longjmp to the exception handler.  The type of exception is
  * stored in the global variable "exception".
+ *
+ * Interrupts are disabled; they should be reenabled when the exception is
+ * caught.
  */
 
 void
 exraise(int e)
 {
+	INTOFF;
 	if (handler == NULL)
 		abort();
 	exception = e;
@@ -138,8 +142,15 @@
 static void
 exverror(int cond, const char *msg, va_list ap)
 {
-	CLEAR_PENDING_INT;
-	INTOFF;
+	/*
+	 * An interrupt trumps an error.  Certain places catch error
+	 * exceptions or transform them to a plain nonzero exit code
+	 * in child processes, and if an error exception can be handled,
+	 * an interrupt can be handled as well.
+	 *
+	 * exraise() will disable interrupts for the exception handler.
+	 */
+	FORCEINTON;
 
 #ifdef DEBUG
 	if (msg)
@@ -149,8 +160,8 @@
 #endif
 	if (msg) {
 		if (commandname)
-			outfmt(&errout, "%s: ", commandname);
-		doformat(&errout, msg, ap);
+			outfmt(out2, "%s: ", commandname);
+		doformat(out2, msg, ap);
 		out2c('\n');
 	}
 	flushall();
diff -urN stable/8/bin/sh/error.h head/bin/sh/error.h
--- stable/8/bin/sh/error.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/error.h	2009-12-24 15:55:14.498557000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)error.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/error.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/error.h 200967 2009-12-24 20:55:14Z jilles $
  */
 
 /*
@@ -72,14 +72,16 @@
 
 #define INTOFF suppressint++
 #define INTON { if (--suppressint == 0 && intpending) onint(); }
+#define is_int_on() suppressint
+#define SETINTON(s) suppressint = (s)
 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
 #define CLEAR_PENDING_INT intpending = 0
 #define int_pending() intpending
 
-void exraise(int);
+void exraise(int) __dead2;
 void onint(void);
-void error(const char *, ...) __printf0like(1, 2);
-void exerror(int, const char *, ...) __printf0like(2, 3);
+void error(const char *, ...) __printf0like(1, 2) __dead2;
+void exerror(int, const char *, ...) __printf0like(2, 3) __dead2;
 
 
 /*
diff -urN stable/8/bin/sh/eval.c head/bin/sh/eval.c
--- stable/8/bin/sh/eval.c	2009-10-11 12:35:12.561852000 -0400
+++ head/bin/sh/eval.c	2010-05-28 18:40:24.781829000 -0400
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/eval.c 197959 2009-10-11 16:35:12Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/eval.c 208630 2010-05-28 22:40:24Z jilles $");
 
 #include <paths.h>
 #include <signal.h>
@@ -74,7 +74,7 @@
 #endif
 
 
-MKINIT int evalskip;		/* set if we are skipping commands */
+int evalskip;			/* set if we are skipping commands */
 STATIC int skipcount;		/* number of levels to skip */
 MKINIT int loopnest;		/* current loop nesting level */
 int funcnest;			/* depth of function calls */
@@ -91,6 +91,7 @@
 STATIC void evalfor(union node *, int);
 STATIC void evalcase(union node *, int);
 STATIC void evalsubshell(union node *, int);
+STATIC void evalredir(union node *, int);
 STATIC void expredir(union node *);
 STATIC void evalpipe(union node *);
 STATIC void evalcommand(union node *, int, struct backcmd *);
@@ -221,10 +222,7 @@
 		evaltree(n->nbinary.ch2, flags);
 		break;
 	case NREDIR:
-		expredir(n->nredir.redirect);
-		redirect(n->nredir.redirect, REDIR_PUSH);
-		evaltree(n->nredir.n, flags);
-		popredir();
+		evalredir(n, flags);
 		break;
 	case NSUBSHELL:
 		evalsubshell(n, flags);
@@ -407,8 +405,7 @@
 			flags &=~ EV_TESTED;
 		redirect(n->nredir.redirect, 0);
 		evaltree(n->nredir.n, flags | EV_EXIT);	/* never returns */
-	}
-	if (! backgnd) {
+	} else if (! backgnd) {
 		INTOFF;
 		exitstatus = waitforjob(jp, (int *)NULL);
 		INTON;
@@ -416,6 +413,46 @@
 }
 
 
+/*
+ * Evaluate a redirected compound command.
+ */
+
+STATIC void
+evalredir(union node *n, int flags)
+{
+	struct jmploc jmploc;
+	struct jmploc *savehandler;
+	volatile int in_redirect = 1;
+
+	expredir(n->nredir.redirect);
+	savehandler = handler;
+	if (setjmp(jmploc.loc)) {
+		int e;
+
+		handler = savehandler;
+		e = exception;
+		if (e == EXERROR || e == EXEXEC) {
+			popredir();
+			if (in_redirect) {
+				exitstatus = 2;
+				return;
+			}
+		}
+		longjmp(handler->loc, 1);
+	} else {
+		INTOFF;
+		handler = &jmploc;
+		redirect(n->nredir.redirect, REDIR_PUSH);
+		in_redirect = 0;
+		INTON;
+		evaltree(n->nredir.n, flags);
+	}
+	INTOFF;
+	handler = savehandler;
+	popredir();
+	INTON;
+}
+
 
 /*
  * Compute the names of the files in a redirection list.
@@ -593,10 +630,12 @@
 	char *savecmdname;
 	struct shparam saveparam;
 	struct localvar *savelocalvars;
+	struct parsefile *savetopfile;
 	volatile int e;
 	char *lastarg;
 	int realstatus;
 	int do_clearcmdentry;
+	char *path = pathval();
 
 	/* First expand the arguments. */
 	TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
@@ -646,7 +685,7 @@
 		out2str(ps4val());
 		for (sp = varlist.list ; sp ; sp = sp->next) {
 			if (sep != 0)
-				outc(' ', &errout);
+				out2c(' ');
 			p = sp->text;
 			while (*p != '=' && *p != '\0')
 				out2c(*p++);
@@ -658,7 +697,7 @@
 		}
 		for (sp = arglist.list ; sp ; sp = sp->next) {
 			if (sep != 0)
-				outc(' ', &errout);
+				out2c(' ');
 			/* Disambiguate command looking like assignment. */
 			if (sp == arglist.list &&
 					strchr(sp->text, '=') != NULL &&
@@ -670,7 +709,7 @@
 				out2qstr(sp->text);
 			sep = ' ';
 		}
-		outc('\n', &errout);
+		out2c('\n');
 		flushout(&errout);
 	}
 
@@ -679,10 +718,10 @@
 		/* Variable assignment(s) without command */
 		cmdentry.cmdtype = CMDBUILTIN;
 		cmdentry.u.index = BLTINCMD;
-		cmdentry.special = 1;
+		cmdentry.special = 0;
 	} else {
 		static const char PATH[] = "PATH=";
-		char *path = pathval();
+		int cmd_flags = 0, bltinonly = 0;
 
 		/*
 		 * Modify the command lookup path, if a PATH= assignment
@@ -713,42 +752,79 @@
 				do_clearcmdentry = 1;
 			}
 
-		find_command(argv[0], &cmdentry, 1, path);
-		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
-			exitstatus = 127;
-			flushout(&errout);
-			return;
-		}
-		/* implement the bltin builtin here */
-		if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
-			for (;;) {
-				argv++;
-				if (--argc == 0)
+		for (;;) {
+			if (bltinonly) {
+				cmdentry.u.index = find_builtin(*argv, &cmdentry.special);
+				if (cmdentry.u.index < 0) {
+					cmdentry.u.index = BLTINCMD;
+					argv--;
+					argc++;
 					break;
-				if ((cmdentry.u.index = find_builtin(*argv,
-				    &cmdentry.special)) < 0) {
-					outfmt(&errout, "%s: not found\n", *argv);
-					exitstatus = 127;
-					flushout(&errout);
-					return;
 				}
-				if (cmdentry.u.index != BLTINCMD)
+			} else
+				find_command(argv[0], &cmdentry, cmd_flags, path);
+			/* implement the bltin and command builtins here */
+			if (cmdentry.cmdtype != CMDBUILTIN)
+				break;
+			if (cmdentry.u.index == BLTINCMD) {
+				if (argc == 1)
 					break;
-			}
+				argv++;
+				argc--;
+				bltinonly = 1;
+			} else if (cmdentry.u.index == COMMANDCMD) {
+				if (argc == 1)
+					break;
+				if (!strcmp(argv[1], "-p")) {
+					if (argc == 2)
+						break;
+					if (argv[2][0] == '-') {
+						if (strcmp(argv[2], "--"))
+							break;
+						if (argc == 3)
+							break;
+						argv += 3;
+						argc -= 3;
+					} else {
+						argv += 2;
+						argc -= 2;
+					}
+					path = _PATH_STDPATH;
+					clearcmdentry(0);
+					do_clearcmdentry = 1;
+				} else if (!strcmp(argv[1], "--")) {
+					if (argc == 2)
+						break;
+					argv += 2;
+					argc -= 2;
+				} else if (argv[1][0] == '-')
+					break;
+				else {
+					argv++;
+					argc--;
+				}
+				cmd_flags |= DO_NOFUNC;
+				bltinonly = 0;
+			} else
+				break;
 		}
+		/*
+		 * Special builtins lose their special properties when
+		 * called via 'command'.
+		 */
+		if (cmd_flags & DO_NOFUNC)
+			cmdentry.special = 0;
 	}
 
 	/* Fork off a child process if necessary. */
 	if (cmd->ncmd.backgnd
-	 || (cmdentry.cmdtype == CMDNORMAL
+	 || ((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN)
 	    && ((flags & EV_EXIT) == 0 || have_traps()))
 	 || ((flags & EV_BACKCMD) != 0
 	    && (cmdentry.cmdtype != CMDBUILTIN
 		 || cmdentry.u.index == CDCMD
 		 || cmdentry.u.index == DOTCMD
-		 || cmdentry.u.index == EVALCMD))
-	 || (cmdentry.cmdtype == CMDBUILTIN &&
-	    cmdentry.u.index == COMMANDCMD)) {
+		 || cmdentry.u.index == EVALCMD))) {
 		jp = makejob(cmd, 1);
 		mode = cmd->ncmd.backgnd;
 		if (flags & EV_BACKCMD) {
@@ -775,7 +851,6 @@
 #ifdef DEBUG
 		trputs("Shell function:  ");  trargs(argv);
 #endif
-		redirect(cmd->ncmd.redirect, REDIR_PUSH);
 		saveparam = shellparam;
 		shellparam.malloc = 0;
 		shellparam.reset = 1;
@@ -786,7 +861,6 @@
 		savelocalvars = localvars;
 		localvars = NULL;
 		reffunc(cmdentry.u.func);
-		INTON;
 		savehandler = handler;
 		if (setjmp(jmploc.loc)) {
 			if (exception == EXSHELLPROC)
@@ -794,23 +868,27 @@
 			else {
 				freeparam(&shellparam);
 				shellparam = saveparam;
+				if (exception == EXERROR || exception == EXEXEC)
+					popredir();
 			}
 			unreffunc(cmdentry.u.func);
 			poplocalvars();
 			localvars = savelocalvars;
+			funcnest--;
 			handler = savehandler;
 			longjmp(handler->loc, 1);
 		}
 		handler = &jmploc;
+		funcnest++;
+		redirect(cmd->ncmd.redirect, REDIR_PUSH);
+		INTON;
 		for (sp = varlist.list ; sp ; sp = sp->next)
 			mklocal(sp->text);
-		funcnest++;
 		exitstatus = oexitstatus;
 		if (flags & EV_TESTED)
 			evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
 		else
 			evaltree(getfuncnode(cmdentry.u.func), 0);
-		funcnest--;
 		INTOFF;
 		unreffunc(cmdentry.u.func);
 		poplocalvars();
@@ -818,6 +896,7 @@
 		freeparam(&shellparam);
 		shellparam = saveparam;
 		handler = savehandler;
+		funcnest--;
 		popredir();
 		INTON;
 		if (evalskip == SKIPFUNC) {
@@ -836,8 +915,10 @@
 			memout.nextc = memout.buf;
 			memout.bufsize = 64;
 			mode |= REDIR_BACKQ;
+			cmdentry.special = 0;
 		}
 		savecmdname = commandname;
+		savetopfile = getcurrentfile();
 		cmdenviron = varlist.list;
 		e = -1;
 		savehandler = handler;
@@ -848,15 +929,25 @@
 		}
 		handler = &jmploc;
 		redirect(cmd->ncmd.redirect, mode);
+		/*
+		 * If there is no command word, redirection errors should
+		 * not be fatal but assignment errors should.
+		 */
+		if (argc == 0 && !(flags & EV_BACKCMD))
+			cmdentry.special = 1;
 		if (cmdentry.special)
 			listsetvar(cmdenviron);
+		if (argc > 0)
+			bltinsetlocale();
 		commandname = argv[0];
 		argptr = argv + 1;
-		optptr = NULL;			/* initialize nextopt */
+		nextopt_optptr = NULL;		/* initialize nextopt */
 		builtin_flags = flags;
 		exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
 		flushall();
 cmddone:
+		if (argc > 0)
+			bltinunsetlocale();
 		cmdenviron = NULL;
 		out1 = &output;
 		out2 = &errout;
@@ -868,29 +959,31 @@
 			}
 		}
 		handler = savehandler;
-		if (e != -1) {
-			if ((e != EXERROR && e != EXEXEC)
-			    || cmdentry.special)
-				exraise(e);
-			FORCEINTON;
-		}
-		if (cmdentry.u.index != EXECCMD)
-			popredir();
 		if (flags == EV_BACKCMD) {
 			backcmd->buf = memout.buf;
 			backcmd->nleft = memout.nextc - memout.buf;
 			memout.buf = NULL;
 		}
+		if (cmdentry.u.index != EXECCMD &&
+				(e == -1 || e == EXERROR || e == EXEXEC))
+			popredir();
+		if (e != -1) {
+			if ((e != EXERROR && e != EXEXEC)
+			    || cmdentry.special)
+				exraise(e);
+			popfilesupto(savetopfile);
+			if (flags != EV_BACKCMD)
+				FORCEINTON;
+		}
 	} else {
 #ifdef DEBUG
 		trputs("normal command:  ");  trargs(argv);
 #endif
-		clearredir();
 		redirect(cmd->ncmd.redirect, 0);
 		for (sp = varlist.list ; sp ; sp = sp->next)
 			setvareq(sp->text, VEXPORT|VSTACK);
 		envp = environment();
-		shellexec(argv, envp, pathval(), cmdentry.u.index);
+		shellexec(argv, envp, path, cmdentry.u.index);
 		/*NOTREACHED*/
 	}
 	goto out;
@@ -946,12 +1039,17 @@
  */
 
 /*
- * No command given, or a bltin command with no arguments.
+ * No command given, a bltin command with no arguments, or a bltin command
+ * with an invalid name.
  */
 
 int
-bltincmd(int argc __unused, char **argv __unused)
+bltincmd(int argc, char **argv)
 {
+	if (argc > 1) {
+		out2fmt_flush("%s: not found\n", argv[1]);
+		return 127;
+	}
 	/*
 	 * Preserve exitstatus of a previous possible redirection
 	 * as POSIX mandates
@@ -991,23 +1089,18 @@
 int
 commandcmd(int argc, char **argv)
 {
-	static char stdpath[] = _PATH_STDPATH;
-	struct jmploc loc, *old;
-	struct strlist *sp;
-	char *path;
+	const char *path;
 	int ch;
 	int cmd = -1;
 
-	for (sp = cmdenviron; sp ; sp = sp->next)
-		setvareq(sp->text, VEXPORT|VSTACK);
-	path = pathval();
+	path = bltinlookup("PATH", 1);
 
 	optind = optreset = 1;
 	opterr = 0;
 	while ((ch = getopt(argc, argv, "pvV")) != -1) {
 		switch (ch) {
 		case 'p':
-			path = stdpath;
+			path = _PATH_STDPATH;
 			break;
 		case 'v':
 			cmd = TYPECMD_SMALLV;
@@ -1026,24 +1119,16 @@
 	if (cmd != -1) {
 		if (argc != 1)
 			error("wrong number of arguments");
-		return typecmd_impl(2, argv - 1, cmd);
-	}
-	if (argc != 0) {
-		old = handler;
-		handler = &loc;
-		if (setjmp(handler->loc) == 0)
-			shellexec(argv, environment(), path, 0);
-		handler = old;
-		if (exception == EXEXEC)
-			exit(exerrno);
-		exraise(exception);
+		return typecmd_impl(2, argv - 1, cmd, path);
 	}
+	if (argc != 0)
+		error("commandcmd() called while it should not be");
 
 	/*
 	 * Do nothing successfully if no command was specified;
 	 * ksh also does this.
 	 */
-	exit(0);
+	return 0;
 }
 
 
@@ -1085,6 +1170,12 @@
 int
 execcmd(int argc, char **argv)
 {
+	/*
+	 * Because we have historically not supported any options,
+	 * only treat "--" specially.
+	 */
+	if (argc > 1 && strcmp(argv[1], "--") == 0)
+		argc--, argv++;
 	if (argc > 1) {
 		struct strlist *sp;
 
diff -urN stable/8/bin/sh/eval.h head/bin/sh/eval.h
--- stable/8/bin/sh/eval.h	2009-06-13 17:17:45.691358000 -0400
+++ head/bin/sh/eval.h	2009-12-27 13:04:05.764326000 -0500
@@ -30,11 +30,12 @@
  * SUCH DAMAGE.
  *
  *	@(#)eval.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/eval.h 194128 2009-06-13 21:17:45Z jilles $
+ * $FreeBSD: head/bin/sh/eval.h 201053 2009-12-27 18:04:05Z 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 */
 
 
diff -urN stable/8/bin/sh/exec.c head/bin/sh/exec.c
--- stable/8/bin/sh/exec.c	2009-10-11 12:35:12.561852000 -0400
+++ head/bin/sh/exec.c	2010-03-06 11:57:53.405454000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/exec.c 197959 2009-10-11 16:35:12Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/exec.c 204800 2010-03-06 16:57:53Z jilles $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -98,7 +98,7 @@
 
 STATIC void tryexec(char *, char **, char **);
 STATIC void printentry(struct tblentry *, int);
-STATIC struct tblentry *cmdlookup(char *, int);
+STATIC struct tblentry *cmdlookup(const char *, int);
 STATIC void delete_cmd_entry(void);
 
 
@@ -109,7 +109,7 @@
  */
 
 void
-shellexec(char **argv, char **envp, char *path, int index)
+shellexec(char **argv, char **envp, const char *path, int idx)
 {
 	char *cmdname;
 	int e;
@@ -120,7 +120,7 @@
 	} else {
 		e = ENOENT;
 		while ((cmdname = padvance(&path, argv[0])) != NULL) {
-			if (--index < 0 && pathopt == NULL) {
+			if (--idx < 0 && pathopt == NULL) {
 				tryexec(cmdname, argv, envp);
 				if (errno != ENOENT && errno != ENOTDIR)
 					e = errno;
@@ -175,13 +175,13 @@
  * NULL.
  */
 
-char *pathopt;
+const char *pathopt;
 
 char *
-padvance(char **path, char *name)
+padvance(const char **path, const char *name)
 {
-	char *p, *q;
-	char *start;
+	const char *p, *start;
+	char *q;
 	int len;
 
 	if (*path == NULL)
@@ -248,14 +248,14 @@
 		 && (cmdp->cmdtype == CMDNORMAL
 		     || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
 			delete_cmd_entry();
-		find_command(name, &entry, 1, pathval());
+		find_command(name, &entry, DO_ERR, pathval());
 		if (verbose) {
 			if (entry.cmdtype != CMDUNKNOWN) {	/* if no error msg */
 				cmdp = cmdlookup(name, 0);
 				if (cmdp != NULL)
 					printentry(cmdp, verbose);
 				else
-					outfmt(&errout, "%s: not found\n", name);
+					outfmt(out2, "%s: not found\n", name);
 			}
 			flushall();
 		}
@@ -268,17 +268,17 @@
 STATIC void
 printentry(struct tblentry *cmdp, int verbose)
 {
-	int index;
-	char *path;
+	int idx;
+	const char *path;
 	char *name;
 
 	if (cmdp->cmdtype == CMDNORMAL) {
-		index = cmdp->param.index;
+		idx = cmdp->param.index;
 		path = pathval();
 		do {
 			name = padvance(&path, cmdp->cmdname);
 			stunalloc(name);
-		} while (--index >= 0);
+		} while (--idx >= 0);
 		out1str(name);
 	} else if (cmdp->cmdtype == CMDBUILTIN) {
 		out1fmt("builtin %s", cmdp->cmdname);
@@ -310,10 +310,11 @@
  */
 
 void
-find_command(char *name, struct cmdentry *entry, int printerr, char *path)
+find_command(const char *name, struct cmdentry *entry, int act,
+    const char *path)
 {
-	struct tblentry *cmdp;
-	int index;
+	struct tblentry *cmdp, loc_cmd;
+	int idx;
 	int prev;
 	char *fullname;
 	struct stat statb;
@@ -329,13 +330,19 @@
 	}
 
 	/* If name is in the table, and not invalidated by cd, we're done */
-	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
-		goto success;
+	if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
+		if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC)
+			cmdp = NULL;
+		else
+			goto success;
+	}
 
 	/* If %builtin not in path, check for builtin next */
 	if (builtinloc < 0 && (i = find_builtin(name, &spec)) >= 0) {
 		INTOFF;
 		cmdp = cmdlookup(name, 1);
+		if (cmdp->cmdtype == CMDFUNCTION)
+			cmdp = &loc_cmd;
 		cmdp->cmdtype = CMDBUILTIN;
 		cmdp->param.index = i;
 		cmdp->special = spec;
@@ -353,17 +360,19 @@
 	}
 
 	e = ENOENT;
-	index = -1;
+	idx = -1;
 loop:
 	while ((fullname = padvance(&path, name)) != NULL) {
 		stunalloc(fullname);
-		index++;
+		idx++;
 		if (pathopt) {
 			if (prefix("builtin", pathopt)) {
 				if ((i = find_builtin(name, &spec)) < 0)
 					goto loop;
 				INTOFF;
 				cmdp = cmdlookup(name, 1);
+				if (cmdp->cmdtype == CMDFUNCTION)
+					cmdp = &loc_cmd;
 				cmdp->cmdtype = CMDBUILTIN;
 				cmdp->param.index = i;
 				cmdp->special = spec;
@@ -376,8 +385,8 @@
 			}
 		}
 		/* if rehash, don't redo absolute path names */
-		if (fullname[0] == '/' && index <= prev) {
-			if (index < prev)
+		if (fullname[0] == '/' && idx <= prev) {
+			if (idx < prev)
 				goto loop;
 			TRACE(("searchexec \"%s\": no change\n", name));
 			goto success;
@@ -413,22 +422,25 @@
 		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
 		INTOFF;
 		cmdp = cmdlookup(name, 1);
+		if (cmdp->cmdtype == CMDFUNCTION)
+			cmdp = &loc_cmd;
 		cmdp->cmdtype = CMDNORMAL;
-		cmdp->param.index = index;
+		cmdp->param.index = idx;
 		INTON;
 		goto success;
 	}
 
 	/* We failed.  If there was an entry for this command, delete it */
-	if (cmdp)
+	if (cmdp && cmdp->cmdtype != CMDFUNCTION)
 		delete_cmd_entry();
-	if (printerr) {
+	if (act & DO_ERR) {
 		if (e == ENOENT || e == ENOTDIR)
 			outfmt(out2, "%s: not found\n", name);
 		else
 			outfmt(out2, "%s: %s\n", name, strerror(e));
 	}
 	entry->cmdtype = CMDUNKNOWN;
+	entry->u.index = 0;
 	return;
 
 success:
@@ -445,7 +457,7 @@
  */
 
 int
-find_builtin(char *name, int *special)
+find_builtin(const char *name, int *special)
 {
 	const struct builtincmd *bp;
 
@@ -492,18 +504,18 @@
 changepath(const char *newval)
 {
 	const char *old, *new;
-	int index;
+	int idx;
 	int firstchange;
 	int bltin;
 
 	old = pathval();
 	new = newval;
 	firstchange = 9999;	/* assume no change */
-	index = 0;
+	idx = 0;
 	bltin = -1;
 	for (;;) {
 		if (*old != *new) {
-			firstchange = index;
+			firstchange = idx;
 			if ((*old == '\0' && *new == ':')
 			 || (*old == ':' && *new == '\0'))
 				firstchange++;
@@ -512,9 +524,9 @@
 		if (*new == '\0')
 			break;
 		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
-			bltin = index;
+			bltin = idx;
 		if (*new == ':') {
-			index++;
+			idx++;
 		}
 		new++, old++;
 	}
@@ -607,10 +619,10 @@
 
 
 STATIC struct tblentry *
-cmdlookup(char *name, int add)
+cmdlookup(const char *name, int add)
 {
 	int hashval;
-	char *p;
+	const char *p;
 	struct tblentry *cmdp;
 	struct tblentry **pp;
 
@@ -663,7 +675,7 @@
  */
 
 void
-addcmdentry(char *name, struct cmdentry *entry)
+addcmdentry(const char *name, struct cmdentry *entry)
 {
 	struct tblentry *cmdp;
 
@@ -683,7 +695,7 @@
  */
 
 void
-defun(char *name, union node *func)
+defun(const char *name, union node *func)
 {
 	struct cmdentry entry;
 
@@ -700,7 +712,7 @@
  */
 
 int
-unsetfunc(char *name)
+unsetfunc(const char *name)
 {
 	struct tblentry *cmdp;
 
@@ -718,19 +730,21 @@
  */
 
 int
-typecmd_impl(int argc, char **argv, int cmd)
+typecmd_impl(int argc, char **argv, int cmd, const char *path)
 {
 	struct cmdentry entry;
 	struct tblentry *cmdp;
-	char **pp;
+	const char *const *pp;
 	struct alias *ap;
 	int i;
-	int error = 0;
-	extern char *const parsekwd[];
+	int error1 = 0;
+
+	if (path != pathval())
+		clearcmdentry(0);
 
 	for (i = 1; i < argc; i++) {
 		/* First look at the keywords */
-		for (pp = (char **)parsekwd; *pp; pp++)
+		for (pp = parsekwd; *pp; pp++)
 			if (**pp == *argv[i] && equal(*pp, argv[i]))
 				break;
 
@@ -760,16 +774,17 @@
 		}
 		else {
 			/* Finally use brute force */
-			find_command(argv[i], &entry, 0, pathval());
+			find_command(argv[i], &entry, 0, path);
 		}
 
 		switch (entry.cmdtype) {
 		case CMDNORMAL: {
 			if (strchr(argv[i], '/') == NULL) {
-				char *path = pathval(), *name;
+				const char *path2 = path;
+				char *name;
 				int j = entry.u.index;
 				do {
-					name = padvance(&path, argv[i]);
+					name = padvance(&path2, argv[i]);
 					stunalloc(name);
 				} while (--j >= 0);
 				if (cmd == TYPECMD_SMALLV)
@@ -790,7 +805,7 @@
 					if (cmd != TYPECMD_SMALLV)
 						outfmt(out2, "%s: %s\n",
 						    argv[i], strerror(errno));
-					error |= 127;
+					error1 |= 127;
 				}
 			}
 			break;
@@ -815,11 +830,15 @@
 		default:
 			if (cmd != TYPECMD_SMALLV)
 				outfmt(out2, "%s: not found\n", argv[i]);
-			error |= 127;
+			error1 |= 127;
 			break;
 		}
 	}
-	return error;
+
+	if (path != pathval())
+		clearcmdentry(0);
+
+	return error1;
 }
 
 /*
@@ -829,5 +848,5 @@
 int
 typecmd(int argc, char **argv)
 {
-	return typecmd_impl(argc, argv, TYPECMD_TYPE);
+	return typecmd_impl(argc, argv, TYPECMD_TYPE, bltinlookup("PATH", 1));
 }
diff -urN stable/8/bin/sh/exec.h head/bin/sh/exec.h
--- stable/8/bin/sh/exec.h	2009-10-11 12:35:12.561852000 -0400
+++ head/bin/sh/exec.h	2010-03-06 11:57:53.405454000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)exec.h	8.3 (Berkeley) 6/8/95
- * $FreeBSD: stable/8/bin/sh/exec.h 197959 2009-10-11 16:35:12Z jilles $
+ * $FreeBSD: head/bin/sh/exec.h 204800 2010-03-06 16:57:53Z jilles $
  */
 
 /* values of cmdtype */
@@ -57,20 +57,24 @@
 };
 
 
-extern char *pathopt;		/* set by padvance */
+/* action to find_command() */
+#define DO_ERR		0x01	/* prints errors */
+#define DO_NOFUNC	0x02	/* don't return shell functions, for command */
+
+extern const char *pathopt;	/* set by padvance */
 extern int exerrno;		/* last exec error */
 
-void shellexec(char **, char **, char *, int);
-char *padvance(char **, char *);
+void shellexec(char **, char **, const char *, int) __dead2;
+char *padvance(const char **, const char *);
 int hashcmd(int, char **);
-void find_command(char *, struct cmdentry *, int, char *);
-int find_builtin(char *, int *);
+void find_command(const char *, struct cmdentry *, int, const char *);
+int find_builtin(const char *, int *);
 void hashcd(void);
 void changepath(const char *);
 void deletefuncs(void);
-void addcmdentry(char *, struct cmdentry *);
-void defun(char *, union node *);
-int unsetfunc(char *);
-int typecmd_impl(int, char **, int);
+void addcmdentry(const char *, struct cmdentry *);
+void defun(const char *, union node *);
+int unsetfunc(const char *);
+int typecmd_impl(int, char **, int, const char *);
 int typecmd(int, char **);
 void clearcmdentry(int);
diff -urN stable/8/bin/sh/expand.c head/bin/sh/expand.c
--- stable/8/bin/sh/expand.c	2010-05-16 18:52:51.682053000 -0400
+++ head/bin/sh/expand.c	2010-05-11 19:19:28.413799000 -0400
@@ -38,7 +38,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/expand.c 208174 2010-05-16 22:52:51Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/expand.c 207944 2010-05-11 23:19:28Z jilles $");
 
 #include <sys/types.h>
 #include <sys/time.h>
@@ -109,7 +109,7 @@
 STATIC void addfname(char *);
 STATIC struct strlist *expsort(struct strlist *);
 STATIC struct strlist *msort(struct strlist *, int);
-STATIC int pmatch(char *, char *, int);
+STATIC int pmatch(const char *, const char *, int);
 STATIC char *cvtnum(int, char *);
 STATIC int collate_range_cmp(int, int);
 
@@ -273,8 +273,12 @@
 
 	while ((c = *p) != '\0') {
 		switch(c) {
-		case CTLESC:
-			return (startp);
+		case CTLESC: /* This means CTL* are always considered quoted. */
+		case CTLVAR:
+		case CTLBACKQ:
+		case CTLBACKQ | CTLQUOTE:
+		case CTLARI:
+		case CTLENDARI:
 		case CTLQUOTEMARK:
 			return (startp);
 		case ':':
@@ -282,6 +286,7 @@
 				goto done;
 			break;
 		case '/':
+		case CTLENDVAR:
 			goto done;
 		}
 		p++;
@@ -357,7 +362,7 @@
 void
 expari(int flag)
 {
-	char *p, *start;
+	char *p, *q, *start;
 	arith_t result;
 	int begoff;
 	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
@@ -395,7 +400,9 @@
 	removerecordregions(begoff);
 	if (quotes)
 		rmescapes(p+2);
+	q = grabstackstr(expdest);
 	result = arith(p+2);
+	ungrabstackstr(q, expdest);
 	fmtstr(p, DIGITS(result), ARITH_FORMAT_STR, result);
 	while (*p++)
 		;
@@ -503,7 +510,9 @@
 	int amount;
 
 	herefd = -1;
-	argstr(p, 0);
+	argstr(p, (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX ||
+	    subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX ?
+	    EXP_CASE : 0) | EXP_TILDE);
 	STACKSTRNUL(expdest);
 	herefd = saveherefd;
 	argbackq = saveargbackq;
@@ -523,7 +532,7 @@
 
 	case VSQUESTION:
 		if (*p != CTLENDVAR) {
-			outfmt(&errout, "%s\n", startp);
+			outfmt(out2, "%s\n", startp);
 			error((char *)NULL);
 		}
 		error("%.*s: parameter %snot set", (int)(p - str - 1),
@@ -659,7 +668,7 @@
 	}
 	varlen = 0;
 	startloc = expdest - stackblock();
-	if (!set && uflag) {
+	if (!set && uflag && *var != '@' && *var != '*') {
 		switch (subtype) {
 		case VSNORMAL:
 		case VSTRIMLEFT:
@@ -852,7 +861,6 @@
 	int num;
 	char *p;
 	int i;
-	extern int oexitstatus;
 	char sep;
 	char **ap;
 	char const *syntax;
@@ -976,7 +984,7 @@
 	char *start;
 	char *p;
 	char *q;
-	char *ifs;
+	const char *ifs;
 	const char *ifsspc;
 	int had_param_ch = 0;
 
@@ -1344,7 +1352,7 @@
  */
 
 int
-patmatch(char *pattern, char *string, int squoted)
+patmatch(const char *pattern, const char *string, int squoted)
 {
 #ifdef notdef
 	if (pattern[0] == '!' && pattern[1] == '!')
@@ -1356,9 +1364,9 @@
 
 
 STATIC int
-pmatch(char *pattern, char *string, int squoted)
+pmatch(const char *pattern, const char *string, int squoted)
 {
-	char *p, *q;
+	const char *p, *q;
 	char c;
 
 	p = pattern;
@@ -1406,7 +1414,7 @@
 			} while (*q++ != '\0');
 			return 0;
 		case '[': {
-			char *endp;
+			const char *endp;
 			int invert, found;
 			char chr;
 
@@ -1510,7 +1518,7 @@
  */
 
 int
-casematch(union node *pattern, char *val)
+casematch(union node *pattern, const char *val)
 {
 	struct stackmark smark;
 	int result;
diff -urN stable/8/bin/sh/expand.h head/bin/sh/expand.h
--- stable/8/bin/sh/expand.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/expand.h	2009-12-24 13:41:14.411055000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)expand.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/expand.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/expand.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 struct strlist {
@@ -58,7 +58,7 @@
 void expandhere(union node *, int);
 void expandarg(union node *, struct arglist *, int);
 void expari(int);
-int patmatch(char *, char *, int);
+int patmatch(const char *, const char *, int);
 void rmescapes(char *);
-int casematch(union node *, char *);
+int casematch(union node *, const char *);
 int wordexpcmd(int, char **);
diff -urN stable/8/bin/sh/funcs/cmv head/bin/sh/funcs/cmv
--- stable/8/bin/sh/funcs/cmv	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/cmv	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)cmv	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/cmv 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD: head/bin/sh/funcs/cmv 139969 2005-01-10 08:39:26Z imp $
 
 # Conditional move--don't replace an existing file.
 
diff -urN stable/8/bin/sh/funcs/dirs head/bin/sh/funcs/dirs
--- stable/8/bin/sh/funcs/dirs	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/dirs	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)dirs	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/dirs 139969 2005-01-10 08:39:26Z imp $
+# $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 -urN stable/8/bin/sh/funcs/kill head/bin/sh/funcs/kill
--- stable/8/bin/sh/funcs/kill	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/kill	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)kill	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/kill 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD: head/bin/sh/funcs/kill 139969 2005-01-10 08:39:26Z imp $
 
 # Convert job names to process ids and then run /bin/kill.
 
diff -urN stable/8/bin/sh/funcs/login head/bin/sh/funcs/login
--- stable/8/bin/sh/funcs/login	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/login	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)login	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/login 139969 2005-01-10 08:39:26Z imp $
+# $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 -urN stable/8/bin/sh/funcs/newgrp head/bin/sh/funcs/newgrp
--- stable/8/bin/sh/funcs/newgrp	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/newgrp	2005-01-10 03:39:26.000000000 -0500
@@ -32,6 +32,6 @@
 # SUCH DAMAGE.
 #
 #	@(#)newgrp	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/newgrp 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD: head/bin/sh/funcs/newgrp 139969 2005-01-10 08:39:26Z imp $
 
 newgrp() exec newgrp "$@"
diff -urN stable/8/bin/sh/funcs/popd head/bin/sh/funcs/popd
--- stable/8/bin/sh/funcs/popd	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/popd	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)popd	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/popd 139969 2005-01-10 08:39:26Z imp $
+# $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 -urN stable/8/bin/sh/funcs/pushd head/bin/sh/funcs/pushd
--- stable/8/bin/sh/funcs/pushd	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/pushd	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)pushd	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/pushd 139969 2005-01-10 08:39:26Z imp $
+# $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 -urN stable/8/bin/sh/funcs/suspend head/bin/sh/funcs/suspend
--- stable/8/bin/sh/funcs/suspend	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/funcs/suspend	2005-01-10 03:39:26.000000000 -0500
@@ -30,7 +30,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)suspend	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/funcs/suspend 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD: head/bin/sh/funcs/suspend 139969 2005-01-10 08:39:26Z imp $
 
 suspend() {
 	local -
diff -urN stable/8/bin/sh/histedit.c head/bin/sh/histedit.c
--- stable/8/bin/sh/histedit.c	2009-06-23 16:45:12.009544000 -0400
+++ head/bin/sh/histedit.c	2010-06-15 17:58:40.504446000 -0400
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/histedit.c 194765 2009-06-23 20:45:12Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/histedit.c 209221 2010-06-15 21:58:40Z jilles $");
 
 #include <sys/param.h>
 #include <limits.h>
@@ -92,12 +92,14 @@
 			if (hist != NULL)
 				sethistsize(histsizeval());
 			else
-				out2str("sh: can't initialize history\n");
+				out2fmt_flush("sh: can't initialize history\n");
 		}
 		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
 			/*
 			 * turn editing on
 			 */
+			char *term;
+
 			INTOFF;
 			if (el_in == NULL)
 				el_in = fdopen(0, "r");
@@ -107,14 +109,22 @@
 				el_out = fdopen(2, "w");
 			if (el_in == NULL || el_err == NULL || el_out == NULL)
 				goto bad;
+			term = lookupvar("TERM");
+			if (term)
+				setenv("TERM", term, 1);
+			else
+				unsetenv("TERM");
 			el = el_init(arg0, el_in, el_out, el_err);
 			if (el != NULL) {
 				if (hist)
 					el_set(el, EL_HIST, history, hist);
 				el_set(el, EL_PROMPT, getprompt);
+				el_set(el, EL_ADDFN, "sh-complete",
+				    "Filename completion",
+				    _el_fn_sh_complete);
 			} else {
 bad:
-				out2str("sh: can't initialize editing\n");
+				out2fmt_flush("sh: can't initialize editing\n");
 			}
 			INTON;
 		} else if (!editing && el) {
@@ -128,6 +138,7 @@
 				el_set(el, EL_EDITOR, "vi");
 			else if (Eflag)
 				el_set(el, EL_EDITOR, "emacs");
+			el_set(el, EL_BIND, "^I", "sh-complete", NULL);
 			el_source(el, NULL);
 		}
 	} else {
@@ -160,23 +171,30 @@
 	}
 }
 
+void
+setterm(const char *term)
+{
+	if (rootshell && el != NULL && term != NULL)
+		el_set(el, EL_TERMINAL, term);
+}
+
 int
 histcmd(int argc, char **argv)
 {
 	int ch;
-	char *editor = NULL;
+	const char *editor = NULL;
 	HistEvent he;
 	int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
 	int i, retval;
-	char *firststr, *laststr;
+	const char *firststr, *laststr;
 	int first, last, direction;
-	char *pat = NULL, *repl;
+	char *pat = NULL, *repl = NULL;
 	static int active = 0;
 	struct jmploc jmploc;
 	struct jmploc *savehandler;
 	char editfilestr[PATH_MAX];
 	char *volatile editfile;
-	FILE *efp;
+	FILE *efp = NULL;
 	int oldhistnum;
 
 	if (hist == NULL)
@@ -336,6 +354,7 @@
 			if (sflg) {
 				if (displayhist) {
 					out2str(s);
+					flushout(out2);
 				}
 				evalstring(s, 0);
 				if (displayhist && hist) {
@@ -405,7 +424,7 @@
 }
 
 int
-not_fcnumber(char *s)
+not_fcnumber(const char *s)
 {
 	if (s == NULL)
 		return (0);
@@ -415,10 +434,10 @@
 }
 
 int
-str_to_event(char *str, int last)
+str_to_event(const char *str, int last)
 {
 	HistEvent he;
-	char *s = str;
+	const char *s = str;
 	int relative = 0;
 	int i, retval;
 
diff -urN stable/8/bin/sh/init.h head/bin/sh/init.h
--- stable/8/bin/sh/init.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/init.h	2004-04-06 16:06:54.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)init.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/init.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/init.h 127958 2004-04-06 20:06:54Z markm $
  */
 
 void init(void);
diff -urN stable/8/bin/sh/input.c head/bin/sh/input.c
--- stable/8/bin/sh/input.c	2009-06-17 17:58:32.143624000 -0400
+++ head/bin/sh/input.c	2009-12-27 13:04:05.764326000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/input.c 194406 2009-06-17 21:58:32Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/input.c 201053 2009-12-27 18:04:05Z jilles $");
 
 #include <stdio.h>	/* defines BUFSIZ */
 #include <fcntl.h>
@@ -93,7 +93,7 @@
 
 
 int plinno = 1;			/* input line number */
-MKINIT int parsenleft;		/* copy of parsefile->nleft */
+int parsenleft;			/* copy of parsefile->nleft */
 MKINIT int parselleft;		/* copy of parsefile->lleft */
 char *parsenextc;		/* copy of parsefile->nextc */
 MKINIT struct parsefile basepf;	/* top level input file */
@@ -111,9 +111,9 @@
 INCLUDE "input.h"
 INCLUDE "error.h"
 
-INIT {
-	extern char basebuf[];
+MKINIT char basebuf[];
 
+INIT {
 	basepf.nextc = basepf.buf = basebuf;
 }
 
@@ -215,7 +215,7 @@
                                 if (flags >= 0 && flags & O_NONBLOCK) {
                                         flags &=~ O_NONBLOCK;
                                         if (fcntl(0, F_SETFL, flags) >= 0) {
-						out2str("sh: turning off NDELAY mode\n");
+						out2fmt_flush("sh: turning off NDELAY mode\n");
                                                 goto retry;
                                         }
                                 }
@@ -359,7 +359,7 @@
 	struct strpush *sp;
 
 	INTOFF;
-/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
+/*out2fmt_flush("*** calling pushstring: %s, %d\n", s, len);*/
 	if (parsefile->strpush) {
 		sp = ckmalloc(sizeof (struct strpush));
 		sp->prev = parsefile->strpush;
@@ -386,7 +386,7 @@
 	parsenextc = sp->prevstring;
 	parsenleft = sp->prevnleft;
 	parselleft = sp->prevlleft;
-/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
+/*out2fmt_flush("*** calling popstring: restoring to '%s'\n", parsenextc);*/
 	if (sp->ap)
 		sp->ap->flag &= ~ALIASINUSE;
 	parsefile->strpush = sp->prev;
@@ -401,7 +401,7 @@
  */
 
 void
-setinputfile(char *fname, int push)
+setinputfile(const char *fname, int push)
 {
 	int fd;
 	int fd2;
@@ -509,6 +509,32 @@
 
 
 /*
+ * Return current file (to go back to it later using popfilesupto()).
+ */
+
+struct parsefile *
+getcurrentfile(void)
+{
+	return parsefile;
+}
+
+
+/*
+ * Pop files until the given file is on top again. Useful for regular
+ * builtins that read shell commands from files or strings.
+ * If the given file is not an active file, an error is raised.
+ */
+
+void
+popfilesupto(struct parsefile *file)
+{
+	while (parsefile != file && parsefile != &basepf)
+		popfile();
+	if (parsefile != file)
+		error("popfilesupto() misused");
+}
+
+/*
  * Return to top level.
  */
 
diff -urN stable/8/bin/sh/input.h head/bin/sh/input.h
--- stable/8/bin/sh/input.h	2009-06-13 17:17:45.691358000 -0400
+++ head/bin/sh/input.h	2009-12-24 13:41:14.411055000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)input.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/input.h 194128 2009-06-13 21:17:45Z jilles $
+ * $FreeBSD: head/bin/sh/input.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 /* PEOF (the end of file marker) is defined in syntax.h */
@@ -45,6 +45,8 @@
 extern char *parsenextc;	/* next character in input buffer */
 extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
 
+struct parsefile;
+
 char *pfgets(char *, int);
 int pgetc(void);
 int preadbuffer(void);
@@ -52,10 +54,12 @@
 void pungetc(void);
 void pushstring(char *, int, void *);
 void popstring(void);
-void setinputfile(char *, int);
+void setinputfile(const char *, int);
 void setinputfd(int, int);
 void setinputstring(char *, int);
 void popfile(void);
+struct parsefile *getcurrentfile(void);
+void popfilesupto(struct parsefile *);
 void popallfiles(void);
 void closescript(void);
 
diff -urN stable/8/bin/sh/jobs.c head/bin/sh/jobs.c
--- stable/8/bin/sh/jobs.c	2006-10-07 12:51:16.000000000 -0400
+++ head/bin/sh/jobs.c	2010-06-06 18:27:32.647903000 -0400
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/jobs.c 163085 2006-10-07 16:51:16Z stefanf $");
+__FBSDID("$FreeBSD: head/bin/sh/jobs.c 208881 2010-06-06 22:27:32Z jilles $");
 
 #include <fcntl.h>
 #include <signal.h>
@@ -91,8 +91,9 @@
 STATIC struct job *getjob(char *);
 STATIC pid_t dowait(int, struct job *);
 STATIC pid_t waitproc(int, int *);
+STATIC void checkzombies(void);
 STATIC void cmdtxt(union node *);
-STATIC void cmdputs(char *);
+STATIC void cmdputs(const char *);
 #if JOBS
 STATIC void setcurjob(struct job *);
 STATIC void deljob(struct job *);
@@ -146,7 +147,7 @@
 		do { /* while we are in the background */
 			initialpgrp = tcgetpgrp(ttyfd);
 			if (initialpgrp < 0) {
-out:				out2str("sh: can't access tty; job control turned off\n");
+out:				out2fmt_flush("sh: can't access tty; job control turned off\n");
 				mflag = 0;
 				return;
 			}
@@ -400,7 +401,7 @@
 	struct job *jp;
 
 	TRACE(("showjobs(%d) called\n", change));
-	while (dowait(0, (struct job *)NULL) > 0);
+	checkzombies();
 	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
 		if (! jp->used)
 			continue;
@@ -742,6 +743,8 @@
 	TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, (void *)n,
 	    mode));
 	INTOFF;
+	if (mode == FORK_BG)
+		checkzombies();
 	flushall();
 	pid = fork();
 	if (pid == -1) {
@@ -757,6 +760,7 @@
 		TRACE(("Child shell %d\n", (int)getpid()));
 		wasroot = rootshell;
 		rootshell = 0;
+		handler = &main_handler;
 		closescript();
 		INTON;
 		clear_traps();
@@ -862,6 +866,7 @@
 {
 #if JOBS
 	pid_t mypgrp = getpgrp();
+	int propagate_int = jp->jobctl && jp->foreground;
 #endif
 	int status;
 	int st;
@@ -899,6 +904,11 @@
 		else
 			CLEAR_PENDING_INT;
 	}
+#if JOBS
+	else if (rootshell && iflag && propagate_int &&
+			WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
+		kill(getpid(), SIGINT);
+#endif
 	INTON;
 	return st;
 }
@@ -1046,7 +1056,7 @@
 		if (jp->used == 0)
 			continue;
 		if (jp->state == JOBSTOPPED) {
-			out2str("You have stopped jobs.\n");
+			out2fmt_flush("You have stopped jobs.\n");
 			job_warning = 2;
 			return (1);
 		}
@@ -1055,6 +1065,15 @@
 	return (0);
 }
 
+
+STATIC void
+checkzombies(void)
+{
+	while (njobs > 0 && dowait(0, NULL) > 0)
+		;
+}
+
+
 /*
  * Return a string identifying a command (to be printed by the
  * jobs command.
@@ -1082,7 +1101,7 @@
 {
 	union node *np;
 	struct nodelist *lp;
-	char *p;
+	const char *p;
 	int i;
 	char s[2];
 
@@ -1211,9 +1230,10 @@
 
 
 STATIC void
-cmdputs(char *s)
+cmdputs(const char *s)
 {
-	char *p, *q;
+	const char *p;
+	char *q;
 	char c;
 	int subtype = 0;
 
diff -urN stable/8/bin/sh/jobs.h head/bin/sh/jobs.h
--- stable/8/bin/sh/jobs.h	2006-10-07 12:51:16.000000000 -0400
+++ head/bin/sh/jobs.h	2006-10-07 12:51:16.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/jobs.h 163085 2006-10-07 16:51:16Z stefanf $
+ * $FreeBSD: head/bin/sh/jobs.h 163085 2006-10-07 16:51:16Z stefanf $
  */
 
 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
diff -urN stable/8/bin/sh/mail.c head/bin/sh/mail.c
--- stable/8/bin/sh/mail.c	2005-08-13 04:26:58.000000000 -0400
+++ head/bin/sh/mail.c	2009-12-24 13:41:14.411055000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/mail.c 149017 2005-08-13 08:26:58Z stefanf $");
+__FBSDID("$FreeBSD: head/bin/sh/mail.c 200956 2009-12-24 18:41:14Z jilles $");
 
 /*
  * Routines to check for mail.  (Perhaps make part of main.c?)
@@ -72,7 +72,7 @@
 chkmail(int silent)
 {
 	int i;
-	char *mpath;
+	const char *mpath;
 	char *p;
 	char *q;
 	struct stackmark smark;
diff -urN stable/8/bin/sh/mail.h head/bin/sh/mail.h
--- stable/8/bin/sh/mail.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/mail.h	2004-04-06 16:06:54.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)mail.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/mail.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/mail.h 127958 2004-04-06 20:06:54Z markm $
  */
 
 void chkmail(int);
diff -urN stable/8/bin/sh/main.c head/bin/sh/main.c
--- stable/8/bin/sh/main.c	2010-04-20 18:52:28.965483000 -0400
+++ head/bin/sh/main.c	2010-05-28 18:40:24.781829000 -0400
@@ -42,7 +42,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/main.c 206950 2010-04-20 22:52:28Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/main.c 208630 2010-05-28 22:40:24Z jilles $");
 
 #include <stdio.h>
 #include <signal.h>
@@ -75,8 +75,9 @@
 
 int rootpid;
 int rootshell;
+struct jmploc main_handler;
 
-STATIC void read_profile(char *);
+STATIC void read_profile(const char *);
 STATIC char *find_dot_file(char *);
 
 /*
@@ -90,14 +91,13 @@
 int
 main(int argc, char *argv[])
 {
-	struct jmploc jmploc;
 	struct stackmark smark;
 	volatile int state;
 	char *shinit;
 
 	(void) setlocale(LC_ALL, "");
 	state = 0;
-	if (setjmp(jmploc.loc)) {
+	if (setjmp(main_handler.loc)) {
 		/*
 		 * When a shell procedure is executed, we raise the
 		 * exception EXSHELLPROC to clean up before executing
@@ -143,7 +143,7 @@
 		else
 			goto state4;
 	}
-	handler = &jmploc;
+	handler = &main_handler;
 #ifdef DEBUG
 	opentrace();
 	trputs("Shell args:  ");  trargs(argv);
@@ -153,10 +153,7 @@
 	init();
 	setstackmark(&smark);
 	procargs(argc, argv);
-	if (getpwd() == NULL && iflag)
-		out2str("sh: cannot determine working directory\n");
-	if (getpwd() != NULL)
-		setvar ("PWD", getpwd(), VEXPORT);
+	pwd_init(iflag);
 	if (iflag)
 		chkmail(1);
 	if (argv[0] && argv[0][0] == '-') {
@@ -225,7 +222,7 @@
 			if (!stoppedjobs()) {
 				if (!Iflag)
 					break;
-				out2str("\nUse \"exit\" to leave shell.\n");
+				out2fmt_flush("\nUse \"exit\" to leave shell.\n");
 			}
 			numeof++;
 		} else if (n != NULL && nflag == 0) {
@@ -250,7 +247,7 @@
  */
 
 STATIC void
-read_profile(char *name)
+read_profile(const char *name)
 {
 	int fd;
 
@@ -271,7 +268,7 @@
  */
 
 void
-readcmdfile(char *name)
+readcmdfile(const char *name)
 {
 	int fd;
 
@@ -298,7 +295,7 @@
 {
 	static char localname[FILENAME_MAX+1];
 	char *fullname;
-	char *path = pathval();
+	const char *path = pathval();
 	struct stat statb;
 
 	/* don't try this for absolute or relative paths */
@@ -317,14 +314,20 @@
 int
 dotcmd(int argc, char **argv)
 {
-	char *fullname;
+	char *filename, *fullname;
 
 	if (argc < 2)
 		error("missing filename");
 
 	exitstatus = 0;
 
-	fullname = find_dot_file(argv[1]);
+	/*
+	 * Because we have historically not supported any options,
+	 * only treat "--" specially.
+	 */
+	filename = argc > 2 && strcmp(argv[1], "--") == 0 ? argv[2] : argv[1];
+
+	fullname = find_dot_file(filename);
 	setinputfile(fullname, 1);
 	commandname = fullname;
 	cmdloop(0);
@@ -336,8 +339,6 @@
 int
 exitcmd(int argc, char **argv)
 {
-	extern int oexitstatus;
-
 	if (stoppedjobs())
 		return 0;
 	if (argc > 1)
diff -urN stable/8/bin/sh/main.h head/bin/sh/main.h
--- stable/8/bin/sh/main.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/main.h	2009-12-25 15:21:35.175590000 -0500
@@ -30,13 +30,14 @@
  * SUCH DAMAGE.
  *
  *	@(#)main.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/main.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/main.h 200998 2009-12-25 20:21:35Z jilles $
  */
 
 extern int rootpid;	/* pid of main shell */
 extern int rootshell;	/* true if we aren't a child of the main shell */
+extern struct jmploc main_handler;	/* top level exception handler */
 
-void readcmdfile(char *);
+void readcmdfile(const char *);
 void cmdloop(int);
 int dotcmd(int, char **);
 int exitcmd(int, char **);
diff -urN stable/8/bin/sh/memalloc.c head/bin/sh/memalloc.c
--- stable/8/bin/sh/memalloc.c	2009-06-01 06:50:17.801753000 -0400
+++ head/bin/sh/memalloc.c	2009-12-24 13:41:14.411055000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/memalloc.c 193221 2009-06-01 10:50:17Z rse $");
+__FBSDID("$FreeBSD: head/bin/sh/memalloc.c 200956 2009-12-24 18:41:14Z jilles $");
 
 #include <sys/param.h>
 #include "shell.h"
@@ -95,7 +95,7 @@
  */
 
 char *
-savestr(char *s)
+savestr(const char *s)
 {
 	char *p;
 
diff -urN stable/8/bin/sh/memalloc.h head/bin/sh/memalloc.h
--- stable/8/bin/sh/memalloc.h	2009-06-01 06:50:17.801753000 -0400
+++ head/bin/sh/memalloc.h	2009-12-24 13:41:14.411055000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/memalloc.h 193221 2009-06-01 10:50:17Z rse $
+ * $FreeBSD: head/bin/sh/memalloc.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 #include <string.h>
@@ -51,7 +51,7 @@
 pointer ckmalloc(size_t);
 pointer ckrealloc(pointer, int);
 void ckfree(pointer);
-char *savestr(char *);
+char *savestr(const char *);
 pointer stalloc(int);
 void stunalloc(pointer);
 void setstackmark(struct stackmark *);
diff -urN stable/8/bin/sh/miscbltin.c head/bin/sh/miscbltin.c
--- stable/8/bin/sh/miscbltin.c	2009-06-23 16:57:27.407248000 -0400
+++ head/bin/sh/miscbltin.c	2009-12-27 13:04:05.764326000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/miscbltin.c 194767 2009-06-23 20:57:27Z kib $");
+__FBSDID("$FreeBSD: head/bin/sh/miscbltin.c 201053 2009-12-27 18:04:05Z jilles $");
 
 /*
  * Miscellaneous builtins.
@@ -93,7 +93,7 @@
 	char c;
 	int rflag;
 	char *prompt;
-	char *ifs;
+	const char *ifs;
 	char *p;
 	int startword;
 	int status;
@@ -254,7 +254,7 @@
 
 
 int
-umaskcmd(int argc __unused, char **argv)
+umaskcmd(int argc __unused, char **argv __unused)
 {
 	char *ap;
 	int mask;
diff -urN stable/8/bin/sh/mkbuiltins head/bin/sh/mkbuiltins
--- stable/8/bin/sh/mkbuiltins	2006-04-02 14:43:33.000000000 -0400
+++ head/bin/sh/mkbuiltins	2009-12-27 13:04:05.764326000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/mkbuiltins 157413 2006-04-02 18:43:33Z stefanf $
+# $FreeBSD: head/bin/sh/mkbuiltins 201053 2009-12-27 18:04:05Z jilles $
 
 temp=`/usr/bin/mktemp -t ka`
 havejobs=0
@@ -88,7 +88,7 @@
 	awk '{	printf "#define %s %d\n", $1, NR-1}'
 echo '
 struct builtincmd {
-      char *name;
+      const char *name;
       int code;
       int special;
 };
diff -urN stable/8/bin/sh/mkinit.c head/bin/sh/mkinit.c
--- stable/8/bin/sh/mkinit.c	2009-06-01 06:50:17.801753000 -0400
+++ head/bin/sh/mkinit.c	2009-12-27 13:04:05.764326000 -0500
@@ -42,7 +42,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/mkinit.c 193221 2009-06-01 10:50:17Z rse $");
+__FBSDID("$FreeBSD: head/bin/sh/mkinit.c 201053 2009-12-27 18:04:05Z jilles $");
 
 /*
  * This program scans all the source files for code to handle various
@@ -102,9 +102,9 @@
  */
 
 struct event {
-	char *name;		/* name of event (e.g. INIT) */
-	char *routine;		/* name of routine called on event */
-	char *comment;		/* comment describing routine */
+	const char *name;	/* name of event (e.g. INIT) */
+	const char *routine;	/* name of routine called on event */
+	const char *comment;	/* comment describing routine */
 	struct text code;	/* code for handling event */
 };
 
@@ -140,7 +140,7 @@
 };
 
 
-char *curfile;				/* current file */
+const char *curfile;			/* current file */
 int linno;				/* current line */
 char *header_files[200];		/* list of header files */
 struct text defines;			/* #define statements */
@@ -148,20 +148,20 @@
 int amiddecls;				/* for formatting */
 
 
-void readfile(char *);
-int match(char *, char *);
-int gooddefine(char *);
-void doevent(struct event *, FILE *, char *);
+void readfile(const char *);
+int match(const char *, const char *);
+int gooddefine(const char *);
+void doevent(struct event *, FILE *, const char *);
 void doinclude(char *);
 void dodecl(char *, FILE *);
 void output(void);
-void addstr(char *, struct text *);
+void addstr(const char *, struct text *);
 void addchar(int, struct text *);
 void writetext(struct text *, FILE *);
-FILE *ckfopen(char *, char *);
+FILE *ckfopen(const char *, const char *);
 void *ckmalloc(size_t);
-char *savestr(char *);
-void error(char *);
+char *savestr(const char *);
+void error(const char *);
 
 #define equal(s1, s2)	(strcmp(s1, s2) == 0)
 
@@ -170,9 +170,9 @@
 {
 	char **ap;
 
-	header_files[0] = "\"shell.h\"";
-	header_files[1] = "\"mystring.h\"";
-	header_files[2] = "\"init.h\"";
+	header_files[0] = savestr("\"shell.h\"");
+	header_files[1] = savestr("\"mystring.h\"");
+	header_files[2] = savestr("\"init.h\"");
 	for (ap = argv + 1 ; *ap ; ap++)
 		readfile(*ap);
 	output();
@@ -186,7 +186,7 @@
  */
 
 void
-readfile(char *fname)
+readfile(const char *fname)
 {
 	FILE *fp;
 	char line[1024];
@@ -230,9 +230,9 @@
 
 
 int
-match(char *name, char *line)
+match(const char *name, const char *line)
 {
-	char *p, *q;
+	const char *p, *q;
 
 	p = name, q = line;
 	while (*p) {
@@ -246,9 +246,9 @@
 
 
 int
-gooddefine(char *line)
+gooddefine(const char *line)
 {
-	char *p;
+	const char *p;
 
 	if (! match("#define", line))
 		return 0;			/* not a define */
@@ -269,11 +269,11 @@
 
 
 void
-doevent(struct event *ep, FILE *fp, char *fname)
+doevent(struct event *ep, FILE *fp, const char *fname)
 {
 	char line[1024];
 	int indent;
-	char *p;
+	const char *p;
 
 	sprintf(line, "\n      /* from %s: */\n", fname);
 	addstr(line, &ep->code);
@@ -407,7 +407,7 @@
  */
 
 void
-addstr(char *s, struct text *text)
+addstr(const char *s, struct text *text)
 {
 	while (*s) {
 		if (--text->nleft < 0)
@@ -452,7 +452,7 @@
 }
 
 FILE *
-ckfopen(char *file, char *mode)
+ckfopen(const char *file, const char *mode)
 {
 	FILE *fp;
 
@@ -474,7 +474,7 @@
 }
 
 char *
-savestr(char *s)
+savestr(const char *s)
 {
 	char *p;
 
@@ -484,7 +484,7 @@
 }
 
 void
-error(char *msg)
+error(const char *msg)
 {
 	if (curfile != NULL)
 		fprintf(stderr, "%s:%d: ", curfile, linno);
diff -urN stable/8/bin/sh/mknodes.c head/bin/sh/mknodes.c
--- stable/8/bin/sh/mknodes.c	2009-10-11 12:35:12.561852000 -0400
+++ head/bin/sh/mknodes.c	2009-08-28 18:41:25.158935000 -0400
@@ -42,7 +42,7 @@
 #endif /* not lint */
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/mknodes.c 197959 2009-10-11 16:35:12Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/mknodes.c 196634 2009-08-28 22:41:25Z jilles $");
 
 /*
  * This program reads the nodetypes file and nodes.c.pat file.  It generates
diff -urN stable/8/bin/sh/mksyntax.c head/bin/sh/mksyntax.c
--- stable/8/bin/sh/mksyntax.c	2009-06-01 07:38:38.880711000 -0400
+++ head/bin/sh/mksyntax.c	2010-04-11 08:24:47.653720000 -0400
@@ -42,7 +42,7 @@
 #endif /* not lint */
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/mksyntax.c 193225 2009-06-01 11:38:38Z rse $");
+__FBSDID("$FreeBSD: head/bin/sh/mksyntax.c 206473 2010-04-11 12:24:47Z jilles $");
 
 /*
  * This program creates syntax.h and syntax.c.
@@ -55,8 +55,8 @@
 
 
 struct synclass {
-	char *name;
-	char *comment;
+	const char *name;
+	const char *comment;
 };
 
 /* Syntax classes */
@@ -101,16 +101,16 @@
 
 static FILE *cfile;
 static FILE *hfile;
-static char *syntax[513];
+static const char *syntax[513];
 static int base;
 static int size;	/* number of values which a char variable can have */
 static int nbits;	/* number of bits in a character */
 static int digit_contig;/* true if digits are contiguous */
 
-static void filltable(char *);
+static void filltable(const char *);
 static void init(void);
-static void add(char *, char *);
-static void print(char *);
+static void add(const char *, const char *);
+static void print(const char *);
 static void output_type_macros(void);
 static void digit_convert(void);
 
@@ -232,7 +232,6 @@
 	add("\n", "CNL");
 	add("\\", "CBACK");
 	add("`", "CBQUOTE");
-	add("'", "CSQUOTE");
 	add("\"", "CDQUOTE");
 	add("$", "CVAR");
 	add("}", "CENDVAR");
@@ -259,7 +258,7 @@
  */
 
 static void
-filltable(char *dftval)
+filltable(const char *dftval)
 {
 	int i;
 
@@ -293,7 +292,7 @@
  */
 
 static void
-add(char *p, char *type)
+add(const char *p, const char *type)
 {
 	while (*p)
 		syntax[*p++ + base] = type;
@@ -306,7 +305,7 @@
  */
 
 static void
-print(char *name)
+print(const char *name)
 {
 	int i;
 	int col;
@@ -338,7 +337,7 @@
  * contiguous, we can test for them quickly.
  */
 
-static char *macro[] = {
+static const char *macro[] = {
 	"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
 	"#define is_eof(c)\t((c) == PEOF)",
 	"#define is_alpha(c)\t(((c) < CTLESC || (c) > CTLQUOTEMARK) && isalpha((unsigned char) (c)))",
@@ -351,7 +350,7 @@
 static void
 output_type_macros(void)
 {
-	char **pp;
+	const char **pp;
 
 	if (digit_contig)
 		macro[0] = "#define is_digit(c)\t((unsigned int)((c) - '0') <= 9)";
diff -urN stable/8/bin/sh/mktokens head/bin/sh/mktokens
--- stable/8/bin/sh/mktokens	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/mktokens	2005-01-10 03:39:26.000000000 -0500
@@ -32,7 +32,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)mktokens	8.1 (Berkeley) 5/31/93
-# $FreeBSD: stable/8/bin/sh/mktokens 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD: head/bin/sh/mktokens 139969 2005-01-10 08:39:26Z imp $
 
 # 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 -urN stable/8/bin/sh/myhistedit.h head/bin/sh/myhistedit.h
--- stable/8/bin/sh/myhistedit.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/myhistedit.h	2010-06-02 15:16:58.408982000 -0400
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)myhistedit.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/myhistedit.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/myhistedit.h 208755 2010-06-02 19:16:58Z jilles $
  */
 
 #include <histedit.h>
@@ -38,8 +38,9 @@
 
 void histedit(void);
 void sethistsize(const char *);
+void setterm(const char *);
 int histcmd(int, char **);
-int not_fcnumber(char *);
-int str_to_event(char *, int);
+int not_fcnumber(const char *);
+int str_to_event(const char *, int);
 int bindcmd(int, char **);
 
diff -urN stable/8/bin/sh/mystring.c head/bin/sh/mystring.c
--- stable/8/bin/sh/mystring.c	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/mystring.c	2009-12-27 13:04:05.764326000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/mystring.c 127958 2004-04-06 20:06:54Z markm $");
+__FBSDID("$FreeBSD: head/bin/sh/mystring.c 201053 2009-12-27 18:04:05Z jilles $");
 
 /*
  * String functions.
@@ -108,7 +108,7 @@
 number(const char *s)
 {
 	if (! is_number(s))
-		error("Illegal number: %s", (char *)s);
+		error("Illegal number: %s", s);
 	return atoi(s);
 }
 
diff -urN stable/8/bin/sh/mystring.h head/bin/sh/mystring.h
--- stable/8/bin/sh/mystring.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/mystring.h	2004-04-06 16:06:54.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)mystring.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/mystring.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/mystring.h 127958 2004-04-06 20:06:54Z markm $
  */
 
 #include <string.h>
diff -urN stable/8/bin/sh/nodes.c.pat head/bin/sh/nodes.c.pat
--- stable/8/bin/sh/nodes.c.pat	2009-10-11 12:35:12.561852000 -0400
+++ head/bin/sh/nodes.c.pat	2009-08-28 18:41:25.158935000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/nodes.c.pat 197959 2009-10-11 16:35:12Z jilles $
+ * $FreeBSD: head/bin/sh/nodes.c.pat 196634 2009-08-28 22:41:25Z jilles $
  */
 
 #include <sys/param.h>
diff -urN stable/8/bin/sh/nodetypes head/bin/sh/nodetypes
--- stable/8/bin/sh/nodetypes	2005-01-10 03:39:26.000000000 -0500
+++ head/bin/sh/nodetypes	2005-01-10 03:39:26.000000000 -0500
@@ -30,7 +30,7 @@
 # SUCH DAMAGE.
 #
 #	@(#)nodetypes	8.2 (Berkeley) 5/4/95
-# $FreeBSD: stable/8/bin/sh/nodetypes 139969 2005-01-10 08:39:26Z imp $
+# $FreeBSD: head/bin/sh/nodetypes 139969 2005-01-10 08:39:26Z imp $
 
 # This file describes the nodes used in parse trees.  Unindented lines
 # contain a node type followed by a structure tag.  Subsequent indented
diff -urN stable/8/bin/sh/options.c head/bin/sh/options.c
--- stable/8/bin/sh/options.c	2008-08-27 16:16:06.461092000 -0400
+++ head/bin/sh/options.c	2010-04-05 10:15:51.345103000 -0400
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/options.c 182300 2008-08-27 20:16:06Z stefanf $");
+__FBSDID("$FreeBSD: head/bin/sh/options.c 206182 2010-04-05 14:15:51Z jilles $");
 
 #include <signal.h>
 #include <unistd.h>
@@ -64,7 +64,7 @@
 struct shparam shellparam;	/* current positional parameters */
 char **argptr;			/* argument list for builtin commands */
 char *shoptarg;			/* set by nextopt (like getopt) */
-char *optptr;			/* used by nextopt */
+char *nextopt_optptr;		/* used by nextopt */
 
 char *minusc;			/* argument to -c option */
 
@@ -93,8 +93,11 @@
 	options(1);
 	if (*argptr == NULL && minusc == NULL)
 		sflag = 1;
-	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
+	if (iflag != 0 && sflag == 1 && isatty(0) && isatty(1)) {
 		iflag = 1;
+		if (Eflag == 2)
+			Eflag = 1;
+	}
 	if (mflag == 2)
 		mflag = iflag;
 	for (i = 0; i < NOPTS; i++)
@@ -554,12 +557,13 @@
  */
 
 int
-nextopt(char *optstring)
+nextopt(const char *optstring)
 {
-	char *p, *q;
+	char *p;
+	const char *q;
 	char c;
 
-	if ((p = optptr) == NULL || *p == '\0') {
+	if ((p = nextopt_optptr) == NULL || *p == '\0') {
 		p = *argptr;
 		if (p == NULL || *p != '-' || *++p == '\0')
 			return '\0';
@@ -580,6 +584,6 @@
 		shoptarg = p;
 		p = NULL;
 	}
-	optptr = p;
+	nextopt_optptr = p;
 	return c;
 }
diff -urN stable/8/bin/sh/options.h head/bin/sh/options.h
--- stable/8/bin/sh/options.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/options.h	2009-12-27 13:04:05.764326000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)options.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/options.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/options.h 201053 2009-12-27 18:04:05Z jilles $
  */
 
 struct shparam {
@@ -102,7 +102,7 @@
 extern struct shparam shellparam;  /* $@ */
 extern char **argptr;		/* argument list for builtin commands */
 extern char *shoptarg;		/* set by nextopt */
-extern char *optptr;		/* used by nextopt */
+extern char *nextopt_optptr;	/* used by nextopt */
 
 void procargs(int, char **);
 void optschanged(void);
@@ -111,5 +111,5 @@
 int shiftcmd(int, char **);
 int setcmd(int, char **);
 int getoptscmd(int, char **);
-int nextopt(char *);
+int nextopt(const char *);
 void getoptsreset(const char *);
diff -urN stable/8/bin/sh/output.c head/bin/sh/output.c
--- stable/8/bin/sh/output.c	2009-06-19 18:09:55.177892000 -0400
+++ head/bin/sh/output.c	2009-12-24 13:41:14.411055000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/output.c 194516 2009-06-19 22:09:55Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/output.c 200956 2009-12-24 18:41:14Z jilles $");
 
 /*
  * Shell output routines.  We use our own output routines because:
@@ -71,7 +71,7 @@
 static int doformat_wr(void *, const char *, int);
 
 struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
-struct output errout = {NULL, 0, NULL, 100, 2, 0};
+struct output errout = {NULL, 0, NULL, 256, 2, 0};
 struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
 struct output *out1 = &output;
 struct output *out2 = &errout;
@@ -124,8 +124,6 @@
 {
 	while (*p)
 		outc(*p++, file);
-	if (file == out2)
-		flushout(file);
 }
 
 /* Like outstr(), but quote for re-input into the shell. */
@@ -255,7 +253,7 @@
 }
 
 void
-dprintf(const char *fmt, ...)
+out2fmt_flush(const char *fmt, ...)
 {
 	va_list ap;
 
@@ -316,7 +314,7 @@
  */
 
 int
-xwrite(int fd, char *buf, int nbytes)
+xwrite(int fd, const char *buf, int nbytes)
 {
 	int ntry;
 	int i;
diff -urN stable/8/bin/sh/output.h head/bin/sh/output.h
--- stable/8/bin/sh/output.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/output.h	2010-01-01 13:17:46.488302000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)output.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/output.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/output.h 201366 2010-01-01 18:17:46Z jilles $
  */
 
 #ifndef OUTPUT_INCL
@@ -46,13 +46,13 @@
 	short flags;
 };
 
-extern struct output output;
-extern struct output errout;
+extern struct output output; /* to fd 1 */
+extern struct output errout; /* to fd 2 */
 extern struct output memout;
-extern struct output *out1;
-extern struct output *out2;
+extern struct output *out1; /* &memout if backquote, otherwise &output */
+extern struct output *out2; /* &memout if backquote with 2>&1, otherwise
+			       &errout */
 
-void open_mem(char *, int, struct output *);
 void out1str(const char *);
 void out1qstr(const char *);
 void out2str(const char *);
@@ -65,10 +65,10 @@
 void freestdout(void);
 void outfmt(struct output *, const char *, ...) __printflike(2, 3);
 void out1fmt(const char *, ...) __printflike(1, 2);
-void dprintf(const char *, ...) __printflike(1, 2);
+void out2fmt_flush(const char *, ...) __printflike(1, 2);
 void fmtstr(char *, int, const char *, ...) __printflike(3, 4);
 void doformat(struct output *, const char *, va_list) __printflike(2, 0);
-int xwrite(int, char *, int);
+int xwrite(int, const char *, int);
 
 #define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
 #define out1c(c)	outc(c, out1);
diff -urN stable/8/bin/sh/parser.c head/bin/sh/parser.c
--- stable/8/bin/sh/parser.c	2010-04-20 18:20:31.838359000 -0400
+++ head/bin/sh/parser.c	2010-06-19 06:33:04.993394000 -0400
@@ -36,10 +36,11 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/parser.c 206942 2010-04-20 22:20:31Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/parser.c 209337 2010-06-19 10:33:04Z jilles $");
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include "shell.h"
 #include "parser.h"
@@ -79,10 +80,13 @@
 	int striptabs;		/* if set, strip leading tabs */
 };
 
+struct parser_temp {
+	struct parser_temp *next;
+	void *data;
+};
 
 
 STATIC struct heredoc *heredoclist;	/* list of here documents to read */
-STATIC int parsebackquote;	/* nonzero if we are inside backquotes */
 STATIC int doprompt;		/* if set, prompt the user */
 STATIC int needprompt;		/* true if interactive and at start of line */
 STATIC int lasttoken;		/* last token read */
@@ -95,6 +99,7 @@
 STATIC int quoteflag;		/* set if (part of) last token was quoted */
 STATIC int startlinno;		/* line # where last token started */
 STATIC int funclinno;		/* line # where the current function started */
+STATIC struct parser_temp *parser_temp;
 
 /* XXX When 'noaliases' is set to one, no alias expansion takes place. */
 static int noaliases = 0;
@@ -114,10 +119,77 @@
 STATIC int readtoken1(int, char const *, char *, int);
 STATIC int noexpand(char *);
 STATIC void synexpect(int);
-STATIC void synerror(char *);
+STATIC void synerror(const char *);
 STATIC void setprompt(int);
 
 
+STATIC void *
+parser_temp_alloc(size_t len)
+{
+	struct parser_temp *t;
+
+	INTOFF;
+	t = ckmalloc(sizeof(*t));
+	t->data = NULL;
+	t->next = parser_temp;
+	parser_temp = t;
+	t->data = ckmalloc(len);
+	INTON;
+	return t->data;
+}
+
+
+STATIC void *
+parser_temp_realloc(void *ptr, size_t len)
+{
+	struct parser_temp *t;
+
+	INTOFF;
+	t = parser_temp;
+	if (ptr != t->data)
+		error("bug: parser_temp_realloc misused");
+	t->data = ckrealloc(t->data, len);
+	INTON;
+	return t->data;
+}
+
+
+STATIC void
+parser_temp_free_upto(void *ptr)
+{
+	struct parser_temp *t;
+	int done = 0;
+
+	INTOFF;
+	while (parser_temp != NULL && !done) {
+		t = parser_temp;
+		parser_temp = t->next;
+		done = t->data == ptr;
+		ckfree(t->data);
+		ckfree(t);
+	}
+	INTON;
+	if (!done)
+		error("bug: parser_temp_free_upto misused");
+}
+
+
+STATIC void
+parser_temp_free_all(void)
+{
+	struct parser_temp *t;
+
+	INTOFF;
+	while (parser_temp != NULL) {
+		t = parser_temp;
+		parser_temp = t->next;
+		ckfree(t->data);
+		ckfree(t);
+	}
+	INTON;
+}
+
+
 /*
  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
  * valid parse tree indicating a blank line.)
@@ -128,6 +200,12 @@
 {
 	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;
 	doprompt = interact;
 	if (doprompt)
@@ -864,6 +942,188 @@
 }
 
 
+#define MAXNEST_STATIC 8
+struct tokenstate
+{
+	const char *syntax; /* *SYNTAX */
+	int parenlevel; /* levels of parentheses in arithmetic */
+	enum tokenstate_category
+	{
+		TSTATE_TOP,
+		TSTATE_VAR_OLD, /* ${var+-=?}, inherits dquotes */
+		TSTATE_VAR_NEW, /* other ${var...}, own dquote state */
+		TSTATE_ARITH
+	} category;
+};
+
+
+/*
+ * Called to parse command substitutions.
+ */
+
+STATIC char *
+parsebackq(char *out, struct nodelist **pbqlist,
+		int oldstyle, int dblquote, int quoted)
+{
+	struct nodelist **nlpp;
+	union node *n;
+	char *volatile str;
+	struct jmploc jmploc;
+	struct jmploc *const savehandler = handler;
+	int savelen;
+	int saveprompt;
+	const int bq_startlinno = plinno;
+	char *volatile ostr = NULL;
+	struct parsefile *const savetopfile = getcurrentfile();
+	struct heredoc *const saveheredoclist = heredoclist;
+	struct heredoc *here;
+
+	str = NULL;
+	if (setjmp(jmploc.loc)) {
+		popfilesupto(savetopfile);
+		if (str)
+			ckfree(str);
+		if (ostr)
+			ckfree(ostr);
+		heredoclist = saveheredoclist;
+		handler = savehandler;
+		if (exception == EXERROR) {
+			startlinno = bq_startlinno;
+			synerror("Error in command substitution");
+		}
+		longjmp(handler->loc, 1);
+	}
+	INTOFF;
+	savelen = out - stackblock();
+	if (savelen > 0) {
+		str = ckmalloc(savelen);
+		memcpy(str, stackblock(), savelen);
+	}
+	handler = &jmploc;
+	heredoclist = NULL;
+	INTON;
+        if (oldstyle) {
+                /* We must read until the closing backquote, giving special
+                   treatment to some slashes, and then push the string and
+                   reread it as input, interpreting it normally.  */
+                char *oout;
+                int c;
+                int olen;
+
+
+                STARTSTACKSTR(oout);
+		for (;;) {
+			if (needprompt) {
+				setprompt(2);
+				needprompt = 0;
+			}
+			switch (c = pgetc()) {
+			case '`':
+				goto done;
+
+			case '\\':
+                                if ((c = pgetc()) == '\n') {
+					plinno++;
+					if (doprompt)
+						setprompt(2);
+					else
+						setprompt(0);
+					/*
+					 * If eating a newline, avoid putting
+					 * the newline into the new character
+					 * stream (via the STPUTC after the
+					 * switch).
+					 */
+					continue;
+				}
+                                if (c != '\\' && c != '`' && c != '$'
+                                    && (!dblquote || c != '"'))
+                                        STPUTC('\\', oout);
+				break;
+
+			case '\n':
+				plinno++;
+				needprompt = doprompt;
+				break;
+
+			case PEOF:
+			        startlinno = plinno;
+				synerror("EOF in backquote substitution");
+ 				break;
+
+			default:
+				break;
+			}
+			STPUTC(c, oout);
+                }
+done:
+                STPUTC('\0', oout);
+                olen = oout - stackblock();
+		INTOFF;
+		ostr = ckmalloc(olen);
+		memcpy(ostr, stackblock(), olen);
+		setinputstring(ostr, 1);
+		INTON;
+        }
+	nlpp = pbqlist;
+	while (*nlpp)
+		nlpp = &(*nlpp)->next;
+	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+	(*nlpp)->next = NULL;
+
+	if (oldstyle) {
+		saveprompt = doprompt;
+		doprompt = 0;
+	}
+
+	n = list(0);
+
+	if (oldstyle)
+		doprompt = saveprompt;
+	else {
+		if (readtoken() != TRP)
+			synexpect(TRP);
+	}
+
+	(*nlpp)->n = n;
+        if (oldstyle) {
+		/*
+		 * Start reading from old file again, ignoring any pushed back
+		 * tokens left from the backquote parsing
+		 */
+                popfile();
+		tokpushback = 0;
+	}
+	while (stackblocksize() <= savelen)
+		growstackblock();
+	STARTSTACKSTR(out);
+	INTOFF;
+	if (str) {
+		memcpy(out, str, savelen);
+		STADJUST(savelen, out);
+		ckfree(str);
+		str = NULL;
+	}
+	if (ostr) {
+		ckfree(ostr);
+		ostr = NULL;
+	}
+	here = saveheredoclist;
+	if (here != NULL) {
+		while (here->next != NULL)
+			here = here->next;
+		here->next = heredoclist;
+		heredoclist = saveheredoclist;
+	}
+	handler = savehandler;
+	INTON;
+	if (quoted)
+		USTPUTC(CTLBACKQ | CTLQUOTE, out);
+	else
+		USTPUTC(CTLBACKQ, out);
+	return out;
+}
+
 
 /*
  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
@@ -880,12 +1140,10 @@
 #define CHECKEND()	{goto checkend; checkend_return:;}
 #define PARSEREDIR()	{goto parseredir; parseredir_return:;}
 #define PARSESUB()	{goto parsesub; parsesub_return:;}
-#define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
-#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
 #define	PARSEARITH()	{goto parsearith; parsearith_return:;}
 
 STATIC int
-readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
+readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
 {
 	int c = firstc;
 	char *out;
@@ -893,23 +1151,21 @@
 	char line[EOFMARKLEN + 1];
 	struct nodelist *bqlist;
 	int quotef;
-	int dblquote;
-	int varnest;	/* levels of variables expansion */
-	int arinest;	/* levels of arithmetic expansion */
-	int parenlevel;	/* levels of parens in arithmetic */
-	int oldstyle;
-	char const *prevsyntax;	/* syntax before arithmetic */
+	int newvarnest;
+	int level;
 	int synentry;
+	struct tokenstate state_static[MAXNEST_STATIC];
+	int maxnest = MAXNEST_STATIC;
+	struct tokenstate *state = state_static;
 
 	startlinno = plinno;
-	dblquote = 0;
-	if (syntax == DQSYNTAX)
-		dblquote = 1;
 	quotef = 0;
 	bqlist = NULL;
-	varnest = 0;
-	arinest = 0;
-	parenlevel = 0;
+	newvarnest = 0;
+	level = 0;
+	state[level].syntax = initialsyntax;
+	state[level].parenlevel = 0;
+	state[level].category = TSTATE_TOP;
 
 	STARTSTACKSTR(out);
 	loop: {	/* for each line, until end of word */
@@ -917,11 +1173,11 @@
 		for (;;) {	/* until end of line or end of word */
 			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */
 
-			synentry = syntax[c];
+			synentry = state[level].syntax[c];
 
 			switch(synentry) {
 			case CNL:	/* '\n' */
-				if (syntax == BASESYNTAX)
+				if (state[level].syntax == BASESYNTAX)
 					goto endword;	/* exit outer loop */
 				USTPUTC(c, out);
 				plinno++;
@@ -935,7 +1191,7 @@
 				USTPUTC(c, out);
 				break;
 			case CCTL:
-				if (eofmark == NULL || dblquote)
+				if (eofmark == NULL || initialsyntax != SQSYNTAX)
 					USTPUTC(CTLESC, out);
 				USTPUTC(c, out);
 				break;
@@ -951,41 +1207,37 @@
 					else
 						setprompt(0);
 				} else {
-					if (dblquote && c != '\\' &&
-					    c != '`' && c != '$' &&
-					    (c != '"' || eofmark != NULL))
+					if (state[level].syntax == DQSYNTAX &&
+					    c != '\\' && c != '`' && c != '$' &&
+					    (c != '"' || (eofmark != NULL &&
+						newvarnest == 0)) &&
+					    (c != '}' || state[level].category != TSTATE_VAR_OLD))
 						USTPUTC('\\', out);
 					if (SQSYNTAX[c] == CCTL)
 						USTPUTC(CTLESC, out);
-					else if (eofmark == NULL)
+					else if (eofmark == NULL ||
+					    newvarnest > 0)
 						USTPUTC(CTLQUOTEMARK, out);
 					USTPUTC(c, out);
 					quotef++;
 				}
 				break;
 			case CSQUOTE:
-				if (eofmark == NULL)
-					USTPUTC(CTLQUOTEMARK, out);
-				syntax = SQSYNTAX;
+				USTPUTC(CTLQUOTEMARK, out);
+				state[level].syntax = SQSYNTAX;
 				break;
 			case CDQUOTE:
-				if (eofmark == NULL)
-					USTPUTC(CTLQUOTEMARK, out);
-				syntax = DQSYNTAX;
-				dblquote = 1;
+				USTPUTC(CTLQUOTEMARK, out);
+				state[level].syntax = DQSYNTAX;
 				break;
 			case CENDQUOTE:
-				if (eofmark != NULL && arinest == 0 &&
-				    varnest == 0) {
+				if (eofmark != NULL && newvarnest == 0)
 					USTPUTC(c, out);
-				} else {
-					if (arinest) {
-						syntax = ARISYNTAX;
-						dblquote = 0;
-					} else if (eofmark == NULL) {
-						syntax = BASESYNTAX;
-						dblquote = 0;
-					}
+				else {
+					if (state[level].category == TSTATE_ARITH)
+						state[level].syntax = ARISYNTAX;
+					else
+						state[level].syntax = BASESYNTAX;
 					quotef++;
 				}
 				break;
@@ -993,30 +1245,33 @@
 				PARSESUB();		/* parse substitution */
 				break;
 			case CENDVAR:	/* '}' */
-				if (varnest > 0) {
-					varnest--;
+				if (level > 0 &&
+				    (state[level].category == TSTATE_VAR_OLD ||
+				    state[level].category == TSTATE_VAR_NEW)) {
+					if (state[level].category == TSTATE_VAR_OLD)
+						state[level - 1].syntax = state[level].syntax;
+					else
+						newvarnest--;
+					level--;
 					USTPUTC(CTLENDVAR, out);
 				} else {
 					USTPUTC(c, out);
 				}
 				break;
 			case CLP:	/* '(' in arithmetic */
-				parenlevel++;
+				state[level].parenlevel++;
 				USTPUTC(c, out);
 				break;
 			case CRP:	/* ')' in arithmetic */
-				if (parenlevel > 0) {
+				if (state[level].parenlevel > 0) {
 					USTPUTC(c, out);
-					--parenlevel;
+					--state[level].parenlevel;
 				} else {
 					if (pgetc() == ')') {
-						if (--arinest == 0) {
+						if (level > 0 &&
+						    state[level].category == TSTATE_ARITH) {
+							level--;
 							USTPUTC(CTLENDARI, out);
-							syntax = prevsyntax;
-							if (syntax == DQSYNTAX)
-								dblquote = 1;
-							else
-								dblquote = 0;
 						} else
 							USTPUTC(')', out);
 					} else {
@@ -1030,12 +1285,15 @@
 				}
 				break;
 			case CBQUOTE:	/* '`' */
-				PARSEBACKQOLD();
+				out = parsebackq(out, &bqlist, 1,
+				    state[level].syntax == DQSYNTAX &&
+				    (eofmark == NULL || newvarnest > 0),
+				    state[level].syntax == DQSYNTAX || state[level].syntax == ARISYNTAX);
 				break;
 			case CEOF:
 				goto endword;		/* exit outer loop */
 			default:
-				if (varnest == 0)
+				if (level == 0)
 					goto endword;	/* exit outer loop */
 				USTPUTC(c, out);
 			}
@@ -1043,14 +1301,17 @@
 		}
 	}
 endword:
-	if (syntax == ARISYNTAX)
+	if (state[level].syntax == ARISYNTAX)
 		synerror("Missing '))'");
-	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
+	if (state[level].syntax != BASESYNTAX && eofmark == NULL)
 		synerror("Unterminated quoted string");
-	if (varnest != 0) {
+	if (state[level].category == TSTATE_VAR_OLD ||
+	    state[level].category == TSTATE_VAR_NEW) {
 		startlinno = plinno;
 		synerror("Missing '}'");
 	}
+	if (state != state_static)
+		parser_temp_free_upto(state);
 	USTPUTC('\0', out);
 	len = out - stackblock();
 	out = stackblock();
@@ -1073,7 +1334,6 @@
 /* end of readtoken routine */
 
 
-
 /*
  * Check to see whether we are at the end of the here document.  When this
  * is called, c is set to the first character of the next input line.  If
@@ -1190,7 +1450,11 @@
 			PARSEARITH();
 		} else {
 			pungetc();
-			PARSEBACKQNEW();
+			out = parsebackq(out, &bqlist, 0,
+			    state[level].syntax == DQSYNTAX &&
+			    (eofmark == NULL || newvarnest > 0),
+			    state[level].syntax == DQSYNTAX ||
+			    state[level].syntax == ARISYNTAX);
 		}
 	} else {
 		USTPUTC(CTLVAR, out);
@@ -1245,6 +1509,8 @@
 				subtype = VSERROR;
 				if (c == '}')
 					pungetc();
+				else if (c == '\n' || c == PEOF)
+					synerror("Unexpected end of line in substitution");
 				else
 					USTPUTC(c, out);
 			} else {
@@ -1261,6 +1527,8 @@
 			default:
 				p = strchr(types, c);
 				if (p == NULL) {
+					if (c == '\n' || c == PEOF)
+						synerror("Unexpected end of line in substitution");
 					if (flags == VSNUL)
 						STPUTC(':', out);
 					STPUTC(c, out);
@@ -1286,192 +1554,74 @@
 			pungetc();
 		}
 		STPUTC('=', out);
-		if (subtype != VSLENGTH && (dblquote || arinest))
+		if (subtype != VSLENGTH && (state[level].syntax == DQSYNTAX ||
+		    state[level].syntax == ARISYNTAX))
 			flags |= VSQUOTE;
 		*(stackblock() + typeloc) = subtype | flags;
-		if (subtype != VSNORMAL)
-			varnest++;
-	}
-	goto parsesub_return;
-}
-
-
-/*
- * Called to parse command substitutions.  Newstyle is set if the command
- * is enclosed inside $(...); nlpp is a pointer to the head of the linked
- * list of commands (passed by reference), and savelen is the number of
- * characters on the top of the stack which must be preserved.
- */
-
-parsebackq: {
-	struct nodelist **nlpp;
-	int savepbq;
-	union node *n;
-	char *volatile str;
-	struct jmploc jmploc;
-	struct jmploc *const savehandler = handler;
-	int savelen;
-	int saveprompt;
-	const int bq_startlinno = plinno;
-
-	savepbq = parsebackquote;
-	if (setjmp(jmploc.loc)) {
-		if (str)
-			ckfree(str);
-		parsebackquote = 0;
-		handler = savehandler;
-		if (exception == EXERROR) {
-			startlinno = bq_startlinno;
-			synerror("Error in command substitution");
-		}
-		longjmp(handler->loc, 1);
-	}
-	INTOFF;
-	str = NULL;
-	savelen = out - stackblock();
-	if (savelen > 0) {
-		str = ckmalloc(savelen);
-		memcpy(str, stackblock(), savelen);
-	}
-	handler = &jmploc;
-	INTON;
-        if (oldstyle) {
-                /* We must read until the closing backquote, giving special
-                   treatment to some slashes, and then push the string and
-                   reread it as input, interpreting it normally.  */
-                char *out;
-                int c;
-                int savelen;
-                char *str;
-
-
-                STARTSTACKSTR(out);
-		for (;;) {
-			if (needprompt) {
-				setprompt(2);
-				needprompt = 0;
+		if (subtype != VSNORMAL) {
+			if (level + 1 >= maxnest) {
+				maxnest *= 2;
+				if (state == state_static) {
+					state = parser_temp_alloc(
+					    maxnest * sizeof(*state));
+					memcpy(state, state_static,
+					    MAXNEST_STATIC * sizeof(*state));
+				} else
+					state = parser_temp_realloc(state,
+					    maxnest * sizeof(*state));
 			}
-			switch (c = pgetc()) {
-			case '`':
-				goto done;
-
-			case '\\':
-                                if ((c = pgetc()) == '\n') {
-					plinno++;
-					if (doprompt)
-						setprompt(2);
-					else
-						setprompt(0);
-					/*
-					 * If eating a newline, avoid putting
-					 * the newline into the new character
-					 * stream (via the STPUTC after the
-					 * switch).
-					 */
-					continue;
-				}
-                                if (c != '\\' && c != '`' && c != '$'
-                                    && (!dblquote || c != '"'))
-                                        STPUTC('\\', out);
-				break;
-
-			case '\n':
-				plinno++;
-				needprompt = doprompt;
-				break;
-
-			case PEOF:
-			        startlinno = plinno;
-				synerror("EOF in backquote substitution");
- 				break;
-
-			default:
-				break;
+			level++;
+			state[level].parenlevel = 0;
+			if (subtype == VSMINUS || subtype == VSPLUS ||
+			    subtype == VSQUESTION || subtype == VSASSIGN) {
+				/*
+				 * For operators that were in the Bourne shell,
+				 * inherit the double-quote state.
+				 */
+				state[level].syntax = state[level - 1].syntax;
+				state[level].category = TSTATE_VAR_OLD;
+			} else {
+				/*
+				 * The other operators take a pattern,
+				 * so go to BASESYNTAX.
+				 * Also, ' and " are now special, even
+				 * in here documents.
+				 */
+				state[level].syntax = BASESYNTAX;
+				state[level].category = TSTATE_VAR_NEW;
+				newvarnest++;
 			}
-			STPUTC(c, out);
-                }
-done:
-                STPUTC('\0', out);
-                savelen = out - stackblock();
-                if (savelen > 0) {
-                        str = ckmalloc(savelen);
-                        memcpy(str, stackblock(), savelen);
-			setinputstring(str, 1);
-                }
-        }
-	nlpp = &bqlist;
-	while (*nlpp)
-		nlpp = &(*nlpp)->next;
-	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
-	(*nlpp)->next = NULL;
-	parsebackquote = oldstyle;
-
-	if (oldstyle) {
-		saveprompt = doprompt;
-		doprompt = 0;
-	}
-
-	n = list(0);
-
-	if (oldstyle)
-		doprompt = saveprompt;
-	else {
-		if (readtoken() != TRP)
-			synexpect(TRP);
-	}
-
-	(*nlpp)->n = n;
-        if (oldstyle) {
-		/*
-		 * Start reading from old file again, ignoring any pushed back
-		 * tokens left from the backquote parsing
-		 */
-                popfile();
-		tokpushback = 0;
-	}
-	while (stackblocksize() <= savelen)
-		growstackblock();
-	STARTSTACKSTR(out);
-	if (str) {
-		memcpy(out, str, savelen);
-		STADJUST(savelen, out);
-		INTOFF;
-		ckfree(str);
-		str = NULL;
-		INTON;
+		}
 	}
-	parsebackquote = savepbq;
-	handler = savehandler;
-	if (arinest || dblquote)
-		USTPUTC(CTLBACKQ | CTLQUOTE, out);
-	else
-		USTPUTC(CTLBACKQ, out);
-	if (oldstyle)
-		goto parsebackq_oldreturn;
-	else
-		goto parsebackq_newreturn;
+	goto parsesub_return;
 }
 
+
 /*
  * Parse an arithmetic expansion (indicate start of one and set state)
  */
 parsearith: {
 
-	if (++arinest == 1) {
-		prevsyntax = syntax;
-		syntax = ARISYNTAX;
-		USTPUTC(CTLARI, out);
-		if (dblquote)
-			USTPUTC('"',out);
-		else
-			USTPUTC(' ',out);
-	} else {
-		/*
-		 * we collapse embedded arithmetic expansion to
-		 * parenthesis, which should be equivalent
-		 */
-		USTPUTC('(', out);
+	if (level + 1 >= maxnest) {
+		maxnest *= 2;
+		if (state == state_static) {
+			state = parser_temp_alloc(
+			    maxnest * sizeof(*state));
+			memcpy(state, state_static,
+			    MAXNEST_STATIC * sizeof(*state));
+		} else
+			state = parser_temp_realloc(state,
+			    maxnest * sizeof(*state));
 	}
+	level++;
+	state[level].syntax = ARISYNTAX;
+	state[level].parenlevel = 0;
+	state[level].category = TSTATE_ARITH;
+	USTPUTC(CTLARI, out);
+	if (state[level - 1].syntax == DQSYNTAX)
+		USTPUTC('"',out);
+	else
+		USTPUTC(' ',out);
 	goto parsearith_return;
 }
 
@@ -1516,9 +1666,9 @@
  */
 
 int
-goodname(char *name)
+goodname(const char *name)
 {
-	char *p;
+	const char *p;
 
 	p = name;
 	if (! is_name(*p))
@@ -1553,11 +1703,11 @@
 
 
 STATIC void
-synerror(char *msg)
+synerror(const char *msg)
 {
 	if (commandname)
-		outfmt(&errout, "%s: %d: ", commandname, startlinno);
-	outfmt(&errout, "Syntax error: %s\n", msg);
+		outfmt(out2, "%s: %d: ", commandname, startlinno);
+	outfmt(out2, "Syntax error: %s\n", msg);
 	error((char *)NULL);
 }
 
@@ -1569,7 +1719,10 @@
 #ifndef NO_HISTORY
 	if (!el)
 #endif
+	{
 		out2str(getprompt(NULL));
+		flushout(out2);
+	}
 }
 
 /*
@@ -1582,13 +1735,14 @@
 	static char ps[PROMPTLEN];
 	char *fmt;
 	int i, j, trim;
+	static char internal_error[] = "<internal prompt error>";
 
 	/*
 	 * Select prompt format.
 	 */
 	switch (whichprompt) {
 	case 0:
-		fmt = "";
+		fmt = nullstr;
 		break;
 	case 1:
 		fmt = ps1val();
@@ -1597,7 +1751,7 @@
 		fmt = ps2val();
 		break;
 	default:
-		return "<internal prompt error>";
+		return internal_error;
 	}
 
 	/*
diff -urN stable/8/bin/sh/parser.h head/bin/sh/parser.h
--- stable/8/bin/sh/parser.h	2008-05-15 15:55:27.000000000 -0400
+++ head/bin/sh/parser.h	2009-12-27 13:04:05.764326000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)parser.h	8.3 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/parser.h 179022 2008-05-15 19:55:27Z stefanf $
+ * $FreeBSD: head/bin/sh/parser.h 201053 2009-12-27 18:04:05Z jilles $
  */
 
 /* control characters in argument strings */
@@ -73,9 +73,10 @@
 extern int tokpushback;
 #define NEOF ((union node *)&tokpushback)
 extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
+extern const char *const parsekwd[];
 
 
 union node *parsecmd(int);
 void fixredir(union node *, const char *, int);
-int goodname(char *);
+int goodname(const char *);
 char *getprompt(void *);
diff -urN stable/8/bin/sh/redir.c head/bin/sh/redir.c
--- stable/8/bin/sh/redir.c	2009-06-20 16:44:27.958917000 -0400
+++ head/bin/sh/redir.c	2009-11-29 17:33:59.045137000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/redir.c 194560 2009-06-20 20:44:27Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/redir.c 199953 2009-11-29 22:33:59Z jilles $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -63,6 +63,7 @@
 
 
 #define EMPTY -2		/* marks an unused slot in redirtab */
+#define CLOSED -1		/* fd was not open before redir */
 #define PIPESIZE 4096		/* amount of buffering in a pipe */
 
 
@@ -101,7 +102,6 @@
 	struct redirtab *sv = NULL;
 	int i;
 	int fd;
-	int try;
 	char memory[10];	/* file descriptors to write to memory */
 
 	for (i = 10 ; --i >= 0 ; )
@@ -116,38 +116,30 @@
 	}
 	for (n = redir ; n ; n = n->nfile.next) {
 		fd = n->nfile.fd;
-		try = 0;
 		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
 		    n->ndup.dupfd == fd)
 			continue; /* redirect from/to same file descriptor */
 
 		if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
 			INTOFF;
-again:
 			if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
 				switch (errno) {
 				case EBADF:
-					if (!try) {
-						openredirect(n, memory);
-						try++;
-						goto again;
-					}
-					/* FALLTHROUGH*/
+					i = CLOSED;
+					break;
 				default:
 					INTON;
 					error("%d: %s", fd, strerror(errno));
 					break;
 				}
-			}
-			if (!try) {
-				sv->renamed[fd] = i;
-			}
+			} else
+				(void)fcntl(i, F_SETFD, FD_CLOEXEC);
+			sv->renamed[fd] = i;
 			INTON;
 		}
 		if (fd == 0)
 			fd0_redirected++;
-		if (!try)
-			openredirect(n, memory);
+		openredirect(n, memory);
 	}
 	if (memory[1])
 		out1 = &memout;
@@ -166,8 +158,11 @@
 
 	/*
 	 * We suppress interrupts so that we won't leave open file
-	 * descriptors around.  This may not be such a good idea because
-	 * an open of a device or a fifo can block indefinitely.
+	 * descriptors around.  Because the signal handler remains
+	 * installed and we do not use system call restart, interrupts
+	 * will still abort blocking opens such as fifos (they will fail
+	 * with EINTR). There is, however, a race condition if an interrupt
+	 * arrives after INTOFF and before open blocks.
 	 */
 	INTOFF;
 	memory[fd] = 0;
diff -urN stable/8/bin/sh/redir.h head/bin/sh/redir.h
--- stable/8/bin/sh/redir.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/redir.h	2004-04-06 16:06:54.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)redir.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/redir.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/redir.h 127958 2004-04-06 20:06:54Z markm $
  */
 
 /* flags passed to redirect */
diff -urN stable/8/bin/sh/sh.1 head/bin/sh/sh.1
--- stable/8/bin/sh/sh.1	2010-04-23 15:26:03.997203000 -0400
+++ head/bin/sh/sh.1	2010-05-24 11:12:12.326105000 -0400
@@ -30,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	from: @(#)sh.1	8.6 (Berkeley) 5/4/95
-.\" $FreeBSD: stable/8/bin/sh/sh.1 207132 2010-04-23 19:26:03Z jilles $
+.\" $FreeBSD: head/bin/sh/sh.1 208505 2010-05-24 15:12:12Z jilles $
 .\"
-.Dd January 8, 2010
+.Dd May 24, 2010
 .Dt SH 1
 .Os
 .Sh NAME
@@ -210,7 +210,8 @@
 .Xr emacs 1
 command line editor (disables the
 .Fl V
-option if it has been set).
+option if it has been set;
+set automatically when interactive on terminals).
 .It Fl e Li errexit
 Exit immediately if any untested command fails in non-interactive mode.
 The exit status of a command is considered to be
@@ -296,7 +297,10 @@
 .Ed
 .It Fl u Li nounset
 Write a message to standard error when attempting
-to expand a variable that is not set, and if the
+to expand a variable, a positional parameter or
+the special parameter
+.Va \&!
+that is not set, and if the
 shell is not interactive, exit immediately.
 .It Fl V Li vi
 Enable the built-in
@@ -411,11 +415,11 @@
 .Pq Ql \en .
 A backslash preceding a newline is treated as a line continuation.
 .El
-.Ss Reserved Words
-Reserved words are words that have special meaning to the
+.Ss Keywords
+Keywords or reserved words are words that have special meaning to the
 shell and are recognized at the beginning of a line and
 after a control operator.
-The following are reserved words:
+The following are keywords:
 .Bl -column "doneXX" "elifXX" "elseXX" "untilXX" "whileX" -offset center
 .It Li \&! Ta { Ta } Ta Ic case Ta Ic do
 .It Ic done Ta Ic elif Ta Ic else Ta Ic esac Ta Ic fi
@@ -425,8 +429,8 @@
 An alias is a name and corresponding value set using the
 .Ic alias
 built-in command.
-Whenever a reserved word may occur (see above),
-and after checking for reserved words, the shell
+Whenever a keyword may occur (see above),
+and after checking for keywords, the shell
 checks the word to see if it matches an alias.
 If it does, it replaces it in the input stream with its value.
 For example, if there is an alias called
@@ -465,7 +469,7 @@
 document).
 Essentially though, a line is read and if
 the first word of the line (or after a control operator)
-is not a reserved word, then the shell has recognized a
+is not a keyword, then the shell has recognized a
 simple command.
 Otherwise, a complex command or some
 other special construct may have been recognized.
@@ -661,11 +665,11 @@
 performing any searches.
 .It
 The shell searches each entry in the
-.Ev PATH
-environment variable
+.Va PATH
+variable
 in turn for the command.
 The value of the
-.Ev PATH
+.Va PATH
 variable should be a series of
 entries separated by colons.
 Each entry consists of a
@@ -691,7 +695,7 @@
 .In sys/signal.h .
 .Ss Complex Commands
 Complex commands are combinations of simple commands
-with control operators or reserved words, together creating a larger complex
+with control operators or keywords, together creating a larger complex
 command.
 More generally, a command is one of the following:
 .Bl -item -offset indent
@@ -735,7 +739,7 @@
 If the pipeline is not in the background (discussed later),
 the shell waits for all commands to complete.
 .Pp
-If the reserved word
+If the keyword
 .Ic !\&
 does not precede the pipeline, the
 exit status is the exit status of the last command specified
@@ -1036,13 +1040,9 @@
 .Ic set
 built-in command can also be used to set or reset them.
 .Ss Special Parameters
-A special parameter is a parameter denoted by a special one-character
-name.
-The special parameters recognized by the
-.Nm
-shell of
-.Fx
-are shown in the following list, exactly as they would appear in input
+Special parameters are parameters denoted by a single special character
+or the digit zero.
+They are shown in the following list, exactly as they would appear in input
 typed by the user or in the source of a shell script.
 .Bl -hang
 .It Li $*
@@ -1109,6 +1109,84 @@
 .It Li $0
 (zero) Expands to the name of the shell or shell script.
 .El
+.Ss Special Variables
+The following variables are set by the shell or
+have special meaning to it:
+.Bl -tag -width ".Va HISTSIZE"
+.It Va CDPATH
+The search path used with the
+.Ic cd
+built-in.
+.It Va EDITOR
+The fallback editor used with the
+.Ic fc
+built-in.
+If not set, the default editor is
+.Xr ed 1 .
+.It Va FCEDIT
+The default editor used with the
+.Ic fc
+built-in.
+.It Va HISTSIZE
+The number of previous commands that are accessible.
+.It Va HOME
+The user's home directory,
+used in tilde expansion and as a default directory for the
+.Ic cd
+built-in.
+.It Va IFS
+Input Field Separators.
+This is normally set to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline .
+See the
+.Sx White Space Splitting
+section for more details.
+.It Va LINENO
+The current line number in the script or function.
+.It Va MAIL
+The name of a mail file, that will be checked for the arrival of new
+mail.
+Overridden by
+.Va MAILPATH .
+.It Va MAILPATH
+A colon
+.Pq Ql \&:
+separated list of file names, for the shell to check for incoming
+mail.
+This variable overrides the
+.Va MAIL
+setting.
+There is a maximum of 10 mailboxes that can be monitored at once.
+.It Va PATH
+The default search path for executables.
+See the
+.Sx Path Search
+section for details.
+.It Va PPID
+The parent process ID of the invoked shell.
+This is set at startup
+unless this variable is in the environment.
+A later change of parent process ID is not reflected.
+A subshell retains the same value of
+.Va PPID .
+.It Va PS1
+The primary prompt string, which defaults to
+.Dq Li "$ " ,
+unless you are the superuser, in which case it defaults to
+.Dq Li "# " .
+.It Va PS2
+The secondary prompt string, which defaults to
+.Dq Li "> " .
+.It Va PS4
+The prefix for the trace output (if
+.Fl x
+is active).
+The default is
+.Dq Li "+ " .
+.El
 .Ss Word Expansions
 This clause describes the various expansions that are
 performed on words.
@@ -1162,7 +1240,7 @@
 username is missing (as in
 .Pa ~/foobar ) ,
 the tilde is replaced with the value of the
-.Ev HOME
+.Va HOME
 variable (the current user's home directory).
 .Ss Parameter Expansion
 The format for parameter expansion is as follows:
@@ -1175,10 +1253,20 @@
 .Ql } .
 Any
 .Ql }
-escaped by a backslash or within a quoted string, and characters in
+escaped by a backslash or within a single-quoted string, and characters in
 embedded arithmetic expansions, command substitutions, and variable
 expansions, are not examined in determining the matching
 .Ql } .
+Except for the variants with
+.Ql + ,
+.Ql - ,
+.Ql =
+or
+.Ql ?\& ,
+any
+.Ql }
+within a double-quoted string is also not examined in determining the matching
+.Ql } .
 .Pp
 The simplest form for parameter expansion is:
 .Pp
@@ -1262,6 +1350,14 @@
 In the parameter expansions shown previously, use of the colon in the
 format results in a test for a parameter that is unset or null; omission
 of the colon results in a test for a parameter that is only unset.
+.Pp
+The
+.Ar word
+inherits the type of quoting
+(unquoted, double-quoted or here-document)
+from the surroundings,
+with the exception that a backslash that quotes a closing brace is removed
+during quote removal.
 .Bl -tag -width indent
 .It Li ${# Ns Ar parameter Ns Li }
 String Length.
@@ -1469,10 +1565,10 @@
 .Ql /
 characters, it is used as is.
 Otherwise, the shell searches the
-.Ev PATH
+.Va PATH
 for the file.
 If it is not found in the
-.Ev PATH ,
+.Va PATH ,
 it is sought in the current working directory.
 .It Ic \&[
 A built-in equivalent of
@@ -1516,7 +1612,7 @@
 Switch to the specified
 .Ar directory ,
 or to the directory specified in the
-.Ev HOME
+.Va HOME
 environment variable if no
 .Ar directory
 is specified.
@@ -1527,17 +1623,17 @@
 or
 .Pa .. ,
 then the directories listed in the
-.Ev CDPATH
+.Va CDPATH
 variable will be
 searched for the specified
 .Ar directory .
 If
-.Ev CDPATH
+.Va CDPATH
 is unset, the current directory is searched.
 The format of
-.Ev CDPATH
+.Va CDPATH
 is the same as that of
-.Ev PATH .
+.Va PATH .
 In an interactive shell,
 the
 .Ic cd
@@ -1545,7 +1641,7 @@
 that it actually switched to
 if this is different from the name that the user gave.
 These may be different either because the
-.Ev CDPATH
+.Va CDPATH
 mechanism was used or because a symbolic link was crossed.
 .Pp
 If the
@@ -1568,16 +1664,18 @@
 .It Ic command Oo Fl p Oc Op Ar utility Op Ar argument ...
 .It Ic command Oo Fl v | V Oc Op Ar utility
 The first form of invocation executes the specified
+.Ar utility ,
+ignoring shell functions in the search.
+If
 .Ar utility
-as a simple command (see the
-.Sx Simple Commands
-section).
+is a special builtin,
+it is executed as if it were a regular builtin.
 .Pp
 If the
 .Fl p
 option is specified, the command search is performed using a
 default value of
-.Ev PATH
+.Va PATH
 that is guaranteed to find all of the standard utilities.
 .Pp
 If the
@@ -1736,20 +1834,20 @@
 .Ar editor
 string is a command name,
 subject to search via the
-.Ev PATH
+.Va PATH
 variable.
 The value in the
-.Ev FCEDIT
+.Va FCEDIT
 variable is used as a default when
 .Fl e
 is not specified.
 If
-.Ev FCEDIT
+.Va FCEDIT
 is null or unset, the value of the
-.Ev EDITOR
+.Va EDITOR
 variable is used.
 If
-.Ev EDITOR
+.Va EDITOR
 is null or unset,
 .Xr ed 1
 is used as the editor.
@@ -1783,7 +1881,7 @@
 Select the commands to list or edit.
 The number of previous commands that can be accessed
 are determined by the value of the
-.Ev HISTSIZE
+.Va HISTSIZE
 variable.
 The value of
 .Ar first
@@ -1814,12 +1912,12 @@
 .El
 .El
 .Pp
-The following environment variables affect the execution of
+The following variables affect the execution of
 .Ic fc :
-.Bl -tag -width ".Ev HISTSIZE"
-.It Ev FCEDIT
+.Bl -tag -width ".Va HISTSIZE"
+.It Va FCEDIT
 Name of the editor to use for history editing.
-.It Ev HISTSIZE
+.It Va HISTSIZE
 The number of previous commands that are accessible.
 .El
 .It Ic fg Op Ar job
@@ -2285,74 +2383,27 @@
 .Sh ENVIRONMENT
 The following environment variables affect the execution of
 .Nm :
-.Bl -tag -width ".Ev HISTSIZE"
-.It Ev CDPATH
-The search path used with the
-.Ic cd
-built-in.
-.It Ev EDITOR
-The fallback editor used with the
-.Ic fc
-built-in.
-If not set, the default editor is
-.Xr ed 1 .
-.It Ev FCEDIT
-The default editor used with the
-.Ic fc
-built-in.
-.It Ev HISTSIZE
-The number of previous commands that are accessible.
-.It Ev HOME
-The starting directory of
-.Nm .
-.It Ev IFS
-Input Field Separators.
-This is normally set to
-.Aq space ,
-.Aq tab ,
-and
-.Aq newline .
-See the
-.Sx White Space Splitting
-section for more details.
-.It Ev MAIL
-The name of a mail file, that will be checked for the arrival of new
-mail.
-Overridden by
-.Ev MAILPATH .
-.It Ev MAILPATH
-A colon
-.Pq Ql \&:
-separated list of file names, for the shell to check for incoming
-mail.
-This environment setting overrides the
-.Ev MAIL
-setting.
-There is a maximum of 10 mailboxes that can be monitored at once.
-.It Ev PATH
-The default search path for executables.
-See the
-.Sx Path Search
-section for details.
-.It Ev PS1
-The primary prompt string, which defaults to
-.Dq Li "$ " ,
-unless you are the superuser, in which case it defaults to
-.Dq Li "# " .
-.It Ev PS2
-The secondary prompt string, which defaults to
-.Dq Li "> " .
-.It Ev PS4
-The prefix for the trace output (if
-.Fl x
-is active).
-The default is
-.Dq Li "+ " .
+.Bl -tag -width ".Ev LANGXXXXXX"
+.It Ev ENV
+Initialization file for interactive shells.
+.It Ev LANG , Ev LC_*
+Locale settings.
+These are inherited by children of the shell,
+and is used in a limited manner by the shell itself.
+.It Ev PWD
+An absolute pathname for the current directory,
+possibly containing symbolic links.
+This is used and updated by the shell.
 .It Ev TERM
 The default terminal setting for the shell.
 This is inherited by children of the shell, and is used in the history
 editing modes.
 .El
+.Pp
+Additionally, all environment variables are turned into shell variables
+at startup,
+which may affect the shell as described under
+.Sx Special Variables .
 .Sh EXIT STATUS
 Errors that are detected by the shell, such as a syntax error, will
 cause the shell to exit with a non-zero exit status.
diff -urN stable/8/bin/sh/shell.h head/bin/sh/shell.h
--- stable/8/bin/sh/shell.h	2008-04-27 16:46:45.000000000 -0400
+++ head/bin/sh/shell.h	2008-04-27 16:46:45.000000000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)shell.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/shell.h 178625 2008-04-27 20:46:45Z stefanf $
+ * $FreeBSD: head/bin/sh/shell.h 178625 2008-04-27 20:46:45Z stefanf $
  */
 
 #ifndef SHELL_H_
diff -urN stable/8/bin/sh/show.c head/bin/sh/show.c
--- stable/8/bin/sh/show.c	2006-04-14 09:59:03.000000000 -0400
+++ head/bin/sh/show.c	2009-12-24 13:41:14.411055000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/show.c 157750 2006-04-14 13:59:03Z schweikh $");
+__FBSDID("$FreeBSD: head/bin/sh/show.c 200956 2009-12-24 18:41:14Z jilles $");
 
 #include <fcntl.h>
 #include <stdio.h>
@@ -307,7 +307,7 @@
 
 
 void
-trputs(char *s)
+trputs(const char *s)
 {
 	if (tracefile == NULL)
 		return;
diff -urN stable/8/bin/sh/show.h head/bin/sh/show.h
--- stable/8/bin/sh/show.h	2004-04-06 16:06:54.000000000 -0400
+++ head/bin/sh/show.h	2009-12-24 13:41:14.411055000 -0500
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)show.h	1.1 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/show.h 127958 2004-04-06 20:06:54Z markm $
+ * $FreeBSD: head/bin/sh/show.h 200956 2009-12-24 18:41:14Z jilles $
  */
 
 void showtree(union node *);
@@ -35,6 +35,6 @@
 void sh_trace(const char *, ...) __printflike(1, 2);
 void trargs(char **);
 void trputc(int);
-void trputs(char *);
+void trputs(const char *);
 void opentrace(void);
 #endif
diff -urN stable/8/bin/sh/trap.c head/bin/sh/trap.c
--- stable/8/bin/sh/trap.c	2009-06-13 17:10:41.755841000 -0400
+++ head/bin/sh/trap.c	2009-11-21 15:44:34.304188000 -0500
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/trap.c 194127 2009-06-13 21:10:41Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/trap.c 199641 2009-11-21 20:44:34Z jilles $");
 
 #include <signal.h>
 #include <unistd.h>
@@ -149,6 +149,7 @@
 {
 	char *action;
 	int signo;
+	int errors = 0;
 
 	if (argc <= 1) {
 		for (signo = 0 ; signo < sys_nsig ; signo++) {
@@ -183,8 +184,10 @@
 		}
 	}
 	while (*argv) {
-		if ((signo = sigstring_to_signum(*argv)) == -1)
-			error("bad signal %s", *argv);
+		if ((signo = sigstring_to_signum(*argv)) == -1) {
+			out2fmt_flush("trap: bad signal %s\n", *argv);
+			errors = 1;
+		}
 		INTOFF;
 		if (action)
 			action = savestr(action);
@@ -196,7 +199,7 @@
 		INTON;
 		argv++;
 	}
-	return 0;
+	return errors;
 }
 
 
@@ -244,7 +247,8 @@
 setsignal(int signo)
 {
 	int action;
-	sig_t sig, sigact = SIG_DFL;
+	sig_t sigact = SIG_DFL;
+	struct sigaction sa;
 	char *t;
 
 	if ((t = trap[signo]) == NULL)
@@ -320,9 +324,10 @@
 		case S_IGN:	sigact = SIG_IGN;	break;
 	}
 	*t = action;
-	sig = signal(signo, sigact);
-	if (sig != SIG_ERR && action == S_CATCH)
-		siginterrupt(signo, 1);
+	sa.sa_handler = sigact;
+	sa.sa_flags = 0;
+	sigemptyset(&sa.sa_mask);
+	sigaction(signo, &sa, NULL);
 }
 
 
diff -urN stable/8/bin/sh/trap.h head/bin/sh/trap.h
--- stable/8/bin/sh/trap.h	2009-06-13 17:10:41.755841000 -0400
+++ head/bin/sh/trap.h	2009-12-24 15:55:14.498557000 -0500
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)trap.h	8.3 (Berkeley) 6/5/95
- * $FreeBSD: stable/8/bin/sh/trap.h 194127 2009-06-13 21:10:41Z jilles $
+ * $FreeBSD: head/bin/sh/trap.h 200967 2009-12-24 20:55:14Z jilles $
  */
 
 extern int pendingsigs;
@@ -45,4 +45,4 @@
 void onsig(int);
 void dotrap(void);
 void setinteractive(int);
-void exitshell(int);
+void exitshell(int) __dead2;
diff -urN stable/8/bin/sh/var.c head/bin/sh/var.c
--- stable/8/bin/sh/var.c	2010-04-20 18:52:28.965483000 -0400
+++ head/bin/sh/var.c	2010-06-02 15:16:58.408982000 -0400
@@ -36,7 +36,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/bin/sh/var.c 206950 2010-04-20 22:52:28Z jilles $");
+__FBSDID("$FreeBSD: head/bin/sh/var.c 208755 2010-06-02 19:16:58Z jilles $");
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -73,13 +73,14 @@
 struct varinit {
 	struct var *var;
 	int flags;
-	char *text;
+	const char *text;
 	void (*func)(const char *);
 };
 
 
 #ifndef NO_HISTORY
 struct var vhistsize;
+struct var vterm;
 #endif
 struct var vifs;
 struct var vmail;
@@ -94,27 +95,31 @@
 
 STATIC const struct varinit varinit[] = {
 #ifndef NO_HISTORY
-	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
+	{ &vhistsize,	VUNSET,				"HISTSIZE=",
 	  sethistsize },
 #endif
-	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
+	{ &vifs,	0,				"IFS= \t\n",
 	  NULL },
-	{ &vmail,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL=",
+	{ &vmail,	VUNSET,				"MAIL=",
 	  NULL },
-	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
+	{ &vmpath,	VUNSET,				"MAILPATH=",
 	  NULL },
-	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
+	{ &vpath,	0,				"PATH=" _PATH_DEFPATH,
 	  changepath },
-	{ &vppid,	VSTRFIXED|VTEXTFIXED|VUNSET,	"PPID=",
+	{ &vppid,	VUNSET,				"PPID=",
 	  NULL },
 	/*
 	 * vps1 depends on uid
 	 */
-	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
+	{ &vps2,	0,				"PS2=> ",
 	  NULL },
-	{ &vps4,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",
+	{ &vps4,	0,				"PS4=+ ",
 	  NULL },
-	{ &voptind,	VSTRFIXED|VTEXTFIXED,		"OPTIND=1",
+#ifndef NO_HISTORY
+	{ &vterm,	VUNSET,				"TERM=",
+	  setterm },
+#endif
+	{ &voptind,	0,				"OPTIND=1",
 	  getoptsreset },
 	{ NULL,	0,				NULL,
 	  NULL }
@@ -122,9 +127,17 @@
 
 STATIC struct var *vartab[VTABSIZE];
 
-STATIC struct var **hashvar(char *);
-STATIC int varequal(char *, char *);
-STATIC int localevar(char *);
+STATIC const char *const locale_names[7] = {
+	"LC_COLLATE", "LC_CTYPE", "LC_MONETARY",
+	"LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL
+};
+STATIC const int locale_categories[7] = {
+	LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0
+};
+
+STATIC struct var **hashvar(const char *);
+STATIC int varequal(const char *, const char *);
+STATIC int localevar(const char *);
 
 /*
  * Initialize the variable symbol tables and import the environment.
@@ -132,9 +145,9 @@
 
 #ifdef mkinit
 INCLUDE "var.h"
+MKINIT char **environ;
 INIT {
 	char **envp;
-	extern char **environ;
 
 	initvar();
 	for (envp = environ ; *envp ; envp++) {
@@ -164,8 +177,8 @@
 			vpp = hashvar(ip->text);
 			vp->next = *vpp;
 			*vpp = vp;
-			vp->text = ip->text;
-			vp->flags = ip->flags;
+			vp->text = __DECONST(char *, ip->text);
+			vp->flags = ip->flags | VSTRFIXED | VTEXTFIXED;
 			vp->func = ip->func;
 		}
 	}
@@ -176,7 +189,7 @@
 		vpp = hashvar("PS1=");
 		vps1.next = *vpp;
 		*vpp = &vps1;
-		vps1.text = geteuid() ? "PS1=$ " : "PS1=# ";
+		vps1.text = __DECONST(char *, geteuid() ? "PS1=$ " : "PS1=# ");
 		vps1.flags = VSTRFIXED|VTEXTFIXED;
 	}
 	if ((vppid.flags & VEXPORT) == 0) {
@@ -190,12 +203,14 @@
  */
 
 int
-setvarsafe(char *name, char *val, int flags)
+setvarsafe(const char *name, const char *val, int flags)
 {
 	struct jmploc jmploc;
 	struct jmploc *const savehandler = handler;
 	int err = 0;
+	int inton;
 
+	inton = is_int_on();
 	if (setjmp(jmploc.loc))
 		err = 1;
 	else {
@@ -203,6 +218,7 @@
 		setvar(name, val, flags);
 	}
 	handler = savehandler;
+	SETINTON(inton);
 	return err;
 }
 
@@ -212,9 +228,9 @@
  */
 
 void
-setvar(char *name, char *val, int flags)
+setvar(const char *name, const char *val, int flags)
 {
-	char *p, *q;
+	const char *p;
 	int len;
 	int namelen;
 	char *nameeq;
@@ -242,25 +258,20 @@
 	} else {
 		len += strlen(val);
 	}
-	p = nameeq = ckmalloc(len);
-	q = name;
-	while (--namelen >= 0)
-		*p++ = *q++;
-	*p++ = '=';
-	*p = '\0';
+	nameeq = ckmalloc(len);
+	memcpy(nameeq, name, namelen);
+	nameeq[namelen] = '=';
 	if (val)
-		scopy(val, p);
+		scopy(val, nameeq + namelen + 1);
+	else
+		nameeq[namelen + 1] = '\0';
 	setvareq(nameeq, flags);
 }
 
 STATIC int
-localevar(char *s)
+localevar(const char *s)
 {
-	static char *lnames[7] = {
-		"ALL", "COLLATE", "CTYPE", "MONETARY",
-		"NUMERIC", "TIME", NULL
-	};
-	char **ss;
+	const char *const *ss;
 
 	if (*s != 'L')
 		return 0;
@@ -268,8 +279,10 @@
 		return 1;
 	if (strncmp(s + 1, "C_", 2) != 0)
 		return 0;
-	for (ss = lnames; *ss ; ss++)
-		if (varequal(s + 3, *ss))
+	if (varequal(s + 3, "ALL"))
+		return 1;
+	for (ss = locale_names; *ss ; ss++)
+		if (varequal(s + 3, *ss + 3))
 			return 1;
 	return 0;
 }
@@ -280,7 +293,7 @@
  * pointer into environ where the string should not be manipulated.
  */
 static void
-change_env(char *s, int set)
+change_env(const char *s, int set)
 {
 	char *eqp;
 	char *ss;
@@ -391,7 +404,7 @@
  */
 
 char *
-lookupvar(char *name)
+lookupvar(const char *name)
 {
 	struct var *v;
 
@@ -414,7 +427,7 @@
  */
 
 char *
-bltinlookup(char *name, int doall)
+bltinlookup(const char *name, int doall)
 {
 	struct strlist *sp;
 	struct var *v;
@@ -435,6 +448,61 @@
 }
 
 
+/*
+ * Set up locale for a builtin (LANG/LC_* assignments).
+ */
+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)) {
+			act = 1;
+			break;
+		}
+	}
+	if (!act)
+		return;
+	loc = bltinlookup("LC_ALL", 0);
+	INTOFF;
+	if (loc != NULL) {
+		setlocale(LC_ALL, loc);
+		INTON;
+		return;
+	}
+	locdef = bltinlookup("LANG", 0);
+	for (i = 0; locale_names[i] != NULL; i++) {
+		loc = bltinlookup(locale_names[i], 0);
+		if (loc == NULL)
+			loc = locdef;
+		if (loc != NULL)
+			setlocale(locale_categories[i], loc);
+	}
+	INTON;
+}
+
+/*
+ * Undo the effect of bltinlocaleset().
+ */
+void
+bltinunsetlocale(void)
+{
+	struct strlist *lp;
+
+	INTOFF;
+	for (lp = cmdenviron ; lp ; lp = lp->next) {
+		if (localevar(lp->text)) {
+			setlocale(LC_ALL, "");
+			return;
+		}
+	}
+	INTON;
+}
+
 
 /*
  * Generate a list of exported variables.  This routine is used to construct
@@ -472,9 +540,9 @@
  * VSTACK set since these are currently allocated on the stack.
  */
 
-#ifdef mkinit
 MKINIT void shprocvar(void);
 
+#ifdef mkinit
 SHELLPROC {
 	shprocvar();
 }
@@ -798,7 +866,7 @@
  */
 
 int
-unsetvar(char *s)
+unsetvar(const char *s)
 {
 	struct var **vpp;
 	struct var *vp;
@@ -838,7 +906,7 @@
  */
 
 STATIC struct var **
-hashvar(char *p)
+hashvar(const char *p)
 {
 	unsigned int hashval;
 
@@ -857,7 +925,7 @@
  */
 
 STATIC int
-varequal(char *p, char *q)
+varequal(const char *p, const char *q)
 {
 	while (*p == *q++) {
 		if (*p++ == '=')
diff -urN stable/8/bin/sh/var.h head/bin/sh/var.h
--- stable/8/bin/sh/var.h	2006-06-15 03:00:49.000000000 -0400
+++ head/bin/sh/var.h	2010-06-02 15:16:58.408982000 -0400
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)var.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: stable/8/bin/sh/var.h 159632 2006-06-15 07:00:49Z stefanf $
+ * $FreeBSD: head/bin/sh/var.h 208755 2010-06-02 19:16:58Z jilles $
  */
 
 /*
@@ -77,6 +77,7 @@
 extern struct var vps4;
 #ifndef NO_HISTORY
 extern struct var vhistsize;
+extern struct var vterm;
 #endif
 
 /*
@@ -96,19 +97,21 @@
 #define optindval()	(voptind.text + 7)
 #ifndef NO_HISTORY
 #define histsizeval()	(vhistsize.text + 9)
+#define termval()	(vterm.text + 5)
 #endif
 
 #define mpathset()	((vmpath.flags & VUNSET) == 0)
 
 void initvar(void);
-void setvar(char *, char *, int);
+void setvar(const char *, const char *, int);
 void setvareq(char *, int);
 struct strlist;
 void listsetvar(struct strlist *);
-char *lookupvar(char *);
-char *bltinlookup(char *, int);
+char *lookupvar(const char *);
+char *bltinlookup(const char *, int);
+void bltinsetlocale(void);
+void bltinunsetlocale(void);
 char **environment(void);
-void shprocvar(void);
 int showvarscmd(int, char **);
 int exportcmd(int, char **);
 int localcmd(int, char **);
@@ -116,5 +119,5 @@
 void poplocalvars(void);
 int setvarcmd(int, char **);
 int unsetcmd(int, char **);
-int unsetvar(char *);
-int setvarsafe(char *, char *, int);
+int unsetvar(const char *);
+int setvarsafe(const char *, const char *, int);
diff -urN stable/8/include/histedit.h head/include/histedit.h
--- stable/8/include/histedit.h	2007-06-11 02:25:19.000000000 -0400
+++ head/include/histedit.h	2010-06-15 17:34:57.534333000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)histedit.h	8.2 (Berkeley) 1/3/94
  *	$NetBSD: histedit.h,v 1.32 2007/06/10 20:20:28 christos Exp $
- * $FreeBSD: stable/8/include/histedit.h 170547 2007-06-11 06:25:19Z stefanf $
+ * $FreeBSD: head/include/histedit.h 209219 2010-06-15 21:34:57Z jilles $
  */
 
 /*
@@ -105,9 +105,8 @@
  */
 int		 el_set(EditLine *, int, ...);
 int		 el_get(EditLine *, int, ...);
-#if 0
 unsigned char	_el_fn_complete(EditLine *, int);
-#endif
+unsigned char	_el_fn_sh_complete(EditLine *, int);
 
 /*
  * el_set/el_get parameters
diff -urN stable/8/lib/libedit/Makefile head/lib/libedit/Makefile
--- stable/8/lib/libedit/Makefile	2009-07-19 13:25:24.703896000 -0400
+++ head/lib/libedit/Makefile	2010-06-13 13:04:42.741765000 -0400
@@ -1,12 +1,13 @@
 #	$NetBSD: Makefile,v 1.34 2005/05/28 12:02:53 lukem Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/4/93
-# $FreeBSD: stable/8/lib/libedit/Makefile 195767 2009-07-19 17:25:24Z kensmith $
+# $FreeBSD: head/lib/libedit/Makefile 209136 2010-06-13 17:04:42Z jilles $
 
 LIB=	edit
 SHLIB_MAJOR=	7
 SHLIBDIR?= /lib
 
-OSRCS=	chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \
+OSRCS=	chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c \
+	hist.c key.c map.c \
 	parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c
 
 DPADD=	${LIBNCURSES}
@@ -35,6 +36,8 @@
 CFLAGS+= #-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
 CFLAGS+= #-DDEBUG_PASTE -DDEBUG_EDIT
 
+WARNS?=	1
+
 AHDR=	vi.h emacs.h common.h
 ASRC=	${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
 
diff -urN stable/8/lib/libedit/TEST/test.c head/lib/libedit/TEST/test.c
--- stable/8/lib/libedit/TEST/test.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/TEST/test.c	2005-08-07 16:55:59.000000000 -0400
@@ -40,7 +40,7 @@
 static char sccsid[] = "@(#)test.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 __RCSID("$NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem Exp $");
-__FBSDID("$FreeBSD: stable/8/lib/libedit/TEST/test.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/TEST/test.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * test.c: A little test program
diff -urN stable/8/lib/libedit/chared.c head/lib/libedit/chared.c
--- stable/8/lib/libedit/chared.c	2005-08-09 09:31:59.000000000 -0400
+++ head/lib/libedit/chared.c	2005-08-09 09:31:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)chared.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/chared.c 148897 2005-08-09 13:31:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/chared.c 148897 2005-08-09 13:31:59Z stefanf $");
 
 /*
  * chared.c: Character editor utilities
diff -urN stable/8/lib/libedit/chared.h head/lib/libedit/chared.h
--- stable/8/lib/libedit/chared.h	2007-03-11 14:30:22.000000000 -0400
+++ head/lib/libedit/chared.h	2007-03-11 14:30:22.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)chared.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: chared.h,v 1.17 2006/03/06 21:11:56 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/chared.h 167457 2007-03-11 18:30:22Z stefanf $
+ * $FreeBSD: head/lib/libedit/chared.h 167457 2007-03-11 18:30:22Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/common.c head/lib/libedit/common.c
--- stable/8/lib/libedit/common.c	2007-03-11 14:30:22.000000000 -0400
+++ head/lib/libedit/common.c	2007-03-11 14:30:22.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)common.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/common.c 167457 2007-03-11 18:30:22Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/common.c 167457 2007-03-11 18:30:22Z stefanf $");
 
 /*
  * common.c: Common Editor functions
diff -urN stable/8/lib/libedit/editline.3 head/lib/libedit/editline.3
--- stable/8/lib/libedit/editline.3	2007-06-10 15:06:09.000000000 -0400
+++ head/lib/libedit/editline.3	2010-04-14 15:08:06.333546000 -0400
@@ -13,9 +13,6 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. Neither the name of The NetBSD Foundation nor the names of its
-.\"    contributors may be used to endorse or promote products derived
-.\"    from this software without specific prior written permission.
 .\"
 .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -29,11 +26,11 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: stable/8/lib/libedit/editline.3 170511 2007-06-10 19:06:09Z stefanf $
+.\" $FreeBSD: head/lib/libedit/editline.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd January 12, 2007
-.Os
 .Dt EDITLINE 3
+.Os
 .Sh NAME
 .Nm editline ,
 .Nm el_init ,
diff -urN stable/8/lib/libedit/editrc.5 head/lib/libedit/editrc.5
--- stable/8/lib/libedit/editrc.5	2007-03-11 04:41:01.000000000 -0400
+++ head/lib/libedit/editrc.5	2010-04-14 15:08:06.333546000 -0400
@@ -13,9 +13,6 @@
 .\" 2. Redistributions in binary form must reproduce the above copyright
 .\"    notice, this list of conditions and the following disclaimer in the
 .\"    documentation and/or other materials provided with the distribution.
-.\" 3. Neither the name of The NetBSD Foundation nor the names of its
-.\"    contributors may be used to endorse or promote products derived
-.\"    from this software without specific prior written permission.
 .\"
 .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -29,11 +26,11 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: stable/8/lib/libedit/editrc.5 167444 2007-03-11 08:41:01Z stefanf $
+.\" $FreeBSD: head/lib/libedit/editrc.5 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd October 18, 2003
-.Os
 .Dt EDITRC 5
+.Os
 .Sh NAME
 .Nm editrc
 .Nd configuration file for editline library
diff -urN stable/8/lib/libedit/el.c head/lib/libedit/el.c
--- stable/8/lib/libedit/el.c	2007-06-10 15:06:09.000000000 -0400
+++ head/lib/libedit/el.c	2007-06-10 15:06:09.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/el.c 170511 2007-06-10 19:06:09Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/el.c 170511 2007-06-10 19:06:09Z stefanf $");
 
 /*
  * el.c: EditLine interface functions
diff -urN stable/8/lib/libedit/el.h head/lib/libedit/el.h
--- stable/8/lib/libedit/el.h	2007-06-10 15:06:09.000000000 -0400
+++ head/lib/libedit/el.h	2007-06-10 15:06:09.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)el.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: el.h,v 1.17 2006/12/15 22:13:33 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/el.h 170511 2007-06-10 19:06:09Z stefanf $
+ * $FreeBSD: head/lib/libedit/el.h 170511 2007-06-10 19:06:09Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/emacs.c head/lib/libedit/emacs.c
--- stable/8/lib/libedit/emacs.c	2007-03-11 14:30:22.000000000 -0400
+++ head/lib/libedit/emacs.c	2007-03-11 14:30:22.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)emacs.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/emacs.c 167457 2007-03-11 18:30:22Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/emacs.c 167457 2007-03-11 18:30:22Z stefanf $");
 
 /*
  * emacs.c: Emacs functions
diff -urN stable/8/lib/libedit/filecomplete.c head/lib/libedit/filecomplete.c
--- stable/8/lib/libedit/filecomplete.c	1969-12-31 19:00:00.000000000 -0500
+++ head/lib/libedit/filecomplete.c	2010-06-15 18:23:21.565992000 -0400
@@ -0,0 +1,667 @@
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	$NetBSD: filecomplete.c,v 1.19 2010/06/01 18:20:26 christos Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libedit/filecomplete.c 209224 2010-06-15 22:23:21Z jilles $");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <vis.h>
+#include "el.h"
+#include "fcns.h"		/* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`',
+    '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
+/* Tilde is deliberately omitted here, we treat it specially. */
+static char extra_quote_chars[] = { ')', '}', '*', '?', '[', '$', '\0' };
+
+
+/********************************/
+/* completion functions */
+
+/*
+ * does tilde expansion of strings of type ``~user/foo''
+ * if ``user'' isn't valid user name or ``txt'' doesn't start
+ * w/ '~', returns pointer to strdup()ed copy of ``txt''
+ *
+ * it's callers's responsibility to free() returned string
+ */
+char *
+fn_tilde_expand(const char *txt)
+{
+	struct passwd pwres, *pass;
+	char *temp;
+	size_t len = 0;
+	char pwbuf[1024];
+
+	if (txt[0] != '~')
+		return (strdup(txt));
+
+	temp = strchr(txt + 1, '/');
+	if (temp == NULL) {
+		temp = strdup(txt + 1);
+		if (temp == NULL)
+			return NULL;
+	} else {
+		len = temp - txt + 1;	/* text until string after slash */
+		temp = malloc(len);
+		if (temp == NULL)
+			return NULL;
+		(void)strncpy(temp, txt + 1, len - 2);
+		temp[len - 2] = '\0';
+	}
+	if (temp[0] == 0) {
+		if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+			pass = NULL;
+	} else {
+		if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+			pass = NULL;
+	}
+	free(temp);		/* value no more needed */
+	if (pass == NULL)
+		return (strdup(txt));
+
+	/* update pointer txt to point at string immediately following */
+	/* first slash */
+	txt += len;
+
+	temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
+	if (temp == NULL)
+		return NULL;
+	(void)sprintf(temp, "%s/%s", pass->pw_dir, txt);
+
+	return (temp);
+}
+
+
+/*
+ * return first found file name starting by the ``text'' or NULL if no
+ * such file can be found
+ * value of ``state'' is ignored
+ *
+ * it's caller's responsibility to free returned string
+ */
+char *
+fn_filename_completion_function(const char *text, int state)
+{
+	static DIR *dir = NULL;
+	static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
+	static size_t filename_len = 0;
+	struct dirent *entry;
+	char *temp;
+	size_t len;
+
+	if (state == 0 || dir == NULL) {
+		temp = strrchr(text, '/');
+		if (temp) {
+			char *nptr;
+			temp++;
+			nptr = realloc(filename, strlen(temp) + 1);
+			if (nptr == NULL) {
+				free(filename);
+				filename = NULL;
+				return NULL;
+			}
+			filename = nptr;
+			(void)strcpy(filename, temp);
+			len = temp - text;	/* including last slash */
+
+			nptr = realloc(dirname, len + 1);
+			if (nptr == NULL) {
+				free(dirname);
+				dirname = NULL;
+				return NULL;
+			}
+			dirname = nptr;
+			(void)strncpy(dirname, text, len);
+			dirname[len] = '\0';
+		} else {
+			free(filename);
+			if (*text == 0)
+				filename = NULL;
+			else {
+				filename = strdup(text);
+				if (filename == NULL)
+					return NULL;
+			}
+			free(dirname);
+			dirname = NULL;
+		}
+
+		if (dir != NULL) {
+			(void)closedir(dir);
+			dir = NULL;
+		}
+
+		/* support for ``~user'' syntax */
+
+		free(dirpath);
+		dirpath = NULL;
+		if (dirname == NULL) {
+			if ((dirname = strdup("")) == NULL)
+				return NULL;
+			dirpath = strdup("./");
+		} else if (*dirname == '~')
+			dirpath = fn_tilde_expand(dirname);
+		else
+			dirpath = strdup(dirname);
+
+		if (dirpath == NULL)
+			return NULL;
+
+		dir = opendir(dirpath);
+		if (!dir)
+			return (NULL);	/* cannot open the directory */
+
+		/* will be used in cycle */
+		filename_len = filename ? strlen(filename) : 0;
+	}
+
+	/* find the match */
+	while ((entry = readdir(dir)) != NULL) {
+		/* skip . and .. */
+		if (entry->d_name[0] == '.' && (!entry->d_name[1]
+		    || (entry->d_name[1] == '.' && !entry->d_name[2])))
+			continue;
+		if (filename_len == 0)
+			break;
+		/* otherwise, get first entry where first */
+		/* filename_len characters are equal	  */
+		if (entry->d_name[0] == filename[0]
+		    && entry->d_namlen >= filename_len
+		    && strncmp(entry->d_name, filename,
+			filename_len) == 0)
+			break;
+	}
+
+	if (entry) {		/* match found */
+		len = entry->d_namlen;
+
+		temp = malloc(strlen(dirname) + len + 1);
+		if (temp == NULL)
+			return NULL;
+		(void)sprintf(temp, "%s%s", dirname, entry->d_name);
+	} else {
+		(void)closedir(dir);
+		dir = NULL;
+		temp = NULL;
+	}
+
+	return (temp);
+}
+
+
+static const char *
+append_char_function(const char *name)
+{
+	struct stat stbuf;
+	char *expname = *name == '~' ? fn_tilde_expand(name) : NULL;
+	const char *rs = " ";
+
+	if (stat(expname ? expname : name, &stbuf) == -1)
+		goto out;
+	if (S_ISDIR(stbuf.st_mode))
+		rs = "/";
+out:
+	if (expname)
+		free(expname);
+	return rs;
+}
+
+
+/*
+ * returns list of completions for text given
+ * non-static for readline.
+ */
+char ** completion_matches(const char *, char *(*)(const char *, int));
+char **
+completion_matches(const char *text, char *(*genfunc)(const char *, int))
+{
+	char **match_list = NULL, *retstr, *prevstr;
+	size_t match_list_len, max_equal, which, i;
+	size_t matches;
+
+	matches = 0;
+	match_list_len = 1;
+	while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
+		/* allow for list terminator here */
+		if (matches + 3 >= match_list_len) {
+			char **nmatch_list;
+			while (matches + 3 >= match_list_len)
+				match_list_len <<= 1;
+			nmatch_list = realloc(match_list,
+			    match_list_len * sizeof(char *));
+			if (nmatch_list == NULL) {
+				free(match_list);
+				return NULL;
+			}
+			match_list = nmatch_list;
+
+		}
+		match_list[++matches] = retstr;
+	}
+
+	if (!match_list)
+		return NULL;	/* nothing found */
+
+	/* find least denominator and insert it to match_list[0] */
+	which = 2;
+	prevstr = match_list[1];
+	max_equal = strlen(prevstr);
+	for (; which <= matches; which++) {
+		for (i = 0; i < max_equal &&
+		    prevstr[i] == match_list[which][i]; i++)
+			continue;
+		max_equal = i;
+	}
+
+	retstr = malloc(max_equal + 1);
+	if (retstr == NULL) {
+		free(match_list);
+		return NULL;
+	}
+	(void)strncpy(retstr, match_list[1], max_equal);
+	retstr[max_equal] = '\0';
+	match_list[0] = retstr;
+
+	/* add NULL as last pointer to the array */
+	match_list[matches + 1] = (char *) NULL;
+
+	return (match_list);
+}
+
+
+/*
+ * Sort function for qsort(). Just wrapper around strcasecmp().
+ */
+static int
+_fn_qsort_string_compare(const void *i1, const void *i2)
+{
+	const char *s1 = ((const char * const *)i1)[0];
+	const char *s2 = ((const char * const *)i2)[0];
+
+	return strcasecmp(s1, s2);
+}
+
+
+/*
+ * Display list of strings in columnar format on readline's output stream.
+ * 'matches' is list of strings, 'len' is number of strings in 'matches',
+ * 'max' is maximum length of string in 'matches'.
+ */
+void
+fn_display_match_list(EditLine *el, char **matches, size_t len, size_t max)
+{
+	size_t i, idx, limit, count;
+	int screenwidth = el->el_term.t_size.h;
+
+	/*
+	 * Find out how many entries can be put on one line, count
+	 * with two spaces between strings.
+	 */
+	limit = screenwidth / (max + 2);
+	if (limit == 0)
+		limit = 1;
+
+	/* how many lines of output */
+	count = len / limit;
+	if (count * limit < len)
+		count++;
+
+	/* Sort the items if they are not already sorted. */
+	qsort(&matches[1], len, sizeof(char *), _fn_qsort_string_compare);
+
+	idx = 1;
+	for(; count > 0; count--) {
+		int more = limit > 0 && matches[0];
+		for(i = 0; more; idx++) {
+			more = ++i < limit && matches[idx + 1];
+			(void)fprintf(el->el_outfile, "%-*s%s", (int)max,
+			    matches[idx], more ? " " : "");
+		}
+		(void)fprintf(el->el_outfile, "\n");
+	}
+}
+
+
+/*
+ * Complete the word at or before point,
+ * 'what_to_do' says what to do with the completion.
+ * \t   means do standard completion.
+ * `?' means list the possible completions.
+ * `*' means insert all of the possible completions.
+ * `!' means to do standard completion, and list all possible completions if
+ * there is more than one.
+ *
+ * Note: '*' support is not implemented
+ *       '!' could never be invoked
+ */
+int
+fn_complete(EditLine *el,
+	char *(*complet_func)(const char *, int),
+	char **(*attempted_completion_function)(const char *, int, int),
+	const char *word_break, const char *special_prefixes,
+	const char *(*app_func)(const char *), size_t query_items,
+	int *completion_type, int *over, int *point, int *end,
+	const char *(*find_word_start_func)(const char *, const char *),
+	char *(*dequoting_func)(const char *),
+	char *(*quoting_func)(const char *))
+{
+	const LineInfo *li;
+	char *temp;
+	char *dequoted_temp;
+	char **matches;
+	const char *ctemp;
+	size_t len;
+	int what_to_do = '\t';
+	int retval = CC_NORM;
+
+	if (el->el_state.lastcmd == el->el_state.thiscmd)
+		what_to_do = '?';
+
+	/* readline's rl_complete() has to be told what we did... */
+	if (completion_type != NULL)
+		*completion_type = what_to_do;
+
+	if (!complet_func)
+		complet_func = fn_filename_completion_function;
+	if (!app_func)
+		app_func = append_char_function;
+
+	/* We now look backwards for the start of a filename/variable word */
+	li = el_line(el);
+	if (find_word_start_func)
+		ctemp = find_word_start_func(li->buffer, li->cursor);
+	else {
+		ctemp = li->cursor;
+		while (ctemp > li->buffer
+		    && !strchr(word_break, ctemp[-1])
+		    && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) )
+			ctemp--;
+	}
+
+	len = li->cursor - ctemp;
+#if defined(__SSP__) || defined(__SSP_ALL__)
+	temp = malloc(sizeof(*temp) * (len + 1));
+	if (temp == NULL)
+		return retval;
+#else
+	temp = alloca(sizeof(*temp) * (len + 1));
+#endif
+	(void)strncpy(temp, ctemp, len);
+	temp[len] = '\0';
+
+	if (dequoting_func) {
+		dequoted_temp = dequoting_func(temp);
+		if (dequoted_temp == NULL)
+			return retval;
+	} else
+		dequoted_temp = NULL;
+
+	/* these can be used by function called in completion_matches() */
+	/* or (*attempted_completion_function)() */
+	if (point != 0)
+		*point = (int)(li->cursor - li->buffer);
+	if (end != NULL)
+		*end = (int)(li->lastchar - li->buffer);
+
+	if (attempted_completion_function) {
+		int cur_off = (int)(li->cursor - li->buffer);
+		matches = (*attempted_completion_function) (dequoted_temp ? dequoted_temp : temp,
+		    (int)(cur_off - len), cur_off);
+	} else
+		matches = 0;
+	if (!attempted_completion_function || 
+	    (over != NULL && !*over && !matches))
+		matches = completion_matches(dequoted_temp ? dequoted_temp : temp, complet_func);
+
+	if (over != NULL)
+		*over = 0;
+
+	if (matches) {
+		int i;
+		size_t matches_num, maxlen, match_len, match_display=1;
+
+		retval = CC_REFRESH;
+		/*
+		 * Only replace the completed string with common part of
+		 * possible matches if there is possible completion.
+		 */
+		if (matches[0][0] != '\0') {
+			char *quoted_match;
+			if (quoting_func) {
+				quoted_match = quoting_func(matches[0]);
+				if (quoted_match == NULL)
+					goto free_matches;
+			} else
+				quoted_match = NULL;
+
+			el_deletestr(el, (int) len);
+			el_insertstr(el, quoted_match ? quoted_match : matches[0]);
+
+			free(quoted_match);
+		}
+
+		if (what_to_do == '?')
+			goto display_matches;
+
+		if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+			/*
+			 * We found exact match. Add a space after
+			 * it, unless we do filename completion and the
+			 * object is a directory.
+			 */
+			el_insertstr(el, (*app_func)(matches[0]));
+		} else if (what_to_do == '!') {
+    display_matches:
+			/*
+			 * More than one match and requested to list possible
+			 * matches.
+			 */
+
+			for(i = 1, maxlen = 0; matches[i]; i++) {
+				match_len = strlen(matches[i]);
+				if (match_len > maxlen)
+					maxlen = match_len;
+			}
+			matches_num = i - 1;
+				
+			/* newline to get on next line from command line */
+			(void)fprintf(el->el_outfile, "\n");
+
+			/*
+			 * If there are too many items, ask user for display
+			 * confirmation.
+			 */
+			if (matches_num > query_items) {
+				(void)fprintf(el->el_outfile,
+				    "Display all %zu possibilities? (y or n) ",
+				    matches_num);
+				(void)fflush(el->el_outfile);
+				if (getc(stdin) != 'y')
+					match_display = 0;
+				(void)fprintf(el->el_outfile, "\n");
+			}
+
+			if (match_display)
+				fn_display_match_list(el, matches, matches_num,
+				    maxlen);
+			retval = CC_REDISPLAY;
+		} else if (matches[0][0]) {
+			/*
+			 * There was some common match, but the name was
+			 * not complete enough. Next tab will print possible
+			 * completions.
+			 */
+			el_beep(el);
+		} else {
+			/* lcd is not a valid object - further specification */
+			/* is needed */
+			el_beep(el);
+			retval = CC_NORM;
+		}
+
+free_matches:
+		/* free elements of array and the array itself */
+		for (i = 0; matches[i]; i++)
+			free(matches[i]);
+		free(matches);
+		matches = NULL;
+	}
+	free(dequoted_temp);
+#if defined(__SSP__) || defined(__SSP_ALL__)
+	free(temp);
+#endif
+	return retval;
+}
+
+
+/*
+ * el-compatible wrapper around rl_complete; needed for key binding
+ */
+/* ARGSUSED */
+unsigned char
+_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
+{
+	return (unsigned char)fn_complete(el, NULL, NULL,
+	    break_chars, NULL, NULL, 100,
+	    NULL, NULL, NULL, NULL,
+	    NULL, NULL, NULL);
+}
+
+
+static const char *
+sh_find_word_start(const char *buffer, const char *cursor)
+{
+	const char *word_start = buffer;
+
+	while (buffer < cursor) {
+		if (*buffer == '\\')
+			buffer++;
+		else if (strchr(break_chars, *buffer))
+			word_start = buffer + 1;
+
+		buffer++;
+	}
+
+	return word_start;
+}
+
+
+static char *
+sh_quote(const char *str)
+{
+	const char *src;
+	int extra_len = 0;
+	char *quoted_str, *dst;
+
+	if (*str == '-' || *str == '+')
+		extra_len += 2;
+	for (src = str; *src != '\0'; src++)
+		if (strchr(break_chars, *src) ||
+		    strchr(extra_quote_chars, *src))
+			extra_len++;
+
+	quoted_str = malloc(sizeof(*quoted_str) *
+	    (strlen(str) + extra_len + 1));
+	if (quoted_str == NULL)
+		return NULL;
+
+	dst = quoted_str;
+	if (*str == '-' || *str == '+')
+		*dst++ = '.', *dst++ = '/';
+	for (src = str; *src != '\0'; src++) {
+		if (strchr(break_chars, *src) ||
+		    strchr(extra_quote_chars, *src))
+			*dst++ = '\\';
+		*dst++ = *src;
+	}
+	*dst = '\0';
+
+	return quoted_str;
+}
+
+
+static char *
+sh_dequote(const char *str)
+{
+	char *dequoted_str, *dst;
+
+	/* save extra space to replace \~ with ./~ */
+	dequoted_str = malloc(sizeof(*dequoted_str) * (strlen(str) + 1 + 1));
+	if (dequoted_str == NULL)
+		return NULL;
+
+	dst = dequoted_str;
+
+	/* dequote \~ at start as ./~ */
+	if (*str == '\\' && str[1] == '~') {
+		str++;
+		*dst++ = '.';
+		*dst++ = '/';
+	}
+
+	while (*str) {
+		if (*str == '\\')
+			str++;
+		if (*str)
+			*dst++ = *str++;
+	}
+	*dst = '\0';
+
+	return dequoted_str;
+}
+
+
+/*
+ * completion function using sh quoting rules; for key binding
+ */
+/* ARGSUSED */
+unsigned char
+_el_fn_sh_complete(EditLine *el, int ch __attribute__((__unused__)))
+{
+	return (unsigned char)fn_complete(el, NULL, NULL,
+	    break_chars, NULL, NULL, 100,
+	    NULL, NULL, NULL, NULL,
+	    sh_find_word_start, sh_dequote, sh_quote);
+}
diff -urN stable/8/lib/libedit/filecomplete.h head/lib/libedit/filecomplete.h
--- stable/8/lib/libedit/filecomplete.h	1969-12-31 19:00:00.000000000 -0500
+++ head/lib/libedit/filecomplete.h	2010-06-15 17:34:57.534333000 -0400
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *	$NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $
+ * $FreeBSD: head/lib/libedit/filecomplete.h 209219 2010-06-15 21:34:57Z jilles $
+ */
+#ifndef _FILECOMPLETE_H_
+#define _FILECOMPLETE_H_
+
+int fn_complete(EditLine *,
+    char *(*)(const char *, int),
+    char **(*)(const char *, int, int),
+    const char *, const char *, const char *(*)(const char *), size_t,
+    int *, int *, int *, int *,
+    const char *(*)(const char *, const char *),
+    char *(*)(const char *),
+    char *(*)(const char *));
+
+void fn_display_match_list(EditLine *, char **, size_t, size_t);
+char *fn_tilde_expand(const char *);
+char *fn_filename_completion_function(const char *, int);
+
+#endif
diff -urN stable/8/lib/libedit/hist.c head/lib/libedit/hist.c
--- stable/8/lib/libedit/hist.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/hist.c	2005-08-07 16:55:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)hist.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/hist.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/hist.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * hist.c: History access functions
diff -urN stable/8/lib/libedit/hist.h head/lib/libedit/hist.h
--- stable/8/lib/libedit/hist.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/hist.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)hist.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $
- * $FreeBSD: stable/8/lib/libedit/hist.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/hist.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/history.c head/lib/libedit/history.c
--- stable/8/lib/libedit/history.c	2007-03-11 17:47:40.000000000 -0400
+++ head/lib/libedit/history.c	2007-03-11 17:47:40.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)history.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/history.c 167464 2007-03-11 21:47:40Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/history.c 167464 2007-03-11 21:47:40Z stefanf $");
 
 /*
  * hist.c: History access functions
diff -urN stable/8/lib/libedit/key.c head/lib/libedit/key.c
--- stable/8/lib/libedit/key.c	2007-03-11 14:30:22.000000000 -0400
+++ head/lib/libedit/key.c	2007-03-11 14:30:22.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)key.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/key.c 167457 2007-03-11 18:30:22Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/key.c 167457 2007-03-11 18:30:22Z stefanf $");
 
 /*
  * key.c: This module contains the procedures for maintaining
diff -urN stable/8/lib/libedit/key.h head/lib/libedit/key.h
--- stable/8/lib/libedit/key.h	2007-03-11 14:30:22.000000000 -0400
+++ head/lib/libedit/key.h	2007-03-11 14:30:22.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)key.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: key.h,v 1.10 2006/03/23 20:22:51 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/key.h 167457 2007-03-11 18:30:22Z stefanf $
+ * $FreeBSD: head/lib/libedit/key.h 167457 2007-03-11 18:30:22Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/makelist head/lib/libedit/makelist
--- stable/8/lib/libedit/makelist	2005-10-04 17:59:29.000000000 -0400
+++ head/lib/libedit/makelist	2005-10-04 17:59:29.000000000 -0400
@@ -1,6 +1,6 @@
 #!/bin/sh -
 #	$NetBSD: makelist,v 1.10 2005/08/08 14:04:49 christos Exp $
-# $FreeBSD: stable/8/lib/libedit/makelist 150947 2005-10-04 21:59:29Z stefanf $
+# $FreeBSD: head/lib/libedit/makelist 150947 2005-10-04 21:59:29Z stefanf $
 #
 # Copyright (c) 1992, 1993
 #	The Regents of the University of California.  All rights reserved.
diff -urN stable/8/lib/libedit/map.c head/lib/libedit/map.c
--- stable/8/lib/libedit/map.c	2007-03-11 17:47:40.000000000 -0400
+++ head/lib/libedit/map.c	2007-03-11 17:47:40.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)map.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/map.c 167464 2007-03-11 21:47:40Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/map.c 167464 2007-03-11 21:47:40Z stefanf $");
 
 /*
  * map.c: Editor function definitions
diff -urN stable/8/lib/libedit/map.h head/lib/libedit/map.h
--- stable/8/lib/libedit/map.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/map.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)map.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $
- * $FreeBSD: stable/8/lib/libedit/map.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/map.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/parse.c head/lib/libedit/parse.c
--- stable/8/lib/libedit/parse.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/parse.c	2005-08-07 16:55:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/parse.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/parse.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * parse.c: parse an editline extended command
diff -urN stable/8/lib/libedit/parse.h head/lib/libedit/parse.h
--- stable/8/lib/libedit/parse.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/parse.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)parse.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $
- * $FreeBSD: stable/8/lib/libedit/parse.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/parse.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/prompt.c head/lib/libedit/prompt.c
--- stable/8/lib/libedit/prompt.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/prompt.c	2005-08-07 16:55:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)prompt.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/prompt.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/prompt.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * prompt.c: Prompt printing functions
diff -urN stable/8/lib/libedit/prompt.h head/lib/libedit/prompt.h
--- stable/8/lib/libedit/prompt.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/prompt.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)prompt.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $
- * $FreeBSD: stable/8/lib/libedit/prompt.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/prompt.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/read.c head/lib/libedit/read.c
--- stable/8/lib/libedit/read.c	2007-03-11 17:47:40.000000000 -0400
+++ head/lib/libedit/read.c	2007-03-11 17:47:40.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)read.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/read.c 167464 2007-03-11 21:47:40Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/read.c 167464 2007-03-11 21:47:40Z stefanf $");
 
 /*
  * read.c: Clean this junk up! This is horrible code.
diff -urN stable/8/lib/libedit/read.h head/lib/libedit/read.h
--- stable/8/lib/libedit/read.h	2007-03-11 04:41:01.000000000 -0400
+++ head/lib/libedit/read.h	2010-03-02 02:25:20.369016000 -0500
@@ -13,9 +13,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -30,7 +27,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  *
  *	$NetBSD: read.h,v 1.5 2006/08/21 12:45:30 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/read.h 167444 2007-03-11 08:41:01Z stefanf $
+ * $FreeBSD: head/lib/libedit/read.h 204555 2010-03-02 07:25:20Z joel $
  */
 
 /*
diff -urN stable/8/lib/libedit/refresh.c head/lib/libedit/refresh.c
--- stable/8/lib/libedit/refresh.c	2005-12-04 04:34:56.000000000 -0500
+++ head/lib/libedit/refresh.c	2005-12-04 04:34:56.000000000 -0500
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)refresh.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/refresh.c 153079 2005-12-04 09:34:56Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/refresh.c 153079 2005-12-04 09:34:56Z stefanf $");
 
 /*
  * refresh.c: Lower level screen refreshing functions
diff -urN stable/8/lib/libedit/refresh.h head/lib/libedit/refresh.h
--- stable/8/lib/libedit/refresh.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/refresh.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)refresh.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $
- * $FreeBSD: stable/8/lib/libedit/refresh.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/refresh.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/search.c head/lib/libedit/search.c
--- stable/8/lib/libedit/search.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/search.c	2005-08-07 16:55:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)search.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/search.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/search.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * search.c: History and character search functions
diff -urN stable/8/lib/libedit/search.h head/lib/libedit/search.h
--- stable/8/lib/libedit/search.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/search.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)search.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/search.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/search.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/sig.c head/lib/libedit/sig.c
--- stable/8/lib/libedit/sig.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/sig.c	2005-08-07 16:55:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)sig.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/sig.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/sig.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * sig.c: Signal handling stuff.
diff -urN stable/8/lib/libedit/sig.h head/lib/libedit/sig.h
--- stable/8/lib/libedit/sig.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/sig.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)sig.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $
- * $FreeBSD: stable/8/lib/libedit/sig.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/sig.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/sys.h head/lib/libedit/sys.h
--- stable/8/lib/libedit/sys.h	2005-08-10 09:41:31.000000000 -0400
+++ head/lib/libedit/sys.h	2005-08-10 09:41:31.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)sys.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: sys.h,v 1.9 2004/01/17 17:57:40 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/sys.h 148924 2005-08-10 13:41:31Z stefanf $
+ * $FreeBSD: head/lib/libedit/sys.h 148924 2005-08-10 13:41:31Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/term.c head/lib/libedit/term.c
--- stable/8/lib/libedit/term.c	2007-06-10 15:06:09.000000000 -0400
+++ head/lib/libedit/term.c	2007-06-10 15:06:09.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)term.c	8.2 (Berkeley) 4/30/95";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/term.c 170511 2007-06-10 19:06:09Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/term.c 170511 2007-06-10 19:06:09Z stefanf $");
 
 /*
  * term.c: Editor/termcap-curses interface
diff -urN stable/8/lib/libedit/term.h head/lib/libedit/term.h
--- stable/8/lib/libedit/term.h	2007-06-10 15:06:09.000000000 -0400
+++ head/lib/libedit/term.h	2007-06-10 15:06:09.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)term.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: term.h,v 1.18 2006/11/24 00:01:17 christos Exp $
- * $FreeBSD: stable/8/lib/libedit/term.h 170511 2007-06-10 19:06:09Z stefanf $
+ * $FreeBSD: head/lib/libedit/term.h 170511 2007-06-10 19:06:09Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/tokenizer.c head/lib/libedit/tokenizer.c
--- stable/8/lib/libedit/tokenizer.c	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/tokenizer.c	2005-08-07 16:55:59.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)tokenizer.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/tokenizer.c 148834 2005-08-07 20:55:59Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/tokenizer.c 148834 2005-08-07 20:55:59Z stefanf $");
 
 /*
  * tokenize.c: Bourne shell like tokenizer
diff -urN stable/8/lib/libedit/tty.c head/lib/libedit/tty.c
--- stable/8/lib/libedit/tty.c	2007-03-11 17:47:40.000000000 -0400
+++ head/lib/libedit/tty.c	2007-03-11 17:47:40.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)tty.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/tty.c 167464 2007-03-11 21:47:40Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/tty.c 167464 2007-03-11 21:47:40Z stefanf $");
 
 /*
  * tty.c: tty interface stuff
diff -urN stable/8/lib/libedit/tty.h head/lib/libedit/tty.h
--- stable/8/lib/libedit/tty.h	2005-08-07 16:55:59.000000000 -0400
+++ head/lib/libedit/tty.h	2005-08-07 16:55:59.000000000 -0400
@@ -31,7 +31,7 @@
  *
  *	@(#)tty.h	8.1 (Berkeley) 6/4/93
  *	$NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $
- * $FreeBSD: stable/8/lib/libedit/tty.h 148834 2005-08-07 20:55:59Z stefanf $
+ * $FreeBSD: head/lib/libedit/tty.h 148834 2005-08-07 20:55:59Z stefanf $
  */
 
 /*
diff -urN stable/8/lib/libedit/vi.c head/lib/libedit/vi.c
--- stable/8/lib/libedit/vi.c	2007-03-11 14:30:22.000000000 -0400
+++ head/lib/libedit/vi.c	2007-03-11 14:30:22.000000000 -0400
@@ -36,7 +36,7 @@
 static char sccsid[] = "@(#)vi.c	8.1 (Berkeley) 6/4/93";
 #endif /* not lint && not SCCSID */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: stable/8/lib/libedit/vi.c 167457 2007-03-11 18:30:22Z stefanf $");
+__FBSDID("$FreeBSD: head/lib/libedit/vi.c 167457 2007-03-11 18:30:22Z stefanf $");
 
 /*
  * vi.c: Vi mode commands.

--------------020203000205020600080704
Content-Type: application/octet-stream;
	name="head_lib_libedit_filecomplete.c.sig"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="head_lib_libedit_filecomplete.c.sig"

iQEcBAABAgAGBQJMH1duAAoJEJBXh4mJ2FR+yvcIAJ+vy6qKj/sx3YEAGxpqNKyJgHr34rA3
N2P4luHJlAkDmja6MlJZno+huYeiZlclokT54MceIuG7Hp7lUHaC12dCLUBMWVYqiYqY6V9O
I7I9Ej7vRksw1PR2T/bX5MbhTFvh2P2T/+vFm6GNAvPGoZBI4s2ty/jxEnNG3YmMYSyJNkun
eZ0E/y+WrqqZ6BRv3dWZu1QPOBOuexmgH5ksCQcIUI7kCBGlMjrmbR9A2sZ4ai6qzniBxMnl
q/hTlRXSs3fd+JMUmRS3J37U49DIBumqrsJrWkEqlXzMYytNhRTODxmEWCxQQNKv+suCX1RY
Sw+C8huo4kGV3TicOovo2VI=
--------------020203000205020600080704
Content-Type: application/octet-stream;
	name="head_lib_libedit_filecomplete.h.sig"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="head_lib_libedit_filecomplete.h.sig"

iQEcBAABAgAGBQJMH1duAAoJEJBXh4mJ2FR+yAQH/1Jz0OK8of1xyOK2ui/rqLQILbyt5bJS
2a28zMS6WqmjEeGVczz9HeDYYcdpiVvWphiyIjx8R2J7guguyd67L9CULkCLFHAhei7Lxhqd
zc3Jf5g+Dol8MLtBBW+jMvxSGTdl/vn7hYHwKXkwhsxcQYu55Cxzmn9RPOx+qFEPibL9mRld
NOJ7dLMWFtN9/PYi/Leai5NMQwy63TNBE93RKFxvN4mXfOvv896XqpYvFZ4TS9mBatC9qF5K
7UivinM+s016dZhoUTJz0Vg5iTBEZB9Cb64yfrKiYeegLzIbRiY7Adtpo0Fc6gF9SBlIzYTi
uSaactMuW2ZVhjpjxvZBc3w=
--------------020203000205020600080704
Content-Type: application/octet-stream; name="sh-tab-complete-stable8.diff.sig"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="sh-tab-complete-stable8.diff.sig"

iQEcBAABAgAGBQJMH1duAAoJEJBXh4mJ2FR+ms8H/2v/IKUFAl5ju4Ve4023aYYpbNYI/6UA
siUMchvqEy34DIeOs7N9eHizcCh9X90m0K1S1cBZvZsm2F7A60o5yuwMR0+GZ3wxGcWRyydt
awdTkVPKTfK4OqfKsgmaSaVDP0Q1/RwcfbaTBhbzS/YvFOIo0cfVIToHh2j/JhqahNwmmSY8
Gw8UT5I7xT8DysEcnFk14BNt8iEq6CX4zrccrfCr5M6AvKQ+3i8EDuCRNgslPFEwHBqTdA0Q
sqAU2lqGOw2scFCHIeUHEeBwfZAqPM7lIYfSuyVetRqG2SR1yumaW0LKnJRW4v2VD2PrxeO7
zmOgDW/8UhkLTloqDkBs/x8=
--------------020203000205020600080704--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4C1F576F.9090901>